1 /*!
2 * \copyright Copyright (c) 2016-2021 Governikus GmbH & Co. KG, Germany
3 */
4
5 #include "HttpServer.h"
6
7 #include <QLoggingCategory>
8 #include <QTcpSocket>
9
10 using namespace governikus;
11
12 Q_DECLARE_LOGGING_CATEGORY(network)
13
14
15 quint16 HttpServer::cPort = PortFile::cDefaultPort;
16
17
HttpServer(quint16 pPort)18 HttpServer::HttpServer(quint16 pPort)
19 : QObject()
20 , mServer(new QTcpServer())
21 , mPortFile()
22 {
23 connect(mServer.data(), &QTcpServer::newConnection, this, &HttpServer::onNewConnection);
24
25 if (mServer->listen(QHostAddress::LocalHost, pPort))
26 {
27 mPortFile.handlePort(mServer->serverPort());
28 qCDebug(network) << "Listening on port:" << mServer->serverPort();
29 }
30 else
31 {
32 qCDebug(network) << "Cannot start server:" << mServer->errorString();
33 }
34 }
35
36
~HttpServer()37 HttpServer::~HttpServer()
38 {
39 if (isListening())
40 {
41 qCDebug(network) << "Shutdown server";
42 mServer->close();
43 }
44 }
45
46
isListening() const47 bool HttpServer::isListening() const
48 {
49 return mServer->isListening();
50 }
51
52
getServerPort() const53 quint16 HttpServer::getServerPort() const
54 {
55 return mServer->serverPort();
56 }
57
58
onNewConnection()59 void HttpServer::onNewConnection()
60 {
61 while (mServer->hasPendingConnections())
62 {
63 auto socket = mServer->nextPendingConnection();
64 socket->startTransaction();
65 auto request = new HttpRequest(socket, this);
66 connect(request, &HttpRequest::fireMessageComplete, this, &HttpServer::onMessageComplete);
67 }
68 }
69
70
checkReceiver(const QMetaMethod & pSignal,HttpRequest * pRequest)71 bool HttpServer::checkReceiver(const QMetaMethod& pSignal, HttpRequest* pRequest)
72 {
73 if (isSignalConnected(pSignal))
74 {
75 return true;
76 }
77
78 qCDebug(network) << "No registration found:" << pSignal.name();
79 pRequest->send(HTTP_STATUS_SERVICE_UNAVAILABLE);
80 pRequest->deleteLater();
81 return false;
82 }
83
84
onMessageComplete(HttpRequest * pRequest)85 void HttpServer::onMessageComplete(HttpRequest* pRequest)
86 {
87 pRequest->setParent(nullptr);
88
89 if (pRequest->isUpgrade())
90 {
91 if (pRequest->getHeader(QByteArrayLiteral("upgrade")).toLower() == QByteArrayLiteral("websocket"))
92 {
93 qCDebug(network) << "Upgrade to websocket requested";
94
95 static const QMetaMethod signal = QMetaMethod::fromSignal(&HttpServer::fireNewWebSocketRequest);
96 if (!checkReceiver(signal, pRequest))
97 {
98 return;
99 }
100
101 pRequest->mSocket->rollbackTransaction();
102 Q_EMIT fireNewWebSocketRequest(QSharedPointer<HttpRequest>(pRequest, &QObject::deleteLater));
103 }
104 else
105 {
106 qCWarning(network) << "Unknown upgrade requested";
107 pRequest->send(HTTP_STATUS_NOT_FOUND);
108 pRequest->deleteLater();
109 }
110 }
111 else
112 {
113 static const QMetaMethod signal = QMetaMethod::fromSignal(&HttpServer::fireNewHttpRequest);
114 if (!checkReceiver(signal, pRequest))
115 {
116 return;
117 }
118
119 pRequest->mSocket->commitTransaction();
120 Q_EMIT fireNewHttpRequest(QSharedPointer<HttpRequest>(pRequest, &QObject::deleteLater));
121 }
122 }
123