Go to the documentation of this file.
2 #include <QDirIterator>
3 #include <QNetworkInterface>
4 #include <QCoreApplication>
7 #include <QSslCertificate>
10 #include "mythversion.h"
14 #ifdef USING_LIBDNS_SD
25 #include <sys/utsname.h>
28 #define LOC QString("HTTPServer: ")
54 static const QStringList s_dirs = {
"/assets/",
"/3rdParty/",
"/css/",
"/images/",
"/js/",
"/misc/",
"/apps/",
"/xslt/" };
57 for (
const auto & dir : s_dirs)
60 QDirIterator it(
m_config.
m_rootDir + dir, QDir::Dirs | QDir::Readable | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
91 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Server is using port %1 - expected %2")
102 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Server is using port %1 - expected %2")
155 #ifndef QT_NO_OPENSSL
163 LOG(VB_HTTP, LOG_INFO,
LOC +
"SSL is disabled");
171 QString server = QStringLiteral(
"Windows");
173 struct utsname uname_info {};
175 QString server = QStringLiteral(
"%1/%2").arg(uname_info.sysname, uname_info.release);
194 #ifdef USING_LIBDNS_SD
199 m_bonjourSSL =
nullptr;
203 auto host = QHostInfo::localHostName();
205 host = tr(
"Unknown");
210 m_bonjour->Register(
m_config.
m_port, QByteArrayLiteral(
"_http._tcp"),
211 QStringLiteral(
"%1 on %2").arg(QCoreApplication::applicationName(), host).toLatin1().constData(), {});
218 QStringLiteral(
"%1 on %2").arg(QCoreApplication::applicationName(), host).toLatin1().constData(), {});
236 #ifdef USING_LIBDNS_SD
241 m_bonjourSSL =
nullptr;
258 auto * server = qobject_cast<PrivTcpServer*>(QObject::sender());
259 auto ssl = server ? server->GetServerType() ==
kSSLServer :
false;
261 auto name = QString(
"HTTP%1%2").arg(ssl ?
"S" :
"").arg(
m_threadNum++);
283 if (s_reservedPaths.contains(Path, Qt::CaseInsensitive))
285 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Server path '%1' is reserved - ignoring").arg(Path));
316 for (
const auto & path : qAsConst(Paths))
321 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"'%1' is already registered").arg(path));
323 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Adding path: '%1'").arg(path));
333 for (
const auto & path : qAsConst(Paths))
337 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Removing path: '%1'").arg(path));
367 bool newhandlers =
false;
368 for (
const auto & handler : qAsConst(Handlers))
373 [&handler](
const HTTPHandler& Handler) { return Handler.first == handler.first; }))
375 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Adding handler for '%1'").arg(handler.first));
381 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Handler '%1' already registered - ignoring")
382 .arg(handler.first));
391 bool stalehandlers =
false;
392 for (
const auto & handler : qAsConst(Handlers))
395 [&handler](
const HTTPHandler& Handler) { return Handler.first == handler.first; });
399 stalehandlers =
true;
408 bool newservices =
false;
409 for (
const auto & service : qAsConst(Services))
416 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Adding service for '%1'").arg(service.first));
422 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Service '%1' already registered - ignoring")
423 .arg(service.first));
432 bool staleservices =
false;
433 for (
const auto & service : qAsConst(Services))
440 staleservices =
true;
456 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Adding error page handler"));
469 bool allipv4 =
false;
470 bool allipv6 =
false;
471 for (
const auto & address : qAsConst(defaults))
473 if (address == QHostAddress::AnyIPv4)
475 else if (address == QHostAddress::AnyIPv6)
478 lookups.append(address.toString());
483 if (allipv4 || allipv6)
485 auto addresses = QNetworkInterface::allAddresses();
486 for (
const auto & address : qAsConst(addresses))
488 if ((allipv4 && address.protocol() == QAbstractSocket::IPv4Protocol) ||
489 (allipv6 && address.protocol() == QAbstractSocket::IPv6Protocol))
491 lookups.append(address.toString());
496 lookups.removeDuplicates();
499 for (
const auto & address : lookups)
528 "https://chromecast.mythtv.org"
530 for (
const auto & extra : extras)
532 QString clean = extra.trimmed();
533 if (clean.startsWith(
"http://") || clean.startsWith(
"https://"))
540 bool addhostname =
true;
543 auto ipaddresses = Info.addresses();
544 for(
auto & address : ipaddresses)
550 results.append(result.toLower());
567 for (
const auto & address : addresses)
587 LOG(VB_GENERAL, LOG_INFO,
LOC +
590 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Allowed origin: %1").arg(address));
599 for (
const auto & address : addresses)
619 LOG(VB_GENERAL, LOG_INFO,
LOC +
620 QString(
"Name resolution complete: %1 'Hosts' found").arg(
m_config.
m_hosts.size()));
622 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Host: %1").arg(address));
~MythHTTPServer() override
void StaleServices(const HTTPServices &Services)
void HostsChanged(const QStringList &Hosts)
QStringList m_allowedOrigins
std::chrono::milliseconds m_timeout
void newTcpConnection(qintptr socket) override
static bool InitSSLServer(QSslConfiguration &Config)
bool isListening(void) const
int GetBackendStatusPort(void)
Returns the locally defined backend status port.
void EnableHTTP(bool Enable)
const char * GetMythSourceVersion()
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
HTTPHandler m_errorPageHandler
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static bool ReservedPath(const QString &Path)
void RemovePaths(const QStringList &Paths)
void AddErrorPageHandler(const HTTPHandler &Handler)
size_t AvailableThreads() const
QSslConfiguration m_sslConfig
QString m_masterIPAddress
int GetMasterServerStatusPort(void)
Returns the Master Backend status port If no master server status port has been defined in the databa...
void AddHandlers(const HTTPHandlers &Handlers)
void NewHandlers(const HTTPHandlers &Handlers)
Add new handlers.
void AddPaths(const QStringList &Paths)
void ServicesChanged(const HTTPServices &Services)
void ResolveMaster(QHostInfo Info)
Add master backend addresses to the allowed Origins list.
void NewServices(const HTTPServices &Services)
void ResolveHost(QHostInfo Info)
Add the results of a reverse lookup to our allowed list.
void ProcessTCPQueueHandler()
void StalePaths(const QStringList &Paths)
size_t MaxThreads() const
void Started(bool Tcp, bool Ssl)
QString GetMasterServerIP(void)
Returns the Master Backend IP address If the address is an IPv6 address, the scope Id is removed.
void HostResolved(QHostInfo Info)
QString GetShareDir(void)
bool IsFrontend(void) const
is this process a frontend process
static QList< QHostAddress > DefaultListen(void)
static QString AddressToString(QHostAddress &Address)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QQueue< qintptr > m_connectionQueue
int GetNumSetting(const QString &key, int defaultval=0)
void MasterResolved(QHostInfo Info)
static QStringList BuildAddressList(QHostInfo &Info)
void HandlersChanged(const HTTPHandlers &Handlers)
#define HTTP_SOCKET_TIMEOUT_MS
void NewErrorPageHandler(const HTTPHandler &Handler)
Add new error page handler.
#define HTTP_SERVICES_DIR
bool IsBackend(void) const
is this process a backend process
void RemoveHandlers(const HTTPHandlers &Handlers)
void StaleHandlers(const HTTPHandlers &Handlers)
QString GetLanguageAndVariant(void)
Returns the user-set language and variant.
void ErrorHandlerChanged(const HTTPHandler &Handler)
void AddThread(MythHTTPThread *Thread)
void EnableDisable(bool Enable)
void NewPaths(const QStringList &Paths)
Add new paths that will serve simple files.
bool listen(QList< QHostAddress > addrs, quint16 port, bool requireall=true, PoolServerType type=kTCPServer)
void AddServices(const HTTPServices &Services)
std::vector< HTTPService > HTTPServices
void RemoveServices(const HTTPServices &Services)
quint16 serverPort(void) const
void PathsChanged(const QStringList &Paths)
std::pair< QString, HTTPFunction > HTTPHandler
void OriginsChanged(const QStringList &Origins)
void BuildOrigins()
Generate a list of allowed 'Origins' for validating CORS requests.
std::pair< QString, HTTPServiceCtor > HTTPService
QString GetSetting(const QString &key, const QString &defaultval="")
std::vector< HTTPHandler > HTTPHandlers
void Init()
Initialise server configuration.