docs [AI]
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
# Блок `rawcast` — локальный протокол сокет ⇄ кадр
|
||||
|
||||
Промежуточный формат между «локальной» стороной клиента (реальные TCP/UDP сокеты
|
||||
приложений) и протоколом туннеля [`nrxp`](../nrxp). Когда трафик приходит не из
|
||||
TUN напрямую, а из локальных соединений, его описывают компактным `RawCastFrame`,
|
||||
а `RawCastAdapter` переводит это в кадры NRXP и обратно.
|
||||
|
||||
> Детали — в rustdoc, модуль `rawcast`.
|
||||
|
||||
## Файлы
|
||||
|
||||
| Файл | Что внутри |
|
||||
|--------------|------------------------------------------------------------------|
|
||||
| `frame.rs` | `RawCastFrame` + enum'ы `LocalProtocol`/`RawCastEvent`, wire-формат. |
|
||||
| `adapter.rs` | `RawCastAdapter`: трансляция RawCast ⇄ NRXP-`Frame`. |
|
||||
|
||||
## Формат кадра
|
||||
|
||||
```text
|
||||
┌──────────┬───────┬───────────┬─────────┬──────────┬─────────────┬─────────┐
|
||||
│ protocol │ event │ socket_id │ dst_ip │ dst_port │ payload_len │ payload │
|
||||
│ 1 байт │ 1 б. │ 8 байт │ 4 байта │ 2 байта │ 2 байта │ N байт │
|
||||
└──────────┴───────┴───────────┴─────────┴──────────┴─────────────┴─────────┘
|
||||
└──────────────── LOCAL_HEADER_SIZE = 16 ────────────────┘
|
||||
```
|
||||
|
||||
## Ментальная модель
|
||||
|
||||
```text
|
||||
локальный сокет ─→ RawCastFrame ─to_nrxp──→ NRXP Frame ─→ туннель
|
||||
туннель ─→ NRXP Frame ─from_nrxp─→ RawCastFrame ─→ локальный сокет
|
||||
```
|
||||
|
||||
`socket_id` локальной стороны напрямую отображается в `stream_id` потока NRXP, так
|
||||
что мультиплексирование «бесплатно» переносится между двумя протоколами. ICMP в
|
||||
формате распознаётся, но ядром NRXP не проксируется.
|
||||
|
||||
## Связи
|
||||
|
||||
Потребитель — клиентская точка входа `ClientHandler::connect` ([`net`](../net)):
|
||||
она гоняет `RawCastFrame` между локальными соединениями ([`client`](../../../../client))
|
||||
и туннелем.
|
||||
@@ -1,3 +1,10 @@
|
||||
//! Трансляция между локальным протоколом RawCast и протоколом туннеля NRXP.
|
||||
//!
|
||||
//! [`RawCastAdapter`] — чистый «переводчик» без состояния. Соответствия:
|
||||
//! `socket_id` ⇄ `stream_id`, `(protocol, event)` ⇄ [`FrameType`]. Для `Connect`
|
||||
//! без явного payload адрес назначения упаковывается строкой `"ip:port"` — это
|
||||
//! то, что ожидает серверная сторона при открытии потока.
|
||||
|
||||
use bytes::Bytes;
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
@@ -6,9 +13,13 @@ use crate::{
|
||||
rawcast::frame::{LocalProtocol, RawCastEvent, RawCastFrame},
|
||||
};
|
||||
|
||||
/// Безсостоятельный конвертер RawCast ⇄ NRXP.
|
||||
pub struct RawCastAdapter;
|
||||
|
||||
impl RawCastAdapter {
|
||||
/// RawCast → NRXP. Маппит протокол+событие в [`FrameType`]; для `Connect`
|
||||
/// без payload подставляет адрес цели строкой `"ip:port"`. ICMP отвергается —
|
||||
/// ядро NRXP его не проксирует.
|
||||
pub(crate) fn to_nrxp(raw: RawCastFrame) -> Result<Frame, String> {
|
||||
let stream_id = raw.socket_id as u32;
|
||||
|
||||
@@ -40,6 +51,9 @@ impl RawCastAdapter {
|
||||
Ok(Frame::new(stream_id, frame_type, payload))
|
||||
}
|
||||
|
||||
/// NRXP → RawCast. Обратный перевод; `is_udp` задаёт протокол локального
|
||||
/// сокета (в NRXP-кадре эта информация частично растворена в типе). Кадры
|
||||
/// `Heartbeat` сюда попадать не должны — их обрабатывает muxer, не мост.
|
||||
pub(crate) fn from_nrxp(
|
||||
nrxp_frame: Frame,
|
||||
dst_ip: Ipv4Addr,
|
||||
|
||||
@@ -1,34 +1,61 @@
|
||||
//! Кадр локального протокола RawCast и его (де)сериализация.
|
||||
//!
|
||||
//! Wire-формат: 16-байтовый фиксированный заголовок + 2 байта длины payload +
|
||||
//! сам payload:
|
||||
//!
|
||||
//! ```text
|
||||
//! ┌──────────┬───────┬───────────┬─────────┬──────────┬─────────────┬─────────┐
|
||||
//! │ protocol │ event │ socket_id │ dst_ip │ dst_port │ payload_len │ payload │
|
||||
//! │ 1 байт │ 1 б. │ 8 байт │ 4 байта │ 2 байта │ 2 байта │ N байт │
|
||||
//! └──────────┴───────┴───────────┴─────────┴──────────┴─────────────┴─────────┘
|
||||
//! └──────────────── LOCAL_HEADER_SIZE = 16 ────────────────┘
|
||||
//! ```
|
||||
|
||||
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use crate::parser::Parser;
|
||||
|
||||
/// Транспортный протокол локального сокета.
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum LocalProtocol {
|
||||
Tcp = 0x01,
|
||||
Udp = 0x02,
|
||||
/// ICMP распознаётся в формате, но ядром NRXP не поддерживается (см. адаптер).
|
||||
Icmp = 0x03,
|
||||
}
|
||||
|
||||
/// Событие жизненного цикла локального сокета.
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum RawCastEvent {
|
||||
/// Новое соединение/сессия к цели.
|
||||
Connect = 0x01,
|
||||
/// Полезные данные.
|
||||
Data = 0x02,
|
||||
/// Закрытие соединения.
|
||||
Close = 0x03,
|
||||
}
|
||||
|
||||
/// Описание одного события локального сокета — единица обмена RawCast.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RawCastFrame {
|
||||
/// TCP/UDP/ICMP.
|
||||
pub protocol: LocalProtocol,
|
||||
/// Connect/Data/Close.
|
||||
pub event: RawCastEvent,
|
||||
/// Идентификатор локального сокета (→ `stream_id` в NRXP).
|
||||
pub socket_id: u64,
|
||||
/// Адрес назначения.
|
||||
pub dst_ip: Ipv4Addr,
|
||||
/// Порт назначения.
|
||||
pub dst_port: u16,
|
||||
/// Полезные данные (пусто для Connect/Close).
|
||||
pub payload: Bytes,
|
||||
}
|
||||
|
||||
/// Размер фиксированной части заголовка (без поля длины и payload) — 16 байт.
|
||||
const LOCAL_HEADER_SIZE: usize = 16;
|
||||
|
||||
impl RawCastFrame {
|
||||
@@ -50,18 +77,22 @@ impl RawCastFrame {
|
||||
}
|
||||
}
|
||||
|
||||
/// Кадр-событие открытия соединения (без payload).
|
||||
pub fn connect(protocol: LocalProtocol, id: u64, ip: Ipv4Addr, port: u16) -> Self {
|
||||
Self::new(protocol, RawCastEvent::Connect, id, ip, port, Bytes::new())
|
||||
}
|
||||
|
||||
/// Кадр с данными соединения.
|
||||
pub fn data(protocol: LocalProtocol, id: u64, ip: Ipv4Addr, port: u16, data: Bytes) -> Self {
|
||||
Self::new(protocol, RawCastEvent::Data, id, ip, port, data)
|
||||
}
|
||||
|
||||
/// Кадр-событие закрытия соединения (без payload).
|
||||
pub fn close(protocol: LocalProtocol, id: u64, ip: Ipv4Addr, port: u16) -> Self {
|
||||
Self::new(protocol, RawCastEvent::Close, id, ip, port, Bytes::new())
|
||||
}
|
||||
|
||||
/// Сериализует кадр в байты по wire-формату из обзора модуля.
|
||||
pub fn into_bytes(self) -> BytesMut {
|
||||
let total_size = LOCAL_HEADER_SIZE + 2 + self.payload.len();
|
||||
let mut buf = BytesMut::with_capacity(total_size);
|
||||
@@ -78,6 +109,9 @@ impl RawCastFrame {
|
||||
}
|
||||
}
|
||||
|
||||
/// Разбор кадра RawCast: `can_parse` подглядывает поле длины payload по
|
||||
/// смещению `LOCAL_HEADER_SIZE` и проверяет, что весь кадр на месте; `parse`
|
||||
/// читает фиксированный заголовок, затем payload.
|
||||
impl Parser for RawCastFrame {
|
||||
type Error = String;
|
||||
|
||||
|
||||
@@ -1,3 +1,28 @@
|
||||
//! # Блок RawCast (`rawcast`) — локальный протокол сокет ⇄ кадр
|
||||
//!
|
||||
//! Промежуточный формат между «локальной» стороной клиента (реальные TCP/UDP
|
||||
//! сокеты приложений) и протоколом туннеля [`nrxp`](crate::nrxp). Когда трафик
|
||||
//! приходит не из TUN, а из локальных соединений, его описывают компактным
|
||||
//! [`RawCastFrame`] — «что за сокет, какой протокол, куда, какое событие, данные» —
|
||||
//! а [`RawCastAdapter`] переводит это в кадры NRXP и обратно.
|
||||
//!
|
||||
//! ## Состав блока
|
||||
//!
|
||||
//! | Файл | Ответственность |
|
||||
//! |-------------|------------------------------------------------------------------|
|
||||
//! | [`frame`] | [`RawCastFrame`] + enum'ы [`LocalProtocol`]/[`RawCastEvent`], wire-формат. |
|
||||
//! | [`adapter`] | [`RawCastAdapter`]: трансляция RawCast ⇄ NRXP-[`Frame`](crate::nrxp).|
|
||||
//!
|
||||
//! ## Связь с остальным
|
||||
//!
|
||||
//! ```text
|
||||
//! локальный сокет ──→ RawCastFrame ──RawCastAdapter::to_nrxp──→ NRXP Frame ──→ туннель
|
||||
//! туннель ──→ NRXP Frame ──RawCastAdapter::from_nrxp──→ RawCastFrame ──→ локальный сокет
|
||||
//! ```
|
||||
//!
|
||||
//! `socket_id` локальной стороны напрямую отображается в `stream_id` потока NRXP,
|
||||
//! так что мультиплексирование «бесплатно» переносится между двумя протоколами.
|
||||
|
||||
mod adapter;
|
||||
mod frame;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user