4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
11 * @file os_abstraction.h Network stuff has many things that needs to be
12 * included and/or implemented by default.
13 * All those things are in this file.
16 #ifndef NETWORK_CORE_OS_ABSTRACTION_H
17 #define NETWORK_CORE_OS_ABSTRACTION_H
19 /* Include standard stuff per OS */
24 #if defined(WIN32) || defined(WIN64)
30 #define GET_LAST_ERROR() WSAGetLastError()
32 #define EWOULDBLOCK WSAEWOULDBLOCK
33 /* Windows has some different names for some types */
34 typedef unsigned long in_addr_t
;
36 #if !(defined(__MINGW32__) || defined(__CYGWIN__))
37 /* Windows has some different names for some types */
38 typedef SSIZE_T ssize_t
;
39 typedef int socklen_t
;
40 # define IPPROTO_IPV6 41
42 #include "../../os/windows/win32.h"
43 #include "../../core/alloc_func.hpp"
45 #define AI_ADDRCONFIG 0x00000400 /* Resolution only if global address configured */
46 #define IPV6_V6ONLY 27
48 static inline int OTTDgetnameinfo(const struct sockaddr
*sa
, socklen_t salen
, char *host
, DWORD hostlen
, char *serv
, DWORD servlen
, int flags
)
50 static int (WINAPI
*getnameinfo
)(const struct sockaddr
*, socklen_t
, char *, DWORD
, char *, DWORD
, int) = NULL
;
51 static bool first_time
= true;
54 LoadLibraryList((Function
*)&getnameinfo
, "ws2_32.dll\0getnameinfo\0\0");
58 if (getnameinfo
!= NULL
) return getnameinfo(sa
, salen
, host
, hostlen
, serv
, servlen
, flags
);
60 strncpy(host
, inet_ntoa(((const struct sockaddr_in
*)sa
)->sin_addr
), hostlen
);
63 #define getnameinfo OTTDgetnameinfo
65 static inline int OTTDgetaddrinfo(const char *nodename
, const char *servname
, const struct addrinfo
*hints
, struct addrinfo
**res
)
67 static int (WINAPI
*getaddrinfo
)(const char *, const char *, const struct addrinfo
*, struct addrinfo
**) = NULL
;
68 static bool first_time
= true;
71 LoadLibraryList((Function
*)&getaddrinfo
, "ws2_32.dll\0getaddrinfo\0\0");
75 if (getaddrinfo
!= NULL
) return getaddrinfo(nodename
, servname
, hints
, res
);
79 in_addr_t ip
= inet_addr(nodename
);
80 if (ip
== INADDR_NONE
) {
81 struct hostent
*he
= gethostbyname(nodename
);
82 if (he
== NULL
) return EAI_NONAME
;
83 ip
= (*(struct in_addr
*)he
->h_addr
).s_addr
;
86 struct sockaddr_in
*sin
= CallocT
<struct sockaddr_in
>(1);
87 sin
->sin_family
= AF_INET
;
88 sin
->sin_port
= htons(strtoul(servname
, NULL
, 10));
89 sin
->sin_addr
.s_addr
= ip
;
91 struct addrinfo
*ai
= CallocT
<struct addrinfo
>(1);
92 ai
->ai_family
= PF_INET
;
93 ai
->ai_addr
= (struct sockaddr
*)sin
;
94 ai
->ai_addrlen
= sizeof(*sin
);
95 ai
->ai_socktype
= hints
->ai_socktype
;
100 #define getaddrinfo OTTDgetaddrinfo
102 static inline void OTTDfreeaddrinfo(struct addrinfo
*ai
)
104 static int (WINAPI
*freeaddrinfo
)(struct addrinfo
*) = NULL
;
105 static bool first_time
= true;
107 if (ai
== NULL
) return;
110 LoadLibraryList((Function
*)&freeaddrinfo
, "ws2_32.dll\0freeaddrinfo\0\0");
114 if (freeaddrinfo
!= NULL
) {
120 struct addrinfo
*next
= ai
->ai_next
;
124 } while (ai
!= NULL
);
126 #define freeaddrinfo OTTDfreeaddrinfo
127 #endif /* __MINGW32__ && __CYGWIN__ */
131 #if defined(UNIX) && !defined(__OS2__)
132 # if defined(OPENBSD) || defined(__NetBSD__)
133 # define AI_ADDRCONFIG 0
136 # define INVALID_SOCKET -1
137 # if !defined(__MORPHOS__) && !defined(__AMIGA__)
138 # define ioctlsocket ioctl
139 # if !defined(BEOS_NET_SERVER)
140 # define closesocket close
142 # define GET_LAST_ERROR() (errno)
144 /* Need this for FIONREAD on solaris */
147 /* Includes needed for UNIX-like systems */
149 # include <sys/ioctl.h>
150 # if defined(__BEOS__) && defined(BEOS_NET_SERVER)
151 # include <be/net/socket.h>
152 # include <be/kernel/OS.h> /* snooze() */
153 # include <be/net/netdb.h>
154 typedef unsigned long in_addr_t
;
155 # define INADDR_NONE INADDR_BROADCAST
157 # include <sys/socket.h>
158 # include <netinet/in.h>
159 # include <netinet/tcp.h>
160 # include <arpa/inet.h>
162 /* According to glibc/NEWS, <ifaddrs.h> appeared in glibc-2.3. */
163 # if !defined(__sgi__) && !defined(SUNOS) && !defined(__MORPHOS__) && !defined(__BEOS__) && !defined(__HAIKU__) && !defined(__INNOTEK_LIBC__) \
164 && !(defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 2)) && !defined(__dietlibc__) && !defined(HPUX)
165 /* If for any reason ifaddrs.h does not exist on your system, comment out
166 * the following two lines and an alternative way will be used to fetch
167 * the list of IPs from the system. */
168 # include <ifaddrs.h>
169 # define HAVE_GETIFADDRS
171 # if !defined(INADDR_NONE)
172 # define INADDR_NONE 0xffffffff
174 # if defined(__BEOS__) && !defined(BEOS_NET_SERVER)
176 # include <sys/sockio.h>
178 # endif /* BEOS_NET_SERVER */
180 # if !defined(__BEOS__) && defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 1)
181 typedef uint32_t in_addr_t
;
185 # include <sys/time.h>
190 typedef int socklen_t
;
194 #define IPV6_V6ONLY 27
198 # include <sys/socket.h>
199 # include <netinet/in.h>
200 # include <arpa/inet.h>
202 # include <pspnet_inet.h>
203 # include <pspnet_apctl.h>
204 # include <pspnet_resolver.h>
207 # include <sys/select.h>
208 # include <sys/time.h>
209 # include <sys/fd_set.h>
211 # define TCP_NODELAY 1
212 # define SO_NONBLOCK 0x1009
214 # define INVALID_SOCKET -1
215 # define INADDR_NONE 0xffffffff
216 # define closesocket close
217 # define GET_LAST_ERROR() sceNetInetGetErrno()
223 # define INVALID_SOCKET -1
224 # define ioctlsocket ioctl
225 # define closesocket close
226 # define GET_LAST_ERROR() (sock_errno())
228 /* Includes needed for OS/2 systems */
231 # include <sys/ioctl.h>
232 # include <sys/socket.h>
233 # include <netinet/in.h>
234 # include <netinet/tcp.h>
235 # include <arpa/inet.h>
238 # include <sys/time.h>
241 # define INADDR_NONE 0xffffffff
242 # include "../../3rdparty/os2/getaddrinfo.h"
243 # include "../../3rdparty/os2/getnameinfo.h"
245 #define IPV6_V6ONLY 27
252 uint8_t __u6_addr8
[16];
253 uint16_t __u6_addr16
[8];
254 uint32_t __u6_addr32
[4];
255 } __u6_addr
; /* 128-bit IP6 address */
258 #define s6_addr __u6_addr.__u6_addr8
260 struct sockaddr_in6
{
261 uint8_t sin6_len
; /* length of this struct */
262 sa_family_t sin6_family
; /* AF_INET6 */
263 in_port_t sin6_port
; /* Transport layer port # */
264 uint32_t sin6_flowinfo
; /* IP6 flow information */
265 struct in6_addr sin6_addr
; /* IP6 address */
266 uint32_t sin6_scope_id
; /* scope zone index */
269 typedef int socklen_t
;
270 #if !defined(__INNOTEK_LIBC__)
271 typedef unsigned long in_addr_t
;
272 #endif /* __INNOTEK_LIBC__ */
276 /* MorphOS and Amiga stuff */
277 #if defined(__MORPHOS__) || defined(__AMIGA__)
278 # include <exec/types.h>
279 # include <proto/exec.h> /* required for Open/CloseLibrary() */
280 /* MorphOS defines his network functions with UBYTE arrays while we
281 * use char arrays. This gives tons of unneeded warnings */
283 # if defined(__MORPHOS__)
284 # include <sys/filio.h> /* FIO* defines */
285 # include <sys/sockio.h> /* SIO* defines */
286 # include <netinet/in.h>
287 # else /* __AMIGA__ */
288 # include <proto/socket.h>
291 /* Make the names compatible */
292 # define closesocket(s) CloseSocket(s)
293 # define GET_LAST_ERROR() Errno()
294 # define ioctlsocket(s, request, status) IoctlSocket((LONG)s, (ULONG)request, (char*)status)
295 # define ioctl ioctlsocket
297 typedef unsigned int in_addr_t
;
298 typedef long socklen_t
;
299 extern struct Library
*SocketBase
;
302 /* for usleep() implementation */
303 extern struct Device
*TimerBase
;
304 extern struct MsgPort
*TimerPort
;
305 extern struct timerequest
*TimerRequest
;
307 #endif /* __MORPHOS__ || __AMIGA__ */
310 * Try to set the socket into non-blocking mode.
311 * @param d The socket to set the non-blocking more for.
312 * @return True if setting the non-blocking mode succeeded, otherwise false.
314 static inline bool SetNonBlocking(SOCKET d
)
317 u_long nonblocking
= 1;
321 #if (defined(__BEOS__) && defined(BEOS_NET_SERVER)) || defined(PSP)
322 return setsockopt(d
, SOL_SOCKET
, SO_NONBLOCK
, &nonblocking
, sizeof(nonblocking
)) == 0;
324 return ioctlsocket(d
, FIONBIO
, &nonblocking
) == 0;
329 * Try to set the socket to not delay sending.
330 * @param d The socket to disable the delaying for.
331 * @return True if disabling the delaying succeeded, otherwise false.
333 static inline bool SetNoDelay(SOCKET d
)
335 /* XXX should this be done at all? */
336 #if !defined(BEOS_NET_SERVER) /* not implemented on BeOS net_server */
338 /* The (const char*) cast is needed for windows */
339 return setsockopt(d
, IPPROTO_TCP
, TCP_NODELAY
, (const char*)&b
, sizeof(b
)) == 0;
345 /* Make sure these structures have the size we expect them to be */
346 assert_compile(sizeof(in_addr
) == 4); ///< IPv4 addresses should be 4 bytes.
347 assert_compile(sizeof(in6_addr
) == 16); ///< IPv6 addresses should be 16 bytes.
349 #endif /* ENABLE_NETWORK */
351 #endif /* NETWORK_CORE_OS_ABSTRACTION_H */