86 lines
5.8 KiB
C++
86 lines
5.8 KiB
C++
/* Desktop-владелец единственного встроенного ядра: читает INI, создаёт uasync и запускает core/chat в std::thread.
|
|
* [gui] utun_enabled=yes дополнительно запускает UTUN; tun_enabled управляет только созданием TUN.
|
|
* start подтверждает готовность сервисов и медиапривязок перед входом в poll.
|
|
* start/stop/настройки принадлежат GUI-потоку; настройки менять при остановленном узле.
|
|
* requestStop допускается из другого потока, stop ждёт worker и освобождает uasync вне callbacks.
|
|
* Worker уничтожает instance; идентичность и NTP читаются через защищённую копию состояния,
|
|
* обновляемую перед подтверждением старта и после каждого poll. instance — только заимствованный
|
|
* указатель для кода ядра: использовать в uasync, согласовав время жизни с stop/restart.
|
|
* Logger общий для процесса; путь файла принадлежит объекту до закрытия лога. */
|
|
#ifndef UTUN_NODE_H
|
|
#define UTUN_NODE_H
|
|
|
|
#include <QObject>
|
|
#include <QByteArray>
|
|
#include <QString>
|
|
#include <atomic>
|
|
#include <cstdint>
|
|
#include <future>
|
|
#include <mutex>
|
|
#include <thread>
|
|
|
|
struct UTUN_INSTANCE;
|
|
|
|
class UtunNode : public QObject {
|
|
Q_OBJECT
|
|
public:
|
|
// QObject принадлежит GUI; деструктор выполняет stop и закрывает собственный файл лога.
|
|
explicit UtunNode(QObject* parent = nullptr);
|
|
~UtunNode();
|
|
|
|
// Запускает сервисы по INI configPath; ждёт готовности. false — ошибка/уже запущен; см. startupError.
|
|
bool start(const QString& configPath);
|
|
// Причина последнего отказа start; читается в GUI-потоке после возврата start.
|
|
QString startupError() const { return m_startupError; }
|
|
void requestStop(); // Попросить выход из poll и разбудить его; не ждёт уничтожения ядра.
|
|
void stop(); // Идемпотентно запросить остановку, join worker и очистить опубликованное состояние.
|
|
// true от начала start до stop/отката; самостоятельный выход worker сначала сообщает stopped.
|
|
bool isRunning() const { return m_running; }
|
|
|
|
void setDebugFile(const QString& path); // Файл общего logger-а, append; пустой — файл задаёт конфиг ядра.
|
|
void setDbPath(const QString& path); // Переопределить db_path INI; создать каталог, ошибку записать в лог.
|
|
void setDebugLevel(const QString& level); // Общий уровень; пустой/неизвестный — info.
|
|
void setDebugCategories(const QString& categories); // Overrides cat=level,... поверх sys=info,bgp=info.
|
|
|
|
struct UTUN_INSTANCE* instance() const { return m_instance.load(); }
|
|
|
|
// Копии данных ядра, безопасны вне uasync; до старта/после stop — пустые строки, 0/false.
|
|
QString nodeIdHex() const;
|
|
QString pubKeyHex() const;
|
|
int64_t ntpOffsetUs() const;
|
|
bool ntpSynced() const;
|
|
bool ntpEnabled() const;
|
|
|
|
signals:
|
|
void started(); // Синхронно в GUI после успешного start.
|
|
void stopped(); // Через Qt-очередь после освобождения ядра; событие прежнего запуска отсекается.
|
|
void error(const QString& msg); // Ошибка start; stopped при отказе запуска не посылается.
|
|
|
|
private:
|
|
void runLoop(std::promise<QString> startup);
|
|
void finalize(); // Только GUI после join: сброс моста, уничтожение uasync, очистка копии состояния.
|
|
void updateSnapshot(const UTUN_INSTANCE* inst); // uasync читает ядро; NULL сбрасывает копию при finalize.
|
|
|
|
struct Snapshot {
|
|
QString nodeId, publicKey;
|
|
int64_t ntpOffsetUs = 0;
|
|
bool ntpSynced = false, ntpEnabled = false;
|
|
} m_snapshot; // Копия для GUI; доступ под m_snapshotMutex, указателей ядра не содержит.
|
|
mutable std::mutex m_snapshotMutex;
|
|
std::atomic<UTUN_INSTANCE*> m_instance{nullptr}; // Публикуется после готовности; не продлевает жизнь ядра.
|
|
struct UASYNC* m_ua = nullptr; // Живёт до join; m_uaMutex защищает wakeup и откат неудачного старта.
|
|
std::mutex m_uaMutex;
|
|
std::thread m_thread; // Присоединяется GUI до повторного старта и уничтожения объекта.
|
|
std::atomic<bool> m_running{false}; // Узел владеет запущенным/останавливаемым worker.
|
|
std::atomic<bool> m_stop{false}; // Потокобезопасный запрос остановки.
|
|
uint64_t m_generation = 0; // Поколение запуска; GUI отбрасывает поздний stopped прежнего worker.
|
|
QString m_configPath;
|
|
QString m_startupError;
|
|
QString m_debugFile;
|
|
QByteArray m_debugLogPath; // Стабильный UTF-8 путь, заимствованный общим logger-ом.
|
|
QString m_dbPath;
|
|
QString m_debugLevel;
|
|
QString m_debugCategories;
|
|
};
|
|
#endif // UTUN_NODE_H
|