Allow to set TCP network listen(2) backlog

Qt has a hardcoded backlog value of 50,
this allows for applications to tune this
value. Modern kernels have the SYN cookie
feature that reduces pressure from an
flood attack, the backlog setting however
is then a queue for most likely real
completed (SYN/ACK) connections hence, it's
easy to get clients connections dropped
with this very small limit.

[ChangeLog][QtNetwork][QTcpServer] Added
QTcpServer::setListenBacklog() to be able
to have control over the listen backlog feature.

Change-Id: I1c78af6d99e012591e214b7e09fa85c485880d48
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
bb10
Daniel Nicoletti 2021-06-29 16:37:41 -03:00
parent 0f32703aa5
commit e095fa7f9c
12 changed files with 48 additions and 17 deletions

View File

@ -133,7 +133,7 @@ public:
virtual bool connectToHost(const QHostAddress &address, quint16 port) = 0;
virtual bool connectToHostByName(const QString &name, quint16 port) = 0;
virtual bool bind(const QHostAddress &address, quint16 port) = 0;
virtual bool listen() = 0;
virtual bool listen(int backlog) = 0;
virtual int accept() = 0;
virtual void close() = 0;

View File

@ -191,8 +191,9 @@ bool QHttpSocketEngine::bind(const QHostAddress &, quint16)
return false;
}
bool QHttpSocketEngine::listen()
bool QHttpSocketEngine::listen(int backlog)
{
Q_UNUSED(backlog);
qWarning("Operation is not supported");
setError(QAbstractSocket::UnsupportedSocketOperationError,
QLatin1String("Unsupported socket operation"));

View File

@ -95,7 +95,7 @@ public:
bool connectToHost(const QHostAddress &address, quint16 port) override;
bool connectToHostByName(const QString &name, quint16 port) override;
bool bind(const QHostAddress &address, quint16 port) override;
bool listen() override;
bool listen(int backlog) override;
int accept() override;
void close() override;

View File

@ -689,7 +689,7 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
\sa bind(), accept()
*/
bool QNativeSocketEngine::listen()
bool QNativeSocketEngine::listen(int backlog)
{
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::listen(), false);
@ -701,11 +701,7 @@ bool QNativeSocketEngine::listen()
Q_CHECK_TYPE(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket, false);
#endif
// We're using a backlog of 50. Most modern kernels support TCP
// syncookies by default, and if they do, the backlog is ignored.
// When there is no support for TCP syncookies, this value is
// fine.
return d->nativeListen(50);
return d->nativeListen(backlog);
}
/*!

View File

@ -138,7 +138,7 @@ public:
bool connectToHost(const QHostAddress &address, quint16 port) override;
bool connectToHostByName(const QString &name, quint16 port) override;
bool bind(const QHostAddress &address, quint16 port) override;
bool listen() override;
bool listen(int backlog) override;
int accept() override;
void close() override;

View File

@ -1391,9 +1391,10 @@ bool QSocks5SocketEngine::bind(const QHostAddress &addr, quint16 port)
}
bool QSocks5SocketEngine::listen()
bool QSocks5SocketEngine::listen(int backlog)
{
Q_D(QSocks5SocketEngine);
Q_UNUSED(backlog);
QSOCKS5_Q_DEBUG << "listen()";

View File

@ -81,7 +81,7 @@ public:
bool connectToHost(const QHostAddress &address, quint16 port) override;
bool connectToHostByName(const QString &name, quint16 port) override;
bool bind(const QHostAddress &address, quint16 port) override;
bool listen() override;
bool listen(int backlog) override;
int accept() override;
void close() override;

View File

@ -331,7 +331,7 @@ bool QTcpServer::listen(const QHostAddress &address, quint16 port)
return false;
}
if (!d->socketEngine->listen()) {
if (!d->socketEngine->listen(d->listenBacklog)) {
d->serverSocketError = d->socketEngine->error();
d->serverSocketErrorString = d->socketEngine->errorString();
return false;
@ -649,6 +649,35 @@ int QTcpServer::maxPendingConnections() const
return d_func()->maxConnections;
}
/*!
Sets the backlog queue size of to be accepted connections to \a
size. The operating system might reduce or ignore this value.
By default, the queue size is 50.
\note This setting is only used when listen() is called.
\since 6.3
\sa listenBacklog()
*/
void QTcpServer::setListenBacklog(int size)
{
d_func()->listenBacklog = size;
}
/*!
Returns the backlog queue size of to be accepted connections. The
default is 50.
\since 6.3
\sa setListenBacklog()
*/
int QTcpServer::listenBacklog() const
{
return d_func()->listenBacklog;
}
/*!
Returns an error code for the last error that occurred.

View File

@ -69,6 +69,9 @@ public:
void setMaxPendingConnections(int numConnections);
int maxPendingConnections() const;
void setListenBacklog(int size);
int listenBacklog() const;
quint16 serverPort() const;
QHostAddress serverAddress() const;

View File

@ -83,6 +83,7 @@ public:
QAbstractSocket::SocketError serverSocketError;
QString serverSocketErrorString;
int listenBacklog = 50;
int maxConnections;
#ifndef QT_NO_NETWORKPROXY

View File

@ -324,7 +324,7 @@ void tst_PlatformSocketEngine::serverTest()
quint16 port = server.localPort();
// Listen for incoming connections
QVERIFY(server.listen());
QVERIFY(server.listen(50));
QCOMPARE(server.state(), QAbstractSocket::ListeningState);
// Initialize a Tcp socket
@ -429,7 +429,7 @@ void tst_PlatformSocketEngine::tcpLoopbackPerformance()
quint16 port = server.localPort();
// Listen for incoming connections
QVERIFY(server.listen());
QVERIFY(server.listen(50));
QCOMPARE(server.state(), QAbstractSocket::ListeningState);
// Initialize a Tcp socket
@ -620,7 +620,7 @@ void tst_PlatformSocketEngine::receiveUrgentData()
QCOMPARE(server.state(), QAbstractSocket::BoundState);
quint16 port = server.localPort();
QVERIFY(server.listen());
QVERIFY(server.listen(50));
QCOMPARE(server.state(), QAbstractSocket::ListeningState);
PLATFORMSOCKETENGINE client;

View File

@ -453,7 +453,7 @@ void tst_QSocks5SocketEngine::serverTest()
QCOMPARE(server.state(), QAbstractSocket::BoundState);
// Listen for incoming connections
QVERIFY(server.listen());
QVERIFY(server.listen(50));
QCOMPARE(server.state(), QAbstractSocket::ListeningState);
// Initialize a Tcp socket