Client and Server communication functionality repaired.

test_UDPpacketVBuffer for testing.
This commit is contained in:
Bubblegumdrop 2022-01-08 23:36:08 -05:00
parent 764ebe4ce2
commit 0cad56c8c6
11 changed files with 308 additions and 108 deletions

View File

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

View File

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

View File

@ -0,0 +1,25 @@
#pragma once
#include <SDL_net.h>
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;
}
};

View File

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

View File

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

55
src/UDPpacketVBuffer.cpp Normal file
View File

@ -0,0 +1,55 @@
#include "UDPpacketVBuffer.h"
#include <string>
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++;
}
}

View File

@ -9,6 +9,7 @@
#include "signal_common.h"
#include "unused.h"
#include "UDPbase.h"
#include "UDPpacketVBuffer.h"
#include <memory>
#include <vector>
@ -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));
}

View File

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

View File

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

View File

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

View File

@ -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 <iostream>
#include <fstream>
#include <memory>
#include <vector>
#include <getopt.h> /* getopt */
#include <stdlib.h> /* exit */
#include <string.h> /* memset */
#include <unistd.h> /* getopt */
#include <glm/vec3.hpp>
#include <glm/gtc/type_ptr.hpp>
#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<UDPbase> client;
int
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->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;
}
}
}