summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium42 <rubidium@openttd.org>2021-04-27 10:50:28 +0200
committerCharles Pigott <charlespigott@googlemail.com>2021-04-27 18:17:34 +0100
commit65c5a647191a9a10a532bb9d67da6938f5eace1b (patch)
tree0a2444886e56ad63583dae0e4e8f5a632a63199d
parenta934dfe0be9621b784ccd1dca81d2ef8214fc4e0 (diff)
downloadopenttd-65c5a647191a9a10a532bb9d67da6938f5eace1b.tar.xz
Fix: [Network] errno and strerror do not handle network errors on Windows
-rw-r--r--src/network/core/address.cpp14
-rw-r--r--src/network/core/core.cpp17
-rw-r--r--src/network/core/os_abstraction.h25
-rw-r--r--src/network/core/tcp.cpp6
-rw-r--r--src/network/core/tcp_http.cpp2
-rw-r--r--src/network/core/tcp_listen.h4
-rw-r--r--src/network/core/udp.cpp4
7 files changed, 54 insertions, 18 deletions
diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp
index 8c6909438..fc19439e0 100644
--- a/src/network/core/address.cpp
+++ b/src/network/core/address.cpp
@@ -316,7 +316,7 @@ static SOCKET ConnectLoopProc(addrinfo *runp)
SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
if (sock == INVALID_SOCKET) {
- DEBUG(net, 1, "[%s] could not create %s socket: %s", type, family, strerror(errno));
+ DEBUG(net, 1, "[%s] could not create %s socket: %s", type, family, NetworkGetLastErrorString());
return INVALID_SOCKET;
}
@@ -331,7 +331,7 @@ static SOCKET ConnectLoopProc(addrinfo *runp)
if (err != 0)
#endif
{
- DEBUG(net, 1, "[%s] could not connect %s socket: %s", type, family, strerror(errno));
+ DEBUG(net, 1, "[%s] could not connect %s socket: %s", type, family, NetworkGetLastErrorString());
closesocket(sock);
return INVALID_SOCKET;
}
@@ -369,7 +369,7 @@ static SOCKET ListenLoopProc(addrinfo *runp)
SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
if (sock == INVALID_SOCKET) {
- DEBUG(net, 0, "[%s] could not create %s socket on port %s: %s", type, family, address, strerror(errno));
+ DEBUG(net, 0, "[%s] could not create %s socket on port %s: %s", type, family, address, NetworkGetLastErrorString());
return INVALID_SOCKET;
}
@@ -380,24 +380,24 @@ static SOCKET ListenLoopProc(addrinfo *runp)
int on = 1;
/* The (const char*) cast is needed for windows!! */
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == -1) {
- DEBUG(net, 3, "[%s] could not set reusable %s sockets for port %s: %s", type, family, address, strerror(errno));
+ DEBUG(net, 3, "[%s] could not set reusable %s sockets for port %s: %s", type, family, address, NetworkGetLastErrorString());
}
#ifndef __OS2__
if (runp->ai_family == AF_INET6 &&
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof(on)) == -1) {
- DEBUG(net, 3, "[%s] could not disable IPv4 over IPv6 on port %s: %s", type, address, strerror(errno));
+ DEBUG(net, 3, "[%s] could not disable IPv4 over IPv6 on port %s: %s", type, address, NetworkGetLastErrorString());
}
#endif
if (bind(sock, runp->ai_addr, (int)runp->ai_addrlen) != 0) {
- DEBUG(net, 1, "[%s] could not bind on %s port %s: %s", type, family, address, strerror(errno));
+ DEBUG(net, 1, "[%s] could not bind on %s port %s: %s", type, family, address, NetworkGetLastErrorString());
closesocket(sock);
return INVALID_SOCKET;
}
if (runp->ai_socktype != SOCK_DGRAM && listen(sock, 1) != 0) {
- DEBUG(net, 1, "[%s] could not listen at %s port %s: %s", type, family, address, strerror(errno));
+ DEBUG(net, 1, "[%s] could not listen at %s port %s: %s", type, family, address, NetworkGetLastErrorString());
closesocket(sock);
return INVALID_SOCKET;
}
diff --git a/src/network/core/core.cpp b/src/network/core/core.cpp
index 0aeb9c65c..8c5c5c229 100644
--- a/src/network/core/core.cpp
+++ b/src/network/core/core.cpp
@@ -13,6 +13,7 @@
#include "../../debug.h"
#include "os_abstraction.h"
#include "packet.h"
+#include "../../string_func.h"
#include "../../safeguards.h"
@@ -48,6 +49,22 @@ void NetworkCoreShutdown()
#endif
}
+#if defined(_WIN32)
+/**
+ * Return the string representation of the given error from the OS's network functions.
+ * @param error The error number (from \c NetworkGetLastError()).
+ * @return The error message, potentially an empty string but never \c nullptr.
+ */
+const char *NetworkGetErrorString(int error)
+{
+ static char buffer[512];
+ if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), NULL) == 0) {
+ seprintf(buffer, lastof(buffer), "Unknown error %d", error);
+ }
+ return buffer;
+}
+#endif /* defined(_WIN32) */
/**
* Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet
diff --git a/src/network/core/os_abstraction.h b/src/network/core/os_abstraction.h
index 836cfeae8..a015c4374 100644
--- a/src/network/core/os_abstraction.h
+++ b/src/network/core/os_abstraction.h
@@ -23,9 +23,17 @@
#include <ws2tcpip.h>
#include <windows.h>
-#define GET_LAST_ERROR() WSAGetLastError()
+/**
+ * Get the last error code from any of the OS's network functions.
+ * What it returns and when it is reset, is implementation defined.
+ * @return The last error code.
+ */
+#define NetworkGetLastError() WSAGetLastError()
#undef EWOULDBLOCK
#define EWOULDBLOCK WSAEWOULDBLOCK
+
+const char *NetworkGetErrorString(int error);
+
/* Windows has some different names for some types */
typedef unsigned long in_addr_t;
@@ -51,7 +59,8 @@ typedef unsigned long in_addr_t;
# define INVALID_SOCKET -1
# define ioctlsocket ioctl
# define closesocket close
-# define GET_LAST_ERROR() (errno)
+# define NetworkGetLastError() (errno)
+# define NetworkGetErrorString(error) (strerror(error))
/* Need this for FIONREAD on solaris */
# define BSD_COMP
@@ -101,7 +110,8 @@ typedef unsigned long in_addr_t;
# define INVALID_SOCKET -1
# define ioctlsocket ioctl
# define closesocket close
-# define GET_LAST_ERROR() (sock_errno())
+# define NetworkGetLastError() (sock_errno())
+# define NetworkGetErrorString(error) (strerror(error))
/* Includes needed for OS/2 systems */
# include <types.h>
@@ -174,6 +184,15 @@ static inline socklen_t FixAddrLenForEmscripten(struct sockaddr_storage &address
#endif
/**
+ * Return the string representation of the last error from the OS's network functions.
+ * @return The error message, potentially an empty string but never \c nullptr.
+ */
+static inline const char *NetworkGetLastErrorString()
+{
+ return NetworkGetErrorString(NetworkGetLastError());
+}
+
+/**
* Try to set the socket into non-blocking mode.
* @param d The socket to set the non-blocking more for.
* @return True if setting the non-blocking mode succeeded, otherwise false.
diff --git a/src/network/core/tcp.cpp b/src/network/core/tcp.cpp
index 72e66a0b5..b9ba33f00 100644
--- a/src/network/core/tcp.cpp
+++ b/src/network/core/tcp.cpp
@@ -86,7 +86,7 @@ SendPacketsState NetworkTCPSocketHandler::SendPackets(bool closing_down)
while ((p = this->packet_queue) != nullptr) {
res = p->TransferOut<int>(send, this->sock, 0);
if (res == -1) {
- int err = GET_LAST_ERROR();
+ int err = NetworkGetLastError();
if (err != EWOULDBLOCK) {
/* Something went wrong.. close client! */
if (!closing_down) {
@@ -136,7 +136,7 @@ Packet *NetworkTCPSocketHandler::ReceivePacket()
while (p->RemainingBytesToTransfer() != 0) {
res = p->TransferIn<int>(recv, this->sock, 0);
if (res == -1) {
- int err = GET_LAST_ERROR();
+ int err = NetworkGetLastError();
if (err != EWOULDBLOCK) {
/* Something went wrong... (104 is connection reset by peer) */
if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
@@ -164,7 +164,7 @@ Packet *NetworkTCPSocketHandler::ReceivePacket()
while (p->RemainingBytesToTransfer() != 0) {
res = p->TransferIn<int>(recv, this->sock, 0);
if (res == -1) {
- int err = GET_LAST_ERROR();
+ int err = NetworkGetLastError();
if (err != EWOULDBLOCK) {
/* Something went wrong... (104 is connection reset by peer) */
if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
diff --git a/src/network/core/tcp_http.cpp b/src/network/core/tcp_http.cpp
index d88ea711d..04bc6a03a 100644
--- a/src/network/core/tcp_http.cpp
+++ b/src/network/core/tcp_http.cpp
@@ -228,7 +228,7 @@ int NetworkHTTPSocketHandler::Receive()
for (;;) {
ssize_t res = recv(this->sock, (char *)this->recv_buffer + this->recv_pos, lengthof(this->recv_buffer) - this->recv_pos, 0);
if (res == -1) {
- int err = GET_LAST_ERROR();
+ int err = NetworkGetLastError();
if (err != EWOULDBLOCK) {
/* Something went wrong... (104 is connection reset by peer) */
if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
diff --git a/src/network/core/tcp_listen.h b/src/network/core/tcp_listen.h
index 53a3d57cc..c11727ba7 100644
--- a/src/network/core/tcp_listen.h
+++ b/src/network/core/tcp_listen.h
@@ -64,7 +64,7 @@ public:
DEBUG(net, 1, "[%s] Banned ip tried to join (%s), refused", Tsocket::GetName(), entry.c_str());
if (p.TransferOut<int>(send, s, 0) < 0) {
- DEBUG(net, 0, "send failed with error %d", GET_LAST_ERROR());
+ DEBUG(net, 0, "send failed with error %d", NetworkGetLastError());
}
closesocket(s);
break;
@@ -81,7 +81,7 @@ public:
p.PrepareToSend();
if (p.TransferOut<int>(send, s, 0) < 0) {
- DEBUG(net, 0, "send failed with error %d", GET_LAST_ERROR());
+ DEBUG(net, 0, "send failed with error %d", NetworkGetLastError());
}
closesocket(s);
diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp
index e8299f7b6..abbb1bbdb 100644
--- a/src/network/core/udp.cpp
+++ b/src/network/core/udp.cpp
@@ -94,7 +94,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a
/* Enable broadcast */
unsigned long val = 1;
if (setsockopt(s.second, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val)) < 0) {
- DEBUG(net, 1, "[udp] setting broadcast failed with: %i", GET_LAST_ERROR());
+ DEBUG(net, 1, "[udp] setting broadcast failed with: %i", NetworkGetLastError());
}
}
@@ -103,7 +103,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a
DEBUG(net, 7, "[udp] sendto(%s)", send.GetAddressAsString().c_str());
/* Check for any errors, but ignore it otherwise */
- if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %i", send.GetAddressAsString().c_str(), GET_LAST_ERROR());
+ if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %i", send.GetAddressAsString().c_str(), NetworkGetLastError());
if (!all) break;
}