From fff501d78601d2410e649b473f1991bfbf7ebaf7 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Tue, 8 Sep 2020 19:15:14 -0400 Subject: [PATCH] Corrections to fix linux, and further cleanup --- common/cross_sockets/xsocket.cpp | 31 +++++++++++------ common/cross_sockets/xsocket.h | 4 +-- game/system/Deci2Server.cpp | 10 +++--- goalc/listener/Listener.cpp | 57 ++++++++++++++++---------------- goalc/listener/Listener.h | 2 +- test/test_listener_deci2.cpp | 10 +++--- 6 files changed, 62 insertions(+), 52 deletions(-) diff --git a/common/cross_sockets/xsocket.cpp b/common/cross_sockets/xsocket.cpp index 96a575e8f0..a7f2827070 100644 --- a/common/cross_sockets/xsocket.cpp +++ b/common/cross_sockets/xsocket.cpp @@ -7,8 +7,9 @@ #include #include #endif - +#include #include +#include int open_socket(int af, int type, int protocol) { #ifdef __linux @@ -38,28 +39,36 @@ void close_socket(int sock) { #endif } -int set_socket_option(int socket, int level, int optname, const char* optval, int optlen) { -#ifdef __linux - return setsockopt(socket, level, optname, optval, optlen); -#elif _WIN32 - int ret = setsockopt(socket, level, optname, optval, optlen); +int set_socket_option(int socket, int level, int optname, const void* optval, int optlen) { + int ret = setsockopt(socket, level, optname, (char*)&optval, optlen); + if (ret < 0) { + printf("Failed to setsockopt(%d, %d, %d, _, _) - Error: %s\n", socket, level, optname, + strerror(errno)); + } +#ifdef _WIN32 if (ret < 0) { int err = WSAGetLastError(); - printf("Failed to setsockopt - Err: %d\n", err); + printf("WSAGetLastError: %d\n", err); } - return ret; #endif + return ret; } -int set_socket_timeout(int socket, int microSeconds) { +int set_socket_timeout(int socket, long microSeconds) { #ifdef __linux - timeval timeout = {}; + struct timeval timeout = {}; timeout.tv_sec = 0; timeout.tv_usec = microSeconds; + int ret = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (struct timeval*)&timeout, sizeof(timeout)); + if (ret < 0) { + printf("Failed to setsockopt(%d, %d, %d, _, _) - Error: %s\n", socket, SOL_SOCKET, SO_RCVTIMEO, + strerror(errno)); + } + return ret; #elif _WIN32 unsigned long timeout = microSeconds / 1000; // milliseconds + return set_socket_option(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); #endif - return set_socket_option(socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)); } int write_to_socket(int socket, const char* buf, int len) { diff --git a/common/cross_sockets/xsocket.h b/common/cross_sockets/xsocket.h index 06f1711ae6..eb8e09b38c 100644 --- a/common/cross_sockets/xsocket.h +++ b/common/cross_sockets/xsocket.h @@ -14,7 +14,7 @@ const int TCP_SOCKET_LEVEL = IPPROTO_TCP; int open_socket(int af, int type, int protocol); void close_socket(int sock); -int set_socket_option(int socket, int level, int optname, const char* optval, int optlen); -int set_socket_timeout(int socket, int microSeconds); +int set_socket_option(int socket, int level, int optname, const void* optval, int optlen); +int set_socket_timeout(int socket, long microSeconds); int write_to_socket(int socket, const char* buf, int len); int read_from_socket(int socket, char* buf, int len); diff --git a/game/system/Deci2Server.cpp b/game/system/Deci2Server.cpp index cbcd924d37..4d7f466aab 100644 --- a/game/system/Deci2Server.cpp +++ b/game/system/Deci2Server.cpp @@ -56,28 +56,28 @@ bool Deci2Server::init() { #ifdef __linux int server_socket_opt = SO_REUSEADDR | SO_REUSEPORT; - int server_socket_tcp_level = SOL_TCP; #elif _WIN32 int server_socket_opt = SO_EXCLUSIVEADDRUSE; - int server_socket_tcp_level = IPPROTO_TCP; #endif - char opt = 1; + int opt = 1; if (set_socket_option(server_socket, SOL_SOCKET, server_socket_opt, &opt, sizeof(opt)) < 0) { close_server_socket(); return false; } + printf("[Deci2Server] Created Socket Options\n"); - if (set_socket_option(server_socket, server_socket_tcp_level, TCP_NODELAY, &opt, sizeof(opt)) < - 0) { + if (set_socket_option(server_socket, TCP_SOCKET_LEVEL, TCP_NODELAY, &opt, sizeof(opt)) < 0) { close_server_socket(); return false; } + printf("[Deci2Server] Created TCP Socket Options\n"); if (set_socket_timeout(server_socket, 100000) < 0) { close_server_socket(); return false; } + printf("[Deci2Server] Created Socket Timeout\n"); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; diff --git a/goalc/listener/Listener.cpp b/goalc/listener/Listener.cpp index bdbcf47820..c47a0610d3 100644 --- a/goalc/listener/Listener.cpp +++ b/goalc/listener/Listener.cpp @@ -33,8 +33,8 @@ Listener::~Listener() { disconnect(); delete[] m_buffer; - if (socket_fd >= 0) { - close_socket(socket_fd); + if (listen_socket >= 0) { + close_socket(listen_socket); } } @@ -59,31 +59,29 @@ bool Listener::connect_to_target(const std::string& ip, int port) { throw std::runtime_error("attempted a Listener::connect_to_target when already connected!"); } - if (socket_fd >= 0) { - close_socket(socket_fd); + if (listen_socket >= 0) { + close_socket(listen_socket); } // construct socket - socket_fd = open_socket(AF_INET, SOCK_STREAM, 0); - if (socket_fd < 0) { + listen_socket = open_socket(AF_INET, SOCK_STREAM, 0); + if (listen_socket < 0) { printf("[Listener] Failed to create socket.\n"); - socket_fd = -1; + listen_socket = -1; return false; } - if (set_socket_timeout(socket_fd, 100000) < 0) { - printf("[Listener] setsockopt failed\n"); - close_socket(socket_fd); - socket_fd = -1; + if (set_socket_timeout(listen_socket, 100000) < 0) { + close_socket(listen_socket); + listen_socket = -1; return false; } // set nodelay, which makes small rapid messages faster, but large messages slower - char one = 1; - if (set_socket_option(socket_fd, TCP_SOCKET_LEVEL, TCP_NODELAY, &one, sizeof(one))) { - printf("[Listener] failed to TCP_NODELAY\n"); - close_socket(socket_fd); - socket_fd = -1; + int one = 1; + if (set_socket_option(listen_socket, TCP_SOCKET_LEVEL, TCP_NODELAY, &one, sizeof(one))) { + close_socket(listen_socket); + listen_socket = -1; return false; } @@ -93,17 +91,17 @@ bool Listener::connect_to_target(const std::string& ip, int port) { server_address.sin_port = htons(port); if (inet_pton(AF_INET, ip.c_str(), &server_address.sin_addr) <= 0) { printf("[Listener] Invalid IP address.\n"); - close_socket(socket_fd); - socket_fd = -1; + close_socket(listen_socket); + listen_socket = -1; return false; } // connect! - int rv = connect(socket_fd, (sockaddr*)&server_address, sizeof(server_address)); + int rv = connect(listen_socket, (sockaddr*)&server_address, sizeof(server_address)); if (rv < 0) { printf("[Listener] Failed to connect\n"); - close_socket(socket_fd); - socket_fd = -1; + close_socket(listen_socket); + listen_socket = -1; return false; } @@ -113,7 +111,7 @@ bool Listener::connect_to_target(const std::string& ip, int port) { int prog = 0; bool ok = true; while (prog < 8) { - auto r = read_from_socket(socket_fd, (char*)version_buffer + prog, 8 - prog); + auto r = read_from_socket(listen_socket, (char*)version_buffer + prog, 8 - prog); if (r < 0) { ok = false; break; @@ -127,8 +125,8 @@ bool Listener::connect_to_target(const std::string& ip, int port) { } if (!ok) { printf("[Listener] Failed to get version number\n"); - close_socket(socket_fd); - socket_fd = -1; + close_socket(listen_socket); + listen_socket = -1; return false; } @@ -141,8 +139,8 @@ bool Listener::connect_to_target(const std::string& ip, int port) { return true; } else { printf(", expected %d.%d. Cannot connect.\n", GOAL_VERSION_MAJOR, GOAL_VERSION_MINOR); - close_socket(socket_fd); - socket_fd = -1; + close_socket(listen_socket); + listen_socket = -1; return false; } } @@ -158,7 +156,7 @@ void Listener::receive_func() { int rcvd_desired = sizeof(ListenerMessageHeader); char buff[sizeof(ListenerMessageHeader)]; while (rcvd < rcvd_desired) { - auto got = read_from_socket(socket_fd, buff + rcvd, rcvd_desired - rcvd); + auto got = read_from_socket(listen_socket, buff + rcvd, rcvd_desired - rcvd); rcvd += got > 0 ? got : 0; // kick us out if we got a bogus read result @@ -191,7 +189,7 @@ void Listener::receive_func() { while (rcvd < hdr->deci2_header.len) { if (!m_connected) return; - int got = read_from_socket(socket_fd, ack_recv_buff + ack_recv_prog, + int got = read_from_socket(listen_socket, ack_recv_buff + ack_recv_prog, hdr->deci2_header.len - rcvd); got = got > 0 ? got : 0; rcvd += got; @@ -214,7 +212,8 @@ void Listener::receive_func() { return; } - int got = read_from_socket(socket_fd, str_buff + msg_prog, hdr->deci2_header.len - rcvd); + int got = + read_from_socket(listen_socket, str_buff + msg_prog, hdr->deci2_header.len - rcvd); got = got > 0 ? got : 0; rcvd += got; msg_prog += got; diff --git a/goalc/listener/Listener.h b/goalc/listener/Listener.h index 5ae49e2f5f..8d8fd25982 100644 --- a/goalc/listener/Listener.h +++ b/goalc/listener/Listener.h @@ -29,7 +29,7 @@ class Listener { char* m_buffer = nullptr; //! buffer for incoming messages bool m_connected = false; //! do we think we are connected? bool receive_thread_running = false; //! is the receive thread unjoined? - int socket_fd = -1; //! socket + int listen_socket = -1; //! socket bool got_ack = false; bool waiting_for_ack = false; diff --git a/test/test_listener_deci2.cpp b/test/test_listener_deci2.cpp index a2ffd96e8c..182d3dbd49 100644 --- a/test/test_listener_deci2.cpp +++ b/test/test_listener_deci2.cpp @@ -55,9 +55,10 @@ TEST(Listener, DeciThenListener) { Listener l; EXPECT_FALSE(s.check_for_listener()); EXPECT_FALSE(s.check_for_listener()); - EXPECT_TRUE(l.connect_to_target()); + bool connected = l.connect_to_target(); + EXPECT_TRUE(connected); // TODO - some sort of backoff and retry would be better - while (!s.check_for_listener()) { + while (connected && !s.check_for_listener()) { } EXPECT_TRUE(s.check_for_listener()); @@ -85,9 +86,10 @@ TEST(Listener, ListenerThenDeci) { Deci2Server s(always_false); EXPECT_TRUE(s.init()); EXPECT_FALSE(s.check_for_listener()); - EXPECT_TRUE(l.connect_to_target()); + bool connected = l.connect_to_target(); + EXPECT_TRUE(connected); // TODO - some sort of backoff and retry would be better - while (!s.check_for_listener()) { + while (connected && !s.check_for_listener()) { } } }