rproxy 0.3.2

Platform independent asynchronous UDP/TCP proxy
Documentation
use std::collections::HashSet;
use std::io::Error;
use tokio::net::lookup_host;
use log::*;
use async_trait::async_trait;

#[async_trait]
#[allow(unused_variables)]
pub trait DNSResolve <'a> {
    fn remote(&self) -> &String;
    fn dns(& self) -> &Vec<String>;
    fn reset_dns(&mut self, d: &Vec<String> ) -> usize;
    
    fn domain(&self) -> String {
        let mut s = self.remote().split(":");
        s.next().unwrap().to_string()
    }
    
    fn port(&self) -> Option<u16> {
        let s: Vec<&str> = self.remote().split(":").collect();
        if s.len() > 1{
            let p = s.last().unwrap();
            Some(p.parse::<u16>().unwrap())
        }else {
            None
        }
    }
    fn on_dns_changed(&self, new_addr: &String) {

    }

    async fn resolve(& mut self) -> Result<usize, Error> { 
        let remote = self.remote().clone();
        let res:usize;
        let socka = lookup_host(remote.clone()).await;
        match socka {
            Ok(sk) => {
                let mut last = HashSet::new();
                last.extend(self.dns().clone());
                let mut dns = vec![];
                for addr in sk{
                    let d = addr.to_string();
                    if !last.contains(&d){
                        info!("Resolve {} -> {}", remote, d);
                        self.on_dns_changed(&d);
                    }
                    dns.push(d);
                }
                res = self.reset_dns(&dns);
            },
            Err(e) => {
                warn!("{:?}", e);
                let d = vec![self.domain()];
                res = self.reset_dns(&d);
            }
        }
        Ok(res)
    }    
}