From 7128f1a0b0a278a838d80fa236a281946f18c1cb Mon Sep 17 00:00:00 2001 From: SASANO Takayoshi Date: Sun, 6 Sep 2020 13:09:31 +0900 Subject: [PATCH 1/5] use system default compiler --- YSFGateway/Makefile | 4 ++-- YSFParrot/Makefile | 4 ++-- YSFReflector/Makefile | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/YSFGateway/Makefile b/YSFGateway/Makefile index 0e1262b..4830908 100644 --- a/YSFGateway/Makefile +++ b/YSFGateway/Makefile @@ -1,5 +1,5 @@ -CC = gcc -CXX = g++ +CC = cc +CXX = c++ # Use the following CFLAGS and LIBS if you don't want to use gpsd. CFLAGS = -g -O3 -Wall -std=c++0x -pthread diff --git a/YSFParrot/Makefile b/YSFParrot/Makefile index b23206c..c73eaf9 100644 --- a/YSFParrot/Makefile +++ b/YSFParrot/Makefile @@ -1,5 +1,5 @@ -CC = gcc -CXX = g++ +CC = cc +CXX = c++ CFLAGS = -g -O3 -Wall -std=c++0x -pthread LIBS = -lpthread LDFLAGS = -g diff --git a/YSFReflector/Makefile b/YSFReflector/Makefile index 58bfccf..e04bd4d 100644 --- a/YSFReflector/Makefile +++ b/YSFReflector/Makefile @@ -1,5 +1,5 @@ -CC = gcc -CXX = g++ +CC = cc +CXX = c++ CFLAGS = -g -O3 -Wall -std=c++0x -pthread LIBS = -lpthread LDFLAGS = -g From 98231b02a558ede426d2746012741e8e85ab9073 Mon Sep 17 00:00:00 2001 From: SASANO Takayoshi Date: Sun, 6 Sep 2020 16:57:44 +0900 Subject: [PATCH 2/5] renew UDPSocket to support multiple sockets --- YSFReflector/UDPSocket.cpp | 152 +++++++++++++++++++++++++------------ YSFReflector/UDPSocket.h | 19 +++-- 2 files changed, 117 insertions(+), 54 deletions(-) diff --git a/YSFReflector/UDPSocket.cpp b/YSFReflector/UDPSocket.cpp index fb4eb16..382925f 100644 --- a/YSFReflector/UDPSocket.cpp +++ b/YSFReflector/UDPSocket.cpp @@ -17,7 +17,6 @@ */ #include "UDPSocket.h" -#include "Log.h" #include @@ -26,26 +25,36 @@ #include #endif +#if defined(HAVE_LOG_H) +#include "Log.h" +#else +#define LogError(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__) +#define LogInfo(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__) +#endif CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) : -m_address(address), -m_port(port), -m_fd(-1) +m_address_save(address), +m_port_save(port), +m_counter(0U) { - assert(!address.empty()); - #if defined(_WIN32) || defined(_WIN64) WSAData data; int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data); if (wsaRet != 0) LogError("Error from WSAStartup"); #endif + for (int i = 0; i < UDP_SOCKET_MAX; i++) { + m_address[i] = ""; + m_port[i] = 0U; + m_af[i] = 0U; + m_fd[i] = -1; + } } CUDPSocket::CUDPSocket(unsigned int port) : -m_address(), -m_port(port), -m_fd(-1) +m_address_save(), +m_port_save(port), +m_counter(0U) { #if defined(_WIN32) || defined(_WIN64) WSAData data; @@ -53,6 +62,12 @@ m_fd(-1) if (wsaRet != 0) LogError("Error from WSAStartup"); #endif + for (int i = 0; i < UDP_SOCKET_MAX; i++) { + m_address[i] = ""; + m_port[i] = 0U; + m_af[i] = 0U; + m_fd[i] = -1; + } } CUDPSocket::~CUDPSocket() @@ -149,6 +164,11 @@ bool CUDPSocket::open(const sockaddr_storage& address) } bool CUDPSocket::open(unsigned int af) +{ + return open(0, af, m_address_save, m_port_save); +} + +bool CUDPSocket::open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port) { sockaddr_storage addr; unsigned int addrlen; @@ -159,14 +179,14 @@ bool CUDPSocket::open(unsigned int af) hints.ai_family = af; /* to determine protocol family, call lookup() first. */ - int err = lookup(m_address, m_port, addr, addrlen, hints); + int err = lookup(address, port, addr, addrlen, hints); if (err != 0) { - LogError("The local address is invalid - %s", m_address.c_str()); + LogError("The local address is invalid - %s", address.c_str()); return false; } - m_fd = ::socket(addr.ss_family, SOCK_DGRAM, 0); - if (m_fd < 0) { + int fd = ::socket(addr.ss_family, SOCK_DGRAM, 0); + if (fd < 0) { #if defined(_WIN32) || defined(_WIN64) LogError("Cannot create the UDP socket, err: %lu", ::GetLastError()); #else @@ -175,9 +195,14 @@ bool CUDPSocket::open(unsigned int af) return false; } - if (m_port > 0U) { + m_address[index] = address; + m_port[index] = port; + m_af[index] = addr.ss_family; + m_fd[index] = fd; + + if (port > 0U) { int reuse = 1; - if (::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) { + if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) { #if defined(_WIN32) || defined(_WIN64) LogError("Cannot set the UDP socket option, err: %lu", ::GetLastError()); #else @@ -186,7 +211,7 @@ bool CUDPSocket::open(unsigned int af) return false; } - if (::bind(m_fd, (sockaddr*)&addr, addrlen) == -1) { + if (::bind(fd, (sockaddr*)&addr, addrlen) == -1) { #if defined(_WIN32) || defined(_WIN64) LogError("Cannot bind the UDP address, err: %lu", ::GetLastError()); #else @@ -195,7 +220,7 @@ bool CUDPSocket::open(unsigned int af) return false; } - LogInfo("Opening UDP port on %u", m_port); + LogInfo("Opening UDP port on %u", port); } return true; @@ -207,30 +232,43 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag assert(length > 0U); // Check that the readfrom() won't block - fd_set readFds; - FD_ZERO(&readFds); + int i, n; + struct pollfd pfd[UDP_SOCKET_MAX]; + for (i = n = 0; i < UDP_SOCKET_MAX; i++) { + if (m_fd[i] >= 0) { + pfd[n].fd = m_fd[i]; + pfd[n].events = POLLIN; + n++; + } + } + + // no socket descriptor to receive + if (n == 0) + return 0; + + // Return immediately #if defined(_WIN32) || defined(_WIN64) - FD_SET((unsigned int)m_fd, &readFds); + int ret = WSAPoll(pfd, n, 0); #else - FD_SET(m_fd, &readFds); + int ret = ::poll(pfd, n, 0); #endif - - // Return immediately - timeval tv; - tv.tv_sec = 0L; - tv.tv_usec = 0L; - - int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv); if (ret < 0) { #if defined(_WIN32) || defined(_WIN64) - LogError("Error returned from UDP select, err: %lu", ::GetLastError()); + LogError("Error returned from UDP poll, err: %lu", ::GetLastError()); #else - LogError("Error returned from UDP select, err: %d", errno); + LogError("Error returned from UDP poll, err: %d", errno); #endif return -1; } - if (ret == 0) + int index; + for (i = 0; i < n; i++) { + // round robin + index = (i + m_counter) % n; + if (pfd[index].revents & POLLIN) + break; + } + if (i == n) return 0; #if defined(_WIN32) || defined(_WIN64) @@ -240,9 +278,9 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag #endif #if defined(_WIN32) || defined(_WIN64) - int len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size); + int len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size); #else - ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size); + ssize_t len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size); #endif if (len <= 0) { #if defined(_WIN32) || defined(_WIN64) @@ -253,8 +291,8 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag return -1; } + m_counter++; address_length = size; - return len; } @@ -263,36 +301,52 @@ bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const s assert(buffer != NULL); assert(length > 0U); + bool result = false; + + for (int i = 0; i < UDP_SOCKET_MAX; i++) { + if (m_fd[i] < 0 || m_af[i] != address.ss_family) + continue; + #if defined(_WIN32) || defined(_WIN64) - int ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, address_length); + int ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length); #else - ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, address_length); + ssize_t ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length); #endif - if (ret < 0) { + + if (ret < 0) { #if defined(_WIN32) || defined(_WIN64) - LogError("Error returned from sendto, err: %lu", ::GetLastError()); + LogError("Error returned from sendto, err: %lu", ::GetLastError()); #else - LogError("Error returned from sendto, err: %d", errno); + LogError("Error returned from sendto, err: %d", errno); #endif - return false; - } - + } else { #if defined(_WIN32) || defined(_WIN64) - if (ret != int(length)) - return false; + if (ret == int(length)) + result = true; #else - if (ret != ssize_t(length)) - return false; + if (ret == ssize_t(length)) + result = true; #endif + } + } - return true; + return result; } void CUDPSocket::close() { + for (int i = 0; i < UDP_SOCKET_MAX; i++) + close(m_fd[i]); +} + +void CUDPSocket::close(const unsigned int index) +{ + if (m_fd[index] >= 0) { #if defined(_WIN32) || defined(_WIN64) - ::closesocket(m_fd); + ::closesocket(m_fd[index]); #else - ::close(m_fd); + ::close(m_fd[index]); #endif + m_fd[index] = -1; + } } diff --git a/YSFReflector/UDPSocket.h b/YSFReflector/UDPSocket.h index b169641..b22eefc 100644 --- a/YSFReflector/UDPSocket.h +++ b/YSFReflector/UDPSocket.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,10 @@ #include #endif +#if !defined(UDP_SOCKET_MAX) +#define UDP_SOCKET_MAX 1 +#endif + enum IPMATCHTYPE { IMT_ADDRESS_AND_PORT, IMT_ADDRESS_ONLY @@ -48,24 +53,28 @@ public: bool open(unsigned int af = AF_UNSPEC); bool open(const sockaddr_storage& address); + bool open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port); int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length); bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length); void close(); + void close(const unsigned int index); static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length); static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length, struct addrinfo& hints); - static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type = IMT_ADDRESS_AND_PORT); static bool isNone(const sockaddr_storage& addr); private: - std::string m_address; - unsigned short m_port; - int m_fd; + std::string m_address_save; + unsigned short m_port_save; + std::string m_address[UDP_SOCKET_MAX]; + unsigned short m_port[UDP_SOCKET_MAX]; + unsigned int m_af[UDP_SOCKET_MAX]; + int m_fd[UDP_SOCKET_MAX]; + unsigned int m_counter; }; #endif - From b09b5c0ed082386acfade964c4219d870cd3172b Mon Sep 17 00:00:00 2001 From: SASANO Takayoshi Date: Sun, 6 Sep 2020 16:58:29 +0900 Subject: [PATCH 3/5] enable IPv4/IPv6 dual-stack --- YSFReflector/Makefile | 2 +- YSFReflector/Network.cpp | 12 ++++++++++-- YSFReflector/Network.h | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/YSFReflector/Makefile b/YSFReflector/Makefile index e04bd4d..db9d0bb 100644 --- a/YSFReflector/Makefile +++ b/YSFReflector/Makefile @@ -1,6 +1,6 @@ CC = cc CXX = c++ -CFLAGS = -g -O3 -Wall -std=c++0x -pthread +CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 LIBS = -lpthread LDFLAGS = -g diff --git a/YSFReflector/Network.cpp b/YSFReflector/Network.cpp index 01cf732..01c2ea2 100644 --- a/YSFReflector/Network.cpp +++ b/YSFReflector/Network.cpp @@ -26,7 +26,8 @@ #include CNetwork::CNetwork(unsigned int port, unsigned int id, const std::string& name, const std::string& description, bool debug) : -m_socket(port), +m_socket(), +m_port(port), m_id(id), m_name(name), m_description(description), @@ -49,7 +50,14 @@ bool CNetwork::open() { LogInfo("Opening YSF network connection"); - return m_socket.open(); + bool status = false; + unsigned int af[] = {AF_INET, AF_INET6}; + + for (int i = 0; i < UDP_SOCKET_MAX && + i < (sizeof(af) / sizeof(unsigned int)); i++) + status |= m_socket.open(i, af[i], "", m_port); + + return status; } bool CNetwork::writeData(const unsigned char* data, const sockaddr_storage& addr, unsigned int addrLen) diff --git a/YSFReflector/Network.h b/YSFReflector/Network.h index e69283a..2c51371 100644 --- a/YSFReflector/Network.h +++ b/YSFReflector/Network.h @@ -44,6 +44,7 @@ public: private: CUDPSocket m_socket; + unsigned short m_port; unsigned int m_id; std::string m_name; std::string m_description; From 1fcf92a0fcc173cb19e873a7a7c60eb24261af40 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 6 Sep 2020 13:17:49 +0100 Subject: [PATCH 4/5] IPv6 cleanups. --- YSFGateway/UDPSocket.cpp | 152 ++++++++++++++++++++---------- YSFGateway/UDPSocket.h | 19 +++- YSFParrot/UDPSocket.cpp | 195 +++++++++++++++++++++++++-------------- YSFParrot/UDPSocket.h | 29 ++++-- YSFReflector/Network.cpp | 3 +- 5 files changed, 262 insertions(+), 136 deletions(-) diff --git a/YSFGateway/UDPSocket.cpp b/YSFGateway/UDPSocket.cpp index fb4eb16..382925f 100644 --- a/YSFGateway/UDPSocket.cpp +++ b/YSFGateway/UDPSocket.cpp @@ -17,7 +17,6 @@ */ #include "UDPSocket.h" -#include "Log.h" #include @@ -26,26 +25,36 @@ #include #endif +#if defined(HAVE_LOG_H) +#include "Log.h" +#else +#define LogError(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__) +#define LogInfo(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__) +#endif CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) : -m_address(address), -m_port(port), -m_fd(-1) +m_address_save(address), +m_port_save(port), +m_counter(0U) { - assert(!address.empty()); - #if defined(_WIN32) || defined(_WIN64) WSAData data; int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data); if (wsaRet != 0) LogError("Error from WSAStartup"); #endif + for (int i = 0; i < UDP_SOCKET_MAX; i++) { + m_address[i] = ""; + m_port[i] = 0U; + m_af[i] = 0U; + m_fd[i] = -1; + } } CUDPSocket::CUDPSocket(unsigned int port) : -m_address(), -m_port(port), -m_fd(-1) +m_address_save(), +m_port_save(port), +m_counter(0U) { #if defined(_WIN32) || defined(_WIN64) WSAData data; @@ -53,6 +62,12 @@ m_fd(-1) if (wsaRet != 0) LogError("Error from WSAStartup"); #endif + for (int i = 0; i < UDP_SOCKET_MAX; i++) { + m_address[i] = ""; + m_port[i] = 0U; + m_af[i] = 0U; + m_fd[i] = -1; + } } CUDPSocket::~CUDPSocket() @@ -149,6 +164,11 @@ bool CUDPSocket::open(const sockaddr_storage& address) } bool CUDPSocket::open(unsigned int af) +{ + return open(0, af, m_address_save, m_port_save); +} + +bool CUDPSocket::open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port) { sockaddr_storage addr; unsigned int addrlen; @@ -159,14 +179,14 @@ bool CUDPSocket::open(unsigned int af) hints.ai_family = af; /* to determine protocol family, call lookup() first. */ - int err = lookup(m_address, m_port, addr, addrlen, hints); + int err = lookup(address, port, addr, addrlen, hints); if (err != 0) { - LogError("The local address is invalid - %s", m_address.c_str()); + LogError("The local address is invalid - %s", address.c_str()); return false; } - m_fd = ::socket(addr.ss_family, SOCK_DGRAM, 0); - if (m_fd < 0) { + int fd = ::socket(addr.ss_family, SOCK_DGRAM, 0); + if (fd < 0) { #if defined(_WIN32) || defined(_WIN64) LogError("Cannot create the UDP socket, err: %lu", ::GetLastError()); #else @@ -175,9 +195,14 @@ bool CUDPSocket::open(unsigned int af) return false; } - if (m_port > 0U) { + m_address[index] = address; + m_port[index] = port; + m_af[index] = addr.ss_family; + m_fd[index] = fd; + + if (port > 0U) { int reuse = 1; - if (::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) { + if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) { #if defined(_WIN32) || defined(_WIN64) LogError("Cannot set the UDP socket option, err: %lu", ::GetLastError()); #else @@ -186,7 +211,7 @@ bool CUDPSocket::open(unsigned int af) return false; } - if (::bind(m_fd, (sockaddr*)&addr, addrlen) == -1) { + if (::bind(fd, (sockaddr*)&addr, addrlen) == -1) { #if defined(_WIN32) || defined(_WIN64) LogError("Cannot bind the UDP address, err: %lu", ::GetLastError()); #else @@ -195,7 +220,7 @@ bool CUDPSocket::open(unsigned int af) return false; } - LogInfo("Opening UDP port on %u", m_port); + LogInfo("Opening UDP port on %u", port); } return true; @@ -207,30 +232,43 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag assert(length > 0U); // Check that the readfrom() won't block - fd_set readFds; - FD_ZERO(&readFds); + int i, n; + struct pollfd pfd[UDP_SOCKET_MAX]; + for (i = n = 0; i < UDP_SOCKET_MAX; i++) { + if (m_fd[i] >= 0) { + pfd[n].fd = m_fd[i]; + pfd[n].events = POLLIN; + n++; + } + } + + // no socket descriptor to receive + if (n == 0) + return 0; + + // Return immediately #if defined(_WIN32) || defined(_WIN64) - FD_SET((unsigned int)m_fd, &readFds); + int ret = WSAPoll(pfd, n, 0); #else - FD_SET(m_fd, &readFds); + int ret = ::poll(pfd, n, 0); #endif - - // Return immediately - timeval tv; - tv.tv_sec = 0L; - tv.tv_usec = 0L; - - int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv); if (ret < 0) { #if defined(_WIN32) || defined(_WIN64) - LogError("Error returned from UDP select, err: %lu", ::GetLastError()); + LogError("Error returned from UDP poll, err: %lu", ::GetLastError()); #else - LogError("Error returned from UDP select, err: %d", errno); + LogError("Error returned from UDP poll, err: %d", errno); #endif return -1; } - if (ret == 0) + int index; + for (i = 0; i < n; i++) { + // round robin + index = (i + m_counter) % n; + if (pfd[index].revents & POLLIN) + break; + } + if (i == n) return 0; #if defined(_WIN32) || defined(_WIN64) @@ -240,9 +278,9 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag #endif #if defined(_WIN32) || defined(_WIN64) - int len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size); + int len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size); #else - ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size); + ssize_t len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size); #endif if (len <= 0) { #if defined(_WIN32) || defined(_WIN64) @@ -253,8 +291,8 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag return -1; } + m_counter++; address_length = size; - return len; } @@ -263,36 +301,52 @@ bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const s assert(buffer != NULL); assert(length > 0U); + bool result = false; + + for (int i = 0; i < UDP_SOCKET_MAX; i++) { + if (m_fd[i] < 0 || m_af[i] != address.ss_family) + continue; + #if defined(_WIN32) || defined(_WIN64) - int ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, address_length); + int ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length); #else - ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, address_length); + ssize_t ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length); #endif - if (ret < 0) { + + if (ret < 0) { #if defined(_WIN32) || defined(_WIN64) - LogError("Error returned from sendto, err: %lu", ::GetLastError()); + LogError("Error returned from sendto, err: %lu", ::GetLastError()); #else - LogError("Error returned from sendto, err: %d", errno); + LogError("Error returned from sendto, err: %d", errno); #endif - return false; - } - + } else { #if defined(_WIN32) || defined(_WIN64) - if (ret != int(length)) - return false; + if (ret == int(length)) + result = true; #else - if (ret != ssize_t(length)) - return false; + if (ret == ssize_t(length)) + result = true; #endif + } + } - return true; + return result; } void CUDPSocket::close() { + for (int i = 0; i < UDP_SOCKET_MAX; i++) + close(m_fd[i]); +} + +void CUDPSocket::close(const unsigned int index) +{ + if (m_fd[index] >= 0) { #if defined(_WIN32) || defined(_WIN64) - ::closesocket(m_fd); + ::closesocket(m_fd[index]); #else - ::close(m_fd); + ::close(m_fd[index]); #endif + m_fd[index] = -1; + } } diff --git a/YSFGateway/UDPSocket.h b/YSFGateway/UDPSocket.h index b169641..b22eefc 100644 --- a/YSFGateway/UDPSocket.h +++ b/YSFGateway/UDPSocket.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,10 @@ #include #endif +#if !defined(UDP_SOCKET_MAX) +#define UDP_SOCKET_MAX 1 +#endif + enum IPMATCHTYPE { IMT_ADDRESS_AND_PORT, IMT_ADDRESS_ONLY @@ -48,24 +53,28 @@ public: bool open(unsigned int af = AF_UNSPEC); bool open(const sockaddr_storage& address); + bool open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port); int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length); bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length); void close(); + void close(const unsigned int index); static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length); static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length, struct addrinfo& hints); - static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type = IMT_ADDRESS_AND_PORT); static bool isNone(const sockaddr_storage& addr); private: - std::string m_address; - unsigned short m_port; - int m_fd; + std::string m_address_save; + unsigned short m_port_save; + std::string m_address[UDP_SOCKET_MAX]; + unsigned short m_port[UDP_SOCKET_MAX]; + unsigned int m_af[UDP_SOCKET_MAX]; + int m_fd[UDP_SOCKET_MAX]; + unsigned int m_counter; }; #endif - diff --git a/YSFParrot/UDPSocket.cpp b/YSFParrot/UDPSocket.cpp index 3e2ac45..382925f 100644 --- a/YSFParrot/UDPSocket.cpp +++ b/YSFParrot/UDPSocket.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2016 by Jonathan Naylor G4KLX + * Copyright (C) 2006-2016,2020 by Jonathan Naylor G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,33 +25,49 @@ #include #endif +#if defined(HAVE_LOG_H) +#include "Log.h" +#else +#define LogError(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__) +#define LogInfo(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__) +#endif CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) : -m_address(address), -m_port(port), -m_fd(-1) +m_address_save(address), +m_port_save(port), +m_counter(0U) { - assert(!address.empty()); - #if defined(_WIN32) || defined(_WIN64) WSAData data; int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data); if (wsaRet != 0) - ::fprintf(stderr, "Error from WSAStartup\n"); + LogError("Error from WSAStartup"); #endif + for (int i = 0; i < UDP_SOCKET_MAX; i++) { + m_address[i] = ""; + m_port[i] = 0U; + m_af[i] = 0U; + m_fd[i] = -1; + } } CUDPSocket::CUDPSocket(unsigned int port) : -m_address(), -m_port(port), -m_fd(-1) +m_address_save(), +m_port_save(port), +m_counter(0U) { #if defined(_WIN32) || defined(_WIN64) WSAData data; int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data); if (wsaRet != 0) - ::fprintf(stderr, "Error from WSAStartup\n"); + LogError("Error from WSAStartup"); #endif + for (int i = 0; i < UDP_SOCKET_MAX; i++) { + m_address[i] = ""; + m_port[i] = 0U; + m_af[i] = 0U; + m_fd[i] = -1; + } } CUDPSocket::~CUDPSocket() @@ -61,7 +77,7 @@ CUDPSocket::~CUDPSocket() #endif } -int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage &addr, unsigned int &address_length) +int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& address_length) { struct addrinfo hints; ::memset(&hints, 0, sizeof(hints)); @@ -69,29 +85,29 @@ int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_ return lookup(hostname, port, addr, address_length, hints); } -int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage &addr, unsigned int &address_length, struct addrinfo &hints) +int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& address_length, struct addrinfo& hints) { - int err; std::string portstr = std::to_string(port); struct addrinfo *res; /* port is always digits, no needs to lookup service */ hints.ai_flags |= AI_NUMERICSERV; - err = getaddrinfo(hostname.empty() ? NULL : hostname.c_str(), portstr.c_str(), &hints, &res); - if (err) { - sockaddr_in *paddr = (sockaddr_in *)&addr; - ::memset(paddr, 0, address_length = sizeof(sockaddr_in)); + int err = getaddrinfo(hostname.empty() ? NULL : hostname.c_str(), portstr.c_str(), &hints, &res); + if (err != 0) { + sockaddr_in* paddr = (sockaddr_in*)&addr; + ::memset(paddr, 0x00U, address_length = sizeof(sockaddr_in)); paddr->sin_family = AF_INET; paddr->sin_port = htons(port); paddr->sin_addr.s_addr = htonl(INADDR_NONE); - ::fprintf(stderr, "Cannot find address for host %s\n", hostname.c_str()); + LogError("Cannot find address for host %s", hostname.c_str()); return err; } ::memcpy(&addr, res->ai_addr, address_length = res->ai_addrlen); freeaddrinfo(res); + return 0; } @@ -147,55 +163,64 @@ bool CUDPSocket::open(const sockaddr_storage& address) return open(address.ss_family); } -bool CUDPSocket::open(const unsigned int af) +bool CUDPSocket::open(unsigned int af) +{ + return open(0, af, m_address_save, m_port_save); +} + +bool CUDPSocket::open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port) { - int err; sockaddr_storage addr; unsigned int addrlen; struct addrinfo hints; ::memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE; hints.ai_family = af; /* to determine protocol family, call lookup() first. */ - err = lookup(m_address, m_port, addr, addrlen, hints); - if (err) { - ::fprintf(stderr, "The local address is invalid - %s\n", m_address.c_str()); + int err = lookup(address, port, addr, addrlen, hints); + if (err != 0) { + LogError("The local address is invalid - %s", address.c_str()); return false; } - m_fd = ::socket(addr.ss_family, SOCK_DGRAM, 0); - if (m_fd < 0) { + int fd = ::socket(addr.ss_family, SOCK_DGRAM, 0); + if (fd < 0) { #if defined(_WIN32) || defined(_WIN64) - ::fprintf(stderr, "Cannot create the UDP socket, err: %lu\n", ::GetLastError()); + LogError("Cannot create the UDP socket, err: %lu", ::GetLastError()); #else - ::fprintf(stderr, "Cannot create the UDP socket, err: %d\n", errno); + LogError("Cannot create the UDP socket, err: %d", errno); #endif return false; } - if (m_port > 0U) { + m_address[index] = address; + m_port[index] = port; + m_af[index] = addr.ss_family; + m_fd[index] = fd; + + if (port > 0U) { int reuse = 1; - if (::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) { + if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) { #if defined(_WIN32) || defined(_WIN64) - ::fprintf(stderr, "Cannot set the UDP socket option, err: %lu\n", ::GetLastError()); + LogError("Cannot set the UDP socket option, err: %lu", ::GetLastError()); #else - ::fprintf(stderr, "Cannot set the UDP socket option, err: %d\n", errno); + LogError("Cannot set the UDP socket option, err: %d", errno); #endif return false; } - if (::bind(m_fd, (sockaddr*)&addr, addrlen) == -1) { + if (::bind(fd, (sockaddr*)&addr, addrlen) == -1) { #if defined(_WIN32) || defined(_WIN64) - ::fprintf(stderr, "Cannot bind the UDP address, err: %lu\n", ::GetLastError()); + LogError("Cannot bind the UDP address, err: %lu", ::GetLastError()); #else - ::fprintf(stderr, "Cannot bind the UDP address, err: %d\n", errno); + LogError("Cannot bind the UDP address, err: %d", errno); #endif return false; } - ::fprintf(stdout, "Opening UDP port on %u\n", m_port); + LogInfo("Opening UDP port on %u", port); } return true; @@ -207,30 +232,43 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag assert(length > 0U); // Check that the readfrom() won't block - fd_set readFds; - FD_ZERO(&readFds); + int i, n; + struct pollfd pfd[UDP_SOCKET_MAX]; + for (i = n = 0; i < UDP_SOCKET_MAX; i++) { + if (m_fd[i] >= 0) { + pfd[n].fd = m_fd[i]; + pfd[n].events = POLLIN; + n++; + } + } + + // no socket descriptor to receive + if (n == 0) + return 0; + + // Return immediately #if defined(_WIN32) || defined(_WIN64) - FD_SET((unsigned int)m_fd, &readFds); + int ret = WSAPoll(pfd, n, 0); #else - FD_SET(m_fd, &readFds); + int ret = ::poll(pfd, n, 0); #endif - - // Return immediately - timeval tv; - tv.tv_sec = 0L; - tv.tv_usec = 0L; - - int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv); if (ret < 0) { #if defined(_WIN32) || defined(_WIN64) - ::fprintf(stderr, "Error returned from UDP select, err: %lu\n", ::GetLastError()); + LogError("Error returned from UDP poll, err: %lu", ::GetLastError()); #else - ::fprintf(stderr, "Error returned from UDP select, err: %d\n", errno); + LogError("Error returned from UDP poll, err: %d", errno); #endif return -1; } - if (ret == 0) + int index; + for (i = 0; i < n; i++) { + // round robin + index = (i + m_counter) % n; + if (pfd[index].revents & POLLIN) + break; + } + if (i == n) return 0; #if defined(_WIN32) || defined(_WIN64) @@ -240,19 +278,20 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag #endif #if defined(_WIN32) || defined(_WIN64) - int len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size); + int len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size); #else - ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size); + ssize_t len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size); #endif if (len <= 0) { #if defined(_WIN32) || defined(_WIN64) - ::fprintf(stderr, "Error returned from recvfrom, err: %lu\n", ::GetLastError()); + LogError("Error returned from recvfrom, err: %lu", ::GetLastError()); #else - ::fprintf(stderr, "Error returned from recvfrom, err: %d\n", errno); + LogError("Error returned from recvfrom, err: %d", errno); #endif return -1; } + m_counter++; address_length = size; return len; } @@ -262,36 +301,52 @@ bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const s assert(buffer != NULL); assert(length > 0U); + bool result = false; + + for (int i = 0; i < UDP_SOCKET_MAX; i++) { + if (m_fd[i] < 0 || m_af[i] != address.ss_family) + continue; + #if defined(_WIN32) || defined(_WIN64) - int ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, address_length); + int ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length); #else - ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, address_length); + ssize_t ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length); #endif - if (ret < 0) { + + if (ret < 0) { #if defined(_WIN32) || defined(_WIN64) - ::fprintf(stderr, "Error returned from sendto, err: %lu\n", ::GetLastError()); + LogError("Error returned from sendto, err: %lu", ::GetLastError()); #else - ::fprintf(stderr, "Error returned from sendto, err: %d\n", errno); + LogError("Error returned from sendto, err: %d", errno); #endif - return false; - } - + } else { #if defined(_WIN32) || defined(_WIN64) - if (ret != int(length)) - return false; + if (ret == int(length)) + result = true; #else - if (ret != ssize_t(length)) - return false; + if (ret == ssize_t(length)) + result = true; #endif + } + } - return true; + return result; } void CUDPSocket::close() { + for (int i = 0; i < UDP_SOCKET_MAX; i++) + close(m_fd[i]); +} + +void CUDPSocket::close(const unsigned int index) +{ + if (m_fd[index] >= 0) { #if defined(_WIN32) || defined(_WIN64) - ::closesocket(m_fd); + ::closesocket(m_fd[index]); #else - ::close(m_fd); + ::close(m_fd[index]); #endif + m_fd[index] = -1; + } } diff --git a/YSFParrot/UDPSocket.h b/YSFParrot/UDPSocket.h index 8dac4d0..b22eefc 100644 --- a/YSFParrot/UDPSocket.h +++ b/YSFParrot/UDPSocket.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2011,2013,2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2009-2011,2013,2015,2016,2020 by Jonathan Naylor G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,10 @@ #include #endif +#if !defined(UDP_SOCKET_MAX) +#define UDP_SOCKET_MAX 1 +#endif + enum IPMATCHTYPE { IMT_ADDRESS_AND_PORT, IMT_ADDRESS_ONLY @@ -46,26 +51,30 @@ public: CUDPSocket(unsigned int port = 0U); ~CUDPSocket(); - bool open(const sockaddr_storage& addr); - bool open(const unsigned int af = AF_UNSPEC); + bool open(unsigned int af = AF_UNSPEC); + bool open(const sockaddr_storage& address); + bool open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port); int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length); bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length); void close(); + void close(const unsigned int index); - static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage &address, unsigned int &address_length); - static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage &address, unsigned int &address_length, struct addrinfo &hints); - + static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length); + static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length, struct addrinfo& hints); static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type = IMT_ADDRESS_AND_PORT); static bool isNone(const sockaddr_storage& addr); - private: - std::string m_address; - unsigned short m_port; - int m_fd; + std::string m_address_save; + unsigned short m_port_save; + std::string m_address[UDP_SOCKET_MAX]; + unsigned short m_port[UDP_SOCKET_MAX]; + unsigned int m_af[UDP_SOCKET_MAX]; + int m_fd[UDP_SOCKET_MAX]; + unsigned int m_counter; }; #endif diff --git a/YSFReflector/Network.cpp b/YSFReflector/Network.cpp index 01c2ea2..1c1b5e4 100644 --- a/YSFReflector/Network.cpp +++ b/YSFReflector/Network.cpp @@ -53,8 +53,7 @@ bool CNetwork::open() bool status = false; unsigned int af[] = {AF_INET, AF_INET6}; - for (int i = 0; i < UDP_SOCKET_MAX && - i < (sizeof(af) / sizeof(unsigned int)); i++) + for (unsigned int i = 0U; i < UDP_SOCKET_MAX && i < (sizeof(af) / sizeof(unsigned int)); i++) status |= m_socket.open(i, af[i], "", m_port); return status; From 470ea37c0e1fc4b570b36b035244da061bd68d77 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 6 Sep 2020 15:12:33 +0100 Subject: [PATCH 5/5] Add HAVE_LOG_H to the YSF Gateway Makefile. --- YSFGateway/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/YSFGateway/Makefile b/YSFGateway/Makefile index 4830908..104837d 100644 --- a/YSFGateway/Makefile +++ b/YSFGateway/Makefile @@ -2,11 +2,11 @@ CC = cc CXX = c++ # Use the following CFLAGS and LIBS if you don't want to use gpsd. -CFLAGS = -g -O3 -Wall -std=c++0x -pthread +CFLAGS = -g -O3 -Wall -DHAVE_LOG_H -std=c++0x -pthread LIBS = -lm -lpthread # Use the following CFLAGS and LIBS if you do want to use gpsd. -#CFLAGS = -g -O3 -Wall -DUSE_GPSD -std=c++0x -pthread +#CFLAGS = -g -O3 -Wall -DHAVE_LOG_H -DUSE_GPSD -std=c++0x -pthread #LIBS = -lm -lpthread -lgps LDFLAGS = -g