|  | @@ -1,12 +1,8 @@
 | 
	
		
			
				|  |  |  package socks
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import (
 | 
	
		
			
				|  |  | -	"math"
 | 
	
		
			
				|  |  | -	"math/rand"
 | 
	
		
			
				|  |  |  	"net"
 | 
	
		
			
				|  |  | -	"sync"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	"github.com/v2ray/v2ray-core/common/collect"
 | 
	
		
			
				|  |  |  	"github.com/v2ray/v2ray-core/common/log"
 | 
	
		
			
				|  |  |  	v2net "github.com/v2ray/v2ray-core/common/net"
 | 
	
		
			
				|  |  |  	"github.com/v2ray/v2ray-core/proxy/socks/protocol"
 | 
	
	
		
			
				|  | @@ -16,66 +12,7 @@ const (
 | 
	
		
			
				|  |  |  	bufferSize = 2 * 1024
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -type portMap struct {
 | 
	
		
			
				|  |  | -	access       sync.Mutex
 | 
	
		
			
				|  |  | -	data         map[uint16]*net.UDPAddr
 | 
	
		
			
				|  |  | -	removedPorts *collect.TimedQueue
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func newPortMap() *portMap {
 | 
	
		
			
				|  |  | -	m := &portMap{
 | 
	
		
			
				|  |  | -		access:       sync.Mutex{},
 | 
	
		
			
				|  |  | -		data:         make(map[uint16]*net.UDPAddr),
 | 
	
		
			
				|  |  | -		removedPorts: collect.NewTimedQueue(1),
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	go m.removePorts(m.removedPorts.RemovedEntries())
 | 
	
		
			
				|  |  | -	return m
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (m *portMap) assignAddressToken(addr *net.UDPAddr) uint16 {
 | 
	
		
			
				|  |  | -	for {
 | 
	
		
			
				|  |  | -		token := uint16(rand.Intn(math.MaxUint16))
 | 
	
		
			
				|  |  | -		if _, used := m.data[token]; !used {
 | 
	
		
			
				|  |  | -			m.access.Lock()
 | 
	
		
			
				|  |  | -			if _, used = m.data[token]; !used {
 | 
	
		
			
				|  |  | -				m.data[token] = addr
 | 
	
		
			
				|  |  | -				m.access.Unlock()
 | 
	
		
			
				|  |  | -				return token
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -			m.access.Unlock()
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (m *portMap) removePorts(removedPorts <-chan interface{}) {
 | 
	
		
			
				|  |  | -	for {
 | 
	
		
			
				|  |  | -		rawToken := <-removedPorts
 | 
	
		
			
				|  |  | -		m.access.Lock()
 | 
	
		
			
				|  |  | -		delete(m.data, rawToken.(uint16))
 | 
	
		
			
				|  |  | -		m.access.Unlock()
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (m *portMap) popPort(token uint16) *net.UDPAddr {
 | 
	
		
			
				|  |  | -	m.access.Lock()
 | 
	
		
			
				|  |  | -	defer m.access.Unlock()
 | 
	
		
			
				|  |  | -	addr, exists := m.data[token]
 | 
	
		
			
				|  |  | -	if !exists {
 | 
	
		
			
				|  |  | -		return nil
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	delete(m.data, token)
 | 
	
		
			
				|  |  | -	return addr
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -var (
 | 
	
		
			
				|  |  | -	ports *portMap
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	udpConn *net.UDPConn
 | 
	
		
			
				|  |  | -)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  func (server *SocksServer) ListenUDP(port uint16) error {
 | 
	
		
			
				|  |  | -	ports = newPortMap()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	addr := &net.UDPAddr{
 | 
	
		
			
				|  |  |  		IP:   net.IP{0, 0, 0, 0},
 | 
	
		
			
				|  |  |  		Port: int(port),
 | 
	
	
		
			
				|  | @@ -88,7 +25,6 @@ func (server *SocksServer) ListenUDP(port uint16) error {
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	go server.AcceptPackets(conn)
 | 
	
		
			
				|  |  | -	udpConn = conn
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -110,20 +46,16 @@ func (server *SocksServer) AcceptPackets(conn *net.UDPConn) error {
 | 
	
		
			
				|  |  |  			continue
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		token := ports.assignAddressToken(addr)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		udpPacket := v2net.NewUDPPacket(request.Destination(), request.Data, token)
 | 
	
		
			
				|  |  | -		server.vPoint.DispatchToOutbound(udpPacket)
 | 
	
		
			
				|  |  | +		udpPacket := v2net.NewPacket(request.Destination(), request.Data, false)
 | 
	
		
			
				|  |  | +		go server.handlePacket(conn, udpPacket, addr)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (server *SocksServer) Dispatch(packet v2net.Packet) {
 | 
	
		
			
				|  |  | -	if udpPacket, ok := packet.(*v2net.UDPPacket); ok {
 | 
	
		
			
				|  |  | -		token := udpPacket.Token()
 | 
	
		
			
				|  |  | -		addr := ports.popPort(token)
 | 
	
		
			
				|  |  | -		if udpConn != nil {
 | 
	
		
			
				|  |  | -			udpConn.WriteToUDP(udpPacket.Chunk(), addr)
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +func (server *SocksServer) handlePacket(conn *net.UDPConn, packet v2net.Packet, clientAddr *net.UDPAddr) {
 | 
	
		
			
				|  |  | +	ray := server.vPoint.DispatchToOutbound(packet)
 | 
	
		
			
				|  |  | +	close(ray.InboundInput())
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if data, ok := <-ray.InboundOutput(); ok {
 | 
	
		
			
				|  |  | +		conn.WriteToUDP(data, clientAddr)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	// We don't expect TCP Packets here
 | 
	
		
			
				|  |  |  }
 |