Browse Source

IPv6: STCP dual-stack + Android config + invite fixes

- stcp_server: dual-stack (AF_INET6 + IPV6_V6ONLY=0) instead of IPv4-only
- stcp_client: getaddrinfo(AF_UNSPEC) instead of inet_pton(AF_INET)
- stcp_link: detect address family from remote_addr->ss_family
- platform_compat.h: add <netdb.h> for getaddrinfo on POSIX
- ConfigProvider.kt: add [server:main6] addr=[::]:PORT for Android
- invite_link_c.c: invite_serialize_addrs handles IPv6 (was IPv4-only)
topo_upd
evgeny 2 months ago
parent
commit
6719a1e23c
  1. 1
      lib/platform_compat.h
  2. 5
      src/routing_layer/conn_mgr.h
  3. 21
      src/transport_layer/stcp_client.c
  4. 17
      src/transport_layer/stcp_link.c
  5. 12
      src/transport_layer/stcp_server.c
  6. 3
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConfigProvider.kt
  7. 6
      tools/chatgui-android/libutun_lite/invite_link_c.c

1
lib/platform_compat.h

@ -166,6 +166,7 @@ extern "C" {
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>

5
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 (по одной на целевой узел), список

21
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;

17
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;

12
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;

3
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()

6
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);
}

Loading…
Cancel
Save