vpn/app/core/freeturn.py
2026-09-23 01:19:36 +00:00

64 lines
1.9 KiB
Python

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