vpn: DragonRelayBackend — QObject bridge between RelayClient/TunnelManager and QML
This commit is contained in:
parent
a13a7b276e
commit
3d8f54a5e4
1 changed files with 129 additions and 0 deletions
129
app/vpn/dragonrelaybackend.h
Normal file
129
app/vpn/dragonrelaybackend.h
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
#pragma once
|
||||
// app/vpn/dragonrelaybackend.h
|
||||
//
|
||||
// DragonRelayBackend is the QObject that QML binds to via the context property
|
||||
// "dragonRelay". It owns a RelayClient and a TunnelManager, coordinates the
|
||||
// login → VPN provision → tunnel-up → host-discovery workflow, and exposes
|
||||
// everything QML needs through Q_PROPERTY / Q_INVOKABLE.
|
||||
//
|
||||
// Registration in main.cpp (or wherever the QML engine is created):
|
||||
//
|
||||
// DragonRelayBackend *backend = new DragonRelayBackend(engine);
|
||||
// engine->rootContext()->setContextProperty("dragonRelay", backend);
|
||||
//
|
||||
// QML usage:
|
||||
//
|
||||
// dragonRelay.connectRelay(url, user, pass)
|
||||
// dragonRelay.disconnectRelay()
|
||||
// dragonRelay.streamHost(ip, app)
|
||||
// dragonRelay.status // int — DragonRelayBackend::Status enum
|
||||
// dragonRelay.statusText // QString
|
||||
// dragonRelay.hosts // QVariantList of {name, ip, port, online, source}
|
||||
// dragonRelay.tunnelIP // QString — local WG address (e.g. "10.99.0.2")
|
||||
|
||||
#ifndef DRAGONRELAYBACKEND_H
|
||||
#define DRAGONRELAYBACKEND_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSettings>
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
#include <QVariant>
|
||||
#include <QVariantList>
|
||||
|
||||
#include "relayclient.h"
|
||||
#include "tunnelmanager.h"
|
||||
#include "wireguardconfig.h"
|
||||
|
||||
class DragonRelayBackend : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
// ── Properties exposed to QML ─────────────────────────────────────────────
|
||||
|
||||
Q_PROPERTY(int status READ status NOTIFY statusChanged)
|
||||
Q_PROPERTY(QString statusText READ statusText NOTIFY statusChanged)
|
||||
Q_PROPERTY(QVariantList hosts READ hosts NOTIFY hostsChanged)
|
||||
Q_PROPERTY(QString tunnelIP READ tunnelIP NOTIFY tunnelIPChanged)
|
||||
|
||||
public:
|
||||
// Status codes (exposed to QML as dragonRelay.StatusXxx or raw int)
|
||||
enum Status {
|
||||
Disconnected = 0,
|
||||
Connecting = 1, // logging in / provisioning VPN peer
|
||||
TunnelUp = 2, // WireGuard tunnel active, hosts loading
|
||||
Ready = 3, // tunnel up + at least one host visible
|
||||
Error = 4,
|
||||
};
|
||||
Q_ENUM(Status)
|
||||
|
||||
explicit DragonRelayBackend(QObject *parent = nullptr);
|
||||
~DragonRelayBackend() override;
|
||||
|
||||
// ── Property accessors ────────────────────────────────────────────────────
|
||||
|
||||
int status() const { return m_status; }
|
||||
QString statusText() const { return m_statusText; }
|
||||
QVariantList hosts() const { return m_hosts; }
|
||||
QString tunnelIP() const { return m_tunnelIP; }
|
||||
|
||||
public slots:
|
||||
// ── Invokable from QML ────────────────────────────────────────────────────
|
||||
|
||||
// Begin the full connect workflow: login → provision VPN → start tunnel → poll hosts.
|
||||
// Idempotent if already connected.
|
||||
Q_INVOKABLE void connectRelay(const QString &url,
|
||||
const QString &username,
|
||||
const QString &password);
|
||||
|
||||
// Tear down tunnel, unregister peer, return to Disconnected state.
|
||||
Q_INVOKABLE void disconnectRelay();
|
||||
|
||||
// Ask Moonlight to stream to a host discovered via the relay.
|
||||
Q_INVOKABLE void streamHost(const QString &ip, const QString &app = QStringLiteral("Desktop"));
|
||||
|
||||
// Refresh the host list immediately (called by QML pull-to-refresh).
|
||||
Q_INVOKABLE void refreshHosts();
|
||||
|
||||
signals:
|
||||
void statusChanged();
|
||||
void hostsChanged();
|
||||
void tunnelIPChanged();
|
||||
|
||||
private slots:
|
||||
// RelayClient signals
|
||||
void onLoginDone(bool ok, const QString &err);
|
||||
void onVPNPeerProvisioned(const RelayVPNConf &conf);
|
||||
void onVPNError(const QString &err);
|
||||
void onHostsFetched(const QList<RelayHost> &hosts);
|
||||
void onHostsError(const QString &err);
|
||||
|
||||
// TunnelManager signals
|
||||
void onTunnelUp(const QString &localIP);
|
||||
void onTunnelDown();
|
||||
void onTunnelError(const QString &err);
|
||||
|
||||
// Timers
|
||||
void pollHosts();
|
||||
|
||||
private:
|
||||
void setStatus(Status s, const QString &text = {});
|
||||
void startHostPoll();
|
||||
void stopHostPoll();
|
||||
|
||||
RelayClient m_relay;
|
||||
TunnelManager m_tunnel;
|
||||
QTimer m_hostPollTimer;
|
||||
|
||||
Status m_status = Disconnected;
|
||||
QString m_statusText = QStringLiteral("Not connected");
|
||||
QVariantList m_hosts;
|
||||
QString m_tunnelIP;
|
||||
|
||||
QString m_savedURL;
|
||||
QString m_savedUser;
|
||||
QString m_savedPass;
|
||||
|
||||
QSettings m_settings; // persists last-used URL + username
|
||||
};
|
||||
|
||||
#endif // DRAGONRELAYBACKEND_H
|
||||
Loading…
Reference in a new issue