diff options
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py')
| -rw-r--r-- | packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py | 110 |
1 files changed, 58 insertions, 52 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py b/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py index 8a5bbff..2bd1419 100644 --- a/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py +++ b/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py @@ -25,8 +25,6 @@ Signaling flow (handled externally by the hub): import asyncio import base64 import contextvars -import hashlib -import hmac import logging import os import re @@ -38,63 +36,53 @@ from pathlib import Path from typing import Any import blake3 -import jwt import msgpack -from aiortc import RTCPeerConnection, RTCSessionDescription, RTCDataChannel +from aiortc import RTCDataChannel, RTCPeerConnection, RTCSessionDescription from cryptography.hazmat.primitives.asymmetric.ed25519 import ( Ed25519PrivateKey, Ed25519PublicKey, ) - from meshbay_common import MNP_VERSION -from meshbay_common.handshake import ( - MNP_MIN_SUPPORTED, - NONCE_LEN, - ROLE_CLIENT, - ROLE_NODE, - HandshakeError, - authorize_token, - check_version, - handshake_transcript, - make_proof, - verify_proof, - webrtc_binding, -) from meshbay_common.adminop import ( ADMIN_CHALLENGE_TTL, + OP_APP_DIRECTORIES, + OP_APPS_ENABLED, + OP_CHAT_DIRECTORY, + OP_CHAT_EPOCH, + OP_CHAT_LINK_PREVIEW, OP_DIR_DELETE, OP_FILE_DELETE, + OP_GEK_ROTATE, + OP_GROUP_ATTACH, + OP_GROUP_DETACH, OP_INVITE_CREATE, OP_MEMBER_REVOKE, - OP_GEK_ROTATE, OP_MEMBER_UNPIN, - OP_APPS_ENABLED, + OP_MUSICBRAINZ_ENABLED, + OP_ROOT_ADD, + OP_ROOT_EJECT, + OP_ROOT_PLUG, + OP_ROOT_REMOVE, + OP_ROOT_UPDATE, + OP_SEARCH_LISTED, OP_SET_SCAN_SETTINGS, - OP_TRANSFER_LIMITS, OP_TMDB_CONFIG, OP_TMDB_ENABLED, OP_TMDB_OVERRIDE, OP_TMDB_REMATCH, - OP_MUSICBRAINZ_ENABLED, - OP_APP_DIRECTORIES, - OP_CHAT_DIRECTORY, - OP_CHAT_EPOCH, - OP_CHAT_LINK_PREVIEW, - OP_SEARCH_LISTED, - OP_ROOT_ADD, - OP_ROOT_REMOVE, - OP_ROOT_UPDATE, - OP_ROOT_EJECT, - OP_ROOT_PLUG, - OP_GROUP_ATTACH, - OP_GROUP_DETACH, + OP_TRANSFER_LIMITS, admin_transcript, ) +from meshbay_common.chatbox import ( + NONCE_LEN as CHAT_NONCE_LEN, +) +from meshbay_common.chatbox import ( + SIG_LEN as CHAT_SIG_LEN, +) from meshbay_common.crypto import pk_to_b64, wrap_gek_aes from meshbay_common.device import ( DEVICE_TTL, device_add_transcript, - device_code_hash, device_hello_transcript, device_request_transcript, ) @@ -104,44 +92,62 @@ from meshbay_common.groupbox import ( PURPOSE_ROSTER, seal, ) +from meshbay_common.handshake import ( + MNP_MIN_SUPPORTED, + NONCE_LEN, + ROLE_CLIENT, + ROLE_NODE, + HandshakeError, + authorize_token, + check_version, + handshake_transcript, + make_proof, + verify_proof, + webrtc_binding, +) from meshbay_common.join import ( JOIN_TTL, ROLE_MEMBER, ROLE_OPERATOR, join_transcript, ) -from meshbay_common.chatbox import ( - NONCE_LEN as CHAT_NONCE_LEN, - SIG_LEN as CHAT_SIG_LEN, -) from meshbay_common.protocol import ( MNP, + UPLOAD_PROBE_INDEX, chunk_ciphertext, file_chunk_wire, - UPLOAD_PROBE_INDEX, file_upload_ack_wire, file_upload_payload, ) -from meshbay_node.chat import FORMAT_SEALED_V1, ReplayedMessage -from meshbay_node.transport.wire import index_sync_message -from meshbay_node.indexer import GroupIndex -from meshbay_node.indexer.indexer import DirectoryIndexer + from meshbay_node import hwaccel, linkpreview, ops, platform from meshbay_node import transfers as transfers_mod from meshbay_node import uploads as uploads_mod -from meshbay_node.transfers import TransferSlots +from meshbay_node.chat import FORMAT_SEALED_V1, ReplayedMessage +from meshbay_node.indexer import GroupIndex +from meshbay_node.indexer.indexer import DirectoryIndexer + # Re-imported under its original name: every call site and existing test in # this module still refers to it as `_probe_video`. The implementation lives # in media_probe.py so the indexer package (imported just above) can call it # too, for index-time enrichment, without a circular import. from meshbay_node.media_probe import ( BROWSER_INCOMPATIBLE_VIDEO_CODECS, +) +from meshbay_node.media_probe import ( probe_video as _probe_video, ) from meshbay_node.roots import ( - ROOT_NOT_SERVED, RootSet, entry_abs_path, off_disk, SAFE_UPLOAD_NAME, safe_subdir, + ROOT_NOT_SERVED, + SAFE_UPLOAD_NAME, + RootSet, _free_name, + entry_abs_path, + off_disk, + safe_subdir, ) +from meshbay_node.transfers import TransferSlots +from meshbay_node.transport.wire import index_sync_message log = logging.getLogger(__name__) @@ -6160,7 +6166,7 @@ class WebRTCPeerSession: # total budget is unchanged. await asyncio.wait_for(self._stream_credit_evt.wait(), timeout=STREAM_CREDIT_POLL) - except asyncio.TimeoutError: + except TimeoutError: silent = time.monotonic() - self._stream_heard_at if silent >= STREAM_CREDIT_TIMEOUT: log.info("Stream stalled: nothing from peer=%s for %.0fs", @@ -6208,7 +6214,7 @@ class WebRTCPeerSession: await asyncio.wait_for(asyncio.shield(prev), timeout=15) log.info("stream: previous stream ended in %.1fs", time.monotonic() - t0) - except asyncio.TimeoutError: + except TimeoutError: log.warning("stream: previous stream STILL RUNNING after 15s") except Exception: pass # it failed on its own; the slot is free either way @@ -6851,7 +6857,7 @@ async def _transcode_audio_to_aac(file_path: Path) -> bytes: try: _, stderr = await asyncio.wait_for( proc.communicate(), timeout=AUDIO_TRANSCODE_TIMEOUT_SECS) - except asyncio.TimeoutError: + except TimeoutError: proc.kill() await proc.wait() raise RuntimeError(f"ffmpeg timed out after {AUDIO_TRANSCODE_TIMEOUT_SECS}s") @@ -6912,7 +6918,7 @@ async def _seek_lands_at(file_path: Path, t: float, map_args: list[str]) -> floa ) stdout, _ = await asyncio.wait_for( probe.communicate(), timeout=SEEK_PROBE_TIMEOUT_SECS) - except (asyncio.TimeoutError, OSError) as e: + except (TimeoutError, OSError) as e: log.warning("stream: seek probe failed at %.1fs: %r", t, e) return None finally: @@ -6967,7 +6973,7 @@ async def _extract_subtitle_to_webvtt(file_path: Path, ordinal: int, try: _, stderr = await asyncio.wait_for( proc.communicate(), timeout=timeout) - except asyncio.TimeoutError: + except TimeoutError: proc.kill() await proc.wait() raise RuntimeError(f"ffmpeg timed out after {timeout:.0f}s") @@ -7152,7 +7158,7 @@ class WebRTCTransport: Returns (answer_sdp, ice_candidates) to relay back via hub signaling. ICE candidates are embedded in the SDP (aiortc gathers before returning). """ - from aiortc import RTCIceServer, RTCConfiguration + from aiortc import RTCConfiguration, RTCIceServer # aiortc keeps only the first STUN entry it sees here; the actual # multi-server fan-out is done by transport/stun_multi, which patches |