mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
Base: More code cleanup and fixes
This commit is contained in:
parent
7e1e1bc33c
commit
e89c0c2b05
@ -1,7 +1,6 @@
|
|||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "plugin-macros.generated.h"
|
|
||||||
#include "utils/Crypto.h"
|
#include "utils/Crypto.h"
|
||||||
#include "utils/Platform.h"
|
#include "utils/Platform.h"
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <util/config-file.h>
|
#include <util/config-file.h>
|
||||||
|
|
||||||
|
#include "plugin-macros.generated.h"
|
||||||
|
|
||||||
class Config {
|
class Config {
|
||||||
public:
|
public:
|
||||||
Config();
|
Config();
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "utils/Crypto.h"
|
#include "utils/Crypto.h"
|
||||||
#include "utils/Platform.h"
|
#include "utils/Platform.h"
|
||||||
#include "plugin-macros.generated.h"
|
|
||||||
|
|
||||||
WebSocketServer::WebSocketServer() :
|
WebSocketServer::WebSocketServer() :
|
||||||
QObject(nullptr),
|
QObject(nullptr),
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "utils/Json.h"
|
#include "utils/Json.h"
|
||||||
#include "WebSocketSession.h"
|
#include "WebSocketSession.h"
|
||||||
|
#include "plugin-macros.generated.h"
|
||||||
|
|
||||||
class WebSocketServer : QObject
|
class WebSocketServer : QObject
|
||||||
{
|
{
|
||||||
|
@ -1,324 +1,322 @@
|
|||||||
#include <QtConcurrent>
|
#include <QtConcurrent>
|
||||||
#include <obs-module.h>
|
#include <obs-module.h>
|
||||||
|
|
||||||
#include "WebSocketServer.h"
|
#include "WebSocketServer.h"
|
||||||
#include "requesthandler/RequestHandler.h"
|
#include "requesthandler/RequestHandler.h"
|
||||||
#include "eventhandler/EventHandler.h"
|
#include "eventhandler/EventHandler.h"
|
||||||
#include "obs-websocket.h"
|
#include "obs-websocket.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "plugin-macros.generated.h"
|
#include "utils/Crypto.h"
|
||||||
#include "utils/Crypto.h"
|
#include "utils/Platform.h"
|
||||||
#include "utils/Json.h"
|
|
||||||
#include "utils/Platform.h"
|
namespace WebSocketOpCode {
|
||||||
|
enum WebSocketOpCode: uint8_t {
|
||||||
namespace WebSocketOpCode {
|
Hello = 0,
|
||||||
enum WebSocketOpCode: uint8_t {
|
Identify = 1,
|
||||||
Hello = 0,
|
Identified = 2,
|
||||||
Identify = 1,
|
Reidentify = 3,
|
||||||
Identified = 2,
|
Event = 5,
|
||||||
Reidentify = 3,
|
Request = 6,
|
||||||
Event = 5,
|
RequestResponse = 7,
|
||||||
Request = 6,
|
RequestBatch = 8,
|
||||||
RequestResponse = 7,
|
RequestBatchResponse = 9,
|
||||||
RequestBatch = 8,
|
};
|
||||||
RequestBatchResponse = 9,
|
};
|
||||||
};
|
|
||||||
};
|
bool IsSupportedRpcVersion(uint8_t requestedVersion)
|
||||||
|
{
|
||||||
bool IsSupportedRpcVersion(uint8_t requestedVersion)
|
return (requestedVersion == 1);
|
||||||
{
|
}
|
||||||
return (requestedVersion == 1);
|
|
||||||
}
|
void WebSocketServer::SetSessionParameters(SessionPtr session, ProcessResult &ret, json payloadData)
|
||||||
|
{
|
||||||
void WebSocketServer::SetSessionParameters(SessionPtr session, ProcessResult &ret, json payloadData)
|
if (payloadData.contains("ignoreInvalidMessages")) {
|
||||||
{
|
if (!payloadData["ignoreInvalidMessages"].is_boolean()) {
|
||||||
if (payloadData.contains("ignoreInvalidMessages")) {
|
ret.closeCode = WebSocketCloseCode::InvalidDataKeyType;
|
||||||
if (!payloadData["ignoreInvalidMessages"].is_boolean()) {
|
ret.closeReason = "Your `ignoreInvalidMessages` is not a boolean.";
|
||||||
ret.closeCode = WebSocketCloseCode::InvalidDataKeyType;
|
return;
|
||||||
ret.closeReason = "Your `ignoreInvalidMessages` is not a boolean.";
|
}
|
||||||
return;
|
session->SetIgnoreInvalidMessages(payloadData["ignoreInvalidMessages"]);
|
||||||
}
|
}
|
||||||
session->SetIgnoreInvalidMessages(payloadData["ignoreInvalidMessages"]);
|
|
||||||
}
|
if (payloadData.contains("ignoreNonFatalRequestChecks")) {
|
||||||
|
if (!payloadData["ignoreNonFatalRequestChecks"].is_boolean()) {
|
||||||
if (payloadData.contains("ignoreNonFatalRequestChecks")) {
|
ret.closeCode = WebSocketCloseCode::InvalidDataKeyType;
|
||||||
if (!payloadData["ignoreNonFatalRequestChecks"].is_boolean()) {
|
ret.closeReason = "Your `ignoreNonFatalRequestChecks` is not a boolean.";
|
||||||
ret.closeCode = WebSocketCloseCode::InvalidDataKeyType;
|
return;
|
||||||
ret.closeReason = "Your `ignoreNonFatalRequestChecks` is not a boolean.";
|
}
|
||||||
return;
|
session->SetIgnoreNonFatalRequestChecks(payloadData["ignoreNonFatalRequestChecks"]);
|
||||||
}
|
}
|
||||||
session->SetIgnoreNonFatalRequestChecks(payloadData["ignoreNonFatalRequestChecks"]);
|
|
||||||
}
|
if (payloadData.contains("eventSubscriptions")) {
|
||||||
|
if (!payloadData["eventSubscriptions"].is_number_unsigned()) {
|
||||||
if (payloadData.contains("eventSubscriptions")) {
|
ret.closeCode = WebSocketCloseCode::InvalidDataKeyType;
|
||||||
if (!payloadData["eventSubscriptions"].is_number_unsigned()) {
|
ret.closeReason = "Your `eventSubscriptions` is not an unsigned number.";
|
||||||
ret.closeCode = WebSocketCloseCode::InvalidDataKeyType;
|
return;
|
||||||
ret.closeReason = "Your `eventSubscriptions` is not an unsigned number.";
|
}
|
||||||
return;
|
session->SetEventSubscriptions(payloadData["eventSubscriptions"]);
|
||||||
}
|
}
|
||||||
session->SetEventSubscriptions(payloadData["eventSubscriptions"]);
|
}
|
||||||
}
|
|
||||||
}
|
void WebSocketServer::ProcessMessage(SessionPtr session, WebSocketServer::ProcessResult &ret, uint8_t opCode, json payloadData)
|
||||||
|
{
|
||||||
void WebSocketServer::ProcessMessage(SessionPtr session, WebSocketServer::ProcessResult &ret, uint8_t opCode, json payloadData)
|
if (!payloadData.is_object()) {
|
||||||
{
|
if (payloadData.is_null()) {
|
||||||
if (!payloadData.is_object()) {
|
ret.closeCode = WebSocketCloseCode::MissingDataKey;
|
||||||
if (payloadData.is_null()) {
|
ret.closeReason = "Your payload is missing data (`d`).";
|
||||||
ret.closeCode = WebSocketCloseCode::MissingDataKey;
|
} else {
|
||||||
ret.closeReason = "Your payload is missing data (`d`).";
|
ret.closeCode = WebSocketCloseCode::InvalidDataKeyType;
|
||||||
} else {
|
ret.closeReason = "Your payload's data (`d`) is not an object.";
|
||||||
ret.closeCode = WebSocketCloseCode::InvalidDataKeyType;
|
}
|
||||||
ret.closeReason = "Your payload's data (`d`) is not an object.";
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
// Only `Identify` is allowed when not identified
|
||||||
|
if (!session->IsIdentified() && opCode != 1) {
|
||||||
// Only `Identify` is allowed when not identified
|
ret.closeCode = WebSocketCloseCode::NotIdentified;
|
||||||
if (!session->IsIdentified() && opCode != 1) {
|
ret.closeReason = "You attempted to send a non-Identify message while not identified.";
|
||||||
ret.closeCode = WebSocketCloseCode::NotIdentified;
|
return;
|
||||||
ret.closeReason = "You attempted to send a non-Identify message while not identified.";
|
}
|
||||||
return;
|
|
||||||
}
|
switch (opCode) {
|
||||||
|
case WebSocketOpCode::Identify: { // Identify
|
||||||
switch (opCode) {
|
std::unique_lock<std::mutex> sessionLock(session->OperationMutex);
|
||||||
case WebSocketOpCode::Identify: { // Identify
|
if (session->IsIdentified()) {
|
||||||
std::unique_lock<std::mutex> sessionLock(session->OperationMutex);
|
if (!session->IgnoreInvalidMessages()) {
|
||||||
if (session->IsIdentified()) {
|
ret.closeCode = WebSocketCloseCode::AlreadyIdentified;
|
||||||
if (!session->IgnoreInvalidMessages()) {
|
ret.closeReason = "You are already Identified with the obs-websocket server.";
|
||||||
ret.closeCode = WebSocketCloseCode::AlreadyIdentified;
|
}
|
||||||
ret.closeReason = "You are already Identified with the obs-websocket server.";
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
if (session->AuthenticationRequired()) {
|
||||||
|
if (!payloadData.contains("authentication")) {
|
||||||
if (session->AuthenticationRequired()) {
|
ret.closeCode = WebSocketCloseCode::AuthenticationFailed;
|
||||||
if (!payloadData.contains("authentication")) {
|
ret.closeReason = "Your payload's data is missing an `authentication` string, however authentication is required.";
|
||||||
ret.closeCode = WebSocketCloseCode::AuthenticationFailed;
|
return;
|
||||||
ret.closeReason = "Your payload's data is missing an `authentication` string, however authentication is required.";
|
}
|
||||||
return;
|
if (!Utils::Crypto::CheckAuthenticationString(session->Secret(), session->Challenge(), payloadData["authentication"])) {
|
||||||
}
|
auto conf = GetConfig();
|
||||||
if (!Utils::Crypto::CheckAuthenticationString(session->Secret(), session->Challenge(), payloadData["authentication"])) {
|
if (conf && conf->AlertsEnabled) {
|
||||||
auto conf = GetConfig();
|
QString title = obs_module_text("OBSWebSocket.TrayNotification.AuthenticationFailed.Title");
|
||||||
if (conf && conf->AlertsEnabled) {
|
QString body = QString(obs_module_text("OBSWebSocket.TrayNotification.AuthenticationFailed.Body")).arg(QString::fromStdString(session->RemoteAddress()));
|
||||||
QString title = obs_module_text("OBSWebSocket.TrayNotification.AuthenticationFailed.Title");
|
Utils::Platform::SendTrayNotification(QSystemTrayIcon::Warning, title, body);
|
||||||
QString body = QString(obs_module_text("OBSWebSocket.TrayNotification.AuthenticationFailed.Body")).arg(QString::fromStdString(session->RemoteAddress()));
|
}
|
||||||
Utils::Platform::SendTrayNotification(QSystemTrayIcon::Warning, title, body);
|
ret.closeCode = WebSocketCloseCode::AuthenticationFailed;
|
||||||
}
|
ret.closeReason = "Authentication failed.";
|
||||||
ret.closeCode = WebSocketCloseCode::AuthenticationFailed;
|
return;
|
||||||
ret.closeReason = "Authentication failed.";
|
}
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
}
|
if (!payloadData.contains("rpcVersion")) {
|
||||||
|
ret.closeCode = WebSocketCloseCode::MissingDataKey;
|
||||||
if (!payloadData.contains("rpcVersion")) {
|
ret.closeReason = "Your payload's data is missing an `rpcVersion`.";
|
||||||
ret.closeCode = WebSocketCloseCode::MissingDataKey;
|
return;
|
||||||
ret.closeReason = "Your payload's data is missing an `rpcVersion`.";
|
}
|
||||||
return;
|
|
||||||
}
|
if (!payloadData["rpcVersion"].is_number_unsigned()) {
|
||||||
|
ret.closeCode = WebSocketCloseCode::InvalidDataKeyType;
|
||||||
if (!payloadData["rpcVersion"].is_number_unsigned()) {
|
ret.closeReason = "Your `rpcVersion` is not an unsigned number.";
|
||||||
ret.closeCode = WebSocketCloseCode::InvalidDataKeyType;
|
}
|
||||||
ret.closeReason = "Your `rpcVersion` is not an unsigned number.";
|
|
||||||
}
|
uint8_t requestedRpcVersion = payloadData["rpcVersion"];
|
||||||
|
if (!IsSupportedRpcVersion(requestedRpcVersion)) {
|
||||||
uint8_t requestedRpcVersion = payloadData["rpcVersion"];
|
ret.closeCode = WebSocketCloseCode::UnsupportedRpcVersion;
|
||||||
if (!IsSupportedRpcVersion(requestedRpcVersion)) {
|
ret.closeReason = "Your requested RPC version is not supported by this server.";
|
||||||
ret.closeCode = WebSocketCloseCode::UnsupportedRpcVersion;
|
return;
|
||||||
ret.closeReason = "Your requested RPC version is not supported by this server.";
|
}
|
||||||
return;
|
session->SetRpcVersion(requestedRpcVersion);
|
||||||
}
|
|
||||||
session->SetRpcVersion(requestedRpcVersion);
|
SetSessionParameters(session, ret, payloadData);
|
||||||
|
if (ret.closeCode != WebSocketCloseCode::DontClose) {
|
||||||
SetSessionParameters(session, ret, payloadData);
|
return;
|
||||||
if (ret.closeCode != WebSocketCloseCode::DontClose) {
|
}
|
||||||
return;
|
|
||||||
}
|
// Increment refs for event subscriptions
|
||||||
|
auto eventHandler = GetEventHandler();
|
||||||
// Increment refs for event subscriptions
|
eventHandler->ProcessSubscription(session->EventSubscriptions());
|
||||||
auto eventHandler = GetEventHandler();
|
|
||||||
eventHandler->ProcessSubscription(session->EventSubscriptions());
|
// Mark session as identified
|
||||||
|
session->SetIsIdentified(true);
|
||||||
// Mark session as identified
|
|
||||||
session->SetIsIdentified(true);
|
// Send desktop notification. TODO: Move to UI code
|
||||||
|
auto conf = GetConfig();
|
||||||
// Send desktop notification. TODO: Move to UI code
|
if (conf && conf->AlertsEnabled) {
|
||||||
auto conf = GetConfig();
|
QString title = obs_module_text("OBSWebSocket.TrayNotification.Identified.Title");
|
||||||
if (conf && conf->AlertsEnabled) {
|
QString body = QString(obs_module_text("OBSWebSocket.TrayNotification.Identified.Body")).arg(QString::fromStdString(session->RemoteAddress()));
|
||||||
QString title = obs_module_text("OBSWebSocket.TrayNotification.Identified.Title");
|
Utils::Platform::SendTrayNotification(QSystemTrayIcon::Information, title, body);
|
||||||
QString body = QString(obs_module_text("OBSWebSocket.TrayNotification.Identified.Body")).arg(QString::fromStdString(session->RemoteAddress()));
|
}
|
||||||
Utils::Platform::SendTrayNotification(QSystemTrayIcon::Information, title, body);
|
|
||||||
}
|
ret.result["op"] = WebSocketOpCode::Identified;
|
||||||
|
ret.result["d"]["negotiatedRpcVersion"] = session->RpcVersion();
|
||||||
ret.result["op"] = WebSocketOpCode::Identified;
|
} return;
|
||||||
ret.result["d"]["negotiatedRpcVersion"] = session->RpcVersion();
|
case WebSocketOpCode::Reidentify: { // Reidentify
|
||||||
} return;
|
std::unique_lock<std::mutex> sessionLock(session->OperationMutex);
|
||||||
case WebSocketOpCode::Reidentify: { // Reidentify
|
|
||||||
std::unique_lock<std::mutex> sessionLock(session->OperationMutex);
|
// Decrement refs for current subscriptions
|
||||||
|
auto eventHandler = GetEventHandler();
|
||||||
// Decrement refs for current subscriptions
|
eventHandler->ProcessUnsubscription(session->EventSubscriptions());
|
||||||
auto eventHandler = GetEventHandler();
|
|
||||||
eventHandler->ProcessUnsubscription(session->EventSubscriptions());
|
SetSessionParameters(session, ret, payloadData);
|
||||||
|
if (ret.closeCode != WebSocketCloseCode::DontClose) {
|
||||||
SetSessionParameters(session, ret, payloadData);
|
return;
|
||||||
if (ret.closeCode != WebSocketCloseCode::DontClose) {
|
}
|
||||||
return;
|
|
||||||
}
|
// Increment refs for new subscriptions
|
||||||
|
eventHandler->ProcessSubscription(session->EventSubscriptions());
|
||||||
// Increment refs for new subscriptions
|
|
||||||
eventHandler->ProcessSubscription(session->EventSubscriptions());
|
ret.result["op"] = WebSocketOpCode::Identified;
|
||||||
|
ret.result["d"]["negotiatedRpcVersion"] = session->RpcVersion();
|
||||||
ret.result["op"] = WebSocketOpCode::Identified;
|
} return;
|
||||||
ret.result["d"]["negotiatedRpcVersion"] = session->RpcVersion();
|
case WebSocketOpCode::Request: { // Request
|
||||||
} return;
|
// RequestID checking has to be done here where we are able to close the connection.
|
||||||
case WebSocketOpCode::Request: { // Request
|
if (!payloadData.contains("requestId")) {
|
||||||
// RequestID checking has to be done here where we are able to close the connection.
|
if (!session->IgnoreInvalidMessages()) {
|
||||||
if (!payloadData.contains("requestId")) {
|
ret.closeCode = WebSocketCloseCode::MissingDataKey;
|
||||||
if (!session->IgnoreInvalidMessages()) {
|
ret.closeReason = "Your payload data is missing a `requestId`.";
|
||||||
ret.closeCode = WebSocketCloseCode::MissingDataKey;
|
}
|
||||||
ret.closeReason = "Your payload data is missing a `requestId`.";
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
RequestHandler requestHandler(session);
|
||||||
|
Request request(payloadData["requestType"], payloadData["requestData"]);
|
||||||
RequestHandler requestHandler(session);
|
|
||||||
Request request(payloadData["requestType"], payloadData["requestData"]);
|
RequestResult requestResult = requestHandler.ProcessRequest(request);
|
||||||
|
|
||||||
RequestResult requestResult = requestHandler.ProcessRequest(request);
|
json resultPayloadData;
|
||||||
|
resultPayloadData["requestType"] = payloadData["requestType"];
|
||||||
json resultPayloadData;
|
resultPayloadData["requestId"] = payloadData["requestId"];
|
||||||
resultPayloadData["requestType"] = payloadData["requestType"];
|
resultPayloadData["requestStatus"] = {
|
||||||
resultPayloadData["requestId"] = payloadData["requestId"];
|
{"result", requestResult.StatusCode == RequestStatus::Success},
|
||||||
resultPayloadData["requestStatus"] = {
|
{"code", requestResult.StatusCode}
|
||||||
{"result", requestResult.StatusCode == RequestStatus::Success},
|
};
|
||||||
{"code", requestResult.StatusCode}
|
if (!requestResult.Comment.empty())
|
||||||
};
|
resultPayloadData["requestStatus"]["comment"] = requestResult.Comment;
|
||||||
if (!requestResult.Comment.empty())
|
if (requestResult.ResponseData.is_object())
|
||||||
resultPayloadData["requestStatus"]["comment"] = requestResult.Comment;
|
resultPayloadData["responseData"] = requestResult.ResponseData;
|
||||||
if (requestResult.ResponseData.is_object())
|
ret.result["op"] = WebSocketOpCode::RequestResponse;
|
||||||
resultPayloadData["responseData"] = requestResult.ResponseData;
|
ret.result["d"] = resultPayloadData;
|
||||||
ret.result["op"] = WebSocketOpCode::RequestResponse;
|
} return;
|
||||||
ret.result["d"] = resultPayloadData;
|
case WebSocketOpCode::RequestBatch: { // RequestBatch
|
||||||
} return;
|
// RequestID checking has to be done here where we are able to close the connection.
|
||||||
case WebSocketOpCode::RequestBatch: { // RequestBatch
|
if (!payloadData.contains("requestId")) {
|
||||||
// RequestID checking has to be done here where we are able to close the connection.
|
if (!session->IgnoreInvalidMessages()) {
|
||||||
if (!payloadData.contains("requestId")) {
|
ret.closeCode = WebSocketCloseCode::MissingDataKey;
|
||||||
if (!session->IgnoreInvalidMessages()) {
|
ret.closeReason = "Your payload data is missing a `requestId`.";
|
||||||
ret.closeCode = WebSocketCloseCode::MissingDataKey;
|
}
|
||||||
ret.closeReason = "Your payload data is missing a `requestId`.";
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
if (!payloadData.contains("requests")) {
|
||||||
|
if (!session->IgnoreInvalidMessages()) {
|
||||||
if (!payloadData.contains("requests")) {
|
ret.closeCode = WebSocketCloseCode::MissingDataKey;
|
||||||
if (!session->IgnoreInvalidMessages()) {
|
ret.closeReason = "Your payload data is missing a `requests`.";
|
||||||
ret.closeCode = WebSocketCloseCode::MissingDataKey;
|
}
|
||||||
ret.closeReason = "Your payload data is missing a `requests`.";
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
if (!payloadData["requests"].is_array()) {
|
||||||
|
if (!session->IgnoreInvalidMessages()) {
|
||||||
if (!payloadData["requests"].is_array()) {
|
ret.closeCode = WebSocketCloseCode::InvalidDataKeyType;
|
||||||
if (!session->IgnoreInvalidMessages()) {
|
ret.closeReason = "Your `requests` is not an array.";
|
||||||
ret.closeCode = WebSocketCloseCode::InvalidDataKeyType;
|
}
|
||||||
ret.closeReason = "Your `requests` is not an array.";
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
std::vector<json> requests = payloadData["requests"];
|
||||||
|
json results = json::array();
|
||||||
std::vector<json> requests = payloadData["requests"];
|
|
||||||
json results = json::array();
|
RequestHandler requestHandler(session);
|
||||||
|
for (auto requestJson : requests) {
|
||||||
RequestHandler requestHandler(session);
|
Request request(requestJson["requestType"], requestJson["requestData"]);
|
||||||
for (auto requestJson : requests) {
|
|
||||||
Request request(requestJson["requestType"], requestJson["requestData"]);
|
RequestResult requestResult = requestHandler.ProcessRequest(request);
|
||||||
|
|
||||||
RequestResult requestResult = requestHandler.ProcessRequest(request);
|
json result;
|
||||||
|
result["requestType"] = requestJson["requestType"];
|
||||||
json result;
|
|
||||||
result["requestType"] = requestJson["requestType"];
|
if (requestJson.contains("requestId"))
|
||||||
|
result["requestId"] = requestJson["requestId"];
|
||||||
if (requestJson.contains("requestId"))
|
|
||||||
result["requestId"] = requestJson["requestId"];
|
result["requestStatus"] = {
|
||||||
|
{"result", requestResult.StatusCode == RequestStatus::Success},
|
||||||
result["requestStatus"] = {
|
{"code", requestResult.StatusCode}
|
||||||
{"result", requestResult.StatusCode == RequestStatus::Success},
|
};
|
||||||
{"code", requestResult.StatusCode}
|
|
||||||
};
|
if (!requestResult.Comment.empty())
|
||||||
|
result["requestStatus"]["comment"] = requestResult.Comment;
|
||||||
if (!requestResult.Comment.empty())
|
|
||||||
result["requestStatus"]["comment"] = requestResult.Comment;
|
if (requestResult.ResponseData.is_object())
|
||||||
|
result["responseData"] = requestResult.ResponseData;
|
||||||
if (requestResult.ResponseData.is_object())
|
|
||||||
result["responseData"] = requestResult.ResponseData;
|
results.push_back(result);
|
||||||
|
}
|
||||||
results.push_back(result);
|
|
||||||
}
|
ret.result["op"] = WebSocketOpCode::RequestBatchResponse;
|
||||||
|
ret.result["d"]["requestId"] = payloadData["requestId"];
|
||||||
ret.result["op"] = WebSocketOpCode::RequestBatchResponse;
|
ret.result["d"]["results"] = results;
|
||||||
ret.result["d"]["requestId"] = payloadData["requestId"];
|
} return;
|
||||||
ret.result["d"]["results"] = results;
|
default:
|
||||||
} return;
|
if (!session->IgnoreInvalidMessages()) {
|
||||||
default:
|
ret.closeCode = WebSocketCloseCode::UnknownOpCode;
|
||||||
if (!session->IgnoreInvalidMessages()) {
|
ret.closeReason = std::string("Unknown OpCode: %s") + std::to_string(opCode);
|
||||||
ret.closeCode = WebSocketCloseCode::UnknownOpCode;
|
}
|
||||||
ret.closeReason = std::string("Unknown OpCode: %s") + std::to_string(opCode);
|
return;
|
||||||
}
|
}
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
}
|
void WebSocketServer::BroadcastEvent(uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion)
|
||||||
|
{
|
||||||
void WebSocketServer::BroadcastEvent(uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion)
|
if (!_server.is_listening())
|
||||||
{
|
return;
|
||||||
if (!_server.is_listening())
|
|
||||||
return;
|
QtConcurrent::run(&_threadPool, [=]() {
|
||||||
|
// Populate message object
|
||||||
QtConcurrent::run(&_threadPool, [=]() {
|
json eventMessage;
|
||||||
// Populate message object
|
eventMessage["op"] = 5;
|
||||||
json eventMessage;
|
eventMessage["d"]["eventType"] = eventType;
|
||||||
eventMessage["op"] = 5;
|
eventMessage["d"]["eventIntent"] = requiredIntent;
|
||||||
eventMessage["d"]["eventType"] = eventType;
|
if (eventData.is_object())
|
||||||
eventMessage["d"]["eventIntent"] = requiredIntent;
|
eventMessage["d"]["eventData"] = eventData;
|
||||||
if (eventData.is_object())
|
|
||||||
eventMessage["d"]["eventData"] = eventData;
|
// Initialize objects. The broadcast process only dumps the data when its needed.
|
||||||
|
std::string messageJson;
|
||||||
// Initialize objects. The broadcast process only dumps the data when its needed.
|
std::string messageMsgPack;
|
||||||
std::string messageJson;
|
|
||||||
std::string messageMsgPack;
|
// Recurse connected sessions and send the event to suitable sessions.
|
||||||
|
std::unique_lock<std::mutex> lock(_sessionMutex);
|
||||||
// Recurse connected sessions and send the event to suitable sessions.
|
for (auto & it : _sessions) {
|
||||||
std::unique_lock<std::mutex> lock(_sessionMutex);
|
if (!it.second->IsIdentified()) {
|
||||||
for (auto & it : _sessions) {
|
continue;
|
||||||
if (!it.second->IsIdentified()) {
|
}
|
||||||
continue;
|
if (rpcVersion && it.second->RpcVersion() != rpcVersion) {
|
||||||
}
|
continue;
|
||||||
if (rpcVersion && it.second->RpcVersion() != rpcVersion) {
|
}
|
||||||
continue;
|
if ((it.second->EventSubscriptions() & requiredIntent) != 0) {
|
||||||
}
|
websocketpp::lib::error_code errorCode;
|
||||||
if ((it.second->EventSubscriptions() & requiredIntent) != 0) {
|
switch (it.second->Encoding()) {
|
||||||
websocketpp::lib::error_code errorCode;
|
case WebSocketEncoding::Json:
|
||||||
switch (it.second->Encoding()) {
|
if (messageJson.empty()) {
|
||||||
case WebSocketEncoding::Json:
|
messageJson = eventMessage.dump();
|
||||||
if (messageJson.empty()) {
|
}
|
||||||
messageJson = eventMessage.dump();
|
_server.send((websocketpp::connection_hdl)it.first, messageJson, websocketpp::frame::opcode::text, errorCode);
|
||||||
}
|
it.second->IncrementOutgoingMessages();
|
||||||
_server.send((websocketpp::connection_hdl)it.first, messageJson, websocketpp::frame::opcode::text, errorCode);
|
break;
|
||||||
it.second->IncrementOutgoingMessages();
|
case WebSocketEncoding::MsgPack:
|
||||||
break;
|
if (messageMsgPack.empty()) {
|
||||||
case WebSocketEncoding::MsgPack:
|
auto msgPackData = json::to_msgpack(eventMessage);
|
||||||
if (messageMsgPack.empty()) {
|
messageMsgPack = std::string(msgPackData.begin(), msgPackData.end());
|
||||||
auto msgPackData = json::to_msgpack(eventMessage);
|
}
|
||||||
messageMsgPack = std::string(msgPackData.begin(), msgPackData.end());
|
_server.send((websocketpp::connection_hdl)it.first, messageMsgPack, websocketpp::frame::opcode::binary, errorCode);
|
||||||
}
|
it.second->IncrementOutgoingMessages();
|
||||||
_server.send((websocketpp::connection_hdl)it.first, messageMsgPack, websocketpp::frame::opcode::binary, errorCode);
|
break;
|
||||||
it.second->IncrementOutgoingMessages();
|
}
|
||||||
break;
|
if (errorCode)
|
||||||
}
|
blog(LOG_ERROR, "[WebSocketServer::BroadcastEvent] Error sending event message: %s", errorCode.message().c_str());
|
||||||
if (errorCode)
|
}
|
||||||
blog(LOG_ERROR, "[WebSocketServer::BroadcastEvent] Error sending event message: %s", errorCode.message().c_str());
|
}
|
||||||
}
|
lock.unlock();
|
||||||
}
|
if (_debugEnabled && (EventSubscription::All & requiredIntent) != 0) // Don't log high volume events
|
||||||
lock.unlock();
|
blog(LOG_INFO, "[WebSocketServer::BroadcastEvent] Outgoing event:\n%s", eventMessage.dump(2).c_str());
|
||||||
if (_debugEnabled && (EventSubscription::All & requiredIntent) != 0) // Don't log high volume events
|
});
|
||||||
blog(LOG_INFO, "[WebSocketServer::BroadcastEvent] Outgoing event:\n%s", eventMessage.dump(2).c_str());
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "WebSocketSession.h"
|
#include "WebSocketSession.h"
|
||||||
#include "eventhandler/types/EventSubscription.h"
|
#include "eventhandler/types/EventSubscription.h"
|
||||||
#include "plugin-macros.generated.h"
|
|
||||||
|
|
||||||
WebSocketSession::WebSocketSession() :
|
WebSocketSession::WebSocketSession() :
|
||||||
_remoteAddress(""),
|
_remoteAddress(""),
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "plugin-macros.generated.h"
|
||||||
|
|
||||||
class WebSocketSession;
|
class WebSocketSession;
|
||||||
typedef std::shared_ptr<WebSocketSession> SessionPtr;
|
typedef std::shared_ptr<WebSocketSession> SessionPtr;
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "EventHandler.h"
|
#include "EventHandler.h"
|
||||||
#include "../plugin-macros.generated.h"
|
|
||||||
|
|
||||||
EventHandler::EventHandler() :
|
EventHandler::EventHandler() :
|
||||||
_obsLoaded(false),
|
_obsLoaded(false),
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "types/EventSubscription.h"
|
#include "types/EventSubscription.h"
|
||||||
#include "../obs-websocket.h"
|
#include "../obs-websocket.h"
|
||||||
#include "../utils/Obs.h"
|
#include "../utils/Obs.h"
|
||||||
|
#include "../plugin-macros.generated.h"
|
||||||
|
|
||||||
template <typename T> T* GetCalldataPointer(const calldata_t *data, const char* name) {
|
template <typename T> T* GetCalldataPointer(const calldata_t *data, const char* name) {
|
||||||
void *ptr = nullptr;
|
void *ptr = nullptr;
|
||||||
@ -40,7 +41,7 @@ class EventHandler
|
|||||||
void ConnectSourceSignals(obs_source_t *source);
|
void ConnectSourceSignals(obs_source_t *source);
|
||||||
void DisconnectSourceSignals(obs_source_t *source);
|
void DisconnectSourceSignals(obs_source_t *source);
|
||||||
|
|
||||||
void BroadcastEvent(uint64_t requiredIntent, std::string eventType, json eventData = nullptr, uint8_t rpcVersion = 1);
|
void BroadcastEvent(uint64_t requiredIntent, std::string eventType, json eventData = nullptr, uint8_t rpcVersion = 0);
|
||||||
|
|
||||||
// Signal handler: frontend
|
// Signal handler: frontend
|
||||||
static void OnFrontendEvent(enum obs_frontend_event event, void *private_data);
|
static void OnFrontendEvent(enum obs_frontend_event event, void *private_data);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "EventHandler.h"
|
#include "EventHandler.h"
|
||||||
#include "../plugin-macros.generated.h"
|
|
||||||
|
|
||||||
void EventHandler::HandleCurrentSceneCollectionChanged()
|
void EventHandler::HandleCurrentSceneCollectionChanged()
|
||||||
{
|
{
|
||||||
|
@ -1,2 +1 @@
|
|||||||
#include "EventHandler.h"
|
#include "EventHandler.h"
|
||||||
#include "../plugin-macros.generated.h"
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "EventHandler.h"
|
#include "EventHandler.h"
|
||||||
#include "../plugin-macros.generated.h"
|
|
||||||
|
|
||||||
void EventHandler::HandleExitStarted()
|
void EventHandler::HandleExitStarted()
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "EventHandler.h"
|
#include "EventHandler.h"
|
||||||
#include "../plugin-macros.generated.h"
|
|
||||||
|
|
||||||
void EventHandler::HandleInputCreated(obs_source_t *source)
|
void EventHandler::HandleInputCreated(obs_source_t *source)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "EventHandler.h"
|
#include "EventHandler.h"
|
||||||
#include "../plugin-macros.generated.h"
|
|
||||||
|
|
||||||
#define CASE(x) case x: return #x;
|
#define CASE(x) case x: return #x;
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "EventHandler.h"
|
#include "EventHandler.h"
|
||||||
#include "../plugin-macros.generated.h"
|
|
||||||
|
|
||||||
#define CASE(x) case x: return #x;
|
#define CASE(x) case x: return #x;
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "EventHandler.h"
|
#include "EventHandler.h"
|
||||||
#include "../plugin-macros.generated.h"
|
|
||||||
|
|
||||||
void EventHandler::HandleSceneItemCreated(void *param, calldata_t *data)
|
void EventHandler::HandleSceneItemCreated(void *param, calldata_t *data)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "EventHandler.h"
|
#include "EventHandler.h"
|
||||||
#include "../plugin-macros.generated.h"
|
|
||||||
|
|
||||||
void EventHandler::HandleSceneCreated(obs_source_t *source)
|
void EventHandler::HandleSceneCreated(obs_source_t *source)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "EventHandler.h"
|
#include "EventHandler.h"
|
||||||
#include "../plugin-macros.generated.h"
|
|
||||||
|
|
||||||
void EventHandler::HandleTransitionCreated(obs_source_t *source)
|
void EventHandler::HandleTransitionCreated(obs_source_t *source)
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include "../obs-websocket.h"
|
#include "../obs-websocket.h"
|
||||||
#include "../Config.h"
|
#include "../Config.h"
|
||||||
#include "../utils/Platform.h"
|
#include "../utils/Platform.h"
|
||||||
#include "../plugin-macros.generated.h"
|
|
||||||
|
|
||||||
ConnectInfo::ConnectInfo(QWidget* parent) :
|
ConnectInfo::ConnectInfo(QWidget* parent) :
|
||||||
QDialog(parent, Qt::Dialog),
|
QDialog(parent, Qt::Dialog),
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <QtWidgets/QDialog>
|
#include <QtWidgets/QDialog>
|
||||||
|
|
||||||
|
#include "../plugin-macros.generated.h"
|
||||||
|
|
||||||
#include "ui_ConnectInfo.h"
|
#include "ui_ConnectInfo.h"
|
||||||
|
|
||||||
class ConnectInfo : public QDialog
|
class ConnectInfo : public QDialog
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "../Config.h"
|
#include "../Config.h"
|
||||||
#include "../WebSocketServer.h"
|
#include "../WebSocketServer.h"
|
||||||
#include "../utils/Crypto.h"
|
#include "../utils/Crypto.h"
|
||||||
#include "../plugin-macros.generated.h"
|
|
||||||
|
|
||||||
QString GetToolTipIconHtml()
|
QString GetToolTipIconHtml()
|
||||||
{
|
{
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include "ui_SettingsDialog.h"
|
|
||||||
#include "ConnectInfo.h"
|
#include "ConnectInfo.h"
|
||||||
|
#include "../plugin-macros.generated.h"
|
||||||
|
|
||||||
|
#include "ui_SettingsDialog.h"
|
||||||
|
|
||||||
class SettingsDialog : public QDialog
|
class SettingsDialog : public QDialog
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include <obs-data.h>
|
#include <obs-data.h>
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
|
|
||||||
#include "plugin-macros.generated.h"
|
|
||||||
#include "obs-websocket.h"
|
#include "obs-websocket.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "WebSocketServer.h"
|
#include "WebSocketServer.h"
|
||||||
@ -34,8 +33,7 @@ void ___properties_dummy_addref(obs_properties_t*) {};
|
|||||||
bool obs_module_load(void)
|
bool obs_module_load(void)
|
||||||
{
|
{
|
||||||
blog(LOG_INFO, "[obs_module_load] you can haz websockets (Version: %s | RPC Version: %d)", OBS_WEBSOCKET_VERSION, OBS_WEBSOCKET_RPC_VERSION);
|
blog(LOG_INFO, "[obs_module_load] you can haz websockets (Version: %s | RPC Version: %d)", OBS_WEBSOCKET_VERSION, OBS_WEBSOCKET_RPC_VERSION);
|
||||||
blog(LOG_INFO, "[obs_module_load] Qt version (compile-time): %s | Qt version (run-time): %s",
|
blog(LOG_INFO, "[obs_module_load] Qt version (compile-time): %s | Qt version (run-time): %s", QT_VERSION_STR, qVersion());
|
||||||
QT_VERSION_STR, qVersion());
|
|
||||||
|
|
||||||
// Randomize the random number generator
|
// Randomize the random number generator
|
||||||
qsrand(QTime::currentTime().msec());
|
qsrand(QTime::currentTime().msec());
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#pragma pop_macro("strtoll")
|
#pragma pop_macro("strtoll")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "plugin-macros.generated.h"
|
||||||
|
|
||||||
// Autorelease object definitions
|
// Autorelease object definitions
|
||||||
void ___source_dummy_addref(obs_source_t*);
|
void ___source_dummy_addref(obs_source_t*);
|
||||||
void ___sceneitem_dummy_addref(obs_sceneitem_t*);
|
void ___sceneitem_dummy_addref(obs_sceneitem_t*);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "RequestHandler.h"
|
#include "RequestHandler.h"
|
||||||
#include "../plugin-macros.generated.h"
|
|
||||||
|
|
||||||
const std::map<std::string, RequestMethodHandler> RequestHandler::_handlerMap
|
const std::map<std::string, RequestMethodHandler> RequestHandler::_handlerMap
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#include <QImageWriter>
|
#include <QImageWriter>
|
||||||
|
|
||||||
#include "RequestHandler.h"
|
#include "RequestHandler.h"
|
||||||
|
#include "../WebSocketServer.h"
|
||||||
#include "../eventhandler/types/EventSubscription.h"
|
#include "../eventhandler/types/EventSubscription.h"
|
||||||
#include "../obs-websocket.h"
|
#include "../obs-websocket.h"
|
||||||
#include "../WebSocketServer.h"
|
|
||||||
|
|
||||||
RequestResult RequestHandler::GetVersion(const Request& request)
|
RequestResult RequestHandler::GetVersion(const Request& request)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user