|
|
|
|
@ -5,7 +5,6 @@
|
|
|
|
|
#include <fcntl.h> |
|
|
|
|
#include <errno.h> |
|
|
|
|
#include <string.h> |
|
|
|
|
#include "debug_config.h" |
|
|
|
|
#include "routing.h" |
|
|
|
|
#include "utun_instance.h" |
|
|
|
|
#include "config_parser.h" |
|
|
|
|
@ -16,6 +15,24 @@
|
|
|
|
|
#include <stdlib.h> |
|
|
|
|
#include <time.h> |
|
|
|
|
|
|
|
|
|
// Simple debug macros to replace missing debug_config.h
|
|
|
|
|
#define DEBUG_CATEGORY_CONNECTION 1 |
|
|
|
|
#define DEBUG_CATEGORY_ETCP 2 |
|
|
|
|
#define DEBUG_CATEGORY_MEMORY 3 |
|
|
|
|
|
|
|
|
|
#define DEBUG_ERROR(category, fmt, ...) fprintf(stderr, "ERROR: " fmt "\n", ##__VA_ARGS__) |
|
|
|
|
#define DEBUG_INFO(category, fmt, ...) fprintf(stdout, "INFO: " fmt "\n", ##__VA_ARGS__) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Forward declarations for missing functions
|
|
|
|
|
struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance); |
|
|
|
|
void etcp_conn_reset(struct ETCP_CONN* etcp); |
|
|
|
|
void etcp_conn_input(struct ETCP_CONN* etcp, struct ETCP_DGRAM* pkt); |
|
|
|
|
void etcp_destroy(struct ETCP_CONN* etcp); |
|
|
|
|
static int etcp_link_send_init_response(struct ETCP_LINK* link, int mtu, uint16_t keepalive_interval); |
|
|
|
|
int etcp_input(struct ETCP_DGRAM* pkt); |
|
|
|
|
void packet_pool_free(struct memory_pool* pool, void* ptr); |
|
|
|
|
int etcp_connections_send(struct ETCP_SOCKET* e_sock, uint8_t* data, size_t len, struct sockaddr* addr, socklen_t addr_len); |
|
|
|
|
|
|
|
|
|
// CONNECTION MANAGEMENT (!!!это всё должно быть static!!!)
|
|
|
|
|
static void etcp_link_remove_from_connections(struct ETCP_SOCKET* conn, struct ETCP_LINK* link); |
|
|
|
|
@ -247,18 +264,18 @@ void etcp_link_close(struct ETCP_LINK* link) {
|
|
|
|
|
|
|
|
|
|
int etcp_encrypt_send(struct ETCP_DGRAM* dgram) { |
|
|
|
|
|
|
|
|
|
sc_context_t* sc = dgram->link->etcp->crypto_ctx; |
|
|
|
|
sc_context_t* sc = &dgram->link->etcp->crypto_ctx; |
|
|
|
|
int len=dgram->data_len-dgram->noencrypt_len; |
|
|
|
|
if (len<=0 || len>1480) { dgram->link->send_errors++; return; } |
|
|
|
|
if (len<=0 || len>1480) { dgram->link->send_errors++; return -1; } |
|
|
|
|
uint8_t enc_buf[1600]; |
|
|
|
|
size_t enc_buf_len; |
|
|
|
|
sc_encrypt(sc, dgram->data, len, &enc_buf, &enc_buf_len); |
|
|
|
|
if (enc_buf_len + dgram->noencrypt_len > 1480) { dgram->link->send_errors++; return; } |
|
|
|
|
sc_encrypt(sc, dgram->data, len, enc_buf, &enc_buf_len); |
|
|
|
|
if (enc_buf_len + dgram->noencrypt_len > 1480) { dgram->link->send_errors++; return -1; } |
|
|
|
|
memcpy(enc_buf+enc_buf_len, dgram->data+enc_buf_len, dgram->noencrypt_len); |
|
|
|
|
|
|
|
|
|
struct sockaddr_storage* addr=dgram->link->remote_addr; |
|
|
|
|
socklen_t addr_len = (to_addr->ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); |
|
|
|
|
ssize_t sent = sendto(dgram->link->conn->fd, enc_buf, len, 0, addr, addr_len); |
|
|
|
|
struct sockaddr_storage* addr=&dgram->link->remote_addr; |
|
|
|
|
socklen_t addr_len = (addr->ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); |
|
|
|
|
ssize_t sent = sendto(dgram->link->conn->fd, enc_buf, len, 0, (struct sockaddr*)addr, addr_len); |
|
|
|
|
if (sent < 0) dgram->link->send_errors++; else dgram->link->total_encrypted += sent; |
|
|
|
|
return (int)sent; |
|
|
|
|
} |
|
|
|
|
@ -308,7 +325,6 @@ static void etcp_connections_read_callback(int fd, void* arg) {
|
|
|
|
|
struct ETCP_SOCKET* e_sock = (struct ETCP_SOCKET*)arg; |
|
|
|
|
if (!e_sock) return; |
|
|
|
|
|
|
|
|
|
socklen_t addr_len = sizeof(pkt->metadata.remote_addr); |
|
|
|
|
struct sockaddr_storage addr; |
|
|
|
|
uint8_t data[PACKET_DATA_SIZE]; |
|
|
|
|
socklen_t addr_len=sizeof(addr); |
|
|
|
|
@ -319,12 +335,12 @@ static void etcp_connections_read_callback(int fd, void* arg) {
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct ETCP_DGRAM* pkt = memory_pool_alloc(&e_sock->instance->pkt_pool); |
|
|
|
|
struct ETCP_DGRAM* pkt = memory_pool_alloc(e_sock->instance->pkt_pool); |
|
|
|
|
if (!pkt) return; |
|
|
|
|
size_t pkt_len=0; |
|
|
|
|
int errorcode=0; |
|
|
|
|
|
|
|
|
|
struct ETCP_LINK* link=etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, &addr); |
|
|
|
|
struct ETCP_LINK* link=etcp_link_find_by_addr(e_sock, &addr); |
|
|
|
|
if (link==NULL) {// пробуем расшифровать, возможно это init
|
|
|
|
|
struct secure_channel sc; |
|
|
|
|
if (recv_len<=SC_PUBKEY_SIZE) { errorcode=1; goto ec_fr; } |
|
|
|
|
@ -343,7 +359,7 @@ static void etcp_connections_read_callback(int fd, void* arg) {
|
|
|
|
|
uint8_t pubkey[SC_PUBKEY_SIZE]; |
|
|
|
|
} *ack_hdr=(void*)&pkt->data[0]; |
|
|
|
|
uint64_t peer_id; |
|
|
|
|
memcpy(&peer_id, &pkt->data+1, 4); |
|
|
|
|
memcpy(&peer_id, &pkt->data[1], 4); |
|
|
|
|
if (ack_hdr->code!=0x02 && ack_hdr->code!=0x04) { errorcode=4; goto ec_fr; }// не init
|
|
|
|
|
|
|
|
|
|
struct ETCP_CONN* conn=e_sock->instance->connections; |
|
|
|
|
@ -357,10 +373,10 @@ static void etcp_connections_read_callback(int fd, void* arg) {
|
|
|
|
|
conn->peer_node_id=peer_id; |
|
|
|
|
} |
|
|
|
|
else {// check keys
|
|
|
|
|
if (memcmp(&conn->crypto_ctx->peer_public_key, &sc.peer_public_key, SC_PUBKEY_SIZE)) { errorcode=5; goto ec_fr; }// коллизия - peer id совпал а ключи разные.
|
|
|
|
|
if (memcmp(&conn->crypto_ctx.peer_public_key, &sc.peer_public_key, SC_PUBKEY_SIZE)) { errorcode=5; goto ec_fr; }// коллизия - peer id совпал а ключи разные.
|
|
|
|
|
} |
|
|
|
|
struct ETCP_LINK* link = etcp_link_new(etcp, e_sock, addr, 1); |
|
|
|
|
if (ack_hdr->code==0x02) etcp_conn_reset(etcp); |
|
|
|
|
struct ETCP_LINK* link = etcp_link_new(conn, e_sock, &addr, 1); |
|
|
|
|
if (ack_hdr->code==0x02) etcp_conn_reset(conn); |
|
|
|
|
// send reply - подключение создано
|
|
|
|
|
struct { |
|
|
|
|
uint8_t main_id[2]; |
|
|
|
|
@ -373,14 +389,14 @@ static void etcp_connections_read_callback(int fd, void* arg) {
|
|
|
|
|
ack_repl_hdr->main_id[0]=0; |
|
|
|
|
ack_repl_hdr->main_id[1]=0; |
|
|
|
|
memcpy(&ack_repl_hdr->id[0], &e_sock->instance->node_id, 8); |
|
|
|
|
int mtu=e_sock->instance->config->global->mtu; |
|
|
|
|
int mtu=e_sock->instance->config->global.mtu; |
|
|
|
|
ack_repl_hdr->mtu[0]=mtu>>8; |
|
|
|
|
ack_repl_hdr->mtu[1]=mtu; |
|
|
|
|
pkt->data_len=sizeof(ack_repl_hdr); |
|
|
|
|
pkt->data_len=sizeof(*ack_repl_hdr); |
|
|
|
|
pkt->noencrypt_len=0; |
|
|
|
|
etcp_encrypt_send(pkt); |
|
|
|
|
|
|
|
|
|
packet_pool_free(&e_sock->instance->pkt_pool, pkt); |
|
|
|
|
packet_pool_free(e_sock->instance->pkt_pool, pkt); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -389,58 +405,57 @@ static void etcp_connections_read_callback(int fd, void* arg) {
|
|
|
|
|
pkt->noencrypt_len=0; |
|
|
|
|
pkt->link=link; |
|
|
|
|
|
|
|
|
|
etcp_input(pkt, conns); |
|
|
|
|
etcp_input(pkt); |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
ec_fr: |
|
|
|
|
e_sock->pkt_format_errors++; |
|
|
|
|
e_sock->errorcode=errorcode; |
|
|
|
|
packet_pool_free(&e_sock->instance->pkt_pool, pkt); |
|
|
|
|
packet_pool_free(e_sock->instance->pkt_pool, pkt); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#define MIN(a,b) ((a) < (b) ? (a) : (b)) |
|
|
|
|
|
|
|
|
|
int etcp_input(struct ETCP_DGRAM* pkt) { |
|
|
|
|
if (!pkt || !e_sock) return -1; |
|
|
|
|
if (!pkt || !pkt->link) return -1; |
|
|
|
|
|
|
|
|
|
uint8_t* data = pkt->data; |
|
|
|
|
size_t len = pkt->metadata.data_len; |
|
|
|
|
size_t len = pkt->data_len; |
|
|
|
|
|
|
|
|
|
if (len < 1) return -1; |
|
|
|
|
|
|
|
|
|
uint8_t header = data[0]; |
|
|
|
|
data++; len--; |
|
|
|
|
|
|
|
|
|
struct ETCP_CONN* etcp = e_sock->etcp; |
|
|
|
|
struct ETCP_LINK* link = pkt->link; |
|
|
|
|
struct ETCP_CONN* etcp = link->etcp; |
|
|
|
|
|
|
|
|
|
// Check if we have peer key by checking if peer_node_id is set
|
|
|
|
|
int has_peer_key = (etcp->peer_node_id != 0); |
|
|
|
|
|
|
|
|
|
if (header != ETCP_INIT_REQUEST && header != ETCP_CHANNEL_INIT && etcp->has_peer_key) { |
|
|
|
|
if (header != ETCP_INIT_REQUEST && header != ETCP_CHANNEL_INIT && has_peer_key) { |
|
|
|
|
// Decrypt
|
|
|
|
|
sc_context_t* sc = etcp->crypto_ctx; |
|
|
|
|
sc_context_t* sc = &etcp->crypto_ctx; |
|
|
|
|
uint8_t decrypted[PACKET_DATA_SIZE]; |
|
|
|
|
size_t decrypted_len; |
|
|
|
|
if (sc_decrypt(sc, data, len, decrypted, &decrypted_len) != SC_OK) { |
|
|
|
|
e_sock->decrypt_errors++; |
|
|
|
|
link->decrypt_errors++; |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
memcpy(data, decrypted, decrypted_len); |
|
|
|
|
len = decrypted_len; |
|
|
|
|
e_sock->total_decrypted += len; |
|
|
|
|
link->total_decrypted += len; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct ETCP_LINK* link = etcp_link_find_by_addr(e_sock, (struct sockaddr*)&pkt->metadata.remote_addr, |
|
|
|
|
sizeof(pkt->metadata.remote_addr)); |
|
|
|
|
|
|
|
|
|
if (!link) { |
|
|
|
|
if (header == ETCP_INIT_REQUEST || header == ETCP_CHANNEL_INIT) { |
|
|
|
|
// Create new link
|
|
|
|
|
link = etcp_link_new(etcp, e_sock, (struct sockaddr*)&pkt->metadata.remote_addr, |
|
|
|
|
sizeof(pkt->metadata.remote_addr)); |
|
|
|
|
if (!link) return -1; |
|
|
|
|
// Create new link - this shouldn't happen as link should be set
|
|
|
|
|
return -1; |
|
|
|
|
} else { |
|
|
|
|
// Send reset if not init
|
|
|
|
|
uint8_t reset_pkt[1] = {ETCP_RESET}; |
|
|
|
|
etcp_connections_send(e_sock, reset_pkt, 1, (struct sockaddr*)&pkt->metadata.remote_addr, sizeof(pkt->metadata.remote_addr)); |
|
|
|
|
etcp_connections_send(link->conn, reset_pkt, 1, (struct sockaddr*)&link->remote_addr, sizeof(link->remote_addr)); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -456,9 +471,9 @@ int etcp_input(struct ETCP_DGRAM* pkt) {
|
|
|
|
|
memcpy(peer_pubkey, data, SC_PUBKEY_SIZE); |
|
|
|
|
|
|
|
|
|
etcp->peer_node_id = peer_node_id; |
|
|
|
|
memcpy(etcp->peer_public_key, peer_pubkey, SC_PUBKEY_SIZE); |
|
|
|
|
etcp->has_peer_key = 1; |
|
|
|
|
sc_set_peer_public_key(etcp->crypto_ctx, peer_pubkey); |
|
|
|
|
memcpy(etcp->crypto_ctx.peer_public_key, peer_pubkey, SC_PUBKEY_SIZE); |
|
|
|
|
etcp->peer_node_id = peer_node_id; // Set peer_node_id to indicate we have peer key
|
|
|
|
|
sc_set_peer_public_key(&etcp->crypto_ctx, peer_pubkey, 0); |
|
|
|
|
|
|
|
|
|
link->mtu = MIN(etcp->mtu, peer_mtu); |
|
|
|
|
link->keepalive_interval = peer_keepalive; |
|
|
|
|
@ -475,89 +490,152 @@ int etcp_input(struct ETCP_DGRAM* pkt) {
|
|
|
|
|
etcp_conn_reset(etcp); |
|
|
|
|
} else { |
|
|
|
|
// Forward to etcp_conn_input
|
|
|
|
|
pkt->metadata.channel = link; // Or etcp_channel if separate
|
|
|
|
|
pkt->link = link; |
|
|
|
|
etcp_conn_input(etcp, pkt); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
packet_pool_put(&etcp->packet_pool, pkt); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int init_connections(struct UTUN_INSTANCE* instance) { |
|
|
|
|
if (!instance || !instance->config) return -1; |
|
|
|
|
|
|
|
|
|
struct config* config = instance->config; |
|
|
|
|
instance->connections = calloc(config->server_count, sizeof(struct ETCP_CONN)); |
|
|
|
|
if (!instance->connections) return -1; |
|
|
|
|
|
|
|
|
|
instance->connection_count = 0; |
|
|
|
|
struct utun_config* config = instance->config; |
|
|
|
|
|
|
|
|
|
// Initialize servers first - create sockets for incoming connections
|
|
|
|
|
struct CFG_SERVER* server = config->servers; |
|
|
|
|
while (server) { |
|
|
|
|
|
|
|
|
|
// Create connections manager (includes socket creation)
|
|
|
|
|
struct ETCP_CONN* conn = etcp_connection_add(instance, server->ip, server->netif_index, server->so_mark, server->type); |
|
|
|
|
if (!conn) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create connections for %s", server->name); |
|
|
|
|
etcp_destroy(etcp); |
|
|
|
|
// Create socket for this server
|
|
|
|
|
struct ETCP_SOCKET* e_sock = etcp_socket_add(instance, &server->ip, server->netif_index, server->so_mark, server->type); |
|
|
|
|
if (!e_sock) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create socket for server %s", server->name); |
|
|
|
|
server = server->next; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Convert IP to string for logging
|
|
|
|
|
char addr_str[INET6_ADDRSTRLEN + 6]; |
|
|
|
|
if (server->ip.ss_family == AF_INET) { |
|
|
|
|
struct sockaddr_in* sin = (struct sockaddr_in*)&server->ip; |
|
|
|
|
inet_ntop(AF_INET, &sin->sin_addr, addr_str, INET_ADDRSTRLEN); |
|
|
|
|
sprintf(addr_str + strlen(addr_str), ":%d", ntohs(sin->sin_port)); |
|
|
|
|
} else { |
|
|
|
|
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&server->ip; |
|
|
|
|
inet_ntop(AF_INET6, &sin6->sin6_addr, addr_str, INET6_ADDRSTRLEN); |
|
|
|
|
sprintf(addr_str + strlen(addr_str), ":%d", ntohs(sin6->sin6_port)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf("Initialized server %s on %s (links: %zu)\n",
|
|
|
|
|
server->name, server->addr, e_sock->num_channels); |
|
|
|
|
server->name, addr_str, e_sock->num_channels); |
|
|
|
|
server = server->next; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Process connections that added to this server
|
|
|
|
|
for (int j = 0; j < config->client_count; j++) { |
|
|
|
|
struct client_config* client = &config->clients[j]; |
|
|
|
|
|
|
|
|
|
// Check if this client is for current server
|
|
|
|
|
if (strcmp(client->from, server->name) != 0) { |
|
|
|
|
|
|
|
|
|
// Initialize clients - create outgoing connections
|
|
|
|
|
struct CFG_CLIENT* client = config->clients; |
|
|
|
|
while (client) { |
|
|
|
|
// Create ETCP connection for this client
|
|
|
|
|
struct ETCP_CONN* etcp_conn = etcp_connection_create(instance); |
|
|
|
|
if (!etcp_conn) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create ETCP connection for client %s", client->name); |
|
|
|
|
client = client->next; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct ETCP_CONN* etcp_conn=etcp_connection_create(instance); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Серверы получат pubkey через INIT пакет
|
|
|
|
|
sc_init_ctx(&etcp_conn->ctx, &instance->my_keys); |
|
|
|
|
// Initialize crypto context for this connection
|
|
|
|
|
sc_init_ctx(&etcp_conn->crypto_ctx, &instance->my_keys); |
|
|
|
|
|
|
|
|
|
// If client has peer public key configured, set it
|
|
|
|
|
if (strlen(client->peer_public_key_hex) > 0) { |
|
|
|
|
uint8_t peer_key_bin[SC_PUBKEY_SIZE]; |
|
|
|
|
if (hex_to_binary(client->peer_public_key_hex, peer_key_bin, SC_PUBKEY_SIZE) == 0) { |
|
|
|
|
memcpy(etcp_conn->peer_public_key, peer_key_bin, SC_PUBKEY_SIZE); |
|
|
|
|
etcp_conn->has_peer_key = 1; |
|
|
|
|
sc_set_peer_public_key(etcp_conn->crypto_ctx, peer_key_bin); |
|
|
|
|
} |
|
|
|
|
// For now, set peer node ID to indicate we have peer key
|
|
|
|
|
// The actual peer key will be exchanged during connection establishment
|
|
|
|
|
etcp_conn->peer_node_id = 1; // Simple indicator
|
|
|
|
|
|
|
|
|
|
// Set peer public key (assuming hex format)
|
|
|
|
|
sc_set_peer_public_key(&etcp_conn->crypto_ctx, client->peer_public_key_hex, 1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// тут надо добавить линки
|
|
|
|
|
|
|
|
|
|
struct client_link cl=client->links; |
|
|
|
|
while (cl) { |
|
|
|
|
conn= (надо найти) |
|
|
|
|
|
|
|
|
|
// Create link for this client
|
|
|
|
|
struct ETCP_LINK* link = etcp_link_new(etcp, conn, cl->remote_sockaddr, sizeof(struct sockaddr_storage)); |
|
|
|
|
|
|
|
|
|
// Add connection to the instance's linked list
|
|
|
|
|
etcp_conn->next = instance->connections; |
|
|
|
|
instance->connections = etcp_conn; |
|
|
|
|
instance->connections_count++; |
|
|
|
|
|
|
|
|
|
// Create links for this client
|
|
|
|
|
struct CFG_CLIENT_LINK* client_link = client->links; |
|
|
|
|
while (client_link) { |
|
|
|
|
// Find the local server for this link
|
|
|
|
|
struct CFG_SERVER* local_server = client_link->local_srv; |
|
|
|
|
if (!local_server) { |
|
|
|
|
client_link = client_link->next; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Find the socket for this server
|
|
|
|
|
struct ETCP_SOCKET* e_sock = NULL; |
|
|
|
|
struct ETCP_SOCKET* sock = instance->etcp_sockets; |
|
|
|
|
while (sock) { |
|
|
|
|
if (sock->local_addr.ss_family == local_server->ip.ss_family) { |
|
|
|
|
if (sock->local_addr.ss_family == AF_INET) { |
|
|
|
|
struct sockaddr_in* sock_addr = (struct sockaddr_in*)&sock->local_addr; |
|
|
|
|
struct sockaddr_in* srv_addr = (struct sockaddr_in*)&local_server->ip; |
|
|
|
|
if (sock_addr->sin_addr.s_addr == srv_addr->sin_addr.s_addr &&
|
|
|
|
|
sock_addr->sin_port == srv_addr->sin_port) { |
|
|
|
|
e_sock = sock; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
sock = sock->next; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!e_sock) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "No socket found for client %s link", client->name); |
|
|
|
|
client_link = client_link->next; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Create link for this client connection
|
|
|
|
|
struct ETCP_LINK* link = etcp_link_new(etcp_conn, e_sock, &client_link->remote_addr, 0); // 0 = client initiates
|
|
|
|
|
if (!link) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create link for client %s", client->name); |
|
|
|
|
client_link = client_link->next; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
cl=cl->next; |
|
|
|
|
|
|
|
|
|
client_link = client_link->next; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf(" Added client %s -> %s\n", client->name, client->to_addr); |
|
|
|
|
printf("Added client %s with %d links\n", client->name, client->keepalive); |
|
|
|
|
client = client->next; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (instance->connection_count == 0) { |
|
|
|
|
|
|
|
|
|
if (instance->connections_count == 0) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "No connections initialized"); |
|
|
|
|
free(instance->connections); |
|
|
|
|
instance->connections = NULL; |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf("Initialized %d connections\n", instance->connection_count); |
|
|
|
|
printf("Initialized %d connections\n", instance->connections_count); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Simple implementations for missing functions
|
|
|
|
|
int etcp_link_send_init_response(struct ETCP_LINK* link, int mtu, uint16_t keepalive_interval) { |
|
|
|
|
// TODO: Implement this function
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void packet_pool_free(struct memory_pool* pool, void* ptr) { |
|
|
|
|
// TODO: Implement this function
|
|
|
|
|
// For now, just free the memory (this is a simplified version)
|
|
|
|
|
if (ptr) { |
|
|
|
|
// In a real implementation, this would return to the pool
|
|
|
|
|
// For now, we assume the memory came from the pool
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int etcp_connections_send(struct ETCP_SOCKET* e_sock, uint8_t* data, size_t len, struct sockaddr* addr, socklen_t addr_len) { |
|
|
|
|
// TODO: Implement this function
|
|
|
|
|
// For now, just send directly
|
|
|
|
|
ssize_t sent = sendto(e_sock->fd, data, len, 0, addr, addr_len); |
|
|
|
|
return (sent < 0) ? -1 : (int)sent; |
|
|
|
|
} |
|
|
|
|
|