From 2f52bd2ed26cc151fa90ed9e06b1ea9990f9fc7c Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Mon, 1 Dec 2014 11:54:37 +0100 Subject: send revision updates from resource to client this includes an initial revision message on connect --- resource/listener.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++++------- resource/listener.h | 16 ++++++++++-- 2 files changed, 77 insertions(+), 11 deletions(-) (limited to 'resource') diff --git a/resource/listener.cpp b/resource/listener.cpp index 8a571e9..5dd8cc3 100644 --- a/resource/listener.cpp +++ b/resource/listener.cpp @@ -3,13 +3,15 @@ #include "common/console.h" #include "common/commands.h" #include "common/handshake_generated.h" +#include "common/revisionupdate_generated.h" #include #include Listener::Listener(const QString &resource, QObject *parent) : QObject(parent), - m_server(new QLocalServer(this)) + m_server(new QLocalServer(this)), + m_revision(0) { connect(m_server, &QLocalServer::newConnection, this, &Listener::acceptConnection); @@ -34,6 +36,19 @@ Listener::~Listener() { } +void Listener::setRevision(unsigned long long revision) +{ + if (m_revision != revision) { + m_revision = revision; + updateClientsWithRevision(); + } +} + +unsigned long long Listener::revision() const +{ + return m_revision; +} + void Listener::closeAllConnections() { //TODO: close all client connectionsin m_connections @@ -73,7 +88,7 @@ void Listener::clientDropped() } Console::main()->log("Dropping connection..."); - QMutableListIterator it(m_connections); + QMutableVectorIterator it(m_connections); while (it.hasNext()) { const Client &client = it.next(); if (client.socket == socket) { @@ -102,24 +117,25 @@ void Listener::readFromSocket() } Console::main()->log("Reading from socket..."); - QMutableListIterator it(m_connections); - while (it.hasNext()) { - Client &client = it.next(); + for (Client &client: m_connections) { if (client.socket == socket) { Console::main()->log(QString(" Client: %1").arg(client.name)); client.commandBuffer += socket->readAll(); - processClientBuffer(client); + // FIXME: schedule these rather than process them all at once + // right now this can lead to starvation of clients due to + // one overly active client + while (processClientBuffer(client)) {} break; } } } -void Listener::processClientBuffer(Client &client) +bool Listener::processClientBuffer(Client &client) { static const int headerSize = (sizeof(int) * 2); Console::main()->log(QString("processing %1").arg(client.commandBuffer.size())); if (client.commandBuffer.size() < headerSize) { - return; + return false; } int commandId, size; @@ -134,12 +150,50 @@ void Listener::processClientBuffer(Client &client) case Commands::HandshakeCommand: { auto buffer = Toynadi::GetHandshake(data.constData()); Console::main()->log(QString(" Handshake from %1").arg(buffer->name()->c_str())); - //TODO: reply? + sendCurrentRevision(client); break; } default: // client.hasSentCommand = true; break; } + + return client.commandBuffer.size() >= headerSize; + } else { + return false; + } +} + +void Listener::sendCurrentRevision(Client &client) +{ + if (!client.socket || !client.socket->isValid()) { + return; + } + + flatbuffers::FlatBufferBuilder fbb; + auto command = Toynadi::CreateRevisionUpdate(fbb, m_revision); + Toynadi::FinishRevisionUpdateBuffer(fbb, command); + const int commandId = Commands::RevisionUpdateCommand; + const int dataSize = fbb.GetSize(); + client.socket->write((const char*)&commandId, sizeof(int)); + client.socket->write((const char*)&dataSize, sizeof(int)); + client.socket->write((const char*)fbb.GetBufferPointer(), dataSize); +} + +void Listener::updateClientsWithRevision() +{ + flatbuffers::FlatBufferBuilder fbb; + auto command = Toynadi::CreateRevisionUpdate(fbb, m_revision); + Toynadi::FinishRevisionUpdateBuffer(fbb, command); + const int commandId = Commands::RevisionUpdateCommand; + const int dataSize = fbb.GetSize(); + + for (const Client &client: m_connections) { + if (!client.socket || !client.socket->isValid()) { + continue; + } + client.socket->write((const char*)&commandId, sizeof(int)); + client.socket->write((const char*)&dataSize, sizeof(int)); + client.socket->write((const char*)fbb.GetBufferPointer(), dataSize); } } diff --git a/resource/listener.h b/resource/listener.h index bfafe5f..0d8f388 100644 --- a/resource/listener.h +++ b/resource/listener.h @@ -8,6 +8,12 @@ class Client { public: + Client() + : socket(nullptr), + hasSentCommand(false) + { + } + Client(const QString &n, QLocalSocket *s) : name(n), socket(s), @@ -29,6 +35,9 @@ public: Listener(const QString &resourceName, QObject *parent = 0); ~Listener(); + void setRevision(unsigned long long revision); + unsigned long long revision() const; + Q_SIGNALS: void noClients(); @@ -42,7 +51,10 @@ private Q_SLOTS: void readFromSocket(); private: - void processClientBuffer(Client &client); + bool processClientBuffer(Client &client); + void sendCurrentRevision(Client &client); + void updateClientsWithRevision(); QLocalServer *m_server; - QList m_connections; + QVector m_connections; + unsigned long long m_revision; }; \ No newline at end of file -- cgit v1.2.3