OpenTTD Source: src/network/core/os_abstraction.cpp Source File

OpenTTD Source 15.0-beta1

os_abstraction.cpp
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
19#include "stdafx.h"
20#include "os_abstraction.h"
21#include "../../string_func.h"
22#include "../../3rdparty/fmt/format.h"
23#include <mutex>
24
25#include "../../safeguards.h"
26
31NetworkError::NetworkError(int error) : error(error)
32{
33}
34
39 bool NetworkError::WouldBlock() const
40{
41#if defined(_WIN32)
42 return this->error == WSAEWOULDBLOCK;
43#else
44 /* Usually EWOULDBLOCK and EAGAIN are the same, but sometimes they are not
45 * and the POSIX.1 specification states that either should be checked. */
46 return this->error == EWOULDBLOCK || this->error == EAGAIN;
47#endif
48}
49
54 bool NetworkError::IsConnectionReset() const
55{
56#if defined(_WIN32)
57 return this->error == WSAECONNRESET;
58#else
59 return this->error == ECONNRESET;
60#endif
61}
62
67 bool NetworkError::IsConnectInProgress() const
68{
69#if defined(_WIN32)
70 return this->error == WSAEWOULDBLOCK;
71#else
72 return this->error == EINPROGRESS;
73#endif
74}
75
80 const std::string &NetworkError::AsString() const
81{
82 if (this->message.empty()) {
83#if defined(_WIN32)
84 wchar_t buffer[512];
85 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, this->error,
86 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, static_cast<DWORD>(std::size(buffer)), nullptr) == 0) {
87 this->message.assign(fmt::format("Unknown error {}", this->error));
88 } else {
89 this->message.assign(FS2OTTD(buffer));
90 }
91#else
92 /* Make strerror thread safe by locking access to it. There is a thread safe strerror_r, however
93 * the non-POSIX variant is available due to defining _GNU_SOURCE meaning it is not portable.
94 * The problem with the non-POSIX variant is that it does not necessarily fill the buffer with
95 * the error message but can also return a pointer to a static bit of memory, whereas the POSIX
96 * variant always fills the buffer. This makes the behaviour too erratic to work with. */
97 static std::mutex mutex;
98 std::lock_guard<std::mutex> guard(mutex);
99 this->message.assign(strerror(this->error));
100#endif
101 }
102 return this->message;
103}
104
109 bool NetworkError::HasError() const
110{
111 return this->error != 0;
112}
113
118/* static */ NetworkError NetworkError::GetLast()
119{
120#if defined(_WIN32)
121 return NetworkError(WSAGetLastError());
122#else
123 return NetworkError(errno);
124#endif
125}
126
127
133 bool SetNonBlocking([[maybe_unused]] SOCKET d)
134{
135#if defined(_WIN32)
136 u_long nonblocking = 1;
137 return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
138#elif defined __EMSCRIPTEN__
139 return true;
140#else
141 int nonblocking = 1;
142 return ioctl(d, FIONBIO, &nonblocking) == 0;
143#endif
144}
145
151 bool SetNoDelay([[maybe_unused]] SOCKET d)
152{
153#ifdef __EMSCRIPTEN__
154 return true;
155#else
156 int flags = 1;
157 /* The (const char*) cast is needed for windows */
158 return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char *)&flags, sizeof(flags)) == 0;
159#endif
160}
161
167 bool SetReusePort(SOCKET d)
168{
169#ifdef _WIN32
170 /* Windows has no SO_REUSEPORT, but for our usecases SO_REUSEADDR does the same job. */
171 int reuse_port = 1;
172 return setsockopt(d, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse_port, sizeof(reuse_port)) == 0;
173#else
174 int reuse_port = 1;
175 return setsockopt(d, SOL_SOCKET, SO_REUSEPORT, &reuse_port, sizeof(reuse_port)) == 0;
176#endif
177}
178
184 NetworkError GetSocketError(SOCKET d)
185{
186 int err;
187 socklen_t len = sizeof(err);
188 getsockopt(d, SOL_SOCKET, SO_ERROR, (char *)&err, &len);
189
190 return NetworkError(err);
191}
NetworkError
Abstraction of a network error where all implementation details of the error codes are encapsulated i...
Definition os_abstraction.h:21
NetworkError::WouldBlock
bool WouldBlock() const
Check whether this error describes that the operation would block.
Definition os_abstraction.cpp:39
NetworkError::IsConnectInProgress
bool IsConnectInProgress() const
Check whether this error describes a connect is in progress.
Definition os_abstraction.cpp:67
NetworkError::error
int error
The underlying error number from errno or WSAGetLastError.
Definition os_abstraction.h:23
NetworkError::HasError
bool HasError() const
Check whether an error was actually set.
Definition os_abstraction.cpp:109
NetworkError::IsConnectionReset
bool IsConnectionReset() const
Check whether this error describes a connection reset.
Definition os_abstraction.cpp:54
NetworkError::message
std::string message
The string representation of the error (set on first call to AsString).
Definition os_abstraction.h:24
NetworkError::AsString
const std::string & AsString() const
Get the string representation of the error message.
Definition os_abstraction.cpp:80
NetworkError::NetworkError
NetworkError(int error)
Construct the network error with the given error code.
Definition os_abstraction.cpp:31
NetworkError::GetLast
static NetworkError GetLast()
Get the last network error.
Definition os_abstraction.cpp:118
SetReusePort
bool SetReusePort(SOCKET d)
Try to set the socket to reuse ports.
Definition os_abstraction.cpp:167
SetNoDelay
bool SetNoDelay(SOCKET d)
Try to set the socket to not delay sending.
Definition os_abstraction.cpp:151
SetNonBlocking
bool SetNonBlocking(SOCKET d)
Try to set the socket into non-blocking mode.
Definition os_abstraction.cpp:133
GetSocketError
NetworkError GetSocketError(SOCKET d)
Get the error from a socket, if any.
Definition os_abstraction.cpp:184
os_abstraction.h
Network stuff has many things that needs to be included and/or implemented by default.
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
FS2OTTD
std::string FS2OTTD(const std::wstring &name)
Convert to OpenTTD's encoding from a wide string.
Definition win32.cpp:337