mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	Schema checking for all commands added
This commit is contained in:
		| @@ -16,20 +16,8 @@ | |||||||
| JsonClientConnection::JsonClientConnection(QTcpSocket *socket) : | JsonClientConnection::JsonClientConnection(QTcpSocket *socket) : | ||||||
| 	QObject(), | 	QObject(), | ||||||
| 	_socket(socket), | 	_socket(socket), | ||||||
| 	_schemaChecker(), |  | ||||||
| 	_receiveBuffer() | 	_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 internal signals and slots | ||||||
| 	connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed())); | 	connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed())); | ||||||
| 	connect(_socket, SIGNAL(readyRead()), this, SLOT(readData())); | 	connect(_socket, SIGNAL(readyRead()), this, SLOT(readData())); | ||||||
| @@ -64,33 +52,80 @@ void JsonClientConnection::socketClosed() | |||||||
| 	emit connectionClosed(this); | 	emit connectionClosed(this); | ||||||
| } | } | ||||||
|  |  | ||||||
| void JsonClientConnection::handleMessage(const std::string &message) | void JsonClientConnection::handleMessage(const std::string &messageString) | ||||||
| { | { | ||||||
| 	Json::Reader reader; | 	Json::Reader reader; | ||||||
| 	Json::Value messageRoot; | 	Json::Value message; | ||||||
| 	if (!reader.parse(message, messageRoot, false)) | 	if (!reader.parse(messageString, message, false)) | ||||||
| 	{ | 	{ | ||||||
| 		sendErrorReply("Error while parsing json: " + reader.getFormattedErrorMessages()); | 		sendErrorReply("Error while parsing json: " + reader.getFormattedErrorMessages()); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (!_schemaChecker.validate(messageRoot)) | 	// check basic message | ||||||
|  | 	std::string errors; | ||||||
|  | 	if (!checkJson(message, ":schema", errors)) | ||||||
| 	{ | 	{ | ||||||
| 		const std::list<std::string> & errors = _schemaChecker.getMessages(); | 		sendErrorReply("Error while validating json: " + errors); | ||||||
| 		std::stringstream ss; |  | ||||||
| 		ss << "Error while validating json: {"; |  | ||||||
| 		foreach (const std::string & error, errors) { |  | ||||||
| 			ss << error << ", "; |  | ||||||
| 		} |  | ||||||
| 		ss << "}"; |  | ||||||
| 		sendErrorReply(ss.str()); |  | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	handleNotImplemented(messageRoot); | 	// check specific message | ||||||
|  | 	const std::string command = message["command"].asString(); | ||||||
|  | 	if (!checkJson(message, QString("schema-%1").arg(QString::fromStdString(command)), errors)) | ||||||
|  | 	{ | ||||||
|  | 		sendErrorReply("Error while validating json: " + errors); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// switch over all possible commands and handle them | ||||||
|  | 	if (command == "color") | ||||||
|  | 		handleColorCommand(message); | ||||||
|  | 	else if (command == "image") | ||||||
|  | 		handleImageCommand(message); | ||||||
|  | 	else if (command == "serverinfo") | ||||||
|  | 		handleServerInfoCommand(message); | ||||||
|  | 	else if (command == "clear") | ||||||
|  | 		handleClearCommand(message); | ||||||
|  | 	else if (command == "clearall") | ||||||
|  | 		handleClearallCommand(message); | ||||||
|  | 	else if (command == "transform") | ||||||
|  | 		handleTransformCommand(message); | ||||||
|  | 	else | ||||||
|  | 		handleNotImplemented(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void JsonClientConnection::handleNotImplemented(const Json::Value & message) | void JsonClientConnection::handleColorCommand(const Json::Value &message) | ||||||
|  | { | ||||||
|  | 	handleNotImplemented(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void JsonClientConnection::handleImageCommand(const Json::Value &message) | ||||||
|  | { | ||||||
|  | 	handleNotImplemented(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void JsonClientConnection::handleServerInfoCommand(const Json::Value &message) | ||||||
|  | { | ||||||
|  | 	handleNotImplemented(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void JsonClientConnection::handleClearCommand(const Json::Value &message) | ||||||
|  | { | ||||||
|  | 	handleNotImplemented(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void JsonClientConnection::handleClearallCommand(const Json::Value &message) | ||||||
|  | { | ||||||
|  | 	handleNotImplemented(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void JsonClientConnection::handleTransformCommand(const Json::Value &message) | ||||||
|  | { | ||||||
|  | 	handleNotImplemented(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void JsonClientConnection::handleNotImplemented() | ||||||
| { | { | ||||||
| 	sendErrorReply("Command not implemented"); | 	sendErrorReply("Command not implemented"); | ||||||
| } | } | ||||||
| @@ -112,3 +147,36 @@ void JsonClientConnection::sendErrorReply(const std::string &error) | |||||||
| 	// send reply | 	// send reply | ||||||
| 	sendMessage(reply); | 	sendMessage(reply); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool JsonClientConnection::checkJson(const Json::Value & message, const QString & schemaResource, std::string & errorMessage) | ||||||
|  | { | ||||||
|  | 	// read the json schema from the resource | ||||||
|  | 	QResource schemaData(schemaResource); | ||||||
|  | 	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())	; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// create schema checker | ||||||
|  | 	JsonSchemaChecker schema; | ||||||
|  | 	schema.setSchema(schemaJson); | ||||||
|  |  | ||||||
|  | 	// check the message | ||||||
|  | 	if (!schema.validate(message)) | ||||||
|  | 	{ | ||||||
|  | 		const std::list<std::string> & errors = schema.getMessages(); | ||||||
|  | 		std::stringstream ss; | ||||||
|  | 		ss << "{"; | ||||||
|  | 		foreach (const std::string & error, errors) { | ||||||
|  | 			ss << error << " "; | ||||||
|  | 		} | ||||||
|  | 		ss << "}"; | ||||||
|  | 		errorMessage = ss.str(); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -30,15 +30,22 @@ private slots: | |||||||
|  |  | ||||||
| private: | private: | ||||||
| 	void handleMessage(const std::string & message); | 	void handleMessage(const std::string & message); | ||||||
| 	void handleNotImplemented(const Json::Value & message); | 	void handleColorCommand(const Json::Value & message); | ||||||
|  | 	void handleImageCommand(const Json::Value & message); | ||||||
|  | 	void handleServerInfoCommand(const Json::Value & message); | ||||||
|  | 	void handleClearCommand(const Json::Value & message); | ||||||
|  | 	void handleClearallCommand(const Json::Value & message); | ||||||
|  | 	void handleTransformCommand(const Json::Value & message); | ||||||
|  | 	void handleNotImplemented(); | ||||||
|  |  | ||||||
| 	void sendMessage(const Json::Value & message); | 	void sendMessage(const Json::Value & message); | ||||||
| 	void sendErrorReply(const std::string & error); | 	void sendErrorReply(const std::string & error); | ||||||
|  |  | ||||||
| private: | private: | ||||||
| 	QTcpSocket * _socket; | 	bool checkJson(const Json::Value & message, const QString &schemaResource, std::string & errors); | ||||||
|  |  | ||||||
| 	JsonSchemaChecker _schemaChecker; | private: | ||||||
|  | 	QTcpSocket * _socket; | ||||||
|  |  | ||||||
| 	QByteArray _receiveBuffer; | 	QByteArray _receiveBuffer; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -37,11 +37,11 @@ uint16_t JsonServer::getPort() const | |||||||
|  |  | ||||||
| void JsonServer::newConnection() | void JsonServer::newConnection() | ||||||
| { | { | ||||||
| 	std::cout << "New incoming json connection" << std::endl; |  | ||||||
| 	QTcpSocket * socket = _server.nextPendingConnection(); | 	QTcpSocket * socket = _server.nextPendingConnection(); | ||||||
|  |  | ||||||
| 	if (socket != nullptr) | 	if (socket != nullptr) | ||||||
| 	{ | 	{ | ||||||
|  | 		std::cout << "New json connection" << std::endl; | ||||||
| 		JsonClientConnection * connection = new JsonClientConnection(socket); | 		JsonClientConnection * connection = new JsonClientConnection(socket); | ||||||
| 		_openConnections.insert(connection); | 		_openConnections.insert(connection); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,11 @@ | |||||||
| <RCC> | <RCC> | ||||||
| 	<qresource prefix="/"> | 	<qresource prefix="/"> | ||||||
|         <file>schema.json</file> | 		<file alias="schema">schema/schema.json</file> | ||||||
|  | 		<file alias="schema-color">schema/schema-color.json</file> | ||||||
|  | 		<file alias="schema-image">schema/schema-image.json</file> | ||||||
|  | 		<file alias="schema-serverinfo">schema/schema-serverinfo.json</file> | ||||||
|  | 		<file alias="schema-clear">schema/schema-clear.json</file> | ||||||
|  | 		<file alias="schema-clearall">schema/schema-clearall.json</file> | ||||||
|  | 		<file alias="schema-transform">schema/schema-transform.json</file> | ||||||
| 	</qresource> | 	</qresource> | ||||||
| </RCC> | </RCC> | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								libsrc/jsonserver/schema/schema-clear.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								libsrc/jsonserver/schema/schema-clear.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | { | ||||||
|  |     "type":"object", | ||||||
|  |     "required":true, | ||||||
|  |     "properties":{ | ||||||
|  |         "command": { | ||||||
|  |             "type" : "string", | ||||||
|  |             "required" : true, | ||||||
|  |             "enum" : ["clear"] | ||||||
|  |         }, | ||||||
|  |         "priority": { | ||||||
|  |             "type": "integer", | ||||||
|  |             "required": true | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     "additionalProperties": false | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								libsrc/jsonserver/schema/schema-clearall.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								libsrc/jsonserver/schema/schema-clearall.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | { | ||||||
|  |     "type":"object", | ||||||
|  |     "required":true, | ||||||
|  |     "properties":{ | ||||||
|  |         "command": { | ||||||
|  |             "type" : "string", | ||||||
|  |             "required" : true, | ||||||
|  |             "enum" : ["clearall"] | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     "additionalProperties": false | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								libsrc/jsonserver/schema/schema-color.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								libsrc/jsonserver/schema/schema-color.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | { | ||||||
|  |     "type":"object", | ||||||
|  |     "required":true, | ||||||
|  |     "properties":{ | ||||||
|  |         "command": { | ||||||
|  |             "type" : "string", | ||||||
|  |             "required" : true, | ||||||
|  |             "enum" : ["color"] | ||||||
|  |         }, | ||||||
|  |         "priority": { | ||||||
|  |             "type": "integer", | ||||||
|  |             "required": true | ||||||
|  |         }, | ||||||
|  |         "duration": { | ||||||
|  |             "type": "integer", | ||||||
|  |             "required": false | ||||||
|  |         }, | ||||||
|  |         "color": { | ||||||
|  |             "type": "array", | ||||||
|  |             "required": true, | ||||||
|  |             "items" :{ | ||||||
|  |                 "type" : "integer" | ||||||
|  |             }, | ||||||
|  |             "minItems": 3, | ||||||
|  |             "maxItems": 3 | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     "additionalProperties": false | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								libsrc/jsonserver/schema/schema-image.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								libsrc/jsonserver/schema/schema-image.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | { | ||||||
|  |     "type":"object", | ||||||
|  |     "required":true, | ||||||
|  |     "properties":{ | ||||||
|  |         "command": { | ||||||
|  |             "type" : "string", | ||||||
|  |             "required" : true, | ||||||
|  |             "enum" : ["image"] | ||||||
|  |         }, | ||||||
|  |         "priority": { | ||||||
|  |             "type": "integer", | ||||||
|  |             "required": true | ||||||
|  |         }, | ||||||
|  |         "duration": { | ||||||
|  |             "type": "integer", | ||||||
|  |             "required": false | ||||||
|  |         }, | ||||||
|  |         "imagewidth": { | ||||||
|  |             "type" : "integer", | ||||||
|  |             "required": true, | ||||||
|  |             "minimum": 0 | ||||||
|  |         }, | ||||||
|  |         "imageheight": { | ||||||
|  |             "type" : "integer", | ||||||
|  |             "required": true, | ||||||
|  |             "minimum": 0 | ||||||
|  |         }, | ||||||
|  |         "imagedata": { | ||||||
|  |             "type": "string", | ||||||
|  |             "required": true | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     "additionalProperties": false | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								libsrc/jsonserver/schema/schema-serverinfo.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								libsrc/jsonserver/schema/schema-serverinfo.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | { | ||||||
|  |     "type":"object", | ||||||
|  |     "required":true, | ||||||
|  |     "properties":{ | ||||||
|  |         "command": { | ||||||
|  |             "type" : "string", | ||||||
|  |             "required" : true, | ||||||
|  |             "enum" : ["serverinfo"] | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     "additionalProperties": false | ||||||
|  | } | ||||||
| @@ -5,42 +5,11 @@ | |||||||
|         "command": { |         "command": { | ||||||
|             "type" : "string", |             "type" : "string", | ||||||
|             "required" : true, |             "required" : true, | ||||||
|             "enum" : ["color", "image", "serverinfo", "clear", "clearall", "transform"] |             "enum" : ["transform"] | ||||||
|         }, |  | ||||||
|         "priority": { |  | ||||||
|             "type": "integer", |  | ||||||
|             "required": false |  | ||||||
|         }, |  | ||||||
|         "duration": { |  | ||||||
|             "type": "integer", |  | ||||||
|             "required": false |  | ||||||
|         }, |  | ||||||
|         "color": { |  | ||||||
|             "type": "array", |  | ||||||
|             "required": false, |  | ||||||
|             "items" :{ |  | ||||||
|                 "type" : "integer" |  | ||||||
|             }, |  | ||||||
|             "minItems": 3, |  | ||||||
|             "maxItems": 3 |  | ||||||
|         }, |  | ||||||
|         "imagewidth": { |  | ||||||
|             "type" : "integer", |  | ||||||
|             "required": false, |  | ||||||
|             "minimum": 0 |  | ||||||
|         }, |  | ||||||
|         "imageheight": { |  | ||||||
|             "type" : "integer", |  | ||||||
|             "required": false, |  | ||||||
|             "minimum": 0 |  | ||||||
|         }, |  | ||||||
|         "imagedata": { |  | ||||||
|             "type": "string", |  | ||||||
|             "required": false |  | ||||||
|         }, |         }, | ||||||
|         "transform": { |         "transform": { | ||||||
|             "type": "object", |             "type": "object", | ||||||
|             "required": false, |             "required": true, | ||||||
|             "properties": { |             "properties": { | ||||||
|                 "threshold": { |                 "threshold": { | ||||||
|                     "type": "array", |                     "type": "array", | ||||||
							
								
								
									
										11
									
								
								libsrc/jsonserver/schema/schema.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								libsrc/jsonserver/schema/schema.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | { | ||||||
|  |     "type":"object", | ||||||
|  |     "required":true, | ||||||
|  |     "properties":{ | ||||||
|  |         "command": { | ||||||
|  |             "type" : "string", | ||||||
|  |             "required" : true, | ||||||
|  |             "enum" : ["color", "image", "serverinfo", "clear", "clearall", "transform"] | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -275,7 +275,7 @@ bool JsonConnection::parseReply(const Json::Value &reply) | |||||||
|  |  | ||||||
| 	if (!success) | 	if (!success) | ||||||
| 	{ | 	{ | ||||||
| 		throw std::runtime_error("Error while executing command: " + reason); | 		throw std::runtime_error("Error: " + reason); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return success; | 	return success; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user