diff --git a/lib/platform_compat.h b/lib/platform_compat.h index 9efeb952..b964a726 100644 --- a/lib/platform_compat.h +++ b/lib/platform_compat.h @@ -166,6 +166,7 @@ extern "C" { #include #include #include + #include #include #include #include diff --git a/src/routing_layer/conn_mgr.h b/src/routing_layer/conn_mgr.h index f63bcd39..bb7c3e23 100644 --- a/src/routing_layer/conn_mgr.h +++ b/src/routing_layer/conn_mgr.h @@ -19,7 +19,10 @@ struct TOPO_GROUP; * @file conn_mgr.h * @brief Подключение к узлам P2P-сети. Handle-based API. * - * === Архитектура === + * Подключает к удалегному узлу либо напрямую, либо через посредника с прямыми адресами. + * При открытии выдаёт handle. и держит подключение открытым пока не закроешь handle. + * Отправлять можно обычным send через роутер - он сам разберётся как отправить, + * либо send этого моделя - он точно отправит через этот мост. * * Один CONN_MGR = одна TOPO_GROUP. Создаётся conn_mgr_init(group), живёт пока * существует группа. Внутри: кеш entries (по одной на целевой узел), список diff --git a/src/transport_layer/stcp_client.c b/src/transport_layer/stcp_client.c index 0dee38f6..b39775ea 100644 --- a/src/transport_layer/stcp_client.c +++ b/src/transport_layer/stcp_client.c @@ -258,16 +258,23 @@ struct stcp_client *stcp_client_connect(struct UASYNC *ua, const char *addr, uin c->on_close = close_cb; c->close_arg = close_arg; c->tx_cb = client_tx_queue_cb; - c->sock = socket(AF_INET, SOCK_STREAM, 0); - if (c->sock == SOCKET_INVALID) { u_free(cli); return NULL; } + struct addrinfo hints = {0}; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + char port_str[16]; snprintf(port_str, sizeof(port_str), "%u", port); + struct addrinfo *res; + if (getaddrinfo(addr, port_str, &hints, &res) != 0) { + DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "stcp_client getaddrinfo %s:%u failed", addr, port); + u_free(cli); return NULL; + } + c->sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (c->sock == SOCKET_INVALID) { freeaddrinfo(res); u_free(cli); return NULL; } socket_set_nonblocking(c->sock); - struct sockaddr_in saddr; memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; saddr.sin_port = htons(port); - if (inet_pton(AF_INET, addr, &saddr.sin_addr) != 1) { socket_close_wrapper(c->sock); u_free(cli); return NULL; } - if (connect(c->sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0 && socket_get_error() != EINPROGRESS) { + if (connect(c->sock, res->ai_addr, res->ai_addrlen) < 0 && socket_get_error() != EINPROGRESS) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "stcp_client connect to %s:%u failed err=%d", addr, port, socket_get_error()); - socket_close_wrapper(c->sock); u_free(cli); return NULL; + socket_close_wrapper(c->sock); freeaddrinfo(res); u_free(cli); return NULL; } + freeaddrinfo(res); c->socket_id = uasync_add_socket_t(ua, c->sock, NULL, client_connect_write_cb, NULL, cli); if (!c->socket_id) { socket_close_wrapper(c->sock); u_free(cli); return NULL; } return cli; diff --git a/src/transport_layer/stcp_link.c b/src/transport_layer/stcp_link.c index 471ea7d1..37a5655c 100644 --- a/src/transport_layer/stcp_link.c +++ b/src/transport_layer/stcp_link.c @@ -133,10 +133,21 @@ struct stcp_link *stcp_link_connect(struct stcp_link_config *cfg) { if (!cfg || !cfg->ua || !cfg->my_keys || !cfg->peer_pubkey || !cfg->remote_addr) return NULL; + int family = cfg->remote_addr->ss_family; char addr_str[64]; - struct sockaddr_in *sa = (struct sockaddr_in *)cfg->remote_addr; - inet_ntop(AF_INET, &sa->sin_addr, addr_str, sizeof(addr_str)); - uint16_t port = cfg->remote_port ? cfg->remote_port : ntohs(sa->sin_port); + uint16_t port; + if (family == AF_INET) { + struct sockaddr_in *sa = (struct sockaddr_in *)cfg->remote_addr; + inet_ntop(AF_INET, &sa->sin_addr, addr_str, sizeof(addr_str)); + port = cfg->remote_port ? cfg->remote_port : ntohs(sa->sin_port); + } else if (family == AF_INET6) { + struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)cfg->remote_addr; + inet_ntop(AF_INET6, &sa6->sin6_addr, addr_str, sizeof(addr_str)); + port = cfg->remote_port ? cfg->remote_port : ntohs(sa6->sin6_port); + } else { + DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "stcp_link: unsupported address family %d", family); + return NULL; + } struct stcp_link *link = u_calloc(1, sizeof(struct stcp_link)); if (!link) return NULL; diff --git a/src/transport_layer/stcp_server.c b/src/transport_layer/stcp_server.c index 5cdcca45..f645d1a2 100644 --- a/src/transport_layer/stcp_server.c +++ b/src/transport_layer/stcp_server.c @@ -355,16 +355,18 @@ struct stcp_server *stcp_server_create(struct UASYNC *ua, uint16_t port, srv->close_cb = close_cb; srv->close_arg = close_arg; - srv->listen_sock = socket(AF_INET, SOCK_STREAM, 0); + srv->listen_sock = socket(AF_INET6, SOCK_STREAM, 0); if (srv->listen_sock == SOCKET_INVALID) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "socket failed"); u_free(srv); return NULL; } socket_set_nonblocking(srv->listen_sock); int reuse = 1; setsockopt(srv->listen_sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse, sizeof(reuse)); - struct sockaddr_in addr; + int v6only = 0; + setsockopt(srv->listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&v6only, sizeof(v6only)); + struct sockaddr_in6 addr; memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons(port); + addr.sin6_family = AF_INET6; + addr.sin6_addr = in6addr_any; + addr.sin6_port = htons(port); if (bind(srv->listen_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "bind port=%u failed err=%d", port, socket_get_error()); socket_close_wrapper(srv->listen_sock); u_free(srv); return NULL; diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConfigProvider.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConfigProvider.kt index 00106e38..da356d2e 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConfigProvider.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConfigProvider.kt @@ -290,6 +290,9 @@ class ConfigProvider(private val context: Context) { appendLine("[server:main]") appendLine("addr=0.0.0.0:$listenPort") appendLine() + appendLine("[server:main6]") + appendLine("addr=[::]:$listenPort") + appendLine() appendLine("[allowed_keys]") appendLine("allow_all=yes") appendLine() diff --git a/tools/chatgui-android/libutun_lite/invite_link_c.c b/tools/chatgui-android/libutun_lite/invite_link_c.c index 39f776fe..f64703f7 100644 --- a/tools/chatgui-android/libutun_lite/invite_link_c.c +++ b/tools/chatgui-android/libutun_lite/invite_link_c.c @@ -127,16 +127,16 @@ int invite_serialize_addrs(const struct InviteDataC* data, uint8_t* buf, size_t if (!data || !buf) return -1; size_t needed = 0; for (int i = 0; i < (int)data->addrCount; i++) - needed += 9U; /* family(1) + sockId(1) + proto(1) + ip4(4) + port(2) = 9; IPv6 skipped */ + needed += (data->addrs[i].family == 6) ? 21U : 9U; if (needed > buf_size) return -1; size_t pos = 0; for (int i = 0; i < (int)data->addrCount; i++) { const struct InviteAddrC* a = &data->addrs[i]; - if (a->family != 4) continue; + int ip_len = (a->family == 6) ? 16 : 4; buf[pos++] = (uint8_t)a->family; buf[pos++] = a->socketId; buf[pos++] = a->proto; - memcpy(buf + pos, a->address, 4); pos += 4; + memcpy(buf + pos, a->address, (size_t)ip_len); pos += ip_len; buf[pos++] = (uint8_t)(a->port >> 8); buf[pos++] = (uint8_t)(a->port & 0xFF); }