3#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
4#include <QtSystemDetection>
7#include <QNetworkInterface>
8#include <QCoreApplication>
11#include <QSslCertificate>
14#include "mythconfig.h"
15#include "mythversion.h"
31#include <sys/utsname.h>
34#define LOC QString("HTTPServer: ")
60 static const QStringList s_dirs = {
"/assets/",
"/3rdParty/",
"/css/",
"/images/",
"/apps/",
"/xslt/" };
63 for (
const auto & dir : s_dirs)
66 QDirIterator it(
m_config.
m_rootDir + dir, QDir::Dirs | QDir::Readable | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
97 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Server is using port %1 - expected %2")
110 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Server is using port %1 - expected %2")
166 LOG(VB_HTTP, LOG_INFO,
LOC +
"SSL is disabled");
174 QString server = QStringLiteral(
"Windows");
176 struct utsname uname_info {};
178 QString server = QStringLiteral(
"%1/%2").arg(uname_info.sysname, uname_info.release);
196 [[maybe_unused]]
bool Ssl)
203 m_bonjourSSL =
nullptr;
207 auto host = QHostInfo::localHostName();
209 host = tr(
"Unknown");
214 m_bonjour->Register(
m_config.
m_port, QByteArrayLiteral(
"_http._tcp"),
215 QStringLiteral(
"%1 on %2").arg(QCoreApplication::applicationName(), host).toLatin1().constData(), {});
222 QStringLiteral(
"%1 on %2").arg(QCoreApplication::applicationName(), host).toLatin1().constData(), {});
242 m_bonjourSSL =
nullptr;
260 auto name = QString(
"HTTP%1%2").arg(entry.m_ssl ?
"S" :
"").arg(
m_threadNum++);
274 auto * server = qobject_cast<PrivTcpServer*>(QObject::sender());
285 if (s_reservedPaths.contains(Path, Qt::CaseInsensitive))
287 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Server path '%1' is reserved - ignoring").arg(Path));
318 for (
const auto & path : std::as_const(Paths))
323 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"'%1' is already registered").arg(path));
325 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Adding path: '%1'").arg(path));
335 for (
const auto & path : std::as_const(Paths))
339 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Removing path: '%1'").arg(path));
369 bool newhandlers =
false;
370 for (
const auto & handler : std::as_const(Handlers))
375 [&handler](
const HTTPHandler& Handler) { return Handler.first == handler.first; }))
377 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Adding handler for '%1'").arg(handler.first));
383 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Handler '%1' already registered - ignoring")
384 .arg(handler.first));
393 bool stalehandlers =
false;
394 for (
const auto & handler : std::as_const(Handlers))
397 [&handler](
const HTTPHandler& Handler) { return Handler.first == handler.first; });
401 stalehandlers =
true;
410 bool newservices =
false;
411 for (
const auto & service : std::as_const(Services))
418 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Adding service for '%1'").arg(service.first));
424 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Service '%1' already registered - ignoring")
425 .arg(service.first));
434 bool staleservices =
false;
435 for (
const auto & service : std::as_const(Services))
442 staleservices =
true;
458 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Adding error page handler"));
471 bool allipv4 =
false;
472 bool allipv6 =
false;
473 for (
const auto & address : std::as_const(defaults))
475 if (address == QHostAddress::AnyIPv4)
477 else if (address == QHostAddress::AnyIPv6)
480 lookups.append(address.toString());
485 if (allipv4 || allipv6)
487 auto addresses = QNetworkInterface::allAddresses();
488 for (
const auto & address : std::as_const(addresses))
490 if ((allipv4 && address.protocol() == QAbstractSocket::IPv4Protocol) ||
491 (allipv6 && address.protocol() == QAbstractSocket::IPv6Protocol))
493 lookups.append(address.toString());
498 lookups.removeDuplicates();
501 for (
const auto & address : lookups)
530 "https://chromecast.mythtv.org"
532 for (
const auto & extra : std::as_const(extras))
534 QString clean = extra.trimmed();
535 if (clean.startsWith(
"http://") || clean.startsWith(
"https://"))
542 bool addhostname =
true;
545 auto ipaddresses = Info.addresses();
546 for(
auto & address : ipaddresses)
552 results.append(result.toLower());
569 for (
const auto & address : std::as_const(addresses))
589 LOG(VB_GENERAL, LOG_INFO,
LOC +
592 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Allowed origin: %1").arg(address));
601 for (
const auto & address : std::as_const(addresses))
621 LOG(VB_GENERAL, LOG_INFO,
LOC +
622 QString(
"Name resolution complete: %1 'Hosts' found").arg(
m_config.
m_hosts.size()));
624 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Host: %1").arg(address));
bool IsFrontend(void) const
is this process a frontend process
QString GetMasterServerIP(void)
Returns the Master Backend IP address If the address is an IPv6 address, the scope Id is removed.
QString GetSetting(const QString &key, const QString &defaultval="")
int GetBackendStatusPort(void)
Returns the locally defined backend status port.
bool IsBackend(void) const
is this process a backend process
int GetMasterServerStatusPort(void)
Returns the Master Backend status port If no master server status port has been defined in the databa...
int GetNumSetting(const QString &key, int defaultval=0)
QString GetLanguageAndVariant(void)
Returns the user-set language and variant.
QSslConfiguration m_sslConfig
std::chrono::milliseconds m_timeout
HTTPHandler m_errorPageHandler
QStringList m_allowedOrigins
static bool InitSSLServer(QSslConfiguration &Config)
void EnableDisable(bool Enable)
void RemoveServices(const HTTPServices &Services)
void NewErrorPageHandler(const HTTPHandler &Handler)
Add new error page handler.
~MythHTTPServer() override
void ServicesChanged(const HTTPServices &Services)
void MasterResolved(QHostInfo Info)
static bool ReservedPath(const QString &Path)
void Started(bool Tcp, bool Ssl)
void RemovePaths(const QStringList &Paths)
QQueue< MythTcpQueueEntry > m_connectionQueue
void Init()
Initialise server configuration.
void BuildOrigins()
Generate a list of allowed 'Origins' for validating CORS requests.
void StalePaths(const QStringList &Paths)
void StaleHandlers(const HTTPHandlers &Handlers)
void EnableHTTP(bool Enable)
void HandlersChanged(const HTTPHandlers &Handlers)
void StaleServices(const HTTPServices &Services)
void ErrorHandlerChanged(const HTTPHandler &Handler)
void AddHandlers(const HTTPHandlers &Handlers)
void OriginsChanged(const QStringList &Origins)
void AddServices(const HTTPServices &Services)
void AddErrorPageHandler(const HTTPHandler &Handler)
static QStringList BuildAddressList(QHostInfo &Info)
void newTcpConnection(qintptr socket) override
void NewPaths(const QStringList &Paths)
Add new paths that will serve simple files.
void ResolveMaster(QHostInfo Info)
Add master backend addresses to the allowed Origins list.
void RemoveHandlers(const HTTPHandlers &Handlers)
void NewServices(const HTTPServices &Services)
void PathsChanged(const QStringList &Paths)
void ResolveHost(QHostInfo Info)
Add the results of a reverse lookup to our allowed list.
void ProcessTCPQueueHandler()
void AddPaths(const QStringList &Paths)
void HostResolved(QHostInfo Info)
QString m_masterIPAddress
void HostsChanged(const QStringList &Hosts)
void NewHandlers(const HTTPHandlers &Handlers)
Add new handlers.
size_t MaxThreads() const
size_t AvailableThreads() const
void AddThread(MythHTTPThread *Thread)
static QString AddressToString(QHostAddress &Address)
static QList< QHostAddress > DefaultListen(void)
bool listen(QList< QHostAddress > addrs, quint16 port, bool requireall=true, PoolServerType type=kTCPServer)
bool isListening(void) const
quint16 serverPort(void) const
QString GetValue(const QString &setting)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QString GetShareDir(void)
std::pair< QString, HTTPServiceCtor > HTTPService
std::vector< HTTPHandler > HTTPHandlers
std::vector< HTTPService > HTTPServices
std::pair< QString, HTTPFunction > HTTPHandler
#define HTTP_SERVICES_DIR
#define HTTP_SOCKET_TIMEOUT_MS
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
const char * GetMythSourceVersion()