| 
									
										
										
										
											2017-08-23 18:47:07 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |   @file | 
					
						
							|  |  |  |   @author Stefan Frings | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "httplistener.h"
 | 
					
						
							|  |  |  | #include "httpconnectionhandler.h"
 | 
					
						
							|  |  |  | #include "httpconnectionhandlerpool.h"
 | 
					
						
							| 
									
										
										
										
											2017-11-13 01:26:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-23 18:47:07 +02:00
										 |  |  | #include <QCoreApplication>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-11 09:32:15 +01:00
										 |  |  | using namespace qtwebapp; | 
					
						
							| 
									
										
										
										
											2017-08-23 18:47:07 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | HttpListener::HttpListener(QSettings* settings, HttpRequestHandler* requestHandler, QObject *parent) | 
					
						
							| 
									
										
										
										
											2017-11-13 01:26:48 +01:00
										 |  |  |     : QTcpServer(parent), useQtSettings(true) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Q_ASSERT(settings != 0); | 
					
						
							|  |  |  |     Q_ASSERT(requestHandler != 0); | 
					
						
							|  |  |  |     pool = 0; | 
					
						
							|  |  |  |     this->settings = settings; | 
					
						
							|  |  |  |     this->requestHandler = requestHandler; | 
					
						
							|  |  |  |     // Reqister type of socketDescriptor for signal/slot handling
 | 
					
						
							|  |  |  |     qRegisterMetaType<tSocketDescriptor>("tSocketDescriptor"); | 
					
						
							|  |  |  |     // Start listening
 | 
					
						
							|  |  |  |     listen(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:46:02 +01:00
										 |  |  | HttpListener::HttpListener(const HttpListenerSettings& settings, HttpRequestHandler* requestHandler, QObject *parent) | 
					
						
							| 
									
										
										
										
											2017-11-13 01:26:48 +01:00
										 |  |  |     : QTcpServer(parent), useQtSettings(false) | 
					
						
							| 
									
										
										
										
											2017-08-23 18:47:07 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-11-13 01:26:48 +01:00
										 |  |  |     Q_ASSERT(requestHandler != 0); | 
					
						
							|  |  |  |     pool = 0; | 
					
						
							|  |  |  |     this->settings = 0; | 
					
						
							| 
									
										
										
										
											2017-11-13 13:46:02 +01:00
										 |  |  |     listenerSettings = settings; | 
					
						
							| 
									
										
										
										
											2017-11-13 01:26:48 +01:00
										 |  |  |     this->requestHandler = requestHandler; | 
					
						
							| 
									
										
										
										
											2017-08-23 18:47:07 +02:00
										 |  |  |     // Reqister type of socketDescriptor for signal/slot handling
 | 
					
						
							|  |  |  |     qRegisterMetaType<tSocketDescriptor>("tSocketDescriptor"); | 
					
						
							|  |  |  |     // Start listening
 | 
					
						
							|  |  |  |     listen(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | HttpListener::~HttpListener() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     close(); | 
					
						
							|  |  |  |     qDebug("HttpListener: destroyed"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void HttpListener::listen() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!pool) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-11-17 08:52:15 +01:00
										 |  |  |         if (useQtSettings) { | 
					
						
							|  |  |  |             pool = new HttpConnectionHandlerPool(settings, requestHandler); | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2017-11-18 10:15:29 +01:00
										 |  |  |             pool = new HttpConnectionHandlerPool(&listenerSettings, requestHandler); | 
					
						
							| 
									
										
										
										
											2017-11-17 08:52:15 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-08-23 18:47:07 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-11-13 13:46:02 +01:00
										 |  |  |     QString host = useQtSettings ? settings->value("host").toString() : listenerSettings.host; | 
					
						
							|  |  |  |     int port = useQtSettings ? settings->value("port").toInt() : listenerSettings.port; | 
					
						
							| 
									
										
										
										
											2017-08-23 18:47:07 +02:00
										 |  |  |     QTcpServer::listen(host.isEmpty() ? QHostAddress::Any : QHostAddress(host), port); | 
					
						
							|  |  |  |     if (!isListening()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qCritical("HttpListener: Cannot bind on port %i: %s",port,qPrintable(errorString())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         qDebug("HttpListener: Listening on port %i",port); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void HttpListener::close() { | 
					
						
							|  |  |  |     QTcpServer::close(); | 
					
						
							|  |  |  |     qDebug("HttpListener: closed"); | 
					
						
							|  |  |  |     if (pool) { | 
					
						
							|  |  |  |         delete pool; | 
					
						
							|  |  |  |         pool=NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void HttpListener::incomingConnection(tSocketDescriptor socketDescriptor) { | 
					
						
							|  |  |  | #ifdef SUPERVERBOSE
 | 
					
						
							|  |  |  |     qDebug("HttpListener: New connection"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     HttpConnectionHandler* freeHandler=NULL; | 
					
						
							|  |  |  |     if (pool) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         freeHandler=pool->getConnectionHandler(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Let the handler process the new connection.
 | 
					
						
							|  |  |  |     if (freeHandler) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // The descriptor is passed via event queue because the handler lives in another thread
 | 
					
						
							|  |  |  |         QMetaObject::invokeMethod(freeHandler, "handleConnection", Qt::QueuedConnection, Q_ARG(tSocketDescriptor, socketDescriptor)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // Reject the connection
 | 
					
						
							|  |  |  |         qDebug("HttpListener: Too many incoming connections"); | 
					
						
							|  |  |  |         QTcpSocket* socket=new QTcpSocket(this); | 
					
						
							|  |  |  |         socket->setSocketDescriptor(socketDescriptor); | 
					
						
							|  |  |  |         connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater())); | 
					
						
							|  |  |  |         socket->write("HTTP/1.1 503 too many connections\r\nConnection: close\r\n\r\nToo many connections\r\n"); | 
					
						
							|  |  |  |         socket->disconnectFromHost(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |