194 lines
6.0 KiB
C++
Executable File
194 lines
6.0 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* One EGCU HandleHttpRequest
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Christian Ehrlicher, SLSE, 2017-02-07
|
|
*/
|
|
|
|
#include "handle_http_request.h"
|
|
#include <QAuthenticator>
|
|
#include <QNetworkAccessManager>
|
|
#include <QNetworkReply>
|
|
#include <QTimer>
|
|
|
|
namespace BuildingControlUnit
|
|
{
|
|
HandleHttpRequest::HandleHttpRequest(bool useQueue, QObject *parent)
|
|
: QObject(parent)
|
|
, m_nam(new QNetworkAccessManager(this))
|
|
, m_bUseQueue(useQueue)
|
|
, m_logger(getLogger("HandleHttpRequest"))
|
|
{
|
|
INFO_LOG(m_logger) << "Using Queue: " << m_bUseQueue;
|
|
connect(m_nam, &QNetworkAccessManager::finished,
|
|
this, &HandleHttpRequest::onReplyFinished);
|
|
connect(m_nam, &QNetworkAccessManager::authenticationRequired,
|
|
this, &HandleHttpRequest::onAuthenticationRequired);
|
|
}
|
|
|
|
|
|
/*
|
|
void HandleHttpRequest::enqueue(const QString &path, const QString &query)
|
|
{
|
|
QUrl url;
|
|
url.setScheme(QStringLiteral("http"));
|
|
url.setHost(m_config.hostname);
|
|
url.setPort(m_config.port);
|
|
url.setUserName(m_config.username);
|
|
url.setPassword(m_config.password);
|
|
url.setPath(path);
|
|
url.setQuery(query);
|
|
m_requests.enqueue(QNetworkRequest(url));
|
|
|
|
INFO_LOG(m_logger) << "Added '" << m_requests.back().url().toString() << " to queue";
|
|
trySendNextRequest();
|
|
}
|
|
*/
|
|
|
|
void HandleHttpRequest::init(const QString &username, const QString &passwd)
|
|
{
|
|
m_username = username;
|
|
m_passwd = passwd;
|
|
}
|
|
|
|
void HandleHttpRequest::enqueue(const QUrl &url, HandleHttpQueueMessageStatus status)
|
|
{
|
|
QString host = url.host();
|
|
if (!m_queueMap.contains(host))//If host already in map
|
|
{
|
|
m_queueMap.insert(host, HandleHttpQueue());
|
|
}
|
|
if ((HandleHttpQueueMessageStatus::MS_Cyclic == status) &&
|
|
m_queueMap[host].uniquenessChecker.contains(url.toString()))
|
|
{
|
|
WARNING_LOG(m_logger) << "Discarding duplicate url \"" << url.toString() << "\" due to slow message handling.";
|
|
}
|
|
else
|
|
{
|
|
NetworkRequest networkRequest;
|
|
networkRequest.request = QNetworkRequest(url);
|
|
m_queueMap[host].uniquenessChecker.insert(url.toString());
|
|
m_queueMap[host].requests.enqueue(networkRequest);
|
|
DEBUG_LOG(m_logger) << "Added '" << url.toString() << " to queue for host: " << host
|
|
<< " Queue has " << m_queueMap[host].requests.count() << " elements";
|
|
trySendNextRequest();
|
|
}
|
|
}
|
|
|
|
void HandleHttpRequest::onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
|
|
{
|
|
if (!reply || !authenticator)
|
|
{
|
|
ERROR_LOG(m_logger) << "Internal error - Nullptr exception!";
|
|
}
|
|
else if (!m_queueMap.contains(reply->url().host()))
|
|
{
|
|
WARNING_LOG(m_logger) << "Internal error - got auth reply from unknown host!";
|
|
}
|
|
else
|
|
{
|
|
if (m_bUseQueue && reply != m_queueMap[reply->url().host()].activeReply)
|
|
WARNING_LOG(m_logger) << "Internal error - got auth reply from unknown request!";
|
|
|
|
// fail on second attempt when user/password is wrong
|
|
if (m_queueMap[reply->url().host()].bAuthAlreadyRequested)
|
|
return;
|
|
DEBUG_LOG(m_logger) << "Authentication request";
|
|
authenticator->setUser(m_username);
|
|
authenticator->setPassword(m_passwd);
|
|
m_queueMap[reply->url().host()].bAuthAlreadyRequested = true;
|
|
}
|
|
}
|
|
|
|
void HandleHttpRequest::onReplyFinished(QNetworkReply *reply)
|
|
{
|
|
if ( reply->error() > 0)
|
|
{
|
|
m_queueMap.remove(reply->url().host());
|
|
return;
|
|
}
|
|
if (!reply)
|
|
{
|
|
ERROR_LOG(m_logger) << "Internal error - Nullptr exception!";
|
|
}
|
|
else if (!m_queueMap.contains(reply->url().host()))
|
|
{
|
|
reply->deleteLater();
|
|
WARNING_LOG(m_logger) << "Internal error - got reply from unknown host!";
|
|
}
|
|
else if (m_bUseQueue && reply != m_queueMap[reply->url().host()].activeReply)
|
|
{
|
|
reply->deleteLater();
|
|
WARNING_LOG(m_logger) << "Internal error - got reply from unknown request!";
|
|
}
|
|
else
|
|
{
|
|
const int responseCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
if (responseCode == 200)
|
|
{
|
|
if ( m_newConnection)
|
|
{
|
|
m_newConnection = false;
|
|
DEBUG_LOG(m_logger) << "emit newEgcuConnection host=" << reply->url().host();
|
|
emit newEgcuConnection(reply->url().host());
|
|
}
|
|
DEBUG_LOG(m_logger) << "Request successfull";
|
|
}
|
|
else
|
|
WARNING_LOG(m_logger) << "Invalid request for host " << reply->url().host() << ", response code: " << responseCode << ", query: " << reply->url().toString();
|
|
|
|
QByteArray replyData = reply->readAll();
|
|
DEBUG_LOG(m_logger) << "Got reply (" << reply->url().toString() << "): " << replyData
|
|
<< " host=" << reply->url().host();
|
|
emit egcuReply(reply->url().host(), replyData);
|
|
|
|
m_queueMap[reply->url().host()].activeReply = nullptr;
|
|
reply->deleteLater();
|
|
QTimer::singleShot(0, this, &HandleHttpRequest::trySendNextRequest);
|
|
|
|
}
|
|
}
|
|
|
|
void HandleHttpRequest::sendNextRequest(HandleHttpQueue& queue)
|
|
{
|
|
if (m_bUseQueue && queue.activeReply != nullptr)
|
|
{
|
|
WARNING_LOG(m_logger) << "Internal error - active reply not yet finished!";
|
|
}
|
|
else if (!queue.requests.isEmpty())
|
|
{
|
|
queue.bAuthAlreadyRequested = false;
|
|
const NetworkRequest networkRequest = queue.requests.dequeue();
|
|
const QNetworkRequest request = networkRequest.request;
|
|
queue.uniquenessChecker.remove(request.url().toString());
|
|
if ( networkRequest.time.secsTo(QTime::currentTime()) < 5)
|
|
{
|
|
queue.activeReply = m_nam->get(request);
|
|
DEBUG_LOG(m_logger) << "Send request " << request.url().toString() << " and waiting for reply (" << queue.activeReply << ")";
|
|
}
|
|
else
|
|
{
|
|
DEBUG_LOG(m_logger) << "remove request " << request.url().toString()
|
|
<< " because it's too old" << networkRequest.time.secsTo(QTime::currentTime());
|
|
sendNextRequest(queue);
|
|
m_newConnection = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void HandleHttpRequest::trySendNextRequest()
|
|
{
|
|
// current active request -> wait for it to finish
|
|
for (HandleHttpQueue& queue : m_queueMap)
|
|
{
|
|
if (!(m_bUseQueue && queue.activeReply != nullptr))
|
|
{
|
|
sendNextRequest(queue);
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace BuildingControlUnit
|