# os_abstraction.h

Go to the documentation of this file.

    00001 /* $Id: os_abstraction.h 24571 2012-10-04 15:25:57Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00016 #ifndef NETWORK_CORE_OS_ABSTRACTION_H
    00017 #define NETWORK_CORE_OS_ABSTRACTION_H
    00018
    00019 /* Include standard stuff per OS */
    00020
    00021 #ifdef ENABLE_NETWORK
    00022
    00023 /* Windows stuff */
    00024 #if defined(WIN32) || defined(WIN64)
    00025 #include <errno.h>
    00026 #include <winsock2.h>
    00027 #include <ws2tcpip.h>
    00028 #include <windows.h>
    00029
    00030 #define GET_LAST_ERROR() WSAGetLastError()
    00031 #undef EWOULDBLOCK
    00032 #define EWOULDBLOCK WSAEWOULDBLOCK
    00033 /* Windows has some different names for some types */
    00034 typedef unsigned long in_addr_t;
    00035
    00036 #if !(defined(__MINGW32__) || defined(__CYGWIN__))
    00037   /* Windows has some different names for some types */
    00038   typedef SSIZE_T ssize_t;
    00039   typedef int socklen_t;
    00040 # define IPPROTO_IPV6 41
    00041 #else
    00042 #include "../../os/windows/win32.h"
    00043 #include "../../core/alloc_func.hpp"
    00044
    00045 #define AI_ADDRCONFIG   0x00000400  /* Resolution only if global address configured */
    00046 #define IPV6_V6ONLY 27
    00047
    00048 static inline int OTTDgetnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, DWORD hostlen, char *serv, DWORD servlen, int flags)
    00049 {
    00050   static int (WINAPI *getnameinfo)(const struct sockaddr *, socklen_t, char *, DWORD, char *, DWORD, int) = NULL;
    00051   static bool first_time = true;
    00052
    00053   if (first_time) {
    00054     LoadLibraryList((Function*)&getnameinfo, "ws2_32.dll\0getnameinfo\0\0");
    00055     first_time = false;
    00056   }
    00057
    00058   if (getnameinfo != NULL) return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
    00059
    00060   strncpy(host, inet_ntoa(((const struct sockaddr_in *)sa)->sin_addr), hostlen);
    00061   return 0;
    00062 }
    00063 #define getnameinfo OTTDgetnameinfo
    00064
    00065 static inline int OTTDgetaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
    00066 {
    00067   static int (WINAPI *getaddrinfo)(const char *, const char *, const struct addrinfo *, struct addrinfo **) = NULL;
    00068   static bool first_time = true;
    00069
    00070   if (first_time) {
    00071     LoadLibraryList((Function*)&getaddrinfo, "ws2_32.dll\0getaddrinfo\0\0");
    00072     first_time = false;
    00073   }
    00074
    00075   if (getaddrinfo != NULL) return getaddrinfo(nodename, servname, hints, res);
    00076
    00077   *res = NULL;
    00078
    00079   in_addr_t ip = inet_addr(nodename);
    00080   if (ip == INADDR_NONE) {
    00081     struct hostent *he = gethostbyname(nodename);
    00082     if (he == NULL) return EAI_NONAME;
    00083     ip = (*(struct in_addr *)he->h_addr).s_addr;
    00084   }
    00085
    00086   struct sockaddr_in *sin = CallocT<struct sockaddr_in>(1);
    00087   sin->sin_family = AF_INET;
    00088   sin->sin_port = htons(strtoul(servname, NULL, 10));
    00089   sin->sin_addr.s_addr = ip;
    00090
    00091   struct addrinfo *ai = CallocT<struct addrinfo>(1);
    00092   ai->ai_family = PF_INET;
    00093   ai->ai_addr = (struct sockaddr*)sin;
    00094   ai->ai_addrlen = sizeof(*sin);
    00095   ai->ai_socktype = hints->ai_socktype;
    00096
    00097   *res = ai;
    00098   return 0;
    00099 }
    00100 #define getaddrinfo OTTDgetaddrinfo
    00101
    00102 static inline void OTTDfreeaddrinfo(struct addrinfo *ai)
    00103 {
    00104   static int (WINAPI *freeaddrinfo)(struct addrinfo *) = NULL;
    00105   static bool first_time = true;
    00106
    00107   if (ai == NULL) return;
    00108
    00109   if (first_time) {
    00110     LoadLibraryList((Function*)&freeaddrinfo, "ws2_32.dll\0freeaddrinfo\0\0");
    00111     first_time = false;
    00112   }
    00113
    00114   if (freeaddrinfo != NULL) {
    00115     freeaddrinfo(ai);
    00116     return;
    00117   }
    00118
    00119   do {
    00120     struct addrinfo *next = ai->ai_next;
    00121     free(ai->ai_addr);
    00122     free(ai);
    00123     ai = next;
    00124   } while (ai != NULL);
    00125 }
    00126 #define freeaddrinfo OTTDfreeaddrinfo
    00127 #endif /* __MINGW32__ && __CYGWIN__ */
    00128 #endif /* WIN32 */
    00129
    00130 /* UNIX stuff */
    00131 #if defined(UNIX) && !defined(__OS2__)
    00132 # if defined(OPENBSD) || defined(__NetBSD__)
    00133 #   define AI_ADDRCONFIG 0
    00134 # endif
    00135 # define SOCKET int
    00136 # define INVALID_SOCKET -1
    00137 # if !defined(__MORPHOS__) && !defined(__AMIGA__)
    00138 #   define ioctlsocket ioctl
    00139 # if !defined(BEOS_NET_SERVER)
    00140 #   define closesocket close
    00141 # endif
    00142 #   define GET_LAST_ERROR() (errno)
    00143 # endif
    00144 /* Need this for FIONREAD on solaris */
    00145 # define BSD_COMP
    00146
    00147 /* Includes needed for UNIX-like systems */
    00148 # include <unistd.h>
    00149 # include <sys/ioctl.h>
    00150 # if defined(__BEOS__) && defined(BEOS_NET_SERVER)
    00151 #   include <be/net/socket.h>
    00152 #   include <be/kernel/OS.h> /* snooze() */
    00153 #   include <be/net/netdb.h>
    00154     typedef unsigned long in_addr_t;
    00155 #   define INADDR_NONE INADDR_BROADCAST
    00156 # else
    00157 #   include <sys/socket.h>
    00158 #   include <netinet/in.h>
    00159 #   include <netinet/tcp.h>
    00160 #   include <arpa/inet.h>
    00161 #   include <net/if.h>
    00162 /* According to glibc/NEWS, <ifaddrs.h> appeared in glibc-2.3. */
    00163 #   if !defined(__sgi__) && !defined(SUNOS) && !defined(__MORPHOS__) && !defined(__BEOS__) && !defined(__HAIKU__) && !defined(__INNOTEK_LIBC__) \
    00164        && !(defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 2)) && !defined(__dietlibc__) && !defined(HPUX)
    00165 /* If for any reason ifaddrs.h does not exist on your system, comment out
    00166  *   the following two lines and an alternative way will be used to fetch
    00167  *   the list of IPs from the system. */
    00168 #     include <ifaddrs.h>
    00169 #     define HAVE_GETIFADDRS
    00170 #   endif
    00171 #   if !defined(INADDR_NONE)
    00172 #     define INADDR_NONE 0xffffffff
    00173 #   endif
    00174 #   if defined(__BEOS__) && !defined(BEOS_NET_SERVER)
    00175       /* needed on Zeta */
    00176 #     include <sys/sockio.h>
    00177 #   endif
    00178 # endif /* BEOS_NET_SERVER */
    00179
    00180 # if !defined(__BEOS__) && defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 1)
    00181     typedef uint32_t in_addr_t;
    00182 # endif
    00183
    00184 # include <errno.h>
    00185 # include <sys/time.h>
    00186 # include <netdb.h>
    00187 #endif /* UNIX */
    00188
    00189 #ifdef __BEOS__
    00190   typedef int socklen_t;
    00191 #endif
    00192
    00193 #ifdef __HAIKU__
    00194   #define IPV6_V6ONLY 27
    00195 #endif
    00196
    00197 #if defined(PSP)
    00198 # include <sys/socket.h>
    00199 # include <netinet/in.h>
    00200 # include <arpa/inet.h>
    00201 # include <pspnet.h>
    00202 # include <pspnet_inet.h>
    00203 # include <pspnet_apctl.h>
    00204 # include <pspnet_resolver.h>
    00205 # include <errno.h>
    00206 # include <unistd.h>
    00207 # include <sys/select.h>
    00208 # include <sys/time.h>
    00209 # include <sys/fd_set.h>
    00210
    00211 # define TCP_NODELAY 1
    00212 # define SO_NONBLOCK 0x1009
    00213 # define SOCKET int
    00214 # define INVALID_SOCKET -1
    00215 # define INADDR_NONE 0xffffffff
    00216 # define closesocket close
    00217 # define GET_LAST_ERROR() sceNetInetGetErrno()
    00218 #endif /* PSP */
    00219
    00220 /* OS/2 stuff */
    00221 #if defined(__OS2__)
    00222 # define SOCKET int
    00223 # define INVALID_SOCKET -1
    00224 # define ioctlsocket ioctl
    00225 # define closesocket close
    00226 # define GET_LAST_ERROR() (sock_errno())
    00227
    00228 /* Includes needed for OS/2 systems */
    00229 # include <types.h>
    00230 # include <unistd.h>
    00231 # include <sys/ioctl.h>
    00232 # include <sys/socket.h>
    00233 # include <netinet/in.h>
    00234 # include <netinet/tcp.h>
    00235 # include <arpa/inet.h>
    00236 # include <net/if.h>
    00237 # include <errno.h>
    00238 # include <sys/time.h>
    00239 # include <netdb.h>
    00240 # include <nerrno.h>
    00241 # define INADDR_NONE 0xffffffff
    00242
    00243 typedef int socklen_t;
    00244 #if !defined(__INNOTEK_LIBC__)
    00245 typedef unsigned long in_addr_t;
    00246 #endif /* __INNOTEK_LIBC__ */
    00247 #endif /* OS/2 */
    00248
    00249 /* MorphOS and Amiga stuff */
    00250 #if defined(__MORPHOS__) || defined(__AMIGA__)
    00251 # include <exec/types.h>
    00252 # include <proto/exec.h>   /* required for Open/CloseLibrary() */
    00253   /* MorphOS defines his network functions with UBYTE arrays while we
    00254    *  use char arrays. This gives tons of unneeded warnings */
    00255 # define UBYTE char
    00256 # if defined(__MORPHOS__)
    00257 #   include <sys/filio.h>  /* FIO* defines */
    00258 #   include <sys/sockio.h> /* SIO* defines */
    00259 #   include <netinet/in.h>
    00260 # else /* __AMIGA__ */
    00261 #   include <proto/socket.h>
    00262 # endif
    00263
    00264 /* Make the names compatible */
    00265 # define closesocket(s) CloseSocket(s)
    00266 # define GET_LAST_ERROR() Errno()
    00267 # define ioctlsocket(s, request, status) IoctlSocket((LONG)s, (ULONG)request, (char*)status)
    00268 # define ioctl ioctlsocket
    00269
    00270   typedef unsigned int in_addr_t;
    00271   typedef long         socklen_t;
    00272   extern struct Library *SocketBase;
    00273
    00274 # ifdef __AMIGA__
    00275   /* for usleep() implementation */
    00276   extern struct Device      *TimerBase;
    00277   extern struct MsgPort     *TimerPort;
    00278   extern struct timerequest *TimerRequest;
    00279 # endif
    00280 #endif /* __MORPHOS__ || __AMIGA__ */
    00281
    00287 static inline bool SetNonBlocking(SOCKET d)
    00288 {
    00289 #ifdef WIN32
    00290   u_long nonblocking = 1;
    00291 #else
    00292   int nonblocking = 1;
    00293 #endif
    00294 #if (defined(__BEOS__) && defined(BEOS_NET_SERVER)) || defined(PSP)
    00295   return setsockopt(d, SOL_SOCKET, SO_NONBLOCK, &nonblocking, sizeof(nonblocking)) == 0;
    00296 #else
    00297   return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
    00298 #endif
    00299 }
    00300
    00306 static inline bool SetNoDelay(SOCKET d)
    00307 {
    00308   /* XXX should this be done at all? */
    00309 #if !defined(BEOS_NET_SERVER) /* not implemented on BeOS net_server */
    00310   int b = 1;
    00311   /* The (const char*) cast is needed for windows */
    00312   return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) == 0;
    00313 #else
    00314   return true;
    00315 #endif
    00316 }
    00317
    00318 /* Make sure these structures have the size we expect them to be */
    00319 assert_compile(sizeof(in_addr)  ==  4);
    00320 assert_compile(sizeof(in6_addr) == 16);
    00321
    00322 #endif /* ENABLE_NETWORK */
    00323
    00324 #endif /* NETWORK_CORE_OS_ABSTRACTION_H */