2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
9 * @file os_abstraction.h Network stuff has many things that needs to be
10 * included and/or implemented by default.
11 * All those things are in this file.
14 #ifndef NETWORK_CORE_OS_ABSTRACTION_H
15 #define NETWORK_CORE_OS_ABSTRACTION_H
17 /* Include standard stuff per OS */
26 #define GET_LAST_ERROR() WSAGetLastError()
28 #define EWOULDBLOCK WSAEWOULDBLOCK
29 /* Windows has some different names for some types */
30 typedef unsigned long in_addr_t
;
32 /* Handle cross-compilation with --build=*-*-cygwin --host=*-*-mingw32 */
33 #if defined(__MINGW32__) && !defined(AI_ADDRCONFIG)
34 # define AI_ADDRCONFIG 0x00000400
37 #if !(defined(__MINGW32__) || defined(__CYGWIN__))
38 /* Windows has some different names for some types */
39 typedef SSIZE_T ssize_t
;
40 typedef int socklen_t
;
41 # define IPPROTO_IPV6 41
42 #endif /* !(__MINGW32__ && __CYGWIN__) */
46 #if defined(UNIX) && !defined(__OS2__)
47 # if defined(OPENBSD) || defined(__NetBSD__)
48 # define AI_ADDRCONFIG 0
51 # define INVALID_SOCKET -1
52 # define ioctlsocket ioctl
53 # define closesocket close
54 # define GET_LAST_ERROR() (errno)
55 /* Need this for FIONREAD on solaris */
58 /* Includes needed for UNIX-like systems */
60 # include <sys/ioctl.h>
61 # include <sys/socket.h>
62 # include <netinet/in.h>
63 # include <netinet/tcp.h>
64 # include <arpa/inet.h>
66 /* According to glibc/NEWS, <ifaddrs.h> appeared in glibc-2.3. */
67 # if !defined(__sgi__) && !defined(SUNOS) && !defined(__INNOTEK_LIBC__) \
68 && !(defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 2)) && !defined(__dietlibc__) && !defined(HPUX)
69 /* If for any reason ifaddrs.h does not exist on your system, comment out
70 * the following two lines and an alternative way will be used to fetch
71 * the list of IPs from the system. */
73 # define HAVE_GETIFADDRS
75 # if !defined(INADDR_NONE)
76 # define INADDR_NONE 0xffffffff
79 # if defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 1)
80 typedef uint32_t in_addr_t
;
84 # include <sys/time.h>
87 # if defined(__EMSCRIPTEN__)
88 /* Emscripten doesn't support AI_ADDRCONFIG and errors out on it. */
90 # define AI_ADDRCONFIG 0
91 /* Emscripten says it supports FD_SETSIZE fds, but it really only supports 64.
92 * https://github.com/emscripten-core/emscripten/issues/1711 */
94 # define FD_SETSIZE 64
101 # define INVALID_SOCKET -1
102 # define ioctlsocket ioctl
103 # define closesocket close
104 # define GET_LAST_ERROR() (sock_errno())
106 /* Includes needed for OS/2 systems */
109 # include <sys/ioctl.h>
110 # include <sys/socket.h>
111 # include <netinet/in.h>
112 # include <netinet/tcp.h>
113 # include <arpa/inet.h>
116 # include <sys/time.h>
119 # define INADDR_NONE 0xffffffff
120 # include "../../3rdparty/os2/getaddrinfo.h"
121 # include "../../3rdparty/os2/getnameinfo.h"
123 #define IPV6_V6ONLY 27
130 uint8_t __u6_addr8
[16];
131 uint16_t __u6_addr16
[8];
132 uint32_t __u6_addr32
[4];
133 } __u6_addr
; /* 128-bit IP6 address */
136 #define s6_addr __u6_addr.__u6_addr8
138 struct sockaddr_in6
{
139 uint8_t sin6_len
; /* length of this struct */
140 sa_family_t sin6_family
; /* AF_INET6 */
141 in_port_t sin6_port
; /* Transport layer port # */
142 uint32_t sin6_flowinfo
; /* IP6 flow information */
143 struct in6_addr sin6_addr
; /* IP6 address */
144 uint32_t sin6_scope_id
; /* scope zone index */
147 typedef int socklen_t
;
148 #if !defined(__INNOTEK_LIBC__)
149 typedef unsigned long in_addr_t
;
150 #endif /* __INNOTEK_LIBC__ */
154 #ifdef __EMSCRIPTEN__
156 * Emscripten doesn't set 'addrlen' for accept(), getsockname(), getpeername()
157 * and recvfrom(), which confuses other functions and causes them to crash.
158 * This function needs to be called after these four functions to make sure
159 * 'addrlen' is patched up.
161 * https://github.com/emscripten-core/emscripten/issues/12996
163 * @param address The address returned by those four functions.
164 * @return The correct value for addrlen.
166 static inline socklen_t
FixAddrLenForEmscripten(struct sockaddr_storage
&address
)
168 switch (address
.ss_family
) {
169 case AF_INET6
: return sizeof(struct sockaddr_in6
);
170 case AF_INET
: return sizeof(struct sockaddr_in
);
171 default: NOT_REACHED();
177 * Try to set the socket into non-blocking mode.
178 * @param d The socket to set the non-blocking more for.
179 * @return True if setting the non-blocking mode succeeded, otherwise false.
181 static inline bool SetNonBlocking(SOCKET d
)
183 #ifdef __EMSCRIPTEN__
187 u_long nonblocking
= 1;
191 return ioctlsocket(d
, FIONBIO
, &nonblocking
) == 0;
196 * Try to set the socket to not delay sending.
197 * @param d The socket to disable the delaying for.
198 * @return True if disabling the delaying succeeded, otherwise false.
200 static inline bool SetNoDelay(SOCKET d
)
202 #ifdef __EMSCRIPTEN__
205 /* XXX should this be done at all? */
207 /* The (const char*) cast is needed for windows */
208 return setsockopt(d
, IPPROTO_TCP
, TCP_NODELAY
, (const char*)&b
, sizeof(b
)) == 0;
212 /* Make sure these structures have the size we expect them to be */
213 static_assert(sizeof(in_addr
) == 4); ///< IPv4 addresses should be 4 bytes.
214 static_assert(sizeof(in6_addr
) == 16); ///< IPv6 addresses should be 16 bytes.
216 #endif /* NETWORK_CORE_OS_ABSTRACTION_H */