hyperion.ng/libsrc/jsonserver/JsonClientConnection.cpp

115 lines
2.6 KiB
C++

// system includes
#include <stdexcept>
#include <cassert>
// stl includes
#include <iostream>
#include <sstream>
#include <iterator>
// Qt includes
#include <QResource>
// project includes
#include "JsonClientConnection.h"
JsonClientConnection::JsonClientConnection(QTcpSocket *socket) :
QObject(),
_socket(socket),
_schemaChecker(),
_receiveBuffer()
{
// read the json schema from the resource
QResource schemaData(":/schema.json");
assert(schemaData.isValid());
Json::Reader jsonReader;
Json::Value schemaJson;
if (!jsonReader.parse(reinterpret_cast<const char *>(schemaData.data()), reinterpret_cast<const char *>(schemaData.data()) + schemaData.size(), schemaJson, false))
{
throw std::runtime_error("Schema error: " + jsonReader.getFormattedErrorMessages()) ;
}
_schemaChecker.setSchema(schemaJson);
// connect internal signals and slots
connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
connect(_socket, SIGNAL(readyRead()), this, SLOT(readData()));
}
JsonClientConnection::~JsonClientConnection()
{
delete _socket;
}
void JsonClientConnection::readData()
{
_receiveBuffer += _socket->readAll();
int bytes = _receiveBuffer.indexOf('\n') + 1;
if (bytes != 0)
{
// create message string
std::string message(_receiveBuffer.data(), bytes);
// remove message data from buffer
_receiveBuffer = _receiveBuffer.mid(bytes);
// handle message
handleMessage(message);
}
}
void JsonClientConnection::socketClosed()
{
emit connectionClosed(this);
}
void JsonClientConnection::handleMessage(const std::string &message)
{
Json::Reader reader;
Json::Value messageRoot;
if (!reader.parse(message, messageRoot, false))
{
sendErrorReply("Error while parsing json: " + reader.getFormattedErrorMessages());
return;
}
if (!_schemaChecker.validate(messageRoot))
{
const std::list<std::string> & errors = _schemaChecker.getMessages();
std::stringstream ss;
ss << "Error while validating json: {";
foreach (const std::string & error, errors) {
ss << error << ", ";
}
ss << "}";
sendErrorReply(ss.str());
return;
}
handleNotImplemented(messageRoot);
}
void JsonClientConnection::handleNotImplemented(const Json::Value & message)
{
sendErrorReply("Command not implemented");
}
void JsonClientConnection::sendMessage(const Json::Value &message)
{
Json::FastWriter writer;
std::string serializedReply = writer.write(message);
_socket->write(serializedReply.data(), serializedReply.length());
}
void JsonClientConnection::sendErrorReply(const std::string &error)
{
// create reply
Json::Value reply;
reply["success"] = false;
reply["error"] = error;
// send reply
sendMessage(reply);
}