github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/proxy/shadowsocks/protocol_test.go (about) 1 package shadowsocks_test 2 3 import ( 4 "testing" 5 6 "github.com/google/go-cmp/cmp" 7 "github.com/xmplusdev/xmcore/common" 8 "github.com/xmplusdev/xmcore/common/buf" 9 "github.com/xmplusdev/xmcore/common/net" 10 "github.com/xmplusdev/xmcore/common/protocol" 11 . "github.com/xmplusdev/xmcore/proxy/shadowsocks" 12 ) 13 14 func toAccount(a *Account) protocol.Account { 15 account, err := a.AsAccount() 16 common.Must(err) 17 return account 18 } 19 20 func equalRequestHeader(x, y *protocol.RequestHeader) bool { 21 return cmp.Equal(x, y, cmp.Comparer(func(x, y protocol.RequestHeader) bool { 22 return x == y 23 })) 24 } 25 26 func TestUDPEncodingDecoding(t *testing.T) { 27 testRequests := []protocol.RequestHeader{ 28 { 29 Version: Version, 30 Command: protocol.RequestCommandUDP, 31 Address: net.LocalHostIP, 32 Port: 1234, 33 User: &protocol.MemoryUser{ 34 Email: "love@example.com", 35 Account: toAccount(&Account{ 36 Password: "password", 37 CipherType: CipherType_AES_128_GCM, 38 }), 39 }, 40 }, 41 { 42 Version: Version, 43 Command: protocol.RequestCommandUDP, 44 Address: net.LocalHostIP, 45 Port: 1234, 46 User: &protocol.MemoryUser{ 47 Email: "love@example.com", 48 Account: toAccount(&Account{ 49 Password: "123", 50 CipherType: CipherType_NONE, 51 }), 52 }, 53 }, 54 } 55 56 for _, request := range testRequests { 57 data := buf.New() 58 common.Must2(data.WriteString("test string")) 59 encodedData, err := EncodeUDPPacket(&request, data.Bytes()) 60 common.Must(err) 61 62 validator := new(Validator) 63 validator.Add(request.User) 64 decodedRequest, decodedData, err := DecodeUDPPacket(validator, encodedData) 65 common.Must(err) 66 67 if r := cmp.Diff(decodedData.Bytes(), data.Bytes()); r != "" { 68 t.Error("data: ", r) 69 } 70 71 if equalRequestHeader(decodedRequest, &request) == false { 72 t.Error("different request") 73 } 74 } 75 } 76 77 func TestUDPDecodingWithPayloadTooShort(t *testing.T) { 78 testAccounts := []protocol.Account{ 79 toAccount(&Account{ 80 Password: "password", 81 CipherType: CipherType_AES_128_GCM, 82 }), 83 toAccount(&Account{ 84 Password: "password", 85 CipherType: CipherType_NONE, 86 }), 87 } 88 89 for _, account := range testAccounts { 90 data := buf.New() 91 data.WriteString("short payload") 92 validator := new(Validator) 93 validator.Add(&protocol.MemoryUser{ 94 Account: account, 95 }) 96 _, _, err := DecodeUDPPacket(validator, data) 97 if err == nil { 98 t.Fatal("expected error") 99 } 100 } 101 } 102 103 func TestTCPRequest(t *testing.T) { 104 cases := []struct { 105 request *protocol.RequestHeader 106 payload []byte 107 }{ 108 { 109 request: &protocol.RequestHeader{ 110 Version: Version, 111 Command: protocol.RequestCommandTCP, 112 Address: net.LocalHostIP, 113 Port: 1234, 114 User: &protocol.MemoryUser{ 115 Email: "love@example.com", 116 Account: toAccount(&Account{ 117 Password: "tcp-password", 118 CipherType: CipherType_AES_128_GCM, 119 }), 120 }, 121 }, 122 payload: []byte("test string"), 123 }, 124 { 125 request: &protocol.RequestHeader{ 126 Version: Version, 127 Command: protocol.RequestCommandTCP, 128 Address: net.LocalHostIPv6, 129 Port: 1234, 130 User: &protocol.MemoryUser{ 131 Email: "love@example.com", 132 Account: toAccount(&Account{ 133 Password: "password", 134 CipherType: CipherType_AES_256_GCM, 135 }), 136 }, 137 }, 138 payload: []byte("test string"), 139 }, 140 { 141 request: &protocol.RequestHeader{ 142 Version: Version, 143 Command: protocol.RequestCommandTCP, 144 Address: net.DomainAddress("example.com"), 145 Port: 1234, 146 User: &protocol.MemoryUser{ 147 Email: "love@example.com", 148 Account: toAccount(&Account{ 149 Password: "password", 150 CipherType: CipherType_CHACHA20_POLY1305, 151 }), 152 }, 153 }, 154 payload: []byte("test string"), 155 }, 156 } 157 158 runTest := func(request *protocol.RequestHeader, payload []byte) { 159 data := buf.New() 160 common.Must2(data.Write(payload)) 161 162 cache := buf.New() 163 defer cache.Release() 164 165 writer, err := WriteTCPRequest(request, cache) 166 common.Must(err) 167 168 common.Must(writer.WriteMultiBuffer(buf.MultiBuffer{data})) 169 170 validator := new(Validator) 171 validator.Add(request.User) 172 decodedRequest, reader, err := ReadTCPSession(validator, cache) 173 common.Must(err) 174 if equalRequestHeader(decodedRequest, request) == false { 175 t.Error("different request") 176 } 177 178 decodedData, err := reader.ReadMultiBuffer() 179 common.Must(err) 180 if r := cmp.Diff(decodedData[0].Bytes(), payload); r != "" { 181 t.Error("data: ", r) 182 } 183 } 184 185 for _, test := range cases { 186 runTest(test.request, test.payload) 187 } 188 } 189 190 func TestUDPReaderWriter(t *testing.T) { 191 user := &protocol.MemoryUser{ 192 Account: toAccount(&Account{ 193 Password: "test-password", 194 CipherType: CipherType_CHACHA20_POLY1305, 195 }), 196 } 197 cache := buf.New() 198 defer cache.Release() 199 200 writer := &UDPWriter{ 201 Writer: cache, 202 Request: &protocol.RequestHeader{ 203 Version: Version, 204 Address: net.DomainAddress("example.com"), 205 Port: 123, 206 User: user, 207 }, 208 } 209 210 reader := &UDPReader{ 211 Reader: cache, 212 User: user, 213 } 214 215 { 216 b := buf.New() 217 common.Must2(b.WriteString("test payload")) 218 common.Must(writer.WriteMultiBuffer(buf.MultiBuffer{b})) 219 220 payload, err := reader.ReadMultiBuffer() 221 common.Must(err) 222 if payload[0].String() != "test payload" { 223 t.Error("unexpected output: ", payload[0].String()) 224 } 225 } 226 227 { 228 b := buf.New() 229 common.Must2(b.WriteString("test payload 2")) 230 common.Must(writer.WriteMultiBuffer(buf.MultiBuffer{b})) 231 232 payload, err := reader.ReadMultiBuffer() 233 common.Must(err) 234 if payload[0].String() != "test payload 2" { 235 t.Error("unexpected output: ", payload[0].String()) 236 } 237 } 238 }