@@ -16,46 +16,6 @@ import (
16
16
ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
17
17
)
18
18
19
- // Due to in/out byte length is inconsistent of the shadowsocks.Conn.Write,
20
- // we wrap around it to make io.Copy happy.
21
- type shadowConn struct {
22
- conn net.Conn
23
- }
24
-
25
- func (c * shadowConn ) Read (b []byte ) (n int , err error ) {
26
- return c .conn .Read (b )
27
- }
28
-
29
- func (c * shadowConn ) Write (b []byte ) (n int , err error ) {
30
- n = len (b ) // force byte length consistent
31
- _ , err = c .conn .Write (b )
32
- return
33
- }
34
-
35
- func (c * shadowConn ) Close () error {
36
- return c .conn .Close ()
37
- }
38
-
39
- func (c * shadowConn ) LocalAddr () net.Addr {
40
- return c .conn .LocalAddr ()
41
- }
42
-
43
- func (c * shadowConn ) RemoteAddr () net.Addr {
44
- return c .conn .RemoteAddr ()
45
- }
46
-
47
- func (c * shadowConn ) SetDeadline (t time.Time ) error {
48
- return c .conn .SetDeadline (t )
49
- }
50
-
51
- func (c * shadowConn ) SetReadDeadline (t time.Time ) error {
52
- return c .conn .SetReadDeadline (t )
53
- }
54
-
55
- func (c * shadowConn ) SetWriteDeadline (t time.Time ) error {
56
- return c .conn .SetWriteDeadline (t )
57
- }
58
-
59
19
type shadowConnector struct {
60
20
Cipher * url.Userinfo
61
21
}
@@ -102,7 +62,7 @@ func (c *shadowConnector) Connect(conn net.Conn, addr string, options ...Connect
102
62
if _ , err := sc .Write (rawaddr ); err != nil {
103
63
return nil , err
104
64
}
105
- return & shadowConn {conn : sc }, nil
65
+ return & shadowConn {sc }, nil
106
66
}
107
67
108
68
type shadowHandler struct {
@@ -142,7 +102,7 @@ func (h *shadowHandler) Handle(conn net.Conn) {
142
102
conn .RemoteAddr (), conn .LocalAddr (), err )
143
103
return
144
104
}
145
- conn = & shadowConn {conn : ss .NewConn (conn , cipher )}
105
+ conn = & shadowConn {ss .NewConn (conn , cipher )}
146
106
147
107
conn .SetReadDeadline (time .Now ().Add (ReadTimeout ))
148
108
host , err := h .getRequest (conn )
@@ -284,6 +244,55 @@ func (h *shadowHandler) getRequest(r io.Reader) (host string, err error) {
284
244
return
285
245
}
286
246
247
+ type shadowUDPConnector struct {
248
+ Cipher * url.Userinfo
249
+ }
250
+
251
+ // ShadowUDPConnector creates a Connector for shadowsocks UDP client.
252
+ // It accepts a cipher info for shadowsocks data encryption/decryption.
253
+ // The cipher must not be nil.
254
+ func ShadowUDPConnector (cipher * url.Userinfo ) Connector {
255
+ return & shadowUDPConnector {Cipher : cipher }
256
+ }
257
+
258
+ func (c * shadowUDPConnector ) Connect (conn net.Conn , addr string , options ... ConnectOption ) (net.Conn , error ) {
259
+ opts := & ConnectOptions {}
260
+ for _ , option := range options {
261
+ option (opts )
262
+ }
263
+
264
+ timeout := opts .Timeout
265
+ if timeout <= 0 {
266
+ timeout = ConnectTimeout
267
+ }
268
+
269
+ conn .SetDeadline (time .Now ().Add (timeout ))
270
+ defer conn .SetDeadline (time.Time {})
271
+
272
+ rawaddr , err := ss .RawAddr (addr )
273
+ if err != nil {
274
+ return nil , err
275
+ }
276
+
277
+ var method , password string
278
+ if c .Cipher != nil {
279
+ method = c .Cipher .Username ()
280
+ password , _ = c .Cipher .Password ()
281
+ }
282
+
283
+ cipher , err := ss .NewCipher (method , password )
284
+ if err != nil {
285
+ return nil , err
286
+ }
287
+
288
+ sc := ss .NewSecurePacketConn (& shadowPacketConn {conn }, cipher , false )
289
+ return & shadowUDPConn {
290
+ PacketConn : sc ,
291
+ raddr : conn .RemoteAddr (),
292
+ header : rawaddr ,
293
+ }, nil
294
+ }
295
+
287
296
type shadowUDPListener struct {
288
297
ln net.PacketConn
289
298
conns map [string ]* udpServerConn
@@ -434,7 +443,9 @@ func (h *shadowUDPdHandler) transportUDP(sc net.Conn, cc net.PacketConn) error {
434
443
errc := make (chan error , 1 )
435
444
go func () {
436
445
for {
437
- b := make ([]byte , mediumBufferSize )
446
+ b := mPool .Get ().([]byte )
447
+ defer mPool .Put (b )
448
+
438
449
n , err := sc .Read (b [3 :]) // add rsv and frag fields to make it the standard SOCKS5 UDP datagram
439
450
if err != nil {
440
451
// log.Logf("[ssu] %s - %s : %s", sc.RemoteAddr(), sc.LocalAddr(), err)
@@ -468,7 +479,9 @@ func (h *shadowUDPdHandler) transportUDP(sc net.Conn, cc net.PacketConn) error {
468
479
469
480
go func () {
470
481
for {
471
- b := make ([]byte , mediumBufferSize )
482
+ b := mPool .Get ().([]byte )
483
+ defer mPool .Put (b )
484
+
472
485
n , addr , err := cc .ReadFrom (b )
473
486
if err != nil {
474
487
errc <- err
@@ -501,3 +514,65 @@ func (h *shadowUDPdHandler) transportUDP(sc net.Conn, cc net.PacketConn) error {
501
514
}
502
515
return err
503
516
}
517
+
518
+ // Due to in/out byte length is inconsistent of the shadowsocks.Conn.Write,
519
+ // we wrap around it to make io.Copy happy.
520
+ type shadowConn struct {
521
+ net.Conn
522
+ }
523
+
524
+ func (c * shadowConn ) Write (b []byte ) (n int , err error ) {
525
+ n = len (b ) // force byte length consistent
526
+ _ , err = c .Conn .Write (b )
527
+ return
528
+ }
529
+
530
+ type shadowUDPConn struct {
531
+ net.PacketConn
532
+ raddr net.Addr
533
+ header []byte
534
+ }
535
+
536
+ func (c * shadowUDPConn ) Write (b []byte ) (n int , err error ) {
537
+ n = len (b ) // force byte length consistent
538
+ if len (c .header ) > 0 {
539
+ b = append (c .header , b ... )
540
+ }
541
+ _ , err = c .PacketConn .WriteTo (b , c .raddr )
542
+ return
543
+ }
544
+
545
+ func (c * shadowUDPConn ) Read (b []byte ) (n int , err error ) {
546
+ buf := mPool .Get ().([]byte )
547
+ defer mPool .Put (buf )
548
+
549
+ n , _ , err = c .PacketConn .ReadFrom (buf [3 :])
550
+ if err != nil {
551
+ return
552
+ }
553
+
554
+ dgram , err := gosocks5 .ReadUDPDatagram (bytes .NewReader (buf [:n + 3 ]))
555
+ if err != nil {
556
+ return
557
+ }
558
+ n = copy (b , dgram .Data )
559
+ return
560
+ }
561
+
562
+ func (c * shadowUDPConn ) RemoteAddr () net.Addr {
563
+ return c .raddr
564
+ }
565
+
566
+ type shadowPacketConn struct {
567
+ net.Conn
568
+ }
569
+
570
+ func (c * shadowPacketConn ) ReadFrom (b []byte ) (n int , addr net.Addr , err error ) {
571
+ n , err = c .Conn .Read (b )
572
+ addr = c .Conn .RemoteAddr ()
573
+ return
574
+ }
575
+
576
+ func (c * shadowPacketConn ) WriteTo (b []byte , addr net.Addr ) (n int , err error ) {
577
+ return c .Conn .Write (b )
578
+ }
0 commit comments