OpenTTD Source  20241121-master-g67a0fccfad
os_abstraction.h
Go to the documentation of this file.
1 /*
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/>.
6  */
7 
14 #ifndef NETWORK_CORE_OS_ABSTRACTION_H
15 #define NETWORK_CORE_OS_ABSTRACTION_H
16 
21 class NetworkError {
22 private:
23  int error;
24  mutable std::string message;
25 public:
26  NetworkError(int error);
27 
28  bool HasError() const;
29  bool WouldBlock() const;
30  bool IsConnectionReset() const;
31  bool IsConnectInProgress() const;
32  const std::string &AsString() const;
33 
34  static NetworkError GetLast();
35 };
36 
37 /* Include standard stuff per OS */
38 
39 /* Windows stuff */
40 #if defined(_WIN32)
41 #include <errno.h>
42 #include <winsock2.h>
43 #include <ws2tcpip.h>
44 #include <windows.h>
45 
46 /* Windows has some different names for some types */
47 typedef unsigned long in_addr_t;
48 
49 /* Handle cross-compilation with --build=*-*-cygwin --host=*-*-mingw32 */
50 #if defined(__MINGW32__) && !defined(AI_ADDRCONFIG)
51 # define AI_ADDRCONFIG 0x00000400
52 #endif
53 
54 #if !(defined(__MINGW32__) || defined(__CYGWIN__))
55  /* Windows has some different names for some types */
56  typedef SSIZE_T ssize_t;
57  typedef int socklen_t;
58 # define IPPROTO_IPV6 41
59 #endif /* !(__MINGW32__ && __CYGWIN__) */
60 #endif /* _WIN32 */
61 
62 /* UNIX stuff */
63 #if defined(UNIX)
64 # if defined(OPENBSD) || defined(__NetBSD__)
65 # define AI_ADDRCONFIG 0
66 # endif
67 # define SOCKET int
68 # define INVALID_SOCKET -1
69 # define closesocket close
70 /* Need this for FIONREAD on solaris */
71 # define BSD_COMP
72 
73 /* Includes needed for UNIX-like systems */
74 # include <unistd.h>
75 # include <sys/ioctl.h>
76 # include <sys/socket.h>
77 # include <netinet/in.h>
78 # include <netinet/tcp.h>
79 # include <arpa/inet.h>
80 # include <net/if.h>
81 # include <ifaddrs.h>
82 # if !defined(INADDR_NONE)
83 # define INADDR_NONE 0xffffffff
84 # endif
85 
86 # if defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 1)
87  typedef uint32_t in_addr_t;
88 # endif
89 
90 # include <errno.h>
91 # include <sys/time.h>
92 # include <netdb.h>
93 
94 # if defined(__EMSCRIPTEN__)
95 /* Emscripten doesn't support AI_ADDRCONFIG and errors out on it. */
96 # undef AI_ADDRCONFIG
97 # define AI_ADDRCONFIG 0
98 /* Emscripten says it supports FD_SETSIZE fds, but it really only supports 64.
99  * https://github.com/emscripten-core/emscripten/issues/1711 */
100 # undef FD_SETSIZE
101 # define FD_SETSIZE 64
102 # endif
103 
104 /* Haiku says it supports FD_SETSIZE fds, but it really only supports 512. */
105 # if defined(__HAIKU__)
106 # undef FD_SETSIZE
107 # define FD_SETSIZE 512
108 # endif
109 
110 #endif /* UNIX */
111 
112 #ifdef __EMSCRIPTEN__
124 inline socklen_t FixAddrLenForEmscripten(struct sockaddr_storage &address)
125 {
126  switch (address.ss_family) {
127  case AF_INET6: return sizeof(struct sockaddr_in6);
128  case AF_INET: return sizeof(struct sockaddr_in);
129  default: NOT_REACHED();
130  }
131 }
132 #endif
133 
134 
135 bool SetNonBlocking(SOCKET d);
136 bool SetNoDelay(SOCKET d);
137 bool SetReusePort(SOCKET d);
138 NetworkError GetSocketError(SOCKET d);
139 
140 /* Make sure these structures have the size we expect them to be */
141 static_assert(sizeof(in_addr) == 4);
142 static_assert(sizeof(in6_addr) == 16);
143 
144 #endif /* NETWORK_CORE_OS_ABSTRACTION_H */
Abstraction of a network error where all implementation details of the error codes are encapsulated i...
bool WouldBlock() const
Check whether this error describes that the operation would block.
bool IsConnectInProgress() const
Check whether this error describes a connect is in progress.
int error
The underlying error number from errno or WSAGetLastError.
bool HasError() const
Check whether an error was actually set.
bool IsConnectionReset() const
Check whether this error describes a connection reset.
std::string message
The string representation of the error (set on first call to AsString).
const std::string & AsString() const
Get the string representation of the error message.
NetworkError(int error)
Construct the network error with the given error code.
static NetworkError GetLast()
Get the last network error.
bool SetNonBlocking([[maybe_unused]] SOCKET d)
Try to set the socket into non-blocking mode.
bool SetNoDelay([[maybe_unused]] SOCKET d)
Try to set the socket to not delay sending.
bool SetReusePort(SOCKET d)
Try to set the socket to reuse ports.
NetworkError GetSocketError(SOCKET d)
Get the error from a socket, if any.