A Python port of the Invisible Internet Project (I2P)
at main 85 lines 2.4 kB view raw
1"""Session registry -- maps nicknames to active sessions. 2 3Ported from net.i2p.sam.SAMBridge session management. 4""" 5 6from __future__ import annotations 7 8import asyncio 9from dataclasses import dataclass, field 10from typing import TYPE_CHECKING 11 12if TYPE_CHECKING: 13 from i2p_sam.handler import SAMHandler 14 15 16@dataclass 17class SessionRecord: 18 """Record for a registered SAM session.""" 19 20 nickname: str 21 style: str # STREAM, DATAGRAM, RAW, PRIMARY 22 destination: bytes # serialized Destination (raw bytes) 23 destination_b64: str 24 handler: "SAMHandler" 25 subsessions: dict[str, "SessionRecord"] = field(default_factory=dict) 26 27 28class SessionsDB: 29 """Singleton registry of active SAM sessions by nickname. 30 31 Thread-safe via asyncio.Lock. 32 """ 33 34 def __init__(self) -> None: 35 self._sessions: dict[str, SessionRecord] = {} 36 self._lock = asyncio.Lock() 37 38 async def add(self, record: SessionRecord) -> bool: 39 """Add session. Returns False if nickname already exists. 40 41 Args: 42 record: The session record to register. 43 44 Returns: 45 True if added, False if nickname is already taken. 46 """ 47 async with self._lock: 48 if record.nickname in self._sessions: 49 return False 50 self._sessions[record.nickname] = record 51 return True 52 53 async def remove(self, nickname: str) -> SessionRecord | None: 54 """Remove and return session. 55 56 Args: 57 nickname: The session nickname to remove. 58 59 Returns: 60 The removed SessionRecord, or None if not found. 61 """ 62 async with self._lock: 63 return self._sessions.pop(nickname, None) 64 65 async def get(self, nickname: str) -> SessionRecord | None: 66 """Look up session by nickname. 67 68 Args: 69 nickname: The session nickname to look up. 70 71 Returns: 72 The SessionRecord, or None if not found. 73 """ 74 async with self._lock: 75 return self._sessions.get(nickname) 76 77 async def has(self, nickname: str) -> bool: 78 """Check if a session with the given nickname exists.""" 79 async with self._lock: 80 return nickname in self._sessions 81 82 @property 83 def count(self) -> int: 84 """Number of registered sessions.""" 85 return len(self._sessions)