tcp_proxy: fix throughput (tx_queue backpressure) + connect timeout + integration test
- Router: unified service delivery format [svc_id][src][dst][payload] (end-to-end src/dst from SVC_ROUTE header) - tcp_proxy_client: replace single tx_buf drop-on-backpressure with bounded tx_queue + send_q waiter + retry timer (no data loss, bulk window reopen — removes 62.5ms delayed-ACK stall) - tcp_io: configurable connect timeout (tcp_conn_set_connect_timeout) - tcp_proxy_server: connect_timeout config option (ms, default 2000, 0=off) - check.sh: run tcp_proxy_full integration test with sudo (skip if passwordless sudo unavailable) - test_tcp_io: connect timeout unit test; docs (lwip_nuances.md)
This commit is contained in:
1 parent
acfaae2801
commit
f47ad7d87f
36 files changed
+758
-269
No files matched your search
@@ -25,6 +25,7 @@ static void fin_deferred_cb(struct ll_queue* q, void* arg);
|
||||
static void write_queue_fetch_cb(struct ll_queue* q, void* arg);
|
||||
static int flush_write_buf(struct tcp_conn* tc);
|
||||
static void tcp_conn_handle_error(struct tcp_conn* tc, int err);
|
||||
static void connect_timeout_cb(void* arg);
|
||||
static const uint8_t tcp_fin_sentinel;
|
||||
|
||||
struct tcp_conn* tcp_conn_create(
|
||||
@@ -121,6 +122,8 @@ void tcp_conn_destroy(struct tcp_conn* tc) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "tcp_conn_destroy: fd=%d connected=%d error=%d fin_remote=%d fin_local=%d closed=%d",
|
||||
(int)tc->sock, tc->connected, tc->error, tc->fin_remote, tc->fin_local, tc->closed);
|
||||
|
||||
if (tc->connect_timer) { uasync_cancel_timeout(tc->ua, tc->connect_timer); tc->connect_timer = NULL; }
|
||||
|
||||
if (tc->socket_id) {
|
||||
uasync_remove_socket_t(tc->ua, tc->sock);
|
||||
tc->socket_id = NULL;
|
||||
@@ -383,6 +386,7 @@ static void write_cb(socket_t sock, void* arg) {
|
||||
socklen_t len = sizeof(err);
|
||||
if (getsockopt(tc->sock, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == 0 && err == 0) {
|
||||
tc->connected = 1;
|
||||
if (tc->connect_timer) { uasync_cancel_timeout(tc->ua, tc->connect_timer); tc->connect_timer = NULL; }
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "tcp_io: connect ok fd=%d", (int)tc->sock);
|
||||
} else {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "tcp_io: connect fail fd=%d err=%d", (int)tc->sock, err);
|
||||
@@ -453,3 +457,26 @@ void tcp_conn_pause_read(struct tcp_conn* tc) {
|
||||
queue_waiter_cancel(tc->read_queue, &tc->read_waiter);
|
||||
tc->read_paused = 1;
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
// Таймаут установления соединения
|
||||
// ====================================================================
|
||||
|
||||
static void connect_timeout_cb(void* arg) {
|
||||
struct tcp_conn* tc = (struct tcp_conn*)arg;
|
||||
if (!tc) return;
|
||||
tc->connect_timer = NULL;
|
||||
if (!tc->connected && tc->sock != SOCKET_INVALID) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_SOCKET, "tcp_io: connect timeout fd=%d (limit %d ms)", (int)tc->sock, tc->connect_timeout_ms);
|
||||
tcp_conn_handle_error(tc, ETIMEDOUT);
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_conn_set_connect_timeout(struct tcp_conn* tc, int timeout_ms) {
|
||||
if (!tc) return;
|
||||
if (timeout_ms < 0) timeout_ms = 0;
|
||||
tc->connect_timeout_ms = timeout_ms;
|
||||
if (!tc->connected && timeout_ms > 0) {
|
||||
tc->connect_timer = uasync_set_timeout(tc->ua, timeout_ms * 10, tc, connect_timeout_cb, "tcp_conn_ct");
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,9 @@ struct tcp_conn {
|
||||
uint8_t closed; // сокет полностью закрыт (close)
|
||||
uint8_t destroyed; // 1 = tcp_conn_destroy вызван, tc ожидает отложенного free
|
||||
|
||||
int connect_timeout_ms; // таймаут установления соединения, 0 = без таймаута
|
||||
void* connect_timer; // handle uasync таймера connect
|
||||
|
||||
// Частичная отправка (из data_pool, не в очереди — досылается первой)
|
||||
uint8_t* write_buf;
|
||||
size_t write_len;
|
||||
@@ -113,6 +116,12 @@ void tcp_conn_set_flushed(struct tcp_conn* tc, void (*on_flushed)(struct tcp_con
|
||||
// Принудительная остановка чтения: убирает EPOLLIN и отменяет read_waiter.
|
||||
void tcp_conn_pause_read(struct tcp_conn* tc);
|
||||
|
||||
// Таймаут установления соединения (мс, 0 = без таймаута). Если соединение ещё не
|
||||
// установлено (connected=0), взводит таймер; по истечении вызывает
|
||||
// tcp_conn_handle_error(ETIMEDOUT) → on_error. Таймер гасится при успешном connect
|
||||
// и при tcp_conn_destroy.
|
||||
void tcp_conn_set_connect_timeout(struct tcp_conn* tc, int timeout_ms);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user