vpn: add RelayClient — HTTP API client for DragonRelay
This commit is contained in:
parent
1711a0bb5a
commit
f2cce0a4f6
1 changed files with 110 additions and 0 deletions
110
app/vpn/relayclient.h
Normal file
110
app/vpn/relayclient.h
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
// relayclient.h — Qt HTTP client for the DragonRelay backend API.
|
||||||
|
//
|
||||||
|
// Workflow:
|
||||||
|
// 1. login() → authenticates, stores JWT in QSettings
|
||||||
|
// 2. provisionVPN()→ POST /api/vpn/peer → returns WireGuardConfig
|
||||||
|
// 3. revokeVPN() → DELETE /api/vpn/peer/:id → cleans up peer on server
|
||||||
|
// 4. fetchHosts() → GET /api/hosts → returns list of streaming hosts
|
||||||
|
//
|
||||||
|
// All calls are asynchronous; results come back via signals.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QList>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
#include "wireguardconfig.h"
|
||||||
|
|
||||||
|
class QNetworkAccessManager;
|
||||||
|
class QNetworkReply;
|
||||||
|
class QSettings;
|
||||||
|
|
||||||
|
// Represents a streaming host as returned by GET /api/hosts
|
||||||
|
struct RelayHost {
|
||||||
|
QString name;
|
||||||
|
QString ip;
|
||||||
|
int port = 47984;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RelayClient : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RelayClient(QObject *parent = nullptr);
|
||||||
|
~RelayClient() override;
|
||||||
|
|
||||||
|
// ── Persistence helpers ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Save relay URL + credentials to QSettings for auto-reconnect.
|
||||||
|
void saveServer(const QString &label, const QUrl &url,
|
||||||
|
const QString &username, const QString &password);
|
||||||
|
|
||||||
|
struct SavedServer { QString label; QUrl url; QString username; QString password; };
|
||||||
|
QList<SavedServer> savedServers() const;
|
||||||
|
void removeServer(const QString &label);
|
||||||
|
|
||||||
|
// ── Async API calls ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Authenticate against the relay. Emits loginSucceeded or loginFailed.
|
||||||
|
void login(const QUrl &relayUrl, const QString &username, const QString &password);
|
||||||
|
|
||||||
|
/// Provision a WireGuard peer for this device.
|
||||||
|
/// Must be called after a successful login().
|
||||||
|
/// Emits vpnProvisioned or vpnProvisionFailed.
|
||||||
|
void provisionVPN(const QString &deviceName = QString());
|
||||||
|
|
||||||
|
/// Revoke the current peer from the server.
|
||||||
|
/// Emits vpnRevoked on completion (best-effort; errors are logged but not fatal).
|
||||||
|
void revokeVPN();
|
||||||
|
|
||||||
|
/// Fetch the list of streaming hosts visible to this user.
|
||||||
|
/// Emits hostsReady or hostsFetchFailed.
|
||||||
|
void fetchHosts();
|
||||||
|
|
||||||
|
// ── State ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
bool isLoggedIn() const { return !m_jwt.isEmpty(); }
|
||||||
|
QUrl relayUrl() const { return m_relayUrl; }
|
||||||
|
QString username() const { return m_username; }
|
||||||
|
int vpnPeerId() const { return m_vpnPeerId; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void loginSucceeded();
|
||||||
|
void loginFailed(const QString &reason);
|
||||||
|
|
||||||
|
void vpnProvisioned(const WireGuardConfig &cfg);
|
||||||
|
void vpnProvisionFailed(const QString &reason);
|
||||||
|
|
||||||
|
void vpnRevoked();
|
||||||
|
|
||||||
|
void hostsReady(const QList<RelayHost> &hosts);
|
||||||
|
void hostsFetchFailed(const QString &reason);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QNetworkAccessManager *m_nam;
|
||||||
|
QSettings *m_settings;
|
||||||
|
|
||||||
|
QUrl m_relayUrl;
|
||||||
|
QString m_username;
|
||||||
|
QString m_jwt;
|
||||||
|
int m_vpnPeerId = -1;
|
||||||
|
|
||||||
|
QUrl apiUrl(const QString &path) const;
|
||||||
|
void setAuthHeader(QNetworkReply *reply);
|
||||||
|
QNetworkReply *authedGet (const QString &path);
|
||||||
|
QNetworkReply *authedPost(const QString &path, const QByteArray &body);
|
||||||
|
QNetworkReply *authedDelete(const QString &path);
|
||||||
|
|
||||||
|
void onLoginReply (QNetworkReply *reply, const QString &username,
|
||||||
|
const QString &password);
|
||||||
|
void onProvisionReply(QNetworkReply *reply);
|
||||||
|
void onRevokeReply (QNetworkReply *reply);
|
||||||
|
void onHostsReply (QNetworkReply *reply);
|
||||||
|
|
||||||
|
void persistJwt();
|
||||||
|
void loadJwt();
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue