From 5864864123359d573592f1e2bc6af7383bf167d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Fri, 15 Nov 2019 21:07:58 +0100 Subject: [PATCH] WSServer: reimplement protocol --- CMakeLists.txt | 2 + src/WSRequestHandler.cpp | 58 --------------------- src/WSServer.cpp | 14 ++++- src/protocol/OBSRemoteProtocol.cpp | 82 ++++++++++++++++++++++++++++++ src/protocol/OBSRemoteProtocol.h | 34 +++++++++++++ src/rpc/RpcResponse.h | 4 +- 6 files changed, 132 insertions(+), 62 deletions(-) create mode 100644 src/protocol/OBSRemoteProtocol.cpp create mode 100644 src/protocol/OBSRemoteProtocol.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f53ba576..ea0a0fab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ set(obs-websocket_SOURCES src/Utils.cpp src/rpc/RpcRequest.cpp src/rpc/RpcResponse.h + src/protocol/OBSRemoteProtocol.cpp src/forms/settings-dialog.cpp) set(obs-websocket_HEADERS @@ -60,6 +61,7 @@ set(obs-websocket_HEADERS src/Utils.h src/rpc/RpcRequest.h src/rpc/RpcResponse.h + src/protocol/OBSRemoteProtocol.h src/forms/settings-dialog.h) # --- Platform-independent build settings --- diff --git a/src/WSRequestHandler.cpp b/src/WSRequestHandler.cpp index 843db11a..0f10fad6 100644 --- a/src/WSRequestHandler.cpp +++ b/src/WSRequestHandler.cpp @@ -156,38 +156,7 @@ WSRequestHandler::WSRequestHandler(ConnectionProperties& connProperties) : { } -// std::string WSRequestHandler::processIncomingMessage(std::string& textMessage) { -// if (GetConfig()->DebugEnabled) { -// blog(LOG_INFO, "Request >> '%s'", textMessage.c_str()); -// } - -// OBSDataAutoRelease responseData = processRequest(textMessage); -// std::string response = obs_data_get_json(responseData); - -// if (GetConfig()->DebugEnabled) { -// blog(LOG_INFO, "Response << '%s'", response.c_str()); -// } - -// return response; -// } - RpcResponse WSRequestHandler::processRequest(const RpcRequest& request){ - // std::string msgContainer(textMessage); - // const char* msg = msgContainer.c_str(); - - // data = obs_data_create_from_json(msg); - // if (!data) { - // blog(LOG_ERROR, "invalid JSON payload received for '%s'", msg); - // return SendErrorResponse("invalid JSON payload"); - // } - - // if (!hasField("request-type") || !hasField("message-id")) { - // return SendErrorResponse("missing request parameters"); - // } - - // _requestType = obs_data_get_string(data, "request-type"); - // _messageId = obs_data_get_string(data, "message-id"); - if (GetConfig()->AuthRequired && (!authNotRequired.contains(request.methodName())) && (!_connProperties.isAuthenticated())) @@ -202,30 +171,3 @@ RpcResponse WSRequestHandler::processRequest(const RpcRequest& request){ return std::bind(handlerFunc, this, _1)(request); } - -// HandlerResponse WSRequestHandler::SendOKResponse(obs_data_t* additionalFields) { -// return SendResponse("ok", additionalFields); -// } - -// HandlerResponse WSRequestHandler::SendErrorResponse(QString errorMessage) { -// OBSDataAutoRelease fields = obs_data_create(); -// obs_data_set_string(fields, "error", errorMessage.toUtf8().constData()); - -// return SendResponse("error", fields); -// } - -// HandlerResponse WSRequestHandler::SendErrorResponse(obs_data_t* additionalFields) { -// return SendResponse("error", additionalFields); -// } - -// HandlerResponse WSRequestHandler::SendResponse(const char* status, obs_data_t* fields) { -// obs_data_t* response = obs_data_create(); -// obs_data_set_string(response, "message-id", _messageId); -// obs_data_set_string(response, "status", status); - -// if (fields) { -// obs_data_apply(response, fields); -// } - -// return response; -// } diff --git a/src/WSServer.cpp b/src/WSServer.cpp index 1b062b97..cb211289 100644 --- a/src/WSServer.cpp +++ b/src/WSServer.cpp @@ -31,6 +31,7 @@ with this program. If not, see #include "obs-websocket.h" #include "Config.h" #include "Utils.h" +#include "protocol/OBSRemoteProtocol.h" QT_USE_NAMESPACE @@ -171,8 +172,17 @@ void WSServer::onMessage(connection_hdl hdl, server::message_ptr message) ConnectionProperties& connProperties = _connectionProperties[hdl]; locker.unlock(); - WSRequestHandler handler(connProperties); - std::string response = handler.processIncomingMessage(payload); + if (GetConfig()->DebugEnabled) { + blog(LOG_INFO, "Request >> '%s'", payload.c_str()); + } + + WSRequestHandler requestHandler(connProperties); + OBSRemoteProtocol protocol(requestHandler); + std::string response = protocol.processMessage(payload); + + if (GetConfig()->DebugEnabled) { + blog(LOG_INFO, "Response << '%s'", response.c_str()); + } websocketpp::lib::error_code errorCode; _server.send(hdl, response, websocketpp::frame::opcode::text, errorCode); diff --git a/src/protocol/OBSRemoteProtocol.cpp b/src/protocol/OBSRemoteProtocol.cpp new file mode 100644 index 00000000..468e0310 --- /dev/null +++ b/src/protocol/OBSRemoteProtocol.cpp @@ -0,0 +1,82 @@ +/* +obs-websocket +Copyright (C) 2016-2019 Stéphane Lepin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see +*/ + +#include "OBSRemoteProtocol.h" +#include "../WSRequestHandler.h" + +std::string buildResponse(QString messageId, QString status, obs_data_t* fields = nullptr) { + obs_data_t* response = obs_data_create(); + obs_data_set_string(response, "message-id", messageId.toUtf8().constData()); + obs_data_set_string(response, "status", status.toUtf8().constData()); + + if (fields) { + obs_data_apply(response, fields); + } + + std::string responseString = obs_data_get_json(response); + return responseString; +} + +std::string successResponse(QString messageId, obs_data_t* fields = nullptr) { + return buildResponse(messageId, "ok", fields); +} + +std::string errorResponse(QString messageId, QString errorMessage, obs_data_t* additionalFields = nullptr) { + OBSDataAutoRelease fields = obs_data_create(); + obs_data_set_string(fields, "error", errorMessage.toUtf8().constData()); + return buildResponse(messageId, "error", fields); +} + +OBSRemoteProtocol::OBSRemoteProtocol(WSRequestHandler& requestHandler) : + _requestHandler(requestHandler) +{ +} + +std::string OBSRemoteProtocol::processMessage(std::string message) +{ + std::string msgContainer(message); + const char* msg = msgContainer.c_str(); + + OBSDataAutoRelease data = obs_data_create_from_json(msg); + if (!data) { + blog(LOG_ERROR, "invalid JSON payload received for '%s'", msg); + return errorResponse(nullptr, "invalid JSON payload"); + } + + if (!obs_data_has_user_value(data, "request-type") || !obs_data_has_user_value(data, "message-id")) { + return errorResponse(nullptr, "missing request parameters"); + } + + QString methodName = obs_data_get_string(data, "request-type"); + QString messageId = obs_data_get_string(data, "message-id"); + + OBSDataAutoRelease params = obs_data_create(); + + RpcRequest request(messageId, methodName, params); + RpcResponse response = _requestHandler.processRequest(request); + + OBSData additionalFields = response.additionalFields(); + switch (response.status()) { + case Ok: + return successResponse(messageId, additionalFields); + case Error: + return errorResponse(messageId, response.errorMessage(), additionalFields); + } + + return std::string(); +} diff --git a/src/protocol/OBSRemoteProtocol.h b/src/protocol/OBSRemoteProtocol.h new file mode 100644 index 00000000..f1751b87 --- /dev/null +++ b/src/protocol/OBSRemoteProtocol.h @@ -0,0 +1,34 @@ +/* +obs-websocket +Copyright (C) 2016-2019 Stéphane Lepin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see +*/ + +#pragma once + +#include +#include + +class WSRequestHandler; + +class OBSRemoteProtocol +{ +public: + explicit OBSRemoteProtocol(WSRequestHandler& requestHandler); + std::string processMessage(std::string message); + +private: + WSRequestHandler& _requestHandler; +}; diff --git a/src/rpc/RpcResponse.h b/src/rpc/RpcResponse.h index 11adfcf5..caf9bdd7 100644 --- a/src/rpc/RpcResponse.h +++ b/src/rpc/RpcResponse.h @@ -57,8 +57,8 @@ public: return _errorMessage; } - const obs_data_t* parameters() const { - return _additionalFields; + const OBSData additionalFields() const { + return OBSData(_additionalFields); } private: