os_abstraction.h

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

Generated on Sat Jul 31 21:37:47 2010 for OpenTTD by  doxygen 1.6.1