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;
}