mirror of
https://github.com/open-goal/jak-project
synced 2026-08-20 14:24:45 -04:00
common: make a common interface for creating a server socket
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
add_library(common
|
||||
audio/audio_formats.cpp
|
||||
cross_os_debug/xdbg.cpp
|
||||
cross_sockets/xsocket.cpp
|
||||
cross_sockets/XSocket.cpp
|
||||
cross_sockets/XSocketServer.cpp
|
||||
custom_data/TFrag3Data.cpp
|
||||
dma/dma.cpp
|
||||
dma/dma_copy.cpp
|
||||
@@ -44,8 +45,7 @@ add_library(common
|
||||
util/FrameLimiter.cpp
|
||||
util/image_loading.cpp
|
||||
goos/Printer.cpp
|
||||
goos/PrettyPrinter2.cpp
|
||||
)
|
||||
goos/PrettyPrinter2.cpp)
|
||||
|
||||
target_link_libraries(common fmt lzokay replxx libzstd_static)
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <fcntl.h>
|
||||
#elif _WIN32
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <sys/types.h>
|
||||
#elif _WIN32
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
#include "XSocketServer.h"
|
||||
|
||||
#include "third-party/fmt/core.h"
|
||||
|
||||
#include "common/cross_sockets/XSocket.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <WinSock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
#endif
|
||||
|
||||
XSocketServer::XSocketServer(std::function<bool()> shutdown_callback,
|
||||
int _tcp_port,
|
||||
int _buffer_size)
|
||||
: want_exit_callback(std::move(shutdown_callback)) {
|
||||
tcp_port = _tcp_port;
|
||||
buffer_size = _buffer_size;
|
||||
buffer = new char[_buffer_size];
|
||||
}
|
||||
|
||||
XSocketServer::~XSocketServer() {
|
||||
shutdown_server();
|
||||
}
|
||||
|
||||
void XSocketServer::shutdown_server() {
|
||||
// Close the listening and accepted socket socket
|
||||
close_server_socket();
|
||||
close_socket(accepted_socket);
|
||||
|
||||
// If the accept thread is still running (nothing ever connected)
|
||||
// kill it and clean it up
|
||||
if (accept_thread_running) {
|
||||
kill_accept_thread = true;
|
||||
accept_thread.join();
|
||||
accept_thread_running = false;
|
||||
}
|
||||
|
||||
// Cleanup our buffer
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
bool XSocketServer::init_server() {
|
||||
listening_socket = open_socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (listening_socket < 0) {
|
||||
listening_socket = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef __linux
|
||||
int server_socket_opt = SO_REUSEADDR | SO_REUSEPORT;
|
||||
#elif _WIN32
|
||||
int server_socket_opt = SO_EXCLUSIVEADDRUSE;
|
||||
#endif
|
||||
|
||||
int opt = 1;
|
||||
if (set_socket_option(listening_socket, SOL_SOCKET, server_socket_opt, &opt, sizeof(opt)) < 0) {
|
||||
close_server_socket();
|
||||
return false;
|
||||
};
|
||||
|
||||
if (set_socket_option(listening_socket, TCP_SOCKET_LEVEL, TCP_NODELAY, &opt, sizeof(opt)) < 0) {
|
||||
close_server_socket();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (set_socket_timeout(listening_socket, 100000) < 0) {
|
||||
close_server_socket();
|
||||
return false;
|
||||
}
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.sin_port = htons(tcp_port);
|
||||
|
||||
if (bind(listening_socket, (sockaddr*)&addr, sizeof(addr)) < 0) {
|
||||
fmt::print("[XSocketServer:{}] failed to bind\n", tcp_port);
|
||||
close_server_socket();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (listen(listening_socket, 0) < 0) {
|
||||
fmt::print("[XSocketServer:{}] failed to listen\n", tcp_port);
|
||||
close_server_socket();
|
||||
return false;
|
||||
}
|
||||
|
||||
server_initialized = true;
|
||||
accept_thread_running = true;
|
||||
kill_accept_thread = false;
|
||||
accept_thread = std::thread(&XSocketServer::accept_thread_func, this);
|
||||
fmt::print("[XSocketServer:{}] awaiting connections\n", tcp_port);
|
||||
return true;
|
||||
}
|
||||
|
||||
void XSocketServer::close_server_socket() {
|
||||
close_socket(listening_socket);
|
||||
listening_socket = -1;
|
||||
}
|
||||
|
||||
void XSocketServer::accept_thread_func() {
|
||||
socklen_t l = sizeof(addr);
|
||||
while (!kill_accept_thread) {
|
||||
accepted_socket = accept_socket(listening_socket, (sockaddr*)&addr, &l);
|
||||
if (accepted_socket >= 0) {
|
||||
set_socket_timeout(accepted_socket, 100000);
|
||||
write_on_accept();
|
||||
client_connected = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool XSocketServer::wait_for_connection() {
|
||||
if (client_connected) {
|
||||
if (accept_thread_running) {
|
||||
accept_thread.join();
|
||||
accept_thread_running = false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void XSocketServer::lock() {
|
||||
server_mutex.lock();
|
||||
}
|
||||
|
||||
void XSocketServer::unlock() {
|
||||
server_mutex.unlock();
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/cross_sockets/XSocket.h"
|
||||
|
||||
#include <thread>
|
||||
#include "common/common_types.h"
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
|
||||
/// @brief A cross platform generic socket server implementation
|
||||
class XSocketServer {
|
||||
public:
|
||||
static constexpr int DEF_BUFFER_SIZE = 32 * 1024 * 1024;
|
||||
XSocketServer(std::function<bool()> shutdown_callback,
|
||||
int _tcp_port,
|
||||
int _buffer_size = DEF_BUFFER_SIZE);
|
||||
~XSocketServer();
|
||||
bool init_server();
|
||||
void shutdown_server();
|
||||
void close_server_socket();
|
||||
|
||||
bool wait_for_connection();
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
// Abstract methods -- use-case dependent
|
||||
virtual void write_on_accept() = 0;
|
||||
virtual void read_data() = 0;
|
||||
virtual void send_data(void* buf, u16 len) = 0;
|
||||
|
||||
protected:
|
||||
int buffer_size;
|
||||
int tcp_port;
|
||||
struct sockaddr_in addr = {};
|
||||
int listening_socket = -1;
|
||||
int accepted_socket = -1;
|
||||
char* buffer = nullptr;
|
||||
|
||||
bool kill_accept_thread = false;
|
||||
bool server_initialized = false;
|
||||
bool accept_thread_running = false;
|
||||
bool client_connected = false;
|
||||
|
||||
std::function<bool()> want_exit_callback;
|
||||
std::thread accept_thread;
|
||||
|
||||
std::mutex server_mutex;
|
||||
|
||||
void accept_thread_func();
|
||||
};
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "third-party/fmt/core.h"
|
||||
|
||||
int open_socket(int af, int type, int protocol) {
|
||||
#ifdef __linux
|
||||
return socket(af, type, protocol);
|
||||
@@ -32,6 +34,20 @@ int open_socket(int af, int type, int protocol) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int accept_socket(int socket, sockaddr* addr, int* addrLen) {
|
||||
#ifdef _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;
|
||||
}
|
||||
#endif
|
||||
return accept(socket, addr, addrLen);
|
||||
}
|
||||
|
||||
void close_socket(int sock) {
|
||||
if (sock < 0) {
|
||||
return;
|
||||
@@ -77,19 +93,26 @@ int set_socket_timeout(int socket, long microSeconds) {
|
||||
}
|
||||
|
||||
int write_to_socket(int socket, const char* buf, int len) {
|
||||
int bytes_wrote;
|
||||
#ifdef __linux
|
||||
return write(socket, buf, len);
|
||||
bytes_wrote = write(socket, buf, len);
|
||||
#elif _WIN32
|
||||
return send(socket, buf, len, 0);
|
||||
bytes_wrote = send(socket, buf, len, 0);
|
||||
#endif
|
||||
if (bytes_wrote < 0) {
|
||||
fmt::print(stderr, "[XSocket:{}] Error writing to socket\n", socket);
|
||||
}
|
||||
return bytes_wrote;
|
||||
}
|
||||
|
||||
int read_from_socket(int socket, char* buf, int len) {
|
||||
int bytes_read;
|
||||
#ifdef __linux
|
||||
return read(socket, buf, len);
|
||||
bytes_read = read(socket, buf, len);
|
||||
#elif _WIN32
|
||||
return recv(socket, buf, len, 0);
|
||||
bytes_read = recv(socket, buf, len, 0);
|
||||
#endif
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
bool socket_timed_out() {
|
||||
@@ -99,4 +122,4 @@ bool socket_timed_out() {
|
||||
auto err = WSAGetLastError();
|
||||
return err == WSAETIMEDOUT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#elif _WIN32
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <WinSock2.h>
|
||||
#endif
|
||||
|
||||
@@ -20,9 +24,10 @@ const int TCP_SOCKET_LEVEL = IPPROTO_TCP;
|
||||
#endif
|
||||
|
||||
int open_socket(int af, int type, int protocol);
|
||||
int accept_socket(int socket, sockaddr* addr, int* addrLen);
|
||||
void close_socket(int sock);
|
||||
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);
|
||||
bool socket_timed_out();
|
||||
bool socket_timed_out();
|
||||
|
||||
@@ -14,6 +14,7 @@ u32 get_current_tid() {
|
||||
}
|
||||
#else
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include "Processthreadsapi.h"
|
||||
u32 get_current_tid() {
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "third-party/fmt/color.h"
|
||||
#include "log.h"
|
||||
#ifdef _WIN32 // see lg::initialize
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
#include "common/util/Assert.h"
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "third-party/lzokay/lzokay.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -41,6 +41,7 @@ void FrameLimiter::run(double target_fps,
|
||||
|
||||
#else
|
||||
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
|
||||
FrameLimiter::FrameLimiter() {
|
||||
@@ -74,4 +75,4 @@ void FrameLimiter::run(double target_fps,
|
||||
m_timer.start();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "Timer.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#define MS_PER_SEC 1000ULL // MS = milliseconds
|
||||
#define US_PER_MS 1000ULL // US = microseconds
|
||||
|
||||
Reference in New Issue
Block a user