Consolidate platform adapter documentation in header

This commit is contained in:
evgeny committed 2026-10-21 17:55:27 +02:00
1 parent 1c4010ebed
commit 4f3f6d3e60
2 files changed
+12 -88

No files matched your search

+12 -7
View File
@@ -2,6 +2,12 @@
* platform_compat — общие заголовки POSIX/Windows и адаптеры отсутствующих POSIX-функций.
* Также предоставляет криптографический random_bytes, адреса интерфейсов, выбор default route
* и классификацию публичных IPv4. Сокетные типы/ошибки и nonblocking API — в socket_compat.h.
* Подключать этот заголовок вместо прямых POSIX includes для общего кода.
* Windows: htobe*/be*toh через byteswap, strcasecmp/strncasecmp через _stricmp/_strnicmp,
* memmem через inline-поиск (пустой образец возвращает начало), poll через WSAPoll, mkdir через _mkdir.
* utun_gettimeofday — календарное Unix-время (не монотонное); Windows игнорирует tz.
* Windows pipe — _pipe(4096, _O_BINARY). fcntl: F_GETFL возвращает 0, F_SETFL с O_NONBLOCK включает
* неблокирующий режим; остальные флаги игнорируются, обратное переключение этим адаптером не выполняется.
*/
#ifndef PLATFORM_COMPAT_H
@@ -178,12 +184,12 @@ extern "C" {
#include <stdint.h>
// Generate cryptographically secure random bytes
// Returns 0 on success, -1 on error
// Заполняет buffer криптографическими случайными байтами: POSIX /dev/urandom, Windows BCryptGenRandom.
// buffer не NULL, len > 0 (Windows: помещается в ULONG). 0 — всё заполнено, -1 — ошибка/неполное чтение.
int random_bytes(uint8_t *buffer, size_t len);
// Get IPv4 address of interface by its index (ifindex)
// Returns IPv4 address in network byte order, 0 on error
// POSIX: getifaddrs; Windows: IP Helper. Адрес в network byte order, 0 при ошибке/отсутствии адреса.
uint32_t get_interface_ip_by_index(uint32_t netif_index);
// Get IPv6 address of interface by its index (ifindex)
@@ -200,15 +206,14 @@ int get_interface_ipv6_by_index(uint32_t netif_index, int temporary, uint8_t* ad
int get_interface_ipv6_addr_nl(uint32_t netif_index, int prefer_stable, uint8_t* addr_out);
// Determine the interface index for the default route (outgoing traffic)
// POSIX: UDP connect к фиксированному внешнему адресу, затем сопоставление локального IP с getifaddrs().
// POSIX: UDP connect к 8.8.8.8:53 или [2001:4860:4860::8888]:53, сопоставление локального IP с getifaddrs().
// Windows: GetBestInterfaceEx к тому же адресу. Результат — выбранный маршрут к этому адресу,
// который может отличаться от default route при более специфичных маршрутах.
// family: AF_INET or AF_INET6, returns ifindex (0 on failure)
uint32_t get_default_route_netif_index(int family);
// Классифицирует IPv4-адрес (network byte order):
// 1 = глобальный/публичный (маршрутизируемый в интернете),
// 0 = приватный, CGNAT, loopback, link-local, multicast или зарезервированный.
// Классифицирует IPv4 (network byte order) по встроенному списку: 0 для 0/8, 10/8, 127/8, 169.254/16,
// 172.16/12, 192.168/16, 100.64/10, 224/4 и 240/4; 1 для остальных. Это не проверка достижимости адреса.
int ip_is_public(uint32_t addr_be);
-81
View File
@@ -1,81 +0,0 @@
# 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 использует <endian.h>, на 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 |