game/deci2: Add a timeout on waiting for a client to connect to DECI2 (#1367)

game/deci2: Add a timeout to waiting for a client to connect
This commit is contained in:
Tyler Wilding
2022-05-21 15:49:01 -04:00
committed by GitHub
parent 19944ebe10
commit 8d71146b81
3 changed files with 43 additions and 1 deletions
+37
View File
@@ -38,6 +38,20 @@ int open_socket(int af, int type, int protocol) {
int accept_socket(int socket, sockaddr* addr, socklen_t* addrLen) {
return accept(socket, addr, addrLen);
}
int select_and_accept_socket(int socket, sockaddr* addr, socklen_t* addrLen, int microSeconds) {
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = microSeconds;
// Use select so it can timeout, accept on the returned socket if it is correct
fd_set read_sockets;
FD_ZERO(&read_sockets);
FD_SET(socket, &read_sockets);
auto activity = select(socket + 1, &read_sockets, NULL, NULL, &timeout);
if (activity > 0) {
return accept(socket, addr, addrLen);
}
return -1;
}
#endif
#ifdef _WIN32
@@ -52,6 +66,29 @@ int accept_socket(int socket, sockaddr* addr, int* addrLen) {
}
return accept(socket, addr, addrLen);
}
int select_and_accept_socket(int socket, sockaddr* addr, int* addrLen, int microSeconds) {
WSADATA wsaData = {0};
int iResult = 0;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = microSeconds;
// Use select so it can timeout, accept on the returned socket if it is correct
fd_set read_sockets;
FD_ZERO(&read_sockets);
FD_SET(socket, &read_sockets);
auto activity = select(socket + 1, &read_sockets, NULL, NULL, &timeout);
if (activity > 0) {
return accept(socket, addr, addrLen);
}
return -1;
}
#endif
void close_socket(int sock) {
+2
View File
@@ -27,8 +27,10 @@ const int TCP_SOCKET_LEVEL = IPPROTO_TCP;
int open_socket(int af, int type, int protocol);
#ifdef __linux
int accept_socket(int socket, sockaddr* addr, socklen_t* addrLen);
int select_and_accept_socket(int socket, sockaddr* addr, socklen_t* addrLen, int microSeconds);
#elif _WIN32
int accept_socket(int socket, sockaddr* addr, int* addrLen);
int select_and_accept_socket(int socket, sockaddr* addr, int* addrLen, int microSeconds);
#endif
void close_socket(int sock);
int set_socket_option(int socket, int level, int optname, const void* optval, int optlen);
+4 -1
View File
@@ -26,6 +26,8 @@ Deci2Server::~Deci2Server() {
// Cleanup the accept thread
if (accept_thread_running) {
kill_accept_thread = true;
// NOTE - if we don't want to wait for the roundtrip timeout to exit the game gracefully
// we should just terminate the thread forcefully
accept_thread.join();
accept_thread_running = false;
}
@@ -43,7 +45,8 @@ void Deci2Server::post_init() {
void Deci2Server::accept_thread_func() {
socklen_t addr_len = sizeof(addr);
while (!kill_accept_thread) {
accepted_socket = accept_socket(listening_socket, (sockaddr*)&addr, &addr_len);
accepted_socket = select_and_accept_socket(listening_socket, (sockaddr*)&addr, &addr_len,
100000); // 0.1 second timeout
if (accepted_socket >= 0) {
set_socket_timeout(accepted_socket, 100000);
u32 versions[2] = {versions::GOAL_VERSION_MAJOR, versions::GOAL_VERSION_MINOR};