12 changed files with 393 additions and 798 deletions
@ -1,751 +0,0 @@
|
||||
#include "etcp_connections.h" |
||||
#include <arpa/inet.h> |
||||
#include "routing.h" |
||||
#include "utun_instance.h" |
||||
#include "crc32.h" |
||||
#include "etcp.h" |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <time.h> |
||||
|
||||
// Forward declaration
|
||||
struct utun_instance; |
||||
|
||||
// Бинарный поиск линка по ip_port_hash
|
||||
static int find_link_index(struct ETCP_CONNECTIONS* conns, uint32_t hash) { |
||||
if (!conns || conns->num_channels == 0) return -1; |
||||
|
||||
int left = 0; |
||||
int right = conns->num_channels - 1; |
||||
|
||||
while (left <= right) { |
||||
int mid = left + (right - left) / 2; |
||||
if (conns->links[mid]->ip_port_hash == hash) { |
||||
return mid; |
||||
} else if (conns->links[mid]->ip_port_hash < hash) { |
||||
left = mid + 1; |
||||
} else { |
||||
right = mid - 1; |
||||
} |
||||
} |
||||
|
||||
return -(left + 1); |
||||
} |
||||
|
||||
// Реалокация массива линков с увеличением в 2 раза
|
||||
static int realloc_links(struct ETCP_CONNECTIONS* conns) { |
||||
size_t new_max = conns->max_channels == 0 ? 8 : conns->max_channels * 2; |
||||
struct ETCP_LINK** new_links = realloc(conns->links, new_max * sizeof(struct ETCP_LINK*)); |
||||
if (!new_links) return -1; |
||||
|
||||
conns->links = new_links; |
||||
conns->max_channels = new_max; |
||||
return 0; |
||||
} |
||||
|
||||
// Вставка линка в отсортированный массив
|
||||
static int insert_link(struct ETCP_CONNECTIONS* conns, struct ETCP_LINK* link) { |
||||
if (!conns || !link) return -1; |
||||
|
||||
if (conns->num_channels >= conns->max_channels) { |
||||
if (realloc_links(conns) < 0) return -1; |
||||
} |
||||
|
||||
int idx = find_link_index(conns, link->ip_port_hash); |
||||
if (idx >= 0) return -1; |
||||
|
||||
idx = -(idx + 1); |
||||
|
||||
if (idx < (int)conns->num_channels) { |
||||
memmove(&conns->links[idx + 1], &conns->links[idx],
|
||||
(conns->num_channels - idx) * sizeof(struct ETCP_LINK*)); |
||||
} |
||||
|
||||
conns->links[idx] = link; |
||||
conns->num_channels++; |
||||
return 0; |
||||
} |
||||
|
||||
// Удаление линка из массива
|
||||
static void remove_link(struct ETCP_CONNECTIONS* conns, uint32_t hash) { |
||||
if (!conns || conns->num_channels == 0) return; |
||||
|
||||
int idx = find_link_index(conns, hash); |
||||
if (idx < 0) return; |
||||
|
||||
if (idx < (int)conns->num_channels - 1) { |
||||
memmove(&conns->links[idx], &conns->links[idx + 1],
|
||||
(conns->num_channels - idx - 1) * sizeof(struct ETCP_LINK*)); |
||||
} |
||||
|
||||
conns->num_channels--; |
||||
} |
||||
|
||||
struct ETCP_CONNECTIONS* etcp_connections_init(etcp_socket_t* socket) { |
||||
if (!socket) return NULL; |
||||
|
||||
struct ETCP_CONNECTIONS* conns = calloc(1, sizeof(struct ETCP_CONNECTIONS)); |
||||
if (!conns) return NULL; |
||||
|
||||
memcpy(&conns->socket, socket, sizeof(struct ETCP_SOCKET)); |
||||
return conns; |
||||
} |
||||
|
||||
void etcp_connections_destroy(struct ETCP_CONNECTIONS* conns) { |
||||
if (!conns) return; |
||||
|
||||
for (size_t i = 0; i < conns->num_channels; i++) { |
||||
etcp_link_close(conns->links[i]); |
||||
} |
||||
|
||||
free(conns->links); |
||||
free(conns); |
||||
} |
||||
|
||||
struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, etcp_socket_t* socket,
|
||||
const struct sockaddr* remote_addr, socklen_t addr_len) { |
||||
if (!etcp || !socket || !remote_addr || addr_len == 0) return NULL; |
||||
|
||||
struct ETCP_LINK* link = calloc(1, sizeof(struct ETCP_LINK)); |
||||
if (!link) return NULL; |
||||
|
||||
link->socket = (struct ETCP_SOCKET*)socket; |
||||
link->etcp = etcp; |
||||
memcpy(&link->remote_addr, remote_addr, addr_len); |
||||
link->remote_addr_len = addr_len; |
||||
link->last_activity = time(NULL); |
||||
|
||||
uint8_t* addr_bytes = (uint8_t*)remote_addr; |
||||
link->ip_port_hash = crc32(0, addr_bytes, addr_len); |
||||
|
||||
return link; |
||||
} |
||||
|
||||
void etcp_link_close(struct ETCP_LINK* link) { |
||||
if (!link) return; |
||||
free(link); |
||||
} |
||||
|
||||
int etcp_input(packet_buffer_t* pkt, etcp_socket_t* socket, struct ETCP_CONNECTIONS* conns) { |
||||
if (!pkt || !socket || !conns) return -1; |
||||
|
||||
if (pkt->metadata.data_len < 1) return -1; |
||||
|
||||
uint8_t* data = pkt->data; |
||||
uint8_t cmd = data[0]; |
||||
|
||||
struct sockaddr* src_addr = packet_remote_addr(pkt); |
||||
socklen_t addr_len = sizeof(struct sockaddr_storage); |
||||
|
||||
if (cmd == ETCP_INIT_REQUEST) { |
||||
if (pkt->metadata.data_len < 1 + 8 + SC_PUBKEY_SIZE + 2 + 2) { |
||||
return -1; |
||||
} |
||||
|
||||
struct ETCP_LINK* link = etcp_link_find_by_addr(conns, src_addr, addr_len); |
||||
if (link) { |
||||
if (link->initialized) { |
||||
etcp_conn_reset(link->etcp); |
||||
} |
||||
etcp_link_remove_from_connections(conns, link); |
||||
etcp_link_close(link); |
||||
} |
||||
|
||||
link = etcp_link_new(NULL, socket, src_addr, addr_len); |
||||
if (!link) return -1; |
||||
|
||||
uint8_t* p = &data[1]; |
||||
link->peer_node_id = 0; |
||||
memcpy(&link->peer_node_id, p, 8); |
||||
p += 8; |
||||
|
||||
memcpy(link->peer_public_key, p, SC_PUBKEY_SIZE); |
||||
link->has_peer_key = 1; |
||||
p += SC_PUBKEY_SIZE; |
||||
|
||||
uint16_t peer_mtu = ntohs(*(uint16_t*)p); |
||||
p += 2; |
||||
uint16_t peer_keepalive = ntohs(*(uint16_t*)p); |
||||
|
||||
link->mtu = peer_mtu; |
||||
link->keepalive_interval = peer_keepalive; |
||||
|
||||
etcp_link_add_to_connections(conns, link); |
||||
|
||||
return etcp_link_send_init_response(link, 1500, 30); |
||||
} |
||||
|
||||
struct ETCP_LINK* link = etcp_link_find_by_addr(conns, src_addr, addr_len); |
||||
if (!link) { |
||||
struct ETCP_LINK* temp_link = etcp_link_new(NULL, socket, src_addr, addr_len); |
||||
if (temp_link) { |
||||
etcp_link_send_reset(temp_link); |
||||
etcp_link_close(temp_link); |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
if (!link->initialized) { |
||||
switch (cmd) { |
||||
case ETCP_INIT_RESPONSE: |
||||
if (pkt->metadata.data_len < 1 + 8 + 2 + 2) return -1; |
||||
|
||||
link->peer_node_id = 0; |
||||
memcpy(&link->peer_node_id, &data[1], 8); |
||||
|
||||
link->mtu = ntohs(*(uint16_t*)&data[1 + 8]); |
||||
link->keepalive_interval = ntohs(*(uint16_t*)&data[1 + 8 + 2]); |
||||
link->initialized = 1; |
||||
break; |
||||
|
||||
case ETCP_CHANNEL_INIT: |
||||
if (pkt->metadata.data_len < 1 + 8 + 2) return -1; |
||||
|
||||
link->peer_node_id = 0; |
||||
memcpy(&link->peer_node_id, &data[1], 8); |
||||
link->keepalive_interval = ntohs(*(uint16_t*)&data[1 + 8]); |
||||
|
||||
return etcp_link_send_channel_response(link); |
||||
|
||||
case ETCP_CHANNEL_RESPONSE: |
||||
if (pkt->metadata.data_len < 1 + 8) return -1; |
||||
|
||||
link->peer_node_id = 0; |
||||
memcpy(&link->peer_node_id, &data[1], 8); |
||||
link->initialized = 1; |
||||
break; |
||||
|
||||
case ETCP_RESET: |
||||
etcp_link_remove_from_connections(conns, link); |
||||
etcp_link_close(link); |
||||
break; |
||||
|
||||
default: |
||||
etcp_link_send_reset(link); |
||||
return -1; |
||||
} |
||||
} else { |
||||
if (cmd >= 0x02 && cmd <= 0x06) { |
||||
etcp_link_send_reset(link); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
link->last_activity = time(NULL); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int etcp_link_init(struct ETCP_CONN* etcp, struct ETCP_LINK* link) { |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
|
||||
int etcp_link_send(struct ETCP_CONN* etcp, struct ETCP_LINK* link,
|
||||
const uint8_t* data, size_t len) { |
||||
if (!etcp || !link || !data || len == 0) return -1; |
||||
|
||||
link->last_activity = time(NULL); |
||||
|
||||
return etcp_socket_send((etcp_socket_t*)link->socket, data, len,
|
||||
(struct sockaddr*)&link->remote_addr); |
||||
} |
||||
|
||||
int etcp_link_send_init(struct ETCP_LINK* link, int mtu, uint16_t keepalive_interval) { |
||||
if (!link || mtu <= 0 || mtu > 65535) return -1; |
||||
|
||||
uint8_t packet[1 + 8 + SC_PUBKEY_SIZE + 2 + 2]; |
||||
uint8_t* p = packet; |
||||
|
||||
*p++ = ETCP_INIT_REQUEST; |
||||
|
||||
uint64_t node_id = link->etcp->node_id; |
||||
memcpy(p, &node_id, 8); |
||||
p += 8; |
||||
|
||||
sc_context_t* sc = link->etcp->crypto_ctx; |
||||
if (!sc || !sc->initialized) return -1; |
||||
|
||||
memcpy(p, sc->public_key, SC_PUBKEY_SIZE); |
||||
p += SC_PUBKEY_SIZE; |
||||
|
||||
uint16_t mtu_be = htons(mtu); |
||||
memcpy(p, &mtu_be, 2); |
||||
p += 2; |
||||
|
||||
uint16_t keepalive_be = htons(keepalive_interval); |
||||
memcpy(p, &keepalive_be, 2); |
||||
p += 2; |
||||
|
||||
link->mtu = mtu; |
||||
link->keepalive_interval = keepalive_interval; |
||||
|
||||
return etcp_socket_send((etcp_socket_t*)link->socket, packet, sizeof(packet),
|
||||
(struct sockaddr*)&link->remote_addr); |
||||
} |
||||
|
||||
int etcp_link_send_init_response(struct ETCP_LINK* link, int mtu, uint16_t keepalive_interval) { |
||||
if (!link || mtu <= 0 || mtu > 65535) return -1; |
||||
|
||||
uint8_t packet[1 + 8 + 2 + 2]; |
||||
uint8_t* p = packet; |
||||
|
||||
*p++ = ETCP_INIT_RESPONSE; |
||||
|
||||
uint64_t node_id = link->etcp->node_id; |
||||
memcpy(p, &node_id, 8); |
||||
p += 8; |
||||
|
||||
uint16_t mtu_be = htons(mtu); |
||||
memcpy(p, &mtu_be, 2); |
||||
p += 2; |
||||
|
||||
uint16_t keepalive_be = htons(keepalive_interval); |
||||
memcpy(p, &keepalive_be, 2); |
||||
p += 2; |
||||
|
||||
link->mtu = mtu; |
||||
link->keepalive_interval = keepalive_interval; |
||||
link->initialized = 1; |
||||
|
||||
return etcp_socket_send((etcp_socket_t*)link->socket, packet, sizeof(packet),
|
||||
(struct sockaddr*)&link->remote_addr); |
||||
} |
||||
|
||||
int etcp_link_send_channel_init(struct ETCP_LINK* link, uint16_t keepalive_interval) { |
||||
if (!link) return -1; |
||||
|
||||
uint8_t packet[1 + 8 + 2]; |
||||
uint8_t* p = packet; |
||||
|
||||
*p++ = ETCP_CHANNEL_INIT; |
||||
|
||||
uint64_t node_id = link->etcp->node_id; |
||||
memcpy(p, &node_id, 8); |
||||
p += 8; |
||||
|
||||
uint16_t keepalive_be = htons(keepalive_interval); |
||||
memcpy(p, &keepalive_be, 2); |
||||
p += 2; |
||||
|
||||
link->keepalive_interval = keepalive_interval; |
||||
|
||||
return etcp_socket_send((etcp_socket_t*)link->socket, packet, sizeof(packet),
|
||||
(struct sockaddr*)&link->remote_addr); |
||||
} |
||||
|
||||
int etcp_link_send_channel_response(struct ETCP_LINK* link) { |
||||
if (!link) return -1; |
||||
|
||||
uint8_t packet[1 + 8]; |
||||
uint8_t* p = packet; |
||||
|
||||
*p++ = ETCP_CHANNEL_RESPONSE; |
||||
|
||||
uint64_t node_id = link->etcp->node_id; |
||||
memcpy(p, &node_id, 8); |
||||
p += 8; |
||||
|
||||
link->initialized = 1; |
||||
|
||||
return etcp_socket_send((etcp_socket_t*)link->socket, packet, sizeof(packet),
|
||||
(struct sockaddr*)&link->remote_addr); |
||||
} |
||||
|
||||
int etcp_link_send_reset(struct ETCP_LINK* link) { |
||||
if (!link) return -1; |
||||
|
||||
uint8_t packet[1] = {ETCP_RESET}; |
||||
|
||||
return etcp_socket_send((etcp_socket_t*)link->socket, packet, sizeof(packet),
|
||||
(struct sockaddr*)&link->remote_addr); |
||||
} |
||||
|
||||
struct ETCP_LINK* etcp_link_find_by_addr(struct ETCP_CONNECTIONS* conns,
|
||||
const struct sockaddr* addr, socklen_t addr_len) { |
||||
if (!conns || !addr || addr_len == 0) return NULL; |
||||
|
||||
uint32_t hash = crc32(0, (uint8_t*)addr, addr_len); |
||||
int idx = find_link_index(conns, hash); |
||||
|
||||
if (idx >= 0) { |
||||
return conns->links[idx]; |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
int etcp_link_add_to_connections(struct ETCP_CONNECTIONS* conns, struct ETCP_LINK* link) { |
||||
if (!conns || !link) return -1; |
||||
return insert_link(conns, link); |
||||
} |
||||
|
||||
void etcp_link_remove_from_connections(struct ETCP_CONNECTIONS* conns, struct ETCP_LINK* link) { |
||||
if (!conns || !link) return; |
||||
remove_link(conns, link->ip_port_hash); |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
// SOCKET FUNCTIONS (moved from etcp_sockets.c)
|
||||
#include <unistd.h> |
||||
#include <fcntl.h> |
||||
#include <errno.h> |
||||
#include <arpa/inet.h> |
||||
|
||||
etcp_socket_t* etcp_socket_create(struct ETCP_CONN* etcp, const char* bind_addr, uint16_t port) { |
||||
if (!etcp) return NULL; |
||||
|
||||
etcp_socket_t* sock = calloc(1, sizeof(etcp_socket_t)); |
||||
if (!sock) return NULL; |
||||
|
||||
sock->etcp = etcp; |
||||
sock->socket_id = (uint32_t)(uintptr_t)sock; |
||||
|
||||
sock->fd = socket(AF_INET, SOCK_DGRAM, 0); |
||||
if (sock->fd < 0) { |
||||
free(sock); |
||||
return NULL; |
||||
} |
||||
|
||||
int flags = fcntl(sock->fd, F_GETFL, 0); |
||||
fcntl(sock->fd, F_SETFL, flags | O_NONBLOCK); |
||||
|
||||
struct sockaddr_in* addr = (struct sockaddr_in*)&sock->local_addr; |
||||
addr->sin_family = AF_INET; |
||||
addr->sin_port = htons(port); |
||||
sock->local_addr_len = sizeof(struct sockaddr_in); |
||||
|
||||
if (bind_addr) { |
||||
inet_pton(AF_INET, bind_addr, &addr->sin_addr); |
||||
} else { |
||||
addr->sin_addr.s_addr = INADDR_ANY; |
||||
} |
||||
|
||||
if (bind(sock->fd, (struct sockaddr*)addr, sock->local_addr_len) < 0) { |
||||
close(sock->fd); |
||||
free(sock); |
||||
return NULL; |
||||
} |
||||
|
||||
if (getsockname(sock->fd, (struct sockaddr*)addr, &sock->local_addr_len) < 0) { |
||||
close(sock->fd); |
||||
free(sock); |
||||
return NULL; |
||||
} |
||||
|
||||
return sock; |
||||
} |
||||
|
||||
void etcp_socket_destroy(etcp_socket_t* sock) { |
||||
if (!sock) return; |
||||
|
||||
if (sock->fd >= 0) { |
||||
close(sock->fd); |
||||
} |
||||
|
||||
free(sock); |
||||
} |
||||
|
||||
int etcp_socket_send(etcp_socket_t* sock, const uint8_t* data, size_t len, const struct sockaddr* to_addr) { |
||||
if (!sock || sock->fd < 0 || !data || !to_addr) { |
||||
return -1; |
||||
} |
||||
|
||||
socklen_t addr_len = (to_addr->sa_family == AF_INET) ?
|
||||
sizeof(struct sockaddr_in) :
|
||||
sizeof(struct sockaddr_in6); |
||||
|
||||
return sendto(sock->fd, data, len, 0, to_addr, addr_len); |
||||
} |
||||
|
||||
int etcp_socket_get_fd(const etcp_socket_t* sock) { |
||||
if (!sock) return -1; |
||||
return sock->fd; |
||||
} |
||||
|
||||
void etcp_socket_get_local_addr(const etcp_socket_t* sock, struct sockaddr_storage* addr, socklen_t* addr_len) { |
||||
if (!sock || !addr || !addr_len) return; |
||||
|
||||
memcpy(addr, &sock->local_addr, sock->local_addr_len); |
||||
*addr_len = sock->local_addr_len; |
||||
} |
||||
|
||||
int etcp_socket_set_option(etcp_socket_t* sock, int level, int optname, const void* optval, socklen_t optlen) { |
||||
if (!sock || sock->fd < 0) return -1; |
||||
return setsockopt(sock->fd, level, optname, optval, optlen); |
||||
} |
||||
// Connection management functions
|
||||
void conn_destroy(conn_handle_t* handle) { |
||||
if (!handle) return; |
||||
if (handle->conns) { |
||||
etcp_socket_destroy((etcp_socket_t*)&handle->conns->socket); |
||||
etcp_connections_destroy(handle->conns); |
||||
} |
||||
if (handle->etcp) { |
||||
etcp_destroy(handle->etcp); |
||||
} |
||||
free(handle); |
||||
} |
||||
|
||||
int conn_send(conn_handle_t* handle, const uint8_t* data, size_t len) { |
||||
if (!handle || !handle->conns || handle->conns->num_channels == 0 || !data || len == 0) { |
||||
return -1; |
||||
} |
||||
|
||||
struct ETCP_LINK* link = handle->conns->links[0]; |
||||
if (!link || !link->etcp) return -1; |
||||
|
||||
return etcp_link_send(link->etcp, link, data, len); |
||||
} |
||||
|
||||
// Parse address in format "IP:port" or "[IPv6]:port" and fill sockaddr
|
||||
static int parse_addr_port(const char* addr_str, struct sockaddr_storage* addr, socklen_t* addr_len) { |
||||
if (!addr_str || !addr || !addr_len) return -1; |
||||
|
||||
char addr_copy[MAX_ADDR_LEN]; |
||||
strncpy(addr_copy, addr_str, MAX_ADDR_LEN - 1); |
||||
addr_copy[MAX_ADDR_LEN - 1] = '\0'; |
||||
|
||||
// Check for IPv6 format: [address]:port
|
||||
if (addr_copy[0] == '[') { |
||||
char* closing_bracket = strchr(addr_copy, ']'); |
||||
if (!closing_bracket) return -1; |
||||
|
||||
// Find port after ']:'
|
||||
char* colon = strchr(closing_bracket + 1, ':'); |
||||
if (!colon) return -1; |
||||
|
||||
*closing_bracket = '\0'; |
||||
uint16_t port = (uint16_t)atoi(colon + 1); |
||||
|
||||
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr; |
||||
memset(sin6, 0, sizeof(struct sockaddr_in6)); |
||||
sin6->sin6_family = AF_INET6; |
||||
sin6->sin6_port = htons(port); |
||||
|
||||
// Extract IP string and port from sockaddr_storage
|
||||
static int sockaddr_to_ip_port(const struct sockaddr_storage* addr, char* ip_out, size_t ip_out_len, uint16_t* port_out) { |
||||
if (!addr || !ip_out || !port_out) return -1; |
||||
|
||||
if (addr->ss_family == AF_INET) { |
||||
struct sockaddr_in* sin = (struct sockaddr_in*)addr; |
||||
*port_out = ntohs(sin->sin_port); |
||||
if (inet_ntop(AF_INET, &sin->sin_addr, ip_out, ip_out_len) == NULL) return -1; |
||||
} else if (addr->ss_family == AF_INET6) { |
||||
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr; |
||||
*port_out = ntohs(sin6->sin6_port); |
||||
if (inet_ntop(AF_INET6, &sin6->sin6_addr, ip_out, ip_out_len) == NULL) return -1; |
||||
} else { |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
for (int i = 0; i < config->server_count; i++) { |
||||
server_config_t* server = &config->servers[i]; |
||||
|
||||
char bind_addr[INET_ADDRSTRLEN]; |
||||
struct sockaddr_storage server_addr; |
||||
socklen_t server_addr_len; |
||||
if (parse_addr_port(server->addr, &server_addr, &server_addr_len) < 0) { |
||||
fprintf(stderr, "Invalid server address '%s'\n", server->addr); |
||||
goto cleanup; |
||||
} |
||||
char bind_addr_str[INET6_ADDRSTRLEN]; |
||||
uint16_t bind_port; |
||||
if (sockaddr_to_ip_port(&server_addr, bind_addr_str, sizeof(bind_addr_str), &bind_port) < 0) { |
||||
etcp_destroy(etcp); |
||||
goto cleanup; |
||||
} |
||||
} |
||||
|
||||
etcp_socket_t* sock = etcp_socket_create(etcp, bind_addr, bind_port); |
||||
if (!sock) { |
||||
fprintf(stderr, "Failed to create socket for %s\n", server->name); |
||||
etcp_destroy(etcp); |
||||
goto cleanup; |
||||
} |
||||
|
||||
if (i == 0) { |
||||
instance->first_listen_socket = (struct ETCP_SOCKET*)sock; |
||||
} |
||||
|
||||
struct ETCP_CONNECTIONS* conns = etcp_connections_init(sock); |
||||
if (!conns) { |
||||
etcp_socket_destroy(sock); |
||||
etcp_destroy(etcp); |
||||
goto cleanup; |
||||
} |
||||
|
||||
conn_handle_t* handle = calloc(1, sizeof(conn_handle_t)); |
||||
if (!handle) { |
||||
etcp_connections_destroy(conns); |
||||
etcp_socket_destroy(sock); |
||||
etcp_destroy(etcp); |
||||
goto cleanup; |
||||
} |
||||
|
||||
handle->etcp = etcp; |
||||
handle->conns = conns; |
||||
|
||||
for (int j = 0; j < config->client_count; j++) { |
||||
client_config_t* client = &config->clients[j]; |
||||
if (strcmp(client->from, server->name) != 0) continue; |
||||
|
||||
struct sockaddr_storage client_addr; |
||||
socklen_t client_addr_len; |
||||
if (parse_addr_port(client->to_addr, &client_addr, &client_addr_len) < 0) { |
||||
fprintf(stderr, "Invalid client address '%s'\n", client->to_addr); |
||||
continue; |
||||
} |
||||
memcpy(&addr, &client_addr, client_addr_len); |
||||
addr_len = client_addr_len; |
||||
struct sockaddr_in* sin = (struct sockaddr_in*)&addr; |
||||
memset(sin, 0, sizeof(struct sockaddr_in)); |
||||
sin->sin_family = AF_INET; |
||||
sin->sin_port = htons(client_port); |
||||
if (inet_pton(AF_INET, client_addr, &sin->sin_addr) != 1) continue; |
||||
addr_len = sizeof(struct sockaddr_in); |
||||
|
||||
struct ETCP_LINK* link = etcp_link_new(etcp, sock, (struct sockaddr*)&addr, addr_len); |
||||
if (link) { |
||||
etcp_link_add_to_connections(conns, link); |
||||
} |
||||
} |
||||
|
||||
instance->connections[i] = handle; |
||||
} |
||||
|
||||
instance->connection_count = config->server_count; |
||||
return 0; |
||||
|
||||
cleanup: |
||||
if (instance->connections) { |
||||
for (int j = 0; j < 0; j++) { |
||||
if (instance->connections[j]) { |
||||
conn_destroy(instance->connections[j]); |
||||
} |
||||
} |
||||
free(instance->connections); |
||||
instance->connections = NULL; |
||||
} |
||||
instance->first_listen_socket = NULL; |
||||
instance->connection_count = 0; |
||||
return -1; |
||||
} |
||||
#include "etcp_connections.h" |
||||
#include "etcp.h" |
||||
#include "config_parser.h" |
||||
#include "utun_instance.h" |
||||
#include <string.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
// Parse address in format "IP:port" or "[IPv6]:port" and fill sockaddr
|
||||
if (!addr || !ip_out || !port_out) return -1; |
||||
|
||||
if (addr->ss_family == AF_INET) { |
||||
struct sockaddr_in* sin = (struct sockaddr_in*)addr; |
||||
*port_out = ntohs(sin->sin_port); |
||||
if (inet_ntop(AF_INET, &sin->sin_addr, ip_out, ip_out_len) == NULL) return -1; |
||||
} else if (addr->ss_family == AF_INET6) { |
||||
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr; |
||||
*port_out = ntohs(sin6->sin6_port); |
||||
if (inet_ntop(AF_INET6, &sin6->sin6_addr, ip_out, ip_out_len) == NULL) return -1; |
||||
} else { |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
|
||||
int init_connections(utun_instance_t* instance) { |
||||
if (!instance || !instance->config) { |
||||
fprintf(stderr, "Invalid instance or config\n"); |
||||
return -1; |
||||
} |
||||
|
||||
utun_config_t* config = instance->config; |
||||
int total_connections = config->server_count, i = 0; |
||||
|
||||
if (total_connections == 0) { |
||||
fprintf(stderr, "No servers found in configuration\n"); |
||||
return -1; |
||||
} |
||||
|
||||
instance->connections = calloc(total_connections, sizeof(conn_handle_t*)); |
||||
if (!instance->connections) { |
||||
fprintf(stderr, "Failed to allocate connections array\n"); |
||||
return -1; |
||||
} |
||||
|
||||
for (i = 0; i < config->server_count; i++) { |
||||
server_config_t* server = &config->servers[i]; |
||||
|
||||
struct sockaddr_storage server_addr; |
||||
socklen_t server_addr_len; |
||||
if (parse_addr_port(server->addr, &server_addr, &server_addr_len) < 0) { |
||||
fprintf(stderr, "Invalid server address '%s'\n", server->addr); |
||||
goto cleanup; |
||||
} |
||||
|
||||
struct ETCP_CONN* etcp = etcp_create(instance); |
||||
if (!etcp) { |
||||
fprintf(stderr, "Failed to create ETCP for server %s\n", server->name); |
||||
goto cleanup; |
||||
} |
||||
|
||||
char bind_addr_str[INET6_ADDRSTRLEN]; |
||||
} |
||||
|
||||
conn_handle_t* handle = calloc(1, sizeof(conn_handle_t)); |
||||
if (!handle) { |
||||
etcp_connections_destroy(conns); |
||||
etcp_socket_destroy(sock); |
||||
etcp_destroy(etcp); |
||||
goto cleanup; |
||||
} |
||||
|
||||
handle->etcp = etcp; |
||||
handle->conns = conns; |
||||
|
||||
for (int j = 0; j < config->client_count; j++) { |
||||
client_config_t* client = &config->clients[j]; |
||||
if (strcmp(client->from, server->name) != 0) continue; |
||||
|
||||
struct sockaddr_storage client_addr; |
||||
socklen_t client_addr_len; |
||||
if (parse_addr_port(client->to_addr, &client_addr, &client_addr_len) < 0) { |
||||
fprintf(stderr, "Invalid client address '%s'\n", client->to_addr); |
||||
continue; |
||||
} |
||||
|
||||
struct sockaddr_storage addr; |
||||
socklen_t addr_len = client_addr_len; |
||||
|
||||
struct ETCP_LINK* link = etcp_link_new(etcp, sock, (struct sockaddr*)&addr, addr_len); |
||||
if (link) { |
||||
etcp_link_add_to_connections(conns, link); |
||||
} |
||||
} |
||||
|
||||
instance->connections[i] = handle; |
||||
} |
||||
|
||||
instance->connection_count = config->server_count; |
||||
return 0; |
||||
|
||||
cleanup: |
||||
if (instance->connections) { |
||||
for (int j = 0; j < i; j++) { |
||||
if (instance->connections[j]) { |
||||
conn_destroy(instance->connections[j]); |
||||
} |
||||
} |
||||
free(instance->connections); |
||||
instance->connections = NULL; |
||||
} |
||||
instance->first_listen_socket = NULL; |
||||
instance->connection_count = 0; |
||||
return -1; |
||||
Loading…
Reference in new issue