socks5_impl/server/connection/
bind.rs

1use crate::protocol::{Address, AsyncStreamOperation, Reply, Response};
2use std::{
3    marker::PhantomData,
4    net::SocketAddr,
5    pin::Pin,
6    task::{Context, Poll},
7    time::Duration,
8};
9use tokio::{
10    io::{AsyncRead, AsyncWrite, AsyncWriteExt, ReadBuf},
11    net::{
12        TcpStream,
13        tcp::{ReadHalf, WriteHalf},
14    },
15};
16
17/// Socks5 command type `Bind`
18///
19/// By [`wait_request`](crate::server::connection::Authenticated::wait_request)
20/// on an [`Authenticated`](crate::server::connection::Authenticated) from SOCKS5 client,
21/// you may get a `Bind<NeedFirstReply>`. After replying the client 2 times
22/// using [`reply()`](crate::server::connection::Bind::reply),
23/// you will get a `Bind<Ready>`, which can be used as a regular async TCP stream.
24///
25/// A `Bind<S>` can be converted to a regular tokio [`TcpStream`](https://docs.rs/tokio/latest/tokio/net/struct.TcpStream.html) by using the `From` trait.
26#[derive(Debug)]
27pub struct Bind<S> {
28    stream: TcpStream,
29    _state: PhantomData<S>,
30}
31
32/// Marker type indicating that the connection needs its first reply.
33#[derive(Debug, Default)]
34pub struct NeedFirstReply;
35
36/// Marker type indicating that the connection needs its second reply.
37#[derive(Debug, Default)]
38pub struct NeedSecondReply;
39
40/// Marker type indicating that the connection is ready to use as a regular TCP stream.
41#[derive(Debug, Default)]
42pub struct Ready;
43
44impl Bind<NeedFirstReply> {
45    #[inline]
46    pub(super) fn new(stream: TcpStream) -> Self {
47        Self {
48            stream,
49            _state: PhantomData,
50        }
51    }
52
53    /// Reply to the SOCKS5 client with the given reply and address.
54    ///
55    /// If encountered an error while writing the reply, the error alongside the original `TcpStream` is returned.
56    pub async fn reply(mut self, reply: Reply, addr: Address) -> std::io::Result<Bind<NeedSecondReply>> {
57        let resp = Response::new(reply, addr);
58        resp.write_to_async_stream(&mut self.stream).await?;
59        Ok(Bind::<NeedSecondReply>::new(self.stream))
60    }
61
62    /// Causes the other peer to receive a read of length 0, indicating that no more data will be sent. This only closes the stream in one direction.
63    #[inline]
64    pub async fn shutdown(&mut self) -> std::io::Result<()> {
65        self.stream.shutdown().await
66    }
67
68    /// Returns the local address that this stream is bound to.
69    #[inline]
70    pub fn local_addr(&self) -> std::io::Result<SocketAddr> {
71        self.stream.local_addr()
72    }
73
74    /// Returns the remote address that this stream is connected to.
75    #[inline]
76    pub fn peer_addr(&self) -> std::io::Result<SocketAddr> {
77        self.stream.peer_addr()
78    }
79
80    /// Reads the linger duration for this socket by getting the `SO_LINGER` option.
81    ///
82    /// For more information about this option, see [`set_linger`](crate::server::connection::Bind::set_linger).
83    #[inline]
84    pub fn linger(&self) -> std::io::Result<Option<Duration>> {
85        self.stream.linger()
86    }
87
88    /// Sets the linger duration of this socket by setting the `SO_LINGER` option.
89    ///
90    /// This option controls the action taken when a stream has unsent messages and the stream is closed.
91    /// If `SO_LINGER` is set, the system shall block the process until it can transmit the data or until the time expires.
92    ///
93    /// If `SO_LINGER` is not specified, and the stream is closed, the system handles the call in a way
94    /// that allows the process to continue as quickly as possible.
95    #[inline]
96    pub fn set_linger(&self, dur: Option<Duration>) -> std::io::Result<()> {
97        self.stream.set_linger(dur)
98    }
99
100    /// Gets the value of the `TCP_NODELAY` option on this socket.
101    ///
102    /// For more information about this option, see [`set_nodelay`](crate::server::connection::Bind::set_nodelay).
103    #[inline]
104    pub fn nodelay(&self) -> std::io::Result<bool> {
105        self.stream.nodelay()
106    }
107
108    /// Sets the value of the `TCP_NODELAY` option on this socket.
109    ///
110    /// If set, this option disables the Nagle algorithm. This means that segments are always sent as soon as possible,
111    /// even if there is only a small amount of data. When not set, data is buffered until there is a sufficient amount to send out,
112    /// thereby avoiding the frequent sending of small packets.
113    pub fn set_nodelay(&self, nodelay: bool) -> std::io::Result<()> {
114        self.stream.set_nodelay(nodelay)
115    }
116
117    /// Gets the value of the `IP_TTL` option for this socket.
118    ///
119    /// For more information about this option, see [`set_ttl`](crate::server::connection::Bind::set_ttl).
120    pub fn ttl(&self) -> std::io::Result<u32> {
121        self.stream.ttl()
122    }
123
124    /// Sets the value for the `IP_TTL` option on this socket.
125    ///
126    /// This value sets the time-to-live field that is used in every packet sent from this socket.
127    pub fn set_ttl(&self, ttl: u32) -> std::io::Result<()> {
128        self.stream.set_ttl(ttl)
129    }
130}
131
132impl Bind<NeedSecondReply> {
133    #[inline]
134    fn new(stream: TcpStream) -> Self {
135        Self {
136            stream,
137            _state: PhantomData,
138        }
139    }
140
141    /// Reply to the SOCKS5 client with the given reply and address.
142    ///
143    /// If encountered an error while writing the reply, the error alongside the original `TcpStream` is returned.
144    pub async fn reply(mut self, reply: Reply, addr: Address) -> Result<Bind<Ready>, (std::io::Error, TcpStream)> {
145        let resp = Response::new(reply, addr);
146
147        if let Err(err) = resp.write_to_async_stream(&mut self.stream).await {
148            return Err((err, self.stream));
149        }
150
151        Ok(Bind::<Ready>::new(self.stream))
152    }
153
154    /// Causes the other peer to receive a read of length 0, indicating that no more data will be sent. This only closes the stream in one direction.
155    #[inline]
156    pub async fn shutdown(&mut self) -> std::io::Result<()> {
157        self.stream.shutdown().await
158    }
159
160    /// Returns the local address that this stream is bound to.
161    #[inline]
162    pub fn local_addr(&self) -> std::io::Result<SocketAddr> {
163        self.stream.local_addr()
164    }
165
166    /// Returns the remote address that this stream is connected to.
167    #[inline]
168    pub fn peer_addr(&self) -> std::io::Result<SocketAddr> {
169        self.stream.peer_addr()
170    }
171
172    /// Reads the linger duration for this socket by getting the `SO_LINGER` option.
173    ///
174    /// For more information about this option, see [`set_linger`](crate::server::connection::Bind::set_linger).
175    #[inline]
176    pub fn linger(&self) -> std::io::Result<Option<Duration>> {
177        self.stream.linger()
178    }
179
180    /// Sets the linger duration of this socket by setting the `SO_LINGER` option.
181    ///
182    /// This option controls the action taken when a stream has unsent messages and the stream is closed.
183    /// If `SO_LINGER` is set, the system shall block the process until it can transmit the data or until the time expires.
184    ///
185    /// If `SO_LINGER` is not specified, and the stream is closed, the system handles the call in a way
186    /// that allows the process to continue as quickly as possible.
187    #[inline]
188    pub fn set_linger(&self, dur: Option<Duration>) -> std::io::Result<()> {
189        self.stream.set_linger(dur)
190    }
191
192    /// Gets the value of the `TCP_NODELAY` option on this socket.
193    ///
194    /// For more information about this option, see
195    /// [`set_nodelay`](crate::server::connection::Bind::set_nodelay).
196    #[inline]
197    pub fn nodelay(&self) -> std::io::Result<bool> {
198        self.stream.nodelay()
199    }
200
201    /// Sets the value of the `TCP_NODELAY` option on this socket.
202    ///
203    /// If set, this option disables the Nagle algorithm. This means that segments are always sent as soon as possible,
204    /// even if there is only a small amount of data. When not set, data is buffered until there is a sufficient amount to send out,
205    /// thereby avoiding the frequent sending of small packets.
206    pub fn set_nodelay(&self, nodelay: bool) -> std::io::Result<()> {
207        self.stream.set_nodelay(nodelay)
208    }
209
210    /// Gets the value of the `IP_TTL` option for this socket.
211    ///
212    /// For more information about this option, see [`set_ttl`](crate::server::connection::Bind::set_ttl).
213    pub fn ttl(&self) -> std::io::Result<u32> {
214        self.stream.ttl()
215    }
216
217    /// Sets the value for the `IP_TTL` option on this socket.
218    ///
219    /// This value sets the time-to-live field that is used in every packet sent from this socket.
220    pub fn set_ttl(&self, ttl: u32) -> std::io::Result<()> {
221        self.stream.set_ttl(ttl)
222    }
223}
224
225impl Bind<Ready> {
226    #[inline]
227    fn new(stream: TcpStream) -> Self {
228        Self {
229            stream,
230            _state: PhantomData,
231        }
232    }
233
234    /// Split the connection into a read and a write half.
235    #[inline]
236    pub fn split(&mut self) -> (ReadHalf, WriteHalf) {
237        self.stream.split()
238    }
239}
240
241impl std::ops::Deref for Bind<Ready> {
242    type Target = TcpStream;
243
244    #[inline]
245    fn deref(&self) -> &Self::Target {
246        &self.stream
247    }
248}
249
250impl std::ops::DerefMut for Bind<Ready> {
251    #[inline]
252    fn deref_mut(&mut self) -> &mut Self::Target {
253        &mut self.stream
254    }
255}
256
257impl AsyncRead for Bind<Ready> {
258    #[inline]
259    fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll<std::io::Result<()>> {
260        Pin::new(&mut self.stream).poll_read(cx, buf)
261    }
262}
263
264impl AsyncWrite for Bind<Ready> {
265    #[inline]
266    fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<std::io::Result<usize>> {
267        Pin::new(&mut self.stream).poll_write(cx, buf)
268    }
269
270    #[inline]
271    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
272        Pin::new(&mut self.stream).poll_flush(cx)
273    }
274
275    #[inline]
276    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
277        Pin::new(&mut self.stream).poll_shutdown(cx)
278    }
279}
280
281impl<S> From<Bind<S>> for TcpStream {
282    #[inline]
283    fn from(conn: Bind<S>) -> Self {
284        conn.stream
285    }
286}