moonlight-qt/app/backend/computermanager.h

216 lines
4.9 KiB
C
Raw Normal View History

2018-06-24 22:13:37 +00:00
#pragma once
#include "nvcomputer.h"
2018-07-06 06:12:55 +00:00
#include "nvpairingmanager.h"
2018-06-24 22:13:37 +00:00
2018-07-01 06:07:31 +00:00
#include <qmdnsengine/server.h>
#include <qmdnsengine/cache.h>
#include <qmdnsengine/browser.h>
#include <qmdnsengine/service.h>
#include <qmdnsengine/resolver.h>
2018-06-27 04:47:01 +00:00
#include <QThread>
#include <QReadWriteLock>
#include <QSettings>
2018-07-06 06:12:55 +00:00
#include <QRunnable>
#include <QTimer>
2018-06-24 22:13:37 +00:00
2018-07-01 06:07:31 +00:00
class MdnsPendingComputer : public QObject
{
Q_OBJECT
public:
explicit MdnsPendingComputer(QMdnsEngine::Server* server,
const QMdnsEngine::Service& service)
: m_Hostname(service.hostname()),
2019-08-05 01:04:07 +00:00
m_Server(server),
m_Resolver(nullptr)
2018-07-01 06:07:31 +00:00
{
2019-08-05 01:04:07 +00:00
// Start resolving
resolve();
}
virtual ~MdnsPendingComputer()
{
delete m_Resolver;
2018-07-01 06:07:31 +00:00
}
QString hostname()
{
return m_Hostname;
}
private slots:
void handleResolvedTimeout()
2018-07-01 06:07:31 +00:00
{
2019-08-05 01:04:07 +00:00
if (m_Addresses.isEmpty()) {
// Try again
qInfo() << "Resolving" << hostname() << "timed out. Retrying...";
resolve();
}
else {
Q_ASSERT(!m_Addresses.isEmpty());
emit resolvedHost(this, m_Addresses);
}
}
void handleResolvedAddress(const QHostAddress& address)
{
qInfo() << "Resolved" << hostname() << "to" << address;
m_Addresses.push_back(address);
2018-07-01 06:07:31 +00:00
}
signals:
void resolvedHost(MdnsPendingComputer*,QVector<QHostAddress>&);
2018-07-01 06:07:31 +00:00
private:
2019-08-05 01:04:07 +00:00
void resolve()
{
delete m_Resolver;
m_Resolver = new QMdnsEngine::Resolver(m_Server, m_Hostname);
connect(m_Resolver, &QMdnsEngine::Resolver::resolved,
this, &MdnsPendingComputer::handleResolvedAddress);
QTimer::singleShot(2000, this, SLOT(handleResolvedTimeout()));
}
2018-07-01 06:07:31 +00:00
QByteArray m_Hostname;
2019-08-05 01:04:07 +00:00
QMdnsEngine::Server* m_Server;
QMdnsEngine::Resolver* m_Resolver;
QVector<QHostAddress> m_Addresses;
2018-07-01 06:07:31 +00:00
};
class ComputerPollingEntry
{
public:
ComputerPollingEntry()
: m_ActiveThread(nullptr)
{
}
virtual ~ComputerPollingEntry()
{
interrupt();
// interrupt() should have taken care of this
Q_ASSERT(m_ActiveThread == nullptr);
for (QThread* thread : m_InactiveList) {
thread->wait();
delete thread;
}
}
bool isActive()
{
cleanInactiveList();
return m_ActiveThread != nullptr;
}
void setActiveThread(QThread* thread)
{
cleanInactiveList();
Q_ASSERT(!isActive());
m_ActiveThread = thread;
}
void interrupt()
{
cleanInactiveList();
if (m_ActiveThread != nullptr) {
// Interrupt the active thread
m_ActiveThread->requestInterruption();
// Place it on the inactive list awaiting death
m_InactiveList.append(m_ActiveThread);
m_ActiveThread = nullptr;
}
}
private:
void cleanInactiveList()
{
QMutableListIterator<QThread*> i(m_InactiveList);
// Reap any threads that have finished
while (i.hasNext()) {
i.next();
QThread* thread = i.value();
if (thread->isFinished()) {
delete thread;
i.remove();
}
}
}
QThread* m_ActiveThread;
QList<QThread*> m_InactiveList;
};
2018-06-27 04:47:01 +00:00
class ComputerManager : public QObject
{
Q_OBJECT
2018-07-06 06:12:55 +00:00
friend class DeferredHostDeletionTask;
2018-07-06 07:34:16 +00:00
friend class PendingAddTask;
2018-07-06 06:12:55 +00:00
2018-06-27 04:47:01 +00:00
public:
2018-06-28 02:55:44 +00:00
explicit ComputerManager(QObject *parent = nullptr);
2018-06-27 04:47:01 +00:00
virtual ~ComputerManager();
Q_INVOKABLE void startPolling();
2018-06-27 04:47:01 +00:00
Q_INVOKABLE void stopPollingAsync();
2018-06-27 04:47:01 +00:00
Q_INVOKABLE void addNewHost(QString address, bool mdns, QHostAddress mdnsIpv6Address = QHostAddress());
2018-06-27 04:47:01 +00:00
2018-07-06 06:12:55 +00:00
void pairHost(NvComputer* computer, QString pin);
void quitRunningApp(NvComputer* computer);
QVector<NvComputer*> getComputers();
// computer is deleted inside this call
void deleteHost(NvComputer* computer);
2020-05-02 01:34:15 +00:00
void renameHost(NvComputer* computer, QString name);
2018-06-27 04:47:01 +00:00
signals:
void computerStateChanged(NvComputer* computer);
2018-07-06 06:12:55 +00:00
void pairingCompleted(NvComputer* computer, QString error);
2018-07-06 07:34:16 +00:00
void computerAddCompleted(QVariant success);
2018-08-02 05:32:21 +00:00
void quitAppCompleted(QVariant error);
2018-06-27 04:47:01 +00:00
private slots:
void handleAboutToQuit();
2018-06-27 04:47:01 +00:00
void handleComputerStateChanged(NvComputer* computer);
void handleMdnsServiceResolved(MdnsPendingComputer* computer, QVector<QHostAddress>& addresses);
2018-07-01 06:07:31 +00:00
2018-06-27 04:47:01 +00:00
private:
void saveHosts();
QHostAddress getBestGlobalAddressV6(QVector<QHostAddress>& addresses);
2018-06-27 04:47:01 +00:00
void startPollingComputer(NvComputer* computer);
int m_PollingRef;
2018-06-27 04:47:01 +00:00
QReadWriteLock m_Lock;
QMap<QString, NvComputer*> m_KnownHosts;
QMap<QString, ComputerPollingEntry*> m_PollEntries;
2018-07-01 06:07:31 +00:00
QMdnsEngine::Server m_MdnsServer;
QMdnsEngine::Browser* m_MdnsBrowser;
QMdnsEngine::Cache m_MdnsCache;
QVector<MdnsPendingComputer*> m_PendingResolution;
2018-06-24 22:13:37 +00:00
};