From 0cad56c8c6ed4bf3f46039cb17b17a9dc83b98f2 Mon Sep 17 00:00:00 2001 From: Bubblegumdrop Date: Sat, 8 Jan 2022 23:36:08 -0500 Subject: [PATCH] Client and Server communication functionality repaired. test_UDPpacketVBuffer for testing. --- Makefile | 11 +--- include/Server.h | 3 + include/UDPpacketVBuffer.h | 25 ++++++++ src/Server.cpp | 80 +++++++++++++++++-------- src/UDPbase.cpp | 22 +++---- src/UDPpacketVBuffer.cpp | 55 +++++++++++++++++ src/client_main.cpp | 17 ++++++ src/server_main.cpp | 4 +- src/util.cpp | 62 ------------------- test/test_FileIO.cpp | 4 +- test/test_UDPpacketBufferV.cpp | 133 +++++++++++++++++++++++++++++++++++++++++ 11 files changed, 308 insertions(+), 108 deletions(-) create mode 100644 include/UDPpacketVBuffer.h create mode 100644 src/UDPpacketVBuffer.cpp create mode 100644 test/test_UDPpacketBufferV.cpp diff --git a/Makefile b/Makefile index 681da51..dc2f75e 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ COMMON_OBJS := \ $(OBJDIR)/src/lib_SDL_common.o \ $(OBJDIR)/src/signal_common.o \ $(OBJDIR)/src/UDPbase.o \ + $(OBJDIR)/src/UDPpacketVBuffer.o \ $(OBJDIR)/src/util.o SERVER_OBJS := \ @@ -58,7 +59,7 @@ TEST_OBJ_COMMON := \ $(COMMON_OBJS) -TESTS := test_FileIO test_Object test_lua +TESTS := test_FileIO test_lua test_UDPpacketBufferV TEST_PROGS := $(addprefix $(TESTDIR)/,$(TESTS)) # {{{ Flags @@ -149,15 +150,9 @@ test: $(TEST_PROGS) test/test_FileIO: $(TEST_OBJ_COMMON) $(OBJDIR)/src/util.o -test/test_Object: $(TEST_OBJ_COMMON) $(OBJDIR)/src/object.o $(OBJDIR)/src/quad.o $(OBJDIR)/src/cube.o $(OBJDIR)/src/lib_GL_common.o - test/test_lua: $(TEST_OBJ_COMMON) $(OBJDIR)/src/lib_lua_common.o -test/client: $(TEST_OBJ_COMMON) $(OBJDIR)/src/UDPbase.o $(OBJDIR)/src/lib_SDL_common.o - -test/test_UDP_DumpPacket: $(TEST_OBJ_COMMON) $(OBJDIR)/src/util.o - -test/server: $(TEST_OBJ_COMMON) +test/test_UDPpacketBufferV: $(TEST_OBJ_COMMON) $(OBJDIR)/src/UDPbase.o $(OBJDIR)/src/lib_SDL_common.o $(OBJDIR)/%.o: %.c $(OBJDIR)/%.o: %.c $(DEPDIR)/%.d diff --git a/include/Server.h b/include/Server.h index 844c98c..447ee58 100644 --- a/include/Server.h +++ b/include/Server.h @@ -6,6 +6,8 @@ #include "lib_lua_common.h" #include "UDPbase.h" +#define DEFAULT_MAX_SOCKET_TIMEOUT 10 + class Server : public UDPbase { SDL_mutex* mProcessPacketMutex; @@ -27,6 +29,7 @@ class Server : public UDPbase int AllocateApproximateBufferSpace (const int nclients); int Start (void); int Stop (void); + void CloseAllSockets (void); int Lock (void) { return SDL_LockMutex (mProcessPacketMutex); diff --git a/include/UDPpacketVBuffer.h b/include/UDPpacketVBuffer.h new file mode 100644 index 0000000..f3c6448 --- /dev/null +++ b/include/UDPpacketVBuffer.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class UDPpacketVBuffer +{ + int npackets; + UDPpacket** packetV; + public: + UDPpacketVBuffer (UDPpacket* src, const void* buf, const size_t size); + ~UDPpacketVBuffer (void) + { + if (packetV) + { + SDLNet_FreePacketV (packetV); + packetV = NULL; + } + } + int Send (UDPsocket sock) + { + int numsent; + numsent = SDLNet_UDP_SendV (sock, packetV, npackets); + return numsent; + } +}; diff --git a/src/Server.cpp b/src/Server.cpp index 8d48b68..8a4e558 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -7,7 +7,6 @@ Server::Server (const char *host, const Uint16 port) : UDPbase (host, port) { UDPsocket sock; - mProcessPacketMutex = SDL_CreateMutex (); if (NULL != (sock = Open (port))) { Bind (sock, -1); @@ -15,12 +14,26 @@ Server::Server (const char *host, const Uint16 port) } SocketSet = NULL; UDPPacketV = NULL; + mLuaState = NULL; + mProcessPacketMutex = SDL_CreateMutex (); } Server::~Server (void) { - int i, n; + CloseAllSockets (); + if (mProcessPacketMutex) + { + SDL_DestroyMutex (mProcessPacketMutex); + mProcessPacketMutex = NULL; + } +} + + +void +Server::CloseAllSockets (void) +{ + size_t i, n; n = TCPsocks.size (); for (i = 0; i < n; i++) SDLNet_TCP_Close (TCPsocks[i]); @@ -29,11 +42,6 @@ Server::~Server (void) for (i = 0; i < n; i++) SDLNet_UDP_Close (UDPsocks[i]); UDPsocks.clear (); - if (mProcessPacketMutex) - { - SDL_DestroyMutex (mProcessPacketMutex); - mProcessPacketMutex = NULL; - } } @@ -72,15 +80,17 @@ Server::AllocateApproximateBufferSpace (const int nclients) return l; } - SDL_Log ("Serving %d clients", nclients); + SDL_Log ("Preparing to serve %d clients", nclients); if (!(UDPPacketV = SDLNet_AllocPacketV (nclients, DEFAULT_MAX_PACKET_SIZE))) { SDL_Log ("SDLNet_AllocPacketV: %s", SDLNet_GetError ()); + return -1; } if (!(SocketSet = SDLNet_AllocSocketSet (nclients))) { SDL_Log ("SDLNet_AllocSocketSet: %s", SDLNet_GetError ()); + return -1; } total = 0; @@ -90,12 +100,16 @@ Server::AllocateApproximateBufferSpace (const int nclients) if (numused < 0) { SDL_Log ("SDLNet_AddSocket: %s", SDLNet_GetError ()); + return -1; } total += numused; } - if (total != UDPsocks.size ()) + if (total != (int)UDPsocks.size ()) + { SDL_Log ("Total clients: %d (%ld?)", total, UDPsocks.size ()); + return -1; + } return Unlock (); } @@ -106,15 +120,19 @@ Server::Start (void) { int l; + const int nclients = UDPsocks.size (); + if ((l = AllocateApproximateBufferSpace (nclients) < 0)) + { + DEBUG_LOG ("Unable to allocate approximate buffer space"); + return l; + } + if ((l = Lock ()) < 0) { DEBUG_LOG ("Lock failed: %s", SDL_GetError ()); return l; } - const int nclients = UDPsocks.size (); - AllocateApproximateBufferSpace (nclients); - mLuaState = luaL_newstate (); luaL_openlibs (mLuaState); @@ -128,6 +146,7 @@ int Server::Stop (void) { int i, l; + if ((l = Lock ()) < 0) { DEBUG_LOG ("Lock failed"); @@ -136,21 +155,34 @@ Server::Stop (void) SDL_RemoveTimer (mFetchPacketsCallbackTimerID); - lua_close (mLuaState); - - const int nclients = UDPsocks.size (); - for (i = 0; i < nclients; i++) + if (mLuaState) { - SDLNet_UDP_DelSocket (SocketSet, UDPsocks[i]); + lua_close (mLuaState); + mLuaState = NULL; } - SDLNet_FreeSocketSet (SocketSet); - SDLNet_FreePacketV (UDPPacketV); - SocketSet = NULL; - UDPPacketV = NULL; + if (SocketSet) + { + int nclients = UDPsocks.size (); + for (i = 0; i < nclients; i++) + { + SDLNet_UDP_DelSocket (SocketSet, UDPsocks[i]); + } + nclients = TCPsocks.size (); + for (i = 0; i < nclients; i++) + { + SDLNet_TCP_DelSocket (SocketSet, TCPsocks[i]); + } - SDL_DestroyMutex (mProcessPacketMutex); - mProcessPacketMutex = NULL; + SDLNet_FreeSocketSet (SocketSet); + SocketSet = NULL; + } + + if (UDPPacketV) + { + SDLNet_FreePacketV (UDPPacketV); + UDPPacketV = NULL; + } return 0; } @@ -177,7 +209,7 @@ Uint32 Server::FetchPacketsCallback (Uint32 interval, void *param) return 0; } - numready = SDLNet_CheckSockets (server->getSocketSet (), 1); + numready = SDLNet_CheckSockets (server->getSocketSet (), DEFAULT_MAX_SOCKET_TIMEOUT); if (numready < 0) { DEBUG_LOG ("SDLNet_CheckSockets: %s", SDLNet_GetError ()); diff --git a/src/UDPbase.cpp b/src/UDPbase.cpp index ff4968c..9466d13 100644 --- a/src/UDPbase.cpp +++ b/src/UDPbase.cpp @@ -2,7 +2,7 @@ UDPbase::UDPbase (const char* host, const Uint16 port) { - if (SDLNet_ResolveHost (&addr, host, SDLNet_Read16 (&port)) < 0) + if (SDLNet_ResolveHost (&addr, host, port) < 0) { throw "SDLNet_ResolveHost: " + std::string (SDLNet_GetError ()); } @@ -22,8 +22,8 @@ UDPsocket UDPbase::Open (void) UDPsocket UDPbase::Open (const Uint16 port) { + IPaddress* addr = NULL; UDPsocket sock = NULL; - IPaddress* addr; if (NULL == (sock = SDLNet_UDP_Open (port))) { throw "SDLNet_UDP_Open: " + std::string (SDLNet_GetError ()); @@ -36,6 +36,14 @@ UDPsocket UDPbase::Open (const Uint16 port) } +void UDPbase::Close (UDPsocket sock) +{ + SDL_assert (NULL != sock); + SDLNet_UDP_Close (sock); + sock = NULL; +} + + int UDPbase::Bind (UDPsocket sock, const int channel) { int binding; @@ -55,15 +63,7 @@ void UDPbase::Unbind (UDPsocket sock, const int channel) } -void UDPbase::Close (UDPsocket sock) -{ - SDL_assert (NULL != sock); - SDLNet_UDP_Close (sock); - sock = NULL; -} - - std::string UDPbase::toString (void) { - return std::string (SDLNet_ResolveIP (&addr)) + ":" + std::to_string (addr.port); + return std::string (SDLNet_ResolveIP (&addr)) + ":" + std::to_string (SDLNet_Read16 (&addr.port)); } diff --git a/src/UDPpacketVBuffer.cpp b/src/UDPpacketVBuffer.cpp new file mode 100644 index 0000000..803fa5b --- /dev/null +++ b/src/UDPpacketVBuffer.cpp @@ -0,0 +1,55 @@ +#include "UDPpacketVBuffer.h" + +#include + +UDPpacketVBuffer::UDPpacketVBuffer (UDPpacket* src, const void* buf, const size_t size) +{ + int i, len, mtu, nsent; + const uint8_t* bufPtr; + const uint8_t* bufPtrEnd; + + SDL_assert (NULL != src); + SDL_assert (NULL != buf); + + mtu = src->len; + SDL_assert (mtu > 0); + + npackets = (int)ceil ((double) size / (double) mtu); + if (NULL == (packetV = SDLNet_AllocPacketV (npackets, mtu))) + { + throw "SDLNet_AllocPacketV: " + std::string (SDLNet_GetError ()); + } + + i = 0; + nsent = size; + bufPtr = (const uint8_t*)buf; + bufPtrEnd = bufPtr + size; + while ((i < npackets) && (bufPtr < bufPtrEnd) && (nsent > 0)) + { + len = nsent; + if (len > mtu) + len = mtu; + /* Use SDLNet_UDP_Send to send an empty packet instead... it's probably simpler than all this machinery. */ + if (len < 1) + break; + + /* SDLNet_UDP_Send sets the channel in the argument, + * this one takes it implicitly from the source UDPpacket. + * Set it for all packets in the vector. */ + packetV[i]->channel = src->channel; + /* Always zero out the entire data */ + SDL_memset (packetV[i]->data, 0, mtu); + /* But only memcpy in the relevant bits */ + SDL_memcpy (packetV[i]->data, bufPtr, len); + packetV[i]->len = len; + /* probably don't need maxlen or status set after this */ + packetV[i]->maxlen = size; + packetV[i]->status = 0; + /* But we will want the destination address of this packet */ + packetV[i]->address = src->address; + /* Advance */ + bufPtr += len; + nsent -= len; + i++; + } +} diff --git a/src/client_main.cpp b/src/client_main.cpp index e5061cd..c3383bb 100644 --- a/src/client_main.cpp +++ b/src/client_main.cpp @@ -9,6 +9,7 @@ #include "signal_common.h" #include "unused.h" #include "UDPbase.h" +#include "UDPpacketVBuffer.h" #include #include @@ -413,6 +414,22 @@ my_Input_Key (SDL_Event * event) { DEBUG_LOG ("Physical %s key acting as %s key", SDL_GetScancodeName (event->key.keysym.scancode), SDL_GetKeyName (event->key.keysym.sym)); } + UDPpacket* packet = SDLNet_AllocPacket (sizeof (SDL_Event)); + if (packet) + { + packet->len = sizeof (SDL_Event); + packet->channel = state.channel; + IPaddress* addr = SDLNet_UDP_GetPeerAddress (state.udpsock, state.channel); + if (addr) + { + SDL_Log ("%s:%d", SDLNet_ResolveIP (addr), SDLNet_Read16(&addr->port)); + packet->address = *addr; + UDPpacketVBuffer packetV (packet, (const void*)event, sizeof (SDL_Event)); + packetV.Send (state.udpsock); + } + SDLNet_FreePacket (packet); + } + // SDL_Log ("%d %d %ld", state.channel, state.mtu, sizeof (SDL_Event)); // Buffer_Write_UDP (state.udpsock, state.channel, state.mtu, (const void*)event, sizeof (SDL_Event)); } diff --git a/src/server_main.cpp b/src/server_main.cpp index db1c8db..ec30a4e 100644 --- a/src/server_main.cpp +++ b/src/server_main.cpp @@ -78,6 +78,7 @@ main (int argc, char **argv) } server->Stop (); + server->CloseAllSockets (); SDL_WaitThread (stdin_loop, NULL); @@ -286,8 +287,9 @@ static int my_StdinThread(void* param) while (!done && getline (std::cin, buf)) { buf = trim (buf); - if ((done = my_StdinThread_Helper (buf))) + if (buf.empty () || my_StdinThread_Helper (buf)) { + done = true; break; } my_ShowPrompt (); diff --git a/src/util.cpp b/src/util.cpp index 8932281..7449e7d 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -92,65 +92,3 @@ util_UDP_DumpPacket (UDPpacket* packet) //DEBUG_LOG ("%d bytes from %s:%d:\n%s", packet->len, hoststring, ntohs (packet->address.port), str.c_str ()); } - - -/* - * UDPsock sock; - * FileIO f (path, "r"); - * std::string buf = f.ReadToString (); - * UDPpacket* packet = SDL_AllocPacket (buf.length ()); - * packet->len = DEFAULT_MAX_PACKET_SIZE; - * packet->address = ipaddress; - * packet->channel = -1; - * UDPpacket** packetV = Buffer_To_UDPPacketV (packet, &buf[0], buf.length ()); - * SDLNet_UDP_SendV (sock, packetV, packetV[0].status); - * SDLNet_FreePacket (packet); - * SDLNet_FreePacketV (packetV); - */ -UDPpacket** -Buffer_To_UDPPacketV (UDPpacket* src, const void* buf, const size_t size) -{ - int i, howmany, len, mtu, nsent; - const uint8_t* bufPtr; - const uint8_t* bufPtrEnd; - UDPpacket** packetV; - - SDL_assert (NULL != src); - SDL_assert (NULL != buf); - - mtu = src->len; - SDL_assert (mtu > 0); - - howmany = (int)ceil ((double) size / (double) mtu); - if (NULL == (packetV = SDLNet_AllocPacketV (howmany, mtu))) - { - SDL_Log ("SDLNet_AllocPacketV: %s", SDLNet_GetError ()); - return NULL; - } - - i = 0; - nsent = size; - bufPtr = (const uint8_t*)buf; - bufPtrEnd = bufPtr + size; - while ((i < howmany) && (bufPtr < bufPtrEnd) && (nsent > 0)) - { - len = nsent; - if (len > mtu) - len = mtu; - - packetV[i]->channel = src->channel; - /* Always zero out the entire data */ - SDL_memset (packetV[i]->data, 0, mtu); - /* But only memcpy in the relevant bits */ - SDL_memcpy (packetV[i]->data, bufPtr, len); - packetV[i]->len = len; - packetV[i]->maxlen = size; - packetV[i]->status = 0; - packetV[i]->address = src->address; - bufPtr += len; - nsent -= len; - i++; - } - - return packetV; -} diff --git a/test/test_FileIO.cpp b/test/test_FileIO.cpp index b924f91..ddcc3fe 100644 --- a/test/test_FileIO.cpp +++ b/test/test_FileIO.cpp @@ -19,10 +19,10 @@ main (int argc, char **argv) { FileIO f (argv[argc], "r"); std::string buf = f.ReadToString (); - if (IsProbablyAscii (buf.c_str (), buf.size ())) + if (util_IsProbablyAscii (buf.c_str (), buf.size ())) printf ("%s", buf.c_str ()); else - HexDump (buf.c_str (), buf.size ()); + util_HexDump (buf.c_str (), buf.size ()); rc = 0; } } diff --git a/test/test_UDPpacketBufferV.cpp b/test/test_UDPpacketBufferV.cpp new file mode 100644 index 0000000..4669709 --- /dev/null +++ b/test/test_UDPpacketBufferV.cpp @@ -0,0 +1,133 @@ +#include "camera.h" +#include "cube.h" +#include "debug.h" +#include "glCheckErrors.h" +#include "lib_GL_common.h" +#include "lib_SDL_common.h" +#include "quad.h" +#include "shader.h" +#include "signal_common.h" +#include "unused.h" +#include "UDPbase.h" +#include "UDPpacketVBuffer.h" +#include "FileIO.h" + +#include +#include +#include +#include + +#include /* getopt */ +#include /* exit */ +#include /* memset */ +#include /* getopt */ + +#include +#include + +#define Perf_Diff(a, b) ((double) 1000 * ((double)(((double) (b) - (double) (a)) / (double) SDL_GetPerformanceFrequency ()))) + +#define MIN_FRAME_MS 7 /* 144 Hz */ + +static void my_GetOpt (int, char **); +static void my_Usage (const char *); + +static const char* host = "localhost"; +static Uint16 port = 6666; +static int channel = -1; +static std::string path = "./test/test_UDPpacketVBuffer.cpp"; + +static std::unique_ptr client; + +int +main (int argc, char **argv) +{ + UDPsocket udpsock; + + common_Signal_Init (); + my_GetOpt (argc, argv); + + common_SDL_Init (); + + client = std::make_unique (host, port); + if (NULL == (udpsock = client->Open (0))) + { + SDL_Log ("Unable to open client port"); + return -1; + } + if (-1 == (channel = client->Bind (udpsock, -1))) + { + SDL_Log ("Unable to bind client port"); + return -1; + } + + std::string buf; + if (path == "-") + { + try { + std::string line; + while (getline (std::cin, line)) + { + buf += line + "\n"; + } + } + catch (std::ifstream::failure& e) { + // std::cout << e << std::endl; + } + } + else + { + FileIO f (path, "r"); + buf = f.ReadToString (); + } + UDPpacket* packet = SDLNet_AllocPacket (buf.length ()); + IPaddress* addr = SDLNet_UDP_GetPeerAddress (udpsock, channel); + packet->len = DEFAULT_MAX_PACKET_SIZE; + packet->address = *addr; + packet->channel = channel; + UDPpacketVBuffer packetV (packet, &buf[0], buf.length ()); + packetV.Send (udpsock); + + client->Close (udpsock); + + common_SDL_Quit (); + + return 0; +} + + + +static void +my_Usage (const char *argv0) +{ + fprintf (stderr, "Usage: %s [-h] [-s host] [-p port]\n", argv0); +} + + +static void +my_GetOpt (int argc, char **argv) +{ + int opt; + host = "localhost"; + port = 6666; + while ((opt = getopt (argc, argv, "f:hp:s:")) != -1) + { + switch (opt) + { + case 'p': + port = strtol (optarg, NULL, 0); + break; + case 's': + host = optarg; + break; + case 'f': + path = std::string (optarg); + break; + case 'h': + default: + my_Usage (argv[0]); + exit (EXIT_FAILURE); + break; + } + } +}