summaryrefslogtreecommitdiff
path: root/server/bouncer.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--server/bouncer.cpp127
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);
+}