diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp index 95d1877a5db..e6ff34cee91 100644 --- a/src/network/socket/qtcpserver.cpp +++ b/src/network/socket/qtcpserver.cpp @@ -172,7 +172,7 @@ void QTcpServerPrivate::readNotification() { Q_Q(QTcpServer); for (;;) { - if (pendingConnections.count() >= maxConnections) { + if (totalPendingConnections() >= maxConnections) { #if defined (QTCPSERVER_DEBUG) qDebug("QTcpServerPrivate::_q_processIncomingConnection() too many connections"); #endif @@ -205,6 +205,20 @@ void QTcpServerPrivate::readNotification() } } +/*! + \internal + Return the amount of sockets currently in queue for the server. + This is to make maxPendingConnections work properly with servers that don't + necessarily have 'ready-to-go' sockets as soon as they connect, + e.g. QSslServer. + By default we just return pendingConnections.size(), which is equivalent to + what it did before. +*/ +int QTcpServerPrivate::totalPendingConnections() const +{ + return int(pendingConnections.size()); +} + /*! Constructs a QTcpServer object. diff --git a/src/network/socket/qtcpserver_p.h b/src/network/socket/qtcpserver_p.h index a5265495386..853a4aaf96b 100644 --- a/src/network/socket/qtcpserver_p.h +++ b/src/network/socket/qtcpserver_p.h @@ -56,6 +56,7 @@ public: #endif virtual void configureCreatedSocket(); + virtual int totalPendingConnections() const; // from QAbstractSocketEngineReceiver void readNotification() override; diff --git a/src/network/ssl/qsslserver.cpp b/src/network/ssl/qsslserver.cpp index 2ec42bf3ce7..f96fccce823 100644 --- a/src/network/ssl/qsslserver.cpp +++ b/src/network/ssl/qsslserver.cpp @@ -350,6 +350,12 @@ void QSslServerPrivate::removeSocketData(quintptr socket) } } +int QSslServerPrivate::totalPendingConnections() const +{ + // max pending connections is int, so this cannot exceed that + return QTcpServerPrivate::totalPendingConnections() + int(socketData.size()); +} + void QSslServerPrivate::checkClientHelloAndContinue() { Q_Q(QSslServer); diff --git a/src/network/ssl/qsslserver_p.h b/src/network/ssl/qsslserver_p.h index 71359f6cff8..1b90d35d489 100644 --- a/src/network/ssl/qsslserver_p.h +++ b/src/network/ssl/qsslserver_p.h @@ -38,6 +38,7 @@ public: void initializeHandshakeProcess(QSslSocket *socket); void removeSocketData(quintptr socket); void handleHandshakeTimedOut(QSslSocket *socket); + int totalPendingConnections() const override; struct SocketData { QMetaObject::Connection readyReadConnection; diff --git a/tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp b/tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp index 088f0170f42..b153d9545e0 100644 --- a/tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp +++ b/tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp @@ -25,6 +25,7 @@ private slots: #endif void plaintextClient(); void quietClient(); + void manyQuietClients(); private: QString testDataDir; @@ -487,6 +488,34 @@ void tst_QSslServer::quietClient() QCOMPARE(serverPeerPort, clientLocalPort); } +void tst_QSslServer::manyQuietClients() +{ + QSslConfiguration serverConfiguration = selfSignedServerQSslConfiguration(); + SslServerSpy server(serverConfiguration); + constexpr qsizetype ExpectedConnections = 5; + server.server.setMaxPendingConnections(ExpectedConnections); + QVERIFY(server.server.listen()); + + // Connect one socket encrypted so we have a socket in the regular queue + QSslSocket tlsSocket; + QObject::connect(&tlsSocket, &QSslSocket::sslErrors, &tlsSocket, + qOverload &>(&QSslSocket::ignoreSslErrors)); + tlsSocket.connectToHostEncrypted("127.0.0.1", server.server.serverPort()); + + // Then we connect a bunch of TCP sockets who will not send any data at all + std::array sockets; + for (QTcpSocket &socket : sockets) + socket.connectToHost(QHostAddress::LocalHost, server.server.serverPort()); + QTest::qWait(500); // some leeway to let connections try to connect... + + // I happen to know the sockets are all children of the server, so let's see + // how many are created: + qsizetype connectedCount = server.server.findChildren().size(); + QCOMPARE(connectedCount, ExpectedConnections); + // 1 socket is ready and pending + QCOMPARE(server.pendingConnectionAvailableSpy.size(), 1); +} + QTEST_MAIN(tst_QSslServer) #include "tst_qsslserver.moc"