diff options
Diffstat (limited to '')
-rw-r--r-- | server/bouncer.cpp | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/server/bouncer.cpp b/server/bouncer.cpp new file mode 100644 index 0000000..0a38c26 --- /dev/null +++ b/server/bouncer.cpp @@ -0,0 +1,127 @@ +#include "bouncer.h" +#include "ircnetwork.h" +#include "packetwriter.h" +#include "server.h" + +Bouncer *Bouncer::m_instancePtr = NULL; + +Bouncer *Bouncer::instance() { + if (!m_instancePtr) + m_instancePtr = new Bouncer(); + return m_instancePtr; +} + +Bouncer::Bouncer(QObject *parent) : + QObject(parent) +{ + connect(&server, SIGNAL(newConnection()), this, SLOT(connectionReceived())); +} + + +void Bouncer::setupBouncer(int port, bool ssl) { + m_ssl = ssl; + + if (!server.listen(QHostAddress::Any, port)) { + qFatal("Error while listening!"); + return; + } +} + +void Bouncer::addNetwork(IRCNetworkConfig &config) { + IRCNetwork *n = new IRCNetwork(config, this); + networks << n; +} + +void Bouncer::connectionReceived() { + Server *c = new Server(this); + clients << c; + + connect(c, SIGNAL(finished()), this, SLOT(connectionFinished())); + + qDebug("new connection!"); + c->setup(server.nextPendingConnection()); +} + +void Bouncer::connectionFinished() { + Server *c = static_cast<Server *>(sender()); + + disconnect(c, SIGNAL(finished()), this, SLOT(connectionFinished())); + + c->deleteLater(); + clients.remove(c); + qDebug("connection finished and removed from list"); +} + + + + + +Server *Bouncer::findClientBySessionKey(quint8 *sessionKey) const { + foreach (Server *iter, clients) { + if (memcmp(sessionKey, iter->sessionKey(), Server::SessionKeySize) == 0) { + return iter; + } + } + + return NULL; +} + +void Bouncer::generateSessionKey(quint8 *output) { + do { + quint32 now = QDateTime::currentDateTime().toTime_t(); + output[0] = (now & 0xFF); + output[1] = ((now >> 8) & 0xFF); + output[2] = ((now >> 16) & 0xFF); + output[3] = ((now >> 24) & 0xFF); + + for (int i = 4; i < Server::SessionKeySize; i++) + output[i] = (qrand() & 0xFF); + + } while (findClientBySessionKey(output) != NULL); +} + + +Server *Bouncer::authenticate(Server *client, QString &username, QString &password, quint8 *sessionKey) const { + // Check the username/password + if (username != "testtest") + return NULL; + if (password != "optimal") + return NULL; + + // Is this a null session key? + bool isNullSessionKey = true; + for (int i = 0; i < Server::SessionKeySize; i++) + if (sessionKey[i] != 0) { + isNullSessionKey = false; + break; + } + + // Force a new session + if (isNullSessionKey) + return client; + + // Check to see if we have an existing session with this key + Server *takeOver = findClientBySessionKey(sessionKey); + if (takeOver != NULL) { + // Yep, we do. + // TODO: check that the username matches. This is a security hole otherwise. + return takeOver; + } + + // Nope. Use a new session. + return client; +} + + +void Bouncer::broadcast(const Message &message) { + if (clients.empty()) + return; + + PacketWriter writer(4 + (message.text.size() * 2)); + writer.writeString(message.text); + + Packet packet(B2C_ConsoleOutput, writer.buffer()); + + foreach (Server *iter, clients) + iter->sendPacket(packet); +} |