- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll - stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close - utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP), add deferred drain in both Phase J and L - stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39, exchange ed25519_pubkey in both handshake directions - etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb - chat_sync.c: fix lk->conn NULL dereference for TCP links - test_stcp.c: update stcp_server_create/stcp_client_connect callsites - tools/chat_tcp_test: change transport udp→tcp
35 lines
2.6 KiB
Markdown
35 lines
2.6 KiB
Markdown
# Get My IP (getmyip.h)
|
|
|
|
## 1. Назначение
|
|
Определение локального IP-адреса, который ОС выберет для исходящего UDP-соединения на заданный удалённый хост. Используется в `etcp_connections.c` при установке соединения: зная remote-адрес, модуль узнаёт, какой source IP ядро назначит пакетам (нужно для проверки NAT и привязки сокета к правильному интерфейсу).
|
|
|
|
## 2. Как пользоваться
|
|
Передать локальный адрес-подсказку (или `0.0.0.0` для автоопределения) и удалённый адрес. Функция создаст временный UDP-сокет, сделает bind+connect, считает выбранный IP через `getsockname` и вернёт его в `result` (порт = 0, только IP).
|
|
|
|
```c
|
|
struct sockaddr_storage local_hint; // AF_INET6, sin6_addr = in6addr_any
|
|
struct sockaddr_storage remote; // AF_INET6, адрес сервера
|
|
struct sockaddr_storage chosen_ip;
|
|
|
|
// ... заполнить local_hint и remote ...
|
|
|
|
if (get_outgoing_local_ip(&local_hint, &remote, &chosen_ip) == 0) {
|
|
// chosen_ip.ss_family == AF_INET6, sin6_addr содержит выбранный source IP
|
|
// chosen_ip.sin6_port == 0
|
|
}
|
|
```
|
|
|
|
**Нюансы:**
|
|
- Функция временно создаёт и закрывает UDP-сокет — нельзя вызывать в hot path
|
|
- `local_addr` и `remote_addr` должны быть одного семейства (оба AF_INET или оба AF_INET6)
|
|
- Порт в `local_addr` заменяется на 0 (чтобы не конфликтовать с основными сокетами)
|
|
- Порт в `result` всегда 0 — только IP
|
|
|
|
## 3. API
|
|
|
|
### Функция
|
|
- **`get_outgoing_local_ip(local_addr, remote_addr, result)`** — создаёт временный UDP-сокет, привязывает к `local_addr` (с портом 0), делает `connect` к `remote_addr` для вычисления маршрута ядром, получает выбранный source IP через `getsockname`. Возвращает 0 при успехе, -1 при ошибке (NULL-аргументы, несовпадение семейств, ошибки сокета).
|
|
|
|
### Зависимости
|
|
- `socket_compat.h` — кроссплатформенные обёртки: `socket_create_udp`, `SOCKET_INVALID`, `socket_close_wrapper`, `socket_get_error`, `socket_strerror`
|