from __future__ import annotations from app.core.errors import UnsupportedEngineError from app.core.interface import EngineBackend from app.models import ( CapabilitySet, EngineKind, EngineState, RuntimeRequest, RuntimeSnapshot, RuntimeStats, ) class FreeTurnBackend(EngineBackend): """FreeTurn adapter contract. The actual Android calls (`Mobile.Start`, `StartTunnel`, `SetProtect`, events, CAPTCHA) are owned by the native service. Desktop support is intentionally not claimed until a desktop build of the core is selected. """ name = "freeturn" capabilities = CapabilitySet( supports_vpn=False, supports_proxy=True, supports_socks=False, supports_http=False, supports_udp=True, supports_mobile=True, supports_desktop=False, supports_stats=True, supports_hot_reload=False, supports_both=False, ) def __init__(self) -> None: self._state = RuntimeSnapshot(engine=EngineKind.FREETURN) async def start(self, request: RuntimeRequest) -> RuntimeSnapshot: self._state = RuntimeSnapshot( state=EngineState.UNSUPPORTED, engine=EngineKind.FREETURN, mode=request.mode, profile_id=request.profile_id, message="FreeTurn is available only through the Android native mobile binding", ) raise UnsupportedEngineError( self._state.message or "FreeTurn is unsupported on this platform" ) async def stop(self) -> RuntimeSnapshot: self._state = self._state.model_copy(update={"state": EngineState.STOPPED}) return self._state async def restart(self, request: RuntimeRequest) -> RuntimeSnapshot: await self.stop() return await self.start(request) async def get_state(self) -> RuntimeSnapshot: return self._state async def get_stats(self) -> RuntimeStats: return self._state.stats