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

/* Стриминг 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