mirror of
				https://github.com/dndx/phantun.git
				synced 2025-11-04 20:05:35 +08:00 
			
		
		
		
	fix(fake-tcp): when connect()-ing, attempt to get ephemeral port using algorithm similar to Linux (#162)
				
					
				
			* fix(fake-tcp): when `connect()`-ing, attempt to get ephemeral port 5 times to reduce the chance of panicking Fixes #79
This commit is contained in:
		@@ -50,8 +50,10 @@ use rand::prelude::*;
 | 
			
		||||
use std::collections::{HashMap, HashSet};
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
 | 
			
		||||
use std::sync::atomic::{AtomicU32, Ordering};
 | 
			
		||||
use std::sync::{Arc, RwLock};
 | 
			
		||||
use std::sync::{
 | 
			
		||||
    atomic::{AtomicU32, Ordering},
 | 
			
		||||
    Arc, RwLock,
 | 
			
		||||
};
 | 
			
		||||
use tokio::sync::broadcast;
 | 
			
		||||
use tokio::sync::mpsc;
 | 
			
		||||
use tokio::time;
 | 
			
		||||
@@ -401,7 +403,7 @@ impl Stack {
 | 
			
		||||
    /// the connection attempt failed.
 | 
			
		||||
    pub async fn connect(&mut self, addr: SocketAddr) -> Option<Socket> {
 | 
			
		||||
        let mut rng = SmallRng::from_entropy();
 | 
			
		||||
        let local_port: u16 = rng.gen_range(1024..65535);
 | 
			
		||||
        for local_port in rng.gen_range(32768..=60999)..=60999 {
 | 
			
		||||
            let local_addr = SocketAddr::new(
 | 
			
		||||
                if addr.is_ipv4() {
 | 
			
		||||
                    IpAddr::V4(self.local_ip)
 | 
			
		||||
@@ -411,7 +413,20 @@ impl Stack {
 | 
			
		||||
                local_port,
 | 
			
		||||
            );
 | 
			
		||||
            let tuple = AddrTuple::new(local_addr, addr);
 | 
			
		||||
        let (mut sock, incoming) = Socket::new(
 | 
			
		||||
            let mut sock;
 | 
			
		||||
 | 
			
		||||
            {
 | 
			
		||||
                let mut tuples = self.shared.tuples.write().unwrap();
 | 
			
		||||
                if tuples.contains_key(&tuple) {
 | 
			
		||||
                    trace!(
 | 
			
		||||
                        "Fake TCP connection to {}, local port number {} already in use, trying another one",
 | 
			
		||||
                        addr, local_port
 | 
			
		||||
                    );
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let incoming;
 | 
			
		||||
                (sock, incoming) = Socket::new(
 | 
			
		||||
                    self.shared.clone(),
 | 
			
		||||
                    self.shared.tun.choose(&mut rng).unwrap().clone(),
 | 
			
		||||
                    local_addr,
 | 
			
		||||
@@ -420,12 +435,17 @@ impl Stack {
 | 
			
		||||
                    State::Idle,
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            let mut tuples = self.shared.tuples.write().unwrap();
 | 
			
		||||
            assert!(tuples.insert(tuple, incoming.clone()).is_none());
 | 
			
		||||
                assert!(tuples.insert(tuple, incoming).is_none());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        sock.connect().await.map(|_| sock)
 | 
			
		||||
            return sock.connect().await.map(|_| sock);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        error!(
 | 
			
		||||
            "Fake TCP connection to {} failed, emphemeral port number exhausted",
 | 
			
		||||
            addr
 | 
			
		||||
        );
 | 
			
		||||
        None
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn reader_task(
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user