package socks5 import ( "bytes" "errors" "net" ) var ( // ErrNoConnectedAddress is the no connected address error ErrNoConnectedAddress = errors.New("no connected address") ) type UDPConn struct { net.PacketConn TCPConn net.Conn ServerAddr net.Addr ConnectedAddr net.Addr } func (s *UDPConn) ReadFrom(b []byte) (int, net.Addr, error) { nr, _, err := s.PacketConn.ReadFrom(b) if err != nil { return 0, nil, err } datagram, err := NewDatagramFrom(bytes.NewReader(b[:nr])) if err != nil { return 0, nil, err } nc := copy(b, datagram.Data) return nc, AddrFromSocks(datagram.ATYP, datagram.DstAddr, datagram.DstPort), nil } func (s *UDPConn) Read(b []byte) (int, error) { n, _, err := s.ReadFrom(b) return n, err } func (s *UDPConn) WriteTo(b []byte, addr net.Addr) (int, error) { socksAddr, err := AddrFromString(addr.String()) if err != nil { return 0, err } atyp, host, port := socksAddr.Socks() datagram := NewDatagram(atyp, host, port, b) n, err := s.PacketConn.WriteTo(datagram.Bytes(), s.ServerAddr) if n < 10 { n = 10 } return n - 10, err } func (s *UDPConn) Write(b []byte) (int, error) { if s.ConnectedAddr == nil { return 0, ErrNoConnectedAddress } return s.WriteTo(b, s.ConnectedAddr) } func (s *UDPConn) Close() error { s.TCPConn.Close() return s.PacketConn.Close() } func (s *UDPConn) RemoteAddr() net.Addr { return s.ConnectedAddr }