2026-03-24 00:44:52 +03:00
2026-03-24 00:44:52 +03:00

Internet Protocol over Incidental Medium

IPoIM - это средство для туннелирования SOCKS5 соединения через среду передачи, которая не предназначена для туннелирования таких соединений. IPoIM разрабатывается в расчёте на то, что к нему можно без больших усилий дописывать расширения на языке C.

Терминология

  • среда передачи - то, через что передаются данные. Например, расширение vk-msg реализует передачу данные через сообщения ВК. Значит, в контексте расширения vk-msg "отправить данные через среду передачи" означает "отправить данные, закодировав их в сообщение"; а "принятие данных из среды передачи" - "принятие сообщения в ВК и его декодировка в двоичный вид".

Архитектура

  • main.c - входная точка приложения, оркестратор
  • event_loop.c, event_loop.h - реализация событийного цикла
    Здесь реализована асинхронная обработка событий через epoll
  • connection.c, connection.h - реализация соединения
    Здесь реализован контроль за существующим соединением.
  • client.c, client.h - реализация клиента
    Здесь реализовано установление соединения с сервером.
  • server.c, server.h - реализация сервера
    Здесь реализован сервер.
  • priv_medium.c, priv_medium.h
    Здесь реализованы внутренние функции IPoIM, связанные с Medium API. Эти функции не должны вызываться из кода расширений.
  • medium.c, medium.h
    Здесь реализованы функции Medium API, которые вызываются из кода расширения.
  • mediums/medium_<NAME>.c, mediums/medium_<NAME>.h
    Реализация расширений. Например, файлы medium_vk_msg.c и medium_vk_msg.h реализуют среду передачи vk-msg.

Разработка расширений

Расширение в своем заголовочном файле должно реализовывать функцию void medium_<NAME>_init(), которая инициализирует всё необходимое для работы расширения. Функция должна вызвать medium_set_callbacks(...), чтобы IPoIM могло взаимодействовать с расширением. Кроме этого расширение должно инициализировать всё, что ему необходимо для работы.

Также расширение должно реализовывать функцию void medium_<NAME>_deinit(), которая освобождает ресурсы и выполняет "правильное" завершение всего, что было инициализировано в ходе работы расширения.

Medium API

IPoIM реализует функции, которые позволяют расширению общаться с остальным приложением:

  • void medium_epoll_ctl(int op, int fd, struct epoll_event *ev)
    • Что делает:
      • Вызывает epoll_ctl для дескриптора epoll, который отвечает за событийный цикл
    • Когда вызывать:
      • Когда нужно добавить, модифицировать или удалить описание файлового дескриптора в epoll
    • Заметки:
      • Если был вызван close(...) для файлового дескриптора, то не нужно вызывать эту функцию, чтобы удалить описание дескриптора из epoll. Ядро Linux само удаляет описание из epoll, если дескриптор закрывается
  • void medium_set_callbacks(/* колбеки в порядке их перечисления в следующей главе */)
    • Что делает:
      • Сообщает IPoIM, какие функции соответствуют каким колбекам
    • Когда вызывать:
      • Инициализация расширения
    • Заметки: нет
  • void medium_on_recv_data(const void *data, int32_t size)
    • Что делает:
      • Сообщает IPoIM, что из среды передачи были получены данные
    • Когда вызывать:
      • При получении данных из среды передачи
    • Заметки:
      • No-op, если data == NULL или size <= 0
  • void medium_set_ready_to_send(bool state)
    • Что делает:
      • Сообщает IPoIM, готово ли расширение к вызову cbmed_on_send_data(...)
    • Когда вызывать:
      • При изменении готовности к вызову cbmed_on_send_data(...) и при инициализации
    • Заметки:
      • Изначально IPoIM предполагает, что среда передачи недоступна. Поэтому эта функция должна быть вызвана, как только расширение становится готовым к вызову cbmed_on_send_data(...) после инициализации
  • void medium_set_max_send_size(int32_t size)
    • Что делает:
      • Сообщает IPoIM, какое максимальное количество байтов можно передать cbmed_on_send_data(...)
    • Когда вызывать:
      • При изменении максимального количества байтов cbmed_on_send_data(...)
    • Заметки:
      • Изначально IPoIM предполагает, что среда передачи может передать 1024 Б за один вызов cbmed_on_send_data(...)
      • Не допускается size <= 0

Необходимые колбеки

Все колбеки, которые вызывает IPoIM рекомендуется называть с префиксом cbmed_ (callback medium).

Время от времени IPoIM обращается к расширению, чтобы отправить данные. Чтобы IPoIM мог это делать, расширение должно реализовывать следующие колбеки:

  • void cbmed_on_fd_event(int fd, uint32_t events)
    • Когда вызвается:
      • С файловым дескриптором, добавленным при помощи medium_epoll_ctl(...), что-то случилось
    • Желаемый исход:
      • IPoIM ожидает, что расширение выполнит нужные действия над файловыми дескрипторами, которые оно добавило в epoll
    • Аргументы:
      • fd - файловый дескриптор
      • events - битовая маска событий (см man epoll_ctl)
    • Возвращаемое значение: нет
    • Заметки: нет
  • int32_t cbmed_on_send_data(const void *data, int32_t size)
    • Когда вызвается:
      • IPoIM хочет отправить данные через среду передачи
    • Желаемый исход:
      • IPoIM ожидает, что после вызова этого колбека, данные отправлены или запланированы к отправке
    • Аргументы:
      • data - двоичные данные, которые нужно отправить через среду передачи
      • size - размер двоичный данных в байтах
    • Возвращаемое значение:
      • В случае успеха колбек должен вернуть число байтов, ушедших в среду передачи
      • Если передача провалена, то колбек должен -1
    • Заметки:
      • Гарантируется size > 0
      • Гарантируется size <= max_send_size (см. medium_set_max_send_size(...))
      • Гарантируется, что этот колбек не будет вызван, если расширение не сообщило, что оно готово к отправке данных через среду передачи (см. medium_set_ready_to_send(...))
Description
Internet Protocol over Incidental Medium
Readme 69 KiB
Languages
C 99.1%
Shell 0.9%