SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
Public Slots | Public Member Functions | Private Slots | Private Member Functions | Private Attributes | List of all members
qtwebapp::HttpConnectionHandler Class Reference

#include <httpconnectionhandler.h>

Inherits QThread.

+ Collaboration diagram for qtwebapp::HttpConnectionHandler:

Public Slots

void handleConnection (tSocketDescriptor socketDescriptor)
 

Public Member Functions

 HttpConnectionHandler (QSettings *settings, HttpRequestHandler *requestHandler, QSslConfiguration *sslConfiguration=NULL)
 
 HttpConnectionHandler (const HttpListenerSettings *settings, HttpRequestHandler *requestHandler, QSslConfiguration *sslConfiguration=NULL)
 
virtual ~HttpConnectionHandler ()
 
bool isBusy ()
 
void setBusy ()
 
const HttpListenerSettingsgetListenerSettings () const
 

Private Slots

void readTimeout ()
 
void read ()
 
void disconnected ()
 

Private Member Functions

void run ()
 
void createSocket ()
 

Private Attributes

QSettings * settings
 
const HttpListenerSettingslistenerSettings
 
QTcpSocket * socket
 
QTimer readTimer
 
HttpRequestcurrentRequest
 
HttpRequestHandlerrequestHandler
 
bool busy
 
QSslConfiguration * sslConfiguration
 
bool useQtSettings
 

Detailed Description

Alias for QSslConfiguration if OpenSSL is not supported The connection handler accepts incoming connections and dispatches incoming requests to to a request mapper. Since HTTP clients can send multiple requests before waiting for the response, the incoming requests are queued and processed one after the other.

Example for the required configuration settings:

readTimeout=60000
maxRequestSize=16000
maxMultiPartSize=1000000

The readTimeout value defines the maximum time to wait for a complete HTTP request.

See also
HttpRequest for description of config settings maxRequestSize and maxMultiPartSize.

Definition at line 52 of file httpconnectionhandler.h.

Constructor & Destructor Documentation

◆ HttpConnectionHandler() [1/2]

HttpConnectionHandler::HttpConnectionHandler ( QSettings *  settings,
HttpRequestHandler requestHandler,
QSslConfiguration *  sslConfiguration = NULL 
)

Constructor.

Parameters
settingsConfiguration settings of the HTTP webserver as Qt settings
requestHandlerHandler that will process each incoming HTTP request
sslConfigurationSSL (HTTPS) will be used if not NULL

Definition at line 11 of file httpconnectionhandler.cpp.

References busy, createSocket(), currentRequest, disconnected(), listenerSettings, read(), readTimeout(), readTimer, requestHandler, settings, socket, and sslConfiguration.

12  : QThread(), useQtSettings(true)
13 {
14  Q_ASSERT(settings != 0);
15  Q_ASSERT(requestHandler != 0);
16  this->settings = settings;
17  this->listenerSettings = 0;
18  this->requestHandler = requestHandler;
20  currentRequest = 0;
21  busy=false;
22 
23  // Create TCP or SSL socket
24  createSocket();
25 
26  // execute signals in my own thread
27  moveToThread(this);
28  socket->moveToThread(this);
29  readTimer.moveToThread(this);
30 
31  // Connect signals
32  connect(socket, SIGNAL(readyRead()), SLOT(read()));
33  connect(socket, SIGNAL(disconnected()), SLOT(disconnected()));
34  connect(&readTimer, SIGNAL(timeout()), SLOT(readTimeout()));
35  readTimer.setSingleShot(true);
36 
37  qDebug("HttpConnectionHandler (%p): constructed", this);
38  this->start();
39 }
const HttpListenerSettings * listenerSettings
+ Here is the call graph for this function:

◆ HttpConnectionHandler() [2/2]

HttpConnectionHandler::HttpConnectionHandler ( const HttpListenerSettings settings,
HttpRequestHandler requestHandler,
QSslConfiguration *  sslConfiguration = NULL 
)

Constructor.

Parameters
settingsConfiguration settings of the HTTP webserver as a structure
requestHandlerHandler that will process each incoming HTTP request
sslConfigurationSSL (HTTPS) will be used if not NULL

Definition at line 41 of file httpconnectionhandler.cpp.

References busy, createSocket(), currentRequest, disconnected(), listenerSettings, read(), readTimeout(), readTimer, requestHandler, settings, socket, and sslConfiguration.

42  : QThread(), useQtSettings(false)
43 {
44  Q_ASSERT(settings != 0);
45  Q_ASSERT(requestHandler != 0);
46  this->settings = 0;
47  this->listenerSettings = settings;
48  this->requestHandler = requestHandler;
50  currentRequest = 0;
51  busy = false;
52 
53  // Create TCP or SSL socket
54  createSocket();
55 
56  // execute signals in my own thread
57  moveToThread(this);
58  socket->moveToThread(this);
59  readTimer.moveToThread(this);
60 
61  // Connect signals
62  connect(socket, SIGNAL(readyRead()), SLOT(read()));
63  connect(socket, SIGNAL(disconnected()), SLOT(disconnected()));
64  connect(&readTimer, SIGNAL(timeout()), SLOT(readTimeout()));
65  readTimer.setSingleShot(true);
66 
67  qDebug("HttpConnectionHandler (%p): constructed", this);
68  this->start();
69 }
const HttpListenerSettings * listenerSettings
+ Here is the call graph for this function:

◆ ~HttpConnectionHandler()

HttpConnectionHandler::~HttpConnectionHandler ( )
virtual

Destructor

Definition at line 72 of file httpconnectionhandler.cpp.

73 {
74  quit();
75  wait();
76  qDebug("HttpConnectionHandler (%p): destroyed", this);
77 }

Member Function Documentation

◆ createSocket()

void HttpConnectionHandler::createSocket ( )
private

Create SSL or TCP socket

Definition at line 80 of file httpconnectionhandler.cpp.

References socket, and sslConfiguration.

Referenced by HttpConnectionHandler().

81 {
82  // If SSL is supported and configured, then create an instance of QSslSocket
83  #ifndef QT_NO_OPENSSL
84  if (sslConfiguration)
85  {
86  QSslSocket* sslSocket=new QSslSocket();
87  sslSocket->setSslConfiguration(*sslConfiguration);
88  socket=sslSocket;
89  qDebug("HttpConnectionHandler (%p): SSL is enabled", this);
90  return;
91  }
92  #endif
93  // else create an instance of QTcpSocket
94  socket=new QTcpSocket();
95 }
+ Here is the caller graph for this function:

◆ disconnected

void HttpConnectionHandler::disconnected ( )
privateslot

Received from the socket when a connection has been closed

Definition at line 182 of file httpconnectionhandler.cpp.

References busy, readTimer, and socket.

Referenced by HttpConnectionHandler().

183 {
184  qDebug("HttpConnectionHandler (%p): disconnected", this);
185  socket->close();
186  readTimer.stop();
187  busy = false;
188 }
+ Here is the caller graph for this function:

◆ getListenerSettings()

const HttpListenerSettings* qtwebapp::HttpConnectionHandler::getListenerSettings ( ) const
inline

Get a listener settings constant reference. Can be changed on the HttpListener only.

Returns
The current listener settings

Definition at line 87 of file httpconnectionhandler.h.

87 { return listenerSettings; }
const HttpListenerSettings * listenerSettings

◆ handleConnection

void HttpConnectionHandler::handleConnection ( tSocketDescriptor  socketDescriptor)
slot

Received from from the listener, when the handler shall start processing a new connection.

Parameters
socketDescriptorreferences the accepted connection.

Definition at line 120 of file httpconnectionhandler.cpp.

References busy, currentRequest, listenerSettings, qtwebapp::HttpListenerSettings::readTimeout, readTimeout(), readTimer, settings, socket, sslConfiguration, and useQtSettings.

121 {
122 #ifdef SUPERVERBOSE
123  qDebug("HttpConnectionHandler (%p): handle new connection", this);
124 #endif
125  busy = true;
126  Q_ASSERT(socket->isOpen()==false); // if not, then the handler is already busy
127 
128  //UGLY workaround - we need to clear writebuffer before reusing this socket
129  //https://bugreports.qt-project.org/browse/QTBUG-28914
130  socket->connectToHost("",0);
131  socket->abort();
132 
133  if (!socket->setSocketDescriptor(socketDescriptor))
134  {
135  qCritical("HttpConnectionHandler (%p): cannot initialize socket: %s", this,qPrintable(socket->errorString()));
136  return;
137  }
138 
139  #ifndef QT_NO_OPENSSL
140  // Switch on encryption, if SSL is configured
141  if (sslConfiguration)
142  {
143  qDebug("HttpConnectionHandler (%p): Starting encryption", this);
144  ((QSslSocket*)socket)->startServerEncryption();
145  }
146  #endif
147 
148  // Start timer for read timeout
149  int readTimeout = useQtSettings ? settings->value("readTimeout",10000).toInt() : listenerSettings->readTimeout;
150  readTimer.start(readTimeout);
151  // delete previous request
152  delete currentRequest;
153  currentRequest=0;
154 }
const HttpListenerSettings * listenerSettings
+ Here is the call graph for this function:

◆ isBusy()

bool HttpConnectionHandler::isBusy ( )

Returns true, if this handler is in use.

Definition at line 157 of file httpconnectionhandler.cpp.

References busy.

Referenced by qtwebapp::HttpConnectionHandlerPool::cleanup(), and qtwebapp::HttpConnectionHandlerPool::getConnectionHandler().

158 {
159  return busy;
160 }
+ Here is the caller graph for this function:

◆ read

void HttpConnectionHandler::read ( )
privateslot

Received from the socket when incoming data can be read

Definition at line 190 of file httpconnectionhandler.cpp.

References qtwebapp::HttpRequest::abort, qtwebapp::HttpRequest::complete, currentRequest, qtwebapp::HttpRequest::getHeader(), qtwebapp::HttpRequest::getMethod(), qtwebapp::HttpRequest::getPath(), qtwebapp::HttpRequest::getPeerAddress(), qtwebapp::HttpRequest::getStatus(), qtwebapp::HttpRequest::getVersion(), listenerSettings, qtwebapp::HttpRequest::readFromSocket(), qtwebapp::HttpListenerSettings::readTimeout, readTimeout(), readTimer, requestHandler, qtwebapp::HttpRequestHandler::service(), settings, socket, useQtSettings, and qtwebapp::HttpRequest::waitForBody.

Referenced by HttpConnectionHandler().

191 {
192  // The loop adds support for HTTP pipelinig
193  while (socket->bytesAvailable())
194  {
195  #ifdef SUPERVERBOSE
196  qDebug("HttpConnectionHandler (%p): read input",this);
197  #endif
198 
199  // Create new HttpRequest object if necessary
200  if (!currentRequest)
201  {
202  if (useQtSettings) {
204  } else {
206  }
207  }
208 
209  // Collect data for the request object
211  {
214  {
215  // Restart timer for read timeout, otherwise it would
216  // expire during large file uploads.
217  int readTimeout = useQtSettings ? settings->value("readTimeout",10000).toInt() : listenerSettings->readTimeout;
218  readTimer.start(readTimeout);
219  }
220  }
221 
222  // If the request is aborted, return error message and close the connection
224  {
225  socket->write("HTTP/1.1 413 entity too large\r\nConnection: close\r\n\r\n413 Entity too large\r\n");
226  while(socket->bytesToWrite()) socket->waitForBytesWritten();
227  socket->disconnectFromHost();
228  delete currentRequest;
229  currentRequest=0;
230  return;
231  }
232 
233  // If the request is complete, let the request mapper dispatch it
235  {
236  readTimer.stop();
237  qDebug("HttpConnectionHandler (%p): received request from %s (%s) %s",
238  this,
239  qPrintable(currentRequest->getPeerAddress().toString()),
240  currentRequest->getMethod().toStdString().c_str(),
241  currentRequest->getPath().toStdString().c_str());
242 
243  // Copy the Connection:close header to the response
244  HttpResponse response(socket);
245  bool closeConnection=QString::compare(currentRequest->getHeader("Connection"),"close",Qt::CaseInsensitive)==0;
246  if (closeConnection)
247  {
248  response.setHeader("Connection","close");
249  }
250 
251  // In case of HTTP 1.0 protocol add the Connection:close header.
252  // This ensures that the HttpResponse does not activate chunked mode, which is not spported by HTTP 1.0.
253  else
254  {
255  bool http1_0=QString::compare(currentRequest->getVersion(),"HTTP/1.0",Qt::CaseInsensitive)==0;
256  if (http1_0)
257  {
258  closeConnection=true;
259  response.setHeader("Connection","close");
260  }
261  }
262 
263  // Call the request mapper
264  try
265  {
267  }
268  catch (...)
269  {
270  qCritical("HttpConnectionHandler (%p): An uncatched exception occurred in the request handler",this);
271  }
272 
273  // Finalize sending the response if not already done
274  if (!response.hasSentLastPart())
275  {
276  response.write(QByteArray(),true);
277  }
278 
279 #ifdef SUPERVERBOSE
280  qDebug("HttpConnectionHandler (%p): finished request",this);
281 #endif
282 
283  // Find out whether the connection must be closed
284  if (!closeConnection)
285  {
286  // Maybe the request handler or mapper added a Connection:close header in the meantime
287  bool closeResponse=QString::compare(response.getHeaders().value("Connection"),"close",Qt::CaseInsensitive)==0;
288  if (closeResponse==true)
289  {
290  closeConnection=true;
291  }
292  else
293  {
294  // If we have no Content-Length header and did not use chunked mode, then we have to close the
295  // connection to tell the HTTP client that the end of the response has been reached.
296  bool hasContentLength=response.getHeaders().contains("Content-Length");
297  if (!hasContentLength)
298  {
299  bool hasChunkedMode=QString::compare(response.getHeaders().value("Transfer-Encoding"),"chunked",Qt::CaseInsensitive)==0;
300  if (!hasChunkedMode)
301  {
302  closeConnection=true;
303  }
304  }
305  }
306  }
307 
308  // Close the connection or prepare for the next request on the same connection.
309  if (closeConnection)
310  {
311  while(socket->bytesToWrite()) socket->waitForBytesWritten();
312  socket->disconnectFromHost();
313  }
314  else
315  {
316  // Start timer for next request
317  int readTimeout = useQtSettings ? settings->value("readTimeout",10000).toInt() : listenerSettings->readTimeout;
318  readTimer.start(readTimeout);
319  }
320  delete currentRequest;
321  currentRequest=0;
322  }
323  }
324 }
RequestStatus getStatus() const
QByteArray getPath() const
QByteArray getVersion() const
QByteArray getHeader(const QByteArray &name) const
const HttpListenerSettings * listenerSettings
void readFromSocket(QTcpSocket *socket)
QHostAddress getPeerAddress() const
QByteArray getMethod() const
virtual void service(HttpRequest &request, HttpResponse &response)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ readTimeout

void HttpConnectionHandler::readTimeout ( )
privateslot

Received from the socket when a read-timeout occurred

Definition at line 168 of file httpconnectionhandler.cpp.

References currentRequest, and socket.

Referenced by handleConnection(), HttpConnectionHandler(), and read().

169 {
170  qDebug("HttpConnectionHandler (%p): read timeout occurred",this);
171 
172  //Commented out because QWebView cannot handle this.
173  //socket->write("HTTP/1.1 408 request timeout\r\nConnection: close\r\n\r\n408 request timeout\r\n");
174 
175  while(socket->bytesToWrite()) socket->waitForBytesWritten();
176  socket->disconnectFromHost();
177  delete currentRequest;
178  currentRequest=0;
179 }
+ Here is the caller graph for this function:

◆ run()

void HttpConnectionHandler::run ( )
private

Executes the threads own event loop

Definition at line 98 of file httpconnectionhandler.cpp.

References readTimer, and socket.

99 {
100 #ifdef SUPERVERBOSE
101  qDebug("HttpConnectionHandler (%p): thread started", this);
102 #endif
103  try
104  {
105  exec();
106  }
107  catch (...)
108  {
109  qCritical("HttpConnectionHandler (%p): an uncatched exception occurred in the thread",this);
110  }
111  socket->close();
112  delete socket;
113  readTimer.stop();
114 #ifdef SUPERVERBOSE
115  qDebug("HttpConnectionHandler (%p): thread stopped", this);
116 #endif
117 }

◆ setBusy()

void HttpConnectionHandler::setBusy ( )

Mark this handler as busy

Definition at line 162 of file httpconnectionhandler.cpp.

References busy.

Referenced by qtwebapp::HttpConnectionHandlerPool::getConnectionHandler().

163 {
164  this->busy = true;
165 }
+ Here is the caller graph for this function:

Member Data Documentation

◆ busy

bool qtwebapp::HttpConnectionHandler::busy
private

This shows the busy-state from a very early time

Definition at line 111 of file httpconnectionhandler.h.

Referenced by disconnected(), handleConnection(), HttpConnectionHandler(), isBusy(), and setBusy().

◆ currentRequest

HttpRequest* qtwebapp::HttpConnectionHandler::currentRequest
private

Storage for the current incoming HTTP request

Definition at line 105 of file httpconnectionhandler.h.

Referenced by handleConnection(), HttpConnectionHandler(), read(), and readTimeout().

◆ listenerSettings

const HttpListenerSettings* qtwebapp::HttpConnectionHandler::listenerSettings
private

Configuration settings

Definition at line 96 of file httpconnectionhandler.h.

Referenced by handleConnection(), HttpConnectionHandler(), and read().

◆ readTimer

QTimer qtwebapp::HttpConnectionHandler::readTimer
private

Time for read timeout detection

Definition at line 102 of file httpconnectionhandler.h.

Referenced by disconnected(), handleConnection(), HttpConnectionHandler(), read(), and run().

◆ requestHandler

HttpRequestHandler* qtwebapp::HttpConnectionHandler::requestHandler
private

Dispatches received requests to services

Definition at line 108 of file httpconnectionhandler.h.

Referenced by HttpConnectionHandler(), and read().

◆ settings

QSettings* qtwebapp::HttpConnectionHandler::settings
private

Configuration settings

Definition at line 93 of file httpconnectionhandler.h.

Referenced by handleConnection(), HttpConnectionHandler(), and read().

◆ socket

QTcpSocket* qtwebapp::HttpConnectionHandler::socket
private

TCP socket of the current connection

Definition at line 99 of file httpconnectionhandler.h.

Referenced by createSocket(), disconnected(), handleConnection(), HttpConnectionHandler(), read(), readTimeout(), and run().

◆ sslConfiguration

QSslConfiguration* qtwebapp::HttpConnectionHandler::sslConfiguration
private

Configuration for SSL

Definition at line 114 of file httpconnectionhandler.h.

Referenced by createSocket(), handleConnection(), and HttpConnectionHandler().

◆ useQtSettings

bool qtwebapp::HttpConnectionHandler::useQtSettings
private

Settings flag

Definition at line 123 of file httpconnectionhandler.h.

Referenced by handleConnection(), and read().


The documentation for this class was generated from the following files: