bump pymd3
This commit is contained in:
@@ -11,16 +11,17 @@ import random
|
||||
import math
|
||||
import socketio
|
||||
import httpx
|
||||
from contextlib import asynccontextmanager, suppress
|
||||
from contextlib import suppress
|
||||
from typing import Optional, Dict
|
||||
from dotenv import load_dotenv
|
||||
|
||||
with warnings.catch_warnings():
|
||||
# Ignore: "Core Pydantic V1 functionality isn't compatible with Python 3.14 or greater."
|
||||
warnings.simplefilter("ignore", category=UserWarning)
|
||||
warnings.simplefilter("ignore", category=UserWarning)
|
||||
import fastapi
|
||||
import uvicorn
|
||||
from fastapi import FastAPI, APIRouter, Request
|
||||
from fastapi import FastAPI, APIRouter, Request, Response
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import FileResponse
|
||||
@@ -140,16 +141,6 @@ class TunneldRunnerSio:
|
||||
usbmux_monitor: bool = True,
|
||||
mobdev2_monitor: bool = True,
|
||||
) -> None:
|
||||
# instance = cls(
|
||||
# host,
|
||||
# port,
|
||||
# protocol=protocol,
|
||||
# usb_monitor=usb_monitor,
|
||||
# wifi_monitor=wifi_monitor,
|
||||
# usbmux_monitor=usbmux_monitor,
|
||||
# mobdev2_monitor=mobdev2_monitor,
|
||||
# context=context,)
|
||||
# asyncio.run(instance._run_app())
|
||||
cls(
|
||||
host,
|
||||
port,
|
||||
@@ -158,7 +149,8 @@ class TunneldRunnerSio:
|
||||
wifi_monitor=wifi_monitor,
|
||||
usbmux_monitor=usbmux_monitor,
|
||||
mobdev2_monitor=mobdev2_monitor,
|
||||
context=context)._run_app()
|
||||
context=context,
|
||||
)._run_app()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -171,11 +163,12 @@ class TunneldRunnerSio:
|
||||
usbmux_monitor: bool = True,
|
||||
mobdev2_monitor: bool = True,
|
||||
):
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
async def app_startup() -> None:
|
||||
logger.info("Application startup: starting tunneld core and watcher")
|
||||
self._tunneld_core.start()
|
||||
await start_tunnel_watcher()
|
||||
yield
|
||||
|
||||
async def app_shutdown() -> None:
|
||||
logger.info("Closing tunneld tasks...")
|
||||
await end_tunnel_watcher()
|
||||
await end_icloud_monitor()
|
||||
@@ -195,10 +188,14 @@ class TunneldRunnerSio:
|
||||
self._vue_dist = os.getenv("VUE_DIST")
|
||||
self._vue_app = FastAPI(
|
||||
title="iOS Device Management API",
|
||||
lifespan=lifespan,
|
||||
cors_allowed_origins="*",
|
||||
)
|
||||
self._asgi_app = socketio.ASGIApp(self.context.sio, self._vue_app)
|
||||
self._asgi_app = socketio.ASGIApp(
|
||||
self.context.sio,
|
||||
self._vue_app,
|
||||
on_startup=app_startup,
|
||||
on_shutdown=app_shutdown,
|
||||
)
|
||||
self.context.icloud_monitor.sio = self.context.sio
|
||||
self.context.icloud_monitor.get_client_sids = lambda: list(
|
||||
self.context.connected_clients
|
||||
@@ -347,60 +344,84 @@ class TunneldRunnerSio:
|
||||
async def tunnel_watcher_loop() -> None:
|
||||
previous = collect_active_tunnels()
|
||||
while True:
|
||||
await asyncio.sleep(1)
|
||||
current = collect_active_tunnels()
|
||||
added_keys = set(current.keys()) - set(previous.keys())
|
||||
removed_keys = set(previous.keys()) - set(current.keys())
|
||||
added = [current[k] for k in sorted(added_keys)]
|
||||
removed = [previous[k] for k in sorted(removed_keys)]
|
||||
for item in added:
|
||||
logger.info(
|
||||
"Tunnel discovered interface=%s udid=%s address=%s port=%s transport=%s",
|
||||
item.get("interface"),
|
||||
item.get("udid"),
|
||||
item.get("address"),
|
||||
item.get("port"),
|
||||
item.get("transport"),
|
||||
)
|
||||
await safe_sio_emit("tunnel_device_connected", item)
|
||||
logger.info(f"Current udid: %s, new udid: %s",
|
||||
self.context.udid, item.get("udid"))
|
||||
if self.context.udid is None:
|
||||
self.context.udid = item.get("udid")
|
||||
device_name = await get_device_name()
|
||||
if device_name != self.context.device_name:
|
||||
self._tunneld_core.cancel(udid=item.get("udid"))
|
||||
logger.warning(
|
||||
"Tunnel established to wrong device. Dropping tunnel. wrong_udid=%s for device: %s",
|
||||
self.context.udid, self.context.device_name)
|
||||
self.context.udid = None
|
||||
await safe_sio_emit(
|
||||
"appError",
|
||||
{
|
||||
"type": "tunnel_wrong_device",
|
||||
"message": "Tunnel established to wrong device. Dropping tunnel.",
|
||||
"wrong_udid": self.context.udid,
|
||||
"device_name": device_name,
|
||||
},
|
||||
)
|
||||
await get_tun(item.get("udid"), max_retries=10, retry_delay=1.0)
|
||||
try:
|
||||
await asyncio.sleep(1)
|
||||
current = collect_active_tunnels()
|
||||
added_keys = set(current.keys()) - set(previous.keys())
|
||||
removed_keys = set(previous.keys()) - set(current.keys())
|
||||
added = [current[k] for k in sorted(added_keys)]
|
||||
removed = [previous[k] for k in sorted(removed_keys)]
|
||||
for item in added:
|
||||
try:
|
||||
logger.info(
|
||||
"Tunnel discovered interface=%s udid=%s address=%s port=%s transport=%s",
|
||||
item.get("interface"),
|
||||
item.get("udid"),
|
||||
item.get("address"),
|
||||
item.get("port"),
|
||||
item.get("transport"),
|
||||
)
|
||||
await safe_sio_emit("tunnel_device_connected", item)
|
||||
logger.info(f"Current udid: %s, new udid: %s",
|
||||
self.context.udid, item.get("udid"))
|
||||
if self.context.udid is None:
|
||||
self.context.udid = item.get("udid")
|
||||
device_name = await get_device_name()
|
||||
selected_device_name = self.context.device_name
|
||||
if selected_device_name and device_name != selected_device_name:
|
||||
wrong_udid = self.context.udid
|
||||
self._tunneld_core.cancel(udid=item.get("udid"))
|
||||
logger.warning(
|
||||
"Tunnel established to wrong device. Dropping tunnel. wrong_udid=%s for device: %s",
|
||||
wrong_udid, selected_device_name)
|
||||
self.context.udid = None
|
||||
await safe_sio_emit(
|
||||
"appError",
|
||||
{
|
||||
"type": "tunnel_wrong_device",
|
||||
"message": "Tunnel established to wrong device. Dropping tunnel.",
|
||||
"wrong_udid": wrong_udid,
|
||||
"device_name": device_name,
|
||||
},
|
||||
)
|
||||
await get_tun(item.get("udid"), max_retries=10, retry_delay=1.0)
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"Tunnel watcher failed while handling added tunnel for udid=%s",
|
||||
item.get("udid"),
|
||||
)
|
||||
|
||||
if removed:
|
||||
for item in removed:
|
||||
logger.warning(
|
||||
"Tunnel disconnected interface=%s udid=%s address=%s port=%s",
|
||||
item.get("interface"),
|
||||
item.get("udid"),
|
||||
item.get("address"),
|
||||
item.get("port"),
|
||||
)
|
||||
await safe_sio_emit("tunnel_device_disconnected", item)
|
||||
await handle_tunnel_drop(removed)
|
||||
if removed:
|
||||
for item in removed:
|
||||
try:
|
||||
logger.warning(
|
||||
"Tunnel disconnected interface=%s udid=%s address=%s port=%s",
|
||||
item.get("interface"),
|
||||
item.get("udid"),
|
||||
item.get("address"),
|
||||
item.get("port"),
|
||||
)
|
||||
await safe_sio_emit("tunnel_device_disconnected", item)
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"Tunnel watcher failed while emitting disconnection for udid=%s",
|
||||
item.get("udid"),
|
||||
)
|
||||
await handle_tunnel_drop(removed)
|
||||
|
||||
previous = current
|
||||
previous = current
|
||||
except asyncio.CancelledError:
|
||||
raise
|
||||
except Exception:
|
||||
logger.exception("Tunnel watcher loop crashed; continuing")
|
||||
|
||||
async def start_tunnel_watcher() -> None:
|
||||
if self.context.tunnel_watcher_task is None or self.context.tunnel_watcher_task.done():
|
||||
if self.context.tunnel_watcher_task is not None and self.context.tunnel_watcher_task.done():
|
||||
with suppress(Exception):
|
||||
exc = self.context.tunnel_watcher_task.exception()
|
||||
if exc is not None:
|
||||
logger.error("Previous tunnel watcher task exited with error: %s", exc)
|
||||
self.context.tunnel_watcher_task = asyncio.create_task(
|
||||
tunnel_watcher_loop(),
|
||||
name="tunnel-task-watcher",
|
||||
@@ -1303,17 +1324,49 @@ class TunneldRunnerSio:
|
||||
logger.info("Reverse Geocoded %s to %s", coords, rev_geocode)
|
||||
return generate_http_response(rev_geocode)
|
||||
|
||||
@self._app.post("/proxy/ors/{full_path:path}")
|
||||
@self._app.get("/ors/status")
|
||||
async def app_ors_status(request: Request) -> fastapi.Response:
|
||||
logger.info("request: %s", request)
|
||||
target_url = "https://ors.intrepidnet.org/ors/v2/status"
|
||||
async with httpx.AsyncClient() as client:
|
||||
# Forward the request to the external service
|
||||
response = await client.get(target_url, params=request.query_params)
|
||||
# Return the response content and status code back to the original client
|
||||
return Response(
|
||||
content=response.content,
|
||||
status_code=response.status_code,
|
||||
headers=dict(response.headers)
|
||||
)
|
||||
|
||||
@self._app.get("/ors/health")
|
||||
async def app_ors_status(request: Request) -> fastapi.Response:
|
||||
logger.info("request: %s", request)
|
||||
target_url = "https://ors.intrepidnet.org/ors/v2/health"
|
||||
async with httpx.AsyncClient() as client:
|
||||
# Forward the request to the external service
|
||||
response = await client.get(target_url, params=request.query_params)
|
||||
# Return the response content and status code back to the original client
|
||||
return Response(
|
||||
content=response.content,
|
||||
status_code=response.status_code,
|
||||
headers=dict(response.headers)
|
||||
)
|
||||
|
||||
@self._app.post("/ors/proxy/{full_path:path}")
|
||||
async def app_proxy_ors(full_path: str, request: Request):
|
||||
logger.info("request: %s", request)
|
||||
body = await request.body()
|
||||
body = await request.json()
|
||||
headers = dict(request.headers)
|
||||
method = request.method
|
||||
url = "https://ors.intrepidnet.org/" + full_path
|
||||
logger.info("body: %s", body)
|
||||
logger.info("headers: %s", headers)
|
||||
logger.info("method: %s", method)
|
||||
logger.info("url: %s", url)
|
||||
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.request(method, url, headers=headers, content=body)
|
||||
return response.content
|
||||
response = await client.request(method, url, json=body)
|
||||
return response.json()
|
||||
|
||||
""" Socket.IO Functions"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user