Browse Source

headless/call: закрывать клиента и логировать при ошибке send() (EPIPE/ECONNRESET)

proxy
evgeny 2 weeks ago
parent
commit
398078a28f
  1. 14
      src/call/call_headless.c
  2. 11
      src/chat/chat_headless_control.c

14
src/call/call_headless.c

@ -71,6 +71,8 @@ static struct call_audio* ca_of(struct UTUN_INSTANCE* inst) {
return inst ? (struct call_audio*)inst->call_audio : NULL;
}
static void ca_close_client(struct call_audio_client* cli);
/* ── отправка фрейма клиенту (с буферизацией как в control-сокете) ── */
static void ca_send_raw(struct call_audio_client* cli, const uint8_t* data, size_t len) {
@ -94,6 +96,10 @@ static void ca_send_raw(struct call_audio_client* cli, const uint8_t* data, size
if (remain <= sizeof(cli->send_buf)) { memcpy(cli->send_buf, data + r, remain); cli->send_len = (int)remain; cli->send_offset = 0; }
if (ca && ca->ua) uasync_set_socket_write(ca->ua, cli->socket_id, 1);
}
if (r < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "%s: send failed err=%d, closing client", CH_ID, socket_get_error());
ca_close_client(cli);
}
}
static void ca_write_frame(struct call_audio_client* cli, uint8_t type, uint64_t call_id,
@ -165,8 +171,6 @@ static void ca_media_recv(struct UTUN_INSTANCE* inst, uint64_t call_id,
/* ── разбор входящих фреймов ── */
static void ca_close_client(struct call_audio_client* cli);
static void ca_parse_frames(struct call_audio_client* cli) {
struct call_audio* ca = cli->ca;
uint8_t* p = cli->recv_buf;
@ -228,7 +232,11 @@ static void ca_write_callback(socket_t fd, void* arg) {
if (cli->send_len <= 0) { if (ca && ca->ua) uasync_set_socket_write(ca->ua, cli->socket_id, 0); return; }
ssize_t r = send(cli->fd, cli->send_buf + cli->send_offset, cli->send_len - cli->send_offset, 0);
if (r < 0 && (socket_get_error() == ERR_AGAIN || socket_get_error() == ERR_WOULDBLOCK)) return;
if (r <= 0) { cli->send_len = 0; cli->send_offset = 0; if (ca && ca->ua) uasync_set_socket_write(ca->ua, cli->socket_id, 0); return; }
if (r <= 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "%s: send failed (r=%zd err=%d) — closing client", CH_ID, r, socket_get_error());
ca_close_client(cli);
return;
}
cli->send_offset += (int)r;
if (cli->send_offset >= cli->send_len) { cli->send_len = 0; cli->send_offset = 0; if (ca && ca->ua) uasync_set_socket_write(ca->ua, cli->socket_id, 0); }
}

11
src/chat/chat_headless_control.c

@ -84,6 +84,7 @@ static struct headless_control* hc_of(struct UTUN_INSTANCE* inst) {
/* ── Forward declarations ── */
static void hc_handle_command(struct headless_client* cli, const char* json);
static void hc_close_client(struct headless_client* cli);
/* ── JSON helpers ── */
@ -145,6 +146,10 @@ static void cli_send(struct headless_client* cli, const char* data, size_t len)
if (remain <= sizeof(cli->send_buf)) { memcpy(cli->send_buf, data + r, remain); cli->send_len = (int)remain; cli->send_offset = 0; }
if (hc && hc->ua) uasync_set_socket_write(hc->ua, cli->socket_id, 1);
}
if (r < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_HEADLESS, "headless: send failed err=%d, closing client", socket_get_error());
hc_close_client(cli);
}
}
static void cli_send_str(struct headless_client* cli, const char* s) {
@ -237,7 +242,11 @@ static void client_write_callback(socket_t fd, void* arg) {
if (cli->send_len <= 0) { if (hc && hc->ua) uasync_set_socket_write(hc->ua, cli->socket_id, 0); return; }
ssize_t r = send(cli->fd, cli->send_buf + cli->send_offset, (int)(cli->send_len - cli->send_offset), 0);
if (r < 0 && (socket_get_error() == ERR_AGAIN || socket_get_error() == ERR_WOULDBLOCK)) return;
if (r <= 0) { cli->send_len = 0; cli->send_offset = 0; if (hc && hc->ua) uasync_set_socket_write(hc->ua, cli->socket_id, 0); return; }
if (r <= 0) {
DEBUG_ERROR(DEBUG_CATEGORY_HEADLESS, "headless: send failed (r=%zd err=%d) — closing client", r, socket_get_error());
hc_close_client(cli);
return;
}
cli->send_offset += (int)r;
if (cli->send_offset >= cli->send_len) { cli->send_len = 0; cli->send_offset = 0; if (hc && hc->ua) uasync_set_socket_write(hc->ua, cli->socket_id, 0); }
}

Loading…
Cancel
Save