Start background thread for client activity monitoring
(self)
| 300 | logging.info(f"First client connected to channel {self.channel_id}") |
| 301 | |
| 302 | def start_cleanup_thread(self): |
| 303 | """Start background thread for client activity monitoring""" |
| 304 | def cleanup_loop(): |
| 305 | # Wait for initial connection window |
| 306 | start_time = time.time() |
| 307 | while self.cleanup_running and (time.time() - start_time) < Config.INITIAL_CONNECTION_WINDOW: |
| 308 | if self.first_client_connected: |
| 309 | break |
| 310 | time.sleep(1) |
| 311 | |
| 312 | if not self.first_client_connected: |
| 313 | logging.info(f"Channel {self.channel_id}: No clients connected within {Config.INITIAL_CONNECTION_WINDOW}s window") |
| 314 | self.proxy_server.stop_channel(self.channel_id) |
| 315 | return |
| 316 | |
| 317 | # Normal client activity monitoring |
| 318 | while self.cleanup_running and self.running: |
| 319 | try: |
| 320 | timeout = self.target_duration * Config.CLIENT_TIMEOUT_FACTOR |
| 321 | if self.client_manager.cleanup_inactive(timeout): |
| 322 | logging.info(f"Channel {self.channel_id}: All clients disconnected for {timeout:.1f}s") |
| 323 | self.proxy_server.stop_channel(self.channel_id) |
| 324 | break |
| 325 | except Exception as e: |
| 326 | logging.error(f"Cleanup error: {e}") |
| 327 | if "cannot join current thread" not in str(e): |
| 328 | time.sleep(Config.CLIENT_CLEANUP_INTERVAL) |
| 329 | time.sleep(Config.CLIENT_CLEANUP_INTERVAL) |
| 330 | |
| 331 | if not self.cleanup_started: |
| 332 | self.cleanup_started = True |
| 333 | self.cleanup_running = True |
| 334 | self.cleanup_thread = threading.Thread( |
| 335 | target=cleanup_loop, |
| 336 | name=f"Cleanup-{self.channel_id}", |
| 337 | daemon=True |
| 338 | ) |
| 339 | self.cleanup_thread.start() |
| 340 | logging.info(f"Started cleanup thread for channel {self.channel_id}") |
| 341 | |
| 342 | class StreamFetcher: |
| 343 | """ |
no test coverage detected