#include "Server.hpp" #include "EpistmoolServer/Protocol/Error.hpp" #include "EpistmoolServer/ServerProperties.hpp" #include #include #include #include #include using namespace Epistmool::Server; // TODO structured error handling similar to messages class Server::Private { public: static bool messageHeader(QJsonObject& msg, SessionId sessionId, int id) { msg.insert("session", sessionId.index); msg.insert("id", id); return true; } static bool messageErrInvalidVersion(QJsonObject& msg) { QJsonObject error; error.insert("type", ProtocolErrors::kUnsupportedVersion.name); error.insert("supportedVersion", ServerProperties::kVersion.toString()); msg.insert("error", error); return true; } }; Server::Server(QObject* parent) : QObject(parent) { mConnectionManager.setLocalConnectionsEnabled(true); connect(&mConnectionManager, &ConnectionManager::messageRecieved, this, &Server::onMessage); connect(&mConnectionManager, &ConnectionManager::connectionDropped, &mSessionManager, &SessionManager::dropConnection); } void Server::onMessage(const QJsonDocument& message, ConnectionId connId) { if (!message.isObject()) return; auto root = message.object(); // Extract as empty string if non-existent auto versionString = root.value("version").toString(); int id = root.value("id").toInt(); SessionId sessionId; if (auto index = root.value("session").toInt(-1); index == -1) { sessionId = SessionId::makeInvalid(); } else { sessionId.index = index; } auto version = [&]() -> QVersionNumber { if (versionString.isEmpty()) { return QVersionNumber(); } else { return QVersionNumber::fromString(versionString).normalized(); } }(); if (version.isNull() || version >= ServerProperties::kVersion) { qWarning() << "Message recieved with invalid version " << versionString; QJsonObject msg; Private::messageHeader(msg, sessionId, id); Private::messageErrInvalidVersion(msg); mConnectionManager.replyMessage(connId, QJsonDocument(msg)); return; } Session* session; if (sessionId.isInvalid()) { session = nullptr; } else { session = mSessionManager.findSession(sessionId); } // TODO dispatch message }