214 lines
7.1 KiB
C++
214 lines
7.1 KiB
C++
// Copyright 2007-2023 The Mumble Developers. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license
|
|
// that can be found in the LICENSE file at the root of the
|
|
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
|
|
|
|
#ifndef MUMBLE_MUMBLE_SERVERHANDLER_H_
|
|
#define MUMBLE_MUMBLE_SERVERHANDLER_H_
|
|
|
|
#include <QtCore/QtGlobal>
|
|
|
|
#ifdef Q_OS_WIN
|
|
# include "win.h"
|
|
#endif
|
|
|
|
#ifndef Q_MOC_RUN
|
|
# include <boost/accumulators/accumulators.hpp>
|
|
# include <boost/accumulators/statistics/mean.hpp>
|
|
# include <boost/accumulators/statistics/stats.hpp>
|
|
# include <boost/accumulators/statistics/variance.hpp>
|
|
# include <boost/shared_ptr.hpp>
|
|
#endif
|
|
|
|
#include <QtCore/QEvent>
|
|
#include <QtCore/QMutex>
|
|
#include <QtCore/QObject>
|
|
#include <QtCore/QStringList>
|
|
#include <QtCore/QThread>
|
|
#include <QtCore/QTimer>
|
|
#include <QtNetwork/QHostAddress>
|
|
#include <QtNetwork/QSslCipher>
|
|
#include <QtNetwork/QSslError>
|
|
|
|
#define SERVERSEND_EVENT 3501
|
|
|
|
#include "Mumble.pb.h"
|
|
#include "MumbleProtocol.h"
|
|
#include "ServerAddress.h"
|
|
#include "Timer.h"
|
|
|
|
class Connection;
|
|
class Database;
|
|
class PacketDataStream;
|
|
class QUdpSocket;
|
|
class QSslSocket;
|
|
class VoiceRecorder;
|
|
|
|
class ServerHandlerMessageEvent : public QEvent {
|
|
public:
|
|
Mumble::Protocol::TCPMessageType type;
|
|
QByteArray qbaMsg;
|
|
bool bFlush;
|
|
ServerHandlerMessageEvent(const QByteArray &msg, Mumble::Protocol::TCPMessageType type, bool flush = false);
|
|
};
|
|
|
|
typedef boost::shared_ptr< Connection > ConnectionPtr;
|
|
|
|
class ServerHandler : public QThread {
|
|
private:
|
|
Q_OBJECT
|
|
Q_DISABLE_COPY(ServerHandler)
|
|
|
|
Database *database;
|
|
|
|
static QMutex nextConnectionIDMutex;
|
|
static int nextConnectionID;
|
|
|
|
protected:
|
|
QString qsHostName;
|
|
QString qsUserName;
|
|
QString qsPassword;
|
|
unsigned short usPort;
|
|
unsigned short usResolvedPort;
|
|
bool bUdp;
|
|
bool bStrong;
|
|
int connectionID;
|
|
Mumble::Protocol::UDPPingEncoder< Mumble::Protocol::Role::Client > m_udpPingEncoder;
|
|
Mumble::Protocol::UDPDecoder< Mumble::Protocol::Role::Client > m_udpDecoder;
|
|
Mumble::Protocol::UDPDecoder< Mumble::Protocol::Role::Client > m_tcpTunnelDecoder;
|
|
|
|
/// Flag indicating whether the server we are currently connected to has
|
|
/// finished synchronizing already.
|
|
bool serverSynchronized = false;
|
|
|
|
#ifdef Q_OS_WIN
|
|
HANDLE hQoS;
|
|
DWORD dwFlowUDP;
|
|
#endif
|
|
|
|
QHostAddress qhaRemote;
|
|
QHostAddress qhaLocal;
|
|
QUdpSocket *qusUdp;
|
|
QMutex qmUdp;
|
|
|
|
void handleVoicePacket(const Mumble::Protocol::AudioData &audioData);
|
|
|
|
public:
|
|
Timer tTimestamp;
|
|
int iInFlightTCPPings;
|
|
QTimer *tConnectionTimeoutTimer;
|
|
QList< QSslError > qlErrors;
|
|
QList< QSslCertificate > qscCert;
|
|
QSslCipher qscCipher;
|
|
ConnectionPtr cConnection;
|
|
QByteArray qbaDigest;
|
|
boost::shared_ptr< VoiceRecorder > recorder;
|
|
QSslSocket *qtsSock;
|
|
QList< ServerAddress > qlAddresses;
|
|
QHash< ServerAddress, QString > qhHostnames;
|
|
ServerAddress saTargetServer;
|
|
|
|
Version::full_t m_version;
|
|
QString qsRelease;
|
|
QString qsOS;
|
|
QString qsOSVersion;
|
|
|
|
/**
|
|
* A flag indicating whether this connection makes use of PFS or not. Note that this flag only has meaning, if the
|
|
* used version of Qt is >= 5.7.
|
|
*/
|
|
bool connectionUsesPerfectForwardSecrecy = false;
|
|
|
|
boost::accumulators::accumulator_set<
|
|
double, boost::accumulators::stats< boost::accumulators::tag::mean, boost::accumulators::tag::variance,
|
|
boost::accumulators::tag::count > >
|
|
accTCP, accUDP, accClean;
|
|
|
|
ServerHandler();
|
|
~ServerHandler();
|
|
void setConnectionInfo(const QString &host, unsigned short port, const QString &username, const QString &pw);
|
|
void getConnectionInfo(QString &host, unsigned short &port, QString &username, QString &pw) const;
|
|
bool isStrong() const;
|
|
void customEvent(QEvent *evt) Q_DECL_OVERRIDE;
|
|
int getConnectionID() const;
|
|
|
|
void setProtocolVersion(Version::full_t version);
|
|
|
|
void sendProtoMessage(const ::google::protobuf::Message &msg, Mumble::Protocol::TCPMessageType type);
|
|
void sendMessage(const unsigned char *data, int len, bool force = false);
|
|
|
|
/// @returns Whether this handler is currently connected to a server.
|
|
bool isConnected() const;
|
|
|
|
/// @returns Whether the server this handler is currently connected to, has finished
|
|
/// synchronizing yet.
|
|
bool hasSynchronized() const;
|
|
|
|
/// @param synchronized Whether the server has finished synchronization
|
|
void setServerSynchronized(bool synchronized);
|
|
|
|
#define PROCESS_MUMBLE_TCP_MESSAGE(name, value) \
|
|
void sendMessage(const MumbleProto::name &msg) { sendProtoMessage(msg, Mumble::Protocol::TCPMessageType::name); }
|
|
MUMBLE_ALL_TCP_MESSAGES
|
|
#undef PROCESS_MUMBLE_TCP_MESSAGE
|
|
|
|
void requestUserStats(unsigned int uiSession, bool statsOnly);
|
|
void joinChannel(unsigned int uiSession, unsigned int channel);
|
|
void joinChannel(unsigned int uiSession, unsigned int channel, const QStringList &temporaryAccessTokens);
|
|
void startListeningToChannel(unsigned int channel);
|
|
void startListeningToChannels(const QList< unsigned int > &channelIDs);
|
|
void stopListeningToChannel(unsigned int channel);
|
|
void stopListeningToChannels(const QList< unsigned int > &channelIDs);
|
|
void createChannel(unsigned int parent_id, const QString &name, const QString &description, unsigned int position,
|
|
bool temporary, unsigned int maxUsers);
|
|
void requestBanList();
|
|
void requestUserList();
|
|
void requestACL(unsigned int channel);
|
|
void registerUser(unsigned int uiSession);
|
|
void kickBanUser(unsigned int uiSession, const QString &reason, bool ban);
|
|
void sendUserTextMessage(unsigned int uiSession, const QString &message_);
|
|
void sendChannelTextMessage(unsigned int channel, const QString &message_, bool tree);
|
|
void setUserComment(unsigned int uiSession, const QString &comment);
|
|
void setUserTexture(unsigned int uiSession, const QByteArray &qba);
|
|
void setTokens(const QStringList &tokens);
|
|
void removeChannel(unsigned int channel);
|
|
void addChannelLink(unsigned int channel, unsigned int link);
|
|
void removeChannelLink(unsigned int channel, unsigned int link);
|
|
void requestChannelPermissions(unsigned int channel);
|
|
void setSelfMuteDeafState(bool mute, bool deaf);
|
|
void announceRecordingState(bool recording);
|
|
|
|
/// Return connection information as a URL
|
|
QUrl getServerURL(bool withPassword = false) const;
|
|
|
|
void disconnect();
|
|
void run() Q_DECL_OVERRIDE;
|
|
signals:
|
|
void error(QAbstractSocket::SocketError, QString reason);
|
|
// This signal is basically the same as disconnected but it will be emitted
|
|
// *right before* disconnected is emitted. Thus this can be used by slots
|
|
// that need to block the disconnected signal from being emitted (using a
|
|
// direct connection) before they're done.
|
|
void aboutToDisconnect(QAbstractSocket::SocketError, QString reason);
|
|
void disconnected(QAbstractSocket::SocketError, QString reason);
|
|
void connected();
|
|
void pingRequested();
|
|
protected slots:
|
|
void message(Mumble::Protocol::TCPMessageType type, const QByteArray &);
|
|
void serverConnectionConnected();
|
|
void serverConnectionTimeoutOnConnect();
|
|
void serverConnectionStateChanged(QAbstractSocket::SocketState);
|
|
void serverConnectionClosed(QAbstractSocket::SocketError, const QString &);
|
|
void setSslErrors(const QList< QSslError > &);
|
|
void udpReady();
|
|
void hostnameResolved();
|
|
private slots:
|
|
void sendPingInternal();
|
|
public slots:
|
|
void sendPing();
|
|
};
|
|
|
|
typedef boost::shared_ptr< ServerHandler > ServerHandlerPtr;
|
|
|
|
#endif
|