/* obs-websocket Copyright (C) 2016 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 "WSServer.h" #include "WSRequestHandler.h" #include "Config.h" #include #include #include #include #include #include "obs-websocket.h" QT_USE_NAMESPACE WSServer::WSServer(quint16 port, QObject *parent) : QObject(parent), _wsServer(Q_NULLPTR), _clients(), _clMutex(QMutex::NonRecursive) { _serverThread = new QThread(); _wsServer = new QWebSocketServer( QStringLiteral("obs-websocket"), QWebSocketServer::NonSecureMode, this); _wsServer->moveToThread(_serverThread); _serverThread->start(); bool serverStarted = _wsServer->listen(QHostAddress::Any, port); if (serverStarted) { connect(_wsServer, &QWebSocketServer::newConnection, this, &WSServer::onNewConnection); } } WSServer::~WSServer() { _wsServer->close(); _clMutex.lock(); qDeleteAll(_clients.begin(), _clients.end()); _clMutex.unlock(); delete _serverThread; } void WSServer::broadcast(QString message) { _clMutex.lock(); Q_FOREACH(QWebSocket *pClient, _clients) { if (Config::Current()->AuthRequired && (pClient->property(PROP_AUTHENTICATED).toBool() == false)) { // Skip this client if unauthenticated continue; } pClient->sendTextMessage(message); } _clMutex.unlock(); } void WSServer::onNewConnection() { QWebSocket *pSocket = _wsServer->nextPendingConnection(); if (pSocket) { connect(pSocket, &QWebSocket::textMessageReceived, this, &WSServer::textMessageReceived); connect(pSocket, &QWebSocket::disconnected, this, &WSServer::socketDisconnected); pSocket->setProperty(PROP_AUTHENTICATED, false); _clMutex.lock(); _clients << pSocket; _clMutex.unlock(); QByteArray client_ip = pSocket->peerAddress().toString().toUtf8(); blog(LOG_INFO, "[obs-websockets] new client connection from %s:%d", client_ip.constData(), pSocket->peerPort()); } } void WSServer::textMessageReceived(QString message) { QWebSocket *pSocket = qobject_cast(sender()); if (pSocket) { WSRequestHandler handler(pSocket); handler.processIncomingMessage(message); } } void WSServer::socketDisconnected() { QWebSocket *pSocket = qobject_cast(sender()); if (pSocket) { pSocket->setProperty(PROP_AUTHENTICATED, false); _clMutex.lock(); _clients.removeAll(pSocket); _clMutex.unlock(); pSocket->deleteLater(); QByteArray client_ip = pSocket->peerAddress().toString().toUtf8(); blog(LOG_INFO, "[obs-websockets] client %s:%d disconnected", client_ip.constData(), pSocket->peerPort()); } }