use webparse::{Buf, http2::frame::{read_u24, encode_u24}, BufMut};
use crate::{Helper, MappingConfig, ProxyResult};
use super::{ProtCreate, ProtClose, ProtData, ProtFlag, ProtKind, ProtMapping, ProtToken};
#[derive(Debug)]
pub struct ProtFrameHeader {
pub length: u32,
kind: ProtKind,
flag: ProtFlag,
sock_map: u64,
}
#[derive(Debug)]
pub enum ProtFrame {
Create(ProtCreate),
Close(ProtClose),
Data(ProtData),
Token(ProtToken),
Mapping(ProtMapping),
}
impl ProtFrameHeader {
pub const FRAME_HEADER_BYTES: usize = 12;
pub fn new(kind: ProtKind, flag: ProtFlag, sock_map: u64) -> ProtFrameHeader {
ProtFrameHeader {
length: 0,
kind,
flag,
sock_map,
}
}
pub fn sock_map(&self) -> u64 {
self.sock_map
}
pub fn flag(&self) -> ProtFlag {
self.flag
}
#[inline]
pub fn parse<T: Buf>(buffer: &mut T) -> ProxyResult<ProtFrameHeader> {
if buffer.remaining() < Self::FRAME_HEADER_BYTES {
return Err(crate::ProxyError::TooShort);
}
let length = read_u24(buffer);
Self::parse_by_len(buffer, length)
}
#[inline]
pub fn parse_by_len<T: Buf>(buffer: &mut T, length: u32) -> ProxyResult<ProtFrameHeader> {
if buffer.remaining() < Self::FRAME_HEADER_BYTES - 3 {
return Err(crate::ProxyError::TooShort);
}
let kind = buffer.get_u8();
let flag = buffer.get_u8();
let sock_map = read_u24(buffer);
let server_id = buffer.get_u32();
Ok(ProtFrameHeader {
length,
kind: ProtKind::new(kind),
flag: ProtFlag::new(flag),
sock_map: Helper::calc_sock_map(server_id, sock_map),
})
}
pub fn encode<B: Buf + BufMut>(&self, buffer: &mut B) -> ProxyResult<usize> {
let mut size = 0;
size += encode_u24(buffer, self.length);
size += buffer.put_u8(self.kind.encode());
size += buffer.put_u8(self.flag.bits());
size += encode_u24(buffer, self.sock_map as u32);
size += buffer.put_u32((self.sock_map >> 32) as u32);
Ok(size)
}
}
impl ProtFrame {
pub fn parse<T: Buf>(
header: ProtFrameHeader,
buf: T,
) -> ProxyResult<ProtFrame> {
let v = match header.kind {
ProtKind::Data => ProtFrame::Data(ProtData::parse(header, buf)?) ,
ProtKind::Create => ProtFrame::Create(ProtCreate::parse(header, buf)?),
ProtKind::Close => ProtFrame::Close(ProtClose::parse(header, buf)?),
ProtKind::Mapping => ProtFrame::Mapping(ProtMapping::parse(header, buf)?),
ProtKind::Token => ProtFrame::Token(ProtToken::parse(header, buf)?),
ProtKind::Unregistered => todo!(),
};
Ok(v)
}
pub fn encode<B: Buf + BufMut>(
self,
buf: &mut B,
) -> ProxyResult<usize> {
let size = match self {
ProtFrame::Data(s) => s.encode(buf)?,
ProtFrame::Create(s) => s.encode(buf)?,
ProtFrame::Close(s) => s.encode(buf)?,
ProtFrame::Mapping(s) => s.encode(buf)?,
ProtFrame::Token(s) => s.encode(buf)?,
};
Ok(size)
}
pub fn new_create(sock_map: u64, domain: Option<String>) -> Self {
Self::Create(ProtCreate::new(sock_map, domain))
}
pub fn new_close(sock_map: u64) -> Self {
Self::Close(ProtClose::new(sock_map))
}
pub fn new_close_reason(sock_map: u64, reason: String) -> Self {
Self::Close(ProtClose::new_by_reason(sock_map, reason))
}
pub fn new_data(sock_map: u64, data: Vec<u8>) -> Self {
Self::Data(ProtData::new(sock_map, data))
}
pub fn new_mapping(sock_map: u64, mappings: Vec<MappingConfig>) -> Self {
Self::Mapping(ProtMapping::new(sock_map, mappings))
}
pub fn new_token(username: String, password: String) -> Self {
Self::Token(ProtToken::new(username, password))
}
pub fn is_create(&self) -> bool {
match self {
ProtFrame::Create(_) => true,
_ => false
}
}
pub fn is_close(&self) -> bool {
match self {
ProtFrame::Close(_) => true,
_ => false
}
}
pub fn is_data(&self) -> bool {
match self {
ProtFrame::Data(_) => true,
_ => false
}
}
pub fn is_mapping(&self) -> bool {
match self {
ProtFrame::Mapping(_) => true,
_ => false
}
}
pub fn sock_map(&self) -> u64 {
match self {
ProtFrame::Data(s) => s.sock_map(),
ProtFrame::Create(s) => s.sock_map(),
ProtFrame::Close(s) => s.sock_map(),
ProtFrame::Mapping(s) => s.sock_map(),
ProtFrame::Token(s) => s.sock_map(),
}
}
}