From 3d68b7c9e535431ff607b83f3a8929ab4e6f363b Mon Sep 17 00:00:00 2001 From: Palakis Date: Thu, 23 Feb 2017 21:01:24 +0100 Subject: [PATCH] Updated locale variables names + WIP Dynamic Server Settings --- Config.cpp | 96 +++++++++++++++++++++++++-------------- Config.h | 10 +++- WSEvents.cpp | 7 ++- WSEvents.h | 2 +- WSServer.cpp | 31 +++++++++++-- WSServer.h | 5 +- data/locale/de-DE.ini | 8 ++-- data/locale/en-US.ini | 10 ++-- data/locale/fr-FR.ini | 10 ++-- forms/settings-dialog.cpp | 65 +++++++++++++++++++------- forms/settings-dialog.ui | 50 ++++++++++++++++---- obs-websocket.cpp | 23 ++++++---- 12 files changed, 224 insertions(+), 93 deletions(-) diff --git a/Config.cpp b/Config.cpp index 070ad6b3..97f6b1d5 100644 --- a/Config.cpp +++ b/Config.cpp @@ -19,22 +19,41 @@ with this program. If not, see #include #include #include +#include #include "Config.h" -#define CONFIG_SECTION_NAME "obs-websocket" -#define CONFIG_PARAM_SECRET "auth_hash" -#define CONFIG_PARAM_SALT "auth_salt" -#define CONFIG_PARAM_AUTHREQUIRED "auth_required" +#define SECTION_NAME "obs-websocket" +#define PARAM_ENABLE "server_enabled" +#define PARAM_PORT "server_port" +#define PARAM_SECRET "auth_hash" +#define PARAM_SALT "auth_salt" +#define PARAM_AUTHREQUIRED "auth_required" Config *Config::_instance = new Config(); -Config::Config() { +Config::Config() +{ // Default settings + ServerEnabled = true; + ServerPort = 4444; + AuthRequired = false; Secret = ""; Salt = ""; SettingsLoaded = false; + // OBS Config defaults + config_t* obs_config = obs_frontend_get_global_config(); + if (obs_config) + { + config_set_default_bool(obs_config, SECTION_NAME, PARAM_ENABLE, ServerEnabled); + config_set_default_uint(obs_config, SECTION_NAME, PARAM_PORT, ServerPort); + + config_set_default_bool(obs_config, SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired); + config_set_default_string(obs_config, SECTION_NAME, PARAM_SECRET, Secret); + config_set_default_string(obs_config, SECTION_NAME, PARAM_SALT, Salt); + } + mbedtls_entropy_init(&entropy); mbedtls_ctr_drbg_init(&rng); mbedtls_ctr_drbg_seed(&rng, mbedtls_entropy_func, &entropy, nullptr, 0); @@ -43,12 +62,40 @@ Config::Config() { SessionChallenge = GenerateSalt(); } -Config::~Config() { +Config::~Config() +{ mbedtls_ctr_drbg_free(&rng); mbedtls_entropy_free(&entropy); } -const char* Config::GenerateSalt() { +void Config::Load() +{ + config_t* obs_config = obs_frontend_get_global_config(); + + ServerEnabled = config_get_bool(obs_config, SECTION_NAME, PARAM_ENABLE); + ServerPort = config_get_uint(obs_config, SECTION_NAME, PARAM_PORT); + + AuthRequired = config_get_bool(obs_config, SECTION_NAME, PARAM_AUTHREQUIRED); + Secret = config_get_string(obs_config, SECTION_NAME, PARAM_SECRET); + Salt = config_get_string(obs_config, SECTION_NAME, PARAM_SALT); +} + +void Config::Save() +{ + config_t* obs_config = obs_frontend_get_global_config(); + + config_set_bool(obs_config, SECTION_NAME, PARAM_ENABLE, ServerEnabled); + config_set_uint(obs_config, SECTION_NAME, PARAM_PORT, ServerPort); + + config_set_bool(obs_config, SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired); + config_set_string(obs_config, SECTION_NAME, PARAM_SECRET, Secret); + config_set_string(obs_config, SECTION_NAME, PARAM_SALT, Salt); + + config_save(obs_config); +} + +const char* Config::GenerateSalt() +{ // Generate 32 random chars unsigned char *random_chars = (unsigned char *)bzalloc(32); mbedtls_ctr_drbg_random(&rng, random_chars, 32); @@ -63,7 +110,8 @@ const char* Config::GenerateSalt() { return (char *)salt; } -const char* Config::GenerateSecret(const char *password, const char *salt) { +const char* Config::GenerateSecret(const char *password, const char *salt) +{ size_t passwordLength = strlen(password); size_t saltLength = strlen(salt); @@ -88,7 +136,8 @@ const char* Config::GenerateSecret(const char *password, const char *salt) { return (char*)challenge; } -void Config::SetPassword(const char *password) { +void Config::SetPassword(const char *password) +{ const char *new_salt = GenerateSalt(); const char *new_challenge = GenerateSecret(password, new_salt); @@ -96,7 +145,8 @@ void Config::SetPassword(const char *password) { this->Secret = new_challenge; } -bool Config::CheckAuth(const char *response) { +bool Config::CheckAuth(const char *response) +{ size_t secretLength = strlen(this->Secret); size_t sessChallengeLength = strlen(this->SessionChallenge); @@ -125,29 +175,7 @@ bool Config::CheckAuth(const char *response) { } } -void Config::OBSSaveCallback(obs_data_t *save_data, bool saving, void *private_data) { - Config *conf = static_cast(private_data); - - if (saving) { - obs_data_t *settings = obs_data_create(); - obs_data_set_bool(settings, CONFIG_PARAM_AUTHREQUIRED, conf->AuthRequired); - obs_data_set_string(settings, CONFIG_PARAM_SECRET, conf->Secret); - obs_data_set_string(settings, CONFIG_PARAM_SALT, conf->Salt); - - obs_data_set_obj(save_data, CONFIG_SECTION_NAME, settings); - } - else { - obs_data_t *settings = obs_data_get_obj(save_data, CONFIG_SECTION_NAME); - if (settings) { - conf->AuthRequired = obs_data_get_bool(settings, CONFIG_PARAM_AUTHREQUIRED); - conf->Secret = obs_data_get_string(settings, CONFIG_PARAM_SECRET); - conf->Salt = obs_data_get_string(settings, CONFIG_PARAM_SALT); - - conf->SettingsLoaded = true; - } - } -} - -Config* Config::Current() { +Config* Config::Current() +{ return _instance; } diff --git a/Config.h b/Config.h index c1ad3ff1..a39b1796 100644 --- a/Config.h +++ b/Config.h @@ -23,15 +23,21 @@ with this program. If not, see #include #include -class Config { +class Config +{ public: Config(); ~Config(); + void Load(); + void Save(); + void SetPassword(const char *password); bool CheckAuth(const char *userChallenge); const char* GenerateSalt(); static const char* GenerateSecret(const char *password, const char *salt); - static void OBSSaveCallback(obs_data_t *save_data, bool saving, void *); + + bool ServerEnabled; + uint64_t ServerPort; bool AuthRequired; const char *Secret; diff --git a/WSEvents.cpp b/WSEvents.cpp index 45032ae1..09714f32 100644 --- a/WSEvents.cpp +++ b/WSEvents.cpp @@ -19,8 +19,8 @@ with this program. If not, see #include "WSEvents.h" -WSEvents::WSEvents(WSServer *server) { - _srv = server; +WSEvents::WSEvents(WSServer *srv) { + _srv = srv; obs_frontend_add_event_callback(WSEvents::FrontendEventHandler, this); QTimer *statusTimer = new QTimer(); @@ -39,6 +39,9 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void *private { WSEvents *owner = static_cast(private_data); + if (!owner->_srv) + return; + // TODO : implement SourceChanged, SourceOrderChanged and RepopulateSources if (event == OBS_FRONTEND_EVENT_SCENE_CHANGED) { diff --git a/WSEvents.h b/WSEvents.h index cfb428fb..6bcbbd67 100644 --- a/WSEvents.h +++ b/WSEvents.h @@ -31,7 +31,7 @@ class WSEvents : public QObject Q_OBJECT public: - explicit WSEvents(WSServer *server); + explicit WSEvents(WSServer *srv); ~WSEvents(); static void FrontendEventHandler(enum obs_frontend_event event, void *private_data); diff --git a/WSServer.cpp b/WSServer.cpp index 7daeea24..57d46191 100644 --- a/WSServer.cpp +++ b/WSServer.cpp @@ -29,7 +29,9 @@ with this program. If not, see QT_USE_NAMESPACE -WSServer::WSServer(quint16 port, QObject *parent) : +WSServer* WSServer::Instance = new WSServer(); + +WSServer::WSServer(QObject *parent) : QObject(parent), _wsServer(Q_NULLPTR), _clients(), @@ -44,6 +46,22 @@ WSServer::WSServer(quint16 port, QObject *parent) : _wsServer->moveToThread(_serverThread); _serverThread->start(); +} + +WSServer::~WSServer() +{ + Stop(); + + delete _serverThread; +} + +void WSServer::Start(quint16 port) +{ + if (port == _wsServer->serverPort()) + return; + + if(_wsServer->isListening()) + Stop(); bool serverStarted = _wsServer->listen(QHostAddress::Any, port); if (serverStarted) @@ -52,15 +70,18 @@ WSServer::WSServer(quint16 port, QObject *parent) : } } -WSServer::~WSServer() +void WSServer::Stop() { - _wsServer->close(); - _clMutex.lock(); + Q_FOREACH(QWebSocket *pClient, _clients) + { + pClient->close(); + } + qDeleteAll(_clients.begin(), _clients.end()); _clMutex.unlock(); - delete _serverThread; + _wsServer->close(); } void WSServer::broadcast(QString message) diff --git a/WSServer.h b/WSServer.h index 993d0229..10b9971e 100644 --- a/WSServer.h +++ b/WSServer.h @@ -34,9 +34,12 @@ class WSServer : public QObject Q_OBJECT public: - explicit WSServer(quint16 port, QObject *parent = Q_NULLPTR); + explicit WSServer(QObject *parent = Q_NULLPTR); virtual ~WSServer(); + void Start(quint16 port); + void Stop(); void broadcast(QString message); + static WSServer* Instance; private Q_SLOTS: void onNewConnection(); diff --git a/data/locale/de-DE.ini b/data/locale/de-DE.ini index 33c642b4..cb929178 100644 --- a/data/locale/de-DE.ini +++ b/data/locale/de-DE.ini @@ -1,4 +1,4 @@ -Menu.SettingsItem="Websocket-Server Einstellungen" -Settings.DialogTitle="Websocket-Server Einstellungen" -Settings.AuthRequired="Authentifizierung erforderlich" -Settings.Password="Passwort" +OBSWebsocket.Menu.SettingsItem="Websocket-Server Einstellungen" +OBSWebsocket.Settings.DialogTitle="Websocket-Server Einstellungen" +OBSWebsocket.Settings.AuthRequired="Authentifizierung erforderlich" +OBSWebsocket.Settings.Password="Passwort" \ No newline at end of file diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 35e950a8..28938b3b 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -1,4 +1,6 @@ -Menu.SettingsItem="Websocket server settings" -Settings.DialogTitle="obs-websocket" -Settings.AuthRequired="Enable authentication" -Settings.Password="Password" \ No newline at end of file +OBSWebsocket.Menu.SettingsItem="Websocket server settings" +OBSWebsocket.Settings.DialogTitle="obs-websocket" +OBSWebsocket.Settings.ServerEnable="Enable Websocket server" +OBSWebsocket.Settings.ServerPort="Server Port" +OBSWebsocket.Settings.AuthRequired="Enable authentication" +OBSWebsocket.Settings.Password="Password" \ No newline at end of file diff --git a/data/locale/fr-FR.ini b/data/locale/fr-FR.ini index e44dde5c..2d81315a 100644 --- a/data/locale/fr-FR.ini +++ b/data/locale/fr-FR.ini @@ -1,4 +1,6 @@ -Menu.SettingsItem="Paramètres du serveur Websocket" -Settings.DialogTitle="obs-websocket" -Settings.AuthRequired="Activer l'authentification" -Settings.Password="Mot de passe" \ No newline at end of file +OBSWebsocket.Menu.SettingsItem="Paramètres du serveur Websocket" +OBSWebsocket.Settings.DialogTitle="obs-websocket" +OBSWebsocket.Settings.ServerEnable="Activer le serveur Websockets" +OBSWebsocket.Settings.ServerPort="Port du serveur" +OBSWebsocket.Settings.AuthRequired="Activer l'authentification" +OBSWebsocket.Settings.Password="Mot de passe" \ No newline at end of file diff --git a/forms/settings-dialog.cpp b/forms/settings-dialog.cpp index 724f97cf..62e9cd98 100644 --- a/forms/settings-dialog.cpp +++ b/forms/settings-dialog.cpp @@ -17,9 +17,12 @@ with this program. If not, see */ #include + +#include "obs-websocket.h" +#include "Config.h" +#include "WSServer.h" #include "settings-dialog.h" #include "ui_settings-dialog.h" -#include "Config.h" #define CHANGE_ME "changeme" @@ -35,12 +38,19 @@ SettingsDialog::SettingsDialog(QWidget *parent) : AuthCheckboxChanged(); } -void SettingsDialog::showEvent(QShowEvent *event) { - ui->authRequired->setChecked(Config::Current()->AuthRequired); +void SettingsDialog::showEvent(QShowEvent *event) +{ + Config* conf = Config::Current(); + + ui->serverEnabled->setChecked(conf->ServerEnabled); + ui->serverPort->setValue(conf->ServerPort); + + ui->authRequired->setChecked(conf->AuthRequired); ui->password->setText(CHANGE_ME); } -void SettingsDialog::ToggleShowHide() { +void SettingsDialog::ToggleShowHide() +{ if (!isVisible()) { setVisible(true); } @@ -49,7 +59,8 @@ void SettingsDialog::ToggleShowHide() { } } -void SettingsDialog::AuthCheckboxChanged() { +void SettingsDialog::AuthCheckboxChanged() +{ if (ui->authRequired->isChecked()) { ui->password->setEnabled(true); } @@ -58,28 +69,48 @@ void SettingsDialog::AuthCheckboxChanged() { } } -void SettingsDialog::FormAccepted() { - if (ui->authRequired->isChecked()) { - if (ui->password->text() != CHANGE_ME) { +void SettingsDialog::FormAccepted() +{ + Config* conf = Config::Current(); + + conf->ServerEnabled = ui->serverEnabled->isChecked(); + conf->ServerPort = ui->serverPort->value(); + + if (ui->authRequired->isChecked()) + { + if (ui->password->text() != CHANGE_ME) + { QByteArray pwd = ui->password->text().toLocal8Bit(); const char *new_password = pwd; blog(LOG_INFO, "new password : %s", new_password); - Config::Current()->SetPassword(new_password); + conf->SetPassword(new_password); } - if (strcmp(Config::Current()->Secret, "") != 0) { - Config::Current()->AuthRequired = true; + if (strcmp(Config::Current()->Secret, "") != 0) + { + conf->AuthRequired = true; } - else { - Config::Current()->AuthRequired = false; + else + { + conf->AuthRequired = false; } } - else { - Config::Current()->AuthRequired = false; + else + { + conf->AuthRequired = false; + } + + conf->Save(); + + if (conf->ServerEnabled) + { + WSServer::Instance->Start(conf->ServerPort); + } + else + { + WSServer::Instance->Stop(); } - - obs_frontend_save(); } SettingsDialog::~SettingsDialog() diff --git a/forms/settings-dialog.ui b/forms/settings-dialog.ui index e905a1ec..108da584 100644 --- a/forms/settings-dialog.ui +++ b/forms/settings-dialog.ui @@ -6,8 +6,8 @@ 0 0 - 354 - 110 + 407 + 155 @@ -17,7 +17,7 @@ - Settings.DialogTitle + OBSWebsocket.Settings.DialogTitle false @@ -28,24 +28,54 @@ - - + + - Settings.Password + OBSWebsocket.Settings.AuthRequired - + + + + OBSWebsocket.Settings.Password + + + + QLineEdit::Password - - + + - Settings.AuthRequired + OBSWebsocket.Settings.ServerEnable + + + true + + + + + + + OBSWebsocket.Settings.ServerPort + + + + + + + 1024 + + + 65535 + + + 4444 diff --git a/obs-websocket.cpp b/obs-websocket.cpp index 422a82d4..01c0644f 100644 --- a/obs-websocket.cpp +++ b/obs-websocket.cpp @@ -21,8 +21,8 @@ with this program. If not, see #include #include "obs-websocket.h" -#include "WSEvents.h" #include "WSServer.h" +#include "WSEvents.h" #include "Config.h" #include "forms/settings-dialog.h" @@ -30,19 +30,21 @@ OBS_DECLARE_MODULE() OBS_MODULE_USE_DEFAULT_LOCALE("obs-websocket", "en-US") WSEvents *eventHandler; -WSServer *server; SettingsDialog *settings_dialog; bool obs_module_load(void) { - blog(LOG_INFO, "[obs-websockets] you can haz websockets (version %s)", OBS_WEBSOCKET_VERSION); - - server = new WSServer(4444); - eventHandler = new WSEvents(server); - - obs_frontend_add_save_callback(Config::OBSSaveCallback, Config::Current()); + // Core setup + Config* config = Config::Current(); + config->Load(); - QAction *menu_action = (QAction*)obs_frontend_add_tools_menu_qaction(obs_module_text("Menu.SettingsItem")); + if (config->ServerEnabled) + WSServer::Instance->Start(config->ServerPort); + + eventHandler = new WSEvents(WSServer::Instance); + + // UI setup + QAction *menu_action = (QAction*)obs_frontend_add_tools_menu_qaction(obs_module_text("OBSWebsocket.Menu.SettingsItem")); obs_frontend_push_ui_translation(obs_module_get_string); settings_dialog = new SettingsDialog(); @@ -53,6 +55,9 @@ bool obs_module_load(void) }; menu_action->connect(menu_action, &QAction::triggered, menu_cb); + // Loading finished + blog(LOG_INFO, "[obs-websockets] you can haz websockets (version %s)", OBS_WEBSOCKET_VERSION); + return true; }