# platform_compat — Cross-platform compatibility layer ## 1. Назначение Унифицирует различия между POSIX (Linux/FreeBSD) и Windows (MSYS2 UCRT64) на уровне системных вызовов и типов. Предоставляет единый API для байтового порядка, строковых функций, энтропии, работы с сетевыми интерфейсами и времени. Полностью заголовочный (inline) для макросов и тривиальных обёрток, `.c` только для нетривиальных реализаций. ## 2. Как пользоваться Подключить `"platform_compat.h"` — всё остальное разрешается автоматически в зависимости от `_WIN32`. ### Байтовый порядок ```c uint16_t v16 = htobe16(x); // host → big-endian uint32_t v32 = be32toh(x); // big-endian → host uint64_t v64 = be64toh(x); // big-endian → host // На Linux использует , на Windows — _byteswap_* ``` ### Криптостойкий random ```c uint8_t salt[8]; if (random_bytes(salt, sizeof(salt)) != 0) { /* ошибка */ } // Linux: /dev/urandom, Windows: BCryptGenRandom ``` ### Сетевые интерфейсы ```c // Определить интерфейс маршрута по умолчанию uint32_t ifidx = get_default_route_netif_index(AF_INET); // или AF_INET6 // Получить IPv4 адрес интерфейса по индексу uint32_t ipv4 = get_interface_ip_by_index(ifidx); // network byte order // Получить IPv6 адрес (постоянный или временный) uint8_t ipv6[16]; if (get_interface_ipv6_by_index(ifidx, 1, ipv6) == 0) { // temporary=1 // ipv6 содержит 16 байт адреса } ``` **Windows**: `get_interface_ip_by_index`, `get_interface_ipv6_by_index`, `get_default_route_netif_index` — заглушки (возвращают 0/-1). ### Время ```c struct timeval tv; utun_gettimeofday(&tv, NULL); // макрос: на Linux → gettimeofday, на Windows → inline-реализация ``` ### Прочее - `strcasecmp`/`strncasecmp` — на Windows `_stricmp`/`_strnicmp` - `memmem` — на Windows inline-реализация `compat_memmem` - `pipe` — на Windows `_pipe` с `_O_BINARY` - `poll` — на Windows `WSAPoll`, флаги `POLLIN`/`POLLOUT` и т.д. определены если отсутствуют - `ssize_t` — определён если отсутствует - `fcntl` — на Windows упрощённая реализация только для `F_SETFL`/`O_NONBLOCK` - `utun_mkdir` — кроссплатформенный `mkdir` ### Ограничения - Функции сетевых интерфейсов работают только на POSIX, на Windows — заглушки - `get_default_route_netif_index` создаёт временный UDP-сокет к `8.8.8.8` (IPv4) или `2001:4860:4860::8888` (IPv6) для определения интерфейса - Только IPv4/IPv6; `family` только `AF_INET` или `AF_INET6` ## 3. API ### Байтовый порядок | Макрос | Назначение | |--------|------------| | `htobe16(x)` / `be16toh(x)` | 16-bit host ↔ big-endian | | `htobe32(x)` / `be32toh(x)` | 32-bit host ↔ big-endian | | `htobe64(x)` / `be64toh(x)` | 64-bit host ↔ big-endian | ### Основные функции | Функция | Назначение | |---------|------------| | `random_bytes(buffer, len)` | Криптостойкие случайные байты. 0 — успех, -1 — ошибка | | `get_interface_ip_by_index(ifindex)` | IPv4 адрес интерфейса в network byte order, 0 при ошибке | | `get_interface_ipv6_by_index(ifindex, temporary, out)` | IPv6 адрес (temporary=1 — временный privacy-адрес), 0 — успех | | `get_default_route_netif_index(family)` | ifindex дефолтного маршрута через connect() к внешнему IP | ### Макросы-заменители (условные) | Макрос | Назначение | |--------|------------| | `utun_gettimeofday(tv, tz)` | gettimeofday (inline на Windows) | | `utun_mkdir(path, mode)` | mkdir |