|
|
|
|
@ -119,10 +119,11 @@ static void router_send_close_to_service(struct ETCP_ROUTER_CONN* rconn) {
|
|
|
|
|
if (!cb) return; |
|
|
|
|
struct ll_entry* e = queue_entry_new(0); |
|
|
|
|
if (!e) return; |
|
|
|
|
e->dgram = u_malloc(1); |
|
|
|
|
e->dgram = u_malloc(9); |
|
|
|
|
if (!e->dgram) { queue_entry_free(e); return; } |
|
|
|
|
e->dgram[0] = rconn->svc_id; |
|
|
|
|
e->len = 1; |
|
|
|
|
memcpy(e->dgram + 1, &rconn->remote_node_id, 8); |
|
|
|
|
e->len = 9; |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router_close_svc: svc_id=%u remote=%016llx", |
|
|
|
|
rconn->svc_id, (unsigned long long)rconn->remote_node_id); |
|
|
|
|
cb(NULL, e); |
|
|
|
|
@ -380,7 +381,8 @@ static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry)
|
|
|
|
|
// Обнаружение перезапуска peer'а: новый sess_id или START-флаг
|
|
|
|
|
{ |
|
|
|
|
uint8_t incoming_sess = (hdr->flags >> ROUTER_SESS_ID_SHIFT) & 0x3; |
|
|
|
|
if (pl_len > 0 && (incoming_sess != rconn->peer_sess_id || (hdr->flags & ROUTER_FLAG_START))) { |
|
|
|
|
if (pl_len > 0 && (incoming_sess != rconn->peer_sess_id || |
|
|
|
|
((hdr->flags & ROUTER_FLAG_START) && rconn->rx_seq > 0))) { |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, |
|
|
|
|
"router: peer restart sess_id=%u→%u svc_id=%u from %016llx", |
|
|
|
|
rconn->peer_sess_id, incoming_sess, hdr->svc_id, |
|
|
|
|
@ -441,7 +443,7 @@ static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry)
|
|
|
|
|
if (seq == rconn->rx_seq) |
|
|
|
|
router_try_assembly(rconn, conn); |
|
|
|
|
|
|
|
|
|
if (!rconn->consumer_ack) router_schedule_ack(rconn); |
|
|
|
|
router_schedule_ack(rconn); |
|
|
|
|
queue_dgram_free(entry); queue_entry_free(entry); |
|
|
|
|
} else { |
|
|
|
|
// ========== Транзит ==========
|
|
|
|
|
@ -597,40 +599,65 @@ void etcp_router_waiter_cancel(struct UTUN_INSTANCE* inst, uint64_t peer_node_id
|
|
|
|
|
queue_waiter_cancel(conn->normalizer->input, h); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void etcp_router_consumer_ack(struct UTUN_INSTANCE* inst, uint64_t remote_node_id, uint8_t svc_id) { |
|
|
|
|
struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(inst, remote_node_id, svc_id); |
|
|
|
|
if (!rconn) return; |
|
|
|
|
rconn->consumer_ack = 1; |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_ETCPROUTE, "CONSUMER_ACK: svc_id=%u rx_seq=%u → %016llx", |
|
|
|
|
svc_id, rconn->rx_seq, (unsigned long long)remote_node_id); |
|
|
|
|
router_ack_do_send(rconn); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void etcp_router_conn_restart(struct UTUN_INSTANCE* inst, uint64_t remote_node_id, uint8_t svc_id) { |
|
|
|
|
struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, remote_node_id, svc_id); |
|
|
|
|
if (!rconn) return; |
|
|
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router_restart: svc_id=%u remote=%016llx — notifying service", |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router_restart: svc_id=%u remote=%016llx — resetting local state", |
|
|
|
|
svc_id, (unsigned long long)remote_node_id); |
|
|
|
|
|
|
|
|
|
rconn->sess_id = (rconn->sess_id + 1) & 0x3; |
|
|
|
|
rconn->start_sent = 0; |
|
|
|
|
|
|
|
|
|
etcp_recv_fn cb = inst->router_bindings.callbacks[svc_id]; |
|
|
|
|
if (cb) { |
|
|
|
|
struct ll_entry* e = queue_entry_new(0); |
|
|
|
|
if (e) { |
|
|
|
|
e->dgram = u_malloc(10); |
|
|
|
|
e->dgram = u_malloc(9); |
|
|
|
|
if (e->dgram) { |
|
|
|
|
e->dgram[0] = svc_id; |
|
|
|
|
e->dgram[1] = 0xFE; // RESTART subcmd
|
|
|
|
|
memcpy(e->dgram + 2, &remote_node_id, 8); |
|
|
|
|
e->len = 10; |
|
|
|
|
memcpy(e->dgram + 1, &remote_node_id, 8); |
|
|
|
|
e->len = 9; |
|
|
|
|
cb(NULL, e); |
|
|
|
|
} else { queue_entry_free(e); } |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
router_close_and_notify(rconn); |
|
|
|
|
|
|
|
|
|
struct ll_entry* f; |
|
|
|
|
if (rconn->send_q) { |
|
|
|
|
while ((f = queue_data_get(rconn->send_q)) != NULL) { queue_dgram_free(f); queue_entry_free(f); } |
|
|
|
|
queue_free(rconn->send_q); |
|
|
|
|
} |
|
|
|
|
if (rconn->recv_q) { |
|
|
|
|
while ((f = queue_data_get(rconn->recv_q)) != NULL) { queue_dgram_free(f); queue_entry_free(f); } |
|
|
|
|
queue_free(rconn->recv_q); |
|
|
|
|
} |
|
|
|
|
rconn->send_q = queue_new(inst->ua, 0, 0, 0, "router_send_q"); |
|
|
|
|
rconn->recv_q = queue_new(inst->ua, ROUTER_RECVQ_HASH_SIZE, 0, 4, "router_recv_q"); |
|
|
|
|
queue_set_threshold(rconn->send_q, ROUTER_MAX_SEND_Q_PACKETS / 2, 0); |
|
|
|
|
|
|
|
|
|
rconn->tx_seq = 0; |
|
|
|
|
rconn->rx_seq = 0; |
|
|
|
|
rconn->tx_acked = 0; |
|
|
|
|
rconn->last_sent_ack_seq = 0; |
|
|
|
|
rconn->sess_id = (rconn->sess_id + 1) & 0x3; |
|
|
|
|
rconn->peer_sess_id = 0; |
|
|
|
|
rconn->start_sent = 0; |
|
|
|
|
rconn->send_blocked = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void etcp_router_on_send_ready(struct UTUN_INSTANCE* inst, uint64_t node_id, uint8_t svc_id, |
|
|
|
|
struct queue_waiter_handle* h, |
|
|
|
|
queue_threshold_callback_fn callback, void* arg) { |
|
|
|
|
if (!inst || !h) return; |
|
|
|
|
struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, node_id, svc_id); |
|
|
|
|
if (!rconn || !rconn->send_q) return; |
|
|
|
|
queue_waiter_wait(rconn->send_q, h, callback, arg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void etcp_router_cancel_send_ready(struct UTUN_INSTANCE* inst, uint64_t node_id, uint8_t svc_id, |
|
|
|
|
struct queue_waiter_handle* h) { |
|
|
|
|
if (!inst || !h) return; |
|
|
|
|
struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, node_id, svc_id); |
|
|
|
|
if (!rconn || !rconn->send_q) return; |
|
|
|
|
queue_waiter_cancel(rconn->send_q, h); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ====================================================================
|
|
|
|
|
@ -653,7 +680,6 @@ struct ETCP_ROUTER_CONN* etcp_router_conn_get(struct UTUN_INSTANCE* inst,
|
|
|
|
|
rconn->rx_seq = 0; |
|
|
|
|
rconn->tx_acked = 0; |
|
|
|
|
rconn->last_sent_ack_seq = 0; |
|
|
|
|
rconn->consumer_ack = 0; |
|
|
|
|
rconn->last_ack_sent_tb = 0; |
|
|
|
|
rconn->inst = inst; |
|
|
|
|
rconn->ack_timer = NULL; |
|
|
|
|
|