mirror of
https://github.com/Such-Software/adaptive-multi-protocol-browser.git
synced 2026-10-26 01:38:32 +01:00
Add transport adapters and candidates
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
import shutil
|
||||
import socket
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TransportStatus:
|
||||
transport: str
|
||||
installed: bool
|
||||
running: bool
|
||||
endpoint: str
|
||||
adoptable: bool
|
||||
manage_supported: bool
|
||||
note: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TransportAdapter:
|
||||
name: str
|
||||
profile: str
|
||||
endpoint: str
|
||||
adopt_check: str
|
||||
managed_state: str
|
||||
install_strategy: str
|
||||
start_strategy: str
|
||||
stop_policy: str
|
||||
note: str
|
||||
commands: tuple[str, ...] = ()
|
||||
connect_host: str = ""
|
||||
connect_port: int = 0
|
||||
builtin_running: bool = False
|
||||
manage_supported: bool = True
|
||||
|
||||
def inspect(self) -> TransportStatus:
|
||||
installed = self.builtin_running or any(shutil.which(command) for command in self.commands)
|
||||
running = self.builtin_running or (
|
||||
bool(self.connect_host) and bool(self.connect_port) and _can_connect(self.connect_host, self.connect_port)
|
||||
)
|
||||
return TransportStatus(
|
||||
transport=self.name,
|
||||
installed=installed,
|
||||
running=running,
|
||||
endpoint=self.endpoint,
|
||||
adoptable=running,
|
||||
manage_supported=self.manage_supported,
|
||||
note=self.note,
|
||||
)
|
||||
|
||||
def setup_steps(self, *, installed: bool, platform: str) -> tuple[str, ...]:
|
||||
steps: list[str] = []
|
||||
if not installed and self.install_strategy != "unsupported":
|
||||
steps.append(self.install_strategy)
|
||||
if platform == "android":
|
||||
steps.append(f"start visible Android foreground service for {self.name}")
|
||||
steps.append(f"start managed Android {self.name} transport")
|
||||
steps.append(f"wait for {self.endpoint}")
|
||||
return tuple(steps)
|
||||
elif platform == "ios":
|
||||
steps.append(f"start foreground-only iOS session for {self.name}")
|
||||
steps.append(f"start foreground-only iOS {self.name} transport")
|
||||
steps.append(f"wait for {self.endpoint}")
|
||||
return tuple(steps)
|
||||
if self.start_strategy != "unsupported":
|
||||
steps.append(self.start_strategy)
|
||||
steps.append(f"wait for {self.endpoint}")
|
||||
return tuple(steps)
|
||||
|
||||
|
||||
ADAPTERS: dict[str, TransportAdapter] = {
|
||||
"tor": TransportAdapter(
|
||||
name="tor",
|
||||
profile="tor",
|
||||
endpoint="socks5://127.0.0.1:9050",
|
||||
adopt_check="SOCKS on 127.0.0.1:9050",
|
||||
managed_state=".ampb/transports/tor",
|
||||
install_strategy="install Tor provider",
|
||||
start_strategy="start managed Tor daemon",
|
||||
stop_policy="stop only AMPB-owned Tor daemon",
|
||||
note="Tor SOCKS proxy",
|
||||
commands=("tor",),
|
||||
connect_host="127.0.0.1",
|
||||
connect_port=9050,
|
||||
),
|
||||
"i2p": TransportAdapter(
|
||||
name="i2p",
|
||||
profile="i2p",
|
||||
endpoint="http://127.0.0.1:4444",
|
||||
adopt_check="HTTP proxy on 127.0.0.1:4444",
|
||||
managed_state=".ampb/transports/i2p",
|
||||
install_strategy="install I2P provider",
|
||||
start_strategy="start managed I2P router",
|
||||
stop_policy="stop only AMPB-owned I2P router",
|
||||
note="I2P HTTP proxy",
|
||||
commands=("i2pd", "i2prouter"),
|
||||
connect_host="127.0.0.1",
|
||||
connect_port=4444,
|
||||
),
|
||||
"reticulum": TransportAdapter(
|
||||
name="reticulum",
|
||||
profile="reticulum",
|
||||
endpoint="rns://local",
|
||||
adopt_check="RNS tools and configured interfaces",
|
||||
managed_state=".ampb/transports/reticulum",
|
||||
install_strategy="install Reticulum provider",
|
||||
start_strategy="start configured Reticulum interface",
|
||||
stop_policy="stop only AMPB-owned Reticulum process",
|
||||
note="Reticulum adapter is planned; interface readiness needs explicit config",
|
||||
commands=("rnsd", "rnstatus", "rnodeconf"),
|
||||
manage_supported=False,
|
||||
),
|
||||
"gemini": TransportAdapter(
|
||||
name="gemini",
|
||||
profile="gemini",
|
||||
endpoint="builtin://gemtext-renderer",
|
||||
adopt_check="built-in renderer available",
|
||||
managed_state=".ampb/transports/gemini",
|
||||
install_strategy="unsupported",
|
||||
start_strategy="use built-in Gemtext fetch/render path",
|
||||
stop_policy="no daemon to stop",
|
||||
note="Built-in Gemtext fetch/render path",
|
||||
builtin_running=True,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def adapter_for(name: str) -> TransportAdapter | None:
|
||||
return ADAPTERS.get(name)
|
||||
|
||||
|
||||
def _can_connect(host: str, port: int) -> bool:
|
||||
try:
|
||||
with socket.create_connection((host, port), timeout=0.2):
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
Reference in New Issue
Block a user