kutils: limit the connections to HTTP(S) server to 10, decrease poll interval

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-05-09 13:53:24 +03:00
parent 61cbcf083c
commit e36bf7631a
2 changed files with 23 additions and 14 deletions

View file

@ -28,7 +28,8 @@
# include <microhttpd.h> # include <microhttpd.h>
#endif #endif
static const int MHDPollInterval = 100; static const int MHDPollInterval = 50;
static const uint MHDConnectionLimit = 10;
class KHTTPPrivate : public QObject class KHTTPPrivate : public QObject
{ {
@ -157,7 +158,7 @@ bool KHTTPPrivate::start(const QHostAddress &address, quint16 port)
kDebug() << "Enabling TLS"; kDebug() << "Enabling TLS";
mhdflags |= MHD_USE_TLS; mhdflags |= MHD_USE_TLS;
} }
const enum MHD_Result mhdresult = MHD_is_feature_supported(MHD_FEATURE_MESSAGES); enum MHD_Result mhdresult = MHD_is_feature_supported(MHD_FEATURE_MESSAGES);
if (mhdresult == MHD_NO) { if (mhdresult == MHD_NO) {
kWarning() << "Messages are not supported"; kWarning() << "Messages are not supported";
} else { } else {
@ -181,12 +182,15 @@ bool KHTTPPrivate::start(const QHostAddress &address, quint16 port)
MHD_OPTION_HTTPS_MEM_CERT, m_tlscert.constData(), MHD_OPTION_HTTPS_MEM_CERT, m_tlscert.constData(),
MHD_OPTION_HTTPS_KEY_PASSWORD, m_tlspassword.constData(), MHD_OPTION_HTTPS_KEY_PASSWORD, m_tlspassword.constData(),
MHD_OPTION_SOCK_ADDR, &socketaddress, MHD_OPTION_SOCK_ADDR, &socketaddress,
MHD_OPTION_CONNECTION_LIMIT, MHDConnectionLimit,
MHD_OPTION_PER_IP_CONNECTION_LIMIT, MHDConnectionLimit,
MHD_OPTION_END MHD_OPTION_END
); );
break; break;
} }
case QAbstractSocket::IPv6Protocol: { case QAbstractSocket::IPv6Protocol: {
if (MHD_is_feature_supported(MHD_FEATURE_IPv6) != MHD_YES) { mhdresult = MHD_is_feature_supported(MHD_FEATURE_IPv6);
if (mhdresult == MHD_NO) {
kWarning() << "IPv6 is not supported"; kWarning() << "IPv6 is not supported";
return false; return false;
} }
@ -207,6 +211,8 @@ bool KHTTPPrivate::start(const QHostAddress &address, quint16 port)
MHD_OPTION_HTTPS_MEM_CERT, m_tlscert.constData(), MHD_OPTION_HTTPS_MEM_CERT, m_tlscert.constData(),
MHD_OPTION_HTTPS_KEY_PASSWORD, m_tlspassword.constData(), MHD_OPTION_HTTPS_KEY_PASSWORD, m_tlspassword.constData(),
MHD_OPTION_SOCK_ADDR, &socketaddress, MHD_OPTION_SOCK_ADDR, &socketaddress,
MHD_OPTION_CONNECTION_LIMIT, MHDConnectionLimit,
MHD_OPTION_PER_IP_CONNECTION_LIMIT, MHDConnectionLimit,
MHD_OPTION_END MHD_OPTION_END
); );
break; break;
@ -253,7 +259,10 @@ QString KHTTPPrivate::errorString() const
void KHTTPPrivate::slotMHDPoll() void KHTTPPrivate::slotMHDPoll()
{ {
if (m_mhddaemon) { if (m_mhddaemon) {
MHD_run(m_mhddaemon); const enum MHD_Result mhdresult = MHD_run(m_mhddaemon);
if (Q_UNLIKELY(mhdresult == MHD_NO)) {
kWarning() << "Could not poll";
}
} }
} }
@ -310,7 +319,7 @@ enum MHD_Result KHTTPPrivate::accessCallback(void *cls,
khttpprivate->m_authmessage.size(), khttpprivate->m_authmessage.data(), khttpprivate->m_authmessage.size(), khttpprivate->m_authmessage.data(),
MHD_RESPMEM_MUST_COPY MHD_RESPMEM_MUST_COPY
); );
if (!mhdresponse) { if (Q_UNLIKELY(!mhdresponse)) {
kWarning() << "Could not create MHD auth response"; kWarning() << "Could not create MHD auth response";
return MHD_NO; return MHD_NO;
} }
@ -331,7 +340,7 @@ enum MHD_Result KHTTPPrivate::accessCallback(void *cls,
} }
} }
khttpprivate->m_url = QUrl(QString::fromUtf8(url)); khttpprivate->m_url = QUrl(QString::fromAscii(url));
MHD_get_connection_values( MHD_get_connection_values(
connection, connection,
MHD_GET_ARGUMENT_KIND, MHD_GET_ARGUMENT_KIND,
@ -340,28 +349,28 @@ enum MHD_Result KHTTPPrivate::accessCallback(void *cls,
); );
QByteArray khttpurl = khttpprivate->m_url.toEncoded(); QByteArray khttpurl = khttpprivate->m_url.toEncoded();
KHTTPHeaders khttpheaders; KHTTPHeaders mhdouthttpheaders;
QByteArray mhdoutdata; QByteArray mhdoutdata;
ushort mhdouthttpstatus = MHD_HTTP_NOT_FOUND; ushort mhdouthttpstatus = MHD_HTTP_NOT_FOUND;
khttp->respond(khttpurl, &mhdoutdata, &mhdouthttpstatus, &khttpheaders); khttp->respond(khttpurl, &mhdoutdata, &mhdouthttpstatus, &mhdouthttpheaders);
struct MHD_Response *mhdresponse = MHD_create_response_from_buffer( struct MHD_Response *mhdresponse = MHD_create_response_from_buffer(
mhdoutdata.size(), mhdoutdata.data(), mhdoutdata.size(), mhdoutdata.data(),
MHD_RESPMEM_MUST_COPY MHD_RESPMEM_MUST_COPY
); );
if (!mhdresponse) { if (Q_UNLIKELY(!mhdresponse)) {
kWarning() << "Could not create MHD response"; kWarning() << "Could not create MHD response";
return MHD_NO; return MHD_NO;
} }
enum MHD_Result mhdresult = MHD_NO; enum MHD_Result mhdresult = MHD_NO;
foreach (const QByteArray &httpheaderkey, khttpheaders.keys()) { foreach (const QByteArray &httpheaderkey, mhdouthttpheaders.keys()) {
if (qstricmp(httpheaderkey.constData(), "Content-Length") == 0) { if (qstricmp(httpheaderkey.constData(), "Content-Length") == 0) {
// MHD refuses to add it // MHD refuses to add it
kDebug() << "Ignoring content-length"; kDebug() << "Ignoring content-length";
continue; continue;
} }
const QByteArray httpheadervalue = khttpheaders.value(httpheaderkey); const QByteArray httpheadervalue = mhdouthttpheaders.value(httpheaderkey);
mhdresult = MHD_add_response_header(mhdresponse, httpheaderkey.constData(), httpheadervalue.constData()); mhdresult = MHD_add_response_header(mhdresponse, httpheaderkey.constData(), httpheadervalue.constData());
if (mhdresult == MHD_NO) { if (mhdresult == MHD_NO) {
kWarning() << "Could not add response header" << httpheaderkey << httpheadervalue; kWarning() << "Could not add response header" << httpheaderkey << httpheadervalue;

View file

@ -49,15 +49,15 @@ public:
requires password it must also be provided as @p password. requires password it must also be provided as @p password.
@note HTTP requests to the server address will not be redirected, clients must request @note HTTP requests to the server address will not be redirected, clients must request
HTTPS address. For example if TLS/SSL certificate is set "http://foo.bar" will not be HTTPS address. For example if TLS/SSL certificate is set "http://foo.bar" will not be
reachable (no data is send) however "https://foo.bar" will be, unless external means are accessible (no data is send) however "https://foo.bar" will be, unless external means are
used to redirect the request. This is the case only when non-standard ports are used, if used to redirect the request. This is the case only when non-standard ports are used, if
HTTP server runs on port 80 and HTTPS server runs on port 443 then both are accessible but HTTP server runs on port 80 and HTTPS server runs on port 443 then both are accessible but
the client will most likely be making requests to the HTTP server on port 80. clients will most likely be making requests to the HTTP server on port 80.
*/ */
bool setCertificate(const QByteArray &keydata, const QByteArray &certdata, const QByteArray &password = QByteArray()); bool setCertificate(const QByteArray &keydata, const QByteArray &certdata, const QByteArray &password = QByteArray());
/*! /*!
@brief Sets @p username and @p password to be used for authentication with @p message as @brief Sets @p username and @p password to be used for authentication with @p message as
content to be send to the client when authentication fails. content to be send to clients when authentication fails.
@note The authentication method used is basic @note The authentication method used is basic
*/ */
bool setAuthenticate(const QByteArray &username, const QByteArray &password, const QString &message); bool setAuthenticate(const QByteArray &username, const QByteArray &password, const QString &message);