use std::num::NonZeroU32;
use binrw::binrw;
use crate::arch;
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 80_u8)]
pub struct GlobalRequest<'b> {
#[bw(calc = context.as_ascii())]
kind: arch::Ascii<'b>,
pub want_reply: arch::Bool,
#[br(args(kind))]
pub context: GlobalRequestContext<'b>,
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big)]
#[br(import(kind: arch::Ascii<'_>))]
pub enum GlobalRequestContext<'b> {
#[br(pre_assert(kind == GlobalRequestContext::TCPIP_FORWARD))]
TcpipForward {
bind_address: arch::Bytes<'b>,
bind_port: u32,
},
#[br(pre_assert(kind == GlobalRequestContext::CANCEL_TCPIP_FORWARD))]
CancelTcpipForward {
bind_address: arch::Bytes<'b>,
bind_port: u32,
},
}
impl GlobalRequestContext<'_> {
const TCPIP_FORWARD: arch::Ascii<'static> = arch::ascii!("tcpip-forward");
const CANCEL_TCPIP_FORWARD: arch::Ascii<'static> = arch::ascii!("cancel-tcpip-forward");
pub fn as_ascii(&self) -> arch::Ascii<'static> {
match self {
Self::TcpipForward { .. } => Self::TCPIP_FORWARD,
Self::CancelTcpipForward { .. } => Self::CANCEL_TCPIP_FORWARD,
}
}
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 81_u8)]
pub struct RequestSuccess;
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 81_u8)]
pub struct ForwardingSuccess {
pub bound_port: u32,
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 82_u8)]
pub struct RequestFailure;
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 90_u8)]
pub struct ChannelOpen<'b> {
#[bw(calc = context.as_ascii())]
kind: arch::Ascii<'b>,
pub sender_channel: u32,
pub initial_window_size: u32,
pub maximum_packet_size: u32,
#[br(args(kind))]
pub context: ChannelOpenContext<'b>,
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big)]
#[br(import(kind: arch::Ascii<'_>))]
pub enum ChannelOpenContext<'b> {
#[br(pre_assert(kind == ChannelOpenContext::SESSION))]
Session,
#[br(pre_assert(kind == ChannelOpenContext::X11))]
X11 {
originator_address: arch::Ascii<'b>,
originator_port: u32,
},
#[br(pre_assert(kind == ChannelOpenContext::FORWARDED_TCPIP))]
ForwardedTcpip {
address: arch::Ascii<'b>,
port: u32,
originator_address: arch::Ascii<'b>,
originator_port: u32,
},
#[br(pre_assert(kind == ChannelOpenContext::DIRECT_TCPIP))]
DirectTcpip {
address: arch::Ascii<'b>,
port: u32,
originator_address: arch::Ascii<'b>,
originator_port: u32,
},
}
impl ChannelOpenContext<'_> {
const SESSION: arch::Ascii<'static> = arch::ascii!("session");
const X11: arch::Ascii<'static> = arch::ascii!("x11");
const FORWARDED_TCPIP: arch::Ascii<'static> = arch::ascii!("forwarded-tcpip");
const DIRECT_TCPIP: arch::Ascii<'static> = arch::ascii!("direct-tcpip");
pub fn as_ascii(&self) -> arch::Ascii<'static> {
match self {
Self::Session { .. } => Self::SESSION,
Self::X11 { .. } => Self::X11,
Self::ForwardedTcpip { .. } => Self::FORWARDED_TCPIP,
Self::DirectTcpip { .. } => Self::DIRECT_TCPIP,
}
}
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 91_u8)]
pub struct ChannelOpenConfirmation {
pub recipient_channel: u32,
pub sender_channel: u32,
pub initial_window_size: u32,
pub maximum_packet_size: u32,
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 92_u8)]
pub struct ChannelOpenFailure<'b> {
pub recipient_channel: u32,
pub reason: ChannelOpenFailureReason,
pub description: arch::Utf8<'b>,
pub language: arch::Ascii<'b>,
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big)]
pub enum ChannelOpenFailureReason {
#[brw(magic = 1_u32)]
AdministrativelyProhibited,
#[brw(magic = 2_u32)]
ConnectFailed,
#[brw(magic = 3_u32)]
UnknownChannelType,
#[brw(magic = 4_u32)]
ResourceShortage,
Other(u32),
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 93_u8)]
pub struct ChannelWindowAdjust {
pub recipient_channel: u32,
pub bytes_to_add: u32,
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 94_u8)]
pub struct ChannelData<'b> {
pub recipient_channel: u32,
pub data: arch::Bytes<'b>,
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 95_u8)]
pub struct ChannelExtendedData<'b> {
pub recipient_channel: u32,
pub data_type: NonZeroU32,
pub data: arch::Bytes<'b>,
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 96_u8)]
pub struct ChannelEof {
pub recipient_channel: u32,
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 97_u8)]
pub struct ChannelClose {
pub recipient_channel: u32,
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 98_u8)]
pub struct ChannelRequest<'b> {
pub recipient_channel: u32,
#[bw(calc = context.as_ascii())]
kind: arch::Ascii<'b>,
pub want_reply: arch::Bool,
#[br(args(kind))]
pub context: ChannelRequestContext<'b>,
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big)]
#[br(import(kind: arch::Ascii<'_>))]
pub enum ChannelRequestContext<'b> {
#[br(pre_assert(kind == ChannelRequestContext::PTY))]
Pty {
term: arch::Bytes<'b>,
width_chars: u32,
height_chars: u32,
width_pixels: u32,
height_pixels: u32,
modes: arch::Bytes<'b>,
},
#[br(pre_assert(kind == ChannelRequestContext::X11))]
X11 {
single_connection: arch::Bool,
x11_authentication_protocol: arch::Bytes<'b>,
x11_authentication_cookie: arch::Bytes<'b>,
x11_screen_number: u32,
},
#[br(pre_assert(kind == ChannelRequestContext::ENV))]
Env {
name: arch::Bytes<'b>,
value: arch::Bytes<'b>,
},
#[br(pre_assert(kind == ChannelRequestContext::SHELL))]
Shell,
#[br(pre_assert(kind == ChannelRequestContext::EXEC))]
Exec {
command: arch::Bytes<'b>,
},
#[br(pre_assert(kind == ChannelRequestContext::SUBSYSTEM))]
Subsystem {
name: arch::Bytes<'b>,
},
#[br(pre_assert(kind == ChannelRequestContext::WINDOW_CHANGE))]
WindowChange {
width_chars: u32,
height_chars: u32,
width_pixels: u32,
height_pixels: u32,
},
#[br(pre_assert(kind == ChannelRequestContext::XON_XOFF))]
XonXoff {
client_can_do: arch::Bool,
},
#[br(pre_assert(kind == ChannelRequestContext::SIGNAL))]
Signal {
name: arch::Bytes<'b>,
},
#[br(pre_assert(kind == ChannelRequestContext::EXIT_STATUS))]
ExitStatus {
code: u32,
},
#[br(pre_assert(kind == ChannelRequestContext::EXIT_SIGNAL))]
ExitSignal {
name: arch::Bytes<'b>,
core_dumped: arch::Bool,
error_message: arch::Utf8<'b>,
language: arch::Ascii<'b>,
},
}
impl ChannelRequestContext<'_> {
const PTY: arch::Ascii<'static> = arch::ascii!("pty-req");
const X11: arch::Ascii<'static> = arch::ascii!("x11-req");
const ENV: arch::Ascii<'static> = arch::ascii!("env");
const SHELL: arch::Ascii<'static> = arch::ascii!("shell");
const EXEC: arch::Ascii<'static> = arch::ascii!("exec");
const SUBSYSTEM: arch::Ascii<'static> = arch::ascii!("subsystem");
const WINDOW_CHANGE: arch::Ascii<'static> = arch::ascii!("window-change");
const XON_XOFF: arch::Ascii<'static> = arch::ascii!("xon-xoff");
const SIGNAL: arch::Ascii<'static> = arch::ascii!("signal");
const EXIT_STATUS: arch::Ascii<'static> = arch::ascii!("exit-status");
const EXIT_SIGNAL: arch::Ascii<'static> = arch::ascii!("exit-signal");
pub fn as_ascii(&self) -> arch::Ascii<'static> {
match self {
Self::Pty { .. } => Self::PTY,
Self::X11 { .. } => Self::X11,
Self::Env { .. } => Self::ENV,
Self::Shell { .. } => Self::SHELL,
Self::Exec { .. } => Self::EXEC,
Self::Subsystem { .. } => Self::SUBSYSTEM,
Self::WindowChange { .. } => Self::WINDOW_CHANGE,
Self::XonXoff { .. } => Self::XON_XOFF,
Self::Signal { .. } => Self::SIGNAL,
Self::ExitStatus { .. } => Self::EXIT_STATUS,
Self::ExitSignal { .. } => Self::EXIT_SIGNAL,
}
}
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 99_u8)]
pub struct ChannelSuccess {
pub recipient_channel: u32,
}
#[binrw]
#[derive(Debug, Clone)]
#[brw(big, magic = 100_u8)]
pub struct ChannelFailure {
pub recipient_channel: u32,
}