From 9f5d2a46bdb21a1ed5ee5a8e692f199b6d1a9742 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 11 Mar 2024 16:35:57 +0600 Subject: [PATCH] Platform-specific netwok sockets --- src/include/86box/plat_netsocket.h | 24 +++++ src/qt/CMakeLists.txt | 2 +- src/win/win_netsocket.c | 148 +++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 src/include/86box/plat_netsocket.h create mode 100644 src/win/win_netsocket.c diff --git a/src/include/86box/plat_netsocket.h b/src/include/86box/plat_netsocket.h new file mode 100644 index 000000000..269f399ff --- /dev/null +++ b/src/include/86box/plat_netsocket.h @@ -0,0 +1,24 @@ +#ifndef _WIN32 +#define SOCKET int +#else +#include +#include +#endif + +enum net_socket_types +{ + /* Only TCP is supported for now. */ + NET_SOCKET_TCP +}; + +SOCKET plat_netsocket_create(int type); +SOCKET plat_netsocket_create_server(int type, unsigned short port); +void plat_netsocket_close(SOCKET socket); + +SOCKET plat_netsocket_accept(SOCKET socket); +int plat_netsocket_connected(SOCKET socket); +int plat_netsocket_connect(SOCKET socket, const char* hostname, unsigned short port); + +/* Returns 0 in case of inability to send. -1 in case of errors. */ +int plat_netsocket_send(SOCKET socket, const unsigned char* data, unsigned int size, int *wouldblock); +int plat_netsocket_receive(SOCKET socket, unsigned char* data, unsigned int size, int *wouldblock); \ No newline at end of file diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 4f073cf4a..48b377044 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -221,7 +221,7 @@ if(WIN32 AND NOT MINGW) endif() if(WIN32) - target_sources(plat PRIVATE ../win/win_serial_passthrough.c) + target_sources(plat PRIVATE ../win/win_serial_passthrough.c ../win/win_netsocket.c) else() target_sources(plat PRIVATE ../unix/unix_serial_passthrough.c) endif() diff --git a/src/win/win_netsocket.c b/src/win/win_netsocket.c new file mode 100644 index 000000000..45ca1f760 --- /dev/null +++ b/src/win/win_netsocket.c @@ -0,0 +1,148 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include + +#include <86box/86box.h> +#include <86box/log.h> +#include <86box/timer.h> +#include <86box/plat.h> +#include <86box/device.h> +#include <86box/plat_netsocket.h> +#include <86box/ui.h> + +#include +#include +#include + +SOCKET plat_netsocket_create(int type) +{ + SOCKET socket = -1; + u_long yes = 1; + + if (type != NET_SOCKET_TCP) + return -1; + + socket = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); + if (socket == INVALID_SOCKET) + return -1; + + ioctlsocket(socket, FIONBIO, &yes); + + return socket; +} + +SOCKET plat_netsocket_create_server(int type, unsigned short port) +{ + struct sockaddr_in sock_addr; + SOCKET socket = plat_netsocket_create(type); + if (socket == INVALID_SOCKET) + return (SOCKET)-1; + + memset(&sock_addr, 0, sizeof(struct sockaddr_in)); + + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = INADDR_ANY; + sock_addr.sin_port = port; + + if (bind(socket, (struct sockaddr *)&sock_addr, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + plat_netsocket_close(socket); + return (SOCKET)-1; + } + + if (listen(socket, 5) == SOCKET_ERROR) { + plat_netsocket_close(socket); + return (SOCKET)-1; + } + + return socket; +} + +void plat_netsocket_close(SOCKET socket) +{ + closesocket((SOCKET)socket); +} + +SOCKET plat_netsocket_accept(SOCKET socket) +{ + SOCKET clientsocket = accept(socket, NULL, NULL); + + if (clientsocket == INVALID_SOCKET) + return -1; + + return clientsocket; +} + +int plat_netsocket_connected(SOCKET socket) +{ + struct sockaddr addr; + socklen_t len = sizeof(struct sockaddr); + if (getpeername(socket, &addr, &len) == SOCKET_ERROR) + return 0; + + return 1; +} + +int plat_netsocket_connect(SOCKET socket, const char* hostname, unsigned short port) +{ + struct sockaddr_in sock_addr; + int res = -1; + + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = inet_addr(hostname); + sock_addr.sin_port = htons(port); + + if (sock_addr.sin_addr.s_addr == -1 || sock_addr.sin_addr.s_addr == 0) { + struct hostent *hp; + + hp = gethostbyname(hostname); + + if (hp) + memcpy(&sock_addr.sin_addr.s_addr, hp->h_addr_list[0], hp->h_length); + else + return -1; + } + + res = connect(socket, (struct sockaddr *)&sock_addr, sizeof(struct sockaddr_in)); + + if (res == SOCKET_ERROR) { + int error = WSAGetLastError(); + + if (error == WSAEISCONN) + return 0; + } + return res; +} + +int plat_netsocket_send(SOCKET socket, const unsigned char* data, unsigned int size, int *wouldblock) +{ + int res = send(socket, (const char*)data, size, 0); + + if (res == SOCKET_ERROR) { + int error = WSAGetLastError(); + + if (wouldblock) + *wouldblock = !!(error == WSAEWOULDBLOCK); + + return -1; + } + return res; +} + +int plat_netsocket_receive(SOCKET socket, unsigned char* data, unsigned int size, int *wouldblock) +{ + int res = recv(socket, (char*)data, size, 0); + + if (res == SOCKET_ERROR) { + int error = WSAGetLastError(); + + if (wouldblock) + *wouldblock = !!(error == WSAEWOULDBLOCK); + + return -1; + } + return res; +}