From 8e94528d6f26f0b5fe378e9a01fd1ec04c214832 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Tue, 24 Nov 2015 15:57:17 +0100 Subject: [PATCH 1/3] Improved signal and UDP bind debugging information, decreased verbosity of windows SHM errors. --- lib/config.cpp | 2 +- lib/shared_memory.cpp | 2 +- lib/socket.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/config.cpp b/lib/config.cpp index 660c07d5..15629e4d 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -453,7 +453,7 @@ void Util::Config::activate() { /// a SIGINT, SIGHUP or SIGTERM signal, reaps children for the SIGCHLD /// signal, and ignores all other signals. void Util::Config::signal_handler(int signum, siginfo_t * sigInfo, void * ignore) { - HIGH_MSG("Received signal %d from process %d", signum, sigInfo->si_pid); + HIGH_MSG("Received signal %s (%d) from process %d", strsignal(signum), signum, sigInfo->si_pid); switch (signum) { case SIGINT: //these three signals will set is_active to false. case SIGHUP: diff --git a/lib/shared_memory.cpp b/lib/shared_memory.cpp index c4fc6751..8b678be4 100644 --- a/lib/shared_memory.cpp +++ b/lib/shared_memory.cpp @@ -353,7 +353,7 @@ namespace IPC { } while (i < 10 && !handle && autoBackoff); } if (!handle) { - FAIL_MSG("%s for page %s failed with error code %u", (master ? "CreateFileMapping" : "OpenFileMapping"), name.c_str(), GetLastError()); + MEDIUM_MSG("%s for page %s failed with error code %u", (master ? "CreateFileMapping" : "OpenFileMapping"), name.c_str(), GetLastError()); return; } mapped = (char *)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0); diff --git a/lib/socket.cpp b/lib/socket.cpp index f197bd36..be206a29 100644 --- a/lib/socket.cpp +++ b/lib/socket.cpp @@ -1157,7 +1157,7 @@ int Socket::UDPConnection::bind(int port) { return ntohs(s4.sin_port); } - DEBUG_MSG(DLVL_FAIL, "Could not bind UDP socket to port %d", port); + DEBUG_MSG(DLVL_FAIL, "Could not bind UDP socket to port %d: %s", port, strerror(errno)); return 0; } From be3a852fb01e6652e310c4edeb539480b415d213 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Tue, 24 Nov 2015 16:57:23 +0100 Subject: [PATCH 2/3] Made UDP socket binding more robust. --- lib/socket.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/socket.cpp b/lib/socket.cpp index be206a29..c41d811e 100644 --- a/lib/socket.cpp +++ b/lib/socket.cpp @@ -1136,28 +1136,27 @@ void Socket::UDPConnection::SendNow(const char * sdata, size_t len) { /// \return Actually bound port number, or zero on error. int Socket::UDPConnection::bind(int port) { struct sockaddr_in6 s6; + memset(&s6, 0, sizeof(s6)); s6.sin6_family = AF_INET6; s6.sin6_addr = in6addr_any; - if (port) { - s6.sin6_port = htons(port); - } + s6.sin6_port = htons(port); int r = ::bind(sock, (sockaddr *)&s6, sizeof(s6)); if (r == 0) { return ntohs(s6.sin6_port); } + unsigned int ipv6_errno = errno; struct sockaddr_in s4; + memset(&s4, 0, sizeof(s4)); s4.sin_family = AF_INET; s4.sin_addr.s_addr = INADDR_ANY; - if (port) { - s4.sin_port = htons(port); - } + s4.sin_port = htons(port); r = ::bind(sock, (sockaddr *)&s4, sizeof(s4)); if (r == 0) { return ntohs(s4.sin_port); } - DEBUG_MSG(DLVL_FAIL, "Could not bind UDP socket to port %d: %s", port, strerror(errno)); + DEBUG_MSG(DLVL_FAIL, "Could not bind UDP socket to port %d: IPv6: %s, IPv4: %s", port, strerror(ipv6_errno), strerror(errno)); return 0; } From 5ae0cb42a9710114dbcc5932d4c4aa84199f29a7 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Tue, 24 Nov 2015 22:46:37 +0100 Subject: [PATCH 3/3] UDP binds can now bind to a specific interface, fixed IPv4 support for UDP sockets on IPv6-capable machines. --- lib/socket.cpp | 62 ++++++++++++++++++++++++++++++++------------------ lib/socket.h | 3 ++- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/lib/socket.cpp b/lib/socket.cpp index c41d811e..a0138904 100644 --- a/lib/socket.cpp +++ b/lib/socket.cpp @@ -971,9 +971,11 @@ int Socket::Server::getSocket() { /// If both fail, prints an DLVL_FAIL debug message. /// \param nonblock Whether the socket should be nonblocking. Socket::UDPConnection::UDPConnection(bool nonblock) { + isIPv6 = true; sock = socket(AF_INET6, SOCK_DGRAM, 0); if (sock == -1) { sock = socket(AF_INET, SOCK_DGRAM, 0); + isIPv6 = false; } if (sock == -1) { DEBUG_MSG(DLVL_FAIL, "Could not create UDP socket: %s", strerror(errno)); @@ -993,9 +995,17 @@ Socket::UDPConnection::UDPConnection(bool nonblock) { /// Copies a UDP socket, re-allocating local copies of any needed structures. /// The data/data_size/data_len variables are *not* copied over. Socket::UDPConnection::UDPConnection(const UDPConnection & o) { + isIPv6 = true; sock = socket(AF_INET6, SOCK_DGRAM, 0); if (sock == -1) { sock = socket(AF_INET, SOCK_DGRAM, 0); + isIPv6 = false; + }else{ +#ifdef __CYGWIN__ + // Under windows, turn IPv6-only mode off. + int on = 0; + setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); +#endif } if (sock == -1) { DEBUG_MSG(DLVL_FAIL, "Could not create UDP socket: %s", strerror(errno)); @@ -1134,29 +1144,37 @@ void Socket::UDPConnection::SendNow(const char * sdata, size_t len) { /// If that fails too, gives up and returns zero. /// Prints a debug message at DLVL_FAIL level if binding failed. /// \return Actually bound port number, or zero on error. -int Socket::UDPConnection::bind(int port) { - struct sockaddr_in6 s6; - memset(&s6, 0, sizeof(s6)); - s6.sin6_family = AF_INET6; - s6.sin6_addr = in6addr_any; - s6.sin6_port = htons(port); - int r = ::bind(sock, (sockaddr *)&s6, sizeof(s6)); - if (r == 0) { - return ntohs(s6.sin6_port); +int Socket::UDPConnection::bind(int port, std::string iface) { + if (isIPv6){ + struct sockaddr_in6 s6; + memset(&s6, 0, sizeof(s6)); + s6.sin6_family = AF_INET6; + if (iface == "0.0.0.0" || iface.length() == 0) { + s6.sin6_addr = in6addr_any; + } else { + inet_pton(AF_INET6, iface.c_str(), &s6.sin6_addr); + } + s6.sin6_port = htons(port); + int r = ::bind(sock, (sockaddr *)&s6, sizeof(s6)); + if (r == 0) { + return ntohs(s6.sin6_port); + } + }else{ + struct sockaddr_in s4; + memset(&s4, 0, sizeof(s4)); + s4.sin_family = AF_INET; + if (iface == "0.0.0.0" || iface.length() == 0) { + s4.sin_addr.s_addr = INADDR_ANY; + } else { + inet_pton(AF_INET, iface.c_str(), &s4.sin_addr); + } + s4.sin_port = htons(port); + int r = ::bind(sock, (sockaddr *)&s4, sizeof(s4)); + if (r == 0) { + return ntohs(s4.sin_port); + } } - unsigned int ipv6_errno = errno; - - struct sockaddr_in s4; - memset(&s4, 0, sizeof(s4)); - s4.sin_family = AF_INET; - s4.sin_addr.s_addr = INADDR_ANY; - s4.sin_port = htons(port); - r = ::bind(sock, (sockaddr *)&s4, sizeof(s4)); - if (r == 0) { - return ntohs(s4.sin_port); - } - - DEBUG_MSG(DLVL_FAIL, "Could not bind UDP socket to port %d: IPv6: %s, IPv4: %s", port, strerror(ipv6_errno), strerror(errno)); + DEBUG_MSG(DLVL_FAIL, "Could not bind %s UDP socket to port %d: %s", isIPv6?"IPv6":"IPv4", port, strerror(errno)); return 0; } diff --git a/lib/socket.h b/lib/socket.h index 62de9d6a..b6e733e1 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -129,6 +129,7 @@ namespace Socket { unsigned int up;///< Amount of bytes transferred up. unsigned int down;///< Amount of bytes transferred down. unsigned int data_size;///< The size in bytes of the allocated space in the data pointer. + bool isIPv6;//<<< True if IPv6 socket, false otherwise. public: char * data;///< Holds the last received packet. unsigned int data_len; ///< The size in bytes of the last received packet. @@ -136,7 +137,7 @@ namespace Socket { UDPConnection(bool nonblock = false); ~UDPConnection(); int getSock(); - int bind(int port); + int bind(int port, std::string iface = ""); void setBlocking(bool blocking); void SetDestination(std::string hostname, uint32_t port); void GetDestination(std::string & hostname, uint32_t & port);