]> git.zarvox.org Git - imoo.git/commitdiff
Parse and validate messages as JSON
authorDrew Fisher <drew.m.fisher@gmail.com>
Thu, 17 Apr 2014 05:13:19 +0000 (22:13 -0700)
committerDrew Fisher <drew.m.fisher@gmail.com>
Thu, 17 Apr 2014 05:13:19 +0000 (22:13 -0700)
Disconnect clients that send invalid frames
Log the invalid frames and the hex

ribbon/ribbonserver.cpp
ribbon/ribbonsocket.cpp
ribbon/ribbonsocket.h

index 1c2ea15053abcb271deba81005d2bc96d8b5077f..1c8e3a80cbc295bcefda4088991f0589b527b194 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <QtNetwork/QTcpServer>
 #include <QtNetwork/QTcpSocket>
+#include <QJsonDocument>
 #include <QDebug>
 
 RibbonServer::RibbonServer(QObject* parent) :
@@ -54,6 +55,14 @@ void RibbonServer::onDisconnection(RibbonSocket* r)
 void RibbonServer::onMessageReceived(RibbonSocket* r, QByteArray buf)
 {
        qDebug() << "server: got data from" << r->s()->peerAddress() << r->s()->peerPort();
-       qDebug() << "        message was:" << buf.constData();
-       // TODO: do something with the packet in buf.constData()
+       QJsonParseError err;
+       QJsonDocument json = QJsonDocument::fromJson(buf, &err);
+       if (json.isNull()) {
+               qWarning() << "Json did not validate:" << err.errorString();
+               qWarning() << buf.constData();
+               qWarning() << "hexencoded:" << buf.toHex().constData();
+               r->abort();
+       } else {
+               qDebug() << "json document:" << json;
+       }
 }
index 8b7e2e5b6b0a51b1cb0f3d51fc156cfc4f60a7e8..c9c5dc94d66924041c899cf4664a3e37fb74ec91 100644 (file)
@@ -1,16 +1,18 @@
 #include "ribbonsocket.h"
-#include <QDebug>
 
 RibbonSocket::RibbonSocket(QTcpSocket* sock, QObject* parent) :
        QObject(parent),
        socket(sock),
        state(WANT_LENGTH),
-       bytes_wanted(0)
+       bytes_wanted(0),
+       aborting(false)
 {
        QObject::connect(socket, SIGNAL(disconnected()),
                        this, SLOT(onDisconnect()));
        QObject::connect(socket, SIGNAL(readyRead()),
                        this, SLOT(onReadyRead()));
+       // Take ownership of the socket
+       socket->setParent(this);
 }
 
 RibbonSocket::~RibbonSocket()
@@ -22,6 +24,12 @@ const QTcpSocket* RibbonSocket::s()
        return socket;
 }
 
+void RibbonSocket::abort()
+{
+       aborting = true;
+       socket->abort();
+}
+
 void RibbonSocket::onDisconnect()
 {
        emit disconnected(this);
@@ -35,7 +43,6 @@ bool RibbonSocket::tryProcess()
 {
        switch(state) {
                case WANT_LENGTH:
-                       qDebug() << "Want length, buf size before read:" << buf.length();
                        if (readUntilBufHas(4)) {
                                // Slice 4 octets off as big-endian integer
                                QByteArray size_buf = buf.left(4);
@@ -46,19 +53,17 @@ bool RibbonSocket::tryProcess()
                                // TODO: decide on a maximum acceptable packet length, to avoid
                                // arbitrarily large packet buffer
                                buf.reserve(bytes_wanted);
-                               qDebug() << "length:" << bytes_wanted;
+                               qDebug() << "socket: got length:" << bytes_wanted;
                                state = WANT_DATA;
                                return true;
                        }
                        break;
                case WANT_DATA:
-                       qDebug() << "Want data, buf size before read:" << buf.length();
                        if (readUntilBufHas(bytes_wanted)) {
                                QByteArray data = buf.left(bytes_wanted);
                                buf = buf.mid(bytes_wanted);
                                // Memory optimization: release the rest of the buffer
                                buf.squeeze();
-                               qDebug() << "data:" << buf;
                                emit messageReceived(this, data);
                                state = WANT_LENGTH;
                                return true;
@@ -74,10 +79,12 @@ bool RibbonSocket::tryProcess()
  */
 bool RibbonSocket::readUntilBufHas(int desired_buffer_length)
 {
-       int size_to_read = desired_buffer_length - buf.length();
-       QByteArray tmp = socket->read(size_to_read);
-       qDebug() << "read" << tmp.length() << "from socket";
-       buf += tmp;
+       // If we're shutting down the socket, don't try to read more from it
+       if (!aborting) {
+               int size_to_read = desired_buffer_length - buf.length();
+               QByteArray tmp = socket->read(size_to_read);
+               buf += tmp;
+       }
        return buf.length() >= desired_buffer_length;
 }
 
index e72ab6caaaca656ccdc3ac6c84ce566fcbdc3eb4..672c4b82bf7013540b9a5f52f61c5a12606f4cd2 100644 (file)
@@ -15,6 +15,7 @@ public:
        RibbonSocket(QTcpSocket* socket, QObject* parent=0);
        // Consider s to be final.  Don't modify it.
        const QTcpSocket* s();
+       void abort();
 signals:
        void disconnected(RibbonSocket* s);
        void messageReceived(RibbonSocket* s, QByteArray buf);
@@ -24,6 +25,7 @@ private:
        QByteArray buf;
        RibbonSocketState state;
        quint32 bytes_wanted;
+       bool aborting;
        bool tryProcess();
        bool readUntilBufHas(int desired_buffer_length);
 private slots: