summaryrefslogtreecommitdiff
path: root/server/socket.cpp
diff options
context:
space:
mode:
authorTreeki <treeki@gmail.com>2013-12-25 09:00:59 +0100
committerTreeki <treeki@gmail.com>2013-12-25 09:00:59 +0100
commitb7a8b597b00eedde277836eb8530ba742edcad5d (patch)
tree1b959fa0eec02ff4e22e168aa4379b2b64575ce3 /server/socket.cpp
downloadbounce_qt-b7a8b597b00eedde277836eb8530ba742edcad5d.tar.gz
bounce_qt-b7a8b597b00eedde277836eb8530ba742edcad5d.zip
commit initial bitsHEADmaster
Diffstat (limited to '')
-rw-r--r--server/socket.cpp214
1 files changed, 214 insertions, 0 deletions
diff --git a/server/socket.cpp b/server/socket.cpp
new file mode 100644
index 0000000..56c5258
--- /dev/null
+++ b/server/socket.cpp
@@ -0,0 +1,214 @@
+#include "socket.h"
+#include "bouncer.h"
+#include "packetreader.h"
+
+Socket::Socket(QObject *parent) :
+ QObject(parent)
+{
+ m_identified = false;
+ m_socket = NULL;
+
+ m_lastSentPacketID = 0;
+ m_lastReceivedPacketID = 0;
+ qDebug("[%p] Socket::Socket()", this);
+}
+
+Socket::~Socket() {
+ unlinkSocket(/*disconnect=*/true);
+ qDebug("[%p] Socket::~Socket()", this);
+}
+
+
+
+
+void Socket::setup(QTcpSocket *socket) {
+ unlinkSocket(/*disconnect=*/true);
+
+ socket->setParent(this);
+ m_socket = socket;
+
+ m_readBuffer.clear();
+ m_handshakeStatus = 0;
+
+ connect(socket, SIGNAL(connected()), this, SLOT(socketConnected()));
+ connect(socket, SIGNAL(readyRead()), this, SLOT(socketReceived()));
+ connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
+ connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
+}
+
+void Socket::unlinkSocket(bool disconnect) {
+ if (!m_socket)
+ return;
+
+ qDebug("[%p] Socket::unlinkSocket...", this);
+
+ QObject::disconnect(m_socket, SIGNAL(connected()), this, SLOT(socketConnected()));
+ QObject::disconnect(m_socket, SIGNAL(readyRead()), this, SLOT(socketReceived()));
+ QObject::disconnect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
+ QObject::disconnect(m_socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
+
+ if (disconnect) {
+ m_socket->flush();
+ m_socket->close();
+ m_socket->deleteLater();
+ }
+ m_socket = NULL;
+}
+
+
+void Socket::socketReceived() {
+ QByteArray readIt = m_socket->readAll();
+ m_readBuffer.append(readIt);
+
+ quint8 *buf = (quint8 *)m_readBuffer.data();
+ int bufSize = m_readBuffer.length();
+ int position = 0;
+
+ while ((position + 8) <= bufSize) {
+ PacketReader reader(&buf[position], bufSize - position);
+
+ quint32 packetType = reader.readU32();
+ quint32 packetSize = reader.readU32();
+
+ if (bufSize > 128000 || packetSize > 128000) {
+ // Something's not right here...
+ // (TODO: investigate if this is really a good thing to do?)
+ m_readBuffer.clear();
+ return;
+ }
+
+ // Out-of-band packets have 8 bytes header, otherwise 16 bytes
+ int headerSize = 8;
+ if (!(packetType & 0x80000000))
+ headerSize = 16;
+
+ if (bufSize >= (position + packetSize + headerSize)) {
+ // We have the whole of this packet
+ // If it's not out-of-band, deal with the IDs
+
+ qDebug("Recv: [%08x] %d bytes", packetType, packetSize);
+
+ bool isUnnecessaryPacket = false;
+
+ if (!(packetType & 0x80000000)) {
+ quint32 packetID = reader.readU32();
+ quint32 lastReceivedID = reader.readU32();
+
+ // Clear messages they already have from our own cache
+ clearAcknowledgedPackets(lastReceivedID);
+
+ if (packetID > m_lastReceivedPacketID) {
+ // New packet, so update this
+ m_lastReceivedPacketID = packetID;
+ } else {
+ // We already got this packet (presumably)...
+ // ...so ignore it!
+ isUnnecessaryPacket = true;
+ }
+
+ qDebug(" packetID=%d, lastReceivedID=%d", packetID, lastReceivedID);
+ }
+
+ // If we haven't received this message, handle it!
+ if (!isUnnecessaryPacket) {
+ PacketReader subReader(&buf[position + headerSize], packetSize);
+ handlePacket(packetType, subReader);
+ }
+
+ position += headerSize + packetSize;
+ } else {
+ // We don't have the whole of this packet yet, so wait.
+ break;
+ }
+ }
+
+
+ // If we managed to handle anything, lop it off the buffer
+ if (position > 0) {
+ if (position >= bufSize) {
+ m_readBuffer.clear();
+ } else {
+ memmove(buf, &buf[position], bufSize - position);
+ m_readBuffer.resize(bufSize - position);
+ }
+ }
+}
+
+
+void Socket::socketConnected() {
+ // we do nothing here, but this is used by Client
+}
+
+void Socket::socketError(QAbstractSocket::SocketError error) {
+ // welp!
+ qDebug("Connection error!");
+ unlinkSocket(/*disconnect=*/true);
+ if (!m_identified)
+ emit finished();
+}
+
+void Socket::socketDisconnected() {
+ // welp 2.
+ qDebug("Connection closed!");
+ unlinkSocket(/*disconnect=*/true);
+ if (!m_identified)
+ emit finished();
+}
+
+
+void Socket::takeOverSocket(Socket *donor) {
+ setup(donor->m_socket);
+ m_readBuffer = donor->m_readBuffer;
+ donor->unlinkSocket(/*disconnect=*/false);
+ emit donor->finished();
+}
+
+
+void Socket::sendPacketOverSocket(const Packet &packet) {
+ quint32 packetHeader[4];
+ int headerSize = 8;
+ packetHeader[0] = packet.type;
+ packetHeader[1] = packet.data.size();
+
+ if (!packet.isOutOfBand()) {
+ headerSize = 16;
+ packetHeader[2] = packet.id;
+ packetHeader[3] = m_lastReceivedPacketID;
+ }
+
+ m_socket->write((const char *)&packetHeader, headerSize);
+ m_socket->write(packet.data);
+}
+
+
+void Socket::clearAcknowledgedPackets(int lastReceivedID) {
+ while (!m_packetCache.empty() && m_packetCache.at(0).id <= lastReceivedID)
+ m_packetCache.removeFirst();
+}
+
+void Socket::flushPacketCache() {
+ foreach (const Packet &packet, m_packetCache)
+ sendPacketOverSocket(packet);
+}
+
+
+void Socket::handlePacket(int type, PacketReader &reader) {
+ // stub
+ (void)type;
+ (void)reader;
+}
+
+
+void Socket::sendPacket(Packet &packet, bool isHandshakePacket) {
+ if (!packet.isOutOfBand()) {
+ m_lastSentPacketID++;
+ packet.id = m_lastSentPacketID;
+
+ m_packetCache.append(packet);
+ }
+
+ if ((m_socket != NULL) && (isHandshakePacket || (m_handshakeStatus > 0)))
+ sendPacketOverSocket(packet);
+ else if (packet.isOutOfBand())
+ qWarning("WARNING: Out-of-band message %08x was lost!", packet.type);
+}