/** * @RDE_HEADER@ * One EGCU HandleHttpRequest * $Id$ * $HeadURL$ * $Author$ * Created by Christian Ehrlicher, SLSE, 2017-02-07 */ #include "handle_http_request.h" #include #include #include #include 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