Add README.md

This commit is contained in:
2026-03-24 00:36:54 +03:00
commit 5e387ead32

102
README.md Normal file
View File

@@ -0,0 +1,102 @@
# 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(...)`)