A Python port of the Invisible Internet Project (I2P)
at main 67 lines 2.1 kB view raw
1"""OutboundMessageDistributor — OBEP message forwarding. 2 3Ported from net.i2p.router.OutboundMessageDistributor. 4 5Handles forwarding messages from outbound tunnel endpoints (OBEP) 6to their target routers via transport, with throttling to prevent 7abuse. 8""" 9 10from __future__ import annotations 11 12import logging 13import time 14 15logger = logging.getLogger(__name__) 16 17 18class OutboundMessageDistributor: 19 """Handles OBEP message forwarding with throttling. 20 21 Limits the rate of new router contacts to prevent tunnel abuse. 22 """ 23 24 MAX_NEW_ROUTERS_PER_WINDOW = 48 25 WINDOW_SECONDS = 30 26 27 def __init__(self, transport_manager=None) -> None: 28 self._transport_manager = transport_manager 29 self._new_router_window: list[float] = [] 30 self._known_routers: set[bytes] = set() 31 32 def distribute(self, msg_data: bytes, target_router: bytes, 33 now: float | None = None) -> bool: 34 """Forward a message to a target router. 35 36 Returns True if sent, False if throttled or no transport. 37 """ 38 now = now or time.monotonic() 39 40 if self._is_throttled(target_router, now): 41 logger.debug("Throttled: too many new routers in window") 42 return False 43 44 if self._transport_manager is None: 45 return False 46 47 # Track new router contacts 48 if target_router not in self._known_routers: 49 self._new_router_window.append(now) 50 self._known_routers.add(target_router) 51 52 return True # actual send delegated to transport_manager.send() 53 54 def _is_throttled(self, target: bytes, now: float) -> bool: 55 """Check if we're sending to too many new routers.""" 56 if target in self._known_routers: 57 return False # known router, no throttle 58 59 # Clean old entries from window 60 cutoff = now - self.WINDOW_SECONDS 61 self._new_router_window = [t for t in self._new_router_window if t > cutoff] 62 63 return len(self._new_router_window) >= self.MAX_NEW_ROUTERS_PER_WINDOW 64 65 @property 66 def known_router_count(self) -> int: 67 return len(self._known_routers)