# 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`