call: P2P аудиозвонки — сигналинг, релей медиа, аудио-контур, headless/desktop/android

- src/call/: сигналинг (call.c, call_proto.h, ETCP_RT_ID_CALL 0x36) + релей медиа
  + headless аудио-сокет (call_headless.c, call_audio_bind) + Opus/jitter/тоны
- chat: события CHAT_EVT_CALL_* (34–40), CHAT_EVT_DM_MESSAGES (41), DM-трамплины
- chatgui: call window, miniaudio I/O, audio_frame_ring, test_audio_jitter
- chatgui-android: CallScreen/IncomingCallDialog, аудио-роутинг, JNI, рингтон
- tests: test_call, test_call_headless
This commit is contained in:
evgeny committed 2026-09-16 10:17:57 +03:00
1 parent 0157f7f96b
commit b11e77e4c0
78 files changed
+7053 -70

No files matched your search

+113
View File
@@ -48,6 +48,14 @@ static gui_bgp_info_fn g_bgp_info_cb = nullptr;
static gui_admin_key_received_fn g_admin_key_received_cb = nullptr;
static gui_invite_link_ready_fn g_invite_link_ready_cb = nullptr;
static gui_invite_candidates_fn g_invite_candidates_cb = nullptr;
static gui_call_incoming_fn g_call_incoming_cb = nullptr;
static gui_call_id_fn g_call_ringing_cb = nullptr;
static gui_call_id_fn g_call_accepted_cb = nullptr;
static gui_call_ended_fn g_call_ended_cb = nullptr;
static gui_call_ended_fn g_call_declined_cb = nullptr;
static gui_dm_msg_received_fn g_dm_msg_received_cb = nullptr;
static gui_dm_conv_updated_fn g_dm_conv_updated_cb = nullptr;
static gui_dm_messages_fn g_dm_messages_cb = nullptr;
static struct UASYNC* g_ua = nullptr;
static struct UTUN_INSTANCE* g_inst = nullptr;
@@ -236,6 +244,79 @@ void GuiBridgeReceiver::processPost(int eventType, QByteArray data) {
}
}
break;
case GUI_EVT_DM_MSG_RECEIVED:
if (dlen >= 2) {
uint8_t cl = d[0];
if (dlen >= 1 + cl + 8) {
uint64_t author; memcpy(&author, d + 1 + cl, 8);
DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "gui_bridge: DM_MSG_RECEIVED conv=%.*s author=%llu",
cl, (const char*)d + 1, (unsigned long long)author);
if (g_dm_msg_received_cb) g_dm_msg_received_cb((const char*)d + 1, cl, author);
}
}
break;
case GUI_EVT_DM_CONV_UPDATED:
if (dlen >= 2) {
uint8_t cl = d[0];
if (dlen >= 1 + cl) {
DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "gui_bridge: DM_CONV_UPDATED conv=%.*s",
cl, (const char*)d + 1);
if (g_dm_conv_updated_cb) g_dm_conv_updated_cb((const char*)d + 1, cl);
}
}
break;
case GUI_EVT_DM_MESSAGES:
if (g_dm_messages_cb) g_dm_messages_cb(d, dlen);
break;
case GUI_EVT_CALL_INCOMING:
if (dlen >= 1 + 8 + 8) {
uint8_t chLen = d[0];
if (dlen >= 1 + chLen + 8 + 8) {
uint64_t caller, callId;
memcpy(&caller, d + 1 + chLen, 8);
memcpy(&callId, d + 1 + chLen + 8, 8);
DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "gui_bridge: CALL_INCOMING ch=%.*s caller=0x%016llx id=0x%016llx",
chLen, (const char*)d + 1, (unsigned long long)caller, (unsigned long long)callId);
if (g_call_incoming_cb) g_call_incoming_cb((const char*)d + 1, chLen, caller, callId);
}
}
break;
case GUI_EVT_CALL_RINGING:
if (dlen >= 8) {
uint64_t callId; memcpy(&callId, d, 8);
if (g_call_ringing_cb) g_call_ringing_cb(callId);
}
break;
case GUI_EVT_CALL_ACCEPTED:
if (dlen >= 8) {
uint64_t callId; memcpy(&callId, d, 8);
if (g_call_accepted_cb) g_call_accepted_cb(callId);
}
break;
case GUI_EVT_CALL_ENDED:
if (dlen >= 9) {
uint64_t callId; memcpy(&callId, d, 8);
if (g_call_ended_cb) g_call_ended_cb(callId, d[8]);
}
break;
case GUI_EVT_CALL_DECLINED:
if (dlen >= 9) {
uint64_t callId; memcpy(&callId, d, 8);
if (g_call_declined_cb) g_call_declined_cb(callId, d[8]);
}
break;
case GUI_EVT_CALL_STATS:
if (dlen >= 14) {
uint64_t callId; memcpy(&callId, d, 8);
uint16_t rtt = (uint16_t)((d[8] << 8) | d[9]);
uint16_t buf = (uint16_t)((d[10] << 8) | d[11]);
uint16_t tempo = (uint16_t)((d[12] << 8) | d[13]);
DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC,
"gui_bridge: CALL_STATS id=0x%016llx rtt=%ums buffer=%ums tempo=%u.%02ux",
(unsigned long long)callId, (unsigned)rtt, (unsigned)buf,
(unsigned)(tempo / 100), (unsigned)(tempo % 100));
}
break;
default:
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "gui_bridge: unknown event type %d", eventType);
break;
@@ -377,6 +458,38 @@ void gui_bridge_set_invite_candidates_cb(gui_invite_candidates_fn cb) {
g_invite_candidates_cb = cb;
}
void gui_bridge_set_call_incoming_cb(gui_call_incoming_fn cb) {
g_call_incoming_cb = cb;
}
void gui_bridge_set_call_ringing_cb(gui_call_id_fn cb) {
g_call_ringing_cb = cb;
}
void gui_bridge_set_call_accepted_cb(gui_call_id_fn cb) {
g_call_accepted_cb = cb;
}
void gui_bridge_set_call_ended_cb(gui_call_ended_fn cb) {
g_call_ended_cb = cb;
}
void gui_bridge_set_call_declined_cb(gui_call_ended_fn cb) {
g_call_declined_cb = cb;
}
void gui_bridge_set_dm_msg_received_cb(gui_dm_msg_received_fn cb) {
g_dm_msg_received_cb = cb;
}
void gui_bridge_set_dm_conv_updated_cb(gui_dm_conv_updated_fn cb) {
g_dm_conv_updated_cb = cb;
}
void gui_bridge_set_dm_messages_cb(gui_dm_messages_fn cb) {
g_dm_messages_cb = cb;
}
} /* extern "C" */
/* ── uTun nodeinfo callback (called from uasync thread) ── */