Skip to main content

ptrs/
lib.rs

1#![deny(missing_docs)]
2#![doc = include_str!("../README.md")]
3
4use std::{
5    net::{SocketAddrV4, SocketAddrV6},
6    pin::Pin,
7    time::{Duration, Instant},
8};
9
10use futures::Future; // , Sink, TryStream};
11use tokio::io::{AsyncRead, AsyncWrite};
12
13mod error;
14pub use error::Error;
15#[macro_use]
16pub mod args;
17mod helpers;
18pub use helpers::*;
19mod log;
20/// ORPort authentication and connection helpers.
21pub mod orport;
22
23/// Core trait for a pluggable transport, defining its builder types.
24pub trait PluggableTransport<InRW>
25where
26    InRW: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
27{
28    /// The client-side builder type for this transport.
29    type ClientBuilder: ClientBuilder<InRW>;
30    /// The server-side builder type for this transport.
31    type ServerBuilder: ServerBuilder<InRW>;
32
33    /// Returns a string identifier for this transport
34    fn name() -> String;
35
36    /// Return a fresh client builder for this transport.
37    fn client_builder() -> <Self as PluggableTransport<InRW>>::ClientBuilder;
38
39    /// Return a fresh server builder for this transport.
40    fn server_builder() -> <Self as PluggableTransport<InRW>>::ServerBuilder;
41}
42
43// ================================================================ //
44//                            Client                                //
45// ================================================================ //
46
47/// Client Transport Builder
48// Struct builder, passed by type and then built from default for each client
49// with params baked in as builder pattern.
50pub trait ClientBuilder<InRW>: Default + Clone
51where
52    InRW: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
53{
54    /// Error type produced by builder methods.
55    type Error: std::error::Error + Send + Sync;
56    /// The client transport produced by [`build`](ClientBuilder::build).
57    type ClientPT: ClientTransport<InRW, Self::Error>;
58    /// The underlying transport type (used for associated-type matching).
59    type Transport;
60
61    /// Returns a string identifier for this transport
62    fn method_name() -> String;
63
64    /// Builds a new PtCommonParameters.
65    ///
66    /// **Errors**
67    /// If a required field has not been initialized.
68    fn build(&self) -> Self::ClientPT;
69
70    /// Pluggable transport attempts to parse and validate options from a string,
71    /// typically using ['parse_smethod_args'].
72    fn options(&mut self, opts: &args::Args) -> Result<&mut Self, Self::Error>;
73
74    /// A path where the launched PT can store state.
75    fn statefile_location(&mut self, path: &str) -> Result<&mut Self, Self::Error>;
76
77    /// The maximum time we should wait for a pluggable transport binary to
78    /// report successful initialization. If `None`, a default value is used.
79    fn timeout(&mut self, timeout: Option<Duration>) -> Result<&mut Self, Self::Error>;
80
81    /// An IPv4 address to bind outgoing connections to (if specified).
82    ///
83    /// Leaving this out will mean the PT uses a sane default.
84    fn v4_bind_addr(&mut self, addr: SocketAddrV4) -> Result<&mut Self, Self::Error>;
85
86    /// An IPv6 address to bind outgoing connections to (if specified).
87    ///
88    /// Leaving this out will mean the PT uses a sane default.
89    fn v6_bind_addr(&mut self, addr: SocketAddrV6) -> Result<&mut Self, Self::Error>;
90}
91
92/// Client Transport
93pub trait ClientTransport<InRW, InErr>
94where
95    InRW: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
96{
97    /// Output stream type produced by the transport.
98    type OutRW: AsyncRead + AsyncWrite + Send + Unpin;
99    /// Error type produced by the transport.
100    type OutErr: std::error::Error + Send + Sync;
101    /// The builder type that creates this transport.
102    type Builder: ClientBuilder<InRW>;
103
104    /// Create a pluggable transport connection given a future that will return
105    /// a Read/Write object that can be used as the underlying socket for the
106    /// connection.
107    fn establish(self, input: Pin<F<InRW, InErr>>) -> Pin<F<Self::OutRW, Self::OutErr>>;
108
109    /// Create a connection for the pluggable transport client using the provided
110    /// (pre-existing/pre-connected) Read/Write object as the underlying socket.
111    fn wrap(self, io: InRW) -> Pin<F<Self::OutRW, Self::OutErr>>;
112
113    /// Returns a string identifier for this transport
114    fn method_name() -> String;
115}
116
117// ================================================================ //
118//                            Server                                //
119// ================================================================ //
120
121/// Server Transport
122// try using objects so we can accept and then handshake (proxy equivalent of
123// accept) as separate steps by the transport user.
124pub trait ServerTransport<InRW>
125where
126    InRW: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
127{
128    /// Output stream type produced by the server transport.
129    type OutRW: AsyncRead + AsyncWrite + Send + Unpin;
130    /// Error type produced by the server transport.
131    type OutErr: std::error::Error + Send + Sync;
132    /// The builder type that creates this transport.
133    type Builder: ServerBuilder<InRW>;
134
135    /// Create/accept a connection for the pluggable transport client using the
136    /// provided (pre-existing/pre-connected) Read/Write object as the
137    /// underlying socket.
138    ///
139    /// Uses `self` instead of `&self` to encourage/force use of reference
140    /// counted objects (Arc, Rc) for server implementations where the server
141    /// needs internal mutability across multiple threads concurrently.
142    fn reveal(self, io: InRW) -> Pin<F<Self::OutRW, Self::OutErr>>;
143
144    /// Returns a string identifier for this transport
145    fn method_name() -> String;
146}
147
148/// Server Transport builder interface
149pub trait ServerBuilder<InRW>: Default
150where
151    InRW: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
152{
153    /// The server transport produced by [`build`](ServerBuilder::build).
154    type ServerPT: ServerTransport<InRW>;
155    /// Error type produced by builder methods.
156    type Error: std::error::Error;
157    /// The underlying transport type (used for associated-type matching).
158    type Transport;
159
160    /// Returns a string identifier for this transport
161    fn method_name() -> String;
162
163    /// Builds a new PtCommonParameters.
164    ///
165    /// **Errors**
166    /// If a required field has not been initialized.
167    fn build(&self) -> Self::ServerPT;
168
169    /// Pluggable transport attempts to parse and validate options from a string,
170    /// typically using ['parse_smethod_args'].
171    fn options(&mut self, opts: &args::Args) -> Result<&mut Self, Self::Error>;
172
173    /// Returns a string or parameters that can be used by a ['ClientBuilder']
174    /// in the `options(...)` function to properly establish a connection with
175    /// this server based on the configuration of the server when this method
176    /// is called.
177    fn get_client_params(&self) -> String;
178
179    /// A path where the launched PT can store state.
180    fn statefile_location(&mut self, path: &str) -> Result<&mut Self, Self::Error>;
181
182    /// The maximum time we should wait for a pluggable transport binary to
183    /// report successful initialization. If `None`, a default value is used.
184    fn timeout(&mut self, timeout: Option<Duration>) -> Result<&mut Self, Self::Error>;
185
186    /// An IPv4 address to bind outgoing connections to (if specified).
187    ///
188    /// Leaving this out will mean the PT uses a sane default.
189    fn v4_bind_addr(&mut self, addr: SocketAddrV4) -> Result<&mut Self, Self::Error>;
190
191    /// An IPv6 address to bind outgoing connections to (if specified).
192    ///
193    /// Leaving this out will mean the PT uses a sane default.
194    fn v6_bind_addr(&mut self, addr: SocketAddrV6) -> Result<&mut Self, Self::Error>;
195}
196
197// ================================================================ //
198//                        Connections                               //
199// ================================================================ //
200
201/// Creator1 defines a stream creator that could be applied to either the input
202/// stream feature or the resulting stream future making them composable.
203pub trait Conn {
204    /// Output connection type.
205    type OutRW;
206    /// Error type for the connection future.
207    type OutErr;
208    /// Future that resolves to the connected stream.
209    type Future: Future<Output = Result<Self::OutRW, Self::OutErr>>;
210
211    /// Create a new connection future.
212    fn new() -> Self::Future;
213}
214
215/// In concept this trait provides extended functionality that can be appled to
216/// the client / server traits for creating connections / pluggable transports.
217/// this is still in a TODO state.
218pub trait ConnectExt: Conn {
219    /// Connect with an absolute deadline.
220    fn connect_with_deadline(
221        &mut self,
222        deadline: Instant,
223    ) -> Result<Self::Future, tokio::time::error::Elapsed>;
224    /// Connect with a relative timeout.
225    fn connect_with_timeout(
226        &mut self,
227        timeout: Duration,
228    ) -> Result<Self::Future, tokio::time::error::Elapsed>;
229}
230
231impl Conn for tokio::net::TcpStream {
232    type OutRW = Self;
233    type OutErr = std::io::Error;
234    type Future = Pin<F<Self::OutRW, Self::OutErr>>;
235
236    fn new() -> Self::Future {
237        let f = tokio::net::TcpStream::connect("127.0.0.1:9000");
238        Box::pin(f)
239    }
240}
241
242impl Conn for tokio::net::UdpSocket {
243    type OutErr = std::io::Error;
244    type OutRW = tokio::net::UdpSocket;
245    type Future = Pin<F<Self::OutRW, Self::OutErr>>;
246
247    fn new() -> Self::Future {
248        let f = tokio::net::UdpSocket::bind("127.0.0.1:9000");
249        Box::pin(f)
250    }
251}
252
253/// Future containing a generic result. We use this for functions that take
254/// and/or return futures that will produce Read/Write tunnels once awaited.
255pub type FutureResult<T, E> = Box<dyn Future<Output = Result<T, E>> + Send>;
256
257/// Future containing a generic result, shorthand for ['FutureResult']. We use
258/// this for functions that take and/or return futures that will produce
259/// Read/Write tunnels once awaited.
260pub(crate) type F<T, E> = FutureResult<T, E>;
261
262/// Future resolving to a TCP stream or its error.
263pub type TcpStreamFut = Pin<FutureResult<tokio::net::TcpStream, std::io::Error>>;
264
265/// Future resolving to a UDP socket or its error.
266pub type UdpSocketFut = Pin<FutureResult<tokio::net::UdpSocket, std::io::Error>>;
267
268#[cfg(test)]
269mod passthrough;