sing/common/uot/protocol.go
2023-09-07 12:46:49 +08:00

75 lines
1.7 KiB
Go

package uot
import (
"encoding/binary"
"io"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
M "github.com/sagernet/sing/common/metadata"
)
const (
Version = 2
LegacyVersion = 1
MagicAddress = "sp.v2.udp-over-tcp.arpa"
LegacyMagicAddress = "sp.udp-over-tcp.arpa"
)
var AddrParser = M.NewSerializer(
M.AddressFamilyByte(0x00, M.AddressFamilyIPv4),
M.AddressFamilyByte(0x01, M.AddressFamilyIPv6),
M.AddressFamilyByte(0x02, M.AddressFamilyFqdn),
)
func RequestDestination(version uint8) M.Socksaddr {
switch version {
case 0, Version:
return M.Socksaddr{Fqdn: MagicAddress}
default:
fallthrough
case LegacyVersion:
return M.Socksaddr{Fqdn: LegacyMagicAddress}
}
}
type Request struct {
IsConnect bool
Destination M.Socksaddr
}
func ReadRequest(reader io.Reader) (*Request, error) {
var request Request
err := binary.Read(reader, binary.BigEndian, &request.IsConnect)
if err != nil {
return nil, err
}
request.Destination, err = M.SocksaddrSerializer.ReadAddrPort(reader)
if err != nil {
return nil, err
}
return &request, nil
}
func EncodeRequest(request Request) (*buf.Buffer, error) {
var bufferLen int
bufferLen += 1 // isConnect
bufferLen += M.SocksaddrSerializer.AddrPortLen(request.Destination)
buffer := buf.NewSize(bufferLen)
common.Must(binary.Write(buffer, binary.BigEndian, request.IsConnect))
err := M.SocksaddrSerializer.WriteAddrPort(buffer, request.Destination)
if err != nil {
buffer.Release()
return nil, err
}
return buffer, nil
}
func WriteRequest(writer io.Writer, request Request) error {
buffer, err := EncodeRequest(request)
if err != nil {
return err
}
defer buffer.Release()
return common.Error(writer.Write(buffer.Bytes()))
}