Developer Referencewebrtc_utils
HMACRTCMonitor
Periodically regenerates HMAC TURN credentials before they expire.
Rebuilds the config every period seconds on the running event loop and
delivers it through the on_rtc_config callback, which the consumer must
assign before start().
Attributes
attributeturn_host= turn_hostattributeturn_port= turn_portattributeturn_username= turn_usernameattributeturn_shared_secret= turn_shared_secretattributeturn_protocol= turn_protocolattributeturn_tls= turn_tlsattributestun_host= stun_hostattributestun_port= stun_portattributeperiod= periodattributeenabled= enabledattributestop_event= asyncio.Event()attributeon_rtc_configCallable[[List[str], List[str], bytes], Any]= lambda stun_servers, turn_servers, rtc_config: logger_rtcice.warning('unhandled on_rtc_config')Functions
func__init__(self, turn_host, turn_port, turn_shared_secret, turn_username, turn_protocol='udp', turn_tls=False, stun_host=None, stun_port=None, period=60, enabled=True)Source Code
def __init__(
self,
turn_host: str,
turn_port: str,
turn_shared_secret: str,
turn_username: str,
turn_protocol: str = 'udp',
turn_tls: bool = False,
stun_host: Optional[str] = None,
stun_port: Optional[str] = None,
period: int = 60,
enabled: bool = True
):
self.turn_host = turn_host
self.turn_port = turn_port
self.turn_username = turn_username
self.turn_shared_secret = turn_shared_secret
self.turn_protocol = turn_protocol
self.turn_tls = turn_tls
self.stun_host = stun_host
self.stun_port = stun_port
self.period = period
self.enabled = enabled
self.stop_event = asyncio.Event()
self._task: Optional[asyncio.Task] = None
self.on_rtc_config: Callable[[List[str], List[str], bytes], Any] = lambda stun_servers, turn_servers, rtc_config: logger_rtcice.warning("unhandled on_rtc_config")paramselfparamturn_hoststrparamturn_portstrparamturn_shared_secretstrparamturn_usernamestrparamturn_protocolstr= 'udp'paramturn_tlsbool= Falseparamstun_hostOptional[str]= Noneparamstun_portOptional[str]= Noneparamperiodint= 60paramenabledbool= TrueReturns
Nonefuncstart(self) -> NoneStarts the periodic refresh task; no-op when disabled.
Source Code
def start(self) -> None:
"""Starts the periodic refresh task; no-op when disabled."""
if not self.enabled:
return
self.stop_event.clear()
self._task = asyncio.create_task(self._monitor_loop())
logger_rtcice.info("HMAC RTC monitor started")paramselfReturns
Nonefunc_monitor_loop(self) -> NoneRegenerates and dispatches credentials until stopped.
The HMAC generation and config parsing run in worker threads so the loop stays responsive; per-iteration failures are logged and retried on the next period rather than killing the monitor.
Source Code
async def _monitor_loop(self) -> None:
"""Regenerates and dispatches credentials until stopped.
The HMAC generation and config parsing run in worker threads so the
loop stays responsive; per-iteration failures are logged and retried
on the next period rather than killing the monitor.
"""
try:
while not self.stop_event.is_set():
try:
hmac_data = await asyncio.to_thread(
generate_rtc_config,
self.turn_host,
self.turn_port,
self.turn_shared_secret,
self.turn_username,
self.turn_protocol,
self.turn_tls,
self.stun_host,
self.stun_port)
stun_servers, turn_servers, rtc_config = await asyncio.to_thread(parse_rtc_config, hmac_data)
await _dispatch_rtc_callback(self.on_rtc_config, stun_servers, turn_servers, rtc_config)
except Exception as e:
logger_rtcice.warning(f"could not fetch TURN HMAC config in periodic monitor: {e}")
try:
await asyncio.wait_for(self.stop_event.wait(), timeout=self.period)
except asyncio.TimeoutError:
pass
except asyncio.CancelledError:
pass
except Exception as e:
logger_rtcice.error(f"Error in HMAC RTC monitor: {e}")
finally:
logger_rtcice.info("HMAC RTC monitor stopped")paramselfReturns
Nonefuncstop(self) -> NoneSignals the loop to exit and waits for the task to finish.
Source Code
async def stop(self) -> None:
"""Signals the loop to exit and waits for the task to finish."""
self.stop_event.set()
if self._task:
await self._taskparamselfReturns
None