5
5
"encoding/binary"
6
6
"errors"
7
7
"fmt"
8
- "io"
9
8
"math/rand"
10
9
"net"
11
10
"strconv"
50
49
// For Shadowsocks 2022, the first payload chunk MUST contain
51
50
// either a non-zero-length padding or initial payload, or both (not recommended client behavior but allowed).
52
51
// If the padding length is 0 and there's no initial payload, an error is returned.
53
- func ParseTCPReqHeader (r Reader , cipherConfig CipherConfig , htype byte ) (string , []byte , error ) {
52
+ func ParseTCPReqHeader (r Reader , cipherConfig CipherConfig ) (string , []byte , error ) {
54
53
// Read first payload chunk.
55
54
if err := r .EnsureLeftover (); err != nil {
56
55
return "" , nil , err
@@ -65,7 +64,7 @@ func ParseTCPReqHeader(r Reader, cipherConfig CipherConfig, htype byte) (string,
65
64
}
66
65
67
66
// Verify type
68
- if b [0 ] != htype {
67
+ if b [0 ] != HeaderTypeClientStream {
69
68
return "" , nil , ErrTypeMismatch
70
69
}
71
70
@@ -139,39 +138,42 @@ func WriteTCPReqHeader(dst, socksaddr []byte, addPadding bool, cipherConfig Ciph
139
138
return
140
139
}
141
140
142
- func ParseTCPRespHeader (r io. Reader , clientSalt []byte , cipherConfig CipherConfig ) error {
141
+ func ParseTCPRespHeader (r Reader , clientSalt []byte , cipherConfig CipherConfig ) ([] byte , error ) {
143
142
if ! cipherConfig .IsSpec2022 {
144
- return nil
143
+ return nil , nil
145
144
}
146
145
147
- b := make ([]byte , 1 + 8 + len (clientSalt ))
146
+ // Read first payload chunk.
147
+ if err := r .EnsureLeftover (); err != nil {
148
+ return nil , err
149
+ }
150
+ b := r .LeftoverZeroCopy ()
148
151
149
- // Read response header
150
- _ , err := io .ReadFull (r , b )
151
- if err != nil {
152
- return fmt .Errorf ("failed to read response header: %w" , err )
152
+ headerLen := 1 + 8 + len (clientSalt )
153
+ if len (b ) < headerLen {
154
+ return nil , ErrIncompleteHeaderInFirstChunk
153
155
}
154
156
155
157
// Verify type
156
158
if b [0 ] != HeaderTypeServerStream {
157
- return ErrTypeMismatch
159
+ return nil , ErrTypeMismatch
158
160
}
159
161
160
162
// Verify timestamp
161
163
epoch := int64 (binary .BigEndian .Uint64 (b [1 : 1 + 8 ]))
162
164
nowEpoch := time .Now ().Unix ()
163
165
diff := epoch - nowEpoch
164
166
if diff < - 30 || diff > 30 {
165
- return ErrBadTimestamp
167
+ return nil , ErrBadTimestamp
166
168
}
167
169
168
170
// Verify client salt
169
- n := bytes .Compare (clientSalt , b [1 + 8 :])
171
+ n := bytes .Compare (clientSalt , b [1 + 8 :headerLen ])
170
172
if n != 0 {
171
- return ErrClientSaltMismatch
173
+ return nil , ErrClientSaltMismatch
172
174
}
173
175
174
- return nil
176
+ return b [ headerLen :], nil
175
177
}
176
178
177
179
func WriteTCPRespHeader (dst , clientSalt []byte , cipherConfig CipherConfig ) (n int ) {
0 commit comments