From 0094d9ce512ca2e10500f079c489fc4c45970813 Mon Sep 17 00:00:00 2001 From: Michael Marley Date: Mon, 24 Feb 2014 14:12:27 +0000 Subject: [PATCH] Allow for clients to negotiate whether compression is used Previously, streaming compression would always be used for the datastream protocol and never for the legacy protocol, regardless of whether the client set the compression bit during the handshake. This patch enables negotiation of compression support and also allows for streaming compression when using the legacy protocol with the new handshake. As is, this patch prevents clients with streaming compression support but without this patch from connecting to cores with this patch. This problem occurs because the above-mentioned clients never set the compression bit during the handshake, which didn't cause a problem before because both sides unconditionally enabled compression. However, when connecting to a core with this patch, such a client will request no compression and the core will disable compression. However, the client will still enable the compression anyway, causing the connection to fail. --- src/client/clientauthhandler.cpp | 12 +++++++++--- src/client/clientauthhandler.h | 1 + src/common/peerfactory.cpp | 10 +++++----- src/common/peerfactory.h | 5 +++-- src/common/protocols/datastream/datastreampeer.cpp | 4 ++-- src/common/protocols/datastream/datastreampeer.h | 2 +- src/common/protocols/legacy/legacypeer.cpp | 4 ++-- src/common/protocols/legacy/legacypeer.h | 2 +- src/core/coreauthhandler.cpp | 10 ++++++++-- 9 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/client/clientauthhandler.cpp b/src/client/clientauthhandler.cpp index 15efef36..0d24a761 100644 --- a/src/client/clientauthhandler.cpp +++ b/src/client/clientauthhandler.cpp @@ -173,7 +173,7 @@ void ClientAuthHandler::onSocketConnected() if (_account.useSsl()) magic |= Protocol::Encryption; #endif - //magic |= Protocol::Compression; // not implemented yet + magic |= Protocol::Compression; stream << magic; @@ -195,7 +195,7 @@ void ClientAuthHandler::onSocketConnected() qDebug() << "Legacy core detected, switching to compatibility mode"; - RemotePeer *peer = PeerFactory::createPeer(PeerFactory::ProtoDescriptor(Protocol::LegacyProtocol, 0), this, socket(), this); + RemotePeer *peer = PeerFactory::createPeer(PeerFactory::ProtoDescriptor(Protocol::LegacyProtocol, 0), this, socket(), Compressor::NoCompression, 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))); @@ -222,7 +222,13 @@ void ClientAuthHandler::onReadyRead() quint16 protoFeatures = static_cast(reply>>8 & 0xffff); _connectionFeatures = static_cast(reply>>24); - RemotePeer *peer = PeerFactory::createPeer(PeerFactory::ProtoDescriptor(type, protoFeatures), this, socket(), this); + Compressor::CompressionLevel level; + if (_connectionFeatures & Protocol::Compression) + level = Compressor::BestCompression; + else + level = Compressor::NoCompression; + + RemotePeer *peer = PeerFactory::createPeer(PeerFactory::ProtoDescriptor(type, protoFeatures), this, socket(), level, this); if (!peer) { qWarning() << "No valid protocol supported for this core!"; emit errorPopup(tr("Incompatible Quassel Core!
" diff --git a/src/client/clientauthhandler.h b/src/client/clientauthhandler.h index 6683d1dd..f6f2fc93 100644 --- a/src/client/clientauthhandler.h +++ b/src/client/clientauthhandler.h @@ -21,6 +21,7 @@ #ifndef CLIENTAUTHHANDLER_H #define CLIENTAUTHHANDLER_H +#include "compressor.h" #include "authhandler.h" #include "coreaccount.h" diff --git a/src/common/peerfactory.cpp b/src/common/peerfactory.cpp index 0dc0140d..2364b719 100644 --- a/src/common/peerfactory.cpp +++ b/src/common/peerfactory.cpp @@ -33,23 +33,23 @@ PeerFactory::ProtoList PeerFactory::supportedProtocols() } -RemotePeer *PeerFactory::createPeer(const ProtoDescriptor &protocol, AuthHandler *authHandler, QTcpSocket *socket, QObject *parent) +RemotePeer *PeerFactory::createPeer(const ProtoDescriptor &protocol, AuthHandler *authHandler, QTcpSocket *socket, Compressor::CompressionLevel level, QObject *parent) { - return createPeer(ProtoList() << protocol, authHandler, socket, parent); + return createPeer(ProtoList() << protocol, authHandler, socket, level, parent); } -RemotePeer *PeerFactory::createPeer(const ProtoList &protocols, AuthHandler *authHandler, QTcpSocket *socket, QObject *parent) +RemotePeer *PeerFactory::createPeer(const ProtoList &protocols, AuthHandler *authHandler, QTcpSocket *socket, Compressor::CompressionLevel level, QObject *parent) { foreach(const ProtoDescriptor &protodesc, protocols) { Protocol::Type proto = protodesc.first; quint16 features = protodesc.second; switch(proto) { case Protocol::LegacyProtocol: - return new LegacyPeer(authHandler, socket, parent); + return new LegacyPeer(authHandler, socket, level, parent); case Protocol::DataStreamProtocol: if (DataStreamPeer::acceptsFeatures(features)) - return new DataStreamPeer(authHandler, socket, features, parent); + return new DataStreamPeer(authHandler, socket, features, level, parent); break; default: break; diff --git a/src/common/peerfactory.h b/src/common/peerfactory.h index 79a0c355..6b1bdf3c 100644 --- a/src/common/peerfactory.h +++ b/src/common/peerfactory.h @@ -23,6 +23,7 @@ #include +#include "compressor.h" #include "protocol.h" class QObject; @@ -41,8 +42,8 @@ public: static ProtoList supportedProtocols(); - static RemotePeer *createPeer(const ProtoDescriptor &protocol, AuthHandler *authHandler, QTcpSocket *socket, QObject *parent = 0); - static RemotePeer *createPeer(const ProtoList &protocols, AuthHandler *authHandler, QTcpSocket *socket, QObject *parent = 0); + static RemotePeer *createPeer(const ProtoDescriptor &protocol, AuthHandler *authHandler, QTcpSocket *socket, Compressor::CompressionLevel level, QObject *parent = 0); + static RemotePeer *createPeer(const ProtoList &protocols, AuthHandler *authHandler, QTcpSocket *socket, Compressor::CompressionLevel level, QObject *parent = 0); }; diff --git a/src/common/protocols/datastream/datastreampeer.cpp b/src/common/protocols/datastream/datastreampeer.cpp index 7d9b8547..b2e44434 100644 --- a/src/common/protocols/datastream/datastreampeer.cpp +++ b/src/common/protocols/datastream/datastreampeer.cpp @@ -28,8 +28,8 @@ using namespace Protocol; -DataStreamPeer::DataStreamPeer(::AuthHandler *authHandler, QTcpSocket *socket, quint16 features, QObject *parent) - : RemotePeer(authHandler, socket, Compressor::BestCompression, parent) +DataStreamPeer::DataStreamPeer(::AuthHandler *authHandler, QTcpSocket *socket, quint16 features, Compressor::CompressionLevel level, QObject *parent) + : RemotePeer(authHandler, socket, level, parent) { Q_UNUSED(features); } diff --git a/src/common/protocols/datastream/datastreampeer.h b/src/common/protocols/datastream/datastreampeer.h index 7d04f4b5..e01fb347 100644 --- a/src/common/protocols/datastream/datastreampeer.h +++ b/src/common/protocols/datastream/datastreampeer.h @@ -39,7 +39,7 @@ public: HeartBeatReply }; - DataStreamPeer(AuthHandler *authHandler, QTcpSocket *socket, quint16 features, QObject *parent = 0); + DataStreamPeer(AuthHandler *authHandler, QTcpSocket *socket, quint16 features, Compressor::CompressionLevel level, QObject *parent = 0); Protocol::Type protocol() const { return Protocol::DataStreamProtocol; } QString protocolName() const { return "the DataStream protocol"; } diff --git a/src/common/protocols/legacy/legacypeer.cpp b/src/common/protocols/legacy/legacypeer.cpp index 49c77fdd..67e51300 100644 --- a/src/common/protocols/legacy/legacypeer.cpp +++ b/src/common/protocols/legacy/legacypeer.cpp @@ -31,8 +31,8 @@ const uint clientNeedsProtocol = protocolVersion; using namespace Protocol; -LegacyPeer::LegacyPeer(::AuthHandler *authHandler, QTcpSocket *socket, QObject *parent) - : RemotePeer(authHandler, socket, Compressor::NoCompression, parent), +LegacyPeer::LegacyPeer(::AuthHandler *authHandler, QTcpSocket *socket, Compressor::CompressionLevel level, QObject *parent) + : RemotePeer(authHandler, socket, level, parent), _useCompression(false) { diff --git a/src/common/protocols/legacy/legacypeer.h b/src/common/protocols/legacy/legacypeer.h index a063616c..ce960fa4 100644 --- a/src/common/protocols/legacy/legacypeer.h +++ b/src/common/protocols/legacy/legacypeer.h @@ -37,7 +37,7 @@ public: HeartBeatReply }; - LegacyPeer(AuthHandler *authHandler, QTcpSocket *socket, QObject *parent = 0); + LegacyPeer(AuthHandler *authHandler, QTcpSocket *socket, Compressor::CompressionLevel level, QObject *parent = 0); Protocol::Type protocol() const { return Protocol::LegacyProtocol; } QString protocolName() const { return "the legacy protocol"; } diff --git a/src/core/coreauthhandler.cpp b/src/core/coreauthhandler.cpp index 36eecc19..9ef67fa2 100644 --- a/src/core/coreauthhandler.cpp +++ b/src/core/coreauthhandler.cpp @@ -63,7 +63,7 @@ void CoreAuthHandler::onReadyRead() // no magic, assume legacy protocol qDebug() << "Legacy client detected, switching to compatibility mode"; _legacy = true; - RemotePeer *peer = PeerFactory::createPeer(PeerFactory::ProtoDescriptor(Protocol::LegacyProtocol, 0), this, socket(), this); + RemotePeer *peer = PeerFactory::createPeer(PeerFactory::ProtoDescriptor(Protocol::LegacyProtocol, 0), this, socket(), Compressor::NoCompression, this); connect(peer, SIGNAL(protocolVersionMismatch(int,int)), SLOT(onProtocolVersionMismatch(int,int))); setPeer(peer); return; @@ -91,7 +91,13 @@ void CoreAuthHandler::onReadyRead() _supportedProtos.append(PeerFactory::ProtoDescriptor(type, protoFeatures)); if (data >= 0x80000000) { // last protocol - RemotePeer *peer = PeerFactory::createPeer(_supportedProtos, this, socket(), this); + Compressor::CompressionLevel level; + if (_connectionFeatures & Protocol::Compression) + level = Compressor::BestCompression; + else + level = Compressor::NoCompression; + + RemotePeer *peer = PeerFactory::createPeer(_supportedProtos, this, socket(), level, this); if (peer->protocol() == Protocol::LegacyProtocol) { _legacy = true; connect(peer, SIGNAL(protocolVersionMismatch(int,int)), SLOT(onProtocolVersionMismatch(int,int))); -- 2.20.1