diff --git a/common/cross_sockets/xsocket.cpp b/common/cross_sockets/xsocket.cpp index f4c89df7e8..763cf596f4 100644 --- a/common/cross_sockets/xsocket.cpp +++ b/common/cross_sockets/xsocket.cpp @@ -86,3 +86,12 @@ int read_from_socket(int socket, char* buf, int len) { return recv(socket, buf, len, 0); #endif } + +bool socket_timed_out() { +#ifdef __linux + return errno == EAGAIN; +#elif _WIN32 + auto err = WSAGetLastError(); + return err == WSAETIMEDOUT; +#endif +} \ No newline at end of file diff --git a/common/cross_sockets/xsocket.h b/common/cross_sockets/xsocket.h index eb8e09b38c..d0e4bb1c16 100644 --- a/common/cross_sockets/xsocket.h +++ b/common/cross_sockets/xsocket.h @@ -18,3 +18,4 @@ int set_socket_option(int socket, int level, int optname, const void* optval, in 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); +bool socket_timed_out(); \ No newline at end of file diff --git a/goalc/listener/Listener.cpp b/goalc/listener/Listener.cpp index 454dcd46f3..1fdb4bbe3d 100644 --- a/goalc/listener/Listener.cpp +++ b/goalc/listener/Listener.cpp @@ -123,7 +123,7 @@ bool Listener::connect_to_target(int n_tries, const std::string& ip, int port) { listen_socket = -1; return false; } else { - printf("[Listener] Socket connected established! (took %d tries)\n", i); + printf("[Listener] Socket connected established! (took %d tries). Waiting for version...\n", i); } // get the GOAL version number, to make sure we connected to the right thing @@ -133,11 +133,8 @@ bool Listener::connect_to_target(int n_tries, const std::string& ip, int port) { bool ok = true; while (prog < 8) { auto r = read_from_socket(listen_socket, (char*)version_buffer + prog, 8 - prog); - if (r < 0) { - ok = false; - break; - } - prog += r; + std::this_thread::sleep_for(std::chrono::microseconds(100000)); + prog += r > 0 ? r : 0; read_tries++; if (read_tries > 50) { ok = false; @@ -181,7 +178,7 @@ void Listener::receive_func() { rcvd += got > 0 ? got : 0; // kick us out if we got a bogus read result - if (got == 0 || (got == -1 && errno != EAGAIN)) { + if (got == 0 || (got == -1 && !socket_timed_out())) { m_connected = false; } @@ -238,7 +235,7 @@ void Listener::receive_func() { got = got > 0 ? got : 0; rcvd += got; msg_prog += got; - if (got == 0 || (got == -1 && errno != EAGAIN)) { + if (got == 0 || (got == -1 && !socket_timed_out())) { m_connected = false; } } diff --git a/test/test_listener_deci2.cpp b/test/test_listener_deci2.cpp index 158a7afb7a..ebc5aedeab 100644 --- a/test/test_listener_deci2.cpp +++ b/test/test_listener_deci2.cpp @@ -45,6 +45,24 @@ TEST(Listener, DeciCheckNoListener) { EXPECT_FALSE(s.check_for_listener()); } +TEST(Listener, CheckConnectionStaysAlive) { + Deci2Server s(always_false); + EXPECT_TRUE(s.init()); + EXPECT_FALSE(s.check_for_listener()); + Listener l; + EXPECT_FALSE(s.check_for_listener()); + bool connected = l.connect_to_target(); + EXPECT_TRUE(connected); + // TODO - some sort of backoff and retry would be better + while (connected && !s.check_for_listener()) { + } + + EXPECT_TRUE(s.check_for_listener()); + std::this_thread::sleep_for(std::chrono::seconds(2)); // sorry for making tests slow. + EXPECT_TRUE(s.check_for_listener()); + EXPECT_TRUE(l.is_connected()); +} + TEST(Listener, DeciThenListener) { for (int i = 0; i < 3; i++) { Deci2Server s(always_false);