async fn relay_l2r(
        context: &Context,
        src: SocketAddr,
        remote_udp: &UdpSocket,
        pkt: Vec<u8>,
        timeout: Duration,
        svr_cfg: &ServerConfig,
        resolved_address_cache: &SharedResolvedAddressCache,
    ) -> io::Result<()> {
        // First of all, decrypt payload CLIENT -> SERVER
        let mut cur = if let CipherCategory::None = svr_cfg.method().category() {
            Cursor::new(pkt)
        } else {
            let decrypted_pkt = match decrypt_payload(context, svr_cfg.method(), svr_cfg.key(), &pkt) {
                Ok(Some(pkt)) => pkt,
                Ok(None) => {
                    error!("failed to decrypt pkt in UDP relay, packet too short");
                    let err = io::Error::new(io::ErrorKind::InvalidData, "packet too short");
                    return Err(err);
                }
                Err(err) => {
                    error!("failed to decrypt pkt in UDP relay: {}", err);
                    let err = io::Error::new(io::ErrorKind::InvalidData, "decrypt failed");
                    return Err(err);
                }
            };

            Cursor::new(decrypted_pkt)
        };

        // CLIENT -> SERVER protocol: ADDRESS + PAYLOAD
        let addr = Address::read_from(&mut cur).await?;

        if context.check_outbound_blocked(&addr).await {
            warn!("{} -> outbound {} is blocked by ACL rules", src, addr);
            return Ok(());
        }

        // Take out internal buffer for optimizing one byte copy
        let header_len = cur.position() as usize;
        let decrypted_pkt = cur.into_inner();
        let body = &decrypted_pkt[header_len..];

        let send_len = match addr {
            Address::SocketAddress(ref remote_addr) => {
                debug!(
                    "UDP ASSOCIATE {} -> {} ({}), payload length {} bytes",
                    src,
                    addr,
                    remote_addr,
                    body.len()
                );
                try_timeout(remote_udp.send_to(body, remote_addr), Some(timeout)).await?
            }
            Address::DomainNameAddress(ref dname, port) => lookup_then!(context, dname, port, |remote_addr| {
                // Record the address mapping no matter send_to is succeeded or not
                resolved_address_cache.lock().insert(remote_addr, addr.clone());

                match try_timeout(remote_udp.send_to(body, &remote_addr), Some(timeout)).await {
                    Ok(l) => {
                        debug!(
                            "UDP ASSOCIATE {} -> {} ({}), payload length {} bytes",
                            src,
                            addr,
                            remote_addr,
                            body.len()
                        );
                        Ok(l)
                    }
                    Err(err) => {
                        error!(
                            "UDP ASSOCIATE {} -> {} ({}), payload length {} bytes",
                            src,
                            addr,
                            remote_addr,
                            body.len()
                        );
                        Err(err)
                    }
                }
            })
            .map(|(_, l)| l)?,
        };

        assert_eq!(body.len(), send_len);

        Ok(())
    }
/// Relay packets from local to remote
Relay packets from local to remote
Relay packets from local to remote
async fn relay_l2r(
        context: &Context,
        src: SocketAddr,
        remote_udp: &UdpSocket,
        pkt: Vec<u8>,
        timeout: Duration,
        svr_cfg: &ServerConfig,
        resolved_address_cache: &SharedResolvedAddressCache,
    ) -> io::Result<()> {
        // First of all, decrypt payload CLIENT -> SERVER
        let mut cur = if let CipherCategory::None = svr_cfg.method().category() {
            Cursor::new(pkt)
        } else {
            let decrypted_pkt = match decrypt_payload(context, svr_cfg.method(), svr_cfg.key(), &pkt) {
                Ok(Some(pkt)) => pkt,
                Ok(None) => {
                    error!("failed to decrypt pkt in UDP relay, packet too short");
                    let err = io::Error::new(io::ErrorKind::InvalidData, "packet too short");
                    return Err(err);
                }
                Err(err) => {
                    error!("failed to decrypt pkt in UDP relay: {}", err);
                    let err = io::Error::new(io::ErrorKind::InvalidData, "decrypt failed");
                    return Err(err);
                }
            };
            Cursor::new(decrypted_pkt)
        };
        // CLIENT -> SERVER protocol: ADDRESS + PAYLOAD
        let addr = Address::read_from(&mut cur).await?;
        if context.check_outbound_blocked(&addr).await {
            warn!("{} -> outbound {} is blocked by ACL rules", src, addr);
            return Ok(());
        }
        // Take out internal buffer for optimizing one byte copy
        let header_len = cur.position() as usize;
        let decrypted_pkt = cur.into_inner();
        let body = &decrypted_pkt[header_len..];
        let send_len = match addr {
            Address::SocketAddress(ref remote_addr) => {
                debug!(
                    "UDP ASSOCIATE {} -> {} ({}), payload length {} bytes",
                    src,
                    addr,
                    remote_addr,
                    body.len()
                );
                try_timeout(remote_udp.send_to(body, remote_addr), Some(timeout)).await?
            }
            Address::DomainNameAddress(ref dname, port) => lookup_then!(context, dname, port, |remote_addr| {
                // Record the address mapping no matter send_to is succeeded or not
                resolved_address_cache.lock().insert(remote_addr, addr.clone());
                match try_timeout(remote_udp.send_to(body, &remote_addr), Some(timeout)).await {
                    Ok(l) => {
                        debug!(
                            "UDP ASSOCIATE {} -> {} ({}), payload length {} bytes",
                            src,
                            addr,
                            remote_addr,
                            body.len()
                        );
                        Ok(l)
                    }
                    Err(err) => {
                        error!(
                            "UDP ASSOCIATE {} -> {} ({}), payload length {} bytes",
                            src,
                            addr,
                            remote_addr,
                            body.len()
                        );
                        Err(err)
                    }
                }
            })
            .map(|(_, l)| l)?,
        };
        assert_eq!(body.len(), send_len);
        Ok(())
    }
async fn relay_l2r ( context : & Context , src : SocketAddr , remote_udp : & UdpSocket , pkt : Vec < u8 > , timeout : Duration , svr_cfg : & ServerConfig , resolved_address_cache : & SharedResolvedAddressCache , ) -> io :: Result < ( ) > { // First of all, decrypt payload CLIENT -> SERVER let mut cur = if let CipherCategory :: None = svr_cfg . method ( ) . category ( ) { Cursor :: new ( pkt ) } else { let decrypted_pkt = match decrypt_payload ( context , svr_cfg . method ( ) , svr_cfg . key ( ) , & pkt ) { Ok ( Some ( pkt ) ) => pkt , Ok ( None ) => { error ! ( " " ) ; let err = io :: Error :: new ( io :: ErrorKind :: InvalidData , " " ) ; return Err ( err ) ; } Err ( err ) => { error ! ( " " err ) ; let err = io :: Error :: new ( io :: ErrorKind :: InvalidData , " " ) ; return Err ( err ) ; } } ; Cursor :: new ( decrypted_pkt ) } ; // CLIENT -> SERVER protocol: ADDRESS + PAYLOAD let addr = Address :: read_from ( & mut cur ) . await ? ; if context . check_outbound_blocked ( & addr ) . await { warn ! ( " " src addr ) ; return Ok ( ( ) ) ; } // Take out internal buffer for optimizing one byte copy let header_len = cur . position ( ) as usize ; let decrypted_pkt = cur . into_inner ( ) ; let body = & decrypted_pkt [ header_len .. ] ; let send_len = match addr { Address :: SocketAddress ( ref remote_addr ) => { debug ! ( " " src addr remote_addr body len ( ) ) ; try_timeout ( remote_udp . send_to ( body , remote_addr ) , Some ( timeout ) ) . await ? } Address :: DomainNameAddress ( ref dname , port ) => lookup_then ! ( context dname port remote_addr { // Record the address mapping no matter send_to is succeeded or not resolved_address_cache lock ( ) insert ( remote_addr addr clone ( ) ) match try_timeout ( remote_udp send_to ( body remote_addr ) Some ( timeout ) ) await { Ok ( l ) { debug ( " " src addr remote_addr body len ( ) ) Ok ( l ) } Err ( err ) { error ( " " src addr remote_addr body len ( ) ) Err ( err ) } } } ) . map ( | ( _ , l ) | l ) ? , } ; assert_eq ! ( body len ( ) send_len ) ; Ok ( ( ) ) }
Relay packets from local to remote
Relay packets from local to remote
context
&Context
src
SocketAddr
remote_udp
&UdpSocket
pkt
Vec<u8>
timeout
Duration
svr_cfg
&ServerConfig
resolved_address_cache
&SharedResolvedAddressCache