mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-06 10:03:26 -08:00
Some checks are pending
CodeQL / Analyze (cpp) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 cover (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 26 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Desktop / Prune caches (push) Waiting to run
Build Docker / Servatrice (arm) (push) Waiting to run
Build Docker / Servatrice (x86) (push) Waiting to run
Build Docker / Publish multi-platform Servatrice image (push) Blocked by required conditions
* [Security] Add challenge-response auth with scrypt verifiers and stop storing plaintext passwords Challenge-response authentication: the client derives a scrypt verifier (RFC 7914, EVP_PBE_scrypt, N=32768, r=8, p=1) and authenticates with HMAC-SHA256(key, nonce), so neither the password nor its hash is transmitted. The stored format becomes "$scrypt$<n>$<r>$<p>$<salt>$<verifier>" and Response_PasswordSalt now carries the cost parameters. Strict servers only accept scrypt verifiers; legacy accounts are migrated after a successful login. Fix #344 for challenge-response servers: a saved profile stores the derived verifier under the password key instead of the plaintext password. The connect dialog loads it without revealing it, autoconnect passes it through, the change-password dialog no longer prefills the old password field with it, and the client only persists the verifier when "Save password" is checked. Took 3 minutes Took 1 minute Took 10 seconds Took 7 minutes * [Security] Harden credential format acceptance and challenge nonce validation * [Security] Refuse KDF downgrade; trim profile name and warn on silent credential drop * [Security] Add SupportsAll ServerOptions enumerator to fix enum validation assert The server advertised both SupportsPasswordHash (1) and SupportsChallengeResponseAuth (2) via a bitwise-OR that produced the value 3, which no enumerator declared. Protobuf's proto2 enum validation rejects the value in _internal_set_server_options, crashing servatrice on the debug assertion. Add a SupportsAll = 3 enumerator with an identical wire value so the bitmask reads unchanged while the value is now a documented, valid member of the enum. * [Security] Normalize username when issuing challenge nonce cmdRequestPasswordSalt bound the challenge nonce to the raw, un-simplified username while cmdLogin verifies it against the simplified name. A user who typed leading or trailing whitespace in the username box would be silently rejected during challenge-response login even with the correct password. Simplify at the nonce-issuing site so both commands agree on the normalized name. Also drive-by formatting: collapse the now single-expression serverOptions initializer onto one line. * [Security] Keep an encrypted legacy password backup for old-client logins Migrating an account to scrypt stranded pre-challenge clients, which can only present the legacy salt+hash: after migration the server served them a scrypt salt they cannot use, so the only recovery was a password reset. When security/legacy_backup_key is configured (64 hex chars, openssl rand -hex 32), submitPasswordVerifier now seals the legacy credential with AES-256-GCM under that key before overwriting the row, storing it in password_legacy_backup with the time it was last used. Old clients keep working: cmdRequestPasswordSalt serves the backup's 16-char salt in password_salt so they can derive the legacy hash they were always able to compute, while new clients derive the verifier from the new scrypt_salt field, which always carries the verifier salt. The non-challenge login path accepts the plaintext or legacy hash against the decrypted backup and refreshes its window; a migrated row with no usable backup fails closed. Backups age out so a database dump taken after the window closes never carries a crackable legacy hash: getUsableLegacyBackup purges on first use past security/legacy_backup_ttl_days (default 90, clamped 1..3650), and a six-hourly sweep drops backups idle accounts never touch. changeUserPassword clears the backup since a new credential invalidates it. Without a configured key nothing is sealed or purged, so a temporarily missing key cannot destroy existing backups. The AAD is the simplified user name on both sides, sealing the blob to its row so it cannot be moved between accounts. Sealing failures degrade to the previous lockout behaviour rather than blocking migration. The columns extend the unmerged 0036->0037 migration, so the schema version stays 37. * [Security] Address review: proto compat, plaintext verify, AAD case, strict scope Fix the two blockers and follow-ups from the 2026-10-16 review: - Advertise challenge-response in a new supports_challenge_response field instead of the ServerOptions enum and drop SupportsAll: proto2 enums are closed, so already-released clients parsed server_options = 3 as NoOptions and fell back to plaintext passwords. server_options stays exactly SupportsPasswordHash on the wire; old clients ignore the new field. - Verify a plaintext password directly against a migrated scrypt row with verifyPassword() so email changes (cmdAccountEdit) and old clients sending password keep working without a legacy backup key. Pre-hashed values are still checked against the backup, and its TTL window is refreshed only when the backup is what actually matched. - Use the stored row name as the AES-GCM AAD on both seal and open so a login whose case differs from the stored name (utf8mb4_unicode_ci) still opens its backup. - Require challenge-response in strict mode only for registered SQL accounts (userExists gate), leaving guest/unregistered logins and none/password auth methods unaffected. - Document in servatrice.ini.example that a captured legacy hash can take over a not-yet-migrated account and that strict only constrains registered SQL accounts. Schema version is 38. * [Security] Raise legacy backup TTL default to 180 days Gives operators and slow-to-upgrade users a longer downgrade window for pre-challenge clients before unused encrypted legacy password backups age out. * [Security] Fix servatrice.cpp formatting per clang-format-18 * [Security] Add missing forward declaration for Command_SubmitPasswordVerifier The cmdSubmitPasswordVerifier declaration references the proto-generated type, which otherwise does not name a type in this header and breaks every C++ build. --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de> Co-authored-by: BruebachL <bruebachl@cockatrice.example>
352 lines
16 KiB
C++
352 lines
16 KiB
C++
/***************************************************************************
|
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
|
* brukie@laptop *
|
|
* *
|
|
* 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, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
***************************************************************************/
|
|
#ifndef SERVERSOCKETINTERFACE_H
|
|
#define SERVERSOCKETINTERFACE_H
|
|
|
|
#include "libcockatrice/protocol/pb/response.pb.h"
|
|
#include "libcockatrice/protocol/pb/server_message.pb.h"
|
|
|
|
#include <QAbstractSocket>
|
|
#include <QByteArray>
|
|
#include <QHostAddress>
|
|
#include <QList>
|
|
#include <QMutex>
|
|
#include <QString>
|
|
#include <QStringList>
|
|
#include <QTcpSocket>
|
|
#include <QWebSocket>
|
|
#include <QtGlobal>
|
|
#include <qtmetamacros.h>
|
|
#include <server_protocolhandler.h>
|
|
|
|
class Servatrice;
|
|
class Servatrice_DatabaseInterface;
|
|
class DeckList;
|
|
class ServerInfo_DeckStorage_Folder;
|
|
class Command_AddToList;
|
|
class Command_RemoveFromList;
|
|
class Command_DeckList;
|
|
class Command_DeckListOtherUser;
|
|
class Command_DeckNewDir;
|
|
class Command_DeckDelDir;
|
|
class Command_DeckDel;
|
|
class Command_DeckDownload;
|
|
class Command_DeckDownloadPublic;
|
|
class Command_DeckUpload;
|
|
class Command_DeckSetVisibility;
|
|
class Command_DeckShareCreate;
|
|
class Command_DeckShareList;
|
|
class Command_DeckShareListMine;
|
|
class Command_DeckShareRemove;
|
|
class Command_DeckShareDownload;
|
|
class Command_ReplayList;
|
|
class Command_ReplayDownload;
|
|
class Command_ReplayModifyMatch;
|
|
class Command_ReplayDeleteMatch;
|
|
class Command_ReplayGetCode;
|
|
class Command_ReplaySubmitCode;
|
|
class Command_BanFromServer;
|
|
class Command_UpdateServerMessage;
|
|
class Command_ShutdownServer;
|
|
class Command_ReloadConfig;
|
|
class Command_ReplayDownloadByGameId;
|
|
class Command_AccountEdit;
|
|
class Command_AccountImage;
|
|
class Command_AccountPassword;
|
|
class Command_Activate;
|
|
class Command_AddCardArtRule;
|
|
class Command_AdjustMod;
|
|
class Command_ForceActivateUser;
|
|
class Command_ForgotPasswordChallenge;
|
|
class Command_ForgotPasswordRequest;
|
|
class Command_ForgotPasswordReset;
|
|
class Command_GetAdminNotes;
|
|
class Command_GetBanHistory;
|
|
class Command_GetModeratorLastLogins;
|
|
class Command_GetServerStats;
|
|
class Command_GetUserAlts;
|
|
class Command_GetUserSessions;
|
|
class Command_GetWarnHistory;
|
|
class Command_GetWarnList;
|
|
class Command_GrantReplayAccess;
|
|
class Command_ListCardArtRules;
|
|
class Command_Register;
|
|
class Command_RemoveCardArtRule;
|
|
class Command_RemoveUserAvatar;
|
|
class Command_Report;
|
|
class Command_ReportAddComment;
|
|
class Command_ReportAssign;
|
|
class Command_ReportDetails;
|
|
class Command_ReportList;
|
|
class Command_ReportMyList;
|
|
class Command_ReportReopen;
|
|
class Command_ReportResolve;
|
|
class Command_ReportStats;
|
|
class Command_ReportUserInfo;
|
|
class Command_RequestPasswordSalt;
|
|
class Command_ResetUserPassword;
|
|
class Command_SetCardArtParams;
|
|
class Command_SubmitPasswordVerifier;
|
|
class Command_UpdateAdminNotes;
|
|
class Command_ViewLogHistory;
|
|
class Command_WarnUser;
|
|
class QObject;
|
|
class ResponseContainer;
|
|
|
|
class AbstractServerSocketInterface : public Server_ProtocolHandler
|
|
{
|
|
Q_OBJECT
|
|
protected slots:
|
|
void catchSocketError(QAbstractSocket::SocketError socketError);
|
|
void catchSocketDisconnected();
|
|
virtual void flushOutputQueue() = 0;
|
|
signals:
|
|
void outputQueueChanged();
|
|
void incTxBytes(qint64 amount);
|
|
|
|
protected:
|
|
void logDebugMessage(const QString &message) override;
|
|
bool tooManyRegistrationAttempts(const QString &ipAddress);
|
|
void processCommandContainer(const CommandContainer &cont) override;
|
|
bool acceptsCredentialFormat(bool passwordNeedsHash, const QString &password) const;
|
|
|
|
virtual void writeToSocket(QByteArray &data) = 0;
|
|
virtual void flushSocket() = 0;
|
|
|
|
Servatrice *servatrice;
|
|
QList<ServerMessage> outputQueue;
|
|
QMutex outputQueueMutex;
|
|
|
|
private:
|
|
Servatrice_DatabaseInterface *sqlInterface;
|
|
|
|
Response::ResponseCode cmdAddToList(const Command_AddToList &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdRemoveFromList(const Command_RemoveFromList &cmd, ResponseContainer &rc);
|
|
int getDeckPathId(int basePathId, QStringList path);
|
|
int getDeckPathId(const QString &path);
|
|
bool deckListHelper(int folderId,
|
|
ServerInfo_DeckStorage_Folder *folder,
|
|
int userId,
|
|
bool inheritedPublic,
|
|
bool publicOnly);
|
|
int getDeckOwnerId(int deckId);
|
|
bool isDeckEffectivelyPublic(int deckId);
|
|
Response::ResponseCode cmdDeckList(const Command_DeckList &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdDeckListOtherUser(const Command_DeckListOtherUser &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdDeckSetVisibility(const Command_DeckSetVisibility &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdDeckNewDir(const Command_DeckNewDir &cmd, ResponseContainer &rc);
|
|
void deckDelDirHelper(int basePathId);
|
|
void sendServerMessage(const QString userName, const QString message);
|
|
Response::ResponseCode cmdDeckDelDir(const Command_DeckDelDir &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdDeckDel(const Command_DeckDel &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdDeckUpload(const Command_DeckUpload &cmd, ResponseContainer &rc);
|
|
DeckList *getDeckFromDatabase(int deckId);
|
|
Response::ResponseCode cmdDeckDownload(const Command_DeckDownload &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdDeckDownloadPublic(const Command_DeckDownloadPublic &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdDeckShareCreate(const Command_DeckShareCreate &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdDeckShareList(const Command_DeckShareList &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdDeckShareListMine(const Command_DeckShareListMine &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdDeckShareRemove(const Command_DeckShareRemove &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdDeckShareDownload(const Command_DeckShareDownload &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdReplayList(const Command_ReplayList &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdReplayDownload(const Command_ReplayDownload &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdReplayModifyMatch(const Command_ReplayModifyMatch &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdReplayDeleteMatch(const Command_ReplayDeleteMatch &cmd, ResponseContainer &rc);
|
|
QString createHashForReplay(int gameId);
|
|
Response::ResponseCode cmdReplayGetCode(const Command_ReplayGetCode &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdReplaySubmitCode(const Command_ReplaySubmitCode &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdBanFromServer(const Command_BanFromServer &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdReportList(const Command_ReportList &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdWarnUser(const Command_WarnUser &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode
|
|
cmdGetLogHistory(const Command_ViewLogHistory &cmd, ResponseContainer &rc, bool allowPrivateChat);
|
|
Response::ResponseCode cmdGetBanHistory(const Command_GetBanHistory &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdGetWarnList(const Command_GetWarnList &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdGetWarnHistory(const Command_GetWarnHistory &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdShutdownServer(const Command_ShutdownServer &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdReportAssign(const Command_ReportAssign &cmd, ResponseContainer &);
|
|
Response::ResponseCode cmdReportResolve(const Command_ReportResolve &cmd, ResponseContainer &);
|
|
Response::ResponseCode cmdReportReopen(const Command_ReportReopen &cmd, ResponseContainer &);
|
|
Response::ResponseCode cmdReportUserInfo(const Command_ReportUserInfo &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdReportStats(const Command_ReportStats &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdRegisterAccount(const Command_Register &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdActivateAccount(const Command_Activate &cmd, ResponseContainer & /* rc */);
|
|
Response::ResponseCode cmdReloadConfig(const Command_ReloadConfig & /* cmd */, ResponseContainer & /*rc*/);
|
|
Response::ResponseCode cmdAdjustMod(const Command_AdjustMod &cmd, ResponseContainer & /*rc*/);
|
|
Response::ResponseCode cmdForgotPasswordRequest(const Command_ForgotPasswordRequest &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode continuePasswordRequest(const QString &userName,
|
|
const QString &clientId,
|
|
ResponseContainer &rc,
|
|
bool challenged = false);
|
|
Response::ResponseCode cmdForgotPasswordReset(const Command_ForgotPasswordReset &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdForgotPasswordChallenge(const Command_ForgotPasswordChallenge &cmd,
|
|
ResponseContainer &rc);
|
|
Response::ResponseCode cmdRequestPasswordSalt(const Command_RequestPasswordSalt &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdReport(const Command_Report &cmd, ResponseContainer &);
|
|
Response::ResponseCode cmdReportMyList(const Command_ReportMyList &cmd, ResponseContainer &rc);
|
|
void sendPendingReportNotifications(ResponseContainer &rc);
|
|
void onLogin(ResponseContainer &rc) override;
|
|
Response::ResponseCode cmdReportDetails(const Command_ReportDetails &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdReportAddComment(const Command_ReportAddComment &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdReplayDownloadByGameId(const Command_ReplayDownloadByGameId &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdSubmitPasswordVerifier(const Command_SubmitPasswordVerifier &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode
|
|
processExtendedSessionCommand(int cmdType, const SessionCommand &cmd, ResponseContainer &rc) override;
|
|
Response::ResponseCode
|
|
processExtendedModeratorCommand(int cmdType, const ModeratorCommand &cmd, ResponseContainer &rc) override;
|
|
Response::ResponseCode
|
|
processExtendedAdminCommand(int cmdType, const AdminCommand &cmd, ResponseContainer &rc) override;
|
|
Response::ResponseCode
|
|
processExtendedDeveloperCommand(int cmdType, const DeveloperCommand &cmd, ResponseContainer &rc) override;
|
|
|
|
Response::ResponseCode cmdAccountEdit(const Command_AccountEdit &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdAccountImage(const Command_AccountImage &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdSetCardArtParams(const Command_SetCardArtParams &cmd, ResponseContainer &);
|
|
Response::ResponseCode cmdAddCardArtRule(const Command_AddCardArtRule &cmd, ResponseContainer &);
|
|
Response::ResponseCode cmdRemoveCardArtRule(const Command_RemoveCardArtRule &cmd, ResponseContainer &);
|
|
Response::ResponseCode cmdListCardArtRules(const Command_ListCardArtRules &, ResponseContainer &rc);
|
|
Response::ResponseCode cmdAccountPassword(const Command_AccountPassword &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdGrantReplayAccess(const Command_GrantReplayAccess &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdForceActivateUser(const Command_ForceActivateUser &cmd, ResponseContainer &rc);
|
|
|
|
Response::ResponseCode cmdGetAdminNotes(const Command_GetAdminNotes &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdUpdateAdminNotes(const Command_UpdateAdminNotes &cmd, ResponseContainer &rc);
|
|
|
|
Response::ResponseCode cmdGetUserSessions(const Command_GetUserSessions &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdGetUserAlts(const Command_GetUserAlts &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdGetModeratorLastLogins(const Command_GetModeratorLastLogins &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdResetUserPassword(const Command_ResetUserPassword &cmd, ResponseContainer &rc);
|
|
Response::ResponseCode cmdRemoveUserAvatar(const Command_RemoveUserAvatar &cmd, ResponseContainer &rc);
|
|
|
|
Response::ResponseCode cmdGetServerStats(const Command_GetServerStats &cmd, ResponseContainer &rc);
|
|
|
|
bool addAdminFlagToUser(const QString &user, int flag);
|
|
bool removeAdminFlagFromUser(const QString &user, int flag);
|
|
|
|
bool isPasswordLongEnough(const int passwordLength);
|
|
void removeSaidMessages(const QString &userName, int amount);
|
|
|
|
public:
|
|
AbstractServerSocketInterface(Servatrice *_server,
|
|
Servatrice_DatabaseInterface *_databaseInterface,
|
|
QObject *parent = 0);
|
|
~AbstractServerSocketInterface()
|
|
{
|
|
}
|
|
bool initSession();
|
|
|
|
virtual QHostAddress getPeerAddress() const = 0;
|
|
QString getAddress() const override = 0;
|
|
|
|
void transmitProtocolItem(const ServerMessage &item) override;
|
|
};
|
|
|
|
class TcpServerSocketInterface : public AbstractServerSocketInterface
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
TcpServerSocketInterface(Servatrice *_server,
|
|
Servatrice_DatabaseInterface *_databaseInterface,
|
|
QObject *parent = 0);
|
|
~TcpServerSocketInterface();
|
|
|
|
QHostAddress getPeerAddress() const
|
|
{
|
|
return socket->peerAddress();
|
|
}
|
|
QString getAddress() const
|
|
{
|
|
return socket->peerAddress().toString();
|
|
}
|
|
QString getConnectionType() const
|
|
{
|
|
return "tcp";
|
|
}
|
|
|
|
private:
|
|
QTcpSocket *socket;
|
|
QByteArray inputBuffer;
|
|
bool messageInProgress;
|
|
bool handshakeStarted;
|
|
int messageLength;
|
|
|
|
protected:
|
|
void writeToSocket(QByteArray &data)
|
|
{
|
|
socket->write(data);
|
|
}
|
|
void flushSocket()
|
|
{
|
|
socket->flush();
|
|
}
|
|
void initSessionDeprecated();
|
|
bool initTcpSession();
|
|
protected slots:
|
|
void readClient();
|
|
void flushOutputQueue();
|
|
public slots:
|
|
void initConnection(int socketDescriptor);
|
|
};
|
|
|
|
class WebsocketServerSocketInterface : public AbstractServerSocketInterface
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
WebsocketServerSocketInterface(Servatrice *_server,
|
|
Servatrice_DatabaseInterface *_databaseInterface,
|
|
QObject *parent = nullptr);
|
|
~WebsocketServerSocketInterface();
|
|
|
|
QHostAddress getPeerAddress() const
|
|
{
|
|
return address;
|
|
}
|
|
QString getAddress() const
|
|
{
|
|
return address.toString();
|
|
}
|
|
QString getConnectionType() const
|
|
{
|
|
return "websocket";
|
|
}
|
|
|
|
private:
|
|
QWebSocket *socket;
|
|
QHostAddress address;
|
|
|
|
protected:
|
|
void writeToSocket(QByteArray &data)
|
|
{
|
|
socket->sendBinaryMessage(data);
|
|
}
|
|
void flushSocket()
|
|
{
|
|
socket->flush();
|
|
}
|
|
bool initWebsocketSession();
|
|
protected slots:
|
|
void binaryMessageReceived(const QByteArray &message);
|
|
void flushOutputQueue();
|
|
public slots:
|
|
void initConnection(void *_socket);
|
|
};
|
|
|
|
#endif
|