3#include <QReadWriteLock>
7#include <QWaitCondition>
9#include <QCoreApplication>
10#include <QNetworkProxy>
16#include "libmythbase/mythversion.h"
24#define LOC QString("MythSocketManager: ")
26static constexpr std::chrono::milliseconds
PRT_TIMEOUT { 10ms };
37 void run(
void)
override
49 m_threadPool(
"MythSocketManager")
59 QMap<QString, SocketRequestHandler*>::iterator i;
87 LOG(VB_GENERAL, LOG_ERR, QString(
"Failed to bind port %1.").arg(port));
100 if (ms->IsConnected())
113 LOG(VB_GENERAL, LOG_WARNING,
LOC + name +
114 " has already been registered.");
119 LOG(VB_GENERAL, LOG_INFO,
LOC +
120 "Registering socket command handler " + name);
162 QMap<QString, SocketRequestHandler*>::const_iterator i;
164 (*i)->connectionClosed(sock);
190 QStringList listline;
194 QString line = listline[0].simplified();
195 QStringList tokens = line.split(
' ', Qt::SkipEmptyParts);
196 QString command = tokens[0];
198 bool handled =
false;
201 if (command ==
"DONE")
211 if (command ==
"MYTH_PROTO_VERSION")
217 LOG(VB_SOCKET, LOG_ERR,
LOC +
218 "Use of socket attempted before protocol validation.");
220 listline <<
"ERROR" <<
"socket has not been validated";
230 if (command ==
"ANN")
234 QMap<QString, SocketRequestHandler*>::const_iterator i
238 LOG(VB_SOCKET, LOG_DEBUG,
LOC +
239 QString(
"Attempting to handle announce with: %1")
240 .arg((*i)->GetHandlerName()));
241 handled = (*i)->HandleAnnounce(sock, tokens, listline);
248 LOG(VB_SOCKET, LOG_DEBUG,
LOC +
249 QString(
"Socket announce handled by: %1")
250 .arg((*i)->GetHandlerName()));
253 (*i)->connectionAnnounced(sock, tokens, listline);
257 LOG(VB_SOCKET, LOG_ERR,
LOC +
"Socket announce unhandled.");
259 listline <<
"ERROR" <<
"unhandled announce";
265 LOG(VB_SOCKET, LOG_ERR,
LOC +
266 "Use of socket attempted before announcement.");
268 listline <<
"ERROR" <<
"socket has not been announced";
273 if (command ==
"ANN")
275 LOG(VB_SOCKET, LOG_ERR,
LOC +
"ANN sent out of sequence.");
277 listline <<
"ERROR" <<
"socket has already been announced";
289 LOG(VB_SOCKET, LOG_ERR,
LOC +
"No handler found for socket.");
291 listline <<
"ERROR" <<
"socket handler cannot be found";
299 QMap<QString, SocketRequestHandler*>::const_iterator i
303 handled = (*i)->HandleQuery(handler, tokens, listline);
308 LOG(VB_SOCKET, LOG_DEBUG,
LOC + QString(
"Query handled by: %1")
309 .arg((*--i)->GetHandlerName()));
314 if (command ==
"BACKEND_MESSAGE")
322 listline <<
"ERROR" <<
"unknown command";
328 const QStringList &slist)
331 const QString&
version = slist[1];
332 if (
version != MYTH_PROTO_VERSION)
334 LOG(VB_GENERAL, LOG_ERR,
LOC +
335 "Client speaks protocol version " +
version +
336 " but we speak " + MYTH_PROTO_VERSION +
'!');
337 retlist <<
"REJECT" << MYTH_PROTO_VERSION;
343 if (slist.size() < 3)
345 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Client did not pass protocol "
346 "token. Refusing connection!");
347 retlist <<
"REJECT" << MYTH_PROTO_VERSION;
353 const QString& token = slist[2];
354 if (token != QString::fromUtf8(MYTH_PROTO_TOKEN))
356 LOG(VB_GENERAL, LOG_ERR,
LOC +
357 QString(
"Client sent incorrect protocol token \"%1\" for "
358 "protocol version. Refusing connection!").arg(token));
359 retlist <<
"REJECT" << MYTH_PROTO_VERSION;
365 LOG(VB_SOCKET, LOG_DEBUG,
LOC +
"Client validated");
366 retlist <<
"ACCEPT" << MYTH_PROTO_VERSION;
void startReserved(QRunnable *runnable, const QString &debugName, std::chrono::milliseconds waitForAvailMS=0ms)
void newConnection(qintptr socket)
QMap< QString, SocketRequestHandler * > m_handlerMap
static void HandleVersion(MythSocket *socket, const QStringList &slist)
SocketHandler * GetConnectionBySocket(MythSocket *socket)
QReadWriteLock m_handlerLock
void readyRead(MythSocket *socket) override
QReadWriteLock m_socketLock
void AddSocketHandler(SocketHandler *socket)
~MythSocketManager() override
void ProcessRequestWork(MythSocket *socket)
void ProcessRequest(MythSocket *socket)
void RegisterHandler(SocketRequestHandler *handler)
void newConnection(qintptr sd)
static void HandleDone(MythSocket *socket)
void connectionClosed(MythSocket *socket) override
QMap< MythSocket *, SocketHandler * > m_socketMap
QSet< MythSocket * > m_socketList
Class for communcating between myth backends and frontends.
bool IsValidated(void) const
bool IsAnnounced(void) const
bool ReadStringList(QStringList &list, std::chrono::milliseconds timeoutMS=kShortTimeout)
bool IsDataAvailable(void)
void DisconnectFromHost(void)
bool WriteStringList(const QStringList &list)
ProcessRequestRunnable(MythSocketManager &parent, MythSocket *sock)
MythSocketManager & m_parent
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
virtual int IncrRef(void)
Increments reference count.
This decrements the reference on destruction.
bool listen(QList< QHostAddress > addrs, quint16 port, bool requireall=true, PoolServerType type=kTCPServer)
void setProxy(const QNetworkProxy &proxy)
MythSocket * GetSocket(void) const
virtual void SetParent(MythSocketManager *parent)
virtual QString GetHandlerName(void)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static constexpr std::chrono::milliseconds PRT_TIMEOUT