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.
103 lines
6.4 KiB
103 lines
6.4 KiB
/* Стриминг CHAT-сервиса: локальные handles владеют общим экземпляром трансляции. |
|
* Все API — uasync-поток. Последний reader close освобождает экземпляр; publisher close |
|
* останавливает свою трансляцию и отсоединяет её readers. Отсоединённый handle всё равно закрывает вызывающий. |
|
* DATA/GAP/END/CLOSED callback отложен, data/описание заимствованы до его возврата. |
|
* Close handles из callback допустим; остановка сервиса/группы и destroy ядра — вне callbacks. |
|
* Источник и локальные подписки публикуются атомарно через опции собственного мембера. */ |
|
#ifndef STREAM_H |
|
#define STREAM_H |
|
|
|
#include "stream_buffer.h" |
|
|
|
#ifdef __cplusplus |
|
extern "C" { |
|
#endif |
|
|
|
struct UTUN_INSTANCE; |
|
struct STREAM_HANDLE; |
|
struct stream_service; |
|
|
|
struct stream_parameters { uint8_t n, r; uint16_t block_size; }; |
|
|
|
enum stream_event_type { STREAM_EVENT_DATA, STREAM_EVENT_GAP, STREAM_EVENT_END, STREAM_EVENT_CLOSED }; |
|
enum stream_close_reason { |
|
STREAM_CLOSE_STOPPED, STREAM_CLOSE_GROUP, STREAM_CLOSE_SERVICE, STREAM_CLOSE_SOURCE_CHANGED, |
|
STREAM_CLOSE_MEMBER, STREAM_CLOSE_FAILED |
|
}; |
|
|
|
struct stream_event { |
|
struct stream_descriptor descriptor; |
|
enum stream_event_type type; |
|
uint64_t first_seq, last_seq; |
|
const uint8_t *data; |
|
size_t length; |
|
int reason; |
|
}; |
|
typedef void (*stream_event_fn)(struct UTUN_INSTANCE *inst, const struct stream_event *event, void *arg); |
|
|
|
struct stream_info { |
|
struct stream_descriptor descriptor; |
|
struct stream_buffer_stats buffer; |
|
unsigned owners; |
|
int publisher; |
|
int finished; |
|
}; |
|
|
|
struct stream_candidate { |
|
uint64_t node_id; |
|
uint8_t client_type; |
|
uint8_t source; |
|
}; |
|
|
|
struct stream_selection_settings { uint32_t migration_confirm_ms, minimum_hold_ms, rtt_hysteresis_ms; }; |
|
struct stream_selection_info { |
|
uint64_t probes_started, cycles, migrations, failures, restarts; |
|
unsigned candidates, probes_active, subflows, overlaps, providers; |
|
int automatic, protected_by_fec; |
|
}; |
|
|
|
int stream_service_init(struct UTUN_INSTANCE *inst); |
|
void stream_service_destroy(struct UTUN_INSTANCE *inst); |
|
void stream_cancel_group(struct UTUN_INSTANCE *inst, uint64_t group_id); |
|
void stream_set_event_callback(struct UTUN_INSTANCE *inst, stream_event_fn callback, void *arg); |
|
/* Проверенные online-публикации: JSON с id(decimal string), epoch(hex string), name, self. |
|
* Только uasync; *out заранее NULL, результат освобождается u_free(). WAIT — группа недоступна. */ |
|
int stream_sources_json(struct UTUN_INSTANCE *inst, uint64_t group_id, char **out); |
|
/* Один выбранный канал frontend: начальный снимок и изменения через CHAT_EVT_STREAM_SOURCES. |
|
* group_id=0 снимает наблюдение. Не создаёт подписку/буфер и не удерживает ACTIVE. Только uasync. */ |
|
int stream_watch_sources(struct UTUN_INSTANCE *inst, uint64_t group_id); |
|
/* Локальный owner удерживает эффективный ACTIVE; желаемый frontend-режим ядро восстанавливает после последнего close. */ |
|
int stream_service_needs_activity(const struct UTUN_INSTANCE *inst); |
|
|
|
/* out заранее NULL. parameters=NULL — 6+2 и полный подписанный блок 1300 байт. |
|
* Одна публикация этого узла в группе; новый запуск получает новый source_epoch. */ |
|
int stream_publish_open(struct UTUN_INSTANCE *inst, uint64_t group_id, const struct stream_parameters *parameters, |
|
struct STREAM_HANDLE **out); |
|
/* Параметры берутся из подписанного профиля источника; дубликаты локальных владельцев делят один буфер. |
|
* WAIT — источник ещё не объявил/не подтвердил трансляцию. Offline не создаёт ложного онлайн-кандидата. */ |
|
int stream_subscribe_open(struct UTUN_INSTANCE *inst, uint64_t group_id, uint64_t source_id, struct STREAM_HANDLE **out); |
|
/* Ручные выдачи для диагностики/явного управления; режим общий для всех owners экземпляра и не смешивается с automatic. */ |
|
int stream_subscribe_manual_open(struct UTUN_INSTANCE *inst, uint64_t group_id, uint64_t source_id, struct STREAM_HANDLE **out); |
|
/* По умолчанию: подтверждение улучшения 2000 мс, удержание 5000 мс, гистерезис RTT 20 мс. */ |
|
int stream_selection_configure(struct STREAM_HANDLE *handle, const struct stream_selection_settings *settings); |
|
int stream_selection_get_info(const struct STREAM_HANDLE *handle, struct stream_selection_info *info); |
|
void stream_close(struct STREAM_HANDLE *handle); |
|
int stream_handle_active(const struct STREAM_HANDLE *handle); |
|
int stream_handle_reason(const struct STREAM_HANDLE *handle); |
|
int stream_get_info(const struct STREAM_HANDLE *handle, struct stream_info *info); |
|
|
|
size_t stream_publish_capacity(const struct STREAM_HANDLE *handle); |
|
int stream_publish_write(struct STREAM_HANDLE *handle, const uint8_t *data, size_t length, size_t *accepted); |
|
/* Публикует одну непустую FEC-пачку, без склейки/таймера. Не смешивать с publish_write в одном запуске. */ |
|
int stream_publish_block(struct STREAM_HANDLE *handle, const uint8_t *data, size_t length); |
|
/* Сбросить остаток, снять статус публикации; DATA перед END. Буфер живёт до close. */ |
|
int stream_publish_finish(struct STREAM_HANDLE *handle); |
|
|
|
/* Только подходящие online-подписчики этой группы/эпохи; мобильные relay исключены, источник допускается. |
|
* out заранее NULL; массив освобождается u_free(). Наличие кандидата не гарантирует прямой транспорт. */ |
|
int stream_get_candidates(const struct STREAM_HANDLE *handle, struct stream_candidate **out, size_t *count); |
|
|
|
#ifdef __cplusplus |
|
} |
|
#endif |
|
#endif
|
|
|