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

     1  package uot
     2  
     3  import (
     4  	"encoding/binary"
     5  	"io"
     6  
     7  	"github.com/sagernet/sing/common"
     8  	"github.com/sagernet/sing/common/buf"
     9  	M "github.com/sagernet/sing/common/metadata"
    10  )
    11  
    12  const (
    13  	Version            = 2
    14  	LegacyVersion      = 1
    15  	MagicAddress       = "sp.v2.udp-over-tcp.arpa"
    16  	LegacyMagicAddress = "sp.udp-over-tcp.arpa"
    17  )
    18  
    19  var AddrParser = M.NewSerializer(
    20  	M.AddressFamilyByte(0x00, M.AddressFamilyIPv4),
    21  	M.AddressFamilyByte(0x01, M.AddressFamilyIPv6),
    22  	M.AddressFamilyByte(0x02, M.AddressFamilyFqdn),
    23  )
    24  
    25  func RequestDestination(version uint8) M.Socksaddr {
    26  	switch version {
    27  	case 0, Version:
    28  		return M.Socksaddr{Fqdn: MagicAddress}
    29  	default:
    30  		fallthrough
    31  	case LegacyVersion:
    32  		return M.Socksaddr{Fqdn: LegacyMagicAddress}
    33  	}
    34  }
    35  
    36  type Request struct {
    37  	IsConnect   bool
    38  	Destination M.Socksaddr
    39  }
    40  
    41  func ReadRequest(reader io.Reader) (*Request, error) {
    42  	var request Request
    43  	err := binary.Read(reader, binary.BigEndian, &request.IsConnect)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  	request.Destination, err = M.SocksaddrSerializer.ReadAddrPort(reader)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	return &request, nil
    52  }
    53  
    54  func EncodeRequest(request Request) (*buf.Buffer, error) {
    55  	var bufferLen int
    56  	bufferLen += 1 // isConnect
    57  	bufferLen += M.SocksaddrSerializer.AddrPortLen(request.Destination)
    58  	buffer := buf.NewSize(bufferLen)
    59  	common.Must(binary.Write(buffer, binary.BigEndian, request.IsConnect))
    60  	err := M.SocksaddrSerializer.WriteAddrPort(buffer, request.Destination)
    61  	if err != nil {
    62  		buffer.Release()
    63  		return nil, err
    64  	}
    65  	return buffer, nil
    66  }
    67  
    68  func WriteRequest(writer io.Writer, request Request) error {
    69  	buffer, err := EncodeRequest(request)
    70  	if err != nil {
    71  		return err
    72  	}
    73  	defer buffer.Release()
    74  	return common.Error(writer.Write(buffer.Bytes()))
    75  }