| 
					
				 | 
			
			
				@@ -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 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |