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