2017-08-23 12:47:07 -04:00
|
|
|
#ifndef QT_NO_OPENSSL
|
|
|
|
#include <QSslSocket>
|
|
|
|
#include <QSslKey>
|
|
|
|
#include <QSslCertificate>
|
|
|
|
#include <QSslConfiguration>
|
|
|
|
#endif
|
|
|
|
#include <QDir>
|
|
|
|
#include "httpconnectionhandlerpool.h"
|
|
|
|
|
2017-11-11 03:32:15 -05:00
|
|
|
using namespace qtwebapp;
|
2017-08-23 12:47:07 -04:00
|
|
|
|
|
|
|
HttpConnectionHandlerPool::HttpConnectionHandlerPool(QSettings* settings, HttpRequestHandler* requestHandler)
|
2017-11-12 19:36:00 -05:00
|
|
|
: QObject(), useQtSettings(true)
|
2017-08-23 12:47:07 -04:00
|
|
|
{
|
2017-11-18 04:15:29 -05:00
|
|
|
Q_ASSERT(settings != 0);
|
|
|
|
this->settings = settings;
|
|
|
|
this->listenerSettings = 0;
|
|
|
|
this->requestHandler = requestHandler;
|
|
|
|
this->sslConfiguration = 0;
|
2017-08-23 12:47:07 -04:00
|
|
|
loadSslConfig();
|
|
|
|
cleanupTimer.start(settings->value("cleanupInterval",1000).toInt());
|
|
|
|
connect(&cleanupTimer, SIGNAL(timeout()), SLOT(cleanup()));
|
|
|
|
}
|
|
|
|
|
2017-11-18 04:15:29 -05:00
|
|
|
HttpConnectionHandlerPool::HttpConnectionHandlerPool(const HttpListenerSettings* settings, HttpRequestHandler* requestHandler)
|
2017-11-13 07:46:02 -05:00
|
|
|
: QObject(), useQtSettings(false)
|
2017-11-12 19:36:00 -05:00
|
|
|
{
|
2017-12-24 14:27:20 -05:00
|
|
|
Q_ASSERT(settings != 0);
|
2017-11-18 04:15:29 -05:00
|
|
|
this->settings = 0;
|
|
|
|
this->listenerSettings = settings;
|
|
|
|
this->requestHandler = requestHandler;
|
|
|
|
this->sslConfiguration = 0;
|
2017-11-12 19:36:00 -05:00
|
|
|
loadSslConfig();
|
2017-11-18 04:15:29 -05:00
|
|
|
cleanupTimer.start(settings->cleanupInterval);
|
2017-11-12 19:36:00 -05:00
|
|
|
connect(&cleanupTimer, SIGNAL(timeout()), SLOT(cleanup()));
|
|
|
|
}
|
|
|
|
|
2017-08-23 12:47:07 -04:00
|
|
|
HttpConnectionHandlerPool::~HttpConnectionHandlerPool()
|
|
|
|
{
|
|
|
|
// delete all connection handlers and wait until their threads are closed
|
|
|
|
foreach(HttpConnectionHandler* handler, pool)
|
|
|
|
{
|
|
|
|
delete handler;
|
|
|
|
}
|
|
|
|
delete sslConfiguration;
|
|
|
|
qDebug("HttpConnectionHandlerPool (%p): destroyed", this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HttpConnectionHandler* HttpConnectionHandlerPool::getConnectionHandler()
|
|
|
|
{
|
|
|
|
HttpConnectionHandler* freeHandler=0;
|
|
|
|
mutex.lock();
|
|
|
|
// find a free handler in pool
|
|
|
|
foreach(HttpConnectionHandler* handler, pool)
|
|
|
|
{
|
|
|
|
if (!handler->isBusy())
|
|
|
|
{
|
|
|
|
freeHandler=handler;
|
|
|
|
freeHandler->setBusy();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// create a new handler, if necessary
|
|
|
|
if (!freeHandler)
|
|
|
|
{
|
2017-11-18 04:15:29 -05:00
|
|
|
int maxConnectionHandlers = useQtSettings ? settings->value("maxThreads",100).toInt() : listenerSettings->maxThreads;
|
2017-08-23 12:47:07 -04:00
|
|
|
if (pool.count()<maxConnectionHandlers)
|
|
|
|
{
|
2017-11-17 02:52:15 -05:00
|
|
|
if (useQtSettings) {
|
|
|
|
freeHandler = new HttpConnectionHandler(settings, requestHandler, sslConfiguration);
|
|
|
|
} else {
|
|
|
|
freeHandler = new HttpConnectionHandler(listenerSettings, requestHandler, sslConfiguration);
|
|
|
|
}
|
|
|
|
|
2017-08-23 12:47:07 -04:00
|
|
|
freeHandler->setBusy();
|
|
|
|
pool.append(freeHandler);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mutex.unlock();
|
|
|
|
return freeHandler;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void HttpConnectionHandlerPool::cleanup()
|
|
|
|
{
|
2017-11-18 04:15:29 -05:00
|
|
|
int maxIdleHandlers = useQtSettings ? settings->value("minThreads",1).toInt() : listenerSettings->minThreads;
|
2017-08-23 12:47:07 -04:00
|
|
|
int idleCounter=0;
|
|
|
|
mutex.lock();
|
|
|
|
foreach(HttpConnectionHandler* handler, pool)
|
|
|
|
{
|
|
|
|
if (!handler->isBusy())
|
|
|
|
{
|
|
|
|
if (++idleCounter > maxIdleHandlers)
|
|
|
|
{
|
|
|
|
delete handler;
|
|
|
|
pool.removeOne(handler);
|
|
|
|
qDebug("HttpConnectionHandlerPool: Removed connection handler (%p), pool size is now %i",handler,pool.size());
|
|
|
|
break; // remove only one handler in each interval
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mutex.unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void HttpConnectionHandlerPool::loadSslConfig()
|
|
|
|
{
|
|
|
|
// If certificate and key files are configured, then load them
|
2017-11-18 04:15:29 -05:00
|
|
|
QString sslKeyFileName = useQtSettings ? settings->value("sslKeyFile","").toString() : listenerSettings->sslKeyFile;
|
|
|
|
QString sslCertFileName = useQtSettings ? settings->value("sslCertFile","").toString() : listenerSettings->sslCertFile;
|
2017-08-23 12:47:07 -04:00
|
|
|
if (!sslKeyFileName.isEmpty() && !sslCertFileName.isEmpty())
|
|
|
|
{
|
|
|
|
#ifdef QT_NO_OPENSSL
|
2018-02-11 15:45:44 -05:00
|
|
|
qWarning("HttpConnectionHandlerPool::loadSslConfig: SSL is not supported");
|
2017-08-23 12:47:07 -04:00
|
|
|
#else
|
|
|
|
// Convert relative fileNames to absolute, based on the directory of the config file.
|
|
|
|
QFileInfo configFile(settings->fileName());
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (QDir::isRelativePath(sslKeyFileName) && settings->format()!=QSettings::NativeFormat)
|
|
|
|
#else
|
|
|
|
if (QDir::isRelativePath(sslKeyFileName))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
sslKeyFileName=QFileInfo(configFile.absolutePath(),sslKeyFileName).absoluteFilePath();
|
|
|
|
}
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (QDir::isRelativePath(sslCertFileName) && settings->format()!=QSettings::NativeFormat)
|
|
|
|
#else
|
|
|
|
if (QDir::isRelativePath(sslCertFileName))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
sslCertFileName=QFileInfo(configFile.absolutePath(),sslCertFileName).absoluteFilePath();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load the SSL certificate
|
|
|
|
QFile certFile(sslCertFileName);
|
|
|
|
if (!certFile.open(QIODevice::ReadOnly))
|
|
|
|
{
|
|
|
|
qCritical("HttpConnectionHandlerPool: cannot open sslCertFile %s", qPrintable(sslCertFileName));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QSslCertificate certificate(&certFile, QSsl::Pem);
|
|
|
|
certFile.close();
|
|
|
|
|
|
|
|
// Load the key file
|
|
|
|
QFile keyFile(sslKeyFileName);
|
|
|
|
if (!keyFile.open(QIODevice::ReadOnly))
|
|
|
|
{
|
|
|
|
qCritical("HttpConnectionHandlerPool: cannot open sslKeyFile %s", qPrintable(sslKeyFileName));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QSslKey sslKey(&keyFile, QSsl::Rsa, QSsl::Pem);
|
|
|
|
keyFile.close();
|
|
|
|
|
|
|
|
// Create the SSL configuration
|
|
|
|
sslConfiguration=new QSslConfiguration();
|
|
|
|
sslConfiguration->setLocalCertificate(certificate);
|
|
|
|
sslConfiguration->setPrivateKey(sslKey);
|
|
|
|
sslConfiguration->setPeerVerifyMode(QSslSocket::VerifyNone);
|
|
|
|
sslConfiguration->setProtocol(QSsl::TlsV1SslV3);
|
|
|
|
|
|
|
|
qDebug("HttpConnectionHandlerPool: SSL settings loaded");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|