Code SslWebSocketServer.cpp
#include "sslWebSocketServer.h"
SslWebSocketServer::SslWebSocketServer(quint16 port, QObject *parent) :
QObject(parent),
webSocketServer(nullptr)
{
webSocketServer = new QWebSocketServer(QStringLiteral("SSL WebSocket Server"),
QWebSocketServer::SecureMode,
this);
QSslConfiguration sslConfiguration;
QFile certFile(QStringLiteral(":/localhost.crt"));
QFile keyFile(QStringLiteral(":/localhost.key"));
certFile.open(QIODevice::ReadOnly);
keyFile.open(QIODevice::ReadOnly);
QSslCertificate certificate(&certFile, QSsl::Pem);
QSslKey sslKey(&keyFile, QSsl::Rsa, QSsl::Pem);
certFile.close();
keyFile.close();
sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
sslConfiguration.setLocalCertificate(certificate);
sslConfiguration.setPrivateKey(sslKey);
webSocketServer->setSslConfiguration(sslConfiguration);
if (webSocketServer->listen(QHostAddress::Any, port))
{
qDebug() << "SSL WebSocket Server listening on port" << port;
connect(webSocketServer, &QWebSocketServer::newConnection, this, &SslWebSocketServer::onNewConnection);
connect(webSocketServer, &QWebSocketServer::closed, this, &SslWebSocketServer::closed);
connect(webSocketServer, &QWebSocketServer::sslErrors, this, &SslWebSocketServer::onSslErrors);
}
// Запись на диск в отдельном потоке
SaveImage *saveImage = new SaveImage();
saveImage->moveToThread(&imageSaveThread);
connect(&imageSaveThread, &QThread::finished, saveImage, &QObject::deleteLater);
connect(this, &SslWebSocketServer::operate, saveImage, &SaveImage::doWork);
connect(saveImage, &SaveImage::resultReady, this, &SslWebSocketServer::handleResults);
}
SslWebSocketServer::~SslWebSocketServer(){
imageSaveThread.quit();
imageSaveThread.wait();
webSocketServer->close();
qDeleteAll(clients.keyBegin(), clients.keyEnd());
clients.clear();
}
// Create and get localPath
QString SslWebSocketServer::getDataPath(QString &localPath)
{
QString user_movie_path = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).at(0);
QDir movie_dir(user_movie_path);
movie_dir.mkpath("SslWebSocketServer/" + localPath);
return movie_dir.absoluteFilePath("SslWebSocketServer/" + localPath);
}
// Новое соединение. Adds socket in QMap<QWebSocket*, QString>
void SslWebSocketServer::onNewConnection()
{
QWebSocket *pSocket = webSocketServer->nextPendingConnection();
qDebug() << "Client connected:" << pSocket;
connect(pSocket, &QWebSocket::textMessageReceived, this, &SslWebSocketServer::getTextMessage);
connect(pSocket, &QWebSocket::binaryMessageReceived, this, &SslWebSocketServer::getBinaryMessage);
connect(pSocket, &QWebSocket::disconnected, this, &SslWebSocketServer::socketDisconnected);
imageSaveThread.start();
clients.insert(pSocket, "empty");
qDebug() << clients.size();
}
// Slot.
// Прием имени подписки и ее сохранение.
// Передача имени объекта и имени файла клиентам.
void SslWebSocketServer::getTextMessage(QString message)
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
if (pClient)
{
// index - позиция разделителя и длина принятой команды
int index = message.indexOf(":");
int length = message.size() - (message.indexOf(":") + 1);
// Для текущего клиента
for(QMap<QWebSocket*, QString >::iterator it = clients.begin(); it != clients.end(); ++it) {
if(it.key() == pClient) {
// Если команда подписка - сохраним ее имя в карте
if(message.left(index) == "Subscription") {
subscription = message.right(length);
//qDebug() << subscription << pClient;
it.value()= subscription;
pClient->sendTextMessage("O.K.");
return;
}
//ObjectName
if(message.left(index) == "ObjectName"){
objectName = message.right(length);
return;
}
//File name - не уходим, идем к передаче для других клиентов
if(message.left(index) == "FileName") {
// Имя файла для своего клиента
fileName = message.right(length);
}
}
}
// Для других клиентов. Отправка текстовых имен клиентам с той же подпиской
for(QMap<QWebSocket*, QString >::iterator it = clients.begin(); it != clients.end(); ++it) {
if((it.key() != pClient) && (subscription == it.value())) {
it.key()->sendTextMessage(message);
}
}
}
}
// Slot. Получить image и записать на диск
// Отправка изображения клиентам с той же подпиской
void SslWebSocketServer::getBinaryMessage(QByteArray message)
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
if (pClient)
{
// Сохраним изображение на диске
if(!message.isEmpty()) image = QImage::fromData(message,"jpg"); else { qDebug()<< "ImageArray empty..."; return;}
for(QMap<QWebSocket*, QString>::iterator it = clients.begin(); it != clients.end(); ++it) {
// find a client
if(it.key() == pClient) {
subscription = it.value();
if(it.value()!= "empty") {
emit operate(image, getDataPath(subscription)+"/" + fileName + ".jpg");
} else
qDebug()<< Q_FUNC_INFO << "Error subscription for: " << pClient;
}
}
// Отправка изображения клиентам с той же подпиской
for(QMap<QWebSocket*, QString>::iterator it = clients.begin(); it != clients.end(); ++it) {
if((it.key() != pClient) && (subscription == it.value())) {
it.key()->sendBinaryMessage(message);
//qDebug() << "send bynary" << it.key();
}
}
}
}
// Отключить клиент и удалить его из списка
void SslWebSocketServer::socketDisconnected()
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
if (pClient)
{
for(QMap<QWebSocket*, QString>::iterator it = clients.begin(); it != clients.end(); ++it) {
if(it.key() == pClient) {
qDebug() << "Client disconnected " << pClient;
clients.erase(it);
pClient->disconnect();
pClient->deleteLater();
}
}
// qDebug() << clients.size();
}
}
// Finish writing to disk
void SslWebSocketServer::handleResults(const QString &result){
qDebug()<< result ;
}
void SslWebSocketServer::onSslErrors(const QList<QSslError> &)
{
qDebug() << "Ssl errors occurred";
}