Add a "SafeUDPpacket" and "SafeUDPpacketV" class.

I'm trying to merge UDPpacketVBuffer and SafeUDPpacketV.

Seems pretty messy so far... hopefully this is fruitful.
This commit is contained in:
Bubblegumdrop 2022-01-16 14:40:20 -05:00
parent dcbd011582
commit 60e282929f
15 changed files with 500 additions and 243 deletions

View File

@ -1,4 +1,4 @@
.PHONY: all clean .PHONY: all clean reallyclean test
.POSIX: .POSIX:
# {{{ Flags # {{{ Flags
@ -27,6 +27,7 @@ OBJS := $(patsubst %,$(OBJDIR)/%.o,$(basename $(SRCS)))
DEPS := $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))) DEPS := $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS)))
COMMON_OBJS := \ COMMON_OBJS := \
$(OBJDIR)/src/lib_GetOpt.o \
$(OBJDIR)/src/lib_lua_common.o \ $(OBJDIR)/src/lib_lua_common.o \
$(OBJDIR)/src/lib_SDL_common.o \ $(OBJDIR)/src/lib_SDL_common.o \
$(OBJDIR)/src/lib_SDL_Log.o \ $(OBJDIR)/src/lib_SDL_Log.o \
@ -186,9 +187,13 @@ $(OBJDIR)/%.o: %.cxx $(DEPDIR)/%.d
$(COMPILE.cc) $< $(COMPILE.cc) $<
$(POSTCOMPILE) $(POSTCOMPILE)
clean: REALLYCLEAN?=@echo
clean: clean:
@echo $(RM) $(DEPDIR) $(OBJDIR) $(PROGS) $(REALLYCLEAN) $(RM) $(DEPDIR) $(OBJDIR) $(PROGS)
@echo $(RM) $(TEST_PROGS) $(REALLYCLEAN) $(RM) $(TEST_PROGS)
reallyclean:
$(MAKE) REALLYCLEAN= clean
.PRECIOUS: $(DEPDIR)/%.d .PRECIOUS: $(DEPDIR)/%.d
$(DEPDIR)/%.d: ; $(DEPDIR)/%.d: ;

99
include/SafeUDPpacket.h Normal file
View File

@ -0,0 +1,99 @@
#pragma once
#include <memory>
#include <string>
#include <vector>
#include <SDL_assert.h>
#include <SDL_net.h>
class SafeUDPpacket
{
struct SDLNet_PacketDeleter
{
void operator () (UDPpacket* p)
{
SDLNet_FreePacket (p);
p = NULL;
}
};
std::unique_ptr<UDPpacket, SDLNet_PacketDeleter> 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<SafeUDPpacket> 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);
};

View File

@ -6,6 +6,9 @@
#include "lib_lua_common.h" #include "lib_lua_common.h"
#include "UDPbase.h" #include "UDPbase.h"
/*
* Used as mFetchPacketsCallbackTimerID timeout
*/
#define DEFAULT_SOCKET_TIMEOUT 10 #define DEFAULT_SOCKET_TIMEOUT 10
class Server : public UDPbase class Server : public UDPbase

View File

@ -5,32 +5,53 @@
#include <SDL_net.h> #include <SDL_net.h>
#define DEFAULT_MAX_PACKET_SIZE 250 #define DEFAULT_MAX_PACKET_SIZE 512
class UDPbase class
UDPbase
{ {
int mChannel; int mChannel;
IPaddress mIPAddress; IPaddress mIPAddress;
void
CloseAllSockets (void);
protected: protected:
std::vector<UDPsocket> UDPsocks; std::vector<UDPsocket> UDPsocks;
public: public:
UDPbase (const char* host, const Uint16 port); UDPbase (const char *host, const Uint16 port);
UDPbase (const char* host, const Uint16 port, const int channel); UDPbase (const char *host, const Uint16 port, const int channel);
~UDPbase (void); ~UDPbase (void);
int ResolveHost (IPaddress*, const char*, const Uint16); int
ResolveHost (IPaddress *, const char *, const Uint16);
UDPsocket UDP_Open (void); UDPsocket
UDPsocket UDP_Open (const Uint16 port); UDP_Open (void);
void UDP_Close (UDPsocket sock); UDPsocket
int UDP_Bind (UDPsocket sock, const int channel); UDP_Open (const Uint16 port);
void UDP_Unbind (UDPsocket sock, const int channel); void
IPaddress* UDP_GetPeerAddress (UDPsocket sock, const int channel); 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; } std::string
UDPsocket getSocket (const size_t idx) const { return UDPsocks.at (idx); } toString (void);
std::string toString (void);
}; };

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <string>
#include <SDL_net.h> #include <SDL_net.h>
/** /**
@ -36,25 +37,26 @@ Then free the leftover setup packet:
*/ */
class UDPpacketVBuffer class UDPpacketVBuffer
{ {
int npackets; int m_howmany;
UDPpacket** packetV; UDPpacket** m_packetV;
public: public:
UDPpacketVBuffer (UDPpacket* src, const void* buf, const size_t size); UDPpacketVBuffer (UDPpacket* src, const void* buf, const size_t size);
~UDPpacketVBuffer (void) ~UDPpacketVBuffer (void)
{ {
if (packetV) if (m_packetV)
{ {
SDLNet_FreePacketV (packetV); SDLNet_FreePacketV (m_packetV);
packetV = NULL; m_packetV = NULL;
} }
} }
int Send (UDPsocket sock) int Send (UDPsocket sock)
{ {
int numsent = 0; 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; return numsent;
} }
std::string Reassemble (void);
}; };

11
include/lib_GetOpt.h Normal file
View File

@ -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*);

View File

@ -26,15 +26,16 @@ bool command_Echo (const std::string& args)
bool command_Shell (const std::string& args) bool command_Shell (const std::string& args)
{ {
int rc; char output[8192];
if (args.empty ()) FILE *fp;
if (!args.empty ())
{ {
} if ((fp = popen (args.c_str (), "r")))
else
{
c = system (args.c_str ());
switch (rc)
{ {
while (fgets (output, (sizeof output) - 1, fp) != NULL) {
printf ("%s", output);
}
pclose (fp);
} }
} }

76
src/SafeUDPpacket.cpp Normal file
View File

@ -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;
}

View File

@ -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 ... * 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. * 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) if (packetV)
{ {
SDLNet_FreePacketV (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 ()); SDL_Log ("SDLNet_AllocPacketV: %s", SDLNet_GetError ());
return -1; return -1;
@ -215,6 +220,12 @@ Uint32 Server::FetchPacketsCallback (Uint32 interval, void *param)
* TODO fix this wait timeout blocking issue * TODO fix this wait timeout blocking issue
* *
* I want this to block, but also to be stoppable. * 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); numready = SDLNet_CheckSockets (server->getSocketSet (), (1000 * DEFAULT_SOCKET_TIMEOUT / 3) / 1000);
if (numready < 0) if (numready < 0)

View File

@ -13,10 +13,10 @@ UDPpacketVBuffer::UDPpacketVBuffer (UDPpacket* src, const void* buf, const size_
mtu = src->len; mtu = src->len;
SDL_assert (mtu > 0); SDL_assert (mtu > 0);
npackets = (int) ceil ((double) size / (double) mtu); m_howmany = (int) ceil ((double) size / (double) mtu);
// SDL_Log ("%d", npackets); // 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 ()); throw "SDLNet_AllocPacketV: " + std::string (SDLNet_GetError ());
} }
@ -25,7 +25,7 @@ UDPpacketVBuffer::UDPpacketVBuffer (UDPpacket* src, const void* buf, const size_
nsent = size; nsent = size;
bufPtr = (const uint8_t*) buf; bufPtr = (const uint8_t*) buf;
bufPtrEnd = bufPtr + size; bufPtrEnd = bufPtr + size;
while ((i < npackets) && (bufPtr < bufPtrEnd) && (nsent > 0)) while ((i < m_howmany) && (bufPtr < bufPtrEnd) && (nsent > 0))
{ {
len = nsent; len = nsent;
if (len > mtu) 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, /* SDLNet_UDP_Send sets the channel in the argument,
* this one takes it implicitly from the source UDPpacket. * this one takes it implicitly from the source UDPpacket.
* Set it for all packets in the vector. */ * 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 */ /* 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 */ /* But only memcpy in the relevant bits */
SDL_memcpy (packetV[i]->data, bufPtr, len); SDL_memcpy (m_packetV[i]->data, bufPtr, len);
packetV[i]->len = len; m_packetV[i]->len = len;
/* probably don't need maxlen or status set after this */ /* probably don't need maxlen or status set after this */
packetV[i]->maxlen = size; m_packetV[i]->maxlen = size;
packetV[i]->status = 0; m_packetV[i]->status = 0;
/* But we will want the destination address of this packet */ /* But we will want the destination address of this packet */
packetV[i]->address = src->address; m_packetV[i]->address = src->address;
/* Advance */ /* Advance */
bufPtr += len; bufPtr += len;
nsent -= len; nsent -= len;
i++; 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;
}

View File

@ -11,6 +11,7 @@
#include "UDPbase.h" #include "UDPbase.h"
#include "UDPpacketVBuffer.h" #include "UDPpacketVBuffer.h"
#include "events_common.h" #include "events_common.h"
#include "lib_GetOpt.h"
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -33,11 +34,9 @@ static bool my_Input (SDL_Event*);
static bool my_SDL_UserEvent (SDL_Event*); static bool my_SDL_UserEvent (SDL_Event*);
static bool my_SDL_WindowEvent (SDL_Event*); static bool my_SDL_WindowEvent (SDL_Event*);
static void my_GetOpt (int, char**);
static void my_Init (int, char**); static void my_Init (int, char**);
static void my_Render (void); static void my_Render (void);
static void my_UpdateValues (void); static void my_UpdateValues (void);
static void my_Usage (const char*);
struct Uniform_Values struct Uniform_Values
{ {
@ -56,16 +55,19 @@ struct Uniform_Values
struct Client_State struct Client_State
{ {
Init_CommonOpts init_opts;
const char* host;
int channel;
int mtu;
Uint16 port;
bool done; bool done;
Uint64 start, end; Uint64 start, end;
double diff; double diff;
UDPsocket udpsock; UDPsocket udpsock;
const char* host;
Uint16 port;
int channel;
int mtu;
SDL_GLContext GLContext; SDL_GLContext GLContext;
SDL_Window* Window; SDL_Window* Window;
@ -86,7 +88,6 @@ struct Client_State
static std::unique_ptr<Cube> cube; static std::unique_ptr<Cube> cube;
static std::unique_ptr<Quad> quad; static std::unique_ptr<Quad> quad;
static std::unique_ptr<ShaderProgram> shader; static std::unique_ptr<ShaderProgram> shader;
static std::unique_ptr<UDPbase> client;
static Camera camera; static Camera camera;
static struct Client_State state; static struct Client_State state;
@ -95,87 +96,94 @@ static struct Uniform_Values values;
int int
main (int argc, char** argv) main (int argc, char** argv)
{ {
glm::mat4 model, view, projection;
SDL_Event event;
my_Init (argc, argv);
shader = std::make_unique<ShaderProgram> ("./glsl/camera.v.glsl", "", "./glsl/new.f.glsl");
if (!shader->ID)
{ {
SDL_Log ("Unable to load shader."); glm::mat4 model, view, projection;
goto _out; SDL_Event event;
} std::unique_ptr<UDPbase> client;
camera = Camera (); my_Init (argc, argv);
values.iResolution.x = state.Window_Width;
values.iResolution.y = state.Window_Height;
values.iResolution.z = 1.0;
cube = std::make_unique<Cube> (1); shader = std::make_unique<ShaderProgram> ("./glsl/camera.v.glsl", "", "./glsl/new.f.glsl");
quad = std::make_unique<Quad> (1); if (!shader->ID)
{
state.mtu = 1450; SDL_Log ("Unable to load shader.");
state.done = false; goto _out;
client = std::make_unique<UDPbase> (state.host, state.port, state.channel); }
if (NULL == (state.udpsock = client->getSocket (0)))
{ camera = Camera ();
SDL_Log ("Unable to open client port"); values.iResolution.x = state.Window_Width;
goto _out; values.iResolution.y = state.Window_Height;
} values.iResolution.z = 1.0;
if (-1 == (state.channel = client->getChannel ()))
{ cube = std::make_unique<Cube> (1);
SDL_Log ("Unable to bind client port"); quad = std::make_unique<Quad> (1);
goto _out;
} state.done = false;
while (!state.done) /* XXX is this okay? We are using C++ after all.. inheritance time */
{ state.mtu = state.init_opts.mtu;
state.end = SDL_GetPerformanceCounter (); state.host = state.init_opts.host;
state.diff = Perf_Diff (state.start, state.end); state.channel = state.init_opts.channel;
while (state.diff < MIN_FRAME_MS) state.port = state.init_opts.port;
client = std::make_unique<UDPbase> (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.end = SDL_GetPerformanceCounter ();
state.diff = Perf_Diff (state.start, state.end); 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: _out:
client->CloseAllSockets ();
SDL_GL_DeleteContext (state.GLContext); SDL_GL_DeleteContext (state.GLContext);
SDL_DestroyWindow (state.Window); SDL_DestroyWindow (state.Window);
common_SDL_Quit (); common_SDL_Quit ();
@ -188,7 +196,8 @@ static void
my_Init (int argc, char** argv) my_Init (int argc, char** argv)
{ {
common_Signal_Init (); common_Signal_Init ();
my_GetOpt (argc, argv);
common_GetOpt (argc, argv, &state.init_opts);
state.start = state.end = SDL_GetPerformanceCounter (); state.start = state.end = SDL_GetPerformanceCounter ();
@ -314,7 +323,7 @@ my_Input (SDL_Event* event)
case SHADER_PROGRAM_REFRESH: case SHADER_PROGRAM_REFRESH:
my_SDL_UserEvent (event); my_SDL_UserEvent (event);
break; break;
break; break;
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
my_SDL_WindowEvent (event); my_SDL_WindowEvent (event);
break; break;
@ -467,7 +476,8 @@ my_SDL_UserEvent (SDL_Event* event)
SDL_Log ("SHADER_PROGRAM_REFRESH"); SDL_Log ("SHADER_PROGRAM_REFRESH");
/* Actually do the refresh */ /* Actually do the refresh */
GLuint id; GLuint id;
try { try
{
id = shader->Compile3ShaderBuffers (shader->getVertexPath (), shader->getGeometryPath (), shader->getFragmentPath ()); id = shader->Compile3ShaderBuffers (shader->getVertexPath (), shader->getGeometryPath (), shader->getFragmentPath ());
} }
catch (const std::string& e) catch (const std::string& e)
@ -510,37 +520,3 @@ my_SDL_WindowEvent (SDL_Event* event)
} }
return done; 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;
}
}
}

43
src/lib_GetOpt.cpp Normal file
View File

@ -0,0 +1,43 @@
#include "lib_GetOpt.h"
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
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;
}
}
}

View File

@ -8,6 +8,7 @@
#include "util.h" #include "util.h"
#include "Server.h" #include "Server.h"
#include "Commands.h" #include "Commands.h"
#include "lib_GetOpt.h"
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
@ -21,16 +22,16 @@
#include <getopt.h> /* getopt */ #include <getopt.h> /* getopt */
static bool done = false; static bool done = false;
static const char* host = NULL;
static Uint16 port = 6666;
static const char* prompt_str = "> "; static const char* prompt_str = "> ";
/* XXX gross */
static std::vector<char> server_data;
static bool left_shift = false;
static std::unique_ptr<Server> server; static std::unique_ptr<Server> server;
static bool my_SDL_UserEvent (SDL_Event *); static bool my_SDL_UserEvent (SDL_Event *);
static int my_StdinThread(void*); static int my_StdinThread(void*);
static void my_Usage (const char *);
static void my_GetOpt (int, char **);
static void my_ProcessPacket (UDPpacket *); static void my_ProcessPacket (UDPpacket *);
static bool my_StdinThread_Helper (const std::string&); static bool my_StdinThread_Helper (const std::string&);
static void my_ShowPrompt (void); static void my_ShowPrompt (void);
@ -38,13 +39,14 @@ static void my_ShowPrompt (void);
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
Init_CommonOpts init_opts;
SDL_Event ev; SDL_Event ev;
my_GetOpt (argc, argv); common_GetOpt (argc, argv, &init_opts);
common_Signal_Init (); common_Signal_Init ();
common_SDL_Init (); common_SDL_Init ();
server = std::make_unique<Server> (host, port); server = std::make_unique<Server> (init_opts.host, init_opts.port);
if (server->Start () < 0) if (server->Start () < 0)
{ {
@ -116,10 +118,6 @@ my_SDL_UserEvent (SDL_Event * ev)
/* XXX gross */ /* XXX gross */
static std::vector<char> server_data;
static bool left_shift = false;
/* XXX gross */
static void static void
my_ProcessPacket (UDPpacket* packet) 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) static void my_ShowPrompt (void)
{ {
printf ("\n%s", prompt_str); printf ("\n%s", prompt_str);

View File

@ -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;
}

View File

@ -40,54 +40,54 @@ static std::unique_ptr<UDPbase> client;
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
UDPsocket udpsock;
common_Signal_Init ();
my_GetOpt (argc, argv);
common_SDL_Init ();
client = std::make_unique<UDPbase> (host, port);
if (NULL == (udpsock = client->UDP_Open (0)))
{ {
SDL_Log ("Unable to open client port"); UDPsocket udpsock;
return -1;
}
if (-1 == (channel = client->UDP_Bind (udpsock, -1)))
{
SDL_Log ("Unable to bind client port");
return -1;
}
std::string buf; common_Signal_Init ();
if (path == "-") my_GetOpt (argc, argv);
{
try { common_SDL_Init ();
std::string line;
while (getline (std::cin, line)) client = std::make_unique<UDPbase> (host, port);
{ if (NULL == (udpsock = client->UDP_Open (0)))
buf += line + "\n"; {
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) { else
// std::cout << e << std::endl; {
FileIO f (path, "r");
buf = f.ReadToString ();
} }
}
else
{
FileIO f (path, "r");
buf = f.ReadToString ();
}
UDPpacket* packet = SDLNet_AllocPacket (buf.length ()); UDPpacket* packet = SDLNet_AllocPacket (buf.length ());
IPaddress* addr = SDLNet_UDP_GetPeerAddress (udpsock, channel); IPaddress* addr = SDLNet_UDP_GetPeerAddress (udpsock, channel);
packet->len = DEFAULT_MAX_PACKET_SIZE; packet->len = DEFAULT_MAX_PACKET_SIZE;
packet->address = *addr; packet->address = *addr;
packet->channel = channel; packet->channel = channel;
UDPpacketVBuffer packetV (packet, &buf[0], buf.length ()); UDPpacketVBuffer packetV (packet, &buf[0], buf.length ());
packetV.Send (udpsock); packetV.Send (udpsock);
}
client->CloseAllSockets ();
common_SDL_Quit (); common_SDL_Quit ();