/* $Id$ */ /** * @file os_abstraction.h Network stuff has many things that needs to be * included and/or implemented by default. * All those things are in this file. */ #ifndef NETWORK_CORE_OS_ABSTRACTION_H #define NETWORK_CORE_OS_ABSTRACTION_H /* Include standard stuff per OS */ #ifdef ENABLE_NETWORK /* Windows stuff */ #if defined(WIN32) || defined(WIN64) #include #include #include #define GET_LAST_ERROR() WSAGetLastError() #define EWOULDBLOCK WSAEWOULDBLOCK /* Windows has some different names for some types */ typedef unsigned long in_addr_t; #if !(defined(__MINGW32__) || defined(__CYGWIN__)) /* Windows has some different names for some types */ typedef SSIZE_T ssize_t; typedef int socklen_t; # define IPPROTO_IPV6 41 #else #include "../../win32.h" #include "../../core/alloc_func.hpp" #define AI_ADDRCONFIG 0x00000400 // Resolution only if global address configured #define IPV6_V6ONLY 27 static inline int OTTDgetnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, DWORD hostlen, char *serv, DWORD servlen, int flags) { static int (WINAPI *getnameinfo)(const struct sockaddr *, socklen_t, char *, DWORD, char *, DWORD, int) = NULL; static bool first_time = true; if (first_time) { LoadLibraryList((Function*)&getnameinfo, "ws2_32.dll\0getnameinfo\0\0"); first_time = false; } if (getnameinfo != NULL) return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); strncpy(host, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), hostlen); return 0; } #define getnameinfo OTTDgetnameinfo static inline int OTTDgetaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { static int (WINAPI *getaddrinfo)(const char *, const char *, const struct addrinfo *, struct addrinfo **) = NULL; static bool first_time = true; if (first_time) { LoadLibraryList((Function*)&getaddrinfo, "ws2_32.dll\0getaddrinfo\0\0"); first_time = false; } if (getaddrinfo != NULL) return getaddrinfo(nodename, servname, hints, res); *res = NULL; in_addr_t ip = inet_addr(nodename); if (ip == INADDR_NONE) { struct hostent *he = gethostbyname(nodename); if (he == NULL) return EAI_NONAME; ip = (*(struct in_addr *)he->h_addr).s_addr; } struct sockaddr_in *sin = CallocT(1); sin->sin_family = AF_INET; sin->sin_port = htons(strtoul(servname, NULL, 10)); sin->sin_addr.s_addr = ip; struct addrinfo *ai = CallocT(1); ai->ai_family = PF_INET; ai->ai_addr = (struct sockaddr*)sin; ai->ai_addrlen = sizeof(*sin); ai->ai_socktype = hints->ai_socktype; *res = ai; return 0; } #define getaddrinfo OTTDgetaddrinfo static inline void OTTDfreeaddrinfo(struct addrinfo *ai) { static int (WINAPI *freeaddrinfo)(struct addrinfo *) = NULL; static bool first_time = true; if (ai == NULL) return; if (first_time) { LoadLibraryList((Function*)&freeaddrinfo, "ws2_32.dll\freeaddrinfo\0\0"); first_time = false; } if (freeaddrinfo != NULL) { freeaddrinfo(ai); return; } do { struct addrinfo *next = ai->ai_next; free(ai->ai_addr); free(ai); ai = next; } while(ai != NULL); } #define freeaddrinfo OTTDfreeaddrinfo #endif /* __MINGW32__ && __CYGWIN__ */ #endif /* WIN32 */ /* UNIX stuff */ #if defined(UNIX) && !defined(__OS2__) # define SOCKET int # define INVALID_SOCKET -1 # if !defined(__MORPHOS__) && !defined(__AMIGA__) # define ioctlsocket ioctl # if !defined(BEOS_NET_SERVER) # define closesocket close # endif # define GET_LAST_ERROR() (errno) # endif /* Need this for FIONREAD on solaris */ # define BSD_COMP /* Includes needed for UNIX-like systems */ # include # include # if defined(__BEOS__) && defined(BEOS_NET_SERVER) # include # include /* snooze() */ # include typedef unsigned long in_addr_t; # define INADDR_NONE INADDR_BROADCAST # else # include # include # include # include # include /* According to glibc/NEWS, appeared in glibc-2.3. */ # if !defined(__sgi__) && !defined(SUNOS) && !defined(__MORPHOS__) && !defined(__BEOS__) && !defined(__INNOTEK_LIBC__) \ && !(defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 2)) && !defined(__dietlibc__) && !defined(HPUX) /* If for any reason ifaddrs.h does not exist on your system, comment out * the following two lines and an alternative way will be used to fetch * the list of IPs from the system. */ # include # define HAVE_GETIFADDRS # endif # if !defined(INADDR_NONE) # define INADDR_NONE 0xffffffff # endif # if defined(__BEOS__) && !defined(BEOS_NET_SERVER) /* needed on Zeta */ # include # endif # endif /* BEOS_NET_SERVER */ # if !defined(__BEOS__) && defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 1) typedef uint32_t in_addr_t; # endif # include # include # include #endif /* UNIX */ #ifdef __BEOS__ typedef int socklen_t; #endif #if defined(PSP) # include # include # include # include # include # include # include # include # include # include # include # include # define TCP_NODELAY 1 # define SO_NONBLOCK 0x1009 # define SOCKET int # define INVALID_SOCKET -1 # define INADDR_NONE 0xffffffff # define closesocket close # define GET_LAST_ERROR() sceNetInetGetErrno() #endif /* PSP */ /* OS/2 stuff */ #if defined(__OS2__) # define SOCKET int # define INVALID_SOCKET -1 # define ioctlsocket ioctl # define closesocket close # define GET_LAST_ERROR() (sock_errno()) /* Includes needed for OS/2 systems */ # include # include # include # include # include # include # include # include # include # include # include # include # define INADDR_NONE 0xffffffff typedef int socklen_t; #if !defined(__INNOTEK_LIBC__) typedef unsigned long in_addr_t; #endif /* __INNOTEK_LIBC__ */ #endif /* OS/2 */ /* MorphOS and Amiga stuff */ #if defined(__MORPHOS__) || defined(__AMIGA__) # include # include /* required for Open/CloseLibrary() */ /* MorphOS defines his network functions with UBYTE arrays while we * use char arrays. This gives tons of unneeded warnings */ # define UBYTE char # if defined(__MORPHOS__) # include /* FIO* defines */ # include /* SIO* defines */ # include # else /* __AMIGA__ */ # include # endif /* Make the names compatible */ # define closesocket(s) CloseSocket(s) # define GET_LAST_ERROR() Errno() # define ioctlsocket(s, request, status) IoctlSocket((LONG)s, (ULONG)request, (char*)status) # define ioctl ioctlsocket typedef unsigned int in_addr_t; typedef long socklen_t; extern struct Library *SocketBase; # ifdef __AMIGA__ /* for usleep() implementation */ extern struct Device *TimerBase; extern struct MsgPort *TimerPort; extern struct timerequest *TimerRequest; # endif #endif /* __MORPHOS__ || __AMIGA__ */ static inline bool SetNonBlocking(SOCKET d) { #ifdef WIN32 u_long nonblocking = 1; #else int nonblocking = 1; #endif #if (defined(__BEOS__) && defined(BEOS_NET_SERVER)) || defined(PSP) return setsockopt(d, SOL_SOCKET, SO_NONBLOCK, &nonblocking, sizeof(nonblocking)) == 0; #else return ioctlsocket(d, FIONBIO, &nonblocking) == 0; #endif } static inline bool SetNoDelay(SOCKET d) { /* XXX should this be done at all? */ #if !defined(BEOS_NET_SERVER) /* not implemented on BeOS net_server */ int b = 1; /* The (const char*) cast is needed for windows */ return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) == 0; #else return true; #endif } #endif /* ENABLE_NETWORK */ #endif /* NETWORK_CORE_OS_ABSTRACTION_H */