Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-9529

QSslSocket::waitForReadyRead is broken with data > 4096 bytes

    XMLWordPrintable

Details

    • Bug
    • Resolution: Out of scope
    • Not Evaluated
    • None
    • 4.6.2
    • Network
    • None
    • Ubuntu 9.04, 64 bits

    Description

      When using a QSslSocket, if I connect the readyRead() signal to a incomingData() slot with the following code:

      void SslTest::incomingData()
      {
        QSslSocket * socket = qobject_cast<QSslSocket*>(sender());
        QByteArray data;
        while(data.size() != 10000)
        {
          data.append(socket->readAll());
          qDebug() << "Size:" << data.size();
          socket->waitForReadyRead(5000);
        }
      }
      

      and I send 10K (or any amount > 4096 bytes) on that socket (in one go) from another client (handshake went fine), I get the following output:
      Size: 4096
      Size: 4096
      Size: 4096
      Size: 4096
      etc....

      with 5s gaps between each line, meaning waitForReadyRead() times out, without ever seeing new data. So clearly, either waitForReadyRead() is not doing it's role, or readAll() isn't. But I can only get the first 4096 bytes from the original data sent.

      Now, if I change this slot to :

      void SslTest::incomingData()
      {
        QSslSocket * socket = qobject_cast<QSslSocket*>(sender());
        QByteArray data;
        data.append(socket->readAll());
        qDebug() << "Size:" << data.size();
      }
      

      Then I get the correct (but somewhat unexpected) output, which properly adds up to 10k :

      Size: 4096
      Size: 4096
      Size: 1808

      I say "somewhat unexpected" because the data is cut in chunks of exactly 4096, but I guess that's due to the encryption.

      I had a look at the qsslsocket sources, and noticed that readData(...) contained a "QMetaObject::invokeMethod(this, "_q_flushReadBuffer", Qt::QueuedConnection);". Obviously that's not going to get called from a waitForReadyRead() so I will never have the extra data I'm waiting for until I exit the incomingData() slot, even though it's probably in the plain socket's buffer, but not decrypted yet.

      This bug seems to be very similar to this one:
      http://www.qtcentre.org/threads/20513-QSslSocket-and-decryption-buffer

      Also, I seem to not be the first to notice the strange implementation of the waitFor* family of functions of QSslSocket, as if you have a look in your own testsuite, in tests/auto/qsslsocket/tst_qsslsocket.cpp, you will find this comment (around line 1594):

      // I don't understand how socket->waitForDisconnected can work on other platforms
      // since socket->write will end to:
      //   QMetaObject::invokeMethod(this, "_q_flushWriteBuffer", Qt::QueuedConnection);
      // In order that _q_flushWriteBuffer will be called the eventloop need to run
      // If we just call waitForDisconnected, which blocks the whole thread how that can happen?
      

      which is my point exactly.

      Summary: I'd very much like to have access to more than 4096 bytes when using the blocking API with QSslSocket.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            tmacieir Thiago Macieira (closed Nokia identity) (Inactive)
            fvichot Florian Vichot
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes