Hobrasoft httpd server
Embedded HTTP server for Qt and C++
httpconnection.cpp
Go to the documentation of this file.
1 
8 #include "httpconnection.h"
9 #include "httprequest.h"
10 #include "httprequesthandler.h"
11 #include "httpresponse.h"
12 #include "httpserver.h"
13 #include "httpsettings.h"
14 #include <QTcpSocket>
15 
16 using namespace HobrasoftHttpd;
17 
18 HttpConnection::~HttpConnection() {
19  close();
20  for (int i=0; i<m_requests.size(); i++) {
21  delete m_requests[i];
22  }
23 }
24 
25 
26 HttpConnection::HttpConnection(HttpServer *parent, QTcpSocket *socket) : QObject(parent) {
27  m_peerAddress = socket->peerAddress();
28  m_socket = socket;
29  m_request = NULL;
30  m_parent = parent;
31  m_handler = parent->requestHandler(this);
32  m_connected = true;
33  m_inService = true;
34 
35  int timeout = settings()->timeout() * 1000;
36 
37  m_timeout = new QTimer(this);
38  m_timeout->setInterval(timeout);
39  m_timeout->setSingleShot(true);
40  startTimeout();
41  connect (m_timeout, SIGNAL(timeout()),
42  this, SLOT(slotTimeout()));
43 
44  connect(m_socket, SIGNAL(readyRead()),
45  this, SLOT(slotRead()));
46 
47  connect(m_socket, SIGNAL(disconnected()),
48  this, SLOT(slotDisconnected()));
49 }
50 
52  return m_parent->settings();
53 }
54 
55 
56 void HttpConnection::startTimeout() {
57  if (m_timeout->interval() == 0) {
58  m_timeout->stop();
59  return;
60  }
61  m_timeout->start();
62 }
63 
64 
65 void HttpConnection::setPeerCertificate(const QSslCertificate& crt) {
66  m_peerCertificate = crt;
67 }
68 
69 
70 QString HttpConnection::commonName() const {
71  #if QT_VERSION > 0x050000
72  QDateTime now = QDateTime::currentDateTime();
73  if (now > m_peerCertificate.expiryDate()) { return QString(); }
74  if (now < m_peerCertificate.effectiveDate()) { return QString(); }
75  if (m_peerCertificate.isBlacklisted()) { return QString(); }
76  QStringList cn = m_peerCertificate.subjectInfo(QSslCertificate::CommonName);
77  if (cn.isEmpty()) { return QString(); }
78  return cn.first();
79  #else
80  if (!m_peerCertificate.isValid()) { return QString(); }
81  return m_peerCertificate.subjectInfo(QSslCertificate::CommonName);
82  #endif
83 }
84 
85 
87  if (!isConnected()) {
88  return;
89  }
90  if (m_socket) {
91  m_socket->disconnectFromHost();
92  }
93  deleteRequest();
94 
95 }
96 
97 
98 void HttpConnection::slotTimeout() {
99  if (!isConnected()) { return; }
100  m_socket->write("HTTP/1.1 408 request timeout\r\n");
101  m_socket->write("Connection: close\r\n");
102  m_socket->write("\r\n");
103  m_socket->write("408 request timeout\r\n");
104  m_socket->disconnectFromHost();
105  deleteRequest();
106 }
107 
108 
109 void HttpConnection::slotDisconnected() {
110  m_connected = false;
111  m_socket->close();
112  deleteRequest();
113  m_timeout->stop();
114  if (m_inService) {
115  QTimer::singleShot(3000, this, SLOT(deleteLater()));
116  } else {
117  deleteLater();
118  }
119 }
120 
121 
123  startTimeout();
124  return new HttpResponse(this);
125 }
126 
127 
128 void HttpConnection::slotRead() {
129  if (!isConnected()) { return; }
130  startTimeout();
131  if (m_request == NULL || (m_request != NULL && m_request->status() == HttpRequest::StatusComplete)) {
132  m_request = new HttpRequest(this);
133  m_requests << m_request;
134  }
135 
136  while (m_socket->bytesAvailable()
137  && m_request->status() != HttpRequest::StatusComplete
138  && m_request->status() != HttpRequest::StatusAbort) {
139  m_request->readFromSocket(m_socket);
140  if (m_request->status() == HttpRequest::StatusWaitForBody) {
141  startTimeout();
142  }
143  }
144 
145  if (m_request->status() == HttpRequest::StatusAbort) {
146  m_socket->write("HTTP/1.1 413 entity too large\r\n");
147  m_socket->write("Connection: close\r\n\r\n");
148  m_socket->write("\r\n");
149  m_socket->write("413 entity too large\r\n");
150  m_socket->disconnectFromHost();
151  m_timeout->stop();
152  deleteRequest();
153  return;
154  }
155 
156  if (m_request->status() == HttpRequest::StatusComplete) {
157  bool disconnect = (m_request->header("Connection").toLower() == "close");
158  m_timeout->stop();
159  HttpResponse *response = new HttpResponse(this);
160  m_inService = true;
161  m_handler->service(m_request, response);
162  m_inService = false;
163 
164  if (!isConnected()) {
165  deleteLater();
166  return;
167  }
168 
169  if (disconnect) {
170  if (isConnected()) {
171  m_socket->disconnectFromHost();
172  deleteRequest();
173  }
174  } else {
175  startTimeout();
176  }
177 
178  }
179 
180 }
181 
182 
183 void HttpConnection::deleteRequest() {
184  m_request = NULL;
185 }
186 
187 
188 QVariant HttpConnection::webStatus() const {
189  QVariantList list;
190  for (int i=0; i<m_requests.size(); i++) {
191  const HttpRequest *request = m_requests[i];
192  QVariantMap data;
193  data["object"] = QString("0x%1").arg((quint64)this, 8, 16, QChar('0'));
194  data["path"] = (request!=NULL) ? request->path() : QVariant();
195  data["time"] = (request!=NULL) ? request->datetime() : QVariant();
196  data["method"] = (request!=NULL) ? request->method() : QVariant();
197  data["status"] = (request!=NULL) ? request->statusString() : QVariant();
198  data["connection"] = (isConnected()) ? "connected" : "disconnected";
199  list << data;
200  }
201  return list;
202 }
203 
204 
const HttpSettings * settings() const
Returns pointer to settings used in the class.
QString statusString() const
Returns current status of the request as a string.
QString path() const
Returns path of the request (/files/index.html)
Definition: httprequest.h:78
QTcpSocket * socket() const
Returns the socket.
General single-threaded, event-driven HTTP server.
Definition: httpserver.h:88
int timeout() const
Returns timeout for opened connection from clients.
Definition: httpsettings.h:68
Response to HTTP request - headers, cookies and body.
Definition: httpresponse.h:30
Configuration of the http server instance.
Definition: httpsettings.h:39
HttpConnection(HttpServer *parent, QTcpSocket *socket)
Constructor is called automatically when new request arrived.
virtual HttpRequestHandler * requestHandler(HttpConnection *)
Creates new request handler and returs pointer to it.
Definition: httpserver.cpp:71
bool isConnected() const
Returns true if the connection is in connected state.
HttpResponse * response()
Returns new instance of class HttpResponse.
void close()
Closes the connection.
const QDateTime & datetime() const
Returns date and time of the request.
Definition: httprequest.h:190
Processes HTTP request, parses headers, body and files sent by HTTP protocol.
Definition: httprequest.h:23
void setPeerCertificate(const QSslCertificate &)
Sets peer&#39;s certificate.
QString method() const
Returns used HTTP method of the request (GET, PUT, POST or DELETE)
Definition: httprequest.h:73
Namespace of HTTP server.
QString commonName() const
Returns CommonName field from certificate.