socks5_proto/
request.rs

1use crate::{address::AddressError, Address, Command, Error, ProtocolError};
2use bytes::{BufMut, BytesMut};
3use std::io::Error as IoError;
4use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
5
6/// SOCKS5 request
7///
8/// ```plain
9/// +-----+-----+-------+------+----------+----------+
10/// | VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
11/// +-----+-----+-------+------+----------+----------+
12/// |  1  |  1  | X'00' |  1   | Variable |    2     |
13/// +-----+-----+-------+------+----------+----------+
14/// ```
15#[derive(Clone, Debug)]
16pub struct Request {
17    pub command: Command,
18    pub address: Address,
19}
20
21impl Request {
22    pub const fn new(command: Command, address: Address) -> Self {
23        Self { command, address }
24    }
25
26    pub async fn read_from<R>(r: &mut R) -> Result<Self, Error>
27    where
28        R: AsyncRead + Unpin,
29    {
30        let ver = r.read_u8().await?;
31
32        if ver != crate::SOCKS_VERSION {
33            return Err(Error::Protocol(ProtocolError::ProtocolVersion {
34                version: ver,
35            }));
36        }
37
38        let cmd = r.read_u8().await?;
39        let cmd = Command::try_from(cmd).map_err(|cmd| ProtocolError::InvalidCommand {
40            version: ver,
41            command: cmd,
42        })?;
43
44        let _ = r.read_u8().await?;
45
46        let addr = Address::read_from(r).await.map_err(|err| match err {
47            AddressError::Io(err) => Error::Io(err),
48            AddressError::InvalidType(code) => {
49                Error::Protocol(ProtocolError::InvalidAddressTypeInRequest {
50                    version: ver,
51                    command: cmd,
52                    address_type: code,
53                })
54            }
55        })?;
56
57        Ok(Self::new(cmd, addr))
58    }
59
60    pub async fn write_to<W>(&self, w: &mut W) -> Result<(), IoError>
61    where
62        W: AsyncWrite + Unpin,
63    {
64        let mut buf = BytesMut::with_capacity(self.serialized_len());
65        self.write_to_buf(&mut buf);
66        w.write_all(&buf).await?;
67
68        Ok(())
69    }
70
71    pub fn write_to_buf<B: BufMut>(&self, buf: &mut B) {
72        buf.put_u8(crate::SOCKS_VERSION);
73        buf.put_u8(u8::from(self.command));
74        buf.put_u8(0x00);
75        self.address.write_to_buf(buf);
76    }
77
78    pub fn serialized_len(&self) -> usize {
79        1 + 1 + 1 + self.address.serialized_len()
80    }
81}