### Compat Construction Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/async-socket.md Example of creating a Compat wrapper for a smol::net::TcpStream. ```rust use tokio_socks::io::Compat; use smol::net::TcpStream; let socket = TcpStream::connect("proxy:1080").await?; let compat = Compat::new(socket); ``` -------------------------------- ### Compat AsRef/AsMut Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/async-socket.md Example demonstrating how to get references to the underlying socket using as_ref and as_mut on a Compat wrapper. ```rust let mut compat = Compat::new(socket); let socket_ref = compat.as_ref(); let socket_mut = compat.as_mut(); ``` -------------------------------- ### Compat into_inner Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/async-socket.md Example of consuming a Compat wrapper to retrieve the original socket. ```rust let compat = Compat::new(some_socket); let original = compat.into_inner(); ``` -------------------------------- ### Perform HTTP GET Request Through a Proxy Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/USAGE_EXAMPLES.md A complete example demonstrating how to establish a SOCKS connection, send an HTTP GET request, and read the response using `tokio-socks` and Tokio's I/O utilities. ```rust use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio_socks::tcp::Socks5Stream; async fn http_get_through_proxy( proxy: &str, host: &str, path: &str, ) -> Result> { // Connect to target through proxy let mut stream = Socks5Stream::connect(proxy, &format!("{}:80", host)).await?; // Send HTTP request let request = format!("GET {} HTTP/1.1\r\nHost: {}\r\nConnection: close\r\n\r\n", path, host); stream.write_all(request.as_bytes()).await?; // Read response let mut response = String::new(); stream.read_to_string(&mut response).await?; Ok(response) } #[tokio::main] async fn main() -> Result<(), Box> { let response = http_get_through_proxy( "127.0.0.1:1080", "example.com", "/" ).await?; println!("Response:\n{}", response); Ok(()) } ``` -------------------------------- ### SOCKS5 Echo Server Workflow Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks5-listener.md An example demonstrating a full echo server workflow using SOCKS5Listener. It binds, retrieves the bind address, accepts a connection, and echoes data back to the client. ```rust use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio_socks::tcp::Socks5Listener; async fn echo_server() -> Result<(), Box> { // Initiate BIND on proxy let listener = Socks5Listener::bind("127.0.0.1:1080", "0.0.0.0:0").await?; // Get the address remote should connect to let bind_addr = listener.bind_addr(); println!("Remote should connect to: {}", bind_addr); // In a real scenario, send bind_addr to the remote process // For now, we just wait... // Accept incoming connection let mut stream = listener.accept().await?; println!("Connection accepted from {}", stream.target_addr()); // Echo everything received back let mut buf = [0; 1024]; loop { let n = stream.read(&mut buf).await?; if n == 0 { break; // Connection closed } stream.write_all(&buf[..n]).await?; } Ok(()) } ``` -------------------------------- ### Minimal Build Example (No Tokio) Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/USAGE_EXAMPLES.md Shows how to use tokio-socks with a custom async runtime by providing your own socket implementation. This build requires `default-features = false`. ```rust // Must provide custom socket implementing AsyncSocket // Use with any futures-io based runtime use your_async_runtime::TcpStream; use tokio_socks::tcp::Socks5Stream; async fn example() -> Result<(), Box> { let socket = TcpStream::connect("proxy:1080").await?; let stream = Socks5Stream::connect_with_socket(socket, "target:80").await?; Ok(()) } ``` -------------------------------- ### ToProxyAddrs Stream Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/target-address.md Demonstrates using the to_proxy_addrs method to get a stream of proxy addresses from a string and iterating through them to try connections. ```rust use tokio_socks::ToProxyAddrs; use futures_util::StreamExt; async fn connect_to_proxies() -> Result<(), Box> { let proxy_addrs = "proxy.example.com:1080".to_proxy_addrs(); let mut stream = proxy_addrs; while let Some(result) = stream.next().await { let addr = result?; println!("Trying proxy: {}", addr); } Ok(()) } ``` -------------------------------- ### Module Usage Examples Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/modules.md Demonstrates how to use the io module's AsyncSocket and Compat traits with different async runtimes like Tokio and futures-io. ```rust use tokio_socks::io::{AsyncSocket, Compat}; use tokio_socks::tcp::Socks5Stream; // Tokio usage (AsyncSocket automatic) use tokio::net::TcpStream; let stream = Socks5Stream::connect("proxy:1080", "target:80").await?; // Futures-io usage (explicit Compat wrapper) use smol::net::TcpStream as SmolTcpStream; let socket = SmolTcpStream::connect("proxy:1080").await?; let socket = Compat::new(socket); let stream = Socks5Stream::connect_with_socket(socket, "target:80").await?; ``` -------------------------------- ### Tor-Enabled Build Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/USAGE_EXAMPLES.md Demonstrates Tor DNS resolution and connecting to an onion site using the 'tor' feature. Ensure the Tor SOCKS proxy is running on localhost:9050. ```rust use tokio_socks::tcp::Socks5Stream; #[tokio::main] async fn main() -> Result<(), Box> { // Tor DNS resolution let ip = Socks5Stream::tor_resolve("127.0.0.1:9050", "example.com:0").await?; println!("Tor resolved: {:?}", ip); // Connect to onion site let stream = Socks5Stream::connect( "127.0.0.1:9050", "example.onion:80" ).await?; Ok(()) } ``` -------------------------------- ### Rust: PasswordAuthFailure Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Shows how to handle PasswordAuthFailure, which occurs during SOCKS5 username/password authentication when the provided credentials are incorrect. It includes catching specific failure codes. ```rust let result = Socks5Stream::connect_with_password( "auth.proxy:1080", "target:80", "user", "wrongpass" ).await; // Error: PasswordAuthFailure(1) ``` ```rust match result { Err(Error::PasswordAuthFailure(code)) => { eprintln!("Auth failed with code: {}", code); } _ => {} } ``` -------------------------------- ### Tokio Runtime Configuration Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/configuration.md Example of using tokio-socks with the default Tokio runtime, utilizing native tokio socket types like TcpStream. ```rust use tokio::net::TcpStream; use tokio_socks::tcp::Socks5Stream; #[tokio::main] async fn main() -> Result<(), Box> { let stream = Socks5Stream::connect("127.0.0.1:1080", "example.com:80").await?; Ok(()) } ``` -------------------------------- ### Tokio-Socks API Reference Overview Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/DOCUMENTATION_SUMMARY.txt This section provides an overview of the Tokio-Socks API reference, guiding users to specific documentation for different components of the library. It highlights the structure of the documentation, including the README for general information, INDEX for navigation, the api-reference directory for detailed method documentation, USAGE_EXAMPLES for practical code patterns, and errors.md for failure modes. ```APIDOC ## Tokio-Socks API Reference This documentation provides a comprehensive technical reference for the Tokio-Socks library, focusing on its public API for SOCKS protocol implementation. ### Navigation - **START HERE**: `README.md` provides an overview and quick reference. - **NAVIGATE**: `INDEX.md` guides users to relevant documentation. - **REFERENCE**: The `api-reference/` directory contains detailed method documentation for the following modules: - `socks5-stream.md`: Documentation for SOCKS5 stream operations. - `async-socket.md`: Documentation for asynchronous socket operations. - `socks4-stream.md`: Documentation for SOCKS4 stream operations. - `socks5-listener.md`: Documentation for SOCKS5 listener operations. - `socks4-listener.md`: Documentation for SOCKS4 listener operations. - `target-address.md`: Documentation for target address handling. - **LEARN**: `USAGE_EXAMPLES.md` provides real code patterns and usage examples. - **UNDERSTAND**: `errors.md` explains all failure modes and error handling. ``` -------------------------------- ### Basic HTTP GET via SOCKS5 Proxy Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/USAGE_EXAMPLES.md Connect to a target server through a SOCKS5 proxy and perform an HTTP GET request. Requires the `tokio` and `tokio-socks` crates. ```rust use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio_socks::tcp::Socks5Stream; #[tokio::main] async fn main() -> Result<(), Box> { // Connect to target through SOCKS5 proxy let mut stream = Socks5Stream::connect( "127.0.0.1:1080", // SOCKS5 proxy "example.com:80" // Target server ).await?; // Send HTTP request stream.write_all(b"GET / HTTP/1.0\r\nHost: example.com\r\n\r\n").await?; // Read response let mut buf = vec![0; 4096]; let n = stream.read(&mut buf).await?; println!("{}", String::from_utf8_lossy(&buf[..n])); Ok(()) } ``` -------------------------------- ### IntoTargetAddr Conversion Examples Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/target-address.md Shows how to convert different types like IP address tuples, string literals, and domain/port tuples into TargetAddr using the IntoTargetAddr trait. ```rust use tokio_socks::IntoTargetAddr; // From IP address let addr = ([127, 0, 0, 1], 8080).into_target_addr()?; // From string let addr = "example.com:80".into_target_addr()?; // From domain and port separately let addr = ("example.com", 80).into_target_addr()?; ``` -------------------------------- ### Full Featured Import Pattern Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/modules.md Imports for a comprehensive setup including all common types and traits for SOCKS clients. ```rust use tokio_socks::{Error, Result, TargetAddr, IntoTargetAddr, ToProxyAddrs}; use tokio_socks::io::{AsyncSocket, Compat}; use tokio_socks::tcp::{Socks5Stream, Socks5Listener, Socks4Stream, Socks4Listener}; ``` -------------------------------- ### Example Usage of Result Type Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/types.md Demonstrates how to use the `Result` type alias as the return type for an asynchronous function that establishes a SOCKS5 connection. ```rust use tokio_socks::Result; async fn connect() -> Result> { // ... } ``` -------------------------------- ### Example of UnknownAuthMethod Error Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Illustrates a scenario leading to the UnknownAuthMethod error. This happens if the proxy advertises an authentication method that the client library is not equipped to handle. ```rust // Proxy returns unrecognized auth method (e.g., 0x03) let result = Socks5Stream::connect("advanced.proxy:1080", "target:80").await; // Error: UnknownAuthMethod ``` -------------------------------- ### Rust: CommandNotSupported Error Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Shows the CommandNotSupported error, which arises when the SOCKS proxy does not support the command issued, such as using BIND on a proxy that only supports CONNECT. ```rust let result = Socks5Listener::bind("limited.proxy:1080", "0.0.0.0:0").await; // Error: CommandNotSupported (proxy only supports CONNECT) ``` -------------------------------- ### Error Handling Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/modules.md Demonstrates basic error handling using the Result type provided by tokio-socks, which is an alias for std::result::Result with the Error type. ```rust use tokio_socks::{Result, Error}; async fn example() -> Result<()> { // Result = std::result::Result Ok(()) } ``` -------------------------------- ### Implement Custom Connection Pool for Proxy Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/configuration.md An example of a custom connection pool using Tokio's RwLock to manage a collection of TcpStream sockets for proxy connections. This allows for reusing existing connections to reduce overhead. ```rust use tokio::sync::RwLock; use std::sync::Arc; use tokio_socks::tcp::Socks5Stream; use tokio::net::TcpStream; struct ProxyPool { proxy_addr: String, sockets: RwLock>, } impl ProxyPool { async fn get_connection(&self) -> Result> { // Try to reuse a pooled socket let sockets = self.sockets.write().await; if let Some(socket) = sockets.pop() { // Reuse existing socket return Socks5Stream::connect_with_socket(socket, "target:80").await; } drop(sockets); // Create new connection Socks5Stream::connect(&self.proxy_addr, "target:80").await } } ``` -------------------------------- ### Example of NetworkUnreachable Error Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Provides an example for the NetworkUnreachable error. This error occurs due to routing issues or firewalls preventing the proxy from reaching the target's network. ```rust let result = Socks5Stream::connect("proxy:1080", "10.0.0.1:80").await; // Error: NetworkUnreachable (proxy has no route to 10.0.0.0/8) ``` -------------------------------- ### Example of GeneralSocksServerFailure Error Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Provides an example of when the GeneralSocksServerFailure error might be returned. This indicates a broad failure on the proxy server's side when trying to establish a connection to the target. ```rust let result = Socks5Stream::connect("proxy:1080", "1.2.3.4:80").await; // Error: GeneralSocksServerFailure ``` -------------------------------- ### connect() Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks5-stream.md Establishes a connection to a target server through a SOCKS5 proxy without authentication. It takes the proxy address and target server address as input and returns a connected Socks5Stream or an error. ```APIDOC ## connect() ### Description Establishes a connection to a target server through a SOCKS5 proxy without authentication. ### Method `pub async fn connect<'t, P, T>(proxy: P, target: T) -> Result>` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Description | |-----------|------|-------------| | `proxy` | `P: ToProxyAddrs` | Proxy server address(es) to connect to | | `target` | `T: IntoTargetAddr<'t>` | Target server address to connect through proxy | ### Response #### Success Response - `Socks5Stream` - Connected stream #### Response Example ```rust let stream = Socks5Stream::connect("127.0.0.1:1080", "example.com:80").await?; ``` ### Errors - `Error::ProxyServerUnreachable` - No proxy address could be connected to - `Error::NoAcceptableAuthMethods` - Proxy requires authentication but none provided - `Error::InvalidResponseVersion` - Proxy returned invalid SOCKS version - Other SOCKS server reply errors ``` -------------------------------- ### Socks5Stream Connect Methods Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/modules.md Illustrates the different ways to establish a SOCKS5 connection using Socks5Stream, including with and without password authentication, and with custom sockets. ```rust // Methods (on TcpStream): // connect() - No auth // connect_with_password() - Username/password auth // tor_resolve() - (tor feature) Tor DNS resolution // tor_resolve_ptr() - (tor feature) Tor reverse DNS // Methods (on custom sockets): // connect_with_socket() - No auth // connect_with_password_and_socket() - With auth // tor_resolve_with_socket() - (tor feature) // tor_resolve_ptr_with_socket() - (tor feature) ``` -------------------------------- ### TargetAddr to_owned() Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/target-address.md Demonstrates creating an owned TargetAddr from a borrowed one, removing lifetime bounds. ```rust use tokio_socks::TargetAddr; use std::net::SocketAddr; use std::borrow::Cow; let borrowed = TargetAddr::Domain(Cow::Borrowed("example.com"), 80); let owned = borrowed.to_owned(); ``` -------------------------------- ### Connect Through Multiple Proxies with Fallback Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/USAGE_EXAMPLES.md Shows how to specify a list of proxy servers, allowing `Socks5Stream::connect` to automatically try each proxy in sequence until a successful connection is established. ```rust use tokio_socks::tcp::Socks5Stream; #[tokio::main] async fn main() -> Result<(), Box> { // Convert slice to proxy addresses let proxies = [ "proxy1.example.com:1080", "proxy2.example.com:1080", "proxy3.example.com:1080", ]; // connect() automatically tries each proxy until one succeeds let stream = Socks5Stream::connect(&proxies[..], "target:80").await?; println!("Connected through one of the proxies"); Ok(()) } ``` -------------------------------- ### Create and Manage a Proxy Connection Pool Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/USAGE_EXAMPLES.md Illustrates how to create a pool of SOCKS connections to reuse them, improving performance by avoiding repeated connection establishments. It includes logic to attempt reusing pooled sockets and creating new ones if necessary. ```rust use tokio::sync::RwLock; use std::sync::Arc; use tokio_socks::tcp::Socks5Stream; use tokio::net::TcpStream; struct ProxyPool { proxy: String, sockets: Arc>>, } impl ProxyPool { fn new(proxy: String) -> Self { ProxyPool { proxy, sockets: Arc::new(RwLock::new(Vec::new())) } } async fn connect(&self, target: &str) -> Result, Box> { // Try to reuse pooled socket { let mut sockets = self.sockets.write().await; if let Some(socket) = sockets.pop() { match Socks5Stream::connect_with_socket(&socket, target).await { Ok(stream) => return Ok(stream), Err(_) => { // Pooled socket is bad, continue to create new one } } } } // Create new connection Socks5Stream::connect(&self.proxy, target).await.map_err(|e| Box::new(e) as _) } async fn release(&self, stream: Socks5Stream) { let socket = stream.into_inner(); self.sockets.write().await.push(socket); } } #[tokio::main] async fn main() -> Result<(), Box> { let pool = ProxyPool::new("127.0.0.1:1080".to_string()); let stream1 = pool.connect("example.com:80").await?; let stream2 = pool.connect("example.com:443").await?; pool.release(stream1).await; pool.release(stream2).await; Ok(()) } ``` -------------------------------- ### Get Target Address from Socks4Stream Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks4-stream.md Retrieves the target address the proxy server connected to. Useful for verifying the connection endpoint. ```rust let stream = Socks4Stream::connect("127.0.0.1:1080", "example.com:80").await?; let target = stream.target_addr(); println!("Connected to: {}", target); ``` -------------------------------- ### Get Target Address from Socks5Stream Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks5-stream.md Retrieves the target address that the SOCKS5 proxy server connected to. This is useful for verifying the connection endpoint. ```rust pub fn target_addr(&self) -> TargetAddr<'_> ``` ```rust let stream = Socks5Stream::connect("127.0.0.1:1080", "example.com:80").await?; let target = stream.target_addr(); println!("Connected to: {}", target); ``` -------------------------------- ### Connect with Comprehensive Error Handling Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/USAGE_EXAMPLES.md Demonstrates how to connect to a target through a SOCKS5 proxy with detailed error handling for various proxy and connection issues. This is useful for building robust network clients. ```rust use tokio_socks::{Error, tcp::Socks5Stream}; async fn connect_with_retries() -> Result<(), Box> { match Socks5Stream::connect( "proxy.example.com:1080", "target.example.com:80" ).await { Ok(stream) => { println!("Connected to {}", stream.target_addr()); Ok(()) } Err(Error::ProxyServerUnreachable) => { eprintln!("Proxy server is down"); Err("Proxy unreachable".into()) } Err(Error::ConnectionRefused) => { eprintln!("Target refused connection"); Err("Connection refused".into()) } Err(Error::NoAcceptableAuthMethods) => { eprintln!("Proxy requires authentication"); Err("Auth required".into()) } Err(Error::InvalidAuthValues(msg)) => { eprintln!("Invalid credentials: {}", msg); Err(format!("Invalid auth: {}", msg).into()) } Err(Error::PasswordAuthFailure(code)) => { eprintln!("Authentication failed (code: {})", code); Err("Auth failed".into()) } Err(e) => { eprintln!("Unexpected error: {}", e); Err(Box::new(e)) } } } ``` -------------------------------- ### Using Futures-io AsyncRead/AsyncWrite with Compat Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/async-socket.md Demonstrates how to use a socket wrapped in `Compat` with futures-io's `AsyncReadExt` and `AsyncWriteExt`. Ensure the underlying socket implements `futures_io::AsyncRead` and `futures_io::AsyncWrite`. ```rust use futures_io::{AsyncReadExt, AsyncWriteExt}; use tokio_socks::io::Compat; use tokio_socks::tcp::Socks5Stream; async fn use_futures_io_socket() -> Result<(), Box> { let socket = smol::net::TcpStream::connect("proxy:1080").await?; let compat = Compat::new(socket); let mut stream = Socks5Stream::connect_with_socket(compat, "target:80").await?; // Use futures-io AsyncReadExt and AsyncWriteExt stream.write_all(b"GET / HTTP/1.0\r\n\r\n").await?; let mut buf = vec![0; 1024]; stream.read(&mut buf).await?; Ok(()) } ``` -------------------------------- ### Basic SOCKS5 Client Import Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/modules.md Imports for setting up a basic SOCKS5 client using Tokio's TcpStream directly. ```rust use tokio_socks::tcp::Socks5Stream; use tokio::net::TcpStream; // Use TcpStream directly (automatic AsyncSocket implementation) ``` -------------------------------- ### Rust: AddressTypeNotSupported Error Examples Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Covers the AddressTypeNotSupported error, occurring when a proxy receives an unsupported address type or when attempting to use IPv6 with SOCKS4. ```rust // IPv6 with SOCKS4 let result = Socks4Stream::connect("proxy:1080", "[::1]:80").await; // Error: AddressTypeNotSupported // Or from proxy response let result = Socks5Stream::connect("proxy:1080", "target:80").await; // Error: AddressTypeNotSupported ``` ```rust match result { Err(Error::AddressTypeNotSupported) => { eprintln!("Address type not supported by proxy"); } _ => {} } ``` -------------------------------- ### connect_with_password() Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks5-stream.md Establishes a connection using username and password authentication (SOCKS5 method 0x02). It requires proxy and target addresses, along with credentials, returning a connected stream or an error. ```APIDOC ## connect_with_password() ### Description Establishes a connection using username and password authentication (SOCKS5 method 0x02). ### Method `pub async fn connect_with_password<'a, 't, P, T>(proxy: P, target: T, username: &'a str, password: &'a str) -> Result>` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Description | |-----------|------|-------------| | `proxy` | `P: ToProxyAddrs` | Proxy server address(es) | | `target` | `T: IntoTargetAddr<'t>` | Target server address | | `username` | `&'a str` | Username for authentication (1-255 bytes) | | `password` | `&'a str` | Password for authentication (1-255 bytes) | ### Response #### Success Response - `Socks5Stream` - Connected stream #### Response Example ```rust let stream = Socks5Stream::connect_with_password("proxy.example.com:1080", "target.example.com:443", "user", "pass").await?; ``` ### Errors - `Error::InvalidAuthValues` - Username or password length invalid - `Error::PasswordAuthFailure(code)` - Authentication failed with given code - Standard SOCKS5 connection errors ``` -------------------------------- ### Rust: ConnectionRefused Error Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Illustrates the ConnectionRefused error, which occurs when a TCP connection is refused by the target host because no service is listening on the specified port. ```rust let result = Socks5Stream::connect("proxy:1080", "1.2.3.4:9999").await; // Error: ConnectionRefused (no service on port 9999) ``` -------------------------------- ### Example of HostUnreachable Error Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Illustrates a scenario leading to the HostUnreachable error. This can happen if the proxy receives an ICMP unreachable message or if the host is detected as offline. ```rust let result = Socks5Stream::connect("proxy:1080", "1.2.3.4:80").await; // Error: HostUnreachable (ICMP Host Unreachable received) ``` -------------------------------- ### Connect to SOCKS5 Proxy with Custom Socket Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/INDEX.md Shows how to establish a SOCKS5 connection using a pre-existing TCP socket, useful for scenarios where the socket is managed separately. ```rust let socket = TcpStream::connect("proxy:1080").await?; let stream = Socks5Stream::connect_with_socket(socket, "target:80").await?; ``` -------------------------------- ### Minimal Configuration (No Runtime Features) Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/configuration.md Disables tokio support, making only `connect_with_socket()` and `bind_with_socket()` methods available. Requires integration with another async runtime. ```toml [dependencies] tokio-socks = { version = "0.5", default-features = false } ``` -------------------------------- ### Configuring Proxy Addresses with ToProxyAddrs Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/configuration.md Illustrates different formats for specifying proxy server addresses when connecting, including single addresses, hostnames, IPv6, and fallback lists. ```rust use tokio_socks::ToProxyAddrs; // Single proxy Socks5Stream::connect("127.0.0.1:1080", "target:80").await?; // With hostname Socks5Stream::connect("proxy.example.com:1080", "target:80").await?; // IPv6 address Socks5Stream::connect(("[::1]", 1080), "target:80").await?; // Multiple proxy addresses (fallback) let proxies = vec!["10.0.0.1:1080".parse()?, "10.0.0.2:1080".parse()?]; Socks5Stream::connect(&proxies[..], "target:80").await?; // Tuple format Socks5Stream::connect(("proxy.example.com", 1080), "target:80").await?; ``` -------------------------------- ### Consume Stream to Get Inner Socket Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks5-stream.md Consumes the Socks5Stream to retrieve the underlying socket. This allows direct use of the socket after the stream is no longer needed. ```rust pub fn into_inner(self) -> S ``` ```rust let stream = Socks5Stream::connect("127.0.0.1:1080", "example.com:80").await?; let socket = stream.into_inner(); // Can now use socket directly ``` -------------------------------- ### Initiate SOCKS5 BIND request (no auth) Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks5-listener.md Use this method to initiate a BIND request to a SOCKS5 proxy without authentication. After creating the listener, obtain the bind address and send it to the remote process. Then, call accept() to wait for an incoming connection. ```rust use tokio_socks::tcp::Socks5Listener; let listener = Socks5Listener::bind("127.0.0.1:1080", "0.0.0.0:0").await?; let bind_addr = listener.bind_addr(); println!("Remote should connect to: {}", bind_addr); // Send bind_addr to remote process somehow... let stream = listener.accept().await?; // stream is now connected to the remote ``` -------------------------------- ### Get Bind Address from Socks4Listener Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks4-listener.md Retrieves the proxy-side bind address for an incoming connection from a Socks4Listener. This address should be communicated to the remote process that will initiate the connection. ```rust pub fn bind_addr(&self) -> TargetAddr<'_> ``` ```rust let listener = Socks4Listener::bind("127.0.0.1:1080", "1.2.3.4:0").await?; let bind_addr = listener.bind_addr(); println!("Tell remote to connect to: {}", bind_addr); ``` -------------------------------- ### accept() Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks5-listener.md Consumes the listener and waits for an incoming connection from the remote. The remote must have connected to the address returned by `bind_addr()` before this method completes. ```APIDOC ## accept() ### Description Consumes the listener and waits for an incoming connection from the remote. The remote must have connected to `bind_addr()` before this method completes. ### Method POST (Conceptual) ### Endpoint N/A (Method on an object) ### Parameters None ### Request Example ```json {} ``` ### Response #### Success Response (200) - **stream** (Socks5Stream) - Connected stream to the remote. ### Response Example ```json { "stream": "" } ``` ### Errors - `Error::InvalidResponseVersion` - Invalid SOCKS response - `Error::InvalidReservedByte` - Malformed SOCKS packet - `Error::UnknownAddressType` - Unknown address type in response - Standard I/O errors ``` -------------------------------- ### Get SOCKS5 Listener Bind Address Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks5-listener.md Retrieves the proxy-side bind address for an incoming connection. This address is used by the remote process to establish the connection. ```rust let listener = Socks5Listener::bind("127.0.0.1:1080", "0.0.0.0:0").await?; let bind_addr = listener.bind_addr(); println!("Tell remote to connect to: {}", bind_addr); ``` -------------------------------- ### Rust: IdentdAuthFailure Error Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Illustrates the IdentdAuthFailure error, which occurs when a SOCKS4 server with identd authentication enabled cannot connect to the identd daemon on the client machine. ```rust let result = Socks4Stream::connect("identd.proxy:1080", "target:80").await; // Error: IdentdAuthFailure (proxy couldn't reach your identd) ``` -------------------------------- ### Basic SOCKS4 Client Import Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/modules.md Imports for setting up a basic SOCKS4 client using Tokio's TcpStream directly. ```rust use tokio_socks::tcp::Socks4Stream; use tokio::net::TcpStream; ``` -------------------------------- ### Connect with Various Target Address Formats Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/USAGE_EXAMPLES.md Demonstrates the flexibility of the `Socks5Stream::connect` method in accepting different formats for specifying the target address, including string, tuple, SocketAddr, and IP address with port. ```rust use tokio_socks::tcp::Socks5Stream; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; #[tokio::main] async fn main() -> Result<(), Box> { // String format "host:port" Socks5Stream::connect("127.0.0.1:1080", "example.com:80").await?; // Tuple format (host, port) Socks5Stream::connect(("127.0.0.1", 1080), ("example.com", 80)).await?; // SocketAddr let addr: SocketAddr = "127.0.0.1:1080".parse()?; Socks5Stream::connect(addr, "example.com:80").await?; // IP and port tuple Socks5Stream::connect( (IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 1080), (IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)), 80) ).await?; // Array address Socks5Stream::connect( ([127, 0, 0, 1], 1080), ([93, 184, 216, 34], 80) ).await?; Ok(()) } ``` -------------------------------- ### Rust: UnknownError Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Demonstrates the UnknownError, triggered by an unrecognized error code in a SOCKS4 response, typically when the proxy returns a code not defined in the SOCKS4 specification. ```rust // SOCKS4 returns 0xFF instead of valid code let result = Socks4Stream::connect("malformed.proxy:1080", "target:80").await; // Error: UnknownError ``` -------------------------------- ### bind_with_user_and_socket() Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks4-listener.md Initiates a BIND request using an existing socket with user ID authentication, returning a Socks4Listener. ```APIDOC ## bind_with_user_and_socket() ### Description Initiates a BIND request using an existing socket with user ID authentication. ### Method `async fn bind_with_user_and_socket<'a, 't, T>(socket: S, target: T, user_id: &'a str) -> Result>` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Description | |-----------|------|-------------| | `socket` | `S` | Socket connected to proxy server | | `target` | `T: IntoTargetAddr<'t>` | Address to filter incoming connections | | `user_id` | `&'a str` | User ID for SOCKS4 authentication (1-255 bytes) | ### Returns `Result>` - Listener wrapping the socket ``` -------------------------------- ### Example of ConnectionNotAllowedByRuleset Error Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Illustrates a scenario triggering the ConnectionNotAllowedByRuleset error. This occurs when the target address violates the proxy's configured access control policy. ```rust // Proxy forbids connections to this IP due to firewall rules let result = Socks5Stream::connect("proxy:1080", "192.168.1.1:80").await; // Error: ConnectionNotAllowedByRuleset ``` -------------------------------- ### accept() Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks4-listener.md Consumes the listener and waits for an incoming connection from the remote. The remote must have connected to the listener's bind address before this method completes. ```APIDOC ## accept() ### Description Consumes the listener and waits for an incoming connection from the remote. ### Method `async fn accept(mut self) -> Result>` ### Parameters None ### Returns `Result>` - Connected stream to the remote ### Request Example ```rust use tokio::io::AsyncWriteExt; use tokio_socks::tcp::Socks4Listener; async fn example() -> Result<(), Box> { let listener = Socks4Listener::bind("127.0.0.1:1080", "0.0.0.0:0").await?; let bind_addr = listener.bind_addr(); // Send bind_addr to remote... let mut stream = listener.accept().await?; stream.write_all(b"Hello").await?; Ok(()) } ``` ### Errors: - `Error::InvalidResponseVersion` - Invalid SOCKS response - `Error::GeneralSocksServerFailure` - Proxy error - `Error::IdentdAuthFailure` - Identd error - `Error::InvalidUserIdAuthFailure` - User ID mismatch - Standard I/O errors ``` -------------------------------- ### bind() Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks5-listener.md Initiates a BIND request to a SOCKS5 proxy without authentication. It returns a Socks5Listener or an error if the connection fails or the proxy does not support the BIND command. ```APIDOC ## bind() ### Description Initiates a BIND request to a SOCKS5 proxy without authentication. It returns a Socks5Listener or an error if the connection fails or the proxy does not support the BIND command. ### Method POST (implied by BIND operation) ### Endpoint N/A (SDK method) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust use tokio_socks::tcp::Socks5Listener; let listener = Socks5Listener::bind("127.0.0.1:1080", "0.0.0.0:0").await?; let bind_addr = listener.bind_addr(); println!("Remote should connect to: {}", bind_addr); // Send bind_addr to remote process somehow... let stream = listener.accept().await?; // stream is now connected to the remote ``` ### Response #### Success Response `Result>` - A listener instance ready to accept connections. #### Response Example None explicitly provided, but the `bind()` function returns a `Result`. ``` -------------------------------- ### Connect via SOCKS5 Proxy (Username/Password Auth) Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks5-stream.md Establishes a connection using username and password authentication (SOCKS5 method 0x02). Use when the proxy requires credentials. Ensure username and password lengths are between 1-255 bytes. ```rust let stream = Socks5Stream::connect_with_password( "proxy.example.com:1080", "target.example.com:443", "user", "pass" ).await?; ``` -------------------------------- ### Rust: UnknownAddressType Error Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Illustrates the UnknownAddressType error, which happens when a SOCKS proxy response contains an unrecognized address type byte, indicating a non-conformant proxy. ```rust // Proxy returns address type 0x05 (not defined in SOCKS5) let result = Socks5Stream::connect("malformed.proxy:1080", "target:80").await; // Error: UnknownAddressType ``` -------------------------------- ### SOCKS5 Connection with Comprehensive Error Handling Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Demonstrates how to connect to a SOCKS5 proxy and handle various potential errors, including proxy server unreachability, authentication failures, and ruleset restrictions. ```rust use tokio_socks::tcp::Socks5Stream; use tokio_socks::Error; async fn connect_with_error_handling() -> Result<(), Box> { match Socks5Stream::connect_with_password( "proxy.example.com:1080", "target.example.com:443", "user", "password" ).await { Ok(stream) => { println!("Connected to {:?}", stream.target_addr()); Ok(()) } Err(Error::ProxyServerUnreachable) => { eprintln!("Proxy is down"); Err("Proxy unreachable".into()) } Err(Error::PasswordAuthFailure(code)) => { eprintln!("Auth failed with code {}", code); Err("Authentication failed".into()) } Err(Error::ConnectionNotAllowedByRuleset) => { eprintln!("Proxy policy forbids this connection"); Err("Forbidden by proxy".into()) } Err(Error::InvalidAuthValues(msg)) => { eprintln!("Invalid credentials: {}", msg); Err(msg.into()) } Err(e) => { eprintln!("Unexpected error: {}", e); Err(Box::new(e)) } } } ``` -------------------------------- ### Example of InvalidReservedByte Error Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Illustrates a scenario where the InvalidReservedByte error might occur. This happens when a proxy implementation is non-compliant and sends a non-zero reserved byte in a SOCKS5 reply. ```rust // Proxy sends reply with reserved byte != 0x00 let result = Socks5Stream::connect("malformed.proxy:1080", "target:80").await; // Error: InvalidReservedByte ``` -------------------------------- ### Using futures-io Socket with AsyncSocket via Compat Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/async-socket.md Demonstrates how to use a futures-io compatible socket (smol::net::TcpStream) with tokio-socks by wrapping it in the Compat type. ```rust use tokio_socks::io::Compat; use tokio_socks::tcp::Socks5Stream; use smol::net::TcpStream; async fn use_smol_socket() -> Result<(), Box> { let socket = TcpStream::connect("proxy.example.com:1080").await?; let socket = Compat::new(socket); let stream = Socks5Stream::connect_with_socket(socket, "target:80").await?; Ok(()) } ``` -------------------------------- ### SOCKS4 Connection with User ID Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Example of establishing a SOCKS4 connection with a user ID. This snippet may trigger an InvalidUserIdAuthFailure if the provided user ID does not match the identd response. ```rust let result = Socks4Stream::connect_with_userid( "strict.proxy:1080", "target:80", "user123" ).await; // Error: InvalidUserIdAuthFailure (identd says you're user456) ``` -------------------------------- ### Configure Socket Options Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/USAGE_EXAMPLES.md Shows how to set various socket options, such as `nodelay` and buffer sizes, on the underlying `TcpStream` by accessing them through the `Socks5Stream` via dereferencing. ```rust let stream = Socks5Stream::connect("127.0.0.1:1080", "example.com:80").await?; // Access socket options through Deref stream.set_nodelay(true)?; stream.set_recv_buffer_size(Some(65536))?; stream.set_send_buffer_size(Some(65536))?; ``` -------------------------------- ### Rust: TtlExpired Error Example Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/errors.md Demonstrates the TtlExpired error, indicating that the Time To Live (TTL) for an IP packet expired en route to the target, usually due to too many hops. ```rust let result = Socks5Stream::connect("proxy:1080", "very.distant.host:80").await; // Error: TtlExpired ``` -------------------------------- ### connect() Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/api-reference/socks4-stream.md Establishes a connection to a target server through a SOCKS4 proxy without authentication. Supports both IPv4 addresses and domain names (SOCKS4a). ```APIDOC ## connect() ### Description Establishes a connection to a target server through a SOCKS4 proxy without authentication. Supports both IPv4 addresses and domain names (SOCKS4a). ### Method `async fn connect<'t, P, T>(proxy: P, target: T) -> Result>` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Description | |-----------|------|-------------| | `proxy` | `P: ToProxyAddrs` | Proxy server address(es) to connect to | | `target` | `T: IntoTargetAddr<'t>` | Target server address (IP or domain) | ### Response #### Success Response - `Socks4Stream` - Connected stream ### Errors - `Error::ProxyServerUnreachable` - No proxy address could be connected to - `Error::GeneralSocksServerFailure` - Proxy rejected connection - `Error::IdentdAuthFailure` - Identd authentication required - `Error::InvalidUserIdAuthFailure` - User ID mismatch with identd ### Example ```rust use tokio_socks::tcp::Socks4Stream; // IPv4 address let stream = Socks4Stream::connect("127.0.0.1:1080", "1.2.3.4:80").await?; // Domain name (SOCKS4a) let stream = Socks4Stream::connect("127.0.0.1:1080", "example.com:80").await?; ``` ``` -------------------------------- ### Socks5Listener Bind Methods Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/modules.md Details the various methods for creating a SOCKS5 BIND listener, supporting different authentication methods and custom socket configurations. ```rust // Bind Methods: // Socks5Listener::bind() - No auth // Socks5Listener::bind_with_password() - With auth // Socks5Listener::bind_with_socket() - Custom socket, no auth // Socks5Listener::bind_with_password_and_socket() - Custom socket, with auth ``` -------------------------------- ### Retrieve Socket Local and Peer Addresses Source: https://github.com/sticnarf/tokio-socks/blob/master/_autodocs/USAGE_EXAMPLES.md Demonstrates how to access the local and peer addresses of an established SOCKS connection by dereferencing the `Socks5Stream` to its underlying `TcpStream`. It also shows how to get the target address. ```rust use tokio_socks::tcp::Socks5Stream; #[tokio::main] async fn main() -> Result<(), Box> { let stream = Socks5Stream::connect("127.0.0.1:1080", "example.com:80").await?; // Deref to underlying TcpStream let local = stream.local_addr()?; let peer = stream.peer_addr()?; println!("Local address: {}", local); println!("Peer address: {}", peer); // Target address let target = stream.target_addr(); println!("Target: {}", target); Ok(()) } ```