From e3e6a3f2c422a6b82b234f575a6b3bad459e5e0b Mon Sep 17 00:00:00 2001 From: Treeki Date: Wed, 22 Jan 2014 09:31:30 +0100 Subject: add window management, move hacky Python client over to PyQt5 --- build.sh | 2 +- core.h | 60 +++++++++++++++- ircserver.cpp | 24 +++++-- mobileclient.cpp | 38 ++++++---- netcore.cpp | 49 +++++++++++++ python_client.py | 206 +++++++++++++++++++++++++++++++++++++++++++++---------- socketcommon.cpp | 2 +- window.cpp | 79 +++++++++++++++++++++ 8 files changed, 397 insertions(+), 63 deletions(-) create mode 100644 window.cpp diff --git a/build.sh b/build.sh index 2bfdfb3..72a77af 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ mkdir -p binary NETCODE="socketcommon.cpp client.cpp mobileclient.cpp server.cpp ircserver.cpp netcore.cpp" -SOURCES="$NETCODE main.cpp dns.cpp" +SOURCES="$NETCODE main.cpp window.cpp dns.cpp" FLAGS="-std=c++11 -lgnutls -pthread -g" g++ -o binary/nb4 $FLAGS $SOURCES diff --git a/core.h b/core.h index 4037f25..3d9fba6 100644 --- a/core.h +++ b/core.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "buffer.h" @@ -31,6 +32,39 @@ class NetCore; class Bouncer; +class IRCServer; + + +class Window { +public: + NetCore *core; + + Window(NetCore *_core); + virtual ~Window() { } + + int id; + std::list messages; + + virtual const char *getTitle() const = 0; + virtual int getType() const = 0; + virtual void syncStateForClient(Buffer &output); + virtual void handleUserInput(const char *str) { } + + void pushMessage(const char *str); +}; + +class StatusWindow : public Window { +public: + StatusWindow(IRCServer *_server); + + IRCServer *server; + + virtual const char *getTitle() const; + virtual int getType() const; + virtual void handleUserInput(const char *str); +}; + + class SocketRWCommon { public: @@ -80,6 +114,12 @@ struct Packet { C2B_COMMAND = 1, B2C_STATUS = 1, + B2C_WINDOW_ADD = 0x100, + B2C_WINDOW_REMOVE = 0x101, + B2C_WINDOW_MESSAGE = 0x102, + + C2B_WINDOW_INPUT = 0x102, + C2B_OOB_LOGIN = 0x8001, B2C_OOB_LOGIN_SUCCESS = 0x8001, @@ -160,7 +200,7 @@ class Server : private SocketRWCommon { public: Server(NetCore *_netCore); - ~Server(); + virtual ~Server(); protected: void connect(const char *hostname, int _port, bool _useTls); @@ -174,10 +214,11 @@ private: void connectionSuccessful(); void processReadBuffer(); -private: virtual void connectedEvent() = 0; virtual void disconnectedEvent() = 0; virtual void lineReceivedEvent(char *line, int size) = 0; + + virtual void attachedToCore() { } }; struct IRCNetworkConfig { @@ -191,11 +232,15 @@ struct IRCNetworkConfig { }; class IRCServer : public Server { - Bouncer *bouncer; public: + Bouncer *bouncer; + + StatusWindow status; + IRCNetworkConfig config; IRCServer(Bouncer *_bouncer); + ~IRCServer(); void connect(); @@ -204,6 +249,8 @@ private: virtual void connectedEvent(); virtual void disconnectedEvent(); virtual void lineReceivedEvent(char *line, int size); + + virtual void attachedToCore(); }; @@ -216,6 +263,13 @@ public: int clientCount; int serverCount; + std::list windows; + int nextWindowID; + + int registerWindow(Window *window); + void deregisterWindow(Window *window); + Window *findWindow(int id) const; + bool quitFlag; int execute(); diff --git a/ircserver.cpp b/ircserver.cpp index 830c82b..f2189b2 100644 --- a/ircserver.cpp +++ b/ircserver.cpp @@ -1,16 +1,29 @@ #include "core.h" -IRCServer::IRCServer(Bouncer *_bouncer) : Server(_bouncer) { - bouncer = _bouncer; +IRCServer::IRCServer(Bouncer *_bouncer) : + Server(_bouncer), + bouncer(_bouncer), + status(this) +{ +} + +IRCServer::~IRCServer() { + bouncer->deregisterWindow(&status); +} + +void IRCServer::attachedToCore() { + bouncer->registerWindow(&status); } void IRCServer::connect() { + status.pushMessage("Connecting..."); Server::connect(config.hostname, config.port, config.useTls); } void IRCServer::connectedEvent() { printf("[IRCServer:%p] connectedEvent\n", this); + status.pushMessage("Connected, identifying to IRC..."); char buf[2048]; @@ -25,13 +38,10 @@ void IRCServer::connectedEvent() { } void IRCServer::disconnectedEvent() { printf("[IRCServer:%p] disconnectedEvent\n", this); + status.pushMessage("Disconnected."); } void IRCServer::lineReceivedEvent(char *line, int size) { printf("[%d] { %s }\n", size, line); - Buffer pkt; - pkt.writeStr(line, size); - for (int i = 0; i < bouncer->clientCount; i++) - if (bouncer->clients[i]->isAuthed()) - bouncer->clients[i]->sendPacket(Packet::B2C_STATUS, pkt); + status.pushMessage(line); } diff --git a/mobileclient.cpp b/mobileclient.cpp index bbfac73..fb8b3c1 100644 --- a/mobileclient.cpp +++ b/mobileclient.cpp @@ -6,6 +6,18 @@ MobileClient::MobileClient(Bouncer *_bouncer) : Client(_bouncer) { void MobileClient::sessionStartEvent() { printf("{Session started}\n"); + + Buffer syncPacket; + syncPacket.writeU32(bouncer->windows.size()); + + std::list::iterator + i = bouncer->windows.begin(), + e = bouncer->windows.end(); + + for (; i != e; ++i) + (*i)->syncStateForClient(syncPacket); + + sendPacket(Packet::B2C_WINDOW_ADD, syncPacket); } void MobileClient::sessionEndEvent() { printf("{Session ended}\n"); @@ -16,6 +28,19 @@ void MobileClient::packetReceivedEvent(Packet::Type type, Buffer &pkt) { pkt.readStr(cmd, sizeof(cmd)); handleDebugCommand(cmd, strlen(cmd)); + } else if (type == Packet::C2B_WINDOW_INPUT) { + int winID = pkt.readU32(); + Window *window = bouncer->findWindow(winID); + if (!window) { + printf("[MobileClient:%p] Message for unknown window %d\n", this, winID); + return; + } + + char text[8192]; + pkt.readStr(text, sizeof(text)); + + window->handleUserInput(text); + } else { printf("[MobileClient:%p] Unrecognised packet for MobileClient: type %d, size %d\n", this, type, pkt.size()); @@ -47,19 +72,6 @@ void MobileClient::handleDebugCommand(char *line, int size) { pkt.writeStr("Your wish is my command!"); for (int i = 0; i < bouncer->clientCount; i++) bouncer->clients[i]->sendPacket(Packet::B2C_STATUS, pkt); - - } else if (strncmp(line, "srvpw", 5) == 0) { - int sid = line[5] - '0'; - // ugly hack, fuck casting, will fix later - strcpy(((IRCServer*)bouncer->servers[sid])->config.password, &line[7]); - - } else if (strncmp(line, "connsrv", 7) == 0) { - int sid = line[7] - '0'; - // ugly hack, fuck casting, will fix later - ((IRCServer*)bouncer->servers[sid])->connect(); - } else if (line[0] >= '0' && line[0] <= '9') { - int sid = line[0] - '0'; - bouncer->servers[sid]->sendLine(&line[1]); } } diff --git a/netcore.cpp b/netcore.cpp index 27769a6..4341787 100644 --- a/netcore.cpp +++ b/netcore.cpp @@ -8,6 +8,8 @@ NetCore::NetCore() { serverCount = 0; for (int i = 0; i < SERVER_LIMIT; i++) servers[i] = NULL; + + nextWindowID = 1; } Client *NetCore::findClientWithSessionKey(uint8_t *key) const { @@ -24,6 +26,7 @@ int NetCore::registerServer(Server *server) { int id = serverCount++; servers[id] = server; + server->attachedToCore(); return id; } void NetCore::deregisterServer(int id) { @@ -251,8 +254,54 @@ int NetCore::execute() { } + +int NetCore::registerWindow(Window *window) { + window->id = nextWindowID; + nextWindowID++; + + windows.push_back(window); + + + Buffer pkt; + pkt.writeU32(1); + window->syncStateForClient(pkt); + + for (int i = 0; i < clientCount; i++) + if (clients[i]->isAuthed()) + clients[i]->sendPacket(Packet::B2C_WINDOW_ADD, pkt); +} + +void NetCore::deregisterWindow(Window *window) { + Buffer pkt; + pkt.writeU32(1); + pkt.writeU32(window->id); + + for (int i = 0; i < clientCount; i++) + if (clients[i]->isAuthed()) + clients[i]->sendPacket(Packet::B2C_WINDOW_REMOVE, pkt); + + windows.remove(window); +} + +Window *NetCore::findWindow(int id) const { + std::list::const_iterator + i = windows.begin(), + e = windows.end(); + + for (; i != e; ++i) + if ((*i)->id == id) + return *i; + + return 0; +} + + + + Client *Bouncer::constructClient() { return new MobileClient(this); } + + diff --git a/python_client.py b/python_client.py index 24c8a3e..88ac307 100644 --- a/python_client.py +++ b/python_client.py @@ -1,4 +1,9 @@ -import socket, ssl, threading, struct +# Yes, this source code is terrible. +# It's just something I've put together to test the server +# before I write a *real* client. + +import sys, socket, ssl, threading, struct +from PyQt5 import QtCore, QtGui, QtWidgets protocolVer = 1 sock = None @@ -9,6 +14,8 @@ lastReceivedPacketID = 0 packetCache = [] packetLock = threading.Lock() +u32 = struct.Struct(' 0) { - printf("[fd=%d] Wrote %d bytes\n", sock, amount); + printf("[fd=%d] Wrote %d bytes out of %d\n", sock, amount, outputBuf.size()); outputBuf.trimFromStart(amount); } else if (amount == 0) printf("Sent 0!\n"); diff --git a/window.cpp b/window.cpp new file mode 100644 index 0000000..5fc094a --- /dev/null +++ b/window.cpp @@ -0,0 +1,79 @@ +#include "core.h" + +Window::Window(NetCore *_core) { + core = _core; +} + +void Window::syncStateForClient(Buffer &output) { + output.writeU32(getType()); + output.writeU32(id); + output.writeStr(getTitle()); + + output.writeU32(messages.size()); + + std::list::iterator + i = messages.begin(), + e = messages.end(); + + for (; i != e; ++i) { + output.writeStr(i->c_str()); + } +} + +void Window::pushMessage(const char *str) { + messages.push_back(str); + + bool createdPacket = false; + Buffer packet; + + for (int i = 0; i < core->clientCount; i++) { + if (core->clients[i]->isAuthed()) { + if (!createdPacket) { + packet.writeU32(id); + packet.writeStr(str); + createdPacket = true; + } + + core->clients[i]->sendPacket(Packet::B2C_WINDOW_MESSAGE, packet); + } + } +} + + + + +StatusWindow::StatusWindow(IRCServer *_server) : + Window(_server->bouncer) +{ + server = _server; +} + +const char *StatusWindow::getTitle() const { + return server->config.hostname; +} + +int StatusWindow::getType() const { + return 1; +} + +void StatusWindow::handleUserInput(const char *str) { + if (str[0] == '/') { + // moof + if (strcmp(str, "/connect") == 0) { + server->connect(); + } else if (strcmp(str, "/disconnect") == 0) { + server->close(); + } else if (strncmp(str, "/password ", 10) == 0) { + pushMessage("Password set."); + + // This is ugly, ugh + strncpy( + server->config.password, + &str[10], + sizeof(server->config.password)); + server->config.password[sizeof(server->config.password) - 1] = 0; + } + } else { + server->sendLine(str); + } +} -- cgit v1.2.3