You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

8.2 KiB

Жизненный цикл ядра и сервисов

Все операции выполняются в потоке единственного UASYNC экземпляра, вне callbacks останавливаемых модулей. GUI передаёт команды в этот поток.

struct UTUN_INSTANCE* inst = utun_instance_create_from_str(ua, config);
if (!inst || utun_core_start(inst) < 0) /* обработать ошибку */;
if (chat_service_start(inst) < 0) /* обработать ошибку */;
if (utun_service_start(inst) < 0) /* обработать ошибку */;

chat_service_stop(inst);  /* UTUN продолжает работать */
chat_service_start(inst); /* загружает сохранённые каналы */
utun_service_stop(inst);  /* чат продолжает работать */
utun_instance_destroy(inst);

utun_instance_init() — сокращение для запуска ядра, UTUN и чата, если чат включён в конфигурации. Desktop GUI и Android запускают ядро и чат явно, без UTUN. Повторный start работающего сервиса и повторный stop допустимы. Ошибка старта сервиса откатывает созданные им ресурсы. utun_instance_stop() останавливает цикл приложения; освобождение ядра выполняет utun_instance_destroy().

Владелец Ресурсы
Ядро Идентичность узла, реестр узлов и групп, SQLite, транспортные сокеты, NCD, маршрутизатор, общая репликация, время, мониторинг
UTUN Группа UTUN, запросы соединений из конфигурации, DATA binding, TUN, системные маршруты, NAT transport
Чат CHAT-группы, запросы подключения и join, экземпляры синхронизации каналов, chat API, медиа, личные сообщения, звонки и headless API
Группа Сессии пиров, её маршруты и логические каналы, планировщик подключения и recovery
Сессия пира группы NCD handle с момента CONNECTING, согласованные эпохи, состояние обмена таблицей, очередь отправки

SQLite открывается ядром один раз: db_path/chats.db, либо :memory:, если путь не задан. Остановка чата сохраняет каналы и сообщения в этой БД. В варианте :memory: данные сохраняются только до уничтожения ядра.

Общий транспорт живёт, пока есть его владельцы. Закрытие запроса одной группы не разрывает соединение, нужное другой группе. При остановке группы отменяются её планировщики, запросы, таймеры и ожидания очередей; отправляется LEAVE, закрываются логические каналы маршрутизатора и удаляется её ожидающий транзит на общих соединениях. Транзит других групп сохраняется. Отложенный LEAVE может временно удерживать транспорт самостоятельно, не обращаясь к уже удалённой группе.

Остановка чата сначала прекращает внешние команды и фоновые задания, затем закрывает медиа и сервисы, синхронизацию и группы, после чего освобождает chat core. media_async_destroy() дожидается завершения native workers и вызывает каждый ожидающий callback с MEDIA_ASYNC_CANCELLED, пока его контекст ещё существует. Результаты отменённых задач не записываются в БД. Это синхронное ожидание: длительное транскодирование или распознавание речи может задержать stop; принудительного прерывания этих библиотек нет.

Статус транспорта UP подтверждает восстановление физического пути. READY сессии группы означает согласованный JOIN/ACCEPT и завершённый обмен её таблицей; именно его ждёт recovery. REINIT меняет эпохи обмена, сохраняя рабочие маршруты. Эпохи защищают от сообщений старой сессии и не задают срок жизни маршрута.

Проверки: test_services проверяет независимый stop/start, общий NCD в CONNECTING, сохранение идентичности/сокетов/БД, повторную загрузку каналов, отмену workers, заблокированного медиа-потока, транзита и ожиданий заменённой очереди. test_chat_join_e2e проверяет join и распространение membership между узлами без UTUN-сервиса.

В Android звонковой сессией владеет CallController уровня приложения; события ядра и команды Telecom обрабатываются один раз в main thread, без повторного проигрывания событий при создании ViewModel. UI получает StateFlow и передаёт пользовательские команды. CallService владеет CallAudioEngine и частичным wake lock: перед исходящим вызовом или принятием входящего запускается foreground режим phoneCall|microphone, затем сигналинг и аудио. Завершение сначала останавливает I/O и дожидается аудиопотоков, затем освобождает native-аудио, wake lock и сервис. Перед NativeLib.stop/restart/destroy выполняется тот же порядок; новый звонок разрешается после SERVICE_STARTED нового ядра.

Активность ядра задаётся явно: видимая Activity или незавершённый звонок удерживают ACTIVE и выключают Android standby. Состояние не истекает по таймеру. После завершения звонка в фоне возвращается standby; экран может гаснуть во время разговора независимо от частичного wake lock сервиса.

utun_set_client_activity() в сборке с UTUN_HAVE_STANDBY применяет фактический режим duty-cycle до рассылки событий активности; JNI не переключает его отдельно. Повторная команда не перезапускает фазу и анонсы, но первый фоновый запуск включает standby даже при начальном client_activity=STANDBY. Keepalive подписан на режим и фазы самого standby; новые UDP/TCP-линки сразу анонсируют текущую фазу после handshake. Пробуждение по таймеру и внешней сети сначала сообщает ACTIVE-окно пирам, затем запускает ожидающие задачи. При выходе сначала восстанавливаются линки; deinit отменяет ожидающие задачи и очищает подписки старого ядра.