3#include <QNetworkInterface>
4#include <QCoreApplication>
7#include <QSslCertificate>
10#include "mythversion.h"
26#include <sys/utsname.h>
29#define LOC QString("HTTPServer: ")
55 static const QStringList s_dirs = {
"/assets/",
"/3rdParty/",
"/css/",
"/images/",
"/js/",
"/misc/",
"/apps/",
"/xslt/" };
58 for (
const auto & dir : s_dirs)
61 QDirIterator it(
m_config.
m_rootDir + dir, QDir::Dirs | QDir::Readable | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
92 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Server is using port %1 - expected %2")
105 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Server is using port %1 - expected %2")
161 LOG(VB_HTTP, LOG_INFO,
LOC +
"SSL is disabled");
169 QString server = QStringLiteral(
"Windows");
171 struct utsname uname_info {};
173 QString server = QStringLiteral(
"%1/%2").arg(uname_info.sysname, uname_info.release);
191 [[maybe_unused]]
bool Ssl)
198 m_bonjourSSL =
nullptr;
202 auto host = QHostInfo::localHostName();
204 host = tr(
"Unknown");
209 m_bonjour->Register(
m_config.
m_port, QByteArrayLiteral(
"_http._tcp"),
210 QStringLiteral(
"%1 on %2").arg(QCoreApplication::applicationName(), host).toLatin1().constData(), {});
217 QStringLiteral(
"%1 on %2").arg(QCoreApplication::applicationName(), host).toLatin1().constData(), {});
237 m_bonjourSSL =
nullptr;
255 auto name = QString(
"HTTP%1%2").arg(entry.m_ssl ?
"S" :
"").arg(
m_threadNum++);
269 auto * server = qobject_cast<PrivTcpServer*>(QObject::sender());
280 if (s_reservedPaths.contains(Path, Qt::CaseInsensitive))
282 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Server path '%1' is reserved - ignoring").arg(Path));
313 for (
const auto & path : std::as_const(Paths))
318 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"'%1' is already registered").arg(path));
320 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Adding path: '%1'").arg(path));
330 for (
const auto & path : std::as_const(Paths))
334 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Removing path: '%1'").arg(path));
364 bool newhandlers =
false;
365 for (
const auto & handler : std::as_const(Handlers))
370 [&handler](
const HTTPHandler& Handler) { return Handler.first == handler.first; }))
372 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Adding handler for '%1'").arg(handler.first));
378 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Handler '%1' already registered - ignoring")
379 .arg(handler.first));
388 bool stalehandlers =
false;
389 for (
const auto & handler : std::as_const(Handlers))
392 [&handler](
const HTTPHandler& Handler) { return Handler.first == handler.first; });
396 stalehandlers =
true;
405 bool newservices =
false;
406 for (
const auto & service : std::as_const(Services))
413 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Adding service for '%1'").arg(service.first));
419 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Service '%1' already registered - ignoring")
420 .arg(service.first));
429 bool staleservices =
false;
430 for (
const auto & service : std::as_const(Services))
437 staleservices =
true;
453 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Adding error page handler"));
466 bool allipv4 =
false;
467 bool allipv6 =
false;
468 for (
const auto & address : std::as_const(defaults))
470 if (address == QHostAddress::AnyIPv4)
472 else if (address == QHostAddress::AnyIPv6)
475 lookups.append(address.toString());
480 if (allipv4 || allipv6)
482 auto addresses = QNetworkInterface::allAddresses();
483 for (
const auto & address : std::as_const(addresses))
485 if ((allipv4 && address.protocol() == QAbstractSocket::IPv4Protocol) ||
486 (allipv6 && address.protocol() == QAbstractSocket::IPv6Protocol))
488 lookups.append(address.toString());
493 lookups.removeDuplicates();
496 for (
const auto & address : lookups)
525 "https://chromecast.mythtv.org"
527 for (
const auto & extra : std::as_const(extras))
529 QString clean = extra.trimmed();
530 if (clean.startsWith(
"http://") || clean.startsWith(
"https://"))
537 bool addhostname =
true;
540 auto ipaddresses = Info.addresses();
541 for(
auto & address : ipaddresses)
547 results.append(result.toLower());
564 for (
const auto & address : std::as_const(addresses))
584 LOG(VB_GENERAL, LOG_INFO,
LOC +
587 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Allowed origin: %1").arg(address));
596 for (
const auto & address : std::as_const(addresses))
616 LOG(VB_GENERAL, LOG_INFO,
LOC +
617 QString(
"Name resolution complete: %1 'Hosts' found").arg(
m_config.
m_hosts.size()));
619 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()