github.com/EagleQL/Xray-core@v1.4.3/transport/internet/kcp/io.go (about)

     1  package kcp
     2  
     3  import (
     4  	"crypto/cipher"
     5  	"crypto/rand"
     6  	"io"
     7  
     8  	"github.com/xtls/xray-core/common"
     9  	"github.com/xtls/xray-core/common/buf"
    10  	"github.com/xtls/xray-core/transport/internet"
    11  )
    12  
    13  type PacketReader interface {
    14  	Read([]byte) []Segment
    15  }
    16  
    17  type PacketWriter interface {
    18  	Overhead() int
    19  	io.Writer
    20  }
    21  
    22  type KCPPacketReader struct {
    23  	Security cipher.AEAD
    24  	Header   internet.PacketHeader
    25  }
    26  
    27  func (r *KCPPacketReader) Read(b []byte) []Segment {
    28  	if r.Header != nil {
    29  		if int32(len(b)) <= r.Header.Size() {
    30  			return nil
    31  		}
    32  		b = b[r.Header.Size():]
    33  	}
    34  	if r.Security != nil {
    35  		nonceSize := r.Security.NonceSize()
    36  		overhead := r.Security.Overhead()
    37  		if len(b) <= nonceSize+overhead {
    38  			return nil
    39  		}
    40  		out, err := r.Security.Open(b[nonceSize:nonceSize], b[:nonceSize], b[nonceSize:], nil)
    41  		if err != nil {
    42  			return nil
    43  		}
    44  		b = out
    45  	}
    46  	var result []Segment
    47  	for len(b) > 0 {
    48  		seg, x := ReadSegment(b)
    49  		if seg == nil {
    50  			break
    51  		}
    52  		result = append(result, seg)
    53  		b = x
    54  	}
    55  	return result
    56  }
    57  
    58  type KCPPacketWriter struct {
    59  	Header   internet.PacketHeader
    60  	Security cipher.AEAD
    61  	Writer   io.Writer
    62  }
    63  
    64  func (w *KCPPacketWriter) Overhead() int {
    65  	overhead := 0
    66  	if w.Header != nil {
    67  		overhead += int(w.Header.Size())
    68  	}
    69  	if w.Security != nil {
    70  		overhead += w.Security.Overhead()
    71  	}
    72  	return overhead
    73  }
    74  
    75  func (w *KCPPacketWriter) Write(b []byte) (int, error) {
    76  	bb := buf.StackNew()
    77  	defer bb.Release()
    78  
    79  	if w.Header != nil {
    80  		w.Header.Serialize(bb.Extend(w.Header.Size()))
    81  	}
    82  	if w.Security != nil {
    83  		nonceSize := w.Security.NonceSize()
    84  		common.Must2(bb.ReadFullFrom(rand.Reader, int32(nonceSize)))
    85  		nonce := bb.BytesFrom(int32(-nonceSize))
    86  
    87  		encrypted := bb.Extend(int32(w.Security.Overhead() + len(b)))
    88  		w.Security.Seal(encrypted[:0], nonce, b, nil)
    89  	} else {
    90  		bb.Write(b)
    91  	}
    92  
    93  	_, err := w.Writer.Write(bb.Bytes())
    94  	return len(b), err
    95  }