pub struct Connection { /* private fields */ }Expand description
A wrapper around a TCP stream that provides additional connection management functionality.
The Connection struct encapsulates a Tokio TcpStream and provides methods for
accessing connection metadata, managing the connection lifecycle, and obtaining
address information for both the local and remote endpoints.
§Design Philosophy
This struct follows the principle of providing a clean, safe interface around the underlying TCP stream while maintaining high performance and low overhead. It allows for future extensibility of connection management features without breaking existing code.
§Thread Safety
The Connection struct is not inherently thread-safe, as it wraps a TcpStream
which is designed to be used from a single task. However, it can be safely
moved between tasks and used in async contexts.
§Examples
§Basic Usage
use ignitia::server::connection::Connection;
use tokio::net::TcpStream;
// Create a connection (usually done by the server)
let stream = TcpStream::connect("httpbin.org:80").await?;
let connection = Connection::new(stream);
// Access connection information
let peer = connection.peer_addr()?;
let local = connection.local_addr()?;
println!("Connected to {} from {}", peer, local);§Connection Information Logging
use ignitia::server::connection::Connection;
use tokio::net::TcpStream;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
let stream = TcpStream::connect("example.com:443").await?;
let connection = Connection::new(stream);
if let Ok(peer_addr) = connection.peer_addr() {
match peer_addr.ip() {
IpAddr::V4(ipv4) => {
println!("IPv4 connection: {}:{}", ipv4, peer_addr.port());
if ipv4.is_private() {
println!("Connection from private network");
}
}
IpAddr::V6(ipv6) => {
println!("IPv6 connection: [{}]:{}", ipv6, peer_addr.port());
if ipv6.is_loopback() {
println!("Local IPv6 connection");
}
}
}
}Implementations§
Source§impl Connection
impl Connection
Sourcepub fn new(stream: TcpStream) -> Self
pub fn new(stream: TcpStream) -> Self
Creates a new Connection wrapper around the provided TCP stream.
This constructor takes ownership of the TCP stream and wraps it in a
Connection instance that provides additional functionality and a
cleaner API for connection management.
§Parameters
stream: TheTcpStreamto wrap
§Returns
A new Connection instance
§Examples
use ignitia::server::connection::Connection;
use tokio::net::TcpStream;
let stream = TcpStream::connect("example.com:80").await?;
let connection = Connection::new(stream);§Server Context Usage
use ignitia::server::connection::Connection;
use tokio::net::{TcpListener, TcpStream};
let listener = TcpListener::bind("127.0.0.1:3000").await?;
loop {
let (stream, _addr) = listener.accept().await?;
let connection = Connection::new(stream);
// Handle the connection
tokio::spawn(async move {
// Connection handling logic would go here
if let Ok(peer) = connection.peer_addr() {
println!("New connection from: {}", peer);
}
});
}Sourcepub fn stream(&self) -> &TcpStream
pub fn stream(&self) -> &TcpStream
Returns a reference to the underlying TCP stream.
This method provides read-only access to the wrapped TcpStream without
transferring ownership. This is useful when you need to inspect stream
properties or perform operations that require a stream reference.
§Returns
A reference to the underlying TcpStream
§Examples
use ignitia::server::connection::Connection;
use tokio::net::TcpStream;
let stream = TcpStream::connect("example.com:80").await?;
let connection = Connection::new(stream);
// Access the stream reference
let stream_ref = connection.stream();
// You can now use stream_ref for operations that need a reference
// For example, checking if the stream is readable§Advanced Stream Operations
use ignitia::server::connection::Connection;
use tokio::net::TcpStream;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
let stream = TcpStream::connect("httpbin.org:80").await?;
let mut connection = Connection::new(stream);
// Get a reference to perform operations
let stream_ref = connection.stream();
// Note: For actual I/O operations, you'd typically use into_stream()
// to get ownership of the streamSourcepub fn into_stream(self) -> TcpStream
pub fn into_stream(self) -> TcpStream
Consumes the connection and returns the underlying TCP stream.
This method transfers ownership of the wrapped TcpStream back to the caller,
consuming the Connection wrapper in the process. This is useful when you
need direct access to the stream for I/O operations or when integrating
with APIs that require ownership of the stream.
§Returns
The underlying TcpStream
§Examples
use ignitia::server::connection::Connection;
use tokio::net::TcpStream;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
let stream = TcpStream::connect("httpbin.org:80").await?;
let connection = Connection::new(stream);
// Extract the stream for direct I/O operations
let mut stream = connection.into_stream();
// Now you can perform I/O operations directly
stream.write_all(b"GET / HTTP/1.1\r\nHost: httpbin.org\r\n\r\n").await?;
let mut response = Vec::new();
stream.read_to_end(&mut response).await?;§Integration with WebSocket Libraries
use ignitia::server::connection::Connection;
use tokio::net::TcpStream;
let stream = TcpStream::connect("echo.websocket.org:80").await?;
let connection = Connection::new(stream);
// Extract stream for WebSocket upgrade
let stream = connection.into_stream();
// Use stream with WebSocket libraries
// let ws_stream = tokio_tungstenite::accept_async(stream).await?;Sourcepub fn peer_addr(&self) -> Result<SocketAddr>
pub fn peer_addr(&self) -> Result<SocketAddr>
Returns the remote peer address of the TCP connection.
This method retrieves the socket address of the remote peer that this connection is connected to. This is useful for logging, security checks, rate limiting, and other connection management tasks.
§Returns
Ok(SocketAddr): The remote peer’s socket addressErr(io::Error): If the peer address cannot be determined
§Errors
This method can return an error if:
- The connection has been closed
- The underlying socket is in an invalid state
- System-level networking errors occur
§Examples
§Basic Peer Address Retrieval
use ignitia::server::connection::Connection;
use tokio::net::TcpStream;
let stream = TcpStream::connect("httpbin.org:80").await?;
let connection = Connection::new(stream);
match connection.peer_addr() {
Ok(addr) => println!("Connected to: {}", addr),
Err(e) => eprintln!("Failed to get peer address: {}", e),
}§Security and Rate Limiting
use ignitia::server::connection::Connection;
use tokio::net::TcpStream;
use std::collections::HashMap;
let stream = TcpStream::connect("example.com:80").await?;
let connection = Connection::new(stream);
// Example rate limiting based on IP address
if let Ok(peer_addr) = connection.peer_addr() {
let ip = peer_addr.ip();
// Check if this IP is allowed
if ip.is_loopback() {
println!("Local connection allowed: {}", ip);
} else if ip.to_string().starts_with("192.168.") {
println!("Private network connection: {}", ip);
} else {
println!("External connection from: {}", ip);
}
}§Geographic Information (Conceptual)
use ignitia::server::connection::Connection;
use tokio::net::TcpStream;
use std::net::IpAddr;
let stream = TcpStream::connect("google.com:80").await?;
let connection = Connection::new(stream);
if let Ok(peer_addr) = connection.peer_addr() {
match peer_addr.ip() {
IpAddr::V4(ipv4) => {
if ipv4.is_private() {
println!("Private IPv4: {}", ipv4);
} else if ipv4.is_multicast() {
println!("Multicast IPv4: {}", ipv4);
} else {
println!("Public IPv4: {}", ipv4);
// In a real application, you might do GeoIP lookup here
}
}
IpAddr::V6(ipv6) => {
if ipv6.is_loopback() {
println!("Loopback IPv6: {}", ipv6);
} else {
println!("IPv6 address: {}", ipv6);
}
}
}
}Sourcepub fn local_addr(&self) -> Result<SocketAddr>
pub fn local_addr(&self) -> Result<SocketAddr>
Returns the local socket address of the TCP connection.
This method retrieves the local socket address that this connection is bound to. This is useful for determining which local interface and port the connection is using, which can be important for logging, debugging, and network configuration validation.
§Returns
Ok(SocketAddr): The local socket addressErr(io::Error): If the local address cannot be determined
§Errors
This method can return an error if:
- The connection has been closed
- The underlying socket is in an invalid state
- System-level networking errors occur
§Examples
§Basic Local Address Retrieval
use ignitia::server::connection::Connection;
use tokio::net::TcpStream;
let stream = TcpStream::connect("httpbin.org:80").await?;
let connection = Connection::new(stream);
match connection.local_addr() {
Ok(addr) => println!("Local address: {}", addr),
Err(e) => eprintln!("Failed to get local address: {}", e),
}§Server Configuration Validation
use ignitia::server::connection::Connection;
use tokio::net::{TcpListener, TcpStream};
// Server setup
let listener = TcpListener::bind("127.0.0.1:0").await?; // Bind to any available port
let server_addr = listener.local_addr()?;
// Client connection
let stream = TcpStream::connect(server_addr).await?;
let connection = Connection::new(stream);
// Verify the connection is using the expected local configuration
if let Ok(local_addr) = connection.local_addr() {
println!("Connected via local address: {}", local_addr);
println!("Local port: {}", local_addr.port());
if local_addr.ip().is_loopback() {
println!("Using loopback interface");
}
}§Multi-Interface Server Debugging
use ignitia::server::connection::Connection;
use tokio::net::TcpStream;
use std::net::{IpAddr, Ipv4Addr};
let stream = TcpStream::connect("example.com:80").await?;
let connection = Connection::new(stream);
// Debug which local interface is being used
if let (Ok(local_addr), Ok(peer_addr)) = (connection.local_addr(), connection.peer_addr()) {
println!("Connection: {} -> {}", local_addr, peer_addr);
match local_addr.ip() {
IpAddr::V4(ipv4) => {
if ipv4 == Ipv4Addr::LOCALHOST {
println!("Using localhost interface");
} else if ipv4.is_private() {
println!("Using private network interface: {}", ipv4);
} else {
println!("Using public interface: {}", ipv4);
}
}
IpAddr::V6(ipv6) => {
println!("Using IPv6 interface: {}", ipv6);
}
}
}§Load Balancer Detection
use ignitia::server::connection::Connection;
use tokio::net::TcpStream;
let stream = TcpStream::connect("example.com:80").await?;
let connection = Connection::new(stream);
// In a real server environment, you might want to detect
// if connections are coming through a load balancer
if let Ok(local_addr) = connection.local_addr() {
let port = local_addr.port();
if port == 80 || port == 443 {
println!("Direct HTTP/HTTPS connection on port {}", port);
} else {
println!("Connection on non-standard port: {}", port);
// Might indicate load balancer or proxy
}
}