8
8
"fmt"
9
9
"io"
10
10
"net"
11
+ "strconv"
12
+ "strings"
11
13
"time"
12
14
13
15
"github.com/metacubex/mihomo/common/pool"
@@ -96,11 +98,11 @@ func (c *CommonConn) Read(b []byte) (int, error) {
96
98
if c .input .Len () > 0 {
97
99
return c .input .Read (b )
98
100
}
99
- peerHeader := make ([ ]byte , 5 )
100
- if _ , err := io .ReadFull (c .Conn , peerHeader ); err != nil {
101
+ peerHeader := [ 5 ]byte {}
102
+ if _ , err := io .ReadFull (c .Conn , peerHeader [:] ); err != nil {
101
103
return 0 , err
102
104
}
103
- l , err := DecodeHeader (peerHeader ) // l: 17~17000
105
+ l , err := DecodeHeader (peerHeader [:] ) // l: 17~17000
104
106
if err != nil {
105
107
if c .Client != nil && errors .Is (err , ErrInvalidHeader ) { // client's 0-RTT
106
108
c .Client .RWLock .Lock ()
@@ -113,7 +115,9 @@ func (c *CommonConn) Read(b []byte) (int, error) {
113
115
return 0 , err
114
116
}
115
117
c .Client = nil
116
- c .rawInput .Grow (l )
118
+ if c .rawInput .Cap () < l {
119
+ c .rawInput .Grow (l ) // no need to use sync.Pool, because we are always reading
120
+ }
117
121
peerData := c .rawInput .Bytes ()[:l ]
118
122
if _ , err := io .ReadFull (c .Conn , peerData ); err != nil {
119
123
return 0 , err
@@ -124,9 +128,9 @@ func (c *CommonConn) Read(b []byte) (int, error) {
124
128
}
125
129
var newAEAD * AEAD
126
130
if bytes .Equal (c .PeerAEAD .Nonce [:], MaxNonce ) {
127
- newAEAD = NewAEAD (append (peerHeader , peerData ... ), c .UnitedKey , c .UseAES )
131
+ newAEAD = NewAEAD (append (peerHeader [:] , peerData ... ), c .UnitedKey , c .UseAES )
128
132
}
129
- _ , err = c .PeerAEAD .Open (dst [:0 ], nil , peerData , peerHeader )
133
+ _ , err = c .PeerAEAD .Open (dst [:0 ], nil , peerData , peerHeader [:] )
130
134
if newAEAD != nil {
131
135
c .PeerAEAD = newAEAD
132
136
}
@@ -213,9 +217,69 @@ func DecodeHeader(h []byte) (l int, err error) {
213
217
return
214
218
}
215
219
220
+ func ParsePadding (padding string , paddingLens , paddingGaps * [][2 ]int ) (err error ) {
221
+ if padding == "" {
222
+ return
223
+ }
224
+ maxLen := 0
225
+ for i , s := range strings .Split (padding , "." ) {
226
+ x := strings .SplitN (s , "-" , 2 )
227
+ if len (x ) != 2 || x [0 ] == "" || x [1 ] == "" {
228
+ return errors .New ("invalid padding lenth/gap parameter: " + s )
229
+ }
230
+ y := [2 ]int {}
231
+ if y [0 ], err = strconv .Atoi (x [0 ]); err != nil {
232
+ return
233
+ }
234
+ if y [1 ], err = strconv .Atoi (x [1 ]); err != nil {
235
+ return
236
+ }
237
+ if i == 0 && (y [0 ] < 17 || y [1 ] < 17 ) {
238
+ return errors .New ("first padding length must be larger than 16" )
239
+ }
240
+ if i % 2 == 0 {
241
+ * paddingLens = append (* paddingLens , y )
242
+ maxLen += max (y [0 ], y [1 ])
243
+ } else {
244
+ * paddingGaps = append (* paddingGaps , y )
245
+ }
246
+ }
247
+ if maxLen > 65535 {
248
+ return errors .New ("total padding length must be smaller than 65536" )
249
+ }
250
+ return
251
+ }
252
+
253
+ func CreatPadding (paddingLens , paddingGaps [][2 ]int ) (length int , lens []int , gaps []time.Duration ) {
254
+ if len (paddingLens ) == 0 {
255
+ paddingLens = [][2 ]int {{111 , 1111 }, {3333 , - 1234 }}
256
+ paddingGaps = [][2 ]int {{111 , - 66 }}
257
+ }
258
+ for _ , l := range paddingLens {
259
+ lens = append (lens , int (max (0 , randBetween (int64 (l [0 ]), int64 (l [1 ])))))
260
+ length += lens [len (lens )- 1 ]
261
+ }
262
+ for _ , g := range paddingGaps {
263
+ gaps = append (gaps , time .Duration (max (0 , randBetween (int64 (g [0 ]), int64 (g [1 ]))))* time .Millisecond )
264
+ }
265
+ return
266
+ }
267
+
268
+ func max [T ~ int | ~ uint | ~ int64 | ~ uint64 | ~ int32 | ~ uint32 | ~ int16 | ~ uint16 | ~ int8 | ~ uint8 ](a , b T ) T {
269
+ if a > b {
270
+ return a
271
+ }
272
+ return b
273
+ }
274
+
216
275
func randBetween (from int64 , to int64 ) int64 {
217
276
if from == to {
218
277
return from
219
278
}
279
+
280
+ if to < from {
281
+ from , to = to , from
282
+ }
283
+
220
284
return from + randv2 .Int64N (to - from )
221
285
}
0 commit comments