handmade/src/server_main.cpp
Bubblegumdrop 60e282929f Add a "SafeUDPpacket" and "SafeUDPpacketV" class.
I'm trying to merge UDPpacketVBuffer and SafeUDPpacketV.

Seems pretty messy so far... hopefully this is fruitful.
2022-01-16 14:40:20 -05:00

313 lines
5.4 KiB
C++

#include "debug.h"
#include "lib_SDL_common.h" /* SDL* */
#include "signal_common.h"
#include "unused.h"
#include "events_common.h"
#include "trim.h"
#include "lib_lua_common.h"
#include "util.h"
#include "Server.h"
#include "Commands.h"
#include "lib_GetOpt.h"
#include <iostream>
#include <fstream>
#include <memory>
#include <string>
#include <vector>
#include <map>
#include <stdlib.h> /* exit */
#include <unistd.h> /* getopt */
#include <getopt.h> /* getopt */
static bool done = false;
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 bool my_SDL_UserEvent (SDL_Event *);
static int my_StdinThread(void*);
static void my_ProcessPacket (UDPpacket *);
static bool my_StdinThread_Helper (const std::string&);
static void my_ShowPrompt (void);
int
main (int argc, char **argv)
{
Init_CommonOpts init_opts;
SDL_Event ev;
common_GetOpt (argc, argv, &init_opts);
common_Signal_Init ();
common_SDL_Init ();
server = std::make_unique<Server> (init_opts.host, init_opts.port);
if (server->Start () < 0)
{
SDL_Log ("Couldn't start server!");
exit (EXIT_FAILURE);
}
done = false;
SDL_Thread* stdin_loop = SDL_CreateThread(my_StdinThread, "my_StdinThread", (void*)NULL);
if (NULL == stdin_loop)
{
error ("SDL_CreateThread failed: %s\n", SDL_GetError());
}
while (!done)
{
SDL_Delay (1);
while (!done && SDL_PollEvent (&ev))
{
switch (ev.type)
{
case SDL_QUIT:
done = true;
break;
case PACKET_SDL_EVENT:
{
done = my_SDL_UserEvent (&ev);
}
break;
default:
break;
}
}
}
server->Stop ();
// server->CloseAllSockets ();
SDL_WaitThread (stdin_loop, NULL);
common_SDL_Quit ();
return 0;
}
static bool
my_SDL_UserEvent (SDL_Event * ev)
{
SDL_assert (NULL != ev);
switch (ev->user.type)
{
case PACKET_SDL_EVENT:
{
UDPpacket* packet = (UDPpacket *) ev->user.data1;
if (packet)
{
// SDL_Log ("PACKET_SDL_EVENT");
my_ProcessPacket (packet);
SDLNet_FreePacket (packet);
}
}
break;
default:
break;
}
return false;
}
/* XXX gross */
static void
my_ProcessPacket (UDPpacket* packet)
{
char c;
size_t len;
SDL_Event event;
if (!packet)
return;
SDL_assert (NULL != packet);
if (!packet->len)
return;
SDL_assert (packet->len > 0);
len = packet->len;
if (len > sizeof (SDL_Event))
len = sizeof (SDL_Event);
SDL_memcpy (&event, packet->data, len);
// SDL_Log ("%d, %x", packet->len, event.type);
if (!((event.type == SDL_KEYDOWN) || (event.type == SDL_KEYUP)))
{
util_UDP_DumpPacket (packet);
return;
}
std::string str = std::string (SDL_GetKeyName (event.key.keysym.sym));
bool down = (event.type == SDL_KEYDOWN);
// SDL_Log ("%d \"%s\"", str.length (), str.c_str ());
/* XXX ultra gross */
if (down)
{
if (str.length () > 1)
{
if (str == "Return")
{
server_data.push_back ('\0');
std::string buf = std::string ((const char*)server_data.data ());
printf ("\n => ");
fflush (stdout);
server->RunLua (buf);
fflush (stdout);
server_data.clear ();
}
else if (str == "Left Shift")
{
left_shift = (bool) true;
}
else if (str == "Space")
{
server_data.push_back (' ');
putchar (' ');
fflush (stdout);
}
else if (str == "Backspace")
{
off_t size = server_data.size () - 1;
if (size < 0)
size = 0;
server_data.resize (size);
printf ("\x08\e[0K");
fflush (stdout);
}
}
else
{
c = tolower (str[0]);
if (isalpha (c))
{
if (left_shift)
c = toupper (c);
}
else if (isdigit (c))
{
const char* sym = ")!@#$%^&*(";
if (left_shift)
c = sym[c - '0'];
}
else
{
if (left_shift)
{
switch (c)
{
case '\'': c = '"'; break;
case ',': c = '<'; break;
case '-': c = '_'; break;
case '.': c = '>'; break;
case '/': c = '?'; break;
case ';': c = ':'; break;
case '=': c = '+'; break;
case '[': c = '{'; break;
case '\\': c = '|'; break;
case ']': c = '}'; break;
case '`': c = '~'; break;
default: break;
}
}
}
server_data.push_back (c);
putchar (c);
fflush (stdout);
}
}
else
{
if (str == "Left Shift")
{
left_shift = (bool) false;
}
}
}
static void my_ShowPrompt (void)
{
printf ("\n%s", prompt_str);
fflush (stdout);
}
/*
* TODO
* Oh boy this would be our main command handler for the server stdin huh? Wowie!
*/
static bool my_StdinThread_Helper (const std::string& buf)
{
std::string argv0 = buf;
std::string args = buf;
auto const& pos = buf.find (' ');
if (pos != std::string::npos)
{
/* command <args> */
argv0 = buf.substr (0, pos);
argv0 = trim (argv0);
args = buf.substr (pos);
}
// SDL_Log ("\"%s\"", argv0.c_str ());
auto const& ref = CommandFunctionList.find (argv0);
if (ref != CommandFunctionList.end ())
{
/* It was found */
return ref->second (args);
}
SDL_Delay (100);
return false;
}
static int my_StdinThread(void* param)
{
std::string buf;
UNUSED (param);
_top:
while (!done)
{
my_ShowPrompt ();
try
{
getline (std::cin, buf);
}
catch (std::ifstream::failure& e)
{
done = true;
}
if (std::cin.bad () || std::cin.eof ())
{
done = true;
goto _out;
}
buf = trim (buf);
if (buf.empty ())
{
goto _top;
}
if ((done = my_StdinThread_Helper (buf)))
{
goto _out;
}
}
_out:
return 0;
}