socks5x 0.1.3

A simple, async SOCKS5 proxy library for Rust
Documentation
use std::{collections::HashMap, sync::Arc};

use socks5x::server::{AuthValidator, ClientHandler, DefaultConnectionCreator};
use tokio::net::TcpListener;

#[derive(Default)]
struct Database {
    inner: HashMap<String, String>,
}

impl Database {
    fn add_user(&mut self, username: &str, password: &str) {
        self.inner
            .insert(username.to_string(), password.to_string());
    }
}

impl AuthValidator for Database {
    async fn validate(&self, username: &str, password: &str) -> bool {
        self.inner
            .get(username)
            .map(|p| p == password)
            .unwrap_or(false)
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let listener = TcpListener::bind("127.0.0.1:1080").await?;
    println!("SOCKS5 proxy server listening on 127.0.0.1:1080");

    let mut db = Database::default();
    db.add_user("admin", "secret");

    let client_handler = Arc::new(ClientHandler::new(
        socks5x::server::Auth::UserPassword(db),
        DefaultConnectionCreator,
    ));

    loop {
        let (socket, addr) = listener.accept().await?;
        println!("New client connection from: {}", addr);
        let client_handler = client_handler.clone();

        tokio::spawn(async move {
            if let Err(e) = client_handler.handle(socket).await {
                eprintln!("Error handling client {}: {}", addr, e);
            } else {
                println!("Client {} disconnected", addr);
            }
        });
    }
}