ソースを参照

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

RPRX 2 年 前
コミット
b4c1a56026
3 ファイル変更14 行追加11 行削除
  1. 5 3
      common/mux/frame.go
  2. 1 1
      common/mux/server.go
  3. 8 7
      common/xudp/xudp.go

+ 5 - 3
common/mux/frame.go

@@ -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 {
 			return err
 		}
-		if b.UDP != nil {
-			b.Write(f.GlobalID[:])
+		if b.UDP != nil { // make sure it's user's proxy request
+			b.Write(f.GlobalID[:]) // no need to check whether it's empty
 		}
 	} else if b.UDP != nil {
 		b.WriteByte(byte(TargetNetworkUDP))
@@ -126,7 +126,8 @@ func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error {
 	f.Option = bitmask.Byte(b.Byte(3))
 	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 {
 			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) &&
 		f.Target.Network == net.Network_UDP && b.Len() >= 8 {
 		copy(f.GlobalID[:], b.Bytes())

+ 1 - 1
common/mux/server.go

@@ -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()
 		if err != nil {
 			return err

+ 8 - 7
common/xudp/xudp.go

@@ -86,21 +86,21 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
 		}
 
 		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 {
 			eb.WriteByte(1) // New
 			eb.WriteByte(1) // Opt
 			eb.WriteByte(2) // UDP
 			AddrParser.WriteAddressPort(eb, w.Dest.Address, w.Dest.Port)
 			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
 		} else {
 			eb.WriteByte(2) // Keep
-			eb.WriteByte(1)
+			eb.WriteByte(1) // Opt
 			if b.UDP != nil {
-				eb.WriteByte(2)
+				eb.WriteByte(2) // UDP
 				AddrParser.WriteAddressPort(eb, b.UDP.Address, b.UDP.Port)
 			}
 		}
@@ -148,9 +148,10 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
 		discard := false
 		switch b.Byte(2) {
 		case 2:
-			if l != 4 {
+			if l > 4 && b.Byte(4) == 2 { // MUST check the flag first
 				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 {
 					b.Release()
 					return nil, err
@@ -167,6 +168,7 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
 			b.Release()
 			return nil, io.EOF
 		}
+		b.Clear() // in case there is padding (empty bytes) attached
 		if b.Byte(3) == 1 {
 			if _, err := io.ReadFull(r.Reader, r.cache); err != nil {
 				b.Release()
@@ -174,7 +176,6 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
 			}
 			length := int32(r.cache[0])<<8 | int32(r.cache[1])
 			if length > 0 {
-				b.Clear()
 				if _, err := b.ReadFullFrom(r.Reader, length); err != nil {
 					b.Release()
 					return nil, err