QSslServer: Make sure maxPendingConnections applies to all sockets
Not just the ones we added to the pending sockets list Pick-to: 6.4 Change-Id: I0a0016fe39df7ca2fc3f0c4e4111195bc6d90198 Reviewed-by: Konrad Kujawa <konrad.kujawa@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
29a1fe72a0
commit
1ee75e4740
@ -172,7 +172,7 @@ void QTcpServerPrivate::readNotification()
|
|||||||
{
|
{
|
||||||
Q_Q(QTcpServer);
|
Q_Q(QTcpServer);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (pendingConnections.count() >= maxConnections) {
|
if (totalPendingConnections() >= maxConnections) {
|
||||||
#if defined (QTCPSERVER_DEBUG)
|
#if defined (QTCPSERVER_DEBUG)
|
||||||
qDebug("QTcpServerPrivate::_q_processIncomingConnection() too many connections");
|
qDebug("QTcpServerPrivate::_q_processIncomingConnection() too many connections");
|
||||||
#endif
|
#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.
|
Constructs a QTcpServer object.
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual void configureCreatedSocket();
|
virtual void configureCreatedSocket();
|
||||||
|
virtual int totalPendingConnections() const;
|
||||||
|
|
||||||
// from QAbstractSocketEngineReceiver
|
// from QAbstractSocketEngineReceiver
|
||||||
void readNotification() override;
|
void readNotification() override;
|
||||||
|
@ -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()
|
void QSslServerPrivate::checkClientHelloAndContinue()
|
||||||
{
|
{
|
||||||
Q_Q(QSslServer);
|
Q_Q(QSslServer);
|
||||||
|
@ -38,6 +38,7 @@ public:
|
|||||||
void initializeHandshakeProcess(QSslSocket *socket);
|
void initializeHandshakeProcess(QSslSocket *socket);
|
||||||
void removeSocketData(quintptr socket);
|
void removeSocketData(quintptr socket);
|
||||||
void handleHandshakeTimedOut(QSslSocket *socket);
|
void handleHandshakeTimedOut(QSslSocket *socket);
|
||||||
|
int totalPendingConnections() const override;
|
||||||
|
|
||||||
struct SocketData {
|
struct SocketData {
|
||||||
QMetaObject::Connection readyReadConnection;
|
QMetaObject::Connection readyReadConnection;
|
||||||
|
@ -25,6 +25,7 @@ private slots:
|
|||||||
#endif
|
#endif
|
||||||
void plaintextClient();
|
void plaintextClient();
|
||||||
void quietClient();
|
void quietClient();
|
||||||
|
void manyQuietClients();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString testDataDir;
|
QString testDataDir;
|
||||||
@ -487,6 +488,34 @@ void tst_QSslServer::quietClient()
|
|||||||
QCOMPARE(serverPeerPort, clientLocalPort);
|
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<const QList<QSslError> &>(&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<QTcpSocket, size_t(ExpectedConnections) * 4> 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<QSslSocket *>().size();
|
||||||
|
QCOMPARE(connectedCount, ExpectedConnections);
|
||||||
|
// 1 socket is ready and pending
|
||||||
|
QCOMPARE(server.pendingConnectionAvailableSpy.size(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QSslServer)
|
QTEST_MAIN(tst_QSslServer)
|
||||||
|
|
||||||
#include "tst_qsslserver.moc"
|
#include "tst_qsslserver.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user