From 60e282929f0bc700a3c1531c114eeccbbe66e587 Mon Sep 17 00:00:00 2001 From: Bubblegumdrop Date: Sun, 16 Jan 2022 14:40:20 -0500 Subject: [PATCH] Add a "SafeUDPpacket" and "SafeUDPpacketV" class. I'm trying to merge UDPpacketVBuffer and SafeUDPpacketV. Seems pretty messy so far... hopefully this is fruitful. --- Makefile | 11 ++- include/SafeUDPpacket.h | 99 ++++++++++++++++++++ include/Server.h | 3 + include/UDPbase.h | 53 +++++++---- include/UDPpacketVBuffer.h | 16 ++-- include/lib_GetOpt.h | 11 +++ src/Commands.cpp | 15 +-- src/SafeUDPpacket.cpp | 76 +++++++++++++++ src/Server.cpp | 13 ++- src/UDPpacketVBuffer.cpp | 53 ++++++++--- src/client_main.cpp | 206 ++++++++++++++++++----------------------- src/lib_GetOpt.cpp | 43 +++++++++ src/server_main.cpp | 49 ++-------- test/test_SafeUDPpacket.cpp | 11 +++ test/test_UDPpacketBufferV.cpp | 84 ++++++++--------- 15 files changed, 500 insertions(+), 243 deletions(-) create mode 100644 include/SafeUDPpacket.h create mode 100644 include/lib_GetOpt.h create mode 100644 src/SafeUDPpacket.cpp create mode 100644 src/lib_GetOpt.cpp create mode 100644 test/test_SafeUDPpacket.cpp diff --git a/Makefile b/Makefile index 828784b..3b9aa77 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all clean +.PHONY: all clean reallyclean test .POSIX: # {{{ Flags @@ -27,6 +27,7 @@ OBJS := $(patsubst %,$(OBJDIR)/%.o,$(basename $(SRCS))) DEPS := $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))) COMMON_OBJS := \ + $(OBJDIR)/src/lib_GetOpt.o \ $(OBJDIR)/src/lib_lua_common.o \ $(OBJDIR)/src/lib_SDL_common.o \ $(OBJDIR)/src/lib_SDL_Log.o \ @@ -186,9 +187,13 @@ $(OBJDIR)/%.o: %.cxx $(DEPDIR)/%.d $(COMPILE.cc) $< $(POSTCOMPILE) +clean: REALLYCLEAN?=@echo clean: - @echo $(RM) $(DEPDIR) $(OBJDIR) $(PROGS) - @echo $(RM) $(TEST_PROGS) + $(REALLYCLEAN) $(RM) $(DEPDIR) $(OBJDIR) $(PROGS) + $(REALLYCLEAN) $(RM) $(TEST_PROGS) + +reallyclean: + $(MAKE) REALLYCLEAN= clean .PRECIOUS: $(DEPDIR)/%.d $(DEPDIR)/%.d: ; diff --git a/include/SafeUDPpacket.h b/include/SafeUDPpacket.h new file mode 100644 index 0000000..1edd8e5 --- /dev/null +++ b/include/SafeUDPpacket.h @@ -0,0 +1,99 @@ +#pragma once + +#include +#include +#include +#include +#include + +class SafeUDPpacket +{ + struct SDLNet_PacketDeleter + { + void operator () (UDPpacket* p) + { + SDLNet_FreePacket (p); + p = NULL; + } + }; + std::unique_ptr m_packet; + void Reset (UDPpacket* p) + { + m_packet.reset (p); + } + public: + SafeUDPpacket (int size) + { + UDPpacket* p; + if (NULL == (p = SDLNet_AllocPacket (size))) + { + throw "SDLNet_AllocPacket: " + std::string (SDLNet_GetError ()); + } + Reset (p); + } + SafeUDPpacket (UDPpacket* p) + { + Reset (p); + } + UDPpacket* get (void) const + { + return m_packet.get (); + } + + int channel (int channel) const { return get()->channel = channel; } + int channel (void) const { return get()->channel; } + + int len (int len) const { return get()->len = len; } + int len (void) const { return get()->len; } + + int maxlen (int maxlen) const { return get()->maxlen = maxlen; } + int maxlen (void) const { return get()->maxlen; } + + int status (int status) const { return get()->status = status; } + int status (void) const { return get()->status; } + + IPaddress address (IPaddress address) const { return get()->address = address; } + IPaddress address (void) const { return get()->address; } + + Uint8 *data (Uint8* data) const { return get()->data = data; } + Uint8 *data (void) const { return get()->data; } +}; + +class SafeUDPpacketV +{ + std::vector m_packetV; + public: + SafeUDPpacketV (const void*, const int, const int mtu = 1450); + SafeUDPpacketV (int howmany, int size) + { + UDPpacket** p; + m_packetV.reserve (howmany); + if (NULL == (p = SDLNet_AllocPacketV (howmany, size))) + { + throw "SDLNet_AllocPacketV: " + std::string (SDLNet_GetError ()); + } + else + { + for (; (p != NULL) && (*p != NULL); p++) + { + m_packetV.push_back (SafeUDPpacket (*p)); + } + SDL_assert ((m_packetV.size () > 0) && (howmany == (int)m_packetV.size ())); + /* + * SDLNet_FreePacketV just calls SDLNet_FreePacket on each packet. + * The "packetV" itself is just something allocated on the heap. + * We don't need this any longer. + */ + SDL_free (p); + } + } + const SafeUDPpacket& get (size_t idx) + { + return m_packetV.at (idx); + } + size_t size (void) const + { + return m_packetV.size (); + } + std::string toString (void); +}; diff --git a/include/Server.h b/include/Server.h index 1b8a880..33b507b 100644 --- a/include/Server.h +++ b/include/Server.h @@ -6,6 +6,9 @@ #include "lib_lua_common.h" #include "UDPbase.h" +/* + * Used as mFetchPacketsCallbackTimerID timeout + */ #define DEFAULT_SOCKET_TIMEOUT 10 class Server : public UDPbase diff --git a/include/UDPbase.h b/include/UDPbase.h index c3a37ef..fd1aee7 100644 --- a/include/UDPbase.h +++ b/include/UDPbase.h @@ -5,32 +5,53 @@ #include -#define DEFAULT_MAX_PACKET_SIZE 250 +#define DEFAULT_MAX_PACKET_SIZE 512 -class UDPbase +class +UDPbase { int mChannel; IPaddress mIPAddress; + void + CloseAllSockets (void); + protected: std::vector UDPsocks; public: - UDPbase (const char* host, const Uint16 port); - UDPbase (const char* host, const Uint16 port, const int channel); + UDPbase (const char *host, const Uint16 port); + UDPbase (const char *host, const Uint16 port, const int channel); ~UDPbase (void); - int ResolveHost (IPaddress*, const char*, const Uint16); + int + ResolveHost (IPaddress *, const char *, const Uint16); - UDPsocket UDP_Open (void); - UDPsocket UDP_Open (const Uint16 port); - void UDP_Close (UDPsocket sock); - int UDP_Bind (UDPsocket sock, const int channel); - void UDP_Unbind (UDPsocket sock, const int channel); - IPaddress* UDP_GetPeerAddress (UDPsocket sock, const int channel); + UDPsocket + UDP_Open (void); + UDPsocket + UDP_Open (const Uint16 port); + void + UDP_Close (UDPsocket sock); + int + UDP_Bind (UDPsocket sock, const int channel); + void + UDP_Unbind (UDPsocket sock, const int channel); + IPaddress * + UDP_GetPeerAddress (UDPsocket sock, const int channel); - void CloseAllSockets (void); + int + getChannel (void) const + { + return + mChannel; + } + UDPsocket + getSocket (const size_t idx) const + { + return + UDPsocks. + at (idx); + } - int getChannel (void) const { return mChannel; } - UDPsocket getSocket (const size_t idx) const { return UDPsocks.at (idx); } - - std::string toString (void); + std::string + toString (void); }; diff --git a/include/UDPpacketVBuffer.h b/include/UDPpacketVBuffer.h index 5b10559..b652813 100644 --- a/include/UDPpacketVBuffer.h +++ b/include/UDPpacketVBuffer.h @@ -1,5 +1,6 @@ #pragma once +#include #include /** @@ -36,25 +37,26 @@ Then free the leftover setup packet: */ class UDPpacketVBuffer { - int npackets; - UDPpacket** packetV; + int m_howmany; + UDPpacket** m_packetV; public: UDPpacketVBuffer (UDPpacket* src, const void* buf, const size_t size); ~UDPpacketVBuffer (void) { - if (packetV) + if (m_packetV) { - SDLNet_FreePacketV (packetV); - packetV = NULL; + SDLNet_FreePacketV (m_packetV); + m_packetV = NULL; } } int Send (UDPsocket sock) { int numsent = 0; - if (packetV) + if ((NULL != m_packetV) && (m_howmany > 0)) { - numsent = SDLNet_UDP_SendV (sock, packetV, npackets); + numsent = SDLNet_UDP_SendV (sock, m_packetV, m_howmany); } return numsent; } + std::string Reassemble (void); }; diff --git a/include/lib_GetOpt.h b/include/lib_GetOpt.h new file mode 100644 index 0000000..5a5350f --- /dev/null +++ b/include/lib_GetOpt.h @@ -0,0 +1,11 @@ +#pragma once + +struct Init_CommonOpts +{ + const char* host; + int channel; + int mtu; + unsigned short port; +}; + +void common_GetOpt (int, char**, Init_CommonOpts*); diff --git a/src/Commands.cpp b/src/Commands.cpp index 2f8d5d1..4aff0d9 100644 --- a/src/Commands.cpp +++ b/src/Commands.cpp @@ -26,15 +26,16 @@ bool command_Echo (const std::string& args) bool command_Shell (const std::string& args) { - int rc; - if (args.empty ()) + char output[8192]; + FILE *fp; + if (!args.empty ()) { - } - else - { - c = system (args.c_str ()); - switch (rc) + if ((fp = popen (args.c_str (), "r"))) { + while (fgets (output, (sizeof output) - 1, fp) != NULL) { + printf ("%s", output); + } + pclose (fp); } } diff --git a/src/SafeUDPpacket.cpp b/src/SafeUDPpacket.cpp new file mode 100644 index 0000000..d2fbc8b --- /dev/null +++ b/src/SafeUDPpacket.cpp @@ -0,0 +1,76 @@ +#include "SafeUDPpacket.h" + +SafeUDPpacketV::SafeUDPpacketV (const void* buf, const int size, const int mtu) +{ + int howmany, i, len, numsent; + const uint8_t* bufPtr; + const uint8_t* bufPtrEnd; + + SDL_assert (NULL != buf); + + SDL_assert (mtu > 0); + howmany = (int) ceil ((double) size / (double) mtu); + + i = 0; + numsent = 0; + bufPtr = (const uint8_t*) buf; + bufPtrEnd = bufPtr + size; + while ((i < howmany) && (bufPtr < bufPtrEnd) && (numsent < size)) + { + SafeUDPpacket p (mtu); + + len = size - numsent; + 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; + + SDL_memset (p.data (), 0, mtu); + p.len (len); + p.maxlen (size); + + /* But only memcpy in the relevant bits */ + SDL_memcpy (p.data (), bufPtr, len); + m_packetV.push_back (std::move (p)); + + /* But we will want the destination address of this packet */ + /* Advance */ + bufPtr += len; + numsent += len; + i++; + } + + SDL_assert (howmany == (int)m_packetV.size ()); +} + + +std::string +SafeUDPpacketV::toString (void) +{ + int howmany, maxlen, mtu, numrecv; + char* bufPtr; + char* bufPtrEnd; + std::string buf; + + howmany = m_packetV.size (); + SDL_assert (howmany > 0); + + maxlen = m_packetV[0].maxlen (); + SDL_assert (maxlen > 0); + buf.reserve (maxlen); + bufPtr = &buf[0]; + bufPtrEnd = bufPtr + maxlen; + + for (numrecv = 0; (numrecv < howmany) && (bufPtr < bufPtrEnd); numrecv++) + { + mtu = m_packetV[numrecv].len (); + SDL_assert (mtu > 0); + memcpy (bufPtr, m_packetV[numrecv].data (), mtu); + bufPtr += mtu; + } + + SDL_assert (numrecv == howmany); + + return buf; +} diff --git a/src/Server.cpp b/src/Server.cpp index 70ab889..1f120c1 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -55,12 +55,17 @@ Server::AllocateApproximateResources (const int nclients) /* * If each client sends 1024 250 byte packets, that's 1/4th of a MB or 256000 bytes ... * seems fine for now as an upper limit. + * + * Since writing that comment, DEFAULT_MAX_PACKET_RECV_SIZE seems to have become 1024. + * So, if 1024 clients are sending 1024 byte packets, we'll need 1 MB of memory. + * + * If 512 clients sending 512 byte packets, that's still 256000 bytes. */ if (packetV) { SDLNet_FreePacketV (packetV); } - if (!(packetV = SDLNet_AllocPacketV (1024 * nclients, DEFAULT_MAX_PACKET_RECV_SIZE))) + if (!(packetV = SDLNet_AllocPacketV (2 * nclients, DEFAULT_MAX_PACKET_RECV_SIZE))) { SDL_Log ("SDLNet_AllocPacketV: %s", SDLNet_GetError ()); return -1; @@ -215,6 +220,12 @@ Uint32 Server::FetchPacketsCallback (Uint32 interval, void *param) * TODO fix this wait timeout blocking issue * * I want this to block, but also to be stoppable. + * + * Maybe I can have clients send a disconnect packet, then when the queue is zero, stop this thread? + * + * How would clients send a connect packet? I'd have to listen indefinitely and that would block. + * + * Tricky tricky! */ numready = SDLNet_CheckSockets (server->getSocketSet (), (1000 * DEFAULT_SOCKET_TIMEOUT / 3) / 1000); if (numready < 0) diff --git a/src/UDPpacketVBuffer.cpp b/src/UDPpacketVBuffer.cpp index 53b80d5..e9546b2 100644 --- a/src/UDPpacketVBuffer.cpp +++ b/src/UDPpacketVBuffer.cpp @@ -13,10 +13,10 @@ UDPpacketVBuffer::UDPpacketVBuffer (UDPpacket* src, const void* buf, const size_ mtu = src->len; SDL_assert (mtu > 0); - npackets = (int) ceil ((double) size / (double) mtu); - // SDL_Log ("%d", npackets); + m_howmany = (int) ceil ((double) size / (double) mtu); + // SDL_Log ("%d", m_howmany); - if (NULL == (packetV = SDLNet_AllocPacketV (npackets, mtu))) + if (NULL == (m_packetV = SDLNet_AllocPacketV (m_howmany, mtu))) { throw "SDLNet_AllocPacketV: " + std::string (SDLNet_GetError ()); } @@ -25,7 +25,7 @@ UDPpacketVBuffer::UDPpacketVBuffer (UDPpacket* src, const void* buf, const size_ nsent = size; bufPtr = (const uint8_t*) buf; bufPtrEnd = bufPtr + size; - while ((i < npackets) && (bufPtr < bufPtrEnd) && (nsent > 0)) + while ((i < m_howmany) && (bufPtr < bufPtrEnd) && (nsent > 0)) { len = nsent; if (len > mtu) @@ -37,20 +37,51 @@ UDPpacketVBuffer::UDPpacketVBuffer (UDPpacket* src, const void* buf, const size_ /* 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; + m_packetV[i]->channel = src->channel; /* Always zero out the entire data */ - SDL_memset (packetV[i]->data, 0, mtu); + SDL_memset (m_packetV[i]->data, 0, mtu); /* But only memcpy in the relevant bits */ - SDL_memcpy (packetV[i]->data, bufPtr, len); - packetV[i]->len = len; + SDL_memcpy (m_packetV[i]->data, bufPtr, len); + m_packetV[i]->len = len; /* probably don't need maxlen or status set after this */ - packetV[i]->maxlen = size; - packetV[i]->status = 0; + m_packetV[i]->maxlen = size; + m_packetV[i]->status = 0; /* But we will want the destination address of this packet */ - packetV[i]->address = src->address; + m_packetV[i]->address = src->address; /* Advance */ bufPtr += len; nsent -= len; i++; } } + + +std::string +UDPpacketVBuffer::Reassemble (void) +{ + int i, maxlen, mtu, numrecv; + char* bufPtr; + char* bufPtrEnd; + std::string buf; + + SDL_assert (NULL != m_packetV); + SDL_assert (NULL != m_packetV[0]); + + maxlen = m_packetV[0]->maxlen; + SDL_assert (maxlen > 0); + buf.reserve (maxlen); + bufPtr = &buf[0]; + bufPtrEnd = bufPtr + maxlen; + + for (numrecv = 0; (numrecv < m_howmany) && m_packetV[numrecv] && (bufPtr < bufPtrEnd); numrecv++) + { + mtu = m_packetV[numrecv]->len; + SDL_assert (mtu > 0); + memcpy (bufPtr, m_packetV[numrecv]->data, mtu); + bufPtr += mtu; + } + + SDL_assert (numrecv == m_howmany); + + return buf; +} diff --git a/src/client_main.cpp b/src/client_main.cpp index d128553..0ae642e 100644 --- a/src/client_main.cpp +++ b/src/client_main.cpp @@ -11,6 +11,7 @@ #include "UDPbase.h" #include "UDPpacketVBuffer.h" #include "events_common.h" +#include "lib_GetOpt.h" #include #include @@ -33,11 +34,9 @@ static bool my_Input (SDL_Event*); static bool my_SDL_UserEvent (SDL_Event*); static bool my_SDL_WindowEvent (SDL_Event*); -static void my_GetOpt (int, char**); static void my_Init (int, char**); static void my_Render (void); static void my_UpdateValues (void); -static void my_Usage (const char*); struct Uniform_Values { @@ -56,16 +55,19 @@ struct Uniform_Values struct Client_State { + Init_CommonOpts init_opts; + + const char* host; + int channel; + int mtu; + Uint16 port; + bool done; Uint64 start, end; double diff; UDPsocket udpsock; - const char* host; - Uint16 port; - int channel; - int mtu; SDL_GLContext GLContext; SDL_Window* Window; @@ -86,7 +88,6 @@ struct Client_State static std::unique_ptr cube; static std::unique_ptr quad; static std::unique_ptr shader; -static std::unique_ptr client; static Camera camera; static struct Client_State state; @@ -95,87 +96,94 @@ static struct Uniform_Values values; int main (int argc, char** argv) { - glm::mat4 model, view, projection; - SDL_Event event; - - my_Init (argc, argv); - - shader = std::make_unique ("./glsl/camera.v.glsl", "", "./glsl/new.f.glsl"); - if (!shader->ID) { - SDL_Log ("Unable to load shader."); - goto _out; - } + glm::mat4 model, view, projection; + SDL_Event event; + std::unique_ptr client; - camera = Camera (); - values.iResolution.x = state.Window_Width; - values.iResolution.y = state.Window_Height; - values.iResolution.z = 1.0; + my_Init (argc, argv); - cube = std::make_unique (1); - quad = std::make_unique (1); - - state.mtu = 1450; - state.done = false; - client = std::make_unique (state.host, state.port, state.channel); - if (NULL == (state.udpsock = client->getSocket (0))) - { - SDL_Log ("Unable to open client port"); - goto _out; - } - if (-1 == (state.channel = client->getChannel ())) - { - SDL_Log ("Unable to bind client port"); - goto _out; - } - - while (!state.done) - { - state.end = SDL_GetPerformanceCounter (); - state.diff = Perf_Diff (state.start, state.end); - while (state.diff < MIN_FRAME_MS) + shader = std::make_unique ("./glsl/camera.v.glsl", "", "./glsl/new.f.glsl"); + if (!shader->ID) + { + SDL_Log ("Unable to load shader."); + goto _out; + } + + camera = Camera (); + values.iResolution.x = state.Window_Width; + values.iResolution.y = state.Window_Height; + values.iResolution.z = 1.0; + + cube = std::make_unique (1); + quad = std::make_unique (1); + + state.done = false; + + /* XXX is this okay? We are using C++ after all.. inheritance time */ + state.mtu = state.init_opts.mtu; + state.host = state.init_opts.host; + state.channel = state.init_opts.channel; + state.port = state.init_opts.port; + client = std::make_unique (state.host, state.port, state.channel); + if (NULL == (state.udpsock = client->getSocket (0))) + { + SDL_Log ("Unable to open client port"); + goto _out; + } + if (-1 == (state.channel = client->getChannel ())) + { + SDL_Log ("Unable to bind client port"); + goto _out; + } + + while (!state.done) { - SDL_Delay (1); state.end = SDL_GetPerformanceCounter (); state.diff = Perf_Diff (state.start, state.end); + while (state.diff < MIN_FRAME_MS) + { + SDL_Delay (1); + state.end = SDL_GetPerformanceCounter (); + state.diff = Perf_Diff (state.start, state.end); + } + state.start = SDL_GetPerformanceCounter (); + + SDL_SetRelativeMouseMode ((SDL_bool) state.InputRelativeMouseMode); + SDL_CaptureMouse ((SDL_bool) state.InputCaptureMouse); + + while (!state.done && SDL_PollEvent (&event)) + { + state.done = my_Input (&event); + } + my_AnalogInput (); + + projection = glm::perspective (glm::radians (camera.Zoom), (float) values.iResolution.x / (float) values.iResolution.y, camera.zNear, camera.zFar); + view = camera.GetViewMatrix (); + model = glm::mat4 (1.0f); + + my_UpdateValues (); + + shader->Use (); + shader->Mat4 ("Projection", projection); + shader->Mat4 ("View", view); + shader->Mat4 ("Model", model); + + my_Render (); + + model = glm::mat4 (1.0f); + model = glm::scale (model, glm::vec3 (10.0f)); + shader->Use (); + shader->Mat4 ("Projection", projection); + shader->Mat4 ("View", view); + shader->Mat4 ("Model", model); + cube->Draw (); + + SDL_GL_SwapWindow (state.Window); } - state.start = SDL_GetPerformanceCounter (); - - SDL_SetRelativeMouseMode ((SDL_bool) state.InputRelativeMouseMode); - SDL_CaptureMouse ((SDL_bool) state.InputCaptureMouse); - - while (!state.done && SDL_PollEvent (&event)) - { - state.done = my_Input (&event); - } - my_AnalogInput (); - - projection = glm::perspective (glm::radians (camera.Zoom), (float) values.iResolution.x / (float) values.iResolution.y, camera.zNear, camera.zFar); - view = camera.GetViewMatrix (); - model = glm::mat4 (1.0f); - - my_UpdateValues (); - - shader->Use (); - shader->Mat4 ("Projection", projection); - shader->Mat4 ("View", view); - shader->Mat4 ("Model", model); - - my_Render (); - - model = glm::mat4 (1.0f); - model = glm::scale (model, glm::vec3 (10.0f)); - shader->Use (); - shader->Mat4 ("Projection", projection); - shader->Mat4 ("View", view); - shader->Mat4 ("Model", model); - cube->Draw (); - - SDL_GL_SwapWindow (state.Window); } _out: - client->CloseAllSockets (); SDL_GL_DeleteContext (state.GLContext); SDL_DestroyWindow (state.Window); common_SDL_Quit (); @@ -188,7 +196,8 @@ static void my_Init (int argc, char** argv) { common_Signal_Init (); - my_GetOpt (argc, argv); + + common_GetOpt (argc, argv, &state.init_opts); state.start = state.end = SDL_GetPerformanceCounter (); @@ -314,7 +323,7 @@ my_Input (SDL_Event* event) case SHADER_PROGRAM_REFRESH: my_SDL_UserEvent (event); break; - break; + break; case SDL_WINDOWEVENT: my_SDL_WindowEvent (event); break; @@ -467,7 +476,8 @@ my_SDL_UserEvent (SDL_Event* event) SDL_Log ("SHADER_PROGRAM_REFRESH"); /* Actually do the refresh */ GLuint id; - try { + try + { id = shader->Compile3ShaderBuffers (shader->getVertexPath (), shader->getGeometryPath (), shader->getFragmentPath ()); } catch (const std::string& e) @@ -510,37 +520,3 @@ my_SDL_WindowEvent (SDL_Event* event) } return done; } - - -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; - state.host = "localhost"; - state.port = 6666; - state.channel = -1; - while ((opt = getopt (argc, argv, "hp:s:")) != -1) - { - switch (opt) - { - case 'p': - state.port = strtol (optarg, NULL, 0); - break; - case 's': - state.host = optarg; - break; - case 'h': - default: - my_Usage (argv[0]); - exit (EXIT_FAILURE); - break; - } - } -} diff --git a/src/lib_GetOpt.cpp b/src/lib_GetOpt.cpp new file mode 100644 index 0000000..bc474e8 --- /dev/null +++ b/src/lib_GetOpt.cpp @@ -0,0 +1,43 @@ +#include "lib_GetOpt.h" + +#include +#include +#include +#include + +static void +common_Usage (const char* argv0) +{ + fprintf (stderr, "Usage: %s [-h] [-s server] [-p port]\n", argv0); +} + + +void +common_GetOpt (int argc, char** argv, Init_CommonOpts* state) +{ + int opt; + state->host = "localhost"; + state->channel = -1; + state->mtu = 1450; + state->port = 6666; + while ((opt = getopt (argc, argv, "hm:p:s:")) != -1) + { + switch (opt) + { + case 'm': + state->mtu = strtol (optarg, NULL, 0); + break; + case 'p': + state->port = strtol (optarg, NULL, 0); + break; + case 's': + state->host = optarg; + break; + case 'h': + default: + common_Usage (argv[0]); + exit (EXIT_FAILURE); + break; + } + } +} diff --git a/src/server_main.cpp b/src/server_main.cpp index dcb29f0..3b55b84 100644 --- a/src/server_main.cpp +++ b/src/server_main.cpp @@ -8,6 +8,7 @@ #include "util.h" #include "Server.h" #include "Commands.h" +#include "lib_GetOpt.h" #include #include @@ -21,16 +22,16 @@ #include /* getopt */ static bool done = false; -static const char* host = NULL; -static Uint16 port = 6666; static const char* prompt_str = "> "; +/* XXX gross */ +static std::vector server_data; +static bool left_shift = false; + static std::unique_ptr server; static bool my_SDL_UserEvent (SDL_Event *); static int my_StdinThread(void*); -static void my_Usage (const char *); -static void my_GetOpt (int, char **); static void my_ProcessPacket (UDPpacket *); static bool my_StdinThread_Helper (const std::string&); static void my_ShowPrompt (void); @@ -38,13 +39,14 @@ static void my_ShowPrompt (void); int main (int argc, char **argv) { + Init_CommonOpts init_opts; SDL_Event ev; - my_GetOpt (argc, argv); + common_GetOpt (argc, argv, &init_opts); common_Signal_Init (); common_SDL_Init (); - server = std::make_unique (host, port); + server = std::make_unique (init_opts.host, init_opts.port); if (server->Start () < 0) { @@ -116,10 +118,6 @@ my_SDL_UserEvent (SDL_Event * ev) /* XXX gross */ -static std::vector server_data; -static bool left_shift = false; - -/* XXX gross */ static void my_ProcessPacket (UDPpacket* packet) { @@ -237,37 +235,6 @@ my_ProcessPacket (UDPpacket* packet) } -static void -my_Usage (const char *argv0) -{ - fprintf (stderr, "Usage: %s [-h] [-s server] [-p port]\n", argv0); -} - - -static void -my_GetOpt (int argc, char **argv) -{ - int opt; - while ((opt = getopt (argc, argv, "hp:s:")) != -1) - { - switch (opt) - { - case 'p': - port = strtol (optarg, NULL, 0); - break; - case 's': - host = optarg; - break; - case 'h': - default: - my_Usage (argv[0]); - exit (EXIT_FAILURE); - break; - } - } -} - - static void my_ShowPrompt (void) { printf ("\n%s", prompt_str); diff --git a/test/test_SafeUDPpacket.cpp b/test/test_SafeUDPpacket.cpp new file mode 100644 index 0000000..095ca47 --- /dev/null +++ b/test/test_SafeUDPpacket.cpp @@ -0,0 +1,11 @@ +#include "SafeUDPpacket.h" + +int main(void) +{ + int size; + size = 1; + UDPpacket* p_ptr; + SafeUDPpacket p (size); + p_ptr = p.get (); + return 0; +} diff --git a/test/test_UDPpacketBufferV.cpp b/test/test_UDPpacketBufferV.cpp index 16d6262..a5d953a 100644 --- a/test/test_UDPpacketBufferV.cpp +++ b/test/test_UDPpacketBufferV.cpp @@ -40,54 +40,54 @@ 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->UDP_Open (0))) { - SDL_Log ("Unable to open client port"); - return -1; - } - if (-1 == (channel = client->UDP_Bind (udpsock, -1))) - { - SDL_Log ("Unable to bind client port"); - return -1; - } + UDPsocket udpsock; - std::string buf; - if (path == "-") - { - try { - std::string line; - while (getline (std::cin, line)) - { - buf += line + "\n"; + common_Signal_Init (); + my_GetOpt (argc, argv); + + common_SDL_Init (); + + client = std::make_unique (host, port); + if (NULL == (udpsock = client->UDP_Open (0))) + { + SDL_Log ("Unable to open client port"); + return -1; + } + if (-1 == (channel = client->UDP_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; } } - catch (std::ifstream::failure& e) { - // std::cout << e << std::endl; + else + { + FileIO f (path, "r"); + buf = f.ReadToString (); } - } - 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->CloseAllSockets (); + 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); + } common_SDL_Quit ();