From 0ca24aa61f56811572aa3438399fb68314d2c1da Mon Sep 17 00:00:00 2001 From: "Leslie P. Polzer" Date: Sat, 29 Nov 2025 12:52:04 +0800 Subject: [PATCH] Fix miniupnpc setsockopt incompatible pointer type on Windows with GCC 14+ GCC 14+ treats -Wincompatible-pointer-types as an error by default. On Windows, setsockopt() expects const char* for the option value, and socket timeouts (SO_RCVTIMEO/SO_SNDTIMEO) use DWORD (milliseconds) instead of struct timeval. This was also a latent bug: the original code passed a struct timeval (8 bytes: {tv_sec=3, tv_usec=0}) but Windows expects a DWORD (4 bytes) containing milliseconds. Windows would read only the first 4 bytes (value 3) as 3 milliseconds instead of the intended 3 seconds. --- ext/miniupnpc/connecthostport.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ext/miniupnpc/connecthostport.c b/ext/miniupnpc/connecthostport.c index aed62c76e3..7eac33e428 100644 --- a/ext/miniupnpc/connecthostport.c +++ b/ext/miniupnpc/connecthostport.c @@ -74,7 +74,11 @@ int connecthostport(const char * host, unsigned short port, struct addrinfo hints; #endif /* #ifdef USE_GETHOSTBYNAME */ #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT +#ifdef _WIN32 + DWORD timeout; +#else struct timeval timeout; +#endif #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ #ifdef USE_GETHOSTBYNAME @@ -94,15 +98,25 @@ int connecthostport(const char * host, unsigned short port, } #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT /* setting a 3 seconds timeout for the connect() call */ +#ifdef _WIN32 + timeout = 3000; /* milliseconds */ + if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)) < 0) +#else timeout.tv_sec = 3; timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) +#endif { PRINT_SOCKET_ERROR("setsockopt SO_RCVTIMEO"); } +#ifdef _WIN32 + timeout = 3000; /* milliseconds */ + if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)) < 0) +#else timeout.tv_sec = 3; timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) +#endif { PRINT_SOCKET_ERROR("setsockopt SO_SNDTIMEO"); } @@ -193,15 +207,25 @@ int connecthostport(const char * host, unsigned short port, } #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT /* setting a 3 seconds timeout for the connect() call */ +#ifdef _WIN32 + timeout = 3000; /* milliseconds */ + if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)) < 0) +#else timeout.tv_sec = 3; timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) +#endif { PRINT_SOCKET_ERROR("setsockopt"); } +#ifdef _WIN32 + timeout = 3000; /* milliseconds */ + if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)) < 0) +#else timeout.tv_sec = 3; timeout.tv_usec = 0; if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) +#endif { PRINT_SOCKET_ERROR("setsockopt"); }