diff options
author | rubidium42 <rubidium@openttd.org> | 2021-04-27 10:50:28 +0200 |
---|---|---|
committer | Charles Pigott <charlespigott@googlemail.com> | 2021-04-27 18:17:34 +0100 |
commit | 65c5a647191a9a10a532bb9d67da6938f5eace1b (patch) | |
tree | 0a2444886e56ad63583dae0e4e8f5a632a63199d | |
parent | a934dfe0be9621b784ccd1dca81d2ef8214fc4e0 (diff) | |
download | openttd-65c5a647191a9a10a532bb9d67da6938f5eace1b.tar.xz |
Fix: [Network] errno and strerror do not handle network errors on Windows
-rw-r--r-- | src/network/core/address.cpp | 14 | ||||
-rw-r--r-- | src/network/core/core.cpp | 17 | ||||
-rw-r--r-- | src/network/core/os_abstraction.h | 25 | ||||
-rw-r--r-- | src/network/core/tcp.cpp | 6 | ||||
-rw-r--r-- | src/network/core/tcp_http.cpp | 2 | ||||
-rw-r--r-- | src/network/core/tcp_listen.h | 4 | ||||
-rw-r--r-- | src/network/core/udp.cpp | 4 |
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; } |