MythTV  master
httpserver.cpp
Go to the documentation of this file.
1 // Program Name: httpserver.cpp
3 // Created : Oct. 1, 2005
4 //
5 // Purpose : HTTP 1.1 Mini Server Implmenetation
6 // Used for UPnp/AV implementation & status information
7 //
8 // Copyright (c) 2005 David Blain <dblain@mythtv.org>
9 // 2014 Stuart Morgan <smorgan@mythtv.org>
10 //
11 // Licensed under the GPL v2 or later, see COPYING for details
12 //
14 
15 // Own headers
16 #include "httpserver.h"
17 
18 // ANSI C headers
19 #include <cmath>
20 
21 // POSIX headers
22 #ifndef _WIN32
23 #include <sys/utsname.h>
24 #endif
25 
26 // Qt headers
27 #include <QScriptEngine>
28 #include <QSslConfiguration>
29 #include <QSslSocket>
30 #include <QSslCipher>
31 #include <QSslCertificate>
32 #include <QUuid>
33 
34 // MythTV headers
35 #include "upnputil.h"
36 #include "upnp.h" // only needed for Config... remove once config is moved.
37 #include "compat.h"
38 #include "mythdirs.h"
39 #include "mythlogging.h"
40 #include "htmlserver.h"
41 #include "mythversion.h"
42 #include "mythcorecontext.h"
43 
45 
50 {
52  pRequest->m_nResponseStatus = 200; // OK
53  // RFC 2616 Sect. 9.2 - If no response body is included, the response
54  // MUST include a Content-Length field with a
55  // field-value of "0".
56  pRequest->SetResponseHeader("Content-Length", "0");
57 
58  QStringList allowedMethods;
60  allowedMethods.append("GET");
62  allowedMethods.append("HEAD");
64  allowedMethods.append("POST");
65 // if (m_nSupportedMethods & RequestTypePut)
66 // allowedMethods.append("PUT");
67 // if (m_nSupportedMethods & RequestTypeDelete)
68 // allowedMethods.append("DELETE");
69 // if (m_nSupportedMethods & RequestTypeConnect)
70 // allowedMethods.append("CONNECT");
72  allowedMethods.append("OPTIONS");
73 // if (m_nSupportedMethods & RequestTypeTrace)
74 // allowedMethods.append("TRACE");
76  allowedMethods.append("M-SEARCH");
78  allowedMethods.append("SUBSCRIBE");
80  allowedMethods.append("UNSUBSCRIBE");
82  allowedMethods.append("NOTIFY");
83 
84  if (!allowedMethods.isEmpty())
85  {
86  pRequest->SetResponseHeader("Allow", allowedMethods.join(", "));
87  return true;
88  }
89 
90  LOG(VB_GENERAL, LOG_ERR, QString("HttpServerExtension::ProcessOptions(): "
91  "Error: No methods supported for "
92  "extension - %1").arg(m_sName));
93 
94  return false;
95 }
96 
97 
100 //
101 // HttpServer Class Implementation
102 //
105 
107 QString HttpServer::s_platform;
108 
110 //
112 
114  m_sSharePath(GetShareDir()),
115  m_threadPool("HttpServerPool"),
116  m_privateToken(QUuid::createUuid().toString()) // Cryptographically random and sufficiently long enough to act as a secure token
117 {
118  // Number of connections processed concurrently
119  int maxHttpWorkers = std::max(QThread::idealThreadCount() * 2, 2); // idealThreadCount can return -1
120  // Don't allow more connections than we can process, it causes browsers
121  // to open lots of new connections instead of reusing existing ones
122  setMaxPendingConnections(maxHttpWorkers);
123  m_threadPool.setMaxThreadCount(maxHttpWorkers);
124 
125  LOG(VB_HTTP, LOG_NOTICE, QString("HttpServer(): Max Thread Count %1")
127 
128  // ----------------------------------------------------------------------
129  // Build Platform String
130  // ----------------------------------------------------------------------
131  {
132  QMutexLocker locker(&s_platformLock);
133 #ifdef _WIN32
134  s_platform = QString("Windows/%1.%2")
135  .arg(LOBYTE(LOWORD(GetVersion())))
136  .arg(HIBYTE(LOWORD(GetVersion())));
137 #else
138  struct utsname uname_info {};
139  uname( &uname_info );
140  s_platform = QString("%1/%2")
141  .arg(uname_info.sysname).arg(uname_info.release);
142 #endif
143  }
144 
145  LOG(VB_HTTP, LOG_INFO, QString("HttpServer() - SharePath = %1")
146  .arg(m_sSharePath));
147 
148  // -=>TODO: Load Config XML
149  // -=>TODO: Load & initialize - HttpServerExtensions
150 
151  // ----------------------------------------------------------------------
152  // Enable Rtti Service for all instances of HttpServer
153  // and register with QtScript Engine.
154  // Rtti service is an alternative to using the xsd uri
155  // it returns xml/json/etc... definitions of types/enums
156  // ----------------------------------------------------------------------
157 
159 
160  LoadSSLConfig();
161 }
162 
164 //
166 
168 {
169  m_rwlock.lockForWrite();
170  m_running = false;
171  m_rwlock.unlock();
172 
173  m_threadPool.Stop();
174 
175  while (!m_extensions.empty())
176  {
177  delete m_extensions.takeFirst();
178  }
179 }
180 
182 {
183 #ifndef QT_NO_OPENSSL
184  m_sslConfig = QSslConfiguration::defaultConfiguration();
185 
186  m_sslConfig.setProtocol(QSsl::SecureProtocols); // Includes SSLv3 which is insecure, but can't be helped
187  m_sslConfig.setSslOption(QSsl::SslOptionDisableLegacyRenegotiation, true); // Potential DoS multiplier
188  m_sslConfig.setSslOption(QSsl::SslOptionDisableCompression, true); // CRIME attack
189 
190  QList<QSslCipher> availableCiphers = QSslConfiguration::supportedCiphers();
191  QList<QSslCipher> secureCiphers;
192  QList<QSslCipher>::iterator it;
193  for (it = availableCiphers.begin(); it != availableCiphers.end(); ++it)
194  {
195  // Remove weak ciphers from the cipher list
196  if ((*it).usedBits() < 128)
197  continue;
198 
199  if ((*it).name().startsWith("RC4") || // Weak cipher
200  (*it).name().startsWith("EXP") || // Weak authentication
201  (*it).name().startsWith("ADH") || // No authentication
202  (*it).name().contains("NULL")) // No encryption
203  continue;
204 
205  secureCiphers.append(*it);
206  }
207  m_sslConfig.setCiphers(secureCiphers);
208 #endif
209 
210  QString hostKeyPath = gCoreContext->GetSetting("hostSSLKey", "");
211 
212  if (hostKeyPath.isEmpty()) // No key, assume no SSL
213  return;
214 
215  QFile hostKeyFile(hostKeyPath);
216  if (!hostKeyFile.exists() || !hostKeyFile.open(QIODevice::ReadOnly))
217  {
218  LOG(VB_GENERAL, LOG_ERR, QString("HttpServer: SSL Host key file (%1) does not exist or is not readable").arg(hostKeyPath));
219  return;
220  }
221 
222 #ifndef QT_NO_OPENSSL
223  QByteArray rawHostKey = hostKeyFile.readAll();
224  QSslKey hostKey = QSslKey(rawHostKey, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
225  if (!hostKey.isNull())
226  m_sslConfig.setPrivateKey(hostKey);
227  else
228  {
229  LOG(VB_GENERAL, LOG_ERR, QString("HttpServer: Unable to load host key from file (%1)").arg(hostKeyPath));
230  return;
231  }
232 
233  QString hostCertPath = gCoreContext->GetSetting("hostSSLCertificate", "");
234  QSslCertificate hostCert;
235  QList<QSslCertificate> certList = QSslCertificate::fromPath(hostCertPath);
236  if (!certList.isEmpty())
237  hostCert = certList.first();
238 
239  if (!hostCert.isNull())
240  {
241  if (hostCert.effectiveDate() > QDateTime::currentDateTime())
242  {
243  LOG(VB_GENERAL, LOG_ERR, QString("HttpServer: Host certificate start date in future (%1)").arg(hostCertPath));
244  return;
245  }
246 
247  if (hostCert.expiryDate() < QDateTime::currentDateTime())
248  {
249  LOG(VB_GENERAL, LOG_ERR, QString("HttpServer: Host certificate has expired (%1)").arg(hostCertPath));
250  return;
251  }
252 
253  m_sslConfig.setLocalCertificate(hostCert);
254  }
255  else
256  {
257  LOG(VB_GENERAL, LOG_ERR, QString("HttpServer: Unable to load host cert from file (%1)").arg(hostCertPath));
258  return;
259  }
260 
261  QString caCertPath = gCoreContext->GetSetting("caSSLCertificate", "");
262  QList< QSslCertificate > CACertList = QSslCertificate::fromPath(caCertPath);
263 
264  if (!CACertList.isEmpty())
265  m_sslConfig.setCaCertificates(CACertList);
266  else if (!caCertPath.isEmpty()) // Only warn if a path was actually configured, this isn't an error otherwise
267  LOG(VB_GENERAL, LOG_ERR, QString("HttpServer: Unable to load CA cert file (%1)").arg(caCertPath));
268 #endif
269 }
270 
272 //
274 
276 {
277  QMutexLocker locker(&s_platformLock);
278  return s_platform;
279 }
280 
282 //
284 
286 {
287  QString mythVersion = GetMythSourceVersion();
288  if (mythVersion.startsWith("v"))
289  mythVersion = mythVersion.right(mythVersion.length() - 1); // Trim off the leading 'v'
290  return QString("MythTV/%2 %1 UPnP/1.0").arg(HttpServer::GetPlatform())
291  .arg(mythVersion);
292 }
293 
295 //
297 
299 {
301  auto *server = qobject_cast<PrivTcpServer *>(QObject::sender());
302  if (server)
303  type = server->GetServerType();
304 
306  new HttpWorker(*this, socket, type
307 #ifndef QT_NO_OPENSSL
308  , m_sslConfig
309 #endif
310  ),
311  QString("HttpServer%1").arg(socket));
312 }
313 
315 //
317 
319 {
320  if (pExtension != nullptr )
321  {
322  LOG(VB_HTTP, LOG_INFO, QString("HttpServer: Registering %1 extension").arg(pExtension->m_sName));
323  m_rwlock.lockForWrite();
324  m_extensions.append( pExtension );
325 
326  // Add to multimap for quick lookup.
327 
328  QStringList list = pExtension->GetBasePaths();
329 
330  for( int nIdx = 0; nIdx < list.size(); nIdx++)
331  m_basePaths.insert( list[ nIdx ], pExtension );
332 
333  m_rwlock.unlock();
334  }
335 }
336 
338 //
340 
342 {
343  if (pExtension != nullptr )
344  {
345  m_rwlock.lockForWrite();
346 
347  QStringList list = pExtension->GetBasePaths();
348 
349  for( int nIdx = 0; nIdx < list.size(); nIdx++)
350  m_basePaths.remove( list[ nIdx ], pExtension );
351 
352  m_extensions.removeAll(pExtension);
353 
354  delete pExtension;
355 
356  m_rwlock.unlock();
357  }
358 }
359 
361 //
363 
365 {
366  bool bProcessed = false;
367 
368  LOG(VB_HTTP, LOG_DEBUG, QString("m_sBaseUrl: %1").arg( pRequest->m_sBaseUrl ));
369  m_rwlock.lockForRead();
370 
371  QList< HttpServerExtension* > list = m_basePaths.values( pRequest->m_sBaseUrl );
372 
373  for (int nIdx=0; nIdx < list.size() && !bProcessed; nIdx++ )
374  {
375  try
376  {
377  if (pRequest->m_eType == RequestTypeOptions)
378  bProcessed = list[ nIdx ]->ProcessOptions(pRequest);
379  else
380  bProcessed = list[ nIdx ]->ProcessRequest(pRequest);
381  }
382  catch(...)
383  {
384  LOG(VB_GENERAL, LOG_ERR, QString("HttpServer::DelegateRequest - "
385  "Unexpected Exception - "
386  "pExtension->ProcessRequest()."));
387  }
388  }
389 
390  HttpServerExtensionList::iterator it = m_extensions.begin();
391 
392  for (; (it != m_extensions.end()) && !bProcessed; ++it)
393  {
394  try
395  {
396  if (pRequest->m_eType == RequestTypeOptions)
397  bProcessed = (*it)->ProcessOptions(pRequest);
398  else
399  bProcessed = (*it)->ProcessRequest(pRequest);
400  }
401  catch(...)
402  {
403  LOG(VB_GENERAL, LOG_ERR, QString("HttpServer::DelegateRequest - "
404  "Unexpected Exception - "
405  "pExtension->ProcessRequest()."));
406  }
407  }
408  m_rwlock.unlock();
409 
410 // if (!bProcessed)
411 // bProcessed = m_pHtmlServer->ProcessRequest(pRequest);
412 
413  if (!bProcessed)
414  {
415  pRequest->m_eResponseType = ResponseTypeHTML;
416  pRequest->m_nResponseStatus = 404;
417  pRequest->m_response.write( pRequest->GetResponsePage() );
418  }
419 }
420 
422 {
423  int timeout = -1;
424 
425  m_rwlock.lockForRead();
426  QList< HttpServerExtension* > list = m_basePaths.values( pRequest->m_sBaseUrl );
427  if (!list.isEmpty())
428  timeout = list.first()->GetSocketTimeout();
429  m_rwlock.unlock();
430 
431  if (timeout < 0)
432  timeout = gCoreContext->GetNumSetting("HTTP/KeepAliveTimeoutSecs", 10);
433 
434  return timeout;
435 }
436 
439 //
440 // HttpWorkerThread Class Implementation
441 //
444 
447 #ifndef QT_NO_OPENSSL
448  , const QSslConfiguration& sslConfig
449 #endif
450 )
451  : m_httpServer(httpServer), m_socket(sock),
452  m_socketTimeout(5 * 1000), m_connectionType(type)
453 #ifndef QT_NO_OPENSSL
454  , m_sslConfig(sslConfig)
455 #endif
456 {
457  LOG(VB_HTTP, LOG_INFO, QString("HttpWorker(%1): New connection")
458  .arg(m_socket));
459 }
460 
462 //
464 
465 void HttpWorker::run(void)
466 {
467 #if 0
468  LOG(VB_HTTP, LOG_DEBUG,
469  QString("HttpWorker::run() socket=%1 -- begin").arg(m_socket));
470 #endif
471 
472  bool bTimeout = false;
473  bool bKeepAlive = true;
474  HTTPRequest *pRequest = nullptr;
475  QTcpSocket *pSocket = nullptr;
476  bool bEncrypted = false;
477 
479  {
480 
481 #ifndef QT_NO_OPENSSL
482  auto *pSslSocket = new QSslSocket();
483  if (pSslSocket->setSocketDescriptor(m_socket)
484  && gCoreContext->CheckSubnet(pSslSocket))
485  {
486  pSslSocket->setSslConfiguration(m_sslConfig);
487  pSslSocket->startServerEncryption();
488  if (pSslSocket->waitForEncrypted(5000))
489  {
490  LOG(VB_HTTP, LOG_INFO, "SSL Handshake occurred, connection encrypted");
491  LOG(VB_HTTP, LOG_INFO, QString("Using %1 cipher").arg(pSslSocket->sessionCipher().name()));
492  bEncrypted = true;
493  }
494  else
495  {
496  LOG(VB_HTTP, LOG_WARNING, "SSL Handshake FAILED, connection terminated");
497  delete pSslSocket;
498  pSslSocket = nullptr;
499  }
500  }
501  else
502  {
503  delete pSslSocket;
504  pSslSocket = nullptr;
505  }
506 
507  if (pSslSocket)
508  pSocket = pSslSocket;
509  else
510  return;
511 #else
512  return;
513 #endif
514  }
515  else // Plain old unencrypted socket
516  {
517  pSocket = new QTcpSocket();
518  pSocket->setSocketDescriptor(m_socket);
519  if (!gCoreContext->CheckSubnet(pSocket))
520  {
521  delete pSocket;
522  pSocket = nullptr;
523  return;
524  }
525 
526  }
527 
528  pSocket->setSocketOption(QAbstractSocket::KeepAliveOption, QVariant(1));
529  int nRequestsHandled = 0; // Allow debugging of keep-alive and connection re-use
530 
531  try
532  {
533  while (m_httpServer.IsRunning() && bKeepAlive && pSocket->isValid() &&
534  pSocket->state() == QAbstractSocket::ConnectedState)
535  {
536  // We set a timeout on keep-alive connections to avoid blocking
537  // new clients from connecting - Default at time of writing was
538  // 5 seconds for initial connection, then up to 10 seconds of idle
539  // time between each subsequent request on the same connection
540  bTimeout = !(pSocket->waitForReadyRead(m_socketTimeout));
541 
542  if (bTimeout) // Either client closed the socket or we timed out waiting for new data
543  break;
544 
545  int64_t nBytes = pSocket->bytesAvailable();
546  if (!m_httpServer.IsRunning())
547  break;
548 
549  if ( nBytes > 0)
550  {
551  // ----------------------------------------------------------
552  // See if this is a valid request
553  // ----------------------------------------------------------
554 
555  pRequest = new BufferedSocketDeviceRequest( pSocket );
556  if (pRequest != nullptr)
557  {
558  pRequest->m_bEncrypted = bEncrypted;
559  if ( pRequest->ParseRequest() )
560  {
561  bKeepAlive = pRequest->GetKeepAlive();
562  // The timeout is defined by the Server/Server Extension
563  // but must appear in the response headers
564  uint nTimeout = m_httpServer.GetSocketTimeout(pRequest); // Seconds
565  pRequest->SetKeepAliveTimeout(nTimeout);
566  m_socketTimeout = nTimeout * 1000; // Milliseconds
567 
568  // ------------------------------------------------------
569  // Request Parsed... Pass on to Main HttpServer class to
570  // delegate processing to HttpServerExtensions.
571  // ------------------------------------------------------
572  if ((pRequest->m_nResponseStatus != 400) &&
573  (pRequest->m_nResponseStatus != 401) &&
574  (pRequest->m_nResponseStatus != 403) &&
575  pRequest->m_eType != RequestTypeUnknown)
576  m_httpServer.DelegateRequest(pRequest);
577 
578  nRequestsHandled++;
579  }
580  else
581  {
582  LOG(VB_HTTP, LOG_ERR, "ParseRequest Failed.");
583 
584  pRequest->m_nResponseStatus = 501;
585  pRequest->m_response.write( pRequest->GetResponsePage() );
586  bKeepAlive = false;
587  }
588 
589  // -------------------------------------------------------
590  // Always MUST send a response.
591  // -------------------------------------------------------
592  if (pRequest->SendResponse() < 0)
593  {
594  bKeepAlive = false;
595  LOG(VB_HTTP, LOG_ERR,
596  QString("socket(%1) - Error returned from "
597  "SendResponse... Closing connection")
598  .arg(pSocket->socketDescriptor()));
599  }
600 
601  // -------------------------------------------------------
602  // Check to see if a PostProcess was registered
603  // -------------------------------------------------------
604  if ( pRequest->m_pPostProcess != nullptr )
605  pRequest->m_pPostProcess->ExecutePostProcess();
606 
607  delete pRequest;
608  pRequest = nullptr;
609  }
610  else
611  {
612  LOG(VB_GENERAL, LOG_ERR,
613  "Error Creating BufferedSocketDeviceRequest");
614  bKeepAlive = false;
615  }
616  }
617  else
618  {
619  bKeepAlive = false;
620  }
621  }
622  }
623  catch(...)
624  {
625  LOG(VB_GENERAL, LOG_ERR,
626  "HttpWorkerThread::ProcessWork - Unexpected Exception.");
627  }
628 
629  delete pRequest;
630 
631  if ((pSocket->error() != QAbstractSocket::UnknownSocketError) &&
632  !(bKeepAlive && pSocket->error() == QAbstractSocket::SocketTimeoutError)) // This 'error' isn't an error when keep-alive is active
633  {
634  LOG(VB_HTTP, LOG_WARNING, QString("HttpWorker(%1): Error %2 (%3)")
635  .arg(m_socket)
636  .arg(pSocket->errorString())
637  .arg(pSocket->error()));
638  }
639 
640  int writeTimeout = 5000; // 5 Seconds
641  // Make sure any data in the buffer is flushed before the socket is closed
642  while (m_httpServer.IsRunning() &&
643  pSocket->isValid() &&
644  pSocket->state() == QAbstractSocket::ConnectedState &&
645  pSocket->bytesToWrite() > 0)
646  {
647  LOG(VB_HTTP, LOG_DEBUG, QString("HttpWorker(%1): "
648  "Waiting for %2 bytes to be written "
649  "before closing the connection.")
650  .arg(m_socket)
651  .arg(pSocket->bytesToWrite()));
652 
653  // If the client stops reading for longer than 'writeTimeout' then
654  // stop waiting for them. We can't afford to leave the socket
655  // connected indefinately, it could be used by another client.
656  //
657  // NOTE: Some clients deliberately stall as a way of 'pausing' A/V
658  // streaming. We should create a new server extension or adjust the
659  // timeout according to the User-Agent, instead of increasing the
660  // standard timeout. However we should ALWAYS have a timeout.
661  if (!pSocket->waitForBytesWritten(writeTimeout))
662  {
663  LOG(VB_GENERAL, LOG_WARNING, QString("HttpWorker(%1): "
664  "Timed out waiting to write bytes to "
665  "the socket, waited %2 seconds")
666  .arg(m_socket)
667  .arg(writeTimeout / 1000));
668  break;
669  }
670  }
671 
672  if (pSocket->bytesToWrite() > 0)
673  {
674  LOG(VB_HTTP, LOG_WARNING, QString("HttpWorker(%1): "
675  "Failed to write %2 bytes to "
676  "socket, (%3)")
677  .arg(m_socket)
678  .arg(pSocket->bytesToWrite())
679  .arg(pSocket->errorString()));
680  }
681 
682  LOG(VB_HTTP, LOG_INFO, QString("HttpWorker(%1): Connection %2 closed. %3 requests were handled")
683  .arg(m_socket)
684  .arg(pSocket->socketDescriptor())
685  .arg(nRequestsHandled));
686 
687  pSocket->close();
688  delete pSocket;
689  pSocket = nullptr;
690 
691 #if 0
692  LOG(VB_HTTP, LOG_DEBUG, "HttpWorkerThread::run() -- end");
693 #endif
694 }
695 
696 
HTTPRequest::m_sBaseUrl
QString m_sBaseUrl
Definition: httprequest.h:125
HttpWorker::m_socketTimeout
int m_socketTimeout
Definition: httpserver.h:198
kSSLServer
@ kSSLServer
Definition: serverpool.h:33
HttpServerExtension::m_nSupportedMethods
uint m_nSupportedMethods
Definition: httpserver.h:81
HTTPRequest
Definition: httprequest.h:108
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
ServerPool::setMaxPendingConnections
void setMaxPendingConnections(int n)
Definition: serverpool.h:94
HttpWorker::m_socket
qt_socket_fd_t m_socket
Definition: httpserver.h:197
HttpWorker
Definition: httpserver.h:178
HttpWorker::m_sslConfig
QSslConfiguration m_sslConfig
Definition: httpserver.h:202
HttpServer::GetServerVersion
static QString GetServerVersion(void)
Definition: httpserver.cpp:285
HttpServer::IsRunning
bool IsRunning(void) const
Definition: httpserver.h:133
HTTPRequest::ParseRequest
bool ParseRequest()
Definition: httprequest.cpp:1262
HttpServer::m_sSharePath
QString m_sSharePath
Definition: httpserver.h:149
MThreadPool::maxThreadCount
int maxThreadCount(void) const
Definition: mthreadpool.cpp:509
HttpServer::RegisterExtension
void RegisterExtension(HttpServerExtension *pExtension)
Definition: httpserver.cpp:318
HttpServer::LoadSSLConfig
void LoadSSLConfig()
Definition: httpserver.cpp:181
arg
arg(title).arg(filename).arg(doDelete))
RequestTypePost
@ RequestTypePost
Definition: httprequest.h:49
RequestTypeOptions
@ RequestTypeOptions
Definition: httprequest.h:53
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
HttpWorker::run
void run(void) override
Definition: httpserver.cpp:465
mythdirs.h
HttpServerExtension::ProcessOptions
virtual bool ProcessOptions(HTTPRequest *pRequest)
Handle an OPTIONS request.
Definition: httpserver.cpp:49
RequestTypeSubscribe
@ RequestTypeSubscribe
Definition: httprequest.h:57
HttpServer::s_platform
static QString s_platform
Definition: httpserver.h:154
MThreadPool::Stop
void Stop(void)
Definition: mthreadpool.cpp:266
RequestTypeUnsubscribe
@ RequestTypeUnsubscribe
Definition: httprequest.h:58
HttpWorker::m_httpServer
HttpServer & m_httpServer
Definition: httpserver.h:196
mythversion.h
RttiServiceHost
Definition: rttiServiceHost.h:43
ResponseTypeHeader
@ ResponseTypeHeader
Definition: httprequest.h:84
toString
QString toString(MarkTypes type)
Definition: programtypes.cpp:26
upnp.h
HttpServer::m_rwlock
QReadWriteLock m_rwlock
Definition: httpserver.h:145
HTTPRequest::m_nResponseStatus
long m_nResponseStatus
Definition: httprequest.h:150
mythlogging.h
HttpServer::GetPlatform
static QString GetPlatform(void)
Definition: httpserver.cpp:275
RequestTypeMSearch
@ RequestTypeMSearch
Definition: httprequest.h:56
HTTPRequest::GetResponsePage
QByteArray GetResponsePage(void)
Definition: httprequest.cpp:1016
HTTPRequest::m_bEncrypted
bool m_bEncrypted
Definition: httprequest.h:140
HTTPRequest::SetKeepAliveTimeout
void SetKeepAliveTimeout(int nTimeout)
Definition: httprequest.h:255
compat.h
HTTPRequest::m_pPostProcess
IPostProcess * m_pPostProcess
Definition: httprequest.h:157
RequestTypeHead
@ RequestTypeHead
Definition: httprequest.h:48
HttpServer::m_running
bool m_running
Definition: httpserver.h:151
GetShareDir
QString GetShareDir(void)
Definition: mythdirs.cpp:222
HttpServer::m_threadPool
MThreadPool m_threadPool
Definition: httpserver.h:150
IPostProcess::ExecutePostProcess
virtual void ExecutePostProcess()=0
PoolServerType
PoolServerType
Definition: serverpool.h:30
HttpServer::UnregisterExtension
void UnregisterExtension(HttpServerExtension *pExtension)
Definition: httpserver.cpp:341
htmlserver.h
HttpWorker::m_connectionType
PoolServerType m_connectionType
Definition: httpserver.h:199
rttiServiceHost.h
uint
unsigned int uint
Definition: compat.h:141
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:933
ResponseTypeHTML
@ ResponseTypeHTML
Definition: httprequest.h:77
HttpServer::HttpServer
HttpServer()
Definition: httpserver.cpp:113
HttpServer::GetSocketTimeout
uint GetSocketTimeout(HTTPRequest *pRequest) const
Get the idle socket timeout value for the relevant extension.
Definition: httpserver.cpp:421
RequestTypeNotify
@ RequestTypeNotify
Definition: httprequest.h:59
BufferedSocketDeviceRequest
Definition: httprequest.h:277
HttpServerExtension::GetBasePaths
virtual QStringList GetBasePaths()=0
mythcorecontext.h
HttpServer::newTcpConnection
void newTcpConnection(qt_socket_fd_t socket) override
Definition: httpserver.cpp:298
HTTPRequest::SetResponseHeader
void SetResponseHeader(const QString &sKey, const QString &sValue, bool replace=false)
Definition: httprequest.cpp:2160
HttpServer::m_basePaths
QMultiMap< QString, HttpServerExtension * > m_basePaths
Definition: httpserver.h:148
HTTPRequest::m_eResponseType
HttpResponseType m_eResponseType
Definition: httprequest.h:147
HttpServer::~HttpServer
~HttpServer() override
Definition: httpserver.cpp:167
HttpServer::m_sslConfig
QSslConfiguration m_sslConfig
Definition: httpserver.h:157
HTTPRequest::GetKeepAlive
bool GetKeepAlive() const
Definition: httprequest.h:235
HttpServer
Definition: httpserver.h:113
GetMythSourceVersion
const char * GetMythSourceVersion()
Definition: mythcoreutil.cpp:313
RequestTypeUnknown
@ RequestTypeUnknown
Definition: httprequest.h:45
HttpServer::m_extensions
HttpServerExtensionList m_extensions
Definition: httpserver.h:146
httpserver.h
MThreadPool::setMaxThreadCount
void setMaxThreadCount(int maxThreadCount)
Definition: mthreadpool.cpp:515
HttpServer::s_platformLock
static QMutex s_platformLock
Definition: httpserver.h:153
HttpServer::DelegateRequest
void DelegateRequest(HTTPRequest *pRequest)
Definition: httpserver.cpp:364
HTTPRequest::SendResponse
qint64 SendResponse(void)
Definition: httprequest.cpp:312
HttpWorker::HttpWorker
HttpWorker(HttpServer &httpServer, qt_socket_fd_t sock, PoolServerType type, const QSslConfiguration &sslConfig)
Definition: httpserver.cpp:445
HttpServerExtension::m_sName
QString m_sName
Definition: httpserver.h:77
RequestTypeGet
@ RequestTypeGet
Definition: httprequest.h:47
HttpServerExtension
Definition: httpserver.h:72
upnputil.h
MythCoreContext::CheckSubnet
bool CheckSubnet(const QAbstractSocket *socket)
Check if a socket is connected to an approved peer.
Definition: mythcorecontext.cpp:1277
qt_socket_fd_t
qintptr qt_socket_fd_t
Definition: mythqtcompat.h:4
MThreadPool::startReserved
void startReserved(QRunnable *runnable, const QString &debugName, int waitForAvailMS=0)
Definition: mthreadpool.cpp:360
HTTPRequest::m_response
QBuffer m_response
Definition: httprequest.h:155
kTCPServer
@ kTCPServer
Definition: serverpool.h:31
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:919
HTTPRequest::m_eType
HttpRequestType m_eType
Definition: httprequest.h:118