github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/uot/server.go (about)

     1  package uot
     2  
     3  import (
     4  	"encoding/binary"
     5  	"io"
     6  	"net"
     7  
     8  	"github.com/sagernet/sing/common/buf"
     9  	M "github.com/sagernet/sing/common/metadata"
    10  )
    11  
    12  type ServerConn struct {
    13  	net.PacketConn
    14  	version                   int
    15  	isConnect                 bool
    16  	destination               M.Socksaddr
    17  	inputReader, outputReader *io.PipeReader
    18  	inputWriter, outputWriter *io.PipeWriter
    19  }
    20  
    21  func NewServerConn(packetConn net.PacketConn, version int) net.Conn {
    22  	c := &ServerConn{
    23  		PacketConn: packetConn,
    24  		version:    version,
    25  	}
    26  	c.inputReader, c.inputWriter = io.Pipe()
    27  	c.outputReader, c.outputWriter = io.Pipe()
    28  	go c.loopInput()
    29  	go c.loopOutput()
    30  	return c
    31  }
    32  
    33  func (c *ServerConn) Read(b []byte) (n int, err error) {
    34  	return c.outputReader.Read(b)
    35  }
    36  
    37  func (c *ServerConn) Write(b []byte) (n int, err error) {
    38  	return c.inputWriter.Write(b)
    39  }
    40  
    41  func (c *ServerConn) RemoteAddr() net.Addr {
    42  	return M.Socksaddr{Fqdn: "pipe"}
    43  }
    44  
    45  //warn:unsafe
    46  func (c *ServerConn) loopInput() {
    47  	if c.version == Version {
    48  		request, err := ReadRequest(c.inputReader)
    49  		if err != nil {
    50  			return
    51  		}
    52  		c.isConnect = request.IsConnect
    53  		c.destination = request.Destination
    54  	}
    55  	buffer := buf.NewPacket()
    56  	defer buffer.Release()
    57  	for {
    58  		var destination M.Socksaddr
    59  		var err error
    60  		if c.isConnect {
    61  			destination = c.destination
    62  		} else {
    63  			destination, err = AddrParser.ReadAddrPort(c.inputReader)
    64  			if err != nil {
    65  				break
    66  			}
    67  		}
    68  		if destination.IsFqdn() {
    69  			addr, err := net.ResolveUDPAddr("udp", destination.String())
    70  			if err != nil {
    71  				continue
    72  			}
    73  			destination = M.SocksaddrFromNet(addr)
    74  		}
    75  		var length uint16
    76  		err = binary.Read(c.inputReader, binary.BigEndian, &length)
    77  		if err != nil {
    78  			break
    79  		}
    80  		buffer.Reset()
    81  		_, err = buffer.ReadFullFrom(c.inputReader, int(length))
    82  		if err != nil {
    83  			break
    84  		}
    85  		_, err = c.WriteTo(buffer.Bytes(), destination.UDPAddr())
    86  		if err != nil {
    87  			break
    88  		}
    89  	}
    90  	c.Close()
    91  }
    92  
    93  //warn:unsafe
    94  func (c *ServerConn) loopOutput() {
    95  	buffer := buf.NewPacket()
    96  	defer buffer.Release()
    97  	for {
    98  		buffer.Reset()
    99  		n, addr, err := buffer.ReadPacketFrom(c)
   100  		if err != nil {
   101  			break
   102  		}
   103  		if !c.isConnect {
   104  			err = AddrParser.WriteAddrPort(c.outputWriter, M.SocksaddrFromNet(addr))
   105  			if err != nil {
   106  				break
   107  			}
   108  		}
   109  		err = binary.Write(c.outputWriter, binary.BigEndian, uint16(n))
   110  		if err != nil {
   111  			break
   112  		}
   113  		_, err = buffer.WriteTo(c.outputWriter)
   114  		if err != nil {
   115  			break
   116  		}
   117  	}
   118  	c.Close()
   119  }
   120  
   121  func (c *ServerConn) Close() error {
   122  	c.inputReader.Close()
   123  	c.inputWriter.Close()
   124  	c.outputReader.Close()
   125  	c.outputWriter.Close()
   126  	c.PacketConn.Close()
   127  	return nil
   128  }