76 lines
4.2 KiB
C
76 lines
4.2 KiB
C
// socks_client.h — SOCKS5 клиент (для исходящих ETCP-линков через SOCKS-прокси)
|
|
//
|
|
// Модуль позволяет подключаться к пиру не напрямую, а через SOCKS5-прокси:
|
|
// - SOCKS5 CONNECT (TCP/STCP-линки) — socks_dial();
|
|
// - SOCKS5 UDP ASSOCIATE (UDP-линки) — socks_udp_associate() и далее.
|
|
//
|
|
// Модуль не знает про ETCP — только транспорт.
|
|
#ifndef SOCKS_CLIENT_H
|
|
#define SOCKS_CLIENT_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <stdint.h>
|
|
#include "../lib/socket_compat.h"
|
|
|
|
struct UASYNC;
|
|
|
|
// Конфигурация прокси. host — ip или домен; user/pass пустые = no-auth (метод 0x00).
|
|
struct socks_cfg {
|
|
char host[64];
|
|
uint16_t port;
|
|
char user[64];
|
|
char pass[64];
|
|
};
|
|
|
|
// ── SOCKS5 CONNECT (TCP) ──────────────────────────────────────────────
|
|
|
|
// Коллбэк завершения подключения:
|
|
// sock — готовый сокет (на нём можно делать STCP-хендшейк), err == 0;
|
|
// sock == SOCKET_INVALID при ошибке, err — код ошибки (errno).
|
|
typedef void (*socks_dial_cb)(socket_t sock, int err, void *arg);
|
|
|
|
// Асинхронно подключиться к прокси и выполнить SOCKS5 CONNECT к target_host:target_port.
|
|
// target_host может быть числовым IP или доменом (домен резолвит сам прокси).
|
|
// Возвращает handle (NULL при немедленной ошибке — тогда cb НЕ вызывается, ошибка залогирована).
|
|
void *socks_dial(struct UASYNC *ua, const struct socks_cfg *cfg,
|
|
const char *target_host, uint16_t target_port,
|
|
socks_dial_cb cb, void *arg, int timeout_tb);
|
|
|
|
// Отменить незавершённый dial: закрывает сокет, освобождает состояние, cb НЕ вызывается.
|
|
void socks_dial_cancel(void *h);
|
|
|
|
// ── SOCKS5 UDP ASSOCIATE (UDP) ────────────────────────────────────────
|
|
|
|
struct socks_udp;
|
|
|
|
// Коллбэк готовности ассоциации: err==0 → relay получен, можно слать через socks_udp_sendto.
|
|
typedef void (*socks_udp_ready_cb)(struct socks_udp *s, int err, void *arg);
|
|
|
|
// Открыть UDP ASSOCIATE к прокси (persistent TCP-control + relay). local_udp_fd — уже
|
|
// забинденный локальный UDP-сокет (reserved port), через него шлём на relay.
|
|
// При обрыве control-канала сессия автоматически пересоздаёт ассоциацию (backoff).
|
|
// Возвращает сессию (NULL только при ошибке аллокации/аргументов).
|
|
struct socks_udp *socks_udp_associate(struct UASYNC *ua, const struct socks_cfg *cfg,
|
|
socket_t local_udp_fd, socks_udp_ready_cb cb, void *arg);
|
|
|
|
// Отправить датаграмму пиру dst: обёртка в SOCKS-UDP заголовок + sendto(relay).
|
|
// -1 пока ассоциация не готова (или ошибка).
|
|
ssize_t socks_udp_sendto(struct socks_udp *s, const uint8_t *data, size_t len,
|
|
const struct sockaddr_storage *dst);
|
|
|
|
// Снять SOCKS-UDP заголовок с входящей датаграммы: вернуть payload и реальный src пира.
|
|
// Возвращает длину payload (<=0 при битом/неподходящем пакете).
|
|
ssize_t socks_udp_unwrap(const struct socks_udp *s, const uint8_t *raw, size_t raw_len,
|
|
uint8_t *payload, size_t cap, struct sockaddr_storage *src);
|
|
|
|
// Закрыть сессию: control-TCP, таймеры, память. Локальный UDP-сокет НЕ закрывается (чужой).
|
|
void socks_udp_destroy(struct socks_udp *s);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif // SOCKS_CLIENT_H
|