package bond import ( "encoding/binary" "io" "github.com/gofrs/uuid/v5" "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/buf" E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" ) const ( Version = 0 ) var Destination = M.Socksaddr{ Fqdn: "sp.bond.sing-box.arpa", Port: 444, } var AddressSerializer = M.NewSerializer( M.AddressFamilyByte(0x01, M.AddressFamilyIPv4), M.AddressFamilyByte(0x03, M.AddressFamilyIPv6), M.AddressFamilyByte(0x02, M.AddressFamilyFqdn), M.PortThenAddress(), ) type Request struct { UUID uuid.UUID Index byte Count byte DownloadRatio byte UploadRatio byte Destination M.Socksaddr } func ReadRequest(reader io.Reader) (*Request, error) { var request Request var version uint8 err := binary.Read(reader, binary.BigEndian, &version) if err != nil { return nil, err } if version != Version { return nil, E.New("unknown version: ", version) } _, err = io.ReadFull(reader, request.UUID[:]) if err != nil { return nil, err } err = binary.Read(reader, binary.BigEndian, &request.Index) if err != nil { return nil, err } err = binary.Read(reader, binary.BigEndian, &request.Count) if err != nil { return nil, err } err = binary.Read(reader, binary.BigEndian, &request.DownloadRatio) if err != nil { return nil, err } err = binary.Read(reader, binary.BigEndian, &request.UploadRatio) if err != nil { return nil, err } request.Destination, err = AddressSerializer.ReadAddrPort(reader) if err != nil { return nil, err } return &request, nil } func WriteRequest(writer io.Writer, request *Request) error { var requestLen int requestLen += 1 // version requestLen += 16 // UUID requestLen += 1 // index requestLen += 1 // count requestLen += 1 // download ratio requestLen += 1 // upload ratio requestLen += AddressSerializer.AddrPortLen(request.Destination) buffer := buf.NewSize(requestLen) defer buffer.Release() common.Must( buffer.WriteByte(Version), common.Error(buffer.Write(request.UUID[:])), buffer.WriteByte(request.Index), buffer.WriteByte(request.Count), buffer.WriteByte(request.DownloadRatio), buffer.WriteByte(request.UploadRatio), ) err := AddressSerializer.WriteAddrPort(buffer, request.Destination) if err != nil { return err } return common.Error(writer.Write(buffer.Bytes())) }