Handle the readyRead() signal in RemotePeer instead of LegacyPeer
authorManuel Nickschas <sputnick@quassel-irc.org>
Thu, 23 Jan 2014 00:05:29 +0000 (01:05 +0100)
committerManuel Nickschas <sputnick@quassel-irc.org>
Thu, 23 Jan 2014 00:54:49 +0000 (01:54 +0100)
That way, the RemotePeer subclasses don't all need to connect to the
signal themselves; also, we can make sure in a central place that
socket data is processed even the socket was handed over to the peer
with unhandled data still in its buffer.

Instead of handling the signal directly, RemotePeer subclasses need
to implement the onSocketDataAvailable() method.

src/common/protocols/legacy/legacypeer.cpp
src/common/protocols/legacy/legacypeer.h
src/common/remotepeer.cpp
src/common/remotepeer.h

index d45eb46..e2890cc 100644 (file)
@@ -38,8 +38,6 @@ LegacyPeer::LegacyPeer(::AuthHandler *authHandler, QTcpSocket *socket, QObject *
 {
     _stream.setDevice(socket);
     _stream.setVersion(QDataStream::Qt_4_2);
-
-    connect(socket, SIGNAL(readyRead()), SLOT(socketDataAvailable()));
 }
 
 
@@ -58,7 +56,7 @@ void LegacyPeer::setSignalProxy(::SignalProxy *proxy)
 }
 
 
-void LegacyPeer::socketDataAvailable()
+void LegacyPeer::onSocketDataAvailable()
 {
     QVariant item;
     while (readSocketData(item)) {
index 8d91c6b..d364c6c 100644 (file)
@@ -74,8 +74,8 @@ signals:
     // only used in compat mode
     void protocolVersionMismatch(int actual, int expected);
 
-private slots:
-    void socketDataAvailable();
+protected slots:
+    void onSocketDataAvailable();
 
 private:
     bool readSocketData(QVariant &item);
index 8ed3469..f2439fc 100644 (file)
@@ -40,8 +40,10 @@ RemotePeer::RemotePeer(::AuthHandler *authHandler, QTcpSocket *socket, QObject *
     _lag(0)
 {
     socket->setParent(this);
-    connect(socket, SIGNAL(disconnected()), SIGNAL(disconnected()));
+    connect(socket, SIGNAL(readyRead()), SLOT(onSocketDataAvailable()));
+    connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(onSocketStateChanged(QAbstractSocket::SocketState)));
     connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(onSocketError(QAbstractSocket::SocketError)));
+    connect(socket, SIGNAL(disconnected()), SIGNAL(disconnected()));
 
 #ifdef HAVE_SSL
     QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket);
@@ -50,6 +52,11 @@ RemotePeer::RemotePeer(::AuthHandler *authHandler, QTcpSocket *socket, QObject *
 #endif
 
     connect(_heartBeatTimer, SIGNAL(timeout()), SLOT(sendHeartBeat()));
+
+    // It's possible that more data has already arrived during the handshake, so readyRead() wouldn't be triggered.
+    // However, we can't call a virtual function from the ctor, so let's do it asynchronously.
+    if (socket->bytesAvailable())
+        QTimer::singleShot(0, this, SLOT(onSocketDataAvailable()));
 }
 
 
index a40edc4..14d49f9 100644 (file)
@@ -76,11 +76,14 @@ protected:
     virtual void dispatch(const Protocol::HeartBeat &msg) = 0;
     virtual void dispatch(const Protocol::HeartBeatReply &msg) = 0;
 
+protected slots:
+    virtual void onSocketDataAvailable() = 0;
+    virtual void onSocketStateChanged(QAbstractSocket::SocketState state);
+    virtual void onSocketError(QAbstractSocket::SocketError error);
+
 private slots:
     void sendHeartBeat();
     void changeHeartBeatInterval(int secs);
-    void onSocketStateChanged(QAbstractSocket::SocketState state);
-    void onSocketError(QAbstractSocket::SocketError error);
 
 private:
     QTcpSocket *_socket;