@@ -97,6 +97,11 @@ func startUDPEchoServer(t testing.TB) (*net.UDPConn, *sync.WaitGroup) {
9797 return conn , & running
9898}
9999
100+ func makeLimiter (cipherList service.CipherList ) service.TrafficLimiter {
101+ c := service .MakeTestTrafficLimiterConfig (cipherList )
102+ return service .NewTrafficLimiter (& c )
103+ }
104+
100105func TestTCPEcho (t * testing.T ) {
101106 echoListener , echoRunning := startTCPEchoServer (t )
102107
@@ -111,7 +116,7 @@ func TestTCPEcho(t *testing.T) {
111116 }
112117 replayCache := service .NewReplayCache (5 )
113118 const testTimeout = 200 * time .Millisecond
114- proxy := service .NewTCPService (cipherList , & replayCache , & metrics.NoOpMetrics {}, testTimeout )
119+ proxy := service .NewTCPService (cipherList , & replayCache , & metrics.NoOpMetrics {}, testTimeout , makeLimiter ( cipherList ) )
115120 proxy .SetTargetIPValidator (allowAll )
116121 go proxy .Serve (proxyListener )
117122
@@ -164,6 +169,192 @@ func TestTCPEcho(t *testing.T) {
164169 echoRunning .Wait ()
165170}
166171
172+ func TestTrafficLimiterTCP (t * testing.T ) {
173+ echoListener , echoRunning := startTCPEchoServer (t )
174+
175+ proxyListener , err := net .ListenTCP ("tcp" , & net.TCPAddr {IP : net .ParseIP ("127.0.0.1" ), Port : 0 })
176+ if err != nil {
177+ t .Fatalf ("ListenTCP failed: %v" , err )
178+ }
179+ secrets := ss .MakeTestSecrets (1 )
180+ cipherList , err := service .MakeTestCiphers (secrets )
181+ if err != nil {
182+ t .Fatal (err )
183+ }
184+ replayCache := service .NewReplayCache (5 )
185+ const testTimeout = 5 * time .Second
186+
187+ key := cipherList .SnapshotForClientIP (net.IP {})[0 ].Value .(* service.CipherEntry ).ID
188+ trafficLimiter := service .NewTrafficLimiter (& service.TrafficLimiterConfig {
189+ KeyToRateLimit : map [string ]int {
190+ key : 1000 ,
191+ },
192+ })
193+
194+ proxy := service .NewTCPService (cipherList , & replayCache , & metrics.NoOpMetrics {}, testTimeout , trafficLimiter )
195+ proxy .SetTargetIPValidator (allowAll )
196+ go proxy .Serve (proxyListener )
197+
198+ proxyHost , proxyPort , err := net .SplitHostPort (proxyListener .Addr ().String ())
199+ if err != nil {
200+ t .Fatal (err )
201+ }
202+ portNum , err := strconv .Atoi (proxyPort )
203+ if err != nil {
204+ t .Fatal (err )
205+ }
206+ client , err := client .NewClient (proxyHost , portNum , secrets [0 ], ss .TestCipher )
207+ if err != nil {
208+ t .Fatalf ("Failed to create ShadowsocksClient: %v" , err )
209+ }
210+
211+ doWriteRead := func (N int , repeats int ) time.Duration {
212+ up := ss .MakeTestPayload (N )
213+ conn , err := client .DialTCP (nil , echoListener .Addr ().String ())
214+ defer conn .Close ()
215+ if err != nil {
216+ t .Fatalf ("ShadowsocksClient.DialTCP failed: %v" , err )
217+ }
218+ start := time .Now ()
219+ down := make ([]byte , N )
220+
221+ for i := 0 ; i < repeats ; i ++ {
222+ n , err := conn .Write (up )
223+ if err != nil {
224+ t .Fatal (err )
225+ }
226+ if n != N {
227+ t .Fatalf ("Tried to upload %d bytes, but only sent %d" , N , n )
228+ }
229+
230+ n , err = io .ReadFull (conn , down )
231+ if err != nil && err != io .EOF {
232+ t .Fatal (err )
233+ }
234+ if n != N {
235+ t .Fatalf ("Expected to download %d bytes, but only received %d" , N , n )
236+ }
237+
238+ if ! bytes .Equal (up , down ) {
239+ t .Fatal ("Echo mismatch" )
240+ }
241+ }
242+
243+ return time .Now ().Sub (start )
244+ }
245+
246+ period1 := doWriteRead (200 , 4 )
247+ if period1 < 500 * time .Millisecond {
248+ t .Fatalf ("Write-read loop is too fast" )
249+ }
250+
251+ time .Sleep (1 * time .Second )
252+
253+ period2 := doWriteRead (200 , 2 )
254+ if period2 > 100 * time .Millisecond {
255+ t .Fatalf ("Write-read loop is too slow" )
256+ }
257+
258+ period3 := doWriteRead (500 , 2 )
259+ if period3 < 500 * time .Millisecond {
260+ t .Fatalf ("Write-read loop is too fast" )
261+ }
262+
263+ proxy .Stop ()
264+ echoListener .Close ()
265+ echoRunning .Wait ()
266+ }
267+
268+ func TestTrafficLimiterUDP (t * testing.T ) {
269+ echoConn , echoRunning := startUDPEchoServer (t )
270+
271+ proxyConn , err := net .ListenUDP ("udp" , & net.UDPAddr {IP : net .ParseIP ("127.0.0.1" ), Port : 0 })
272+ if err != nil {
273+ t .Fatalf ("ListenTCP failed: %v" , err )
274+ }
275+ secrets := ss .MakeTestSecrets (1 )
276+ cipherList , err := service .MakeTestCiphers (secrets )
277+ if err != nil {
278+ t .Fatal (err )
279+ }
280+ testMetrics := & fakeUDPMetrics {fakeLocation : "QQ" }
281+
282+ key := cipherList .SnapshotForClientIP (net.IP {})[0 ].Value .(* service.CipherEntry ).ID
283+ trafficLimiter := service .NewTrafficLimiter (& service.TrafficLimiterConfig {
284+ KeyToRateLimit : map [string ]int {
285+ key : 1000 ,
286+ },
287+ })
288+
289+ proxy := service .NewUDPService (time .Hour , cipherList , testMetrics , trafficLimiter )
290+ proxy .SetTargetIPValidator (allowAll )
291+ go proxy .Serve (proxyConn )
292+
293+ proxyHost , proxyPort , err := net .SplitHostPort (proxyConn .LocalAddr ().String ())
294+ if err != nil {
295+ t .Fatal (err )
296+ }
297+ portNum , err := strconv .Atoi (proxyPort )
298+ if err != nil {
299+ t .Fatal (err )
300+ }
301+ client , err := client .NewClient (proxyHost , portNum , secrets [0 ], ss .TestCipher )
302+ if err != nil {
303+ t .Fatalf ("Failed to create ShadowsocksClient: %v" , err )
304+ }
305+ conn , err := client .ListenUDP (nil )
306+ if err != nil {
307+ t .Fatalf ("ShadowsocksClient.ListenUDP failed: %v" , err )
308+ }
309+
310+ run := func (N int , expectReadError bool ) {
311+ up := ss .MakeTestPayload (N )
312+ n , err := conn .WriteTo (up , echoConn .LocalAddr ())
313+ if err != nil {
314+ t .Fatal (err )
315+ }
316+ if n != N {
317+ t .Fatalf ("Tried to upload %d bytes, but only sent %d" , N , n )
318+ }
319+
320+ conn .SetReadDeadline (time .Now ().Add (50 * time .Millisecond ))
321+
322+ down := make ([]byte , N )
323+ n , addr , err := conn .ReadFrom (down )
324+ if err != nil {
325+ if ! expectReadError {
326+ t .Fatalf ("Unexpected read error: %v" , err )
327+ }
328+ return
329+ } else {
330+ if expectReadError {
331+ t .Fatalf ("Expected read error" )
332+ }
333+ }
334+ if n != N {
335+ t .Fatalf ("Tried to download %d bytes, but only sent %d" , N , n )
336+ }
337+ if addr .String () != echoConn .LocalAddr ().String () {
338+ t .Errorf ("Reported address mismatch: %s != %s" , addr .String (), echoConn .LocalAddr ().String ())
339+ }
340+
341+ if ! bytes .Equal (up , down ) {
342+ t .Fatal ("Echo mismatch" )
343+ }
344+ }
345+
346+ for i := 0 ; i < 3 ; i ++ {
347+ run (300 , false )
348+ run (300 , true )
349+ time .Sleep (time .Second )
350+ }
351+
352+ conn .Close ()
353+ echoConn .Close ()
354+ echoRunning .Wait ()
355+ proxy .GracefulStop ()
356+ }
357+
167358type statusMetrics struct {
168359 metrics.NoOpMetrics
169360 sync.Mutex
@@ -184,7 +375,7 @@ func TestRestrictedAddresses(t *testing.T) {
184375 require .NoError (t , err )
185376 const testTimeout = 200 * time .Millisecond
186377 testMetrics := & statusMetrics {}
187- proxy := service .NewTCPService (cipherList , nil , testMetrics , testTimeout )
378+ proxy := service .NewTCPService (cipherList , nil , testMetrics , testTimeout , makeLimiter ( cipherList ) )
188379 go proxy .Serve (proxyListener )
189380
190381 proxyHost , proxyPort , err := net .SplitHostPort (proxyListener .Addr ().String ())
@@ -266,7 +457,7 @@ func TestUDPEcho(t *testing.T) {
266457 t .Fatal (err )
267458 }
268459 testMetrics := & fakeUDPMetrics {fakeLocation : "QQ" }
269- proxy := service .NewUDPService (time .Hour , cipherList , testMetrics )
460+ proxy := service .NewUDPService (time .Hour , cipherList , testMetrics , makeLimiter ( cipherList ) )
270461 proxy .SetTargetIPValidator (allowAll )
271462 go proxy .Serve (proxyConn )
272463
@@ -363,7 +554,7 @@ func BenchmarkTCPThroughput(b *testing.B) {
363554 b .Fatal (err )
364555 }
365556 const testTimeout = 200 * time .Millisecond
366- proxy := service .NewTCPService (cipherList , nil , & metrics.NoOpMetrics {}, testTimeout )
557+ proxy := service .NewTCPService (cipherList , nil , & metrics.NoOpMetrics {}, testTimeout , makeLimiter ( cipherList ) )
367558 proxy .SetTargetIPValidator (allowAll )
368559 go proxy .Serve (proxyListener )
369560
@@ -430,7 +621,7 @@ func BenchmarkTCPMultiplexing(b *testing.B) {
430621 }
431622 replayCache := service .NewReplayCache (service .MaxCapacity )
432623 const testTimeout = 200 * time .Millisecond
433- proxy := service .NewTCPService (cipherList , & replayCache , & metrics.NoOpMetrics {}, testTimeout )
624+ proxy := service .NewTCPService (cipherList , & replayCache , & metrics.NoOpMetrics {}, testTimeout , makeLimiter ( cipherList ) )
434625 proxy .SetTargetIPValidator (allowAll )
435626 go proxy .Serve (proxyListener )
436627
@@ -505,7 +696,7 @@ func BenchmarkUDPEcho(b *testing.B) {
505696 if err != nil {
506697 b .Fatal (err )
507698 }
508- proxy := service .NewUDPService (time .Hour , cipherList , & metrics.NoOpMetrics {})
699+ proxy := service .NewUDPService (time .Hour , cipherList , & metrics.NoOpMetrics {}, makeLimiter ( cipherList ) )
509700 proxy .SetTargetIPValidator (allowAll )
510701 go proxy .Serve (proxyConn )
511702
@@ -554,7 +745,7 @@ func BenchmarkUDPManyKeys(b *testing.B) {
554745 if err != nil {
555746 b .Fatal (err )
556747 }
557- proxy := service .NewUDPService (time .Hour , cipherList , & metrics.NoOpMetrics {})
748+ proxy := service .NewUDPService (time .Hour , cipherList , & metrics.NoOpMetrics {}, makeLimiter ( cipherList ) )
558749 proxy .SetTargetIPValidator (allowAll )
559750 go proxy .Serve (proxyConn )
560751
0 commit comments