|
|
@@ -94,13 +94,18 @@ func (m *ClientManager) onClientFinish() {
|
|
|
m.access.Lock()
|
|
|
defer m.access.Unlock()
|
|
|
|
|
|
- nActive := 0
|
|
|
- for idx, client := range m.clients {
|
|
|
- if nActive != idx && !client.Closed() {
|
|
|
- m.clients[nActive] = client
|
|
|
+ if len(m.clients) < 10 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ activeClients := make([]*Client, 0, len(m.clients))
|
|
|
+
|
|
|
+ for _, client := range m.clients {
|
|
|
+ if !client.Closed() {
|
|
|
+ activeClients = append(activeClients, client)
|
|
|
}
|
|
|
}
|
|
|
- m.clients = m.clients[:nActive]
|
|
|
+ m.clients = activeClients
|
|
|
}
|
|
|
|
|
|
type Client struct {
|
|
|
@@ -209,12 +214,40 @@ func (m *Client) Dispatch(ctx context.Context, outboundRay ray.OutboundRay) bool
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
+func drain(reader *Reader) error {
|
|
|
+ for {
|
|
|
+ data, more, err := reader.Read()
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ data.Release()
|
|
|
+ if !more {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func pipe(reader *Reader, writer buf.Writer) error {
|
|
|
+ for {
|
|
|
+ data, more, err := reader.Read()
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if err := writer.Write(data); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if !more {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func (m *Client) fetchOutput() {
|
|
|
reader := NewReader(m.inboundRay.InboundOutput())
|
|
|
for {
|
|
|
meta, err := reader.ReadMetadata()
|
|
|
if err != nil {
|
|
|
- log.Warning("Proxyman|Mux|Client: Failed to read metadata: ", err)
|
|
|
+ log.Info("Proxyman|Mux|Client: Failed to read metadata: ", err)
|
|
|
break
|
|
|
}
|
|
|
m.access.RLock()
|
|
|
@@ -228,19 +261,15 @@ func (m *Client) fetchOutput() {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
- for {
|
|
|
- data, more, err := reader.Read()
|
|
|
- if err != nil {
|
|
|
- break
|
|
|
- }
|
|
|
- if found {
|
|
|
- if err := s.output.Write(data); err != nil {
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- if !more {
|
|
|
- break
|
|
|
- }
|
|
|
+ if found {
|
|
|
+ err = pipe(reader, s.output)
|
|
|
+ } else {
|
|
|
+ err = drain(reader)
|
|
|
+ }
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ log.Info("Proxyman|Mux|Client: Failed to read data: ", err)
|
|
|
+ break
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -295,22 +324,9 @@ func handle(ctx context.Context, s *session, output buf.Writer) {
|
|
|
writer := NewResponseWriter(s.id, output)
|
|
|
defer writer.Close()
|
|
|
|
|
|
- for {
|
|
|
- select {
|
|
|
- case <-ctx.Done():
|
|
|
- log.Debug("Proxyman|Mux|ServerWorker: Session ", s.id, " ends by context.")
|
|
|
- return
|
|
|
- default:
|
|
|
- data, err := s.input.Read()
|
|
|
- if err != nil {
|
|
|
- log.Info("Proxyman|Mux|ServerWorker: Session ", s.id, " ends: ", err)
|
|
|
- return
|
|
|
- }
|
|
|
- if err := writer.Write(data); err != nil {
|
|
|
- log.Info("Proxyman|Mux|ServerWorker: Session ", s.id, " ends: ", err)
|
|
|
- return
|
|
|
- }
|
|
|
- }
|
|
|
+ _, timer := signal.CancelAfterInactivity(ctx, time.Minute*30)
|
|
|
+ if err := buf.PipeUntilEOF(timer, s.input, writer); err != nil {
|
|
|
+ log.Info("Proxyman|Mux|ServerWorker: Session ", s.id, " ends: ", err)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -357,20 +373,19 @@ func (w *ServerWorker) run(ctx context.Context) {
|
|
|
go handle(ctx, s, w.outboundRay.OutboundOutput())
|
|
|
}
|
|
|
|
|
|
- if meta.Option.Has(OptionData) {
|
|
|
- for {
|
|
|
- data, more, err := reader.Read()
|
|
|
- if err != nil {
|
|
|
- break
|
|
|
- }
|
|
|
- if s != nil {
|
|
|
- if err := s.output.Write(data); err != nil {
|
|
|
- }
|
|
|
- }
|
|
|
- if !more {
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
+ if !meta.Option.Has(OptionData) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ if s != nil {
|
|
|
+ err = pipe(reader, s.output)
|
|
|
+ } else {
|
|
|
+ err = drain(reader)
|
|
|
+ }
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ log.Info("Proxyman|Mux|ServerWorker: Failed to read data: ", err)
|
|
|
+ break
|
|
|
}
|
|
|
}
|
|
|
}
|