diff options
Diffstat (limited to '')
-rw-r--r-- | server/server.cpp | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/server/server.cpp b/server/server.cpp new file mode 100644 index 0000000..6c9412b --- /dev/null +++ b/server/server.cpp @@ -0,0 +1,131 @@ +#include "server.h" +#include "packetreader.h" +#include "packetwriter.h" +#include "ircnetworkconfig.h" +#include "ircnetwork.h" +#include "bouncer.h" + +Server::Server(QObject *parent) : + Socket(parent) +{ + Bouncer::instance()->generateSessionKey(m_sessionKey); +} + + + +void Server::handlePacket(int type, PacketReader &reader) { + switch (type) { + case C2B_OOB_Login: + net_login(reader); + break; + + case C2B_ConsoleInput: + net_consoleInput(reader.readString(MaxConsoleStringSize)); + break; + } +} + + + +void Server::net_login(PacketReader &reader) { + if (m_handshakeStatus > 0) + return; + + quint32 errorCode = attemptLogin(reader); + + if (errorCode > 0) { + // Yay, we failed somewhere above, so send out an error code + // and disconnect the client! + Packet packet(B2C_OOB_LoginFailed, + QByteArray((const char *)&errorCode, sizeof(errorCode))); + + sendPacket(packet, /*isHandshakePacket=*/true); + unlinkSocket(/*disconnect=*/true); + } +} + +int Server::attemptLogin(PacketReader &reader) { + quint32 protocolVer = reader.readU32(); + if (protocolVer != ProtocolVersion) + return 1; + + quint32 lastReceivedID = reader.readU32(); + + quint8 checkSessKey[SessionKeySize]; + if (!reader.readBytes(checkSessKey, 64)) + return 2; + + QString username = reader.readString(100); + QString password = reader.readString(100); + if (username.isNull() || password.isNull()) + return 2; + + // Parsed the packet, try out the stuff + Server *auth = Bouncer::instance()->authenticate(this, username, password, checkSessKey); + if (!auth) + return 3; + + // Who are we? + if (auth != this) { + // Taking over another session!! + auth->clearAcknowledgedPackets(lastReceivedID); + auth->takeOverSocket(this); + return 0; + } + + // We've successfully authed here, so go ahead. + m_identified = true; + sendLoginSuccess(); + + // Probably don't need to call flushPacketCache here: + // theoretically it should be empty at this point..... + + return 0; +} + +void Server::takeOverSocket(Socket *donor) { + Socket::takeOverSocket(donor); + sendLoginSuccess(); + + flushPacketCache(); +} + +void Server::sendLoginSuccess() { + PacketWriter writer(4 + SessionKeySize); + writer.writeU32(lastReceivedPacketID()); + writer.writeBytes(m_sessionKey, SessionKeySize); + + Packet packet(B2C_OOB_LoginSuccess, writer.buffer()); + sendPacket(packet, /*isHandshakePacket=*/true); + + m_handshakeStatus = 1; + flushPacketCache(); +} + + + +void Server::net_consoleInput(const QString &string) { + if (string.startsWith("woof")) + sendConsoleOutput(QString("woof back: [%1]").arg(string)); + + if (string.startsWith("addznc ")) { + IRCNetworkConfig config; + config.hostname = "209.20.91.134"; + config.port = 1191; + config.password = string.mid(7); + config.useSSL = true; + Bouncer::instance()->addNetwork(config); + } + + if (string.startsWith("connect")) { + Bouncer::instance()->networks.values()[0]->startConnection(); + } +} + +void Server::sendConsoleOutput(const QString &string) { + PacketWriter writer(4 + (string.size() * 2)); + writer.writeString(string); + + Packet packet(B2C_ConsoleOutput, writer.buffer()); + sendPacket(packet); +} |