From bd923aeb4c4d566ea17d2ad2efdd255764ec9870 Mon Sep 17 00:00:00 2001 From: "J.G.Adams" <82924084+JG-Adams@users.noreply.github.com> Date: Tue, 25 Feb 2025 16:46:53 -0500 Subject: [PATCH 1/4] Supporting dependency injection via direct use of external socket. I added two things. a function is_udp_socket(socket) to ensure it's UDP. and a bool ownsSocket for host to ensure it behave with internal mechanism for socket or to use external without creating or closing socket or changing the configuration of it. (Leaving it all to the implementer of their own network.) You use your own socket by putting it in the new argument of enet_host_create() ENetSocket* externalUDPSocket. You set it to NULL to use the internal socket as normally done. This should theoretically work. I am unable to test it for myself because I don't need to make my own network so I'm not sure how to do it either. Things to test: Use of external socket should work. is_udp_socket should be valid. External socket should only be managed by the programmer. --- include/enet.h | 68 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/include/enet.h b/include/enet.h index 34a36da..af38175 100644 --- a/include/enet.h +++ b/include/enet.h @@ -824,6 +824,7 @@ extern "C" { size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */ size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */ size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */ + bool ownsSocket; /**< Whether it use internally managed socket or custom network implementation */ } ENetHost; /** @@ -1011,7 +1012,7 @@ extern "C" { ENET_API ENetPacket * enet_packet_create_offset(const void *, size_t, size_t, enet_uint32); ENET_API enet_uint32 enet_crc32(const ENetBuffer *, size_t); - ENET_API ENetHost * enet_host_create(const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32); + ENET_API ENetHost * enet_host_create(const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32, ENetSocket* externalUDPSocket); ENET_API void enet_host_destroy(ENetHost *); ENET_API ENetPeer * enet_host_connect(ENetHost *, const ENetAddress *, size_t, enet_uint32); ENET_API int enet_host_check_events(ENetHost *, ENetEvent *); @@ -4515,6 +4516,23 @@ extern "C" { // ! // =======================================================================// + int is_udp_socket(const ENetSocket* socket) { + #ifdef _WIN32 + WSAPROTOCOL_INFO info; + int len = sizeof(info); + if (getsockopt(*socket, SOL_SOCKET, SO_PROTOCOL_INFO, (char*)&info, &len) == 0) { + return (info.iSocketType == SOCK_DGRAM); + } + #else + int type; + socklen_t len = sizeof(type); + if (getsockopt(socket, SOL_SOCKET, SO_TYPE, &type, &len) == 0) { + return (type == SOCK_DGRAM); + } + #endif + return 0; /* Error: Could not determine socket type */ + } + /** Creates a host for communicating to peers. * * @param address the address at which other peers may connect to this host. If NULL, then no peers may connect to the host. @@ -4530,7 +4548,7 @@ extern "C" { * the window size of a connection which limits the amount of reliable packets that may be in transit * at any given time. */ - ENetHost * enet_host_create(const ENetAddress *address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth) { + ENetHost * enet_host_create(const ENetAddress *address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth, ENetSocket* externalUDPSocket) { ENetHost *host; ENetPeer *currentPeer; @@ -4550,28 +4568,34 @@ extern "C" { memset(host->peers, 0, peerCount * sizeof(ENetPeer)); - host->socket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); - if (host->socket != ENET_SOCKET_NULL) { - enet_socket_set_option (host->socket, ENET_SOCKOPT_IPV6_V6ONLY, 0); - } - - if (host->socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind(host->socket, address) < 0)) { + if (externalUDPSocket==NULL || !is_udp_socket(externalUDPSocket)){ + host->socket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); if (host->socket != ENET_SOCKET_NULL) { - enet_socket_destroy(host->socket); + enet_socket_set_option (host->socket, ENET_SOCKOPT_IPV6_V6ONLY, 0); } - - enet_free(host->peers); - enet_free(host); - - return NULL; + + if (host->socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind(host->socket, address) < 0)) { + if (host->socket != ENET_SOCKET_NULL) { + enet_socket_destroy(host->socket); + } + + enet_free(host->peers); + enet_free(host); + + return NULL; + } + + enet_socket_set_option(host->socket, ENET_SOCKOPT_NONBLOCK, 1); + enet_socket_set_option(host->socket, ENET_SOCKOPT_BROADCAST, 1); + enet_socket_set_option(host->socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE); + enet_socket_set_option(host->socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE); + enet_socket_set_option(host->socket, ENET_SOCKOPT_IPV6_V6ONLY, 0); + host->ownsSocket = true; + }else{ + host->socket = *externalUDPSocket; + host->ownsSocket = false; } - enet_socket_set_option(host->socket, ENET_SOCKOPT_NONBLOCK, 1); - enet_socket_set_option(host->socket, ENET_SOCKOPT_BROADCAST, 1); - enet_socket_set_option(host->socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE); - enet_socket_set_option(host->socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE); - enet_socket_set_option(host->socket, ENET_SOCKOPT_IPV6_V6ONLY, 0); - if (address != NULL && enet_socket_get_address(host->socket, &host->address) < 0) { host->address = *address; } @@ -4643,7 +4667,9 @@ extern "C" { return; } - enet_socket_destroy(host->socket); + if (host->ownsSocket){ /* Only destroy if it's internally managed. */ + enet_socket_destroy(host->socket); + } for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) { enet_peer_reset(currentPeer); From 5e177ef77bb7edeb3bab0573d67c6736633119cd Mon Sep 17 00:00:00 2001 From: "J.G.Adams" <82924084+JG-Adams@users.noreply.github.com> Date: Tue, 25 Feb 2025 22:47:49 +0000 Subject: [PATCH 2/4] modified: test/build.c modified: test/cli-server.c --- test/build.c | 4 ++-- test/cli-server.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/build.c b/test/build.c index 72cdb54..0771ecd 100644 --- a/test/build.c +++ b/test/build.c @@ -74,7 +74,7 @@ int main() { /* create a server */ printf("starting server...\n"); - server = enet_host_create(&address, MAX_CLIENTS, 2, 0, 0); + server = enet_host_create(&address, MAX_CLIENTS, 2, 0, 0, NULL); if (server == NULL) { printf("An error occurred while trying to create an ENet server host.\n"); return 1; @@ -83,7 +83,7 @@ int main() { printf("starting clients...\n"); for (i = 0; i < MAX_CLIENTS; ++i) { enet_address_set_host(&address, "127.0.0.1"); - clients[i].host = enet_host_create(NULL, 1, 2, 0, 0); + clients[i].host = enet_host_create(NULL, 1, 2, 0, 0, NULL); clients[i].peer = enet_host_connect(clients[i].host, &address, 2, 0); if (clients[i].peer == NULL) { printf("coundlnt connect\n"); diff --git a/test/cli-server.c b/test/cli-server.c index 3cff8da..df674de 100644 --- a/test/cli-server.c +++ b/test/cli-server.c @@ -38,7 +38,7 @@ void run_server() { address.host = ENET_HOST_ANY; address.port = 1234; - ENetHost* host = enet_host_create(&address, 4, 1, 0, 0); + ENetHost* host = enet_host_create(&address, 4, 1, 0, 0, NULL); if (!host) { printf("Failed to create server\n"); @@ -97,7 +97,7 @@ void run_client() { address.host = ENET_HOST_ANY; address.port = 1234; - ENetHost* host = enet_host_create(NULL, 1, 1, 0, 0); + ENetHost* host = enet_host_create(NULL, 1, 1, 0, 0, NULL); enet_address_set_host(&address, "127.0.0.1"); address.port = 1234; From 9975c49a77a4a9bdbb7167cb16121f5b2663764b Mon Sep 17 00:00:00 2001 From: "J.G.Adams" <82924084+JG-Adams@users.noreply.github.com> Date: Tue, 25 Feb 2025 23:01:59 +0000 Subject: [PATCH 3/4] modified: include/enet.h --- .vscode/settings.json | 5 +++++ include/enet.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..eef3d04 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "enet.h": "c" + } +} \ No newline at end of file diff --git a/include/enet.h b/include/enet.h index af38175..afe7480 100644 --- a/include/enet.h +++ b/include/enet.h @@ -4526,7 +4526,7 @@ extern "C" { #else int type; socklen_t len = sizeof(type); - if (getsockopt(socket, SOL_SOCKET, SO_TYPE, &type, &len) == 0) { + if (getsockopt(*socket, SOL_SOCKET, SO_TYPE, &type, &len) == 0) { return (type == SOCK_DGRAM); } #endif From ee0a96a7deee45c42017daef76c831e52be03ee7 Mon Sep 17 00:00:00 2001 From: "J.G.Adams" <82924084+JG-Adams@users.noreply.github.com> Date: Tue, 25 Feb 2025 18:11:01 -0500 Subject: [PATCH 4/4] Delete .vscode/settings.json --- .vscode/settings.json | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index eef3d04..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "files.associations": { - "enet.h": "c" - } -} \ No newline at end of file