A Python port of the Invisible Internet Project (I2P)
at main 87 lines 3.0 kB view raw
1"""I2PTunnel controller group — manages multiple tunnels from config. 2 3Ported from net.i2p.i2ptunnel.TunnelControllerGroup. 4""" 5 6from __future__ import annotations 7 8import logging 9from pathlib import Path 10 11from i2p_apps.i2ptunnel.config import TunnelConfigParser, TunnelDefinition 12from i2p_apps.i2ptunnel.controller import TunnelController, TunnelState 13from i2p_apps.i2ptunnel.sam_session import SessionFactory 14 15logger = logging.getLogger(__name__) 16 17 18class TunnelControllerGroup: 19 """Manages a group of TunnelControllers loaded from config.""" 20 21 def __init__( 22 self, 23 config_path: Path, 24 sam_host: str = "127.0.0.1", 25 sam_port: int = 7656, 26 ) -> None: 27 self._config_path = config_path 28 self._session_factory = SessionFactory(sam_host, sam_port) 29 self._controllers: list[TunnelController] = [] 30 31 @property 32 def controllers(self) -> list[TunnelController]: 33 return list(self._controllers) 34 35 def get_controller(self, name: str) -> TunnelController | None: 36 for c in self._controllers: 37 if c.config.name == name: 38 return c 39 return None 40 41 def list_controllers(self) -> list[TunnelController]: 42 return list(self._controllers) 43 44 async def load_and_start(self) -> None: 45 """Load config, create controllers, start startOnLoad tunnels.""" 46 tunnels = TunnelConfigParser.load(self._config_path) 47 48 # Also load from config.d/ if it exists 49 config_d = self._config_path.parent / (self._config_path.name + ".d") 50 if config_d.exists(): 51 tunnels.extend(TunnelConfigParser.load_dir(config_d)) 52 53 for td in tunnels: 54 controller = TunnelController(td, self._session_factory) 55 self._controllers.append(controller) 56 57 # Start tunnels marked startOnLoad 58 for controller in self._controllers: 59 if controller.config.start_on_load: 60 try: 61 await controller.start() 62 except Exception: 63 logger.exception("Failed to start tunnel %r", 64 controller.config.name) 65 66 async def start_all(self) -> None: 67 """Start all tunnels.""" 68 for controller in self._controllers: 69 if controller.state == TunnelState.STOPPED: 70 try: 71 await controller.start() 72 except Exception: 73 logger.exception("Failed to start tunnel %r", 74 controller.config.name) 75 76 async def stop_all(self) -> None: 77 """Stop all running tunnels.""" 78 for controller in self._controllers: 79 if controller.state == TunnelState.RUNNING: 80 try: 81 await controller.stop() 82 except Exception: 83 logger.exception("Failed to stop tunnel %r", 84 controller.config.name) 85 86 # Release shared sessions 87 await self._session_factory.close_all()