/* * chat_event.c — реализация системы нотификаций * * Обработчик — per-instance (хранится в UTUN_INSTANCE.chat_event_handler). * Пока обработчик не зарегистрирован — события логируются. * При регистрации обработчика — форвардятся ему синхронно. */ #include "chat_event.h" #include "../utun_instance.h" #include "../lib/debug_config.h" #include #include #ifdef __ANDROID__ #include #endif void chat_event_set_handler(struct UTUN_INSTANCE* inst, chat_event_handler_fn handler) { if (!inst) return; #ifdef __ANDROID__ __android_log_print(ANDROID_LOG_INFO, "utun-evt", "chat_event_set_handler: handler=%p old=%p", (void*)handler, (void*)inst->chat_event_handler); #endif inst->chat_event_handler = handler; } void chat_event_post(struct UTUN_INSTANCE* inst, int type, const uint8_t* data, int len) { if (inst && inst->chat_event_handler) { inst->chat_event_handler(inst, type, data, len); return; } static const char* names[] = { [1]="MSG_RECEIVED", [2]="CONNECT_RESULT", [3]="NEW_PEER", [4]="CHANNEL_UPDATED", [5]="MEMBERS_CHANGED", [6]="MY_NODE_ID", [7]="AUTO_CONNECT_STATUS", [8]="CHANNEL_PEERS_ONLINE", [9]="DB_READY", [10]="STATUS_REFRESH", [11]="KEYS_GENERATED", [12]="SERVICE_STARTED", [13]="SERVICE_STOPPED", [14]="ATTACHMENT_DOWNLOADED", [15]="DOWNLOAD_PROGRESS", [16]="NODEINFO_UPDATED", [17]="LINK_STATUS_CHANGED", [18]="INVITE_RECEIVED", [19]="LOCAL_SOCKETS", [20]="CONN_LIST", [21]="CONN_METRICS", [22]="MEMBER_DETAIL", [23]="MEMBER_LIST", [24]="MEMBER_UPDATED", [25]="MEMBER_REMOVED", [26]="BGP_INFO", [27]="CONNECTING_NODES", [28]="ADMIN_KEY_RECEIVED", [29]="INVITE_LINK_READY", [30]="INVITE_CANDIDATES", [31]="CHANNEL_DELETED", [32]="DM_MSG_RECEIVED", [33]="DM_CONV_UPDATED", [34]="CALL_INCOMING", [35]="CALL_RINGING", [36]="CALL_ACCEPTED", [37]="CALL_ENDED", [38]="CALL_DECLINED", [39]="CALL_STATS", [40]="CALL_ERROR", [41]="DM_MESSAGES", [42]="CALL_PATH", [43]="RADIO_TALK", [44]="CALL_CONNECTION", [45]="DM_CONVERSATIONS", [46]="ATTACHMENT_PREPARATION", [47]="DM_CALL_ROUTE", [55]="RADIO_MUTE_RESULT", }; const char* n = (type >= 1 && type < (int)(sizeof(names) / sizeof(names[0]))) ? names[type] : "?"; DEBUG_DEBUG(DEBUG_CATEGORY_CHAT, "chat_event: %s(%d) data=%d bytes", n, type, len); if (data && len > 0) log_dump(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_CHAT, " ", data, len); } /* ID задачи не даёт позднему завершению изменить статус другой подготовки. */ void chat_event_attachment(struct UTUN_INSTANCE* inst, int is_dm, const char* target, const uint8_t id[16], int state) { char name[68]; int n = snprintf(name, sizeof(name), "%s%s", is_dm ? "dm:" : "", target); if (n <= 0 || (size_t)n >= sizeof(name) || state < 0 || state > 2) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment: invalid preparation event target=%s state=%d", target, state); return; } uint8_t data[1 + 68 + 16 + 1]; data[0] = (uint8_t)n; memcpy(data + 1, name, (size_t)n); memcpy(data + 1 + n, id, 16); data[17 + n] = (uint8_t)state; chat_event_post(inst, CHAT_EVT_ATTACHMENT_PREPARATION, data, n + 18); }