diff --git a/CMakeLists.txt b/CMakeLists.txt index b40377dc4..32fea0bb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,9 @@ add_subdirectory(asset_tool) # build type_system library for compiler/decompiler add_subdirectory(common/type_system) +# build cross platform socket library +add_subdirectory(common/cross_sockets) + # build decompiler add_subdirectory(decompiler) diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index 59cacdf7a..3a18ddf0c 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -76,11 +76,10 @@ add_executable(gk ${RUNTIME_SOURCE} main.cpp) # can be used to test other things. add_library(runtime ${RUNTIME_SOURCE}) - IF (WIN32) # set stuff for windows - target_link_libraries(gk mman) + target_link_libraries(gk cross_sockets mman) ELSE() # set stuff for other systems - target_link_libraries(gk pthread) + target_link_libraries(gk cross_sockets) ENDIF() diff --git a/game/system/Deci2Server.cpp b/game/system/Deci2Server.cpp index 600f34462..2618d2404 100644 --- a/game/system/Deci2Server.cpp +++ b/game/system/Deci2Server.cpp @@ -4,15 +4,22 @@ * Works with deci2.cpp (sceDeci2) to implement the networking on target */ -// TODO-WINDOWS -#ifdef __linux__ #include +#include +#include + +// TODO - i think im not including the dependency right..? +#include "common/cross_sockets/xsocket.h" + +#ifdef __linux #include #include #include -#include -#include +#elif _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif #include "common/listener_common.h" #include "common/versions.h" @@ -33,38 +40,39 @@ Deci2Server::~Deci2Server() { delete[] buffer; - if (server_fd >= 0) { - close(server_fd); - } - - if (new_sock >= 0) { - close(new_sock); - } + close_server_socket(); + close_socket(new_sock); } /*! * Start waiting for the Listener to connect */ bool Deci2Server::init() { - server_fd = socket(AF_INET, SOCK_STREAM, 0); - if (server_fd < 0) { - server_fd = -1; + server_socket = socket(AF_INET, SOCK_STREAM, 0); + if (server_socket < 0) { + server_socket = -1; return false; } +#ifdef __linux + 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; +#endif + int opt = 1; - if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + if (set_socket_option(server_socket, SOL_SOCKET, server_socket_opt, opt, sizeof(opt))) { printf("[Deci2Server] Failed to setsockopt 1\n"); - close(server_fd); - server_fd = -1; + close_server_socket(); return false; } int one = 1; - if (setsockopt(server_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) { + if (set_socket_option(server_socket, server_socket_tcp_level, TCP_NODELAY, one, sizeof(one))) { printf("[Deci2Server] Failed to setsockopt 2\n"); - close(server_fd); - server_fd = -1; + close_server_socket(); return false; } @@ -72,10 +80,9 @@ bool Deci2Server::init() { timeout.tv_sec = 0; timeout.tv_usec = 100000; - if (setsockopt(server_fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0) { + if (setsockopt(server_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0) { printf("[Deci2Server] Failed to setsockopt 3\n"); - close(server_fd); - server_fd = -1; + close_server_socket(); return false; } @@ -83,17 +90,15 @@ bool Deci2Server::init() { addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(DECI2_PORT); - if (bind(server_fd, (sockaddr*)&addr, sizeof(addr)) < 0) { + if (bind(server_socket, (sockaddr*)&addr, sizeof(addr)) < 0) { printf("[Deci2Server] Failed to bind\n"); - close(server_fd); - server_fd = -1; + close_server_socket(); return false; } - if (listen(server_fd, 0) < 0) { + if (listen(server_socket, 0) < 0) { printf("[Deci2Server] Failed to listen\n"); - close(server_fd); - server_fd = -1; + close_server_socket(); return false; } @@ -104,6 +109,11 @@ bool Deci2Server::init() { return true; } +void Deci2Server::close_server_socket() { + close_socket(server_socket); + server_socket = -1; +} + /*! * Return true if the listener is connected. */ @@ -129,7 +139,7 @@ void Deci2Server::send_data(void* buf, u16 len) { } else { uint16_t prog = 0; while (prog < len) { - auto wrote = write(new_sock, (char*)(buf) + prog, len - prog); + int wrote = write_to_socket(new_sock, (char*)(buf) + prog, len - prog); prog += wrote; if (!server_connected || want_exit()) { unlock(); @@ -186,7 +196,7 @@ void Deci2Server::run() { while (got < desired_size) { assert(got + desired_size < BUFFER_SIZE); - auto x = read(new_sock, buffer + got, desired_size - got); + auto x = read_from_socket(new_sock, buffer + got, desired_size - got); if (want_exit()) { return; } @@ -237,7 +247,7 @@ void Deci2Server::run() { // receive from network if (hdr->rsvd < hdr->len) { - auto x = read(new_sock, buffer + hdr->rsvd, hdr->len - hdr->rsvd); + auto x = read_from_socket(new_sock, buffer + hdr->rsvd, hdr->len - hdr->rsvd); if (want_exit()) { return; } @@ -256,13 +266,12 @@ void Deci2Server::run() { void Deci2Server::accept_thread_func() { socklen_t l = sizeof(addr); while (!kill_accept_thread) { - new_sock = accept(server_fd, (sockaddr*)&addr, &l); + new_sock = accept(server_socket, (sockaddr*)&addr, &l); if (new_sock >= 0) { u32 versions[2] = {versions::GOAL_VERSION_MAJOR, versions::GOAL_VERSION_MINOR}; - send(new_sock, &versions, 8, 0); // todo, check result? + write_to_socket(new_sock, (char*)&versions, 8); // todo, check result? server_connected = true; return; } } } -#endif \ No newline at end of file diff --git a/game/system/Deci2Server.h b/game/system/Deci2Server.h index 8695ff020..c8ddbaa1d 100644 --- a/game/system/Deci2Server.h +++ b/game/system/Deci2Server.h @@ -4,11 +4,14 @@ * Works with deci2.cpp (sceDeci2) to implement the networking on target */ -#ifdef __linux__ #ifndef JAK1_DECI2SERVER_H #define JAK1_DECI2SERVER_H +#ifdef __linux #include +#elif _WIN32 +#include +#endif #include #include #include @@ -32,11 +35,12 @@ class Deci2Server { void run(); private: + void close_server_socket(); void accept_thread_func(); bool kill_accept_thread = false; char* buffer = nullptr; - int server_fd = -1; - sockaddr_in addr; + int server_socket = -1; + struct sockaddr_in addr = {}; int new_sock = -1; bool server_initialized = false; bool accept_thread_running = false; @@ -52,4 +56,3 @@ class Deci2Server { }; #endif // JAK1_DECI2SERVER_H -#endif diff --git a/goalc/CMakeLists.txt b/goalc/CMakeLists.txt index 21b3fcb92..ee0a59f2f 100644 --- a/goalc/CMakeLists.txt +++ b/goalc/CMakeLists.txt @@ -1,12 +1,6 @@ add_subdirectory(util) add_subdirectory(goos) - -IF (WIN32) - # TODO - implement windows listener - message("Windows Listener Not Implemented!") -ELSE() - add_subdirectory(listener) -ENDIF() +add_subdirectory(listener) add_library(compiler SHARED @@ -26,12 +20,10 @@ add_library(compiler compiler/Compiler.cpp ) -add_executable(goalc main.cpp - ) +add_executable(goalc main.cpp) IF (WIN32) - set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) - target_link_libraries(compiler util goos type_system mman) + target_link_libraries(compiler cross_sockets util goos type_system mman) +ELSE() + target_link_libraries(compiler cross_sockets util goos goalc type_system) ENDIF() - -target_link_libraries(goalc util goos compiler type_system) diff --git a/goalc/listener/Listener.cpp b/goalc/listener/Listener.cpp index 2a53f2661..709d5ab5b 100644 --- a/goalc/listener/Listener.cpp +++ b/goalc/listener/Listener.cpp @@ -3,13 +3,20 @@ * The Listener can connect to a Deci2Server for debugging. */ -// TODO-Windows -#ifdef __linux__ - -#include +#ifdef __linux #include #include #include +#elif _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif + +// TODO - i think im not including the dependency right..? +#include "common/cross_sockets/xsocket.h" + +#include #include #include "Listener.h" #include "common/versions.h" @@ -27,7 +34,7 @@ Listener::~Listener() { delete[] m_buffer; if (socket_fd >= 0) { - close(socket_fd); + close_socket(socket_fd); } } @@ -53,7 +60,7 @@ bool Listener::connect_to_target(const std::string& ip, int port) { } if (socket_fd >= 0) { - close(socket_fd); + close_socket(socket_fd); } // construct socket @@ -70,16 +77,16 @@ bool Listener::connect_to_target(const std::string& ip, int port) { timeout.tv_usec = 100000; if (setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0) { printf("[Listener] setsockopt failed\n"); - close(socket_fd); + close_socket(socket_fd); socket_fd = -1; return false; } // set nodelay, which makes small rapid messages faster, but large messages slower int one = 1; - if (setsockopt(socket_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) { + if (set_socket_option(socket_fd, TCP_SOCKET_LEVEL, TCP_NODELAY, one, sizeof(one))) { printf("[Listener] failed to TCP_NODELAY\n"); - close(socket_fd); + close_socket(socket_fd); socket_fd = -1; return false; } @@ -90,7 +97,7 @@ 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_fd); + close_socket(socket_fd); socket_fd = -1; return false; } @@ -99,7 +106,7 @@ bool Listener::connect_to_target(const std::string& ip, int port) { int rv = connect(socket_fd, (sockaddr*)&server_address, sizeof(server_address)); if (rv < 0) { printf("[Listener] Failed to connect\n"); - close(socket_fd); + close_socket(socket_fd); socket_fd = -1; return false; } @@ -110,7 +117,7 @@ bool Listener::connect_to_target(const std::string& ip, int port) { int prog = 0; bool ok = true; while (prog < 8) { - auto r = read(socket_fd, version_buffer + prog, 8 - prog); + auto r = read_from_socket(socket_fd, (char*)version_buffer + prog, 8 - prog); if (r < 0) { ok = false; break; @@ -124,7 +131,7 @@ bool Listener::connect_to_target(const std::string& ip, int port) { } if (!ok) { printf("[Listener] Failed to get version number\n"); - close(socket_fd); + close_socket(socket_fd); socket_fd = -1; return false; } @@ -138,7 +145,7 @@ 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_fd); + close_socket(socket_fd); socket_fd = -1; return false; } @@ -155,7 +162,7 @@ void Listener::receive_func() { int rcvd_desired = sizeof(ListenerMessageHeader); char buff[sizeof(ListenerMessageHeader)]; while (rcvd < rcvd_desired) { - auto got = read(socket_fd, buff + rcvd, rcvd_desired - rcvd); + auto got = read_from_socket(socket_fd, buff + rcvd, rcvd_desired - rcvd); rcvd += got > 0 ? got : 0; // kick us out if we got a bogus read result @@ -188,7 +195,7 @@ void Listener::receive_func() { while (rcvd < hdr->deci2_header.len) { if (!m_connected) return; - int got = read(socket_fd, ack_recv_buff + ack_recv_prog, hdr->deci2_header.len - rcvd); + int got = read_from_socket(socket_fd, ack_recv_buff + ack_recv_prog, hdr->deci2_header.len - rcvd); got = got > 0 ? got : 0; rcvd += got; ack_recv_prog += got; @@ -210,7 +217,7 @@ void Listener::receive_func() { return; } - int got = read(socket_fd, str_buff + msg_prog, hdr->deci2_header.len - rcvd); + int got = read_from_socket(socket_fd, str_buff + msg_prog, hdr->deci2_header.len - rcvd); got = got > 0 ? got : 0; rcvd += got; msg_prog += got; @@ -242,4 +249,3 @@ void Listener::receive_func() { } } // namespace listener -#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8173c9820..05bcf9570 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -18,9 +18,8 @@ add_executable(goalc-test IF (WIN32) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - # TODO - implement windows listener - message("Windows Listener Not Implemented!") - target_link_libraries(goalc-test mman goos util runtime compiler type_system gtest) + # TODO - split out these declarations for platform specific includes + target_link_libraries(goalc-test cross_sockets listener mman goos util runtime compiler type_system gtest) ELSE() - target_link_libraries(goalc-test goos util listener runtime compiler type_system gtest) + target_link_libraries(goalc-test cross_sockets goos util listener runtime compiler type_system gtest) ENDIF() diff --git a/test/test_listener_deci2.cpp b/test/test_listener_deci2.cpp index d7b65cba2..99874e3d0 100644 --- a/test/test_listener_deci2.cpp +++ b/test/test_listener_deci2.cpp @@ -1,5 +1,3 @@ -#ifdef __linux__ - #include "gtest/gtest.h" #include "goalc/listener/Listener.h" #include "game/system/Deci2Server.h" @@ -126,5 +124,3 @@ TEST(Listener, ListenerMultipleDecis) { l.disconnect(); } } - -#endif \ No newline at end of file