You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
97 lines
4.9 KiB
97 lines
4.9 KiB
#include <assert.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include "utun_instance.h" |
|
#include "config_parser.h" |
|
#include "routing_layer/topo_group.h" |
|
#include "transport_layer/etcp.h" |
|
#include "transport_layer/etcp_connections.h" |
|
#include "transport_layer/node_conn_direct.h" |
|
#include "../lib/u_async.h" |
|
#include "../lib/debug_config.h" |
|
|
|
static int links(struct ETCP_CONN* conn) { |
|
int count = 0; |
|
for (struct ETCP_LINK* link = conn->links; link; link = link->next) count++; |
|
return count; |
|
} |
|
|
|
static void endpoint(struct CFG_CLIENT_LINK* link, struct CFG_SERVER* local, int port) { |
|
memset(link, 0, sizeof(*link)); link->local_srv = local; |
|
struct sockaddr_in* addr = (struct sockaddr_in*)&link->remote_addr; |
|
addr->sin_family = AF_INET; addr->sin_addr.s_addr = htonl(0x7f000001); addr->sin_port = htons((uint16_t)port); |
|
} |
|
|
|
int main(void) { |
|
debug_config_init(); debug_set_level(DEBUG_LEVEL_INFO); |
|
utun_instance_set_tun_init_enabled(0); |
|
struct UASYNC* ua = uasync_create(); assert(ua); |
|
struct UTUN_INSTANCE* inst = utun_instance_create_from_str(ua, |
|
"[global]\n" |
|
"my_private_key=704f2e012c8fa8768130cb0f988a997dccb628372bc5ceccacc78dcbfec5916f\n" |
|
"my_public_key=b3193173def895bd0fcea6f86af077c7d77216f10395275f627ac18242ec0f01\n" |
|
"[server: udp]\naddr=127.0.0.1:0\ntype=public\n" |
|
"[server: tcp]\naddr=127.0.0.1:0\ntype=public\ntransport=tcp\n"); |
|
assert(inst && utun_instance_init(inst) >= 0); |
|
struct CFG_SERVER *udp = NULL, *tcp = NULL; |
|
for (struct CFG_SERVER* s = inst->config->servers; s; s = s->next) { |
|
if (!strcmp(s->name, "udp")) udp = s; |
|
if (!strcmp(s->name, "tcp")) tcp = s; |
|
} |
|
assert(udp && tcp); |
|
struct CFG_CLIENT client = { .name = "peer" }; |
|
struct SC_MYKEYS peer; assert(sc_generate_keypair(&peer) == SC_OK); |
|
for (int i = 0; i < 32; i++) snprintf(client.peer_public_key_hex + i * 2, 3, "%02x", peer.public_key[i]); |
|
struct CFG_CLIENT_LINK first, second, third; |
|
endpoint(&first, udp, 9); endpoint(&second, udp, 10); endpoint(&third, tcp, 11); |
|
first.next = &second; second.next = &third; client.links = &first; |
|
assert(init_client_connections(inst, &client) == 0); |
|
assert(inst->config_conn_handles && !inst->config_conn_handles->next); |
|
struct ETCP_CONN* conn = topo_group_peer_conn(inst->config_conn_handles->request); |
|
assert(conn && links(conn) == 3 && !conn->fin_wait); |
|
struct NODE_CONN_DIRECT* chat = NULL; |
|
assert(node_conn_direct_open(inst, conn->peer_node_id, NULL, NULL, &chat, NULL) == NCD_REUSED); |
|
assert(init_client_connections(inst, &client) == 0); |
|
assert(topo_group_peer_conn(inst->config_conn_handles->request) == conn && links(conn) == 3 && !conn->fin_wait); |
|
|
|
/* Ошибка нового набора не освобождает предыдущие handles. */ |
|
struct CFG_CLIENT invalid = { .name = "invalid", .peer_public_key_hex = "not-a-key" }; |
|
client.next = &invalid; |
|
struct CONFIG_CONN_HANDLE* previous = inst->config_conn_handles; |
|
assert(init_client_connections(inst, &client) < 0 && inst->config_conn_handles == previous); |
|
assert(node_conn_direct_get_conn(chat) == conn && !conn->fin_wait); |
|
client.next = NULL; |
|
|
|
/* REALITY идёт по тому же NCD пути; полное SNI не обрезается. */ |
|
client.links = &third; client.reality_enabled = 1; |
|
reality_client_config_set_defaults(&client.reality); |
|
memcpy(client.reality.server_static_pubkey, peer.public_key, 32); |
|
memset(client.reality.server_name, 'a', 180); client.reality.server_name[180] = 0; |
|
assert(init_client_connections(inst, &client) == 0); |
|
assert(links(conn) == 3); |
|
struct ETCP_LINK* real = NULL; |
|
for (struct ETCP_LINK* link = conn->links; link; link = link->next) if (link->is_tcp) real = link; |
|
assert(real && real->reality_set && !strcmp(real->reality.server_name, client.reality.server_name)); |
|
assert(init_client_connections(inst, &client) == 0 && links(conn) == 3); |
|
assert(init_client_connections(inst, NULL) == 0 && !inst->config_conn_handles); |
|
assert(node_conn_direct_get_conn(chat) == conn && !conn->fin_wait); |
|
node_conn_direct_force_close(chat); |
|
uasync_poll(ua, 0); |
|
/* Клиентский TCP/REALITY не требует локального TCP listen-сокета. */ |
|
struct ETCP_SOCKET* sock = inst->etcp_sockets; |
|
while (sock) { |
|
struct ETCP_SOCKET* next = sock->next; |
|
if (sock->is_tcp) etcp_socket_remove(sock); |
|
sock = next; |
|
} |
|
third.local_srv = NULL; |
|
assert(init_client_connections(inst, &client) == 0); |
|
conn = topo_group_peer_conn(inst->config_conn_handles->request); |
|
assert(conn && links(conn) == 1 && conn->links->is_tcp && !conn->links->conn); |
|
assert(conn->links->reality_set && !strcmp(conn->links->reality.server_name, client.reality.server_name)); |
|
assert(init_client_connections(inst, NULL) == 0); |
|
inst->running = 0; utun_instance_destroy(inst); |
|
uasync_poll(ua, 0); |
|
uasync_destroy(ua, 0); |
|
return 0; |
|
}
|
|
|