github.com/xraypb/Xray-core@v1.8.1/transport/internet/kcp/io.go (about) 1 package kcp 2 3 import ( 4 "crypto/cipher" 5 "crypto/rand" 6 "io" 7 8 "github.com/xraypb/Xray-core/common" 9 "github.com/xraypb/Xray-core/common/buf" 10 "github.com/xraypb/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 }