2013-08-17 19:20:19 +02:00
|
|
|
// system includes
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <cassert>
|
|
|
|
|
2013-08-17 15:39:29 +02:00
|
|
|
// stl includes
|
|
|
|
#include <iostream>
|
2013-08-17 19:20:19 +02:00
|
|
|
#include <sstream>
|
|
|
|
#include <iterator>
|
|
|
|
|
|
|
|
// Qt includes
|
|
|
|
#include <QResource>
|
2013-08-17 15:39:29 +02:00
|
|
|
|
2013-08-17 19:20:19 +02:00
|
|
|
// project includes
|
2013-08-17 15:39:29 +02:00
|
|
|
#include "JsonClientConnection.h"
|
|
|
|
|
|
|
|
JsonClientConnection::JsonClientConnection(QTcpSocket *socket) :
|
|
|
|
QObject(),
|
2013-08-17 19:20:19 +02:00
|
|
|
_socket(socket),
|
|
|
|
_schemaChecker(),
|
|
|
|
_receiveBuffer()
|
2013-08-17 15:39:29 +02:00
|
|
|
{
|
2013-08-17 19:20:19 +02:00
|
|
|
// 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
|
2013-08-17 15:39:29 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-08-17 19:20:19 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-08-17 15:39:29 +02:00
|
|
|
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);
|
|
|
|
}
|