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)
This commit is contained in:
1 parent
f5e18891bc
commit
6719a1e23c
7 files changed
+48
-21
No files matched your search
@@ -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 (по одной на целевой узел), список
|
||||
|
||||
@@ -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; }
|
||||
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) {
|
||||
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;
|
||||
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);
|
||||
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); 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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user