@@ -3,6 +3,7 @@ package mux
33import (
44 "context"
55 "io"
6+ "time"
67
78 "github.com/xtls/xray-core/app/dispatcher"
89 "github.com/xtls/xray-core/common"
@@ -12,6 +13,7 @@ import (
1213 "github.com/xtls/xray-core/common/net"
1314 "github.com/xtls/xray-core/common/protocol"
1415 "github.com/xtls/xray-core/common/session"
16+ "github.com/xtls/xray-core/common/signal/done"
1517 "github.com/xtls/xray-core/core"
1618 "github.com/xtls/xray-core/features/routing"
1719 "github.com/xtls/xray-core/transport"
@@ -63,8 +65,15 @@ func (s *Server) DispatchLink(ctx context.Context, dest net.Destination, link *t
6365 return s .dispatcher .DispatchLink (ctx , dest , link )
6466 }
6567 link = s .dispatcher .(* dispatcher.DefaultDispatcher ).WrapLink (ctx , link )
66- _ , err := NewServerWorker (ctx , s .dispatcher , link )
67- return err
68+ worker , err := NewServerWorker (ctx , s .dispatcher , link )
69+ if err != nil {
70+ return err
71+ }
72+ select {
73+ case <- ctx .Done ():
74+ case <- worker .done .Wait ():
75+ }
76+ return nil
6877}
6978
7079// Start implements common.Runnable.
@@ -81,22 +90,23 @@ type ServerWorker struct {
8190 dispatcher routing.Dispatcher
8291 link * transport.Link
8392 sessionManager * SessionManager
93+ done * done.Instance
94+ timer * time.Ticker
8495}
8596
8697func NewServerWorker (ctx context.Context , d routing.Dispatcher , link * transport.Link ) (* ServerWorker , error ) {
8798 worker := & ServerWorker {
8899 dispatcher : d ,
89100 link : link ,
90101 sessionManager : NewSessionManager (),
102+ done : done .New (),
103+ timer : time .NewTicker (60 * time .Second ),
91104 }
92105 if inbound := session .InboundFromContext (ctx ); inbound != nil {
93106 inbound .CanSpliceCopy = 3
94107 }
95- if _ , ok := link .Reader .(* pipe.Reader ); ok {
96- go worker .run (ctx )
97- } else {
98- worker .run (ctx )
99- }
108+ go worker .run (ctx )
109+ go worker .monitor ()
100110 return worker , nil
101111}
102112
@@ -111,12 +121,40 @@ func handle(ctx context.Context, s *Session, output buf.Writer) {
111121 s .Close (false )
112122}
113123
124+ func (w * ServerWorker ) monitor () {
125+ defer w .timer .Stop ()
126+
127+ for {
128+ checkSize := w .sessionManager .Size ()
129+ checkCount := w .sessionManager .Count ()
130+ select {
131+ case <- w .done .Wait ():
132+ w .sessionManager .Close ()
133+ common .Interrupt (w .link .Writer )
134+ common .Interrupt (w .link .Reader )
135+ return
136+ case <- w .timer .C :
137+ if w .sessionManager .CloseIfNoSessionAndIdle (checkSize , checkCount ) {
138+ common .Must (w .done .Close ())
139+ }
140+ }
141+ }
142+ }
143+
114144func (w * ServerWorker ) ActiveConnections () uint32 {
115145 return uint32 (w .sessionManager .Size ())
116146}
117147
118148func (w * ServerWorker ) Closed () bool {
119- return w .sessionManager .Closed ()
149+ return w .done .Done ()
150+ }
151+
152+ func (w * ServerWorker ) WaitClosed () <- chan struct {} {
153+ return w .done .Wait ()
154+ }
155+
156+ func (w * ServerWorker ) Close () error {
157+ return w .done .Close ()
120158}
121159
122160func (w * ServerWorker ) handleStatusKeepAlive (meta * FrameMetadata , reader * buf.BufferedReader ) error {
@@ -317,11 +355,11 @@ func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedRead
317355}
318356
319357func (w * ServerWorker ) run (ctx context.Context ) {
320- reader := & buf.BufferedReader {Reader : w .link .Reader }
358+ defer func () {
359+ common .Must (w .done .Close ())
360+ }()
321361
322- defer w .sessionManager .Close ()
323- defer common .Interrupt (w .link .Reader )
324- defer common .Interrupt (w .link .Writer )
362+ reader := & buf.BufferedReader {Reader : w .link .Reader }
325363
326364 for {
327365 select {
0 commit comments