118 lines
11 KiB
C
118 lines
11 KiB
C
/*
|
||
* Android-владелец одного ядра: INI из Kotlin → pthread с uasync → core_start + chat_service_start.
|
||
* UTUN выключен по умолчанию; [gui] utun_enabled=yes включает его явно. Поток владеет instance/ua; UI передаёт работу через uasync.
|
||
* С UTUN_WITH_VOICE worker регистрирует call_audio до SERVICE_STARTED и снимает привязку перед уничтожением ядра.
|
||
* Полученные handles заимствованы и могут смениться при restart; сохранять их между рестартами нельзя.
|
||
* Start/stop/restart сериализованы внутри владельца pthread. Вызовы по сырым handles сериализует frontend:
|
||
* атомарный getter не удерживает ресурс от уничтожения. JOIN использует отдельный защищённый port.
|
||
*/
|
||
#ifndef INSTANCE_LITE_H
|
||
#define INSTANCE_LITE_H
|
||
|
||
#include <stdint.h>
|
||
#include <stddef.h>
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
struct UASYNC;
|
||
struct UTUN_INSTANCE;
|
||
struct utun_config;
|
||
|
||
/* Копирует INI и запускает поток. 0 = поток создан либо уже запущен, -1 = ошибка запуска.
|
||
* Готовность самого ядра появляется позже: проверять is_running и события инициализации.
|
||
* Startup/restart читает идентичность из keys.conf, если он есть (она старше снимка INI в очереди).
|
||
* Формат: public_key=<64 HEX> LF private_key=<64 HEX> LF; ошибка чтения/пары запрещает запуск.
|
||
* Без файла используются ключи INI; при их отсутствии сначала сохраняется новая пара. */
|
||
int instance_lite_start(const char* config_text);
|
||
|
||
/* Остановить и собрать joinable worker, включая инициализацию до появления instance и уже завершившийся startup.
|
||
* Блокирует до полного cleanup/pthread_join; каждые 2с ожидания пишет предупреждение, поток не отсоединяет.
|
||
* Worker снимает media-привязки, уничтожает instance, затем uasync.
|
||
* Управляющий frontend предварительно останавливает аудио I/O и освобождает DSP звонка.
|
||
* Вызывать вне UI и callbacks ядра. Без worker повторный вызов безопасен и сразу возвращается.
|
||
* 0 — worker полностью собран/отсутствует; -1 — ошибка join/недопустимый поток, callbacks освобождать нельзя. */
|
||
int instance_lite_stop(void);
|
||
|
||
/* 1 — instance опубликован и завершил запуск сервисов, 0 — ещё не готов либо остановлен; это не проверка сети. */
|
||
int instance_lite_is_running(void);
|
||
|
||
/* Текущий заимствованный uasync, NULL до create/после destroy; ненулевой handle ещё не означает готовность ядра. */
|
||
struct UASYNC* instance_lite_get_uasync(void);
|
||
|
||
/* Текущий заимствованный instance, NULL до create/после снятия; может быть ненулевым во время инициализации. */
|
||
struct UTUN_INSTANCE* instance_lite_get_instance(void);
|
||
/* Потокобезопасный JOIN через удержанный port: копирует len байтов ссылки, request ненулевой.
|
||
* 0 — принят, результат CHAT_EVT_CONNECT_RESULT с тем же request; <0 — отказ без события.
|
||
* Не требует от caller удерживать inst/ua; при stop/restart port закрывается. */
|
||
int instance_lite_join_link(uint64_t request, const char* link, size_t len);
|
||
/* Любой поток: добавить выбранный локальный channel на сервер по SERVER-ссылке.
|
||
* 0 — команда принята, результат CONNECT_RESULT с request; <0 — отказ без события. */
|
||
int instance_lite_add_server(uint64_t request, uint64_t channel, const char* link, size_t len);
|
||
|
||
/* События CHAT_EVT_* из native-потока; data заимствован только на вызов, формат зависит от type (не всегда JSON).
|
||
* Установить до start; callback и его окружение должны жить до завершения worker. NULL отключает доставку. */
|
||
typedef void (*instance_lite_event_fn)(int type, const uint8_t* data, int len);
|
||
void instance_lite_set_event_handler(instance_lite_event_fn handler);
|
||
|
||
/* Создать X25519-пару и атомарно сохранить в config->global.db_path/keys.conf с правами 0600.
|
||
* config — разобранный конфиг с непустым db_path; caller исключает параллельную смену идентичности.
|
||
* 0 — файл и каталог синхронизированы, ключи/node_id config обновлены; -1 — config не изменён, ошибка залогирована.
|
||
* До rename прежний файл сохраняется; при ошибке sync каталога после rename файл уже заменён (published=1 в логе).
|
||
* Не меняет работающее ядро; для новой идентичности его нужно пересоздать. */
|
||
int instance_lite_generate_keys(struct utun_config* config);
|
||
|
||
/* Принять INI для полной смены идентичности в worker: сохранить новую пару и пересоздать ядро/сервисы.
|
||
* Нужен готовый core; frontend предварительно останавливает media workers/DSP. 0 — копия INI принята, -1 — отказ с логом.
|
||
* Ошибка разбора/сохранения оставляет прежнее ядро; успех даёт KEYS_GENERATED (64 HEX) и SERVICE_STARTED.
|
||
* Последний ещё не взятый worker запрос restart/regenerate заменяет предыдущий. */
|
||
int instance_lite_regenerate_keys(const char* config_text);
|
||
|
||
/* Frontend: поставить ACTIVE (active!=0) / STANDBY (0) без заимствования сырого uasync.
|
||
* 0 — задача зарезервирована и поставлена живому worker; -1 — ядро не готово/останавливается, ошибка памяти или неверный поток.
|
||
* При stop ожидающая команда может отмениться. Результат применения/stream hold логируется в потоке ядра. */
|
||
int instance_lite_set_active(int active);
|
||
|
||
/* Frontend: поставить состояние SIM (0 UNKNOWN/1 IDLE/2 BUSY) и маску call_policy (0..31) живому worker.
|
||
* 0 — данные скопированы в задачу под защитой времени жизни uasync; -1 — неверные аргументы/поток, неготовое ядро или OOM.
|
||
* Применение асинхронно в текущем ядре; stop/restart может отменить ожидающую команду, освободив её данные.
|
||
* После SERVICE_STARTED frontend повторно отправляет актуальные state/policy. */
|
||
int instance_lite_set_phone_state(int state, unsigned policy);
|
||
|
||
#define INSTANCE_LITE_RADIO_SETTINGS_COUNT 7
|
||
/* Результат атомарной проверки/применения в worker; request_id возвращается без изменения.
|
||
* Callback живёт до join; из него нельзя синхронно останавливать worker. */
|
||
typedef void (*instance_lite_radio_configured_fn)(int64_t request_id, int success);
|
||
/* Frontend: копирует 7 читаемых int: enabled, mode, levelOn, levelOff, hangoverMs, vadThreshold, vadGain.
|
||
* 0 — копия поставлена живому worker под защитой владельца; -1 — неготовое ядро, OOM, NULL values/callback или неверный поток.
|
||
* В worker все поля проверяются и применяются целиком; configured(request_id, 1/0) означает успех/отказ без частичного изменения.
|
||
* Stop/restart может отменить ожидающий снимок без callback, освободив всё выделение. Новый запуск аудио присылает актуальный снимок. */
|
||
int instance_lite_configure_radio(int64_t request_id, const int* values, instance_lite_radio_configured_fn configured);
|
||
|
||
/* Копирует INI, будит poll-loop и пересоздаёт instance и uasync внутри worker.
|
||
* До остановки проверяет конфиг и сохраняет отсутствующие ключи; отказ оставляет прежнее ядро.
|
||
* При инициализации ставит запрос в очередь; при завершившемся worker делает join/start.
|
||
* Обновление асинхронное; старые handles утрачивают силу.
|
||
* Stop имеет приоритет перед ожидающим restart. Последний ещё не взятый worker запрос заменяет предыдущий. */
|
||
void instance_lite_restart(const char* new_config_text);
|
||
|
||
/* Лёгкое обновление сокетов (auto_sockets=android): перечитывает [server] секции
|
||
* из нового конфига и сверяет сокеты без полного рестарта. Posts to uasync thread.
|
||
* Если ядро не запущено — только логирует ошибку и дропает вызов. */
|
||
void instance_lite_update_sockets(const char* config_text);
|
||
|
||
/* Поставить локальный ping в uasync (не сетевой). is_responsive=1 после исполнения последнего ping;
|
||
* до первого ping/при остановке возвращает 0. Встроенного ожидания и проверки таймаута нет. */
|
||
void instance_lite_ping(void);
|
||
int instance_lite_is_responsive(void);
|
||
|
||
/* Асинхронные снимки: CHAT_EVT_CONN_LIST и CHAT_EVT_CONN_METRICS; peer_node_id — ID интересующего пира. */
|
||
void instance_lite_collect_conn_list(void);
|
||
void instance_lite_collect_conn_metrics(uint64_t peer_node_id);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
#endif /* INSTANCE_LITE_H */
|