|
|
|
|
@ -33,7 +33,7 @@ static void rp_sock_error_cb(socket_t sock, void* arg);
|
|
|
|
|
static void rp_conn_free(struct remote_proxy_conn* rc); |
|
|
|
|
|
|
|
|
|
static int rp_send_msg(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t subcmd, |
|
|
|
|
uint64_t sid, const uint8_t* data, size_t len) { |
|
|
|
|
uint64_t sid, uint16_t seq, const uint8_t* data, size_t len) { |
|
|
|
|
struct ll_entry* e = queue_entry_new(0); |
|
|
|
|
if (!e) return -1; |
|
|
|
|
e->dgram = u_malloc(TCP_PROXY_HDR_SIZE + len); |
|
|
|
|
@ -41,6 +41,7 @@ static int rp_send_msg(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t subcmd,
|
|
|
|
|
e->dgram[0] = ETCP_ID_TCP_PROXY; |
|
|
|
|
e->dgram[1] = subcmd; |
|
|
|
|
memcpy(e->dgram + 2, &sid, 8); |
|
|
|
|
memcpy(e->dgram + 10, &seq, 2); |
|
|
|
|
if (len > 0) memcpy(e->dgram + TCP_PROXY_HDR_SIZE, data, len); |
|
|
|
|
e->len = TCP_PROXY_HDR_SIZE + len; |
|
|
|
|
return etcp_route_send(inst, dst, e); |
|
|
|
|
@ -50,7 +51,7 @@ static int rp_send_connected(struct UTUN_INSTANCE* inst, uint64_t dst, uint64_t
|
|
|
|
|
uint16_t local_port, uint8_t status) { |
|
|
|
|
uint8_t buf[3]; |
|
|
|
|
memcpy(buf, &local_port, 2); buf[2] = status; |
|
|
|
|
return rp_send_msg(inst, dst, TCP_PROXY_SUBCMD_CONNECTED, sid, buf, 3); |
|
|
|
|
return rp_send_msg(inst, dst, TCP_PROXY_SUBCMD_CONNECTED, sid, 0, buf, 3); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ====================================================================
|
|
|
|
|
@ -62,12 +63,15 @@ static void rp_sock_read_cb(socket_t sock, void* arg) {
|
|
|
|
|
uint8_t buf[8192]; ssize_t n = recv(rc->sock, buf, sizeof(buf), 0); |
|
|
|
|
if (n > 0) { |
|
|
|
|
struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL; |
|
|
|
|
if (inst) rp_send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_DATA, rc->stream_id, buf, (size_t)n); |
|
|
|
|
if (inst) { |
|
|
|
|
rp_send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_DATA, rc->stream_id, rc->send_seq, buf, (size_t)n); |
|
|
|
|
rc->send_seq++; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if (n == 0) DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "remote_proxy: EOF stream=%016llx", (unsigned long long)rc->stream_id); |
|
|
|
|
else DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: recv error %s", strerror(errno)); |
|
|
|
|
struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL; |
|
|
|
|
if (inst) rp_send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_CLOSE, rc->stream_id, NULL, 0); |
|
|
|
|
if (inst) rp_send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_CLOSE, rc->stream_id, 0, NULL, 0); |
|
|
|
|
rc->connected = -1; |
|
|
|
|
rp_conn_free(rc); |
|
|
|
|
} |
|
|
|
|
@ -105,7 +109,7 @@ static void rp_sock_error_cb(socket_t sock, void* arg) {
|
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: socket error stream=%016llx", (unsigned long long)(rc ? rc->stream_id : 0)); |
|
|
|
|
rc->connected = -1; |
|
|
|
|
struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL; |
|
|
|
|
if (inst) rp_send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_CLOSE, rc->stream_id, NULL, 0); |
|
|
|
|
if (inst) rp_send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_CLOSE, rc->stream_id, 0, NULL, 0); |
|
|
|
|
rp_conn_free(rc); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -162,6 +166,7 @@ int remote_proxy_handle_connect(struct UTUN_INSTANCE* inst, struct ll_entry* ent
|
|
|
|
|
rc->ctx = ctx; rc->stream_id = stream_id; rc->peer_node_id = src_node_id; |
|
|
|
|
memcpy(rc->dest_ip, dest_ip, 4); rc->dest_port = dest_port; |
|
|
|
|
rc->ua = inst->ua; rc->sock = SOCKET_INVALID; |
|
|
|
|
rc->send_seq = 0; rc->recv_seq_init = 0; |
|
|
|
|
|
|
|
|
|
rc->sock = socket(AF_INET, SOCK_STREAM, 0); |
|
|
|
|
if (rc->sock == SOCKET_INVALID) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: socket() failed"); rp_conn_free(rc); queue_entry_free(entry); queue_dgram_free(entry); return -1; } |
|
|
|
|
@ -191,6 +196,23 @@ int remote_proxy_handle_data(struct UTUN_INSTANCE* inst, struct ll_entry* entry,
|
|
|
|
|
struct remote_proxy_ctx* ctx = &inst->remote_proxy; |
|
|
|
|
struct remote_proxy_conn* rc = remote_proxy_find_conn(ctx, stream_id); |
|
|
|
|
if (!rc || rc->sock == SOCKET_INVALID || rc->connected != 1) { queue_entry_free(entry); queue_dgram_free(entry); return -1; } |
|
|
|
|
uint16_t seq; memcpy(&seq, entry->dgram + 10, 2); |
|
|
|
|
if (!rc->recv_seq_init) { |
|
|
|
|
rc->recv_last_seq = seq; rc->recv_seq_init = 1; |
|
|
|
|
} else { |
|
|
|
|
int16_t delta = (int16_t)(seq - rc->recv_last_seq); |
|
|
|
|
if (delta <= 0) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_SOCKET, "remote_proxy: duplicate DATA seq=%u stream=%016llx, discard", seq, (unsigned long long)stream_id); |
|
|
|
|
queue_entry_free(entry); queue_dgram_free(entry); return 0; |
|
|
|
|
} |
|
|
|
|
if (delta > 1) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: seq gap seq=%u last=%u stream=%016llx, tearing down", seq, rc->recv_last_seq, (unsigned long long)stream_id); |
|
|
|
|
rp_send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_CLOSE, rc->stream_id, 0, NULL, 0); |
|
|
|
|
rp_conn_free(rc); |
|
|
|
|
queue_entry_free(entry); queue_dgram_free(entry); return -1; |
|
|
|
|
} |
|
|
|
|
rc->recv_last_seq = seq; |
|
|
|
|
} |
|
|
|
|
size_t data_len = entry->len - TCP_PROXY_HDR_SIZE; |
|
|
|
|
uint8_t* data = entry->dgram + TCP_PROXY_HDR_SIZE; |
|
|
|
|
ssize_t n = send(rc->sock, data, data_len, MSG_NOSIGNAL); |
|
|
|
|
|