@@ -22,6 +22,7 @@ import (
2222 "net/url"
2323 "os"
2424 "path/filepath"
25+ "slices"
2526 "strconv"
2627 "strings"
2728 "sync"
@@ -280,15 +281,15 @@ func (l *Locale) ServeSocks4(ctx *Context, cli io.ReadWriteCloser) error {
280281 Closer : cli ,
281282 }
282283 var (
283- fCode uint8
284- fDstPort = make ([]byte , 2 )
285- fDstIP = make ([]byte , 4 )
286- fHostName []byte
287284 dstHost string
288285 dstPort uint16
289286 dst string
290- srv io.ReadWriteCloser
291287 err error
288+ fCode uint8
289+ fDstIP = make ([]byte , 4 )
290+ fDstPort = make ([]byte , 2 )
291+ fHostName []byte
292+ srv io.ReadWriteCloser
292293 )
293294 cliReader .Discard (1 )
294295 fCode , err = cliReader .ReadByte ()
@@ -344,15 +345,15 @@ func (l *Locale) ServeSocks5(ctx *Context, cli io.ReadWriteCloser) error {
344345 Closer : cli ,
345346 }
346347 var (
347- fN uint8
348- fCmd uint8
349- fAT uint8
350- fDstAddr []byte
351- fDstPort = make ([]byte , 2 )
352348 dstHost string
353349 dstPort uint16
354350 dst string
355351 err error
352+ fAT uint8
353+ fCmd uint8
354+ fDstAddr []byte
355+ fDstPort = make ([]byte , 2 )
356+ fN uint8
356357 )
357358 cliReader .Discard (1 )
358359 fN = doa .Val (cliReader .ReadByte ())
@@ -411,21 +412,20 @@ func (l *Locale) ServeSocks5TCP(ctx *Context, cli io.ReadWriteCloser, dst string
411412// ServeSocks5UDP serves socks5 UDP protocol.
412413func (l * Locale ) ServeSocks5UDP (ctx * Context , cli io.ReadWriteCloser ) error {
413414 var (
414- bndAddr * net.UDPAddr
415- bndPort uint16
416- bnd * net.UDPConn
417415 appAddr * net.UDPAddr
418- appSize int
419416 appHeadSize int
420417 appHead []byte
418+ appSize int
419+ bndAddr * net.UDPAddr
420+ bndPort uint16
421+ bnd * net.UDPConn
422+ buf = make ([]byte , 2048 )
423+ cpl = map [string ]io.ReadWriteCloser {}
421424 dstHost string
422425 dstPort uint16
423426 dst string
424- srv io.ReadWriteCloser
425- b bool
426- cpl = map [string ]io.ReadWriteCloser {}
427- buf = make ([]byte , 2048 )
428427 err error
428+ srv io.ReadWriteCloser
429429 )
430430 bndAddr = doa .Try (net .ResolveUDPAddr ("udp" , "127.0.0.1:0" ))
431431 bnd = doa .Try (net .ListenUDP ("udp" , bndAddr ))
@@ -478,10 +478,7 @@ func (l *Locale) ServeSocks5UDP(ctx *Context, cli io.ReadWriteCloser) error {
478478 case 0x04 :
479479 appHeadSize = 22
480480 }
481-
482- appHead = make ([]byte , appHeadSize )
483- copy (appHead , buf [0 :appHeadSize ])
484-
481+ appHead = buf [0 :appHeadSize ]
485482 switch appHead [3 ] {
486483 case 0x01 :
487484 dstHost = net .IP (appHead [4 :8 ]).String ()
@@ -495,45 +492,25 @@ func (l *Locale) ServeSocks5UDP(ctx *Context, cli io.ReadWriteCloser) error {
495492 dstPort = binary .BigEndian .Uint16 (appHead [20 :22 ])
496493 }
497494 dst = dstHost + ":" + strconv .Itoa (int (dstPort ))
498-
499- srv , b = cpl [dst ]
500- if b {
501- goto send
502- } else {
503- goto init
504- }
505- init:
506- log .Printf ("conn: %08x proto format=socks5" , ctx .Cid )
507- srv , err = l .Dialer .Dial (ctx , "udp" , dst )
508- if err != nil {
509- log .Printf ("conn: %08x error %s" , ctx .Cid , err )
510- continue
511- }
512- cpl [dst ] = srv
513- go func (srv io.ReadWriteCloser , appHead []byte , appAddr * net.UDPAddr ) error {
514- var (
515- buf = make ([]byte , 2048 )
516- l = len (appHead )
517- n int
518- err error
519- )
520- copy (buf , appHead )
521- for {
522- n , err = srv .Read (buf [l :])
523- if err != nil {
524- break
525- }
526- _ , err = bnd .WriteToUDP (buf [:l + n ], appAddr )
527- if err != nil {
528- break
529- }
495+ srv = cpl [dst ]
496+ if srv == nil {
497+ log .Printf ("conn: %08x proto format=socks5" , ctx .Cid )
498+ srv , err = l .Dialer .Dial (ctx , "udp" , dst )
499+ if err != nil {
500+ log .Printf ("conn: %08x error %s" , ctx .Cid , err )
501+ continue
530502 }
531- return err
532- }(srv , appHead , appAddr )
533- send:
503+ cpl [dst ] = srv
504+ retHead := slices .Clone (appHead )
505+ go ReadCall (srv , func (data []byte ) error {
506+ return doa .Err (bnd .WriteToUDP (append (retHead , data ... ), appAddr ))
507+ })
508+ }
534509 _ , err = srv .Write (buf [appHeadSize :appSize ])
535510 if err != nil {
536511 log .Printf ("conn: %08x error %s" , ctx .Cid , err )
512+ srv .Close ()
513+ delete (cpl , dst )
537514 continue
538515 }
539516 }
@@ -1047,12 +1024,31 @@ type RandomReader struct{}
10471024
10481025// Read implements io.Reader.
10491026func (r * RandomReader ) Read (p []byte ) (int , error ) {
1050- for i := 0 ; i < len (p ); i ++ {
1027+ for i := range len (p ) {
10511028 p [i ] = byte (rand .Uint64 ())
10521029 }
10531030 return len (p ), nil
10541031}
10551032
1033+ // ReadCall reads data from the given io.Reader and passes it to the provided call function.
1034+ func ReadCall (conn io.Reader , call func ([]byte ) error ) error {
1035+ var (
1036+ buf = make ([]byte , 2048 )
1037+ err error
1038+ n int
1039+ )
1040+ for {
1041+ n , err = conn .Read (buf )
1042+ if err != nil {
1043+ break
1044+ }
1045+ if err = call (buf [:n ]); err != nil {
1046+ break
1047+ }
1048+ }
1049+ return err
1050+ }
1051+
10561052// Salt converts the stupid password passed in by the user to 32-sized byte array.
10571053func Salt (s string ) []byte {
10581054 h := sha256 .Sum256 ([]byte (s ))
0 commit comments