mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
server: import websockets++ server from master
This commit is contained in:
parent
974d6b48b2
commit
16bc68f2f9
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[submodule "deps/websocketpp"]
|
||||||
|
path = deps/websocketpp
|
||||||
|
url = https://github.com/zaphoyd/websocketpp.git
|
||||||
|
[submodule "deps/asio"]
|
||||||
|
path = deps/asio
|
||||||
|
url = https://github.com/chriskohlhoff/asio.git
|
@ -6,14 +6,26 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
if (WIN32 OR APPLE)
|
||||||
|
include(external/FindLibObs.cmake)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_definitions(-DASIO_STANDALONE)
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||||
|
endif()
|
||||||
|
|
||||||
if (WIN32 OR APPLE)
|
if (WIN32 OR APPLE)
|
||||||
include(external/FindLibObs.cmake)
|
include(external/FindLibObs.cmake)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(LibObs REQUIRED)
|
find_package(LibObs REQUIRED)
|
||||||
find_package(Qt5Core REQUIRED)
|
find_package(Qt5Core REQUIRED)
|
||||||
find_package(Qt5WebSockets REQUIRED)
|
|
||||||
find_package(Qt5Widgets REQUIRED)
|
find_package(Qt5Widgets REQUIRED)
|
||||||
|
find_package(Boost REQUIRED)
|
||||||
|
|
||||||
set(obs-websocket_SOURCES
|
set(obs-websocket_SOURCES
|
||||||
src/obs-websocket.cpp
|
src/obs-websocket.cpp
|
||||||
@ -52,13 +64,14 @@ add_library(obs-websocket MODULE
|
|||||||
include_directories(
|
include_directories(
|
||||||
"${LIBOBS_INCLUDE_DIR}/../UI/obs-frontend-api"
|
"${LIBOBS_INCLUDE_DIR}/../UI/obs-frontend-api"
|
||||||
${Qt5Core_INCLUDES}
|
${Qt5Core_INCLUDES}
|
||||||
${Qt5WebSockets_INCLUDES}
|
${Qt5Widgets_INCLUDES}
|
||||||
${Qt5Widgets_INCLUDES})
|
${Boost_INCLUDE_DIRS}
|
||||||
|
"${CMAKE_SOURCE_DIR}/deps/asio/asio/include"
|
||||||
|
"${CMAKE_SOURCE_DIR}/deps/websocketpp")
|
||||||
|
|
||||||
target_link_libraries(obs-websocket
|
target_link_libraries(obs-websocket
|
||||||
libobs
|
libobs
|
||||||
Qt5::Core
|
Qt5::Core
|
||||||
Qt5::WebSockets
|
|
||||||
Qt5::Widgets)
|
Qt5::Widgets)
|
||||||
|
|
||||||
# --- End of section ---
|
# --- End of section ---
|
||||||
@ -70,6 +83,8 @@ if(WIN32)
|
|||||||
message(FATAL_ERROR "Could not find OBS Frontend API's library !")
|
message(FATAL_ERROR "Could not find OBS Frontend API's library !")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
||||||
|
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
set(ARCH_NAME "64bit")
|
set(ARCH_NAME "64bit")
|
||||||
set(OBS_BUILDDIR_ARCH "build64")
|
set(OBS_BUILDDIR_ARCH "build64")
|
||||||
@ -102,8 +117,6 @@ if(WIN32)
|
|||||||
|
|
||||||
COMMAND if $<CONFIG:Release>==1 ("${CMAKE_COMMAND}" -E copy
|
COMMAND if $<CONFIG:Release>==1 ("${CMAKE_COMMAND}" -E copy
|
||||||
"$<TARGET_FILE:obs-websocket>"
|
"$<TARGET_FILE:obs-websocket>"
|
||||||
"${QTDIR}/bin/Qt5WebSockets.dll"
|
|
||||||
"${QTDIR}/bin/Qt5Network.dll"
|
|
||||||
"${RELEASE_DIR}/obs-plugins/${ARCH_NAME}")
|
"${RELEASE_DIR}/obs-plugins/${ARCH_NAME}")
|
||||||
|
|
||||||
# If config is RelWithDebInfo, package release files
|
# If config is RelWithDebInfo, package release files
|
||||||
@ -118,8 +131,6 @@ if(WIN32)
|
|||||||
|
|
||||||
COMMAND if $<CONFIG:RelWithDebInfo>==1 ("${CMAKE_COMMAND}" -E copy
|
COMMAND if $<CONFIG:RelWithDebInfo>==1 ("${CMAKE_COMMAND}" -E copy
|
||||||
"$<TARGET_FILE:obs-websocket>"
|
"$<TARGET_FILE:obs-websocket>"
|
||||||
"${QTDIR}/bin/Qt5WebSockets.dll"
|
|
||||||
"${QTDIR}/bin/Qt5Network.dll"
|
|
||||||
"${RELEASE_DIR}/obs-plugins/${ARCH_NAME}")
|
"${RELEASE_DIR}/obs-plugins/${ARCH_NAME}")
|
||||||
|
|
||||||
COMMAND if $<CONFIG:RelWithDebInfo>==1 ("${CMAKE_COMMAND}" -E copy
|
COMMAND if $<CONFIG:RelWithDebInfo>==1 ("${CMAKE_COMMAND}" -E copy
|
||||||
@ -130,8 +141,6 @@ if(WIN32)
|
|||||||
COMMAND if $<CONFIG:Debug>==1 (
|
COMMAND if $<CONFIG:Debug>==1 (
|
||||||
"${CMAKE_COMMAND}" -E copy
|
"${CMAKE_COMMAND}" -E copy
|
||||||
"$<TARGET_FILE:obs-websocket>"
|
"$<TARGET_FILE:obs-websocket>"
|
||||||
"${QTDIR}/bin/Qt5WebSocketsd.dll"
|
|
||||||
"${QTDIR}/bin/Qt5Networkd.dll"
|
|
||||||
"${LIBOBS_INCLUDE_DIR}/../${OBS_BUILDDIR_ARCH}/rundir/$<CONFIG>/obs-plugins/${ARCH_NAME}")
|
"${LIBOBS_INCLUDE_DIR}/../${OBS_BUILDDIR_ARCH}/rundir/$<CONFIG>/obs-plugins/${ARCH_NAME}")
|
||||||
|
|
||||||
COMMAND if $<CONFIG:Debug>==1 (
|
COMMAND if $<CONFIG:Debug>==1 (
|
||||||
@ -155,11 +164,8 @@ endif()
|
|||||||
|
|
||||||
# --- Linux-specific build settings and tasks ---
|
# --- Linux-specific build settings and tasks ---
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
|
||||||
|
|
||||||
set_target_properties(obs-websocket PROPERTIES PREFIX "")
|
set_target_properties(obs-websocket PROPERTIES PREFIX "")
|
||||||
target_link_libraries(obs-websocket
|
target_link_libraries(obs-websocket obs-frontend-api)
|
||||||
obs-frontend-api)
|
|
||||||
|
|
||||||
file(GLOB locale_files data/locale/*.ini)
|
file(GLOB locale_files data/locale/*.ini)
|
||||||
|
|
||||||
|
227
src/WSServer.cpp
227
src/WSServer.cpp
@ -16,11 +16,11 @@ You should have received a copy of the GNU General Public License along
|
|||||||
with this program. If not, see <https://www.gnu.org/licenses/>
|
with this program. If not, see <https://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QtWebSockets/QWebSocket>
|
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
#include <QtCore/QByteArray>
|
#include <QtCore/QByteArray>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QtConcurrent/QtConcurrent>
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
|
|
||||||
#include "WSServer.h"
|
#include "WSServer.h"
|
||||||
@ -30,139 +30,178 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
QT_USE_NAMESPACE
|
QT_USE_NAMESPACE
|
||||||
|
|
||||||
|
using websocketpp::lib::placeholders::_1;
|
||||||
|
using websocketpp::lib::placeholders::_2;
|
||||||
|
using websocketpp::lib::bind;
|
||||||
|
|
||||||
WSServer* WSServer::Instance = nullptr;
|
WSServer* WSServer::Instance = nullptr;
|
||||||
|
|
||||||
|
QString decodeBase64(const QString& source)
|
||||||
|
{
|
||||||
|
return QString::fromUtf8(
|
||||||
|
QByteArray::fromBase64(
|
||||||
|
source.toUtf8()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
WSServer::WSServer(QObject* parent)
|
WSServer::WSServer(QObject* parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
_wsServer(Q_NULLPTR),
|
_connections(),
|
||||||
_clients(),
|
|
||||||
_clMutex(QMutex::Recursive)
|
_clMutex(QMutex::Recursive)
|
||||||
{
|
{
|
||||||
_wsServer = new QWebSocketServer(
|
_server.init_asio();
|
||||||
QStringLiteral("obs-websocket"),
|
|
||||||
QWebSocketServer::NonSecureMode);
|
_server.set_validate_handler(bind(&WSServer::validateConnection, this, ::_1));
|
||||||
|
_server.set_open_handler(bind(&WSServer::onOpen, this, ::_1));
|
||||||
|
_server.set_close_handler(bind(&WSServer::onClose, this, ::_1));
|
||||||
|
_server.set_message_handler(bind(&WSServer::onMessage, this, ::_1, ::_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
WSServer::~WSServer() {
|
WSServer::~WSServer()
|
||||||
Stop();
|
{
|
||||||
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSServer::Start(quint16 port) {
|
void WSServer::start(quint16 port)
|
||||||
if (port == _wsServer->serverPort())
|
{
|
||||||
|
if (_server.is_listening() && port == _serverPort) {
|
||||||
|
blog(LOG_INFO, "WebSocketsServer::start: server already on this port. no restart needed");
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(_wsServer->isListening())
|
|
||||||
Stop();
|
|
||||||
|
|
||||||
bool serverStarted = _wsServer->listen(QHostAddress::Any, port);
|
|
||||||
if (serverStarted) {
|
|
||||||
blog(LOG_INFO, "server started successfully on TCP port %d", port);
|
|
||||||
|
|
||||||
connect(_wsServer, SIGNAL(newConnection()),
|
|
||||||
this, SLOT(onNewConnection()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
QString errorString = _wsServer->errorString();
|
|
||||||
blog(LOG_ERROR,
|
|
||||||
"error: failed to start server on TCP port %d: %s",
|
|
||||||
port, errorString.toUtf8().constData());
|
|
||||||
|
|
||||||
QMainWindow* mainWindow = (QMainWindow*)obs_frontend_get_main_window();
|
|
||||||
|
|
||||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
|
||||||
QString title = tr("OBSWebsocket.Server.StartFailed.Title");
|
|
||||||
QString msg = tr("OBSWebsocket.Server.StartFailed.Message").arg(port);
|
|
||||||
obs_frontend_pop_ui_translation();
|
|
||||||
|
|
||||||
QMessageBox::warning(mainWindow, title, msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSServer::Stop() {
|
if (_server.is_listening()) {
|
||||||
QMutexLocker locker(&_clMutex);
|
stop();
|
||||||
for(QWebSocket* pClient : _clients) {
|
|
||||||
pClient->close();
|
|
||||||
}
|
}
|
||||||
locker.unlock();
|
|
||||||
|
|
||||||
_wsServer->close();
|
_serverPort = port;
|
||||||
|
|
||||||
|
_server.listen(_serverPort);
|
||||||
|
_server.start_accept();
|
||||||
|
|
||||||
|
QtConcurrent::run([=]() {
|
||||||
|
_server.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
blog(LOG_INFO, "server started successfully on port %d", _serverPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WSServer::stop()
|
||||||
|
{
|
||||||
|
_server.stop();
|
||||||
|
_server.stop_listening();
|
||||||
blog(LOG_INFO, "server stopped successfully");
|
blog(LOG_INFO, "server stopped successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSServer::broadcast(QString message) {
|
void WSServer::broadcast(QString message)
|
||||||
|
{
|
||||||
QMutexLocker locker(&_clMutex);
|
QMutexLocker locker(&_clMutex);
|
||||||
for(QWebSocket* pClient : _clients) {
|
for (connection_hdl hdl : _connections) {
|
||||||
if (Config::Current()->AuthRequired
|
_server.send(hdl, message.toStdString(), websocketpp::frame::opcode::text);
|
||||||
&& (pClient->property(PROP_AUTHENTICATED).toBool() == false)) {
|
|
||||||
// Skip this client if unauthenticated
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pClient->sendTextMessage(message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSServer::onNewConnection() {
|
bool WSServer::validateConnection(connection_hdl hdl)
|
||||||
QWebSocket* pSocket = _wsServer->nextPendingConnection();
|
{
|
||||||
if (pSocket) {
|
// TODO enforce subprotocol
|
||||||
connect(pSocket, SIGNAL(textMessageReceived(const QString&)),
|
|
||||||
this, SLOT(onTextMessageReceived(QString)));
|
|
||||||
connect(pSocket, SIGNAL(disconnected()),
|
|
||||||
this, SLOT(onSocketDisconnected()));
|
|
||||||
|
|
||||||
pSocket->setProperty(PROP_AUTHENTICATED, false);
|
Config* config = Config::Current();
|
||||||
|
if (config->AuthRequired) {
|
||||||
|
auto conn = _server.get_con_from_hdl(hdl);
|
||||||
|
|
||||||
|
QString authorization =
|
||||||
|
QString::fromStdString(conn->get_request_header("Authorization"));
|
||||||
|
if (!authorization.isNull() && !authorization.isEmpty()) {
|
||||||
|
const QStringList& parts = authorization.split(" ", QString::SplitBehavior::SkipEmptyParts);
|
||||||
|
if (parts.length() >= 2) {
|
||||||
|
const QString& authType = parts.at(0);
|
||||||
|
const QString& authValue = parts.at(1);
|
||||||
|
|
||||||
|
if (authType == "Basic") {
|
||||||
|
const QStringList& decodedParts =
|
||||||
|
decodeBase64(authValue).split(":", QString::SplitBehavior::SkipEmptyParts);
|
||||||
|
if (decodedParts.length() >= 2) {
|
||||||
|
const QString& username = decodedParts.at(0);
|
||||||
|
const QString& password = decodedParts.at(1);
|
||||||
|
|
||||||
|
// TODO time-constant string comparison
|
||||||
|
if (password == config->AuthPassword) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->set_status(websocketpp::http::status_code::unauthorized);
|
||||||
|
conn->append_header("WWW-Authenticate", "Basic charset=\"UTF-8\"");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WSServer::onOpen(connection_hdl hdl)
|
||||||
|
{
|
||||||
QMutexLocker locker(&_clMutex);
|
QMutexLocker locker(&_clMutex);
|
||||||
_clients << pSocket;
|
_connections.insert(hdl);
|
||||||
locker.unlock();
|
locker.unlock();
|
||||||
|
|
||||||
QHostAddress clientAddr = pSocket->peerAddress();
|
QString clientIp = getRemoteEndpoint(hdl);
|
||||||
QString clientIp = Utils::FormatIPAddress(clientAddr);
|
notifyConnection(clientIp);
|
||||||
|
blog(LOG_INFO, "new client connection from %s", clientIp.toUtf8().constData());
|
||||||
|
}
|
||||||
|
|
||||||
blog(LOG_INFO, "new client connection from %s:%d",
|
void WSServer::onMessage(connection_hdl hdl, server::message_ptr message)
|
||||||
clientIp.toUtf8().constData(), pSocket->peerPort());
|
{
|
||||||
|
auto opcode = message->get_opcode();
|
||||||
|
if (opcode != websocketpp::frame::opcode::text) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString payload = QString::fromStdString(message->get_payload());
|
||||||
|
|
||||||
|
// TODO refactor handler
|
||||||
|
WSRequestHandler handler;
|
||||||
|
handler.processIncomingMessage(payload);
|
||||||
|
std::string response = handler.getResponse().toStdString();
|
||||||
|
|
||||||
|
_server.send(hdl, response, websocketpp::frame::opcode::text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WSServer::onClose(connection_hdl hdl)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&_clMutex);
|
||||||
|
_connections.erase(hdl);
|
||||||
|
locker.unlock();
|
||||||
|
|
||||||
|
QString clientIp = getRemoteEndpoint(hdl);
|
||||||
|
notifyDisconnection(clientIp);
|
||||||
|
blog(LOG_INFO, "client %s disconnected", clientIp.toUtf8().constData());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString WSServer::getRemoteEndpoint(connection_hdl hdl)
|
||||||
|
{
|
||||||
|
auto conn = _server.get_con_from_hdl(hdl);
|
||||||
|
return QString::fromStdString(conn->get_remote_endpoint());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WSServer::notifyConnection(QString clientIp)
|
||||||
|
{
|
||||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||||
QString title = tr("OBSWebsocket.NotifyConnect.Title");
|
QString title = tr("OBSWebsocket.NotifyConnect.Title");
|
||||||
QString msg = tr("OBSWebsocket.NotifyConnect.Message")
|
QString msg = tr("OBSWebsocket.NotifyConnect.Message").arg(clientIp);
|
||||||
.arg(Utils::FormatIPAddress(clientAddr));
|
|
||||||
obs_frontend_pop_ui_translation();
|
obs_frontend_pop_ui_translation();
|
||||||
|
|
||||||
Utils::SysTrayNotify(msg, QSystemTrayIcon::Information, title);
|
Utils::SysTrayNotify(msg, QSystemTrayIcon::Information, title);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void WSServer::onTextMessageReceived(QString message) {
|
|
||||||
QWebSocket* pSocket = qobject_cast<QWebSocket*>(sender());
|
|
||||||
if (pSocket) {
|
|
||||||
WSRequestHandler handler(pSocket);
|
|
||||||
handler.processIncomingMessage(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WSServer::onSocketDisconnected() {
|
|
||||||
QWebSocket* pSocket = qobject_cast<QWebSocket*>(sender());
|
|
||||||
if (pSocket) {
|
|
||||||
pSocket->setProperty(PROP_AUTHENTICATED, false);
|
|
||||||
|
|
||||||
QMutexLocker locker(&_clMutex);
|
|
||||||
_clients.removeAll(pSocket);
|
|
||||||
locker.unlock();
|
|
||||||
|
|
||||||
pSocket->deleteLater();
|
|
||||||
|
|
||||||
QHostAddress clientAddr = pSocket->peerAddress();
|
|
||||||
QString clientIp = Utils::FormatIPAddress(clientAddr);
|
|
||||||
|
|
||||||
blog(LOG_INFO, "client %s:%d disconnected",
|
|
||||||
clientIp.toUtf8().constData(), pSocket->peerPort());
|
|
||||||
|
|
||||||
|
void WSServer::notifyDisconnection(QString clientIp)
|
||||||
|
{
|
||||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||||
QString title = tr("OBSWebsocket.NotifyDisconnect.Title");
|
QString title = tr("OBSWebsocket.NotifyDisconnect.Title");
|
||||||
QString msg = tr("OBSWebsocket.NotifyDisconnect.Message")
|
QString msg = tr("OBSWebsocket.NotifyDisconnect.Message").arg(clientIp);
|
||||||
.arg(Utils::FormatIPAddress(clientAddr));
|
|
||||||
obs_frontend_pop_ui_translation();
|
obs_frontend_pop_ui_translation();
|
||||||
|
|
||||||
Utils::SysTrayNotify(msg, QSystemTrayIcon::Information, title);
|
Utils::SysTrayNotify(msg, QSystemTrayIcon::Information, title);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -20,32 +20,47 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
|||||||
#define WSSERVER_H
|
#define WSSERVER_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QList>
|
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <websocketpp/config/asio_no_tls.hpp>
|
||||||
|
#include <websocketpp/server.hpp>
|
||||||
|
|
||||||
#include "WSRequestHandler.h"
|
#include "WSRequestHandler.h"
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QWebSocketServer)
|
QT_FORWARD_DECLARE_CLASS(QWebSocketServer)
|
||||||
QT_FORWARD_DECLARE_CLASS(QWebSocket)
|
QT_FORWARD_DECLARE_CLASS(QWebSocket)
|
||||||
|
|
||||||
class WSServer : public QObject {
|
using websocketpp::connection_hdl;
|
||||||
|
|
||||||
|
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||||
|
typedef std::set<connection_hdl,std::owner_less<connection_hdl>> con_list;
|
||||||
|
|
||||||
|
class WSServer : public QObject
|
||||||
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit WSServer(QObject* parent = Q_NULLPTR);
|
explicit WSServer(QObject* parent = Q_NULLPTR);
|
||||||
virtual ~WSServer();
|
virtual ~WSServer();
|
||||||
void Start(quint16 port);
|
void start(quint16 port);
|
||||||
void Stop();
|
void stop();
|
||||||
void broadcast(QString message);
|
void broadcast(QString message);
|
||||||
static WSServer* Instance;
|
static WSServer* Instance;
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onNewConnection();
|
|
||||||
void onTextMessageReceived(QString message);
|
|
||||||
void onSocketDisconnected();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWebSocketServer* _wsServer;
|
bool validateConnection(connection_hdl hdl);
|
||||||
QList<QWebSocket*> _clients;
|
void onOpen(connection_hdl hdl);
|
||||||
|
void onMessage(connection_hdl hdl, server::message_ptr message);
|
||||||
|
void onClose(connection_hdl hdl);
|
||||||
|
|
||||||
|
QString getRemoteEndpoint(connection_hdl hdl);
|
||||||
|
void notifyConnection(QString clientIp);
|
||||||
|
void notifyDisconnection(QString clientIp);
|
||||||
|
|
||||||
|
server _server;
|
||||||
|
quint16 _serverPort;
|
||||||
|
con_list _connections;
|
||||||
QMutex _clMutex;
|
QMutex _clMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user