OpenTTD Source 20260109-master-g241b5fcdfe
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10#ifndef NETWORK_CORE_OS_ABSTRACTION_H
11#define NETWORK_CORE_OS_ABSTRACTION_H
12
18private:
19 int error;
20 mutable std::string message;
21public:
22 NetworkError(int error, std::string_view message = {});
23
24 bool HasError() const;
25 bool WouldBlock() const;
26 bool IsConnectionReset() const;
27 bool IsConnectInProgress() const;
28 std::string_view AsString() const;
29
30 static NetworkError GetLast();
31};
32
33/* Include standard stuff per OS */
34
35/* Windows stuff */
36#if defined(_WIN32)
37#include <errno.h>
38#include <winsock2.h>
39#include <ws2tcpip.h>
40#include <windows.h>
41
42/* Windows has some different names for some types */
43typedef unsigned long in_addr_t;
44
45/* Handle cross-compilation with --build=*-*-cygwin --host=*-*-mingw32 */
46#if defined(__MINGW32__) && !defined(AI_ADDRCONFIG)
47# define AI_ADDRCONFIG 0x00000400
48#endif
49
50#if !(defined(__MINGW32__) || defined(__CYGWIN__))
51 /* Windows has some different names for some types */
52 typedef SSIZE_T ssize_t;
53 typedef int socklen_t;
54# define IPPROTO_IPV6 41
55#endif /* !(__MINGW32__ && __CYGWIN__) */
56#endif /* _WIN32 */
57
58/* UNIX stuff */
59#if defined(UNIX)
60# if defined(OPENBSD) || defined(__NetBSD__)
61# define AI_ADDRCONFIG 0
62# endif
63# define SOCKET int
64# define INVALID_SOCKET -1
65# define closesocket close
66/* Need this for FIONREAD on solaris */
67# define BSD_COMP
68
69/* Includes needed for UNIX-like systems */
70# include <unistd.h>
71# include <sys/ioctl.h>
72# include <sys/socket.h>
73# include <netinet/in.h>
74# include <netinet/tcp.h>
75# include <arpa/inet.h>
76# include <net/if.h>
77# include <ifaddrs.h>
78# if !defined(INADDR_NONE)
79# define INADDR_NONE 0xffffffff
80# endif
81
82# if defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 1)
83 typedef uint32_t in_addr_t;
84# endif
85
86# include <errno.h>
87# include <sys/time.h>
88# include <netdb.h>
89
90# if defined(__EMSCRIPTEN__)
91/* Emscripten doesn't support AI_ADDRCONFIG and errors out on it. */
92# undef AI_ADDRCONFIG
93# define AI_ADDRCONFIG 0
94/* Emscripten says it supports FD_SETSIZE fds, but it really only supports 64.
95 * https://github.com/emscripten-core/emscripten/issues/1711 */
96# undef FD_SETSIZE
97# define FD_SETSIZE 64
98# endif
99
100/* Haiku says it supports FD_SETSIZE fds, but it really only supports 512. */
101# if defined(__HAIKU__)
102# undef FD_SETSIZE
103# define FD_SETSIZE 512
104# endif
105
106#endif /* UNIX */
107
108#ifdef __EMSCRIPTEN__
120inline socklen_t FixAddrLenForEmscripten(struct sockaddr_storage &address)
121{
122 switch (address.ss_family) {
123 case AF_INET6: return sizeof(struct sockaddr_in6);
124 case AF_INET: return sizeof(struct sockaddr_in);
125 default: NOT_REACHED();
126 }
127}
128#endif
129
130
131bool SetNonBlocking(SOCKET d);
132bool SetNoDelay(SOCKET d);
133bool SetReusePort(SOCKET d);
135
136/* Make sure these structures have the size we expect them to be */
137static_assert(sizeof(in_addr) == 4);
138static_assert(sizeof(in6_addr) == 16);
139
141 SOCKET sock;
142
143 ssize_t operator()(std::span<const uint8_t> buffer)
144 {
145 return send(this->sock, reinterpret_cast<const char *>(buffer.data()), static_cast<int>(buffer.size()), 0);
146 }
147};
148
150 SOCKET sock;
151
152 ssize_t operator()(std::span<uint8_t> buffer)
153 {
154 return recv(this->sock, reinterpret_cast<char *>(buffer.data()), static_cast<int>(buffer.size()), 0);
155 }
156};
157
158#endif /* NETWORK_CORE_OS_ABSTRACTION_H */
Abstraction of a network error where all implementation details of the error codes are encapsulated i...
std::string_view AsString() const
Get the string representation of the error message.
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).
static NetworkError GetLast()
Get the last network error.
bool SetReusePort(SOCKET d)
Try to set the socket to reuse ports.
bool SetNoDelay(SOCKET d)
Try to set the socket to not delay sending.
bool SetNonBlocking(SOCKET d)
Try to set the socket into non-blocking mode.
NetworkError GetSocketError(SOCKET d)
Get the error from a socket, if any.
IPv4 addresses should be 4 bytes.