@@ -5,16 +5,13 @@ import (
55 "io"
66 "net"
77 "sync"
8- "sync/atomic"
98 "time"
109
1110 "github.com/linkdata/socks5"
1211)
1312
1413// Server is a SOCKS5 proxy server.
1514type Server struct {
16- Started time.Time // time when Server.Serve() was called
17-
1815 // List of authentication providers. If nil, uses NoAuthAuthenticator.
1916 // Order matters; they are tried in the given order.
2017 Authenticators []Authenticator
@@ -26,9 +23,10 @@ type Server struct {
2623 Logger socks5.Logger // If not nil, use this Logger (compatible with log/slog)
2724 Debug bool // If true, output debug logging using Logger.Info
2825
29- closed atomic.Bool
3026 mu sync.Mutex // protects following
27+ serving int
3128 listeners map [string ]* listener
29+ started time.Time // time when Server.Serve() was called
3230}
3331
3432func listenKey (client net.Conn , address string ) (key string ) {
@@ -47,7 +45,7 @@ func listenKey(client net.Conn, address string) (key string) {
4745
4846func (s * Server ) getListener (ctx context.Context , client net.Conn , bindaddress string ) (nl net.Listener , err error ) {
4947 err = net .ErrClosed
50- if ! s . closed . Load () {
48+ if s . Serving () > 0 {
5149 err = nil
5250 key := listenKey (client , bindaddress )
5351 var lc net.ListenConfig
@@ -113,9 +111,10 @@ func (s *Server) maybeLogError(err error, msg string, keyvaluepairs ...any) {
113111}
114112
115113func (s * Server ) close () {
116- if ! s .closed .Swap (true ) {
117- s .mu .Lock ()
118- defer s .mu .Unlock ()
114+ s .mu .Lock ()
115+ defer s .mu .Unlock ()
116+ s .serving --
117+ if s .serving < 1 {
119118 for _ , l := range s .listeners {
120119 _ = s .Debug && s .LogDebug ("Server.close(): listener stop" , "address" , l .key )
121120 l .refs .Store (0 )
@@ -125,14 +124,26 @@ func (s *Server) close() {
125124 }
126125}
127126
127+ // Serving returns the number of active calls to Serve()
128+ func (s * Server ) Serving () (n int ) {
129+ s .mu .Lock ()
130+ n = s .serving
131+ s .mu .Unlock ()
132+ return
133+ }
134+
128135// Serve accepts and handles incoming connections on the given listener.
129136func (s * Server ) Serve (ctx context.Context , l net.Listener ) (err error ) {
130- defer l .Close ()
131137 defer s .close ()
132- s .Started = time .Now ()
138+ s .mu .Lock ()
139+ s .serving ++
140+ if s .listeners == nil {
141+ s .listeners = make (map [string ]* listener )
142+ s .started = time .Now ()
143+ }
144+ s .mu .Unlock ()
133145 errchan := make (chan error , 1 )
134146 s .LogInfo ("listening" , "addr" , l .Addr ())
135- s .listeners = make (map [string ]* listener )
136147 go s .listenerMaintenance (ctx )
137148 go s .listen (ctx , errchan , l )
138149 select {
@@ -145,7 +156,7 @@ func (s *Server) Serve(ctx context.Context, l net.Listener) (err error) {
145156func (s * Server ) listenerCleanup () {
146157 s .mu .Lock ()
147158 defer s .mu .Unlock ()
148- deadline := int64 (time .Since (s .Started ) - socks5 .ListenerTimeout )
159+ deadline := int64 (time .Since (s .started ) - socks5 .ListenerTimeout )
149160 for k , l := range s .listeners {
150161 if refs := l .refs .Load (); refs < 1 {
151162 if died := l .died .Load (); died < deadline {
0 commit comments