MythTV  master
mythhttpsocket.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QThread>
3 #include <QTcpSocket>
4 #ifndef QT_NO_OPENSSL
5 #include <QSslSocket>
6 #endif
7 
8 // MythTV
9 #include "mythlogging.h"
10 #include "mythcorecontext.h"
11 #include "http/mythwebsocket.h"
12 #include "http/mythhttps.h"
13 #include "http/mythhttpsocket.h"
14 #include "http/mythhttpdata.h"
15 #include "http/mythhttpfile.h"
16 #include "http/mythhttpresponse.h"
17 #include "http/mythhttprequest.h"
18 #include "http/mythhttpranges.h"
19 #include "http/mythhttpservices.h"
21 
22 // Std
23 #include <chrono>
24 using namespace std::chrono_literals;
25 
26 #define LOC QString(m_peer + ": ")
27 
28 MythHTTPSocket::MythHTTPSocket(qintptr Socket, bool SSL, MythHTTPConfig Config)
29  : m_socketFD(Socket),
30  m_config(std::move(Config))
31 {
32  // Connect Finish signal to Stop
33  connect(this, &MythHTTPSocket::Finish, this, &MythHTTPSocket::Stop);
34 
35  // Create socket
36  QSslSocket* sslsocket = nullptr;
37  if (SSL)
38  {
39 #ifndef QT_NO_OPENSSL
40  sslsocket = new QSslSocket(this);
41  m_socket = sslsocket;
42 #endif
43  }
44  else
45  {
46  m_socket = new QTcpSocket(this);
47  }
48 
49  if (!m_socket)
50  {
51  Stop();
52  return;
53  }
54 
55  connect(m_socket, &QTcpSocket::readyRead, this, &MythHTTPSocket::Read);
56  connect(m_socket, &QTcpSocket::bytesWritten, this, &MythHTTPSocket::Write);
57  connect(m_socket, &QTcpSocket::disconnected, this, &MythHTTPSocket::Disconnected);
58  connect(m_socket, &QTcpSocket::disconnected, QThread::currentThread(), &QThread::quit);
59  connect(m_socket, &QTcpSocket::errorOccurred, this, &MythHTTPSocket::Error);
60  m_socket->setSocketDescriptor(m_socketFD);
61 
62 #ifndef QT_NO_OPENSSL
63  if (SSL && sslsocket)
65 #endif
66 
67  m_peer = QString("%1:%2").arg(m_socket->peerAddress().toString()).arg(m_socket->peerPort());
68  LOG(VB_HTTP, LOG_INFO, LOC + "New connection");
69 
70  // Setup up timeout timer
71  m_timer.setTimerType(Qt::PreciseTimer);
73  m_timer.start(m_config.m_timeout);
74 
76  Stop();
77 
78  // Setup root services handler - a service for services
79  // Note: the services service is not self aware - i.e. it doesn't list itself
80  // as a service. This is intentional; a client needs to know of the existence
81  // of /services/ already - otherwise it wouldn't be calling it and the 'services'
82  // service would appear again as /services/services/
83  auto service = MythHTTPService::Create<MythHTTPServices>();
84  m_activeServices.emplace_back(service);
85  auto * services = dynamic_cast<MythHTTPServices*>(service.get());
86  if (services == nullptr)
87  {
88  LOG(VB_HTTP, LOG_ERR, LOC + "Failed to get root services handler.");
89  return;
90  }
92  services->UpdateServices(m_config.m_services);
93 }
94 
96 {
97  delete m_websocketevent;
98  delete m_websocket;
99  if (m_socket)
100  m_socket->close();
101  delete m_socket;
102 }
103 
109 void MythHTTPSocket::PathsChanged(const QStringList& Paths)
110 {
111  m_config.m_filePaths = Paths;
112 }
113 
115 {
116  m_config.m_handlers = Handlers;
117 }
118 
120 {
121  m_config.m_services = Services;
123 }
124 
130 void MythHTTPSocket::OriginsChanged(const QStringList& Origins)
131 {
132  m_config.m_allowedOrigins = Origins;
133 }
134 
135 void MythHTTPSocket::HostsChanged(const QStringList& Hosts)
136 {
137  m_config.m_hosts = Hosts;
138 }
139 
146 {
147  LOG(VB_HTTP, LOG_INFO, LOC + "Disconnected");
148 }
149 
150 void MythHTTPSocket::Error(QAbstractSocket::SocketError Error)
151 {
152  if (Error != QAbstractSocket::RemoteHostClosedError)
153  LOG(VB_HTTP, LOG_INFO, LOC + QString("Error %1 (%2)").arg(Error).arg(m_socket->errorString()));
154 }
155 
161 {
162  LOG(VB_HTTP, LOG_DEBUG, LOC + "Timed out waiting for activity");
163  // Send '408 Request Timeout' - Respond will close the socket.
164  // Note: some clients will close the socket themselves at the correct time -
165  // in which case the disconnect may preceed the timeout here - so avoid
166  // misleading write errors...
167  if (m_socket->state() == QAbstractSocket::ConnectedState)
168  {
169  // If this has timed out while a write is in progress, then the socket
170  // buffers are not empty and we cannot send a response - so just close.
171  if (m_socket->bytesToWrite() || !m_queue.empty())
172  {
173  m_queue.clear();
174  LOG(VB_HTTP, LOG_INFO, LOC + "Timeout during write. Quitting.");
175  Stop();
176  return;
177  }
179  Stop();
180  }
181 }
182 
190 {
191  LOG(VB_HTTP, LOG_INFO, LOC + "Stop");
192  if (m_websocket)
193  m_websocket->Close();
194  m_timer.stop();
195  m_stopping = true;
196  // Note: previously this called QTcpSocket::disconnectFromHost - but when
197  // an interrupt is received (i.e. quit the app), there is an intermittent
198  // race condition where the socket is disconnected before the thread is told
199  // to quit and the call to QThread::quit is not triggered (i.e. the connection
200  // between QTcpSocket::disconnected and QThread::quit does not work). So
201  // just quit the thread.
202  QThread::currentThread()->quit();
203 }
204 
210 {
211  if (m_stopping)
212  return;
213 
214  // Warn if we haven't sent the last response
215  if (!m_queue.empty())
216  LOG(VB_GENERAL, LOG_WARNING, LOC + "New request but queue is not empty");
217 
218  // reset the idle timer
219  m_timer.start(m_config.m_timeout);
220 
221  bool ready = false;
222  if (!m_parser.Read(m_socket, ready))
223  {
224  LOG(VB_HTTP, LOG_WARNING, LOC + "HTTP error");
225  Stop();
226  return;
227  }
228 
229  if (!ready)
230  return;
231 
232  // We have a completed request
234  HTTPResponse response = nullptr;
235 
236  // Request should have initial OK status if valid
237  if (request->m_status != HTTPOK)
238  {
239  response = MythHTTPResponse::ErrorResponse(request);
240  Respond(response);
241  return;
242  }
243 
244  // Websocket upgrade request...
245  // This will have a connection type of HTTPConnectionUpgrade on success.
246  // Once the response is sent, we will create a WebSocket instance to handle
247  // further read/write signals.
248  if (!MythHTTP::GetHeader(request->m_headers, "upgrade").isEmpty())
250 
251  // Try (possibly file specific) handlers
252  if (response == nullptr)
253  {
254  // cppcheck-suppress unassignedVariable
255  for (const auto& [path, function] : m_config.m_handlers)
256  {
257  if (path == request->m_url.toString())
258  {
259  response = std::invoke(function, request);
260  if (response)
261  break;
262  }
263  }
264  }
265 
266  const QString& rpath = request->m_path;
267 
268  // Try active services first - this is currently the services root only
269  if (response == nullptr)
270  {
271  LOG(VB_HTTP, LOG_INFO, LOC + QString("Processing: path '%1' file '%2'")
272  .arg(rpath, request->m_fileName));
273 
274  for (auto & service : m_activeServices)
275  {
276  if (service->Name() == rpath)
277  {
278  response = service->HTTPRequest(request);
279  if (response)
280  break;
281  }
282  }
283  }
284 
285  // Then 'inactive' services
286  if (response == nullptr)
287  {
288  // cppcheck-suppress unassignedVariable
289  for (const auto & [path, constructor] : m_config.m_services)
290  {
291  if (path == rpath)
292  {
293  auto instance = std::invoke(constructor);
294  response = instance->HTTPRequest(request);
295  if (response)
296  break;
297  // the service object will be deleted here as it goes out of scope
298  // but we could retain a cache...
299  }
300  }
301  }
302 
303  // Try (dynamic) handlers
304  if (response == nullptr)
305  {
306  // cppcheck-suppress unassignedVariable
307  for (const auto& [path, function] : m_config.m_handlers)
308  {
309  if (path == rpath)
310  {
311  response = std::invoke(function, request);
312  if (response)
313  break;
314  }
315  }
316  }
317 
318  // then simple file path handlers
319  if (response == nullptr)
320  {
321  for (const auto & path : std::as_const(m_config.m_filePaths))
322  {
323  if (path == rpath)
324  {
325  response = MythHTTPFile::ProcessFile(request);
326  if (response)
327  break;
328  }
329  }
330  }
331 
332  // Try error page handler
333  if (response == nullptr || response->m_status == HTTPNotFound)
334  {
335  if(m_config.m_errorPageHandler.first.length() > 0)
336  {
337  auto function = m_config.m_errorPageHandler.second;
338  response = std::invoke(function, request);
339  }
340  }
341 
342  // nothing to see
343  if (response == nullptr)
344  {
345  request->m_status = HTTPNotFound;
346  response = MythHTTPResponse::ErrorResponse(request);
347  }
348 
349  // Send the response
350  Respond(response);
351 }
352 
359 {
360  if (!Response || (m_socket->state() != QAbstractSocket::ConnectedState))
361  return;
362 
363  // Warn if the last response has not been completed
364  if (!m_queue.empty())
365  LOG(VB_GENERAL, LOG_WARNING, LOC + "Responding but queue is not empty");
366 
367  // Reset the write tracker
368  m_writeTime.start();
369  m_totalToSend = 0;
370  m_totalWritten = 0;
371  m_totalSent = 0;
372  m_writeBuffer = nullptr;
373 
374  // Finalise the response
375  Response->Finalise(m_config);
376 
377  // Queue headers
378  for (const auto & header : std::as_const(Response->m_responseHeaders))
379  {
380  LOG(VB_HTTP, LOG_DEBUG, header->trimmed().constData());
381  m_queue.emplace_back(header);
382  }
383 
384  // Queue in memory response content or file
385  if (!std::get_if<std::monostate>(&Response->m_response))
386  m_queue.push_back(Response->m_response);
387  else
388  LOG(VB_HTTP, LOG_DEBUG, LOC + "No content in response");
389 
390  // Sum the expected number of bytes to be written. This is the size of the
391  // data or file OR the total size of the range request. For multipart range
392  // requests, add the total size of the additional headers.
393  for (const auto & content : std::as_const(m_queue))
394  {
395  if (const auto * data = std::get_if<HTTPData>(&content))
396  {
397  m_totalToSend += (*data)->m_partialSize > 0 ? (*data)->m_partialSize : (*data)->size();
398  m_totalToSend += (*data)->m_multipartHeaderSize;
399  }
400  else if (const auto * file = std::get_if<HTTPFile>(&content))
401  {
402  m_totalToSend += (*file)->m_partialSize > 0 ? (*file)->m_partialSize : (*file)->size();
403  m_totalToSend += (*file)->m_multipartHeaderSize;
404  }
405  }
406 
407  // Signal what to do once the response is sent (close, keep alive or upgrade)
408  m_nextConnection = Response->m_connection;
409 
410  // Get the ball rolling
411  Write();
412 }
413 
418 void MythHTTPSocket::RespondDirect(qintptr Socket, const HTTPResponse& Response, const MythHTTPConfig &Config)
419 {
420  if (!(Socket && Response))
421  return;
422 
423  Response->Finalise(Config);
424  auto * socket = new QTcpSocket();
425  socket->setSocketDescriptor(Socket);
426  for (const auto & header : std::as_const(Response->m_responseHeaders))
427  socket->write(*header);
428  socket->flush();
429  socket->disconnectFromHost();
430  delete socket;
431 }
432 
433 void MythHTTPSocket::Write(int64_t Written)
434 {
435  auto chunkheader = [&](const QByteArray& Data)
436  {
437  int64_t wrote = m_socket->write(Data);
438  if (wrote < 0)
439  {
440  LOG(VB_GENERAL, LOG_ERR, "Error writing chunk header");
441  return;
442  }
443  m_totalToSend += wrote;
444  m_totalWritten += wrote;
445  };
446 
447  if (m_stopping)
448  return;
449 
450  // Naughty clients have a habit of stopping reading but leaving the socket open.
451  // Instead of stopping the timer when a request has been received, we leave
452  // it running and update when we see any read OR write activity
453  // TODO perhaps worth using a larger timeout (e.g. *2) for writes - for clients
454  // that are streaming video and have buffered a large amount of data - but with range
455  // request support this probably shouldn't matter - as they can just reconnect
456  // and pick up where they left off.
457  m_timer.start(m_config.m_timeout);
458 
459  // Update write tracker
460  m_totalSent += Written;
461  int64_t buffered = m_socket->bytesToWrite();
462  LOG(VB_HTTP, LOG_DEBUG, LOC + QString("Socket sent %1bytes (still to send %2)")
463  .arg(Written).arg(buffered));
464 
465  // If the client cannot consume data as fast as we are sending it, we just
466  // buffer more and more data in the Qt socket code. So return and wait for
467  // the next write.
468  if (buffered > (HTTP_CHUNKSIZE << 1))
469  {
470  LOG(VB_HTTP, LOG_DEBUG, LOC + "Draining buffers");
471  return;
472  }
473 
474  if (m_totalSent >= m_totalToSend)
475  {
476  auto seconds = static_cast<double>(m_writeTime.nsecsElapsed()) / 1000000000.0;
477  auto rate = static_cast<uint64_t>(static_cast<double>(m_totalSent) / seconds);
478  LOG(VB_HTTP, LOG_INFO, LOC + QString("Wrote %1bytes in %2seconds (%3)")
479  .arg(m_totalSent).arg(seconds, 8, 'f', 6, '0')
480  .arg(MythHTTPWS::BitrateToString(rate)));
481 
482  if (m_queue.empty())
483  {
485  Stop();
487  SetupWebSocket();
488  return;
489  }
490  // This is going to be unrecoverable
491  LOG(VB_GENERAL, LOG_ERR, LOC + "Write complete but queue not empty");
492  Stop();
493  return;
494  }
495 
496  // Fill them buffers
497  int64_t available = HTTP_CHUNKSIZE;
498  while ((available > 0) && !m_queue.empty())
499  {
500  int64_t written = 0;
501  int64_t read = 0;
502  int64_t wrote = 0;
503  int64_t itemsize = 0;
504  int64_t towrite = 0;
505  bool chunk = false;
506  auto * data = std::get_if<HTTPData>(&m_queue.front());
507  auto * file = std::get_if<HTTPFile>(&m_queue.front());
508 
509  if (data)
510  {
511  chunk = (*data)->m_encoding == HTTPChunked;
512  written = (*data)->m_written;
513  itemsize = (*data)->m_partialSize > 0 ? (*data)->m_partialSize : static_cast<int64_t>((*data)->size());
514  towrite = std::min(itemsize - written, available);
515  int64_t offset = 0;
516  HTTPMulti multipart { nullptr, nullptr };
517  if (!(*data)->m_ranges.empty())
518  multipart = MythHTTPRanges::HandleRangeWrite(*data, available, towrite, offset);
519  if (chunk)
520  chunkheader(QStringLiteral("%1\r\n").arg(towrite, 0, 16).toLatin1().constData());
521  if (multipart.first)
522  wrote += m_socket->write(multipart.first->constData());
523  wrote += m_socket->write((*data)->constData() + written + offset, towrite);
524  if (multipart.second)
525  wrote += m_socket->write(multipart.second->constData());
526  if (chunk)
527  chunkheader("\r\n");
528  }
529  else if (file)
530  {
531  chunk = (*file)->m_encoding == HTTPChunked;
532  written = (*file)->m_written;
533  itemsize = (*file)->m_partialSize > 0 ? (*file)->m_partialSize : static_cast<int64_t>((*file)->size());
534  towrite = std::min(itemsize - written, available);
535  HTTPMulti multipart { nullptr, nullptr };
536  if (!(*file)->m_ranges.empty())
537  {
538  int64_t offset = 0;
539  multipart = MythHTTPRanges::HandleRangeWrite(*file, available, towrite, offset);
540  if (offset != (*file)->pos())
541  (*file)->seek(offset);
542  }
543  int64_t writebufsize = std::min(itemsize, static_cast<int64_t>(HTTP_CHUNKSIZE));
544  if (m_writeBuffer && (m_writeBuffer->size() < writebufsize))
545  m_writeBuffer = nullptr;
546  if (!m_writeBuffer)
547  m_writeBuffer = MythHTTPData::Create(static_cast<int>(writebufsize), '\0');
548  read = (*file)->read(m_writeBuffer->data(), towrite);
549  if (read > 0)
550  {
551  if (chunk)
552  chunkheader(QStringLiteral("%1\r\n").arg(read, 0, 16).toLatin1().constData());
553  if (multipart.first)
554  wrote += m_socket->write(multipart.first->constData());
555  wrote += m_socket->write(m_writeBuffer->data(), read);
556  if (multipart.second)
557  wrote += m_socket->write(multipart.second->constData());
558  if (chunk)
559  chunkheader("\r\n");
560  }
561  }
562 
563  if (wrote < 0 || read < 0)
564  {
565  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Write error (Read: %1 Write: %2)")
566  .arg(read).arg(wrote));
567  Stop();
568  return;
569  }
570 
571  written += wrote;
572  if (data) (*data)->m_written = written;
573  if (file) (*file)->m_written = written;
574  m_totalWritten += wrote;
575  available -= wrote;
576 
577 #if 0
578  LOG(VB_HTTP, LOG_DEBUG, LOC + QString("Sent %1 bytes (cum: %2 of %3)")
579  .arg(wrote).arg(m_totalWritten).arg(m_totalToSend));
580 #endif
581 
582  // Move on to the next buffer?
583  if (written >= itemsize)
584  {
585  if (chunk)
586  chunkheader("0\r\n\r\n");
587  m_queue.pop_front();
588  m_writeBuffer = nullptr;
589  }
590  }
591 }
592 
596 {
597  // Disconnect and stop our read/write timer
598  m_timer.disconnect(this);
599  m_timer.stop();
600 
601  // Disconnect our socket read/writes
602  disconnect(m_socket, &QTcpSocket::readyRead, this, &MythHTTPSocket::Read);
603  disconnect(m_socket, &QTcpSocket::bytesWritten, this, &MythHTTPSocket::Write);
604 
605  // Create server websocket instance
607  if (!m_websocket)
608  {
609  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create websocket");
610  Stop();
611  return;
612  }
613  // Create event listener
615  if (!m_websocketevent)
616  {
617  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create websocket event listener");
618  Stop();
619  return;
620  }
621 
622  // Listen for messages
626 
627  // Sending messages
629 
630  // Add this thread to the list of upgraded threads, so we free up slots
631  // for regular HTTP sockets.
632  emit ThreadUpgraded(QThread::currentThread());
633 }
634 
636 {
637  if (!Text)
638  return;
640 }
641 
643 {
644  if (Payloads.empty())
645  return;
647 }
648 
650 {
651  if (Payloads.empty())
652  return;
653 }
HTTPChunked
@ HTTPChunked
Definition: mythhttptypes.h:138
MythHTTPSocket::m_config
MythHTTPConfig m_config
Definition: mythhttpsocket.h:56
MythHTTPSocket::Read
void Read()
Read data from the socket which is parsed by MythHTTPParser.
Definition: mythhttpsocket.cpp:209
StringPayload
std::shared_ptr< MythSharedString > StringPayload
Definition: mythhttpcommon.h:56
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:102
MythHTTPResponse::UpgradeResponse
static HTTPResponse UpgradeResponse(const HTTPRequest2 &Request, MythSocketProtocol &Protocol, bool &Testing)
Definition: mythhttpresponse.cpp:371
MythHTTPSocket::m_writeTime
QElapsedTimer m_writeTime
Definition: mythhttpsocket.h:68
HTTPOK
@ HTTPOK
Definition: mythhttptypes.h:107
MythHTTPSocket::Finish
void Finish()
MythHTTPConfig::m_allowedOrigins
QStringList m_allowedOrigins
Definition: mythhttptypes.h:71
MythHTTPConfig::m_timeout
std::chrono::milliseconds m_timeout
Definition: mythhttptypes.h:68
MythHTTPSocket::ServicesChanged
void ServicesChanged(const HTTPServices &Services)
Definition: mythhttpsocket.cpp:119
MythHTTPSocket::m_totalSent
int64_t m_totalSent
Definition: mythhttpsocket.h:67
HTTP_CHUNKSIZE
#define HTTP_CHUNKSIZE
A group of functions shared between HTTP and WebSocket code.
Definition: mythhttpcommon.h:18
MythHTTPSocket::ThreadUpgraded
void ThreadUpgraded(QThread *Thread)
discid.disc.read
def read(device=None, features=[])
Definition: disc.py:35
MythHTTPSocket::Error
void Error(QAbstractSocket::SocketError Error)
Definition: mythhttpsocket.cpp:150
MythHTTPSocket::NewTextMessage
void NewTextMessage(const StringPayload &Text)
Definition: mythhttpsocket.cpp:635
build_compdb.content
content
Definition: build_compdb.py:38
MythHTTPSocket::m_websocket
MythWebSocket * m_websocket
Definition: mythhttpsocket.h:60
mythhttps.h
MythHTTP::GetHeader
static QString GetHeader(const HTTPHeaders &Headers, const QString &Value, const QString &Default="")
Definition: mythhttptypes.h:317
MythHTTPConfig::m_errorPageHandler
HTTPHandler m_errorPageHandler
Definition: mythhttptypes.h:75
mythhttpranges.h
MythHTTPSocket::m_timer
QTimer m_timer
Definition: mythhttpsocket.h:62
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythHTTPRanges::HandleRangeWrite
static HTTPMulti HandleRangeWrite(HTTPVariant Data, int64_t Available, int64_t &ToWrite, int64_t &Offset)
Definition: mythhttpranges.cpp:89
MythHTTPSocket::m_writeBuffer
HTTPData m_writeBuffer
Definition: mythhttpsocket.h:69
mythhttpsocket.h
MythHTTPSocket::Write
void Write(int64_t Written=0)
Definition: mythhttpsocket.cpp:433
build_compdb.file
file
Definition: build_compdb.py:55
mythhttpdata.h
MythHTTPConfig::m_sslConfig
QSslConfiguration m_sslConfig
Definition: mythhttptypes.h:77
MythHTTPSocket::m_websocketevent
MythWebSocketEvent * m_websocketevent
Definition: mythhttpsocket.h:74
MythHTTPSocket::UpdateServices
void UpdateServices(const HTTPServices &Services)
MythWebSocketEvent::HandleRawTextMessage
bool HandleRawTextMessage(const DataPayloads &Payloads)
Definition: mythwebsocketevent.cpp:15
HTTPNotFound
@ HTTPNotFound
Definition: mythhttptypes.h:115
MythHTTPSocket::m_totalWritten
int64_t m_totalWritten
Definition: mythhttpsocket.h:66
mythhttpfile.h
HTTPRequestTimeout
@ HTTPRequestTimeout
Definition: mythhttptypes.h:117
quit
@ quit
Definition: lirc_client.h:30
MythHTTPSocket::PathsChanged
void PathsChanged(const QStringList &Paths)
Update our list of recognised file paths.
Definition: mythhttpsocket.cpp:109
MythHTTPSocket::m_testSocket
bool m_testSocket
Definition: mythhttpsocket.h:73
MythHTTPFile::ProcessFile
static HTTPResponse ProcessFile(const HTTPRequest2 &Request)
Definition: mythhttpfile.cpp:35
mythlogging.h
HTTPMulti
std::pair< HTTPData, HTTPData > HTTPMulti
Definition: mythhttptypes.h:48
MythWebSocket::CreateWebsocket
static MythWebSocket * CreateWebsocket(bool Server, QTcpSocket *Socket, MythSocketProtocol Protocol, bool Testing)
Definition: mythwebsocket.cpp:31
MythHTTPConfig::m_filePaths
QStringList m_filePaths
Definition: mythhttptypes.h:72
MythWebSocketEvent::SendTextMessage
void SendTextMessage(const QString &)
MythHTTPData::Create
static HTTPData Create()
Definition: mythhttpdata.cpp:4
MythHTTPSocket::NewBinaryMessage
static void NewBinaryMessage(const DataPayloads &Payloads)
Definition: mythhttpsocket.cpp:649
MythHTTPServices
Definition: mythhttpservices.h:7
MythHTTPSocket::m_socket
QTcpSocket * m_socket
Definition: mythhttpsocket.h:59
LOC
#define LOC
Definition: mythhttpsocket.cpp:26
MythWebSocketEvent::HandleTextMessage
bool HandleTextMessage(const StringPayload &Text)
Definition: mythwebsocketevent.cpp:24
MythHTTPSocket::m_socketFD
qintptr m_socketFD
Definition: mythhttpsocket.h:55
MythHTTPResponse::ErrorResponse
static HTTPResponse ErrorResponse(MythHTTPStatus Status, const QString &ServerName)
Definition: mythhttpresponse.cpp:203
HTTPConnectionClose
@ HTTPConnectionClose
Definition: mythhttptypes.h:129
MythHTTPConfig::m_handlers
HTTPHandlers m_handlers
Definition: mythhttptypes.h:73
MythWebSocket::NewBinaryMessage
void NewBinaryMessage(const DataPayloads &Payloads)
MythHTTPSocket::Disconnected
void Disconnected()
The socket was disconnected.
Definition: mythhttpsocket.cpp:145
mythhttpresponse.h
MythHTTPSocket::m_protocol
MythSocketProtocol m_protocol
Definition: mythhttpsocket.h:71
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
MythHTTPSocket::HostsChanged
void HostsChanged(const QStringList &Hosts)
Definition: mythhttpsocket.cpp:135
MythHTTPParser::GetRequest
HTTPRequest2 GetRequest(const MythHTTPConfig &Config, QTcpSocket *Socket)
Definition: mythhttpparser.cpp:15
MythHTTPSocket::RespondDirect
static void RespondDirect(qintptr Socket, const HTTPResponse &Response, const MythHTTPConfig &Config)
Send an (error) response directly without creating a thread.
Definition: mythhttpsocket.cpp:418
MythWebSocket::NewTextMessage
void NewTextMessage(const StringPayload &Text)
MythHTTPServices::UpdateServices
void UpdateServices(const HTTPServices &Services)
Definition: mythhttpservices.cpp:14
HTTPResponse
std::shared_ptr< MythHTTPResponse > HTTPResponse
Definition: mythhttptypes.h:39
MythHTTPSocket::m_activeServices
HTTPServicePtrs m_activeServices
Definition: mythhttpsocket.h:57
MythHTTPSocket::m_queue
HTTPQueue m_queue
Definition: mythhttpsocket.h:64
MythWebSocket::NewRawTextMessage
void NewRawTextMessage(const DataPayloads &Payloads)
MythWebSocketEvent
Definition: mythwebsocketevent.h:6
MythWebSocket::Close
void Close()
Initiate the close handshake when we are exiting.
Definition: mythwebsocket.cpp:80
MythHTTPWS::BitrateToString
static QString BitrateToString(uint64_t Rate)
Definition: mythhttpcommon.h:76
mythcorecontext.h
MythHTTPS::InitSSLSocket
static void InitSSLSocket(QSslSocket *Socket, QSslConfiguration &Config)
Definition: mythhttps.cpp:118
MythHTTPSocket::MythHTTPSocket
MythHTTPSocket(qintptr Socket, bool SSL, MythHTTPConfig Config)
Definition: mythhttpsocket.cpp:28
MythHTTPConfig::m_hosts
QStringList m_hosts
Definition: mythhttptypes.h:70
MythHTTPSocket::m_nextConnection
MythHTTPConnection m_nextConnection
Definition: mythhttpsocket.h:70
std
Definition: mythchrono.h:23
HTTPRequest2
std::shared_ptr< MythHTTPRequest > HTTPRequest2
Definition: mythhttptypes.h:38
mythwebsocket.h
MythHTTPSocket::m_stopping
bool m_stopping
Definition: mythhttpsocket.h:58
mythhttprequest.h
HTTPConnectionUpgrade
@ HTTPConnectionUpgrade
Definition: mythhttptypes.h:131
MythHTTPSocket::Respond
void Respond(const HTTPResponse &Response)
Send response to client.
Definition: mythhttpsocket.cpp:358
MythHTTPConfig::m_services
HTTPServices m_services
Definition: mythhttptypes.h:74
MythHTTPSocket::m_totalToSend
int64_t m_totalToSend
Definition: mythhttpsocket.h:65
MythHTTPSocket::OriginsChanged
void OriginsChanged(const QStringList &Origins)
Update the list of allowed Origins.
Definition: mythhttpsocket.cpp:130
mythhttpservices.h
MythWebSocket::SendTextFrame
void SendTextFrame(const QString &Text)
Definition: mythwebsocket.cpp:85
MythHTTPSocket::SetupWebSocket
void SetupWebSocket()
Transition socket to a WebSocket.
Definition: mythhttpsocket.cpp:595
HTTPServices
std::vector< HTTPService > HTTPServices
Definition: mythhttptypes.h:54
MythHTTPSocket::~MythHTTPSocket
~MythHTTPSocket() override
Definition: mythhttpsocket.cpp:95
MythHTTPConfig
Definition: mythhttptypes.h:60
MythHTTPSocket::m_parser
MythHTTPParser m_parser
Definition: mythhttpsocket.h:63
MythHTTPSocket::NewRawTextMessage
void NewRawTextMessage(const DataPayloads &Payloads)
Definition: mythhttpsocket.cpp:642
mythwebsocketevent.h
MythCoreContext::CheckSubnet
bool CheckSubnet(const QAbstractSocket *socket)
Check if a socket is connected to an approved peer.
Definition: mythcorecontext.cpp:1268
MythHTTPSocket::Stop
void Stop()
Close the socket and quit the thread.
Definition: mythhttpsocket.cpp:189
MythHTTPSocket::HandlersChanged
void HandlersChanged(const HTTPHandlers &Handlers)
Definition: mythhttpsocket.cpp:114
MythHTTPParser::Read
bool Read(QTcpSocket *Socket, bool &Ready)
Definition: mythhttpparser.cpp:42
MythHTTPSocket::m_peer
QString m_peer
Definition: mythhttpsocket.h:61
HTTPHandlers
std::vector< HTTPHandler > HTTPHandlers
Definition: mythhttptypes.h:47
MythHTTPSocket::Timeout
void Timeout()
Close the socket after a period of inactivity.
Definition: mythhttpsocket.cpp:160
DataPayloads
std::vector< DataPayload > DataPayloads
Definition: mythhttpcommon.h:37
MythHTTPConfig::m_serverName
QString m_serverName
Definition: mythhttptypes.h:67