From d1bf207d30fe62a15d0e8669d186374c68e6eae8 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Thu, 23 Jan 2014 20:36:43 +0100 Subject: [PATCH 1/1] Implement protocol detection This introduces a new initial handshake for negotiating the supported protocols and connection features on both sides. It is completely backwards compatible with older releases, in which case we go into fallback mode. Arguably, we could've used a nice, verbose, text-based handshake, but that would've introduced questions around string formats, parsing and so on. Also I felt like doing some bitbanging, so now the probing only exchanges a few bytes which are described in the wiki [1]. If we ever plan to use a more verbose or different format, changing the magic that starts the whole shebang will be sufficient to indicate a new format. Immediately after probing, if both core and client support the new format (and a protocol other than the legacy one),we'll enable SSL and compression [2] as appropriate, instead of doing it somewhat later in the middle of the legacy handshake. To retain compatibility, the magic number sent by the client is designed such that older cores will immediately close the connection; we'll then reconnect in compatibility mode. The other way round, if an older client connects to a new core, we'll figure out that there's no magic being sent and switch to legacy mode as well. The unchanged legacy protocol is also the last resort even if both ends speak the new handshake as long as we don't have an alternative to offer. So for now, we'll probe for protocol support, get back the legacy protocol as only choice, and use that as before. This also disables early SSL and compression mentioned above. This means that 3rd party clients could already implement the handshake in preparation for the future without changing anything else. Note that they should also implement the detection of older cores in order to stay compatible with them - simply detect a disconnect after the first few bytes sent and reconnect again in compat mode. [1] http://bugs.quassel-irc.org/projects/quassel-irc/wiki/Doc_quassel_protocols [2] Not implemented yet. --- src/client/clientauthhandler.cpp | 337 +++++++++++++++++++++---------- src/client/clientauthhandler.h | 13 +- src/common/protocol.h | 11 +- src/core/coreauthhandler.cpp | 165 +++++++++++---- src/core/coreauthhandler.h | 13 +- 5 files changed, 383 insertions(+), 156 deletions(-) diff --git a/src/client/clientauthhandler.cpp b/src/client/clientauthhandler.cpp index 6661119f..415a7ddb 100644 --- a/src/client/clientauthhandler.cpp +++ b/src/client/clientauthhandler.cpp @@ -22,6 +22,8 @@ // TODO: support system application proxy (new in Qt 4.6) +#include + #ifdef HAVE_SSL #include #else @@ -30,6 +32,7 @@ #include "client.h" #include "clientsettings.h" +#include "peerfactory.h" #include "protocols/legacy/legacypeer.h" @@ -38,7 +41,10 @@ using namespace Protocol; ClientAuthHandler::ClientAuthHandler(CoreAccount account, QObject *parent) : AuthHandler(parent), _peer(0), - _account(account) + _account(account), + _probing(false), + _legacy(false), + _connectionFeatures(0) { } @@ -76,9 +82,8 @@ void ClientAuthHandler::connectToCore() #endif setSocket(socket); - // handled by the base class for now; may need to rethink for protocol detection - //connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(onSocketError(QAbstractSocket::SocketError))); connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(onSocketStateChanged(QAbstractSocket::SocketState))); + connect(socket, SIGNAL(readyRead()), SLOT(onReadyRead())); connect(socket, SIGNAL(connected()), SLOT(onSocketConnected())); emit statusMessage(tr("Connecting to %1...").arg(_account.accountName())); @@ -86,29 +91,33 @@ void ClientAuthHandler::connectToCore() } -// TODO: handle protocol detection void ClientAuthHandler::onSocketStateChanged(QAbstractSocket::SocketState socketState) { QString text; switch(socketState) { - case QAbstractSocket::UnconnectedState: - text = tr("Disconnected"); - // Ensure the disconnected() signal is sent even if we haven't reached the Connected state yet. - // The baseclass implementation will make sure to only send the signal once. - onSocketDisconnected(); - break; case QAbstractSocket::HostLookupState: - text = tr("Looking up %1...").arg(_account.hostName()); + if (!_legacy) + text = tr("Looking up %1...").arg(_account.hostName()); break; case QAbstractSocket::ConnectingState: - text = tr("Connecting to %1...").arg(_account.hostName()); + if (!_legacy) + text = tr("Connecting to %1...").arg(_account.hostName()); break; case QAbstractSocket::ConnectedState: text = tr("Connected to %1").arg(_account.hostName()); break; case QAbstractSocket::ClosingState: - text = tr("Disconnecting from %1...").arg(_account.hostName()); + if (!_probing) + text = tr("Disconnecting from %1...").arg(_account.hostName()); + break; + case QAbstractSocket::UnconnectedState: + if (!_probing) { + text = tr("Disconnected"); + // Ensure the disconnected() signal is sent even if we haven't reached the Connected state yet. + // The baseclass implementation will make sure to only send the signal once. + onSocketDisconnected(); + } break; default: break; @@ -119,18 +128,35 @@ void ClientAuthHandler::onSocketStateChanged(QAbstractSocket::SocketState socket } } -// TODO: handle protocol detection -/* void ClientAuthHandler::onSocketError(QAbstractSocket::SocketError error) { - emit socketError(error, socket()->errorString()); + if (_probing && error == QAbstractSocket::RemoteHostClosedError) { + _legacy = true; + return; + } + + _probing = false; // all other errors are unrelated to probing and should be handled + AuthHandler::onSocketError(error); } -*/ -void ClientAuthHandler::onSocketConnected() + +void ClientAuthHandler::onSocketDisconnected() { - // TODO: protocol detection + if (_probing && _legacy) { + // Remote host has closed the connection while probing + _probing = false; + disconnect(socket(), SIGNAL(readyRead()), this, SLOT(onReadyRead())); + emit statusMessage(tr("Reconnecting in compatibility mode...")); + socket()->connectToHost(_account.hostName(), _account.port()); + return; + } + + AuthHandler::onSocketDisconnected(); +} + +void ClientAuthHandler::onSocketConnected() +{ if (_peer) { qWarning() << Q_FUNC_INFO << "Peer already exists!"; return; @@ -138,21 +164,75 @@ void ClientAuthHandler::onSocketConnected() socket()->setSocketOption(QAbstractSocket::KeepAliveOption, true); - _peer = new LegacyPeer(this, socket(), this); + if (!_legacy) { + // First connection attempt, try probing for a capable core + _probing = true; - connect(_peer, SIGNAL(transferProgress(int,int)), SIGNAL(transferProgress(int,int))); - - // compat only - connect(_peer, SIGNAL(protocolVersionMismatch(int,int)), SLOT(onProtocolVersionMismatch(int,int))); + QDataStream stream(socket()); // stream handles the endianness for us - emit statusMessage(tr("Synchronizing to core...")); - - bool useSsl = false; + quint32 magic = Protocol::magic; #ifdef HAVE_SSL - useSsl = _account.useSsl(); + if (_account.useSsl()) + magic |= Protocol::Encryption; #endif + //magic |= Protocol::Compression; // not implemented yet - _peer->dispatch(RegisterClient(Quassel::buildInfo().fancyVersionString, useSsl)); + stream << magic; + + // here goes the list of protocols we support, in order of preference + stream << ((quint32)Protocol::LegacyProtocol | 0x80000000); // end list + + socket()->flush(); // make sure the probing data is sent immediately + return; + } + + // If we arrive here, it's the second connection attempt, meaning probing was not successful -> enable legacy support + + qDebug() << "Legacy core detected, switching to compatibility mode"; + + RemotePeer *peer = new LegacyPeer(this, socket(), this); + // Only needed for the legacy peer, as all others check the protocol version before instantiation + connect(peer, SIGNAL(protocolVersionMismatch(int,int)), SLOT(onProtocolVersionMismatch(int,int))); + + setPeer(peer); +} + + +void ClientAuthHandler::onReadyRead() +{ + if (socket()->bytesAvailable() < 4) + return; + + if (!_probing) + return; // make sure to not read more data than needed + + _probing = false; + disconnect(socket(), SIGNAL(readyRead()), this, SLOT(onReadyRead())); + + quint32 reply; + socket()->read((char *)&reply, 4); + reply = qFromBigEndian(reply); + + Protocol::Type type = static_cast(reply & 0xff); + quint16 protoFeatures = static_cast(reply>>8 & 0xffff); + _connectionFeatures = static_cast(reply>>24); + + RemotePeer *peer = PeerFactory::createPeer(PeerFactory::ProtoDescriptor(type, protoFeatures), this, socket(), this); + if (!peer) { + qWarning() << "No valid protocol supported for this core!"; + emit errorPopup(tr("Incompatible Quassel Core!
" + "None of the protocols this client speaks are supported by the core you are trying to connect to.")); + + requestDisconnect(tr("Core speaks none of the protocols we support")); + return; + } + + if (peer->protocol() == Protocol::LegacyProtocol) { + connect(peer, SIGNAL(protocolVersionMismatch(int,int)), SLOT(onProtocolVersionMismatch(int,int))); + _legacy = true; + } + + setPeer(peer); } @@ -164,104 +244,55 @@ void ClientAuthHandler::onProtocolVersionMismatch(int actual, int expected) } -void ClientAuthHandler::handle(const ClientDenied &msg) +void ClientAuthHandler::setPeer(RemotePeer *peer) { - emit errorPopup(msg.errorString); - requestDisconnect(tr("The core refused connection from this client")); + _peer = peer; + connect(_peer, SIGNAL(transferProgress(int,int)), SIGNAL(transferProgress(int,int))); + + // The legacy protocol enables SSL later, after registration + if (!_account.useSsl() || _legacy) + startRegistration(); + // otherwise, do it now + else + checkAndEnableSsl(_connectionFeatures & Protocol::Encryption); } -void ClientAuthHandler::handle(const ClientRegistered &msg) +void ClientAuthHandler::startRegistration() { - _coreConfigured = msg.coreConfigured; - _backendInfo = msg.backendInfo; - - Client::setCoreFeatures(static_cast(msg.coreFeatures)); + emit statusMessage(tr("Synchronizing to core...")); + // useSsl will be ignored by non-legacy peers + bool useSsl = false; #ifdef HAVE_SSL - CoreAccountSettings s; - if (_account.useSsl()) { - if (msg.sslSupported) { - // Make sure the warning is shown next time we don't have SSL in the core - s.setAccountValue("ShowNoCoreSslWarning", true); - - QSslSocket *sslSocket = qobject_cast(socket()); - Q_ASSERT(sslSocket); - connect(sslSocket, SIGNAL(encrypted()), SLOT(onSslSocketEncrypted())); - connect(sslSocket, SIGNAL(sslErrors(QList)), SLOT(onSslErrors())); - qDebug() << "Starting encryption..."; - sslSocket->flush(); - sslSocket->startClientEncryption(); - } - else { - if (s.accountValue("ShowNoCoreSslWarning", true).toBool()) { - bool accepted = false; - emit handleNoSslInCore(&accepted); - if (!accepted) { - requestDisconnect(tr("Unencrypted connection cancelled")); - return; - } - s.setAccountValue("ShowNoCoreSslWarning", false); - s.setAccountValue("SslCert", QString()); - } - onConnectionReady(); - } - return; - } + useSsl = _account.useSsl(); #endif - // if we use SSL we wait for the next step until every SSL warning has been cleared - onConnectionReady(); -} + _peer->dispatch(RegisterClient(Quassel::buildInfo().fancyVersionString, useSsl)); +} -#ifdef HAVE_SSL -void ClientAuthHandler::onSslSocketEncrypted() +void ClientAuthHandler::handle(const ClientDenied &msg) { - QSslSocket *socket = qobject_cast(sender()); - Q_ASSERT(socket); - - if (!socket->sslErrors().count()) { - // Cert is valid, so we don't want to store it as known - // That way, a warning will appear in case it becomes invalid at some point - CoreAccountSettings s; - s.setAccountValue("SSLCert", QString()); - } - - emit encrypted(true); - onConnectionReady(); + emit errorPopup(msg.errorString); + requestDisconnect(tr("The core refused connection from this client")); } -void ClientAuthHandler::onSslErrors() +void ClientAuthHandler::handle(const ClientRegistered &msg) { - QSslSocket *socket = qobject_cast(sender()); - Q_ASSERT(socket); - - CoreAccountSettings s; - QByteArray knownDigest = s.accountValue("SslCert").toByteArray(); - - if (knownDigest != socket->peerCertificate().digest()) { - bool accepted = false; - bool permanently = false; - emit handleSslErrors(socket, &accepted, &permanently); - - if (!accepted) { - requestDisconnect(tr("Unencrypted connection canceled")); - return; - } + _coreConfigured = msg.coreConfigured; + _backendInfo = msg.backendInfo; - if (permanently) - s.setAccountValue("SslCert", socket->peerCertificate().digest()); - else - s.setAccountValue("SslCert", QString()); - } + Client::setCoreFeatures(static_cast(msg.coreFeatures)); - socket->ignoreSslErrors(); + // The legacy protocol enables SSL at this point + if(_legacy && _account.useSsl()) + checkAndEnableSsl(msg.sslSupported); + else + onConnectionReady(); } -#endif /* HAVE_SSL */ - void ClientAuthHandler::onConnectionReady() { @@ -344,3 +375,95 @@ void ClientAuthHandler::handle(const SessionState &msg) _peer->setParent(0); emit handshakeComplete(_peer, msg); } + + +/*** SSL Stuff ***/ + +void ClientAuthHandler::checkAndEnableSsl(bool coreSupportsSsl) +{ +#ifndef HAVE_SSL + Q_UNUSED(coreSupportsSsl); +#else + CoreAccountSettings s; + if (coreSupportsSsl && _account.useSsl()) { + // Make sure the warning is shown next time we don't have SSL in the core + s.setAccountValue("ShowNoCoreSslWarning", true); + + QSslSocket *sslSocket = qobject_cast(socket()); + Q_ASSERT(sslSocket); + connect(sslSocket, SIGNAL(encrypted()), SLOT(onSslSocketEncrypted())); + connect(sslSocket, SIGNAL(sslErrors(QList)), SLOT(onSslErrors())); + qDebug() << "Starting encryption..."; + sslSocket->flush(); + sslSocket->startClientEncryption(); + } + else { + if (s.accountValue("ShowNoCoreSslWarning", true).toBool()) { + bool accepted = false; + emit handleNoSslInCore(&accepted); + if (!accepted) { + requestDisconnect(tr("Unencrypted connection cancelled")); + return; + } + s.setAccountValue("ShowNoCoreSslWarning", false); + s.setAccountValue("SslCert", QString()); + } + if (_legacy) + onConnectionReady(); + else + startRegistration(); + } +#endif +} + +#ifdef HAVE_SSL + +void ClientAuthHandler::onSslSocketEncrypted() +{ + QSslSocket *socket = qobject_cast(sender()); + Q_ASSERT(socket); + + if (!socket->sslErrors().count()) { + // Cert is valid, so we don't want to store it as known + // That way, a warning will appear in case it becomes invalid at some point + CoreAccountSettings s; + s.setAccountValue("SSLCert", QString()); + } + + emit encrypted(true); + + if (_legacy) + onConnectionReady(); + else + startRegistration(); +} + + +void ClientAuthHandler::onSslErrors() +{ + QSslSocket *socket = qobject_cast(sender()); + Q_ASSERT(socket); + + CoreAccountSettings s; + QByteArray knownDigest = s.accountValue("SslCert").toByteArray(); + + if (knownDigest != socket->peerCertificate().digest()) { + bool accepted = false; + bool permanently = false; + emit handleSslErrors(socket, &accepted, &permanently); + + if (!accepted) { + requestDisconnect(tr("Unencrypted connection canceled")); + return; + } + + if (permanently) + s.setAccountValue("SslCert", socket->peerCertificate().digest()); + else + s.setAccountValue("SslCert", QString()); + } + + socket->ignoreSslErrors(); +} + +#endif /* HAVE_SSL */ diff --git a/src/client/clientauthhandler.h b/src/client/clientauthhandler.h index d80051a8..6683d1dd 100644 --- a/src/client/clientauthhandler.h +++ b/src/client/clientauthhandler.h @@ -78,10 +78,17 @@ private: void handle(const Protocol::LoginSuccess &msg); void handle(const Protocol::SessionState &msg); + void setPeer(RemotePeer *peer); + void checkAndEnableSsl(bool coreSupportsSsl); + void startRegistration(); + private slots: void onSocketConnected(); void onSocketStateChanged(QAbstractSocket::SocketState state); - //void onSocketError(QAbstractSocket::SocketError); + void onSocketError(QAbstractSocket::SocketError); + void onSocketDisconnected(); + void onReadyRead(); + #ifdef HAVE_SSL void onSslSocketEncrypted(); void onSslErrors(); @@ -96,7 +103,9 @@ private: bool _coreConfigured; QVariantList _backendInfo; CoreAccount _account; - + bool _probing; + bool _legacy; + quint8 _connectionFeatures; }; #endif diff --git a/src/common/protocol.h b/src/common/protocol.h index d1154db8..d7c1b1d5 100644 --- a/src/common/protocol.h +++ b/src/common/protocol.h @@ -27,17 +27,26 @@ namespace Protocol { +const quint32 magic = 0x42b33f00; + enum Type { LegacyProtocol = 1 }; + +enum Feature { + Encryption = 0x01, + Compression = 0x02 +}; + + enum Handler { SignalProxy, AuthHandler }; -/*** Handshake, handled by AuthHandler ***/ +/*** Handshake, handled by AuthHandler ***/ struct HandshakeMessage { inline Handler handler() const { return AuthHandler; } diff --git a/src/core/coreauthhandler.cpp b/src/core/coreauthhandler.cpp index c27afde2..e277fcb3 100644 --- a/src/core/coreauthhandler.cpp +++ b/src/core/coreauthhandler.cpp @@ -32,22 +32,94 @@ using namespace Protocol; CoreAuthHandler::CoreAuthHandler(QTcpSocket *socket, QObject *parent) - : AuthHandler(parent) - , _peer(0) - , _clientRegistered(false) + : AuthHandler(parent), + _peer(0), + _magicReceived(false), + _legacy(false), + _clientRegistered(false), + _connectionFeatures(0) { setSocket(socket); + connect(socket, SIGNAL(readyRead()), SLOT(onReadyRead())); - // TODO: protocol detection + // TODO: Timeout for the handshake phase - // FIXME: make sure _peer gets deleted - // TODO: socket ownership goes to the peer! (-> use shared ptr later...) - _peer = new LegacyPeer(this, socket, this); - // only in compat mode - connect(_peer, SIGNAL(protocolVersionMismatch(int,int)), SLOT(onProtocolVersionMismatch(int,int))); } +void CoreAuthHandler::onReadyRead() +{ + if (socket()->bytesAvailable() < 4) + return; + + // once we have selected a peer, we certainly don't want to read more data! + if (_peer) + return; + + if (!_magicReceived) { + quint32 magic; + socket()->peek((char*)&magic, 4); + magic = qFromBigEndian(magic); + + if ((magic & 0xffffff00) != Protocol::magic) { + // no magic, assume legacy protocol + qDebug() << "Legacy client detected, switching to compatibility mode"; + _legacy = true; + RemotePeer *peer = new LegacyPeer(this, socket(), this); + connect(peer, SIGNAL(protocolVersionMismatch(int,int)), SLOT(onProtocolVersionMismatch(int,int))); + setPeer(peer); + return; + } + + _magicReceived = true; + quint8 features = magic & 0xff; + // figure out which connection features we'll use based on the client's support + if (Core::sslSupported() && (features & Protocol::Encryption)) + _connectionFeatures |= Protocol::Encryption; + if (features & Protocol::Compression) + _connectionFeatures |= Protocol::Compression; + + socket()->read((char*)&magic, 4); // read the 4 bytes we've just peeked at + } + + // read the list of protocols supported by the client + while (socket()->bytesAvailable() >= 4) { + quint32 data; + socket()->read((char*)&data, 4); + data = qFromBigEndian(data); + + Protocol::Type type = static_cast(data & 0xff); + quint16 protoFeatures = static_cast(data>>8 & 0xffff); + _supportedProtos.append(PeerFactory::ProtoDescriptor(type, protoFeatures)); + + if (data >= 0x80000000) { // last protocol + RemotePeer *peer = PeerFactory::createPeer(_supportedProtos, this, socket(), this); + if (peer->protocol() == Protocol::LegacyProtocol) { + _legacy = true; + connect(peer, SIGNAL(protocolVersionMismatch(int,int)), SLOT(onProtocolVersionMismatch(int,int))); + } + setPeer(peer); + + // inform the client + quint32 reply = peer->protocol() | peer->enabledFeatures()<<8 | _connectionFeatures<<24; + reply = qToBigEndian(reply); + socket()->write((char*)&reply, 4); + socket()->flush(); + + if (!_legacy && (_connectionFeatures & Protocol::Encryption)) + startSsl(); // legacy peer enables it later + return; + } + } +} + + +void CoreAuthHandler::setPeer(RemotePeer *peer) +{ + _peer = peer; + disconnect(socket(), SIGNAL(readyRead()), this, SLOT(onReadyRead())); +} + // only in compat mode void CoreAuthHandler::onProtocolVersionMismatch(int actual, int expected) { @@ -60,35 +132,11 @@ void CoreAuthHandler::onProtocolVersionMismatch(int actual, int expected) } -void CoreAuthHandler::startSsl() -{ -#ifdef HAVE_SSL - QSslSocket *sslSocket = qobject_cast(socket()); - Q_ASSERT(sslSocket); - - qDebug() << qPrintable(tr("Starting encryption for Client:")) << _peer->description(); - connect(sslSocket, SIGNAL(sslErrors(const QList &)), SLOT(onSslErrors())); - sslSocket->flush(); // ensure that the write cache is flushed before we switch to ssl (bug 682) - sslSocket->startServerEncryption(); -#endif -} - - -#ifdef HAVE_SSL -void CoreAuthHandler::onSslErrors() -{ - QSslSocket *sslSocket = qobject_cast(socket()); - Q_ASSERT(sslSocket); - sslSocket->ignoreSslErrors(); -} -#endif - - bool CoreAuthHandler::checkClientRegistered() { if (!_clientRegistered) { - qWarning() << qPrintable(tr("Client")) << qPrintable(socket()->peerAddress().toString()) << qPrintable(tr("did not send an init message before trying to login, rejecting.")); - _peer->dispatch(ClientDenied(tr("Client not initialized!
You need to send an init message before trying to login."))); + qWarning() << qPrintable(tr("Client")) << qPrintable(socket()->peerAddress().toString()) << qPrintable(tr("did not send a registration message before trying to login, rejecting.")); + _peer->dispatch(ClientDenied(tr("Client not initialized!
You need to send a registration message before trying to login."))); _peer->close(); return false; } @@ -98,25 +146,27 @@ bool CoreAuthHandler::checkClientRegistered() void CoreAuthHandler::handle(const RegisterClient &msg) { - // TODO: only in compat mode - bool useSsl = false; -#ifdef HAVE_SSL - if (Quassel::isOptionSet("require-ssl") && !msg.sslSupported) { + bool useSsl; + if (_legacy) + useSsl = Core::sslSupported() && msg.sslSupported; + else + useSsl = _connectionFeatures & Protocol::Encryption; + + if (Quassel::isOptionSet("require-ssl") && !useSsl) { _peer->dispatch(ClientDenied(tr("SSL is required!
You need to use SSL in order to connect to this core."))); _peer->close(); return; } - if (Core::sslSupported() && msg.sslSupported) - useSsl = true; -#endif + QVariantList backends; bool configured = Core::isConfigured(); if (!configured) backends = Core::backendInfo(); + // useSsl and startTime are only used for the legacy protocol _peer->dispatch(ClientRegistered(Quassel::features(), configured, backends, useSsl, Core::instance()->startTime())); - // TODO: only in compat mode - if (useSsl) + + if (_legacy && useSsl) startSsl(); _clientRegistered = true; @@ -157,3 +207,30 @@ void CoreAuthHandler::handle(const Login &msg) socket()->flush(); // Make sure all data is sent before handing over the peer (and socket) to the session thread (bug 682) emit handshakeComplete(_peer, uid); } + + +/*** SSL Stuff ***/ + +void CoreAuthHandler::startSsl() +{ + #ifdef HAVE_SSL + QSslSocket *sslSocket = qobject_cast(socket()); + Q_ASSERT(sslSocket); + + qDebug() << qPrintable(tr("Starting encryption for Client:")) << _peer->description(); + connect(sslSocket, SIGNAL(sslErrors(const QList &)), SLOT(onSslErrors())); + sslSocket->flush(); // ensure that the write cache is flushed before we switch to ssl (bug 682) + sslSocket->startServerEncryption(); + #endif /* HAVE_SSL */ +} + + +#ifdef HAVE_SSL +void CoreAuthHandler::onSslErrors() +{ + QSslSocket *sslSocket = qobject_cast(socket()); + Q_ASSERT(sslSocket); + sslSocket->ignoreSslErrors(); +} +#endif + diff --git a/src/core/coreauthhandler.h b/src/core/coreauthhandler.h index 3f7ddf3c..bb0b28b8 100644 --- a/src/core/coreauthhandler.h +++ b/src/core/coreauthhandler.h @@ -22,6 +22,7 @@ #define COREAUTHHANDLER_H #include "authhandler.h" +#include "peerfactory.h" #include "remotepeer.h" #include "types.h" @@ -42,21 +43,29 @@ private: void handle(const Protocol::SetupData &msg); void handle(const Protocol::Login &msg); + void setPeer(RemotePeer *peer); + void startSsl(); + bool checkClientRegistered(); private slots: - void startSsl(); + void onReadyRead(); + #ifdef HAVE_SSL void onSslErrors(); #endif - // only in compat mode + // only in legacy mode void onProtocolVersionMismatch(int actual, int expected); private: RemotePeer *_peer; + bool _magicReceived; + bool _legacy; bool _clientRegistered; + quint8 _connectionFeatures; + QVector _supportedProtos; }; #endif -- 2.20.1