1use crate::{address::AddressError, Address, Error, ProtocolError, Reply};
2use bytes::{BufMut, BytesMut};
3use std::io::Error as IoError;
4use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
5
6#[derive(Clone, Debug)]
16pub struct Response {
17 pub reply: Reply,
18 pub address: Address,
19}
20
21impl Response {
22 pub const fn new(reply: Reply, address: Address) -> Self {
23 Self { reply, 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 rep = r.read_u8().await?;
39 let rep = Reply::try_from(rep).map_err(|rep| ProtocolError::InvalidReply {
40 version: ver,
41 reply: rep,
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::InvalidAddressTypeInResponse {
50 version: ver,
51 reply: rep,
52 address_type: code,
53 })
54 }
55 })?;
56
57 Ok(Self::new(rep, 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.reply));
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}