From a9afbebbc3ef29e3912e003b66adeee7b8371cea Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Thu, 14 Oct 2021 15:51:38 -0400 Subject: [PATCH] Add LpxClient/LpxServer stubs, add dispatcher to main --- luprex/core/Makefile | 3 + luprex/core/cpp/drivenengine.hpp | 3 + luprex/core/cpp/drivertests.cpp | 141 +++++++++++++++++++++++++++ luprex/core/cpp/drivertests.hpp | 12 +++ luprex/core/cpp/lpxclient.cpp | 38 ++++++++ luprex/core/cpp/lpxclient.hpp | 8 ++ luprex/core/cpp/lpxserver.cpp | 30 ++++++ luprex/core/cpp/lpxserver.hpp | 9 ++ luprex/core/cpp/main.cpp | 158 ++++++++----------------------- luprex/core/cpp/textgame.cpp | 34 ++++++- luprex/core/cpp/textgame.hpp | 31 +----- 11 files changed, 315 insertions(+), 152 deletions(-) create mode 100644 luprex/core/cpp/drivertests.cpp create mode 100644 luprex/core/cpp/drivertests.hpp create mode 100644 luprex/core/cpp/lpxclient.cpp create mode 100644 luprex/core/cpp/lpxclient.hpp create mode 100644 luprex/core/cpp/lpxserver.cpp create mode 100644 luprex/core/cpp/lpxserver.hpp diff --git a/luprex/core/Makefile b/luprex/core/Makefile index 3ab3fe2b..1b571578 100644 --- a/luprex/core/Makefile +++ b/luprex/core/Makefile @@ -28,6 +28,9 @@ CPP_FILES=\ cpp/world-pairtab.cpp\ cpp/world-testing.cpp\ cpp/textgame.cpp\ + cpp/lpxserver.cpp\ + cpp/lpxclient.cpp\ + cpp/drivertests.cpp\ cpp/main.cpp OBJ_FILES=$(patsubst cpp/%.cpp,obj/%.o,$(CPP_FILES)) diff --git a/luprex/core/cpp/drivenengine.hpp b/luprex/core/cpp/drivenengine.hpp index 061049f8..15580d60 100644 --- a/luprex/core/cpp/drivenengine.hpp +++ b/luprex/core/cpp/drivenengine.hpp @@ -409,4 +409,7 @@ private: friend class Channel; }; +using UniqueDrivenEngine = std::unique_ptr; +using DrivenEngineMaker = UniqueDrivenEngine (*)(); + #endif // DRIVENENGINE_HPP diff --git a/luprex/core/cpp/drivertests.cpp b/luprex/core/cpp/drivertests.cpp new file mode 100644 index 00000000..86433a0d --- /dev/null +++ b/luprex/core/cpp/drivertests.cpp @@ -0,0 +1,141 @@ +#include "drivertests.hpp" +#include "drivenengine.hpp" +#include +#include + +static void write_closed_message(Channel *ch, StreamBuffer *out) { + std::ostringstream oss; + oss << "Chan " << ch->chid() << " closed [" << ch->error() << "]\n"; + out->write_bytes(oss.str()); +} + +static void dump_lines(StreamBuffer *in, StreamBuffer *out, int chid) { + while (true) { + std::string l = in->readline(); + if (l == "") break; + std::ostringstream oss; + oss << "Chan " << chid << ": " << l; + out->write_bytes(oss.str()); + } +} + +// This test allows input on stdin or on port 8085. +// You can type lines and see them echoed. +class DriverListenTest : public DrivenEngine { +public: + std::vector channels_; + virtual void event_init() { + listen_port(8085); + } + + virtual void event_update() { + while (true) { + UniqueChannel ch = new_incoming_channel(); + if (ch == nullptr) break; + ch->set_readline(true); + channels_.emplace_back(std::move(ch)); + } + + Channel *stdioch = get_stdio_channel(); + dump_lines(stdioch->in(), stdioch->out(), 0); + std::vector keep; + for (UniqueChannel &ch : channels_) { + dump_lines(ch->in(), stdioch->out(), ch->chid()); + if (ch->closed()) { + write_closed_message(ch.get(), stdioch->out()); + } else { + keep.emplace_back(std::move(ch)); + } + } + channels_ = std::move(keep); + } +}; + +// This test connects to a public webserver and prints +// the output from the server. +class DriverWebServerTest : public DrivenEngine { +public: + std::vector channels_; + virtual void event_init() { + UniqueChannel ch = new_outgoing_channel("stanford.edu:80"); + ch->out()->write_bytes("GET http://stanford.edu/index.html HTTP/1.1\n\n"); + channels_.emplace_back(std::move(ch)); + } + + virtual void event_update() { + Channel *stdioch = get_stdio_channel(); + dump_lines(stdioch->in(), stdioch->out(), 0); + std::vector keep; + for (UniqueChannel &ch : channels_) { + dump_lines(ch->in(), stdioch->out(), ch->chid()); + if (ch->closed()) { + write_closed_message(ch.get(), stdioch->out()); + } else { + keep.emplace_back(std::move(ch)); + } + } + channels_ = std::move(keep); + } +}; + +// This test produces a DNS resolution failure. +class DriverDNSFailTest : public DrivenEngine { +public: + std::vector channels_; + virtual void event_init() { + UniqueChannel ch = new_outgoing_channel("akjsdkajshdakjshd.alk:80"); + ch->out()->write_bytes("GET http://stanford.edu/index.html HTTP/1.1\n\n"); + channels_.emplace_back(std::move(ch)); + } + + virtual void event_update() { + Channel *stdioch = get_stdio_channel(); + dump_lines(stdioch->in(), stdioch->out(), 0); + std::vector keep; + for (UniqueChannel &ch : channels_) { + dump_lines(ch->in(), stdioch->out(), ch->chid()); + if (ch->closed()) { + write_closed_message(ch.get(), stdioch->out()); + } else { + keep.emplace_back(std::move(ch)); + } + } + channels_ = std::move(keep); + } +}; + +// This test just prints the time. +class DriverPrintClockTest : public DrivenEngine { +public: + int count; + virtual void event_init() { + count = 0; + } + + virtual void event_update() { + std::cerr << std::fixed << std::setprecision(2) << get_clock() << " "; + count++; + if (count == 10) { + std::cerr << std::endl; + count = 0; + } + } +}; + +UniqueDrivenEngine make_DriverListenTest() { + return UniqueDrivenEngine(new DriverListenTest); +} + +UniqueDrivenEngine make_DriverWebServerTest() { + return UniqueDrivenEngine(new DriverWebServerTest); +} + +UniqueDrivenEngine make_DriverDNSFailTest() { + return UniqueDrivenEngine(new DriverDNSFailTest); +} + +UniqueDrivenEngine make_DriverPrintClockTest() { + return UniqueDrivenEngine(new DriverPrintClockTest); +} + + diff --git a/luprex/core/cpp/drivertests.hpp b/luprex/core/cpp/drivertests.hpp new file mode 100644 index 00000000..c7321af7 --- /dev/null +++ b/luprex/core/cpp/drivertests.hpp @@ -0,0 +1,12 @@ +#ifndef DRIVERTESTS_HPP +#define DRIVERTESTS_HPP + +#include "drivenengine.hpp" + +UniqueDrivenEngine make_DriverListenTest(); +UniqueDrivenEngine make_DriverWebServerTest(); +UniqueDrivenEngine make_DriverDNSFailTest(); +UniqueDrivenEngine make_DriverPrintClockTest(); + +#endif // DRIVERTESTS_HPP + diff --git a/luprex/core/cpp/lpxclient.cpp b/luprex/core/cpp/lpxclient.cpp new file mode 100644 index 00000000..2271ecbf --- /dev/null +++ b/luprex/core/cpp/lpxclient.cpp @@ -0,0 +1,38 @@ +#include "lpxclient.hpp" + +#include "drivenengine.hpp" +#include "world.hpp" +#include "luaconsole.hpp" +#include "invocation.hpp" +#include + +class LpxClient : public DrivenEngine { +public: + using StringVec = LuaConsole::StringVec; + std::unique_ptr world_; + int64_t actor_id_; + InvocationQueue unack_; + Channel *channel_; + LuaConsole console_; + Gui gui_; + int64_t gui_place_; + + void do_view_command(const StringVec &cmd); + void do_menu_command(const StringVec &cmd); + void do_choose_command(const StringVec &cmd); + void do_quit_command(const StringVec &cmd); + void do_lua(const std::string &exp); + void do_command(const StringVec &exp); + +public: + virtual void event_init() { + } + + virtual void event_update() { + } +}; + +UniqueDrivenEngine make_LpxClient() { + return UniqueDrivenEngine(new LpxClient); +} + diff --git a/luprex/core/cpp/lpxclient.hpp b/luprex/core/cpp/lpxclient.hpp new file mode 100644 index 00000000..b590eb09 --- /dev/null +++ b/luprex/core/cpp/lpxclient.hpp @@ -0,0 +1,8 @@ +#ifndef LPXCLIENT_HPP +#define LPXCLIENT_HPP + +#include "drivenengine.hpp" + +UniqueDrivenEngine make_LpxClient(); + +#endif // LPXCLIENT_HPP diff --git a/luprex/core/cpp/lpxserver.cpp b/luprex/core/cpp/lpxserver.cpp new file mode 100644 index 00000000..8b0fb37b --- /dev/null +++ b/luprex/core/cpp/lpxserver.cpp @@ -0,0 +1,30 @@ +#include "lpxserver.hpp" + +#include "world.hpp" +#include "drivenengine.hpp" +#include + +class ServerClient { +public: + int64_t actor_id_; + Channel *channel_; + std::unique_ptr sync_; +}; + +class LpxServer : public DrivenEngine { +public: + std::unique_ptr master_; + std::vector> clients_; + +public: + virtual void event_init() { + } + + virtual void event_update() { + } +}; + +UniqueDrivenEngine make_LpxServer() { + return UniqueDrivenEngine(new LpxServer); +} + diff --git a/luprex/core/cpp/lpxserver.hpp b/luprex/core/cpp/lpxserver.hpp new file mode 100644 index 00000000..2d44460a --- /dev/null +++ b/luprex/core/cpp/lpxserver.hpp @@ -0,0 +1,9 @@ +#ifndef LPXSERVER_HPP +#define LPXSERVER_HPP + +#include "drivenengine.hpp" + +UniqueDrivenEngine make_LpxServer(); + +#endif // LPXSERVER_HPP + diff --git a/luprex/core/cpp/main.cpp b/luprex/core/cpp/main.cpp index 8b2df45d..38c4af6a 100644 --- a/luprex/core/cpp/main.cpp +++ b/luprex/core/cpp/main.cpp @@ -1,131 +1,47 @@ #include "textgame.hpp" +#include "lpxclient.hpp" +#include "lpxserver.hpp" +#include "drivertests.hpp" #include "driver.hpp" -#include "drivenengine.hpp" #include -#include -void write_closed_message(Channel *ch, StreamBuffer *out) { - std::ostringstream oss; - oss << "Chan " << ch->chid() << " closed [" << ch->error() << "]\n"; - out->write_bytes(oss.str()); +struct EngineMaker { + const char *name; + DrivenEngineMaker func; +}; + +static EngineMaker makers[] = { + { "textgame", make_TextGame }, + { "lpxclient", make_LpxClient }, + { "lpxserver", make_LpxServer }, + { "driverlistentest", make_DriverListenTest }, + { "driverwebservertest", make_DriverWebServerTest }, + { "driverdnsfailtest", make_DriverDNSFailTest }, + { "driverprintclocktest", make_DriverPrintClockTest }, + { nullptr, nullptr }, +}; + +static void usage() { + std::cerr << "Usage: main " << std::endl; + for (int i = 0; makers[i].name != nullptr; i++) { + std::cerr << " can be: " << makers[i].name << std::endl; + } + exit(1); } -void dump_lines(StreamBuffer *in, StreamBuffer *out, int chid) { - while (true) { - std::string l = in->readline(); - if (l == "") break; - std::ostringstream oss; - oss << "Chan " << chid << ": " << l; - out->write_bytes(oss.str()); - } -} - -// This test allows input on stdin or on port 8085. -// You can type lines and see them echoed. -class TNTest1 : public DrivenEngine { -public: - std::vector channels_; - virtual void event_init() { - listen_port(8085); - } - - virtual void event_update() { - while (true) { - UniqueChannel ch = new_incoming_channel(); - if (ch == nullptr) break; - ch->set_readline(true); - channels_.emplace_back(std::move(ch)); - } - - Channel *stdioch = get_stdio_channel(); - dump_lines(stdioch->in(), stdioch->out(), 0); - std::vector keep; - for (UniqueChannel &ch : channels_) { - dump_lines(ch->in(), stdioch->out(), ch->chid()); - if (ch->closed()) { - write_closed_message(ch.get(), stdioch->out()); - } else { - keep.emplace_back(std::move(ch)); - } - } - channels_ = std::move(keep); - } -}; - -// This test connects to a public webserver and prints -// the output from the server. -class TNTest2 : public DrivenEngine { -public: - std::vector channels_; - virtual void event_init() { - UniqueChannel ch = new_outgoing_channel("stanford.edu:80"); - ch->out()->write_bytes("GET http://stanford.edu/index.html HTTP/1.1\n\n"); - channels_.emplace_back(std::move(ch)); - } - - virtual void event_update() { - Channel *stdioch = get_stdio_channel(); - dump_lines(stdioch->in(), stdioch->out(), 0); - std::vector keep; - for (UniqueChannel &ch : channels_) { - dump_lines(ch->in(), stdioch->out(), ch->chid()); - if (ch->closed()) { - write_closed_message(ch.get(), stdioch->out()); - } else { - keep.emplace_back(std::move(ch)); - } - } - channels_ = std::move(keep); - } -}; - -// This test produces a DNS resolution failure. -class TNTest3 : public DrivenEngine { -public: - std::vector channels_; - virtual void event_init() { - UniqueChannel ch = new_outgoing_channel("akjsdkajshdakjshd.alk:80"); - ch->out()->write_bytes("GET http://stanford.edu/index.html HTTP/1.1\n\n"); - channels_.emplace_back(std::move(ch)); - } - - virtual void event_update() { - Channel *stdioch = get_stdio_channel(); - dump_lines(stdioch->in(), stdioch->out(), 0); - std::vector keep; - for (UniqueChannel &ch : channels_) { - dump_lines(ch->in(), stdioch->out(), ch->chid()); - if (ch->closed()) { - write_closed_message(ch.get(), stdioch->out()); - } else { - keep.emplace_back(std::move(ch)); - } - } - channels_ = std::move(keep); - } -}; - -// This test just prints the time. -class TNTest4 : public DrivenEngine { -public: - int count; - virtual void event_init() { - count = 0; - } - - virtual void event_update() { - std::cerr << std::fixed << std::setprecision(2) << get_clock() << " "; - count++; - if (count == 10) { - std::cerr << std::endl; - count = 0; - } - } -}; - int main(int argc, char **argv) { - TextGame tg; - driver_drive(&tg); + UniqueDrivenEngine engine; + if (argc != 2) usage(); + std::string mode = argv[1]; + for (int i = 0; makers[i].name != nullptr; i++) { + if (mode == makers[i].name) { + engine = makers[i].func(); + break; + } + } + if (engine == nullptr) usage(); + driver_drive(engine.get()); } + diff --git a/luprex/core/cpp/textgame.cpp b/luprex/core/cpp/textgame.cpp index 6df69ad3..f9df95ff 100644 --- a/luprex/core/cpp/textgame.cpp +++ b/luprex/core/cpp/textgame.cpp @@ -15,8 +15,37 @@ #include "textgame.hpp" #include "luaconsole.hpp" #include "print.hpp" +#include + + +class TextGame : public DrivenEngine { +private: + using StringVec = LuaConsole::StringVec; + std::unique_ptr world_; + LuaConsole console_; + Gui gui_; + int64_t gui_place_; + int64_t actor_id_; + + void do_view_command(const StringVec &cmd); + void do_menu_command(const StringVec &cmd); + void do_choose_command(const StringVec &cmd); + void do_quit_command(const StringVec &cmd); + void do_snapshot_command(const StringVec &cmd); + void do_rollback_command(const StringVec &cmd); + void do_tick_command(const StringVec &cmd); + + void do_lua(const std::string &exp); + void do_command(const StringVec &exp); + + void check_redirects(); + +public: + virtual void event_init(); + virtual void event_update(); +}; + -// Add another error status. static lua_State *globalL = NULL; @@ -222,3 +251,6 @@ void TextGame::event_update() } } +UniqueDrivenEngine make_TextGame() { + return UniqueDrivenEngine(new TextGame); +} diff --git a/luprex/core/cpp/textgame.hpp b/luprex/core/cpp/textgame.hpp index bdc9ba93..4fa33481 100644 --- a/luprex/core/cpp/textgame.hpp +++ b/luprex/core/cpp/textgame.hpp @@ -2,37 +2,8 @@ #ifndef TEXTGAME_HPP #define TEXTGAME_HPP -#include "luaconsole.hpp" -#include "world.hpp" #include "drivenengine.hpp" -#include -class TextGame : public DrivenEngine { -private: - using StringVec = LuaConsole::StringVec; - std::unique_ptr world_; - LuaConsole console_; - Gui gui_; - int64_t gui_place_; - int64_t actor_id_; - - void do_view_command(const StringVec &cmd); - void do_menu_command(const StringVec &cmd); - void do_choose_command(const StringVec &cmd); - void do_quit_command(const StringVec &cmd); - void do_snapshot_command(const StringVec &cmd); - void do_rollback_command(const StringVec &cmd); - void do_tick_command(const StringVec &cmd); - - void do_lua(const std::string &exp); - void do_command(const StringVec &exp); - - void check_redirects(); - -public: - virtual void event_init(); - virtual void event_update(); -}; +UniqueDrivenEngine make_TextGame(); #endif // TEXTGAME_HPP -