Files
utun2/tools/chatgui/transport/gui_bridge.h
T
evgeny 1345f44e10 chat: invite-ссылки с выбором достижимого узла + tcp_io фикс half-close FIN
- Общий модуль invite_build: сборка utun://-ссылок, авто-выбор лучшего
  достижимого узла, список кандидатов (вынесено из android jni_bridge)
- chatgui: диалог invite с выбором узла (комбобокс), события INVITE_CANDIDATES /
  INVITE_LINK_READY через gui_bridge
- headless/chatcli: invite <ch_id> [node_id], команда invite_nodes
- tcp_io: error_cb отличает грациозный EPOLLHUP (SO_ERROR==0) от реальной ошибки —
  при приостановленном чтении FIN не роняет недослейные данные (фикс flaky half-close)
- run_test.sh: half-close echo на выделенном порту 19190 + отдельный DNAT (был недостижим)
2026-09-07 13:59:15 +03:00

167 lines
10 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifndef GUI_BRIDGE_H
#define GUI_BRIDGE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
struct UASYNC;
struct TOPO_GROUP;
struct TOPO_GROUP_NODE;
/* ── Типы уведомлений uasync→GUI (fire-and-forget) ── */
#define GUI_EVT_MSG_RECEIVED 1 /* data: [ch_id_len:1][ch_id:var][author_node_id:8] */
#define GUI_EVT_CONNECT_RESULT 2 /* data: [node_id:8][result:4][channel_id:8] */
#define GUI_EVT_NEW_PEER 3 /* data: [node_id:8] */
#define GUI_EVT_CHANNEL_UPDATED 4 /* data: [ch_id_len:1][ch_id:var] */
#define GUI_EVT_MEMBERS_CHANGED 5 /* data: [ch_id_len:1][ch_id:var] */
#define GUI_EVT_MY_NODE_ID 6 /* data: [node_id:8] */
#define GUI_EVT_AUTO_CONNECT_STATUS 7 /* data: [status:1][total_tried:2][node_count:2][success:2] */
#define GUI_EVT_CHANNEL_PEERS_ONLINE 8 /* data: [ch_id_len:1][ch_id:var][online_count:2] */
#define GUI_EVT_DB_READY 9 /* data: none — DB is open, tables created */
#define GUI_EVT_STATUS_REFRESH 10 /* data: status text (null-terminated string) */
#define GUI_EVT_NODE_CHANGED 11 /* data: [node_id:8] */
#define GUI_EVT_ATTACHMENT_DOWNLOADED 14 /* data: [ch_id_len:1][ch_id:var][msg_id:8] */
#define GUI_EVT_DOWNLOAD_PROGRESS 15 /* data: [ch_id_len:1][ch_id:var][msg_id:8][blocks_done:4][num_blocks:4] */
#define GUI_EVT_NODEINFO_UPDATE 16 /* data: node_id:8 conn_presence:1 conn_up:1 best_rtt:2(0.1ms,0xFFFF=nodata) */
#define GUI_EVT_CONN_LIST 20 /* data: [count:2][entry:46B]* — binary conn list */
#define GUI_EVT_CONN_METRICS 21 /* data: text dump of selected connection metrics */
#define GUI_EVT_MEMBER_DETAIL 22 /* data: [node_id:8][flags:1][own_tcp_active:2][links...][socks...] — live snapshot for member detail panel */
#define GUI_EVT_MEMBER_LIST 23 /* data: [ch_id_len:1][ch_id:var][count:2][member:79B]* — полный список мемберов канала */
#define GUI_EVT_MEMBER_UPDATED 24 /* data: [ch_id_len:1][ch_id:var][count:1][member:79B] — обновление одного мембера */
#define GUI_EVT_MEMBER_REMOVED 25 /* data: [ch_id_len:1][ch_id:var][node_id:8] — мембер удалён из канала */
#define GUI_EVT_BGP_INFO 26 /* data: text — BGP hop summary for member detail */
#define GUI_EVT_ADMIN_KEY_RECEIVED 28 /* data: [ch_id_len:1][ch_id:var][from_node_id:8] — получен канальный ключ */
#define GUI_EVT_INVITE_LINK_READY 29 /* data: [ch_id_len:1][ch_id:var][link_len:2][link:var] — пустой link = ошибка */
#define GUI_EVT_INVITE_CANDIDATES 30 /* data: [ch_id_len:1][ch_id:var][auto_node_id:8][count:2][node_id:8]* — достижимые узлы для invite */
/* Размеры элементов пакета GUI_EVT_MEMBER_DETAIL (должны совпадать с chat_status.c) */
#define MEMBER_DETAIL_LINK_SIZE 63
#define MEMBER_DETAIL_MAX_LINKS 16
#define MEMBER_DETAIL_MAX_SOCKS 16
#define MEMBER_DETAIL_SOCK_SIZE 48
/* ── API ── */
/* Инициализация моста (вызывается из GUI при старте) */
void gui_bridge_init(void);
/* Установить uasync (вызывается из UtunNode после создания ua) */
void gui_bridge_set_uasync(struct UASYNC* ua);
/* uasync → GUI: уведомление (fire-and-forget, через Qt::QueuedConnection) */
void gui_bridge_post(int event_type, const uint8_t* data, int data_len);
/* GUI → uasync: выполнить функцию в uasync-потоке */
void gui_bridge_post_uasync_fn(void (*fn)(void*), void* arg);
/* Проверить готовность uasync (g_ua != NULL) */
int gui_bridge_is_uasync_ready(void);
/* Callback для результатов подключения (вызывается из GUI-потока) */
typedef void (*gui_connect_result_fn)(uint64_t node_id, uint64_t channel_id, int result);
void gui_bridge_set_connect_result_cb(gui_connect_result_fn cb);
/* Callback для входящих сообщений (вызывается из GUI-потока) */
typedef void (*gui_msg_received_fn)(const char* ch_id, int ch_id_len, uint64_t author);
void gui_bridge_set_msg_received_cb(gui_msg_received_fn cb);
/* Callback для обновления канала (вызывается из GUI-потока) */
typedef void (*gui_channel_updated_fn)(const char* ch_id, int ch_id_len);
void gui_bridge_set_channel_updated_cb(gui_channel_updated_fn cb);
/* Callback для получения своего node_id после инициализации uTun */
typedef void (*gui_my_node_id_fn)(uint64_t node_id);
void gui_bridge_set_my_node_id_cb(gui_my_node_id_fn cb);
/* Callback для статуса авто-подключения (вызывается из GUI-потока)
* status: 0=in_progress, 1=done(3+), 2=stopped */
typedef void (*gui_auto_connect_status_fn)(uint8_t status, uint16_t total_tried, uint16_t node_count, uint16_t connected);
void gui_bridge_set_auto_connect_status_cb(gui_auto_connect_status_fn cb);
/* Callback для обновления числа онлайн-пиров канала (вызывается из GUI-потока) */
typedef void (*gui_channel_peers_online_fn)(const char* ch_id, int ch_id_len, uint16_t online_count);
void gui_bridge_set_channel_peers_online_cb(gui_channel_peers_online_fn cb);
/* Callback: DB открыта, таблицы созданы, можно загружать данные (вызывается из GUI-потока) */
typedef void (*gui_db_ready_fn)(void);
void gui_bridge_set_db_ready_cb(gui_db_ready_fn cb);
/* Callback для обновления статуса (NTP + connections) — text без \0, вызывается из GUI-потока */
typedef void (*gui_status_refresh_fn)(const char* text, int len);
void gui_bridge_set_status_refresh_cb(gui_status_refresh_fn cb);
/* Callback для завершения загрузки медиа-аттача */
typedef void (*gui_attachment_downloaded_fn)(const char* ch_id, int ch_id_len, int64_t msg_id);
void gui_bridge_set_attachment_downloaded_cb(gui_attachment_downloaded_fn cb);
/* Callback для прогресса загрузки медиа */
typedef void (*gui_download_progress_fn)(const char* ch_id, int ch_id_len, int64_t msg_id, int blocks_done, int num_blocks);
void gui_bridge_set_download_progress_cb(gui_download_progress_fn cb);
/* Callback для обновления статуса узла (nodeinfo) — data: 12B packed */
typedef void (*gui_nodeinfo_update_fn)(const uint8_t* data, int len);
void gui_bridge_set_nodeinfo_update_cb(gui_nodeinfo_update_fn cb);
/* Callback для входящих приглашений (вызывается из GUI-потока)
data: [ch_id_len:1][ch_id][name_len:1][name][inviter_node_id:8][inviter_name_len:1][inviter_name] */
typedef void (*gui_invite_received_fn)(const uint8_t* data, int len);
void gui_bridge_set_invite_received_cb(gui_invite_received_fn cb);
/* Callback для списка ETCP-соединений (вызывается из GUI-потока) */
typedef void (*gui_conn_list_fn)(const uint8_t* data, int len);
void gui_bridge_set_conn_list_cb(gui_conn_list_fn cb);
/* Callback для метрик выбранного соединения (вызывается из GUI-потока) */
typedef void (*gui_conn_metrics_fn)(const uint8_t* data, int len);
void gui_bridge_set_conn_metrics_cb(gui_conn_metrics_fn cb);
/* Callback для live-снапшота панели деталей участника (вызывается из GUI-потока)
data: [node_id:8][flags:1][own_tcp_active:2][links...][socks...] — см. chat_status.c collect_member_detail */
typedef void (*gui_member_detail_fn)(const uint8_t* data, int len);
void gui_bridge_set_member_detail_cb(gui_member_detail_fn cb);
/* Callback для получения полного списка мемберов канала (вызывается из GUI-потока)
data: [ch_id_len:1][ch_id:var][count:2][member:79B]* */
typedef void (*gui_member_list_fn)(const uint8_t* data, int len);
void gui_bridge_set_member_list_cb(gui_member_list_fn cb);
/* Callback для обновления одного мембера (вызывается из GUI-потока)
data: [ch_id_len:1][ch_id:var][count:1][member:79B] */
typedef void (*gui_member_updated_fn)(const uint8_t* data, int len);
void gui_bridge_set_member_updated_cb(gui_member_updated_fn cb);
/* Callback для удаления мембера из канала (вызывается из GUI-потока)
data: [ch_id_len:1][ch_id:var][node_id:8] */
typedef void (*gui_member_removed_fn)(const uint8_t* data, int len);
void gui_bridge_set_member_removed_cb(gui_member_removed_fn cb);
/* Callback для BGP hop info текста (вызывается из GUI-потока)
data: текстовая строка формата "rtt:12ms hop:3 via bgp: [ABCD] name1 [EF12] name2" */
typedef void (*gui_bgp_info_fn)(const uint8_t* data, int len);
void gui_bridge_set_bgp_info_cb(gui_bgp_info_fn cb);
/* Callback: получен канальный приватный ключ (стал совладельцем) — data: [ch_id_len:1][ch_id][from_node_id:8] */
typedef void (*gui_admin_key_received_fn)(const uint8_t* data, int len);
void gui_bridge_set_admin_key_received_cb(gui_admin_key_received_fn cb);
/* Callback: готова invite-ссылка (link = пустая строка при ошибке, детали в логе) */
typedef void (*gui_invite_link_ready_fn)(const char* ch_id, int ch_id_len, const char* link);
void gui_bridge_set_invite_link_ready_cb(gui_invite_link_ready_fn cb);
/* Callback: список достижимых узлов-кандидатов для invite — data: [auto_node_id:8][count:2][node_id:8]* */
typedef void (*gui_invite_candidates_fn)(const char* ch_id, int ch_id_len, const uint8_t* data, int len);
void gui_bridge_set_invite_candidates_cb(gui_invite_candidates_fn cb);
/* uTun nodeinfo callback — registered via utun_add_nodeinfo_cbk, called from uasync thread */
void gui_nodeinfo_cb_impl(struct TOPO_GROUP* group, struct TOPO_GROUP_NODE* nq, void* arg);
#ifdef __cplusplus
}
#endif
#endif /* GUI_BRIDGE_H */