diff --git a/common/cross_sockets/xsocket.cpp b/common/cross_sockets/xsocket.cpp index 010550d2c5..de15d2ec90 100644 --- a/common/cross_sockets/xsocket.cpp +++ b/common/cross_sockets/xsocket.cpp @@ -8,6 +8,24 @@ #include #endif +#include + +int open_socket(int af, int type, int protocol) { +#ifdef __linux + return socket(af, type, protocol); +#elif _WIN32 + 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; + } + return socket(af, type, protocol); +#endif +} + void close_socket(int sock) { if (sock < 0) { return; @@ -16,15 +34,20 @@ void close_socket(int sock) { close(sock); #elif _WIN32 closesocket(sock); + WSACleanup(); #endif } -int set_socket_option(int socket, int level, int optname, int optval, int optlen) { +int set_socket_option(int socket, int level, int optname, const char* optval, int optlen) { #ifdef __linux - return setsockopt(socket, level, optname, &optval, optlen); + return setsockopt(socket, level, optname, optval, optlen); #elif _WIN32 - const char optVal = optval; - return setsockopt(socket, level, optname, &optVal, optlen); + int ret = setsockopt(socket, level, optname, optval, optlen); + if (ret < 0) { + int err = WSAGetLastError(); + printf("Failed to setsockopt - Err: %d\n", err); + } + return ret; #endif } @@ -42,4 +65,4 @@ int read_from_socket(int socket, char* buf, int len) { #elif _WIN32 return recv(socket, buf, len, 0); #endif -} \ No newline at end of file +} diff --git a/common/cross_sockets/xsocket.h b/common/cross_sockets/xsocket.h index fa1e5b4e70..8f7bb359ae 100644 --- a/common/cross_sockets/xsocket.h +++ b/common/cross_sockets/xsocket.h @@ -9,10 +9,11 @@ #ifdef __linux const int TCP_SOCKET_LEVEL = SOL_TCP; #elif _WIN32 -const int TCP_SOCKET_LEVEL = IPPROTO_IP; +const int TCP_SOCKET_LEVEL = IPPROTO_TCP; #endif +int open_socket(int af, int type, int protocol); void close_socket(int sock); -int set_socket_option(int socket, int level, int optname, int optval, int optlen); +int set_socket_option(int socket, int level, int optname, const char* optval, int optlen); 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 2618d2404d..5f2308f575 100644 --- a/game/system/Deci2Server.cpp +++ b/game/system/Deci2Server.cpp @@ -4,7 +4,6 @@ * Works with deci2.cpp (sceDeci2) to implement the networking on target */ - #include #include #include @@ -17,7 +16,8 @@ #include #include #elif _WIN32 -#define WIN32_LEAN_AND_MEAN +#include +#include #include #endif @@ -48,7 +48,7 @@ Deci2Server::~Deci2Server() { * Start waiting for the Listener to connect */ bool Deci2Server::init() { - server_socket = socket(AF_INET, SOCK_STREAM, 0); + server_socket = open_socket(AF_INET, SOCK_STREAM, 0); if (server_socket < 0) { server_socket = -1; return false; @@ -58,33 +58,41 @@ bool Deci2Server::init() { int server_socket_opt = SO_REUSEADDR | SO_REUSEPORT; int server_socket_tcp_level = SOL_TCP; #elif _WIN32 - int server_socket_opt = SO_REUSEADDR | SO_BROADCAST; - int server_socket_tcp_level = IPPROTO_IP; + int server_socket_opt = SO_EXCLUSIVEADDRUSE; + int server_socket_tcp_level = IPPROTO_TCP; #endif - int opt = 1; - if (set_socket_option(server_socket, SOL_SOCKET, server_socket_opt, opt, sizeof(opt))) { - printf("[Deci2Server] Failed to setsockopt 1\n"); + char opt = 1; + if (set_socket_option(server_socket, SOL_SOCKET, server_socket_opt, &opt, sizeof(opt)) < + 0) { close_server_socket(); return false; } - int one = 1; - if (set_socket_option(server_socket, server_socket_tcp_level, TCP_NODELAY, one, sizeof(one))) { - printf("[Deci2Server] Failed to setsockopt 2\n"); + if (set_socket_option(server_socket, server_socket_tcp_level, TCP_NODELAY, &opt, + sizeof(opt)) < 0) { close_server_socket(); return false; } - timeval timeout = {}; +// TODO - put in library +#ifdef __linux + timeval timeout = {}; timeout.tv_sec = 0; timeout.tv_usec = 100000; - - if (setsockopt(server_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0) { - printf("[Deci2Server] Failed to setsockopt 3\n"); + if (set_socket_option(server_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < + 0) { close_server_socket(); return false; } +#elif _WIN32 + unsigned long timeout = 100; // ms + if (set_socket_option(server_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < + 0) { + close_server_socket(); + return false; + } +#endif addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; @@ -266,6 +274,7 @@ void Deci2Server::run() { void Deci2Server::accept_thread_func() { socklen_t l = sizeof(addr); while (!kill_accept_thread) { + // TODO - might want to do a WSAStartUp call here as well, else it won't be balanced on the close new_sock = accept(server_socket, (sockaddr*)&addr, &l); if (new_sock >= 0) { u32 versions[2] = {versions::GOAL_VERSION_MAJOR, versions::GOAL_VERSION_MINOR}; diff --git a/goalc/listener/Listener.cpp b/goalc/listener/Listener.cpp index 709d5ab5b1..774f0415a0 100644 --- a/goalc/listener/Listener.cpp +++ b/goalc/listener/Listener.cpp @@ -64,27 +64,38 @@ bool Listener::connect_to_target(const std::string& ip, int port) { } // construct socket - socket_fd = socket(AF_INET, SOCK_STREAM, 0); + socket_fd = open_socket(AF_INET, SOCK_STREAM, 0); if (socket_fd < 0) { printf("[Listener] Failed to create socket.\n"); socket_fd = -1; return false; } - // set timeout for receive - timeval timeout = {}; + // TODO - put in library +#ifdef __linux + timeval timeout = {}; timeout.tv_sec = 0; timeout.tv_usec = 100000; - if (setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0) { - printf("[Listener] setsockopt failed\n"); + if (set_socket_option(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < + 0) { close_socket(socket_fd); - socket_fd = -1; + socket_fd = -1; return false; } +#elif _WIN32 + unsigned long timeout = 100; // ms + if (set_socket_option(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < + 0) { + printf("[Listener] setsockopt failed\n"); + close_socket(socket_fd); + socket_fd = -1; + return false; + } +#endif // set nodelay, which makes small rapid messages faster, but large messages slower - int one = 1; - if (set_socket_option(socket_fd, TCP_SOCKET_LEVEL, TCP_NODELAY, one, sizeof(one))) { + 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;