OpenTTD Source  20240919-master-gdf0233f4c2
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__
113 
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 */
SetNonBlocking
bool SetNonBlocking([[maybe_unused]] SOCKET d)
Try to set the socket into non-blocking mode.
Definition: os_abstraction.cpp:133
NetworkError::HasError
bool HasError() const
Check whether an error was actually set.
Definition: os_abstraction.cpp:109
NetworkError::message
std::string message
The string representation of the error (set on first call to AsString).
Definition: os_abstraction.h:24
NetworkError::WouldBlock
bool WouldBlock() const
Check whether this error describes that the operation would block.
Definition: os_abstraction.cpp:39
NetworkError::GetLast
static NetworkError GetLast()
Get the last network error.
Definition: os_abstraction.cpp:118
SetNoDelay
bool SetNoDelay([[maybe_unused]] SOCKET d)
Try to set the socket to not delay sending.
Definition: os_abstraction.cpp:151
NetworkError::error
int error
The underlying error number from errno or WSAGetLastError.
Definition: os_abstraction.h:23
NetworkError::IsConnectInProgress
bool IsConnectInProgress() const
Check whether this error describes a connect is in progress.
Definition: os_abstraction.cpp:67
SetReusePort
bool SetReusePort(SOCKET d)
Try to set the socket to reuse ports.
Definition: os_abstraction.cpp:167
NetworkError::IsConnectionReset
bool IsConnectionReset() const
Check whether this error describes a connection reset.
Definition: os_abstraction.cpp:54
NetworkError::AsString
const std::string & AsString() const
Get the string representation of the error message.
Definition: os_abstraction.cpp:80
NetworkError
Abstraction of a network error where all implementation details of the error codes are encapsulated i...
Definition: os_abstraction.h:21
GetSocketError
NetworkError GetSocketError(SOCKET d)
Get the error from a socket, if any.
Definition: os_abstraction.cpp:184
NetworkError::NetworkError
NetworkError(int error)
Construct the network error with the given error code.
Definition: os_abstraction.cpp:31