XUDP practice: MUST check the flag first & Add more comments

This commit is contained in:
RPRX 2023-04-16 21:15:27 +00:00 committed by GitHub
parent 9f8e9e8e64
commit b4c1a56026
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 14 additions and 11 deletions

View File

@ -82,8 +82,8 @@ func (f FrameMetadata) WriteTo(b *buf.Buffer) error {
if err := addrParser.WriteAddressPort(b, f.Target.Address, f.Target.Port); err != nil { if err := addrParser.WriteAddressPort(b, f.Target.Address, f.Target.Port); err != nil {
return err return err
} }
if b.UDP != nil { if b.UDP != nil { // make sure it's user's proxy request
b.Write(f.GlobalID[:]) b.Write(f.GlobalID[:]) // no need to check whether it's empty
} }
} else if b.UDP != nil { } else if b.UDP != nil {
b.WriteByte(byte(TargetNetworkUDP)) b.WriteByte(byte(TargetNetworkUDP))
@ -126,7 +126,8 @@ func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error {
f.Option = bitmask.Byte(b.Byte(3)) f.Option = bitmask.Byte(b.Byte(3))
f.Target.Network = net.Network_Unknown f.Target.Network = net.Network_Unknown
if f.SessionStatus == SessionStatusNew || (f.SessionStatus == SessionStatusKeep && b.Len() != 4) { if f.SessionStatus == SessionStatusNew || (f.SessionStatus == SessionStatusKeep && b.Len() > 4 &&
TargetNetwork(b.Byte(4)) == TargetNetworkUDP) { // MUST check the flag first
if b.Len() < 8 { if b.Len() < 8 {
return newError("insufficient buffer: ", b.Len()) return newError("insufficient buffer: ", b.Len())
} }
@ -148,6 +149,7 @@ func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error {
} }
} }
// Application data is essential, to test whether the pipe is closed.
if f.SessionStatus == SessionStatusNew && f.Option.Has(OptionData) && if f.SessionStatus == SessionStatusNew && f.Option.Has(OptionData) &&
f.Target.Network == net.Network_UDP && b.Len() >= 8 { f.Target.Network == net.Network_UDP && b.Len() >= 8 {
copy(f.GlobalID[:], b.Bytes()) copy(f.GlobalID[:], b.Bytes())

View File

@ -138,7 +138,7 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
} }
} }
if meta.GlobalID != [8]byte{} { if meta.GlobalID != [8]byte{} { // MUST ignore empty Global ID
mb, err := NewPacketReader(reader, &meta.Target).ReadMultiBuffer() mb, err := NewPacketReader(reader, &meta.Target).ReadMultiBuffer()
if err != nil { if err != nil {
return err return err

View File

@ -86,21 +86,21 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
} }
eb := buf.New() eb := buf.New()
eb.Write([]byte{0, 0, 0, 0}) eb.Write([]byte{0, 0, 0, 0}) // Meta data length; Mux Session ID
if w.Dest.Network == net.Network_UDP { if w.Dest.Network == net.Network_UDP {
eb.WriteByte(1) // New eb.WriteByte(1) // New
eb.WriteByte(1) // Opt eb.WriteByte(1) // Opt
eb.WriteByte(2) // UDP eb.WriteByte(2) // UDP
AddrParser.WriteAddressPort(eb, w.Dest.Address, w.Dest.Port) AddrParser.WriteAddressPort(eb, w.Dest.Address, w.Dest.Port)
if b.UDP != nil { // make sure it's user's proxy request if b.UDP != nil { // make sure it's user's proxy request
eb.Write(w.GlobalID[:]) eb.Write(w.GlobalID[:]) // no need to check whether it's empty
} }
w.Dest.Network = net.Network_Unknown w.Dest.Network = net.Network_Unknown
} else { } else {
eb.WriteByte(2) // Keep eb.WriteByte(2) // Keep
eb.WriteByte(1) eb.WriteByte(1) // Opt
if b.UDP != nil { if b.UDP != nil {
eb.WriteByte(2) eb.WriteByte(2) // UDP
AddrParser.WriteAddressPort(eb, b.UDP.Address, b.UDP.Port) AddrParser.WriteAddressPort(eb, b.UDP.Address, b.UDP.Port)
} }
} }
@ -148,9 +148,10 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
discard := false discard := false
switch b.Byte(2) { switch b.Byte(2) {
case 2: case 2:
if l != 4 { if l > 4 && b.Byte(4) == 2 { // MUST check the flag first
b.Advance(5) b.Advance(5)
addr, port, err := AddrParser.ReadAddressPort(nil, b) // read addr will read all content and clear b // b.Clear() will be called automatically if all data had been read.
addr, port, err := AddrParser.ReadAddressPort(nil, b)
if err != nil { if err != nil {
b.Release() b.Release()
return nil, err return nil, err
@ -167,6 +168,7 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
b.Release() b.Release()
return nil, io.EOF return nil, io.EOF
} }
b.Clear() // in case there is padding (empty bytes) attached
if b.Byte(3) == 1 { if b.Byte(3) == 1 {
if _, err := io.ReadFull(r.Reader, r.cache); err != nil { if _, err := io.ReadFull(r.Reader, r.cache); err != nil {
b.Release() b.Release()
@ -174,7 +176,6 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
} }
length := int32(r.cache[0])<<8 | int32(r.cache[1]) length := int32(r.cache[0])<<8 | int32(r.cache[1])
if length > 0 { if length > 0 {
b.Clear()
if _, err := b.ReadFullFrom(r.Reader, length); err != nil { if _, err := b.ReadFullFrom(r.Reader, length); err != nil {
b.Release() b.Release()
return nil, err return nil, err