Integrate shared C transport with desktop and Android frontends, add radio probes and detailed Windows diagnostics, and fix GUI build dependencies and early configuration startup errors.
108 lines
7.9 KiB
C++
108 lines
7.9 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 после подтверждённого stopping в GUI: читатели SQLite должны снять handle в его слотах.
|
|
* Идентичность, путь БД и 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 <condition_variable>
|
|
#include <mutex>
|
|
#include <thread>
|
|
#include "desktop_ble.h"
|
|
|
|
struct UTUN_INSTANCE;
|
|
struct sqlite3;
|
|
|
|
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(); }
|
|
/* GUI: заимствованный handle, живой до stopping; после сигнала новые чтения запрещены.
|
|
* Слот stopping снимает handle без вызова stop/join. Worker ждёт завершения слотов перед destroy. */
|
|
struct sqlite3* databaseHandle() const;
|
|
QString databasePath() const; // Копия фактического каталога db_path ядра; пусто без instance.
|
|
|
|
// Копии данных ядра, безопасны вне uasync; до старта/после stop — пустые строки, 0/false.
|
|
QString nodeIdHex() const;
|
|
QString pubKeyHex() const;
|
|
int64_t ntpOffsetUs() const;
|
|
bool ntpSynced() const;
|
|
bool ntpEnabled() const;
|
|
DesktopBleSnapshot bluetoothSnapshot() const; // GUI: копия состояния радио и свежих обнаруженных узлов.
|
|
bool setBluetoothFlags(int flags); // GUI: 0..7; применить в uasync после пробуждения, INI сохраняет вызывающий.
|
|
ble_transport* bluetoothTransport() const; // Только uasync: заимствованный C API handle до выключения/stop.
|
|
|
|
signals:
|
|
void started(); // Синхронно в GUI после успешного start.
|
|
void stopping(); // GUI: освободить заимствованные данные; SQLite/ядро ещё живы до возврата слотов.
|
|
void stopped(); // Через Qt-очередь после освобождения ядра; событие прежнего запуска отсекается.
|
|
void error(const QString& msg); // Ошибка start; stopped при отказе запуска не посылается.
|
|
|
|
private:
|
|
void runLoop(std::promise<QString> startup);
|
|
void finalize(); // Только GUI после join: сброс моста, уничтожение uasync, очистка копии состояния.
|
|
void detachGuiReaders(); // GUI: stopping и подтверждение worker; идемпотентно в пределах запуска.
|
|
void updateSnapshot(const UTUN_INSTANCE* inst); // uasync читает ядро; NULL сбрасывает копию при finalize.
|
|
|
|
struct Snapshot {
|
|
QString nodeId, publicKey;
|
|
int64_t ntpOffsetUs = 0;
|
|
bool ntpSynced = false, ntpEnabled = false;
|
|
struct sqlite3* database = nullptr; // Заимствован до подтверждения stopping в GUI.
|
|
QString databasePath; // Каталог SQLite/media после применения GUI override.
|
|
DesktopBleSnapshot bluetooth;
|
|
} m_snapshot; // Копия для GUI; доступ под m_snapshotMutex, указателей ядра не содержит.
|
|
mutable std::mutex m_snapshotMutex;
|
|
std::atomic<UTUN_INSTANCE*> m_instance{nullptr}; // Публикуется после готовности; не продлевает жизнь ядра.
|
|
std::atomic<int> m_bluetoothFlags{0};
|
|
DesktopBle* m_bluetooth = nullptr; // Только uasync; объект живёт на стеке runLoop.
|
|
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}; // Потокобезопасный запрос остановки.
|
|
std::atomic<bool> m_stopping{false}; // Закрывает публикацию handle перед ожиданием GUI.
|
|
std::mutex m_guiStopMutex; // Подтверждение отсоединения GUI до уничтожения SQLite.
|
|
std::condition_variable m_guiStopCondition;
|
|
bool m_guiDetached = true; // Под m_guiStopMutex; сбрасывается перед start.
|
|
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
|