| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 | package socksimport (	"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")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),		Zone: "",	}	conn, err := net.ListenUDP("udp", addr)	if err != nil {		log.Error("Socks failed to listen UDP on port %d: %v", port, err)		return err	}	go server.AcceptPackets(conn)	udpConn = conn	return nil}func (server *SocksServer) AcceptPackets(conn *net.UDPConn) error {	for {		buffer := make([]byte, 0, bufferSize)		nBytes, addr, err := conn.ReadFromUDP(buffer)		if err != nil {			log.Error("Socks failed to read UDP packets: %v", err)			return err		}		request, err := protocol.ReadUDPRequest(buffer[:nBytes])		if err != nil {			log.Error("Socks failed to parse UDP request: %v", err)			return err		}		if request.Fragment != 0 {			// TODO handle fragments			continue		}		token := ports.assignAddressToken(addr)		udpPacket := v2net.NewUDPPacket(request.Destination(), request.Data, token)		server.vPoint.DispatchToOutbound(udpPacket)	}}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)		}	}	// We don't expect TCP Packets here}
 |