@@ -8,12 +8,19 @@ import (
88 "io"
99 "net"
1010 "strings"
11+ "sync"
1112 "time"
1213
1314 "github.com/xtls/xray-core/common/errors"
1415 "lukechampine.com/blake3"
1516)
1617
18+ var OutBytesPool = sync.Pool {
19+ New : func () any {
20+ return make ([]byte , 5 + 8192 + 16 )
21+ },
22+ }
23+
1724type CommonConn struct {
1825 net.Conn
1926 Client * ClientInstance
@@ -22,35 +29,44 @@ type CommonConn struct {
2229 GCM * GCM
2330 PeerGCM * GCM
2431 PeerPadding []byte
32+ PeerInBytes []byte
2533 PeerCache []byte
2634}
2735
36+ func NewCommonConn (conn net.Conn ) * CommonConn {
37+ return & CommonConn {
38+ Conn : conn ,
39+ PeerInBytes : make ([]byte , 5 + 17000 ), // no need to use sync.Pool, because we are always reading
40+ }
41+ }
42+
2843func (c * CommonConn ) Write (b []byte ) (int , error ) {
2944 if len (b ) == 0 {
3045 return 0 , nil
3146 }
32- var data []byte
47+ outBytes := OutBytesPool .Get ().([]byte )
48+ defer OutBytesPool .Put (outBytes )
3349 for n := 0 ; n < len (b ); {
3450 b := b [n :]
3551 if len (b ) > 8192 {
3652 b = b [:8192 ] // for avoiding another copy() in peer's Read()
3753 }
3854 n += len (b )
39- data = make ([] byte , 5 + len (b )+ 16 )
40- EncodeHeader (data , len (b )+ 16 )
55+ headerAndData := outBytes [: 5 + len (b )+ 16 ]
56+ EncodeHeader (headerAndData , len (b )+ 16 )
4157 max := false
4258 if bytes .Equal (c .GCM .Nonce [:], MaxNonce ) {
4359 max = true
4460 }
45- c .GCM .Seal (data [:5 ], nil , b , data [:5 ])
61+ c .GCM .Seal (headerAndData [:5 ], nil , b , headerAndData [:5 ])
4662 if max {
47- c .GCM = NewGCM (data [ 5 :] , c .UnitedKey )
63+ c .GCM = NewGCM (headerAndData , c .UnitedKey )
4864 }
4965 if c .PreWrite != nil {
50- data = append (c .PreWrite , data ... )
66+ headerAndData = append (c .PreWrite , headerAndData ... )
5167 c .PreWrite = nil
5268 }
53- if _ , err := c .Conn .Write (data ); err != nil {
69+ if _ , err := c .Conn .Write (headerAndData ); err != nil {
5470 return 0 , err
5571 }
5672 }
@@ -80,14 +96,18 @@ func (c *CommonConn) Read(b []byte) (int, error) {
8096 }
8197 c .PeerPadding = nil
8298 }
83- if len (c .PeerCache ) != 0 {
99+ if len (c .PeerCache ) > 0 {
84100 n := copy (b , c .PeerCache )
85101 c .PeerCache = c .PeerCache [n :]
86102 return n , nil
87103 }
88- h , l , err := ReadAndDecodeHeader (c .Conn ) // l: 17~17000
104+ peerHeader := c .PeerInBytes [:5 ]
105+ if _ , err := io .ReadFull (c .Conn , peerHeader ); err != nil {
106+ return 0 , err
107+ }
108+ l , err := DecodeHeader (c .PeerInBytes [:5 ]) // l: 17~17000
89109 if err != nil {
90- if c .Client != nil && strings .HasPrefix (err .Error (), "invalid header: " ) { // client's 0-RTT
110+ if c .Client != nil && strings .Contains (err .Error (), "invalid header: " ) { // client's 0-RTT
91111 c .Client .RWLock .Lock ()
92112 if bytes .HasPrefix (c .UnitedKey , c .Client .PfsKey ) {
93113 c .Client .Expire = time .Now () // expired
@@ -98,7 +118,7 @@ func (c *CommonConn) Read(b []byte) (int, error) {
98118 return 0 , err
99119 }
100120 c .Client = nil
101- peerData := make ([] byte , l )
121+ peerData := c . PeerInBytes [ 5 : 5 + l ]
102122 if _ , err := io .ReadFull (c .Conn , peerData ); err != nil {
103123 return 0 , err
104124 }
@@ -108,9 +128,9 @@ func (c *CommonConn) Read(b []byte) (int, error) {
108128 }
109129 var newGCM * GCM
110130 if bytes .Equal (c .PeerGCM .Nonce [:], MaxNonce ) {
111- newGCM = NewGCM (peerData , c .UnitedKey )
131+ newGCM = NewGCM (c . PeerInBytes [: 5 + l ] , c .UnitedKey )
112132 }
113- _ , err = c .PeerGCM .Open (dst [:0 ], nil , peerData , h )
133+ _ , err = c .PeerGCM .Open (dst [:0 ], nil , peerData , peerHeader )
114134 if newGCM != nil {
115135 c .PeerGCM = newGCM
116136 }
@@ -190,23 +210,3 @@ func DecodeHeader(h []byte) (l int, err error) {
190210 }
191211 return
192212}
193-
194- func ReadAndDecodeHeader (conn net.Conn ) (h []byte , l int , err error ) {
195- h = make ([]byte , 5 )
196- if _ , err = io .ReadFull (conn , h ); err != nil {
197- return
198- }
199- l , err = DecodeHeader (h )
200- return
201- }
202-
203- func ReadAndDiscardPaddings (conn net.Conn ) (h []byte , l int , err error ) {
204- for {
205- if h , l , err = ReadAndDecodeHeader (conn ); err != nil {
206- return
207- }
208- if _ , err = io .ReadFull (conn , make ([]byte , l )); err != nil {
209- return
210- }
211- }
212- }
0 commit comments