hyper_util/client/legacy/connect/proxy/socks/v4/
messages.rs
1use super::super::{ParsingError, SerializeError};
2
3use bytes::{Buf, BufMut, BytesMut};
4use std::net::SocketAddrV4;
5
6#[derive(Debug)]
14pub struct Request<'a>(pub &'a Address);
15
16#[derive(Debug)]
24pub struct Response(pub Status);
25
26#[derive(Debug)]
27pub enum Address {
28 Socket(SocketAddrV4),
29 Domain(String, u16),
30}
31
32#[derive(Debug, PartialEq)]
33pub enum Status {
34 Success = 90,
35 Failed = 91,
36 IdentFailure = 92,
37 IdentMismatch = 93,
38}
39
40impl Request<'_> {
41 pub fn write_to_buf<B: BufMut>(&self, mut buf: B) -> Result<usize, SerializeError> {
42 match self.0 {
43 Address::Socket(socket) => {
44 if buf.remaining_mut() < 10 {
45 return Err(SerializeError::WouldOverflow);
46 }
47
48 buf.put_u8(0x04); buf.put_u8(0x01); buf.put_u16(socket.port()); buf.put_slice(&socket.ip().octets()); buf.put_u8(0x00); buf.put_u8(0x00); Ok(10)
58 }
59
60 Address::Domain(domain, port) => {
61 if buf.remaining_mut() < 10 + domain.len() + 1 {
62 return Err(SerializeError::WouldOverflow);
63 }
64
65 buf.put_u8(0x04); buf.put_u8(0x01); buf.put_u16(*port); buf.put_slice(&[0x00, 0x00, 0x00, 0xFF]); buf.put_u8(0x00); buf.put_u8(0x00); buf.put_slice(domain.as_bytes()); buf.put_u8(0x00); Ok(10 + domain.len() + 1)
78 }
79 }
80 }
81}
82
83impl TryFrom<&mut BytesMut> for Response {
84 type Error = ParsingError;
85
86 fn try_from(buf: &mut BytesMut) -> Result<Self, Self::Error> {
87 if buf.remaining() < 8 {
88 return Err(ParsingError::Incomplete);
89 }
90
91 if buf.get_u8() != 0x00 {
92 return Err(ParsingError::Other);
93 }
94
95 let status = buf.get_u8().try_into()?;
96 let _addr = {
97 let port = buf.get_u16();
98 let mut ip = [0; 4];
99 buf.copy_to_slice(&mut ip);
100
101 SocketAddrV4::new(ip.into(), port)
102 };
103
104 return Ok(Self(status));
105 }
106}
107
108impl TryFrom<u8> for Status {
109 type Error = ParsingError;
110
111 fn try_from(byte: u8) -> Result<Self, Self::Error> {
112 Ok(match byte {
113 90 => Self::Success,
114 91 => Self::Failed,
115 92 => Self::IdentFailure,
116 93 => Self::IdentMismatch,
117 _ => return Err(ParsingError::Other),
118 })
119 }
120}
121
122impl std::fmt::Display for Status {
123 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124 f.write_str(match self {
125 Self::Success => "success",
126 Self::Failed => "server failed to execute command",
127 Self::IdentFailure => "server ident service failed",
128 Self::IdentMismatch => "server ident service did not recognise client identifier",
129 })
130 }
131}