Files
ipoim/README.md
2026-03-24 00:36:54 +03:00

102 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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, uint32_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(uint32_t size)`**
- **Что делает:**
- Сообщает IPoIM, какое максимальное количество байтов можно передать `cbmed_on_send_data(...)`
- **Когда вызывать:**
- При изменении максимального количества байтов `cbmed_on_send_data(...)`
- **Заметки:**
- Изначально IPoIM предполагает, что среда передачи может передать 1024 Б за один вызов `cbmed_on_send_data(...)`
### Необходимые колбеки
Все колбеки, которые вызывает 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, uint32_t size)`**
- **Когда вызвается:**
- IPoIM хочет отправить данные через среду передачи
- **Желаемый исход:**
- IPoIM ожидает, что после вызова этого колбека, данные отправлены или запланированы к отправке
- **Аргументы:**
- `data` - двоичные данные, которые нужно отправить через среду передачи
- `size` - размер двоичный данных в байтах
- **Возвращаемое значение:**
- В случае успеха колбек должен вернуть `size`
- Если передача провалена, то колбек должен вернуть любое другое значение
- **Заметки**:
- Гарантируется `size > 0`
- Гарантируется `size <= max_send_size` (см. `medium_set_max_send_size(...)`)
- Гарантируется, что этот колбек не будет вызван, если расширение не сообщило, что оно готово к отправке данных через среду передачи (см. `medium_set_ready_to_send(...)`)