remoteRF-server 1.1.0.dev47__py3-none-any.whl → 1.1.0.dev48__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -50,6 +50,41 @@ from .global_onboarding import RELAYED, hostname, is_offsite
50
50
 
51
51
  logger = logging.getLogger("remoteRF_server.direct")
52
52
 
53
+
54
+ async def close_ice(ice) -> None:
55
+ """Close an aioice Connection without the library's after-close noise.
56
+
57
+ aioice leaves STUN retry timers armed and connectivity-check tasks waiting
58
+ on futures nobody resolves; the timers then fire on closed sockets and the
59
+ tasks die "pending" when the loop stops. Fail those transactions first so
60
+ everything finishes cleanly, then close."""
61
+ from aioice import stun
62
+
63
+ for protocol in list(getattr(ice, "_protocols", [])):
64
+ for transaction in list(getattr(protocol, "transactions", {}).values()):
65
+ handle = getattr(transaction, "_Transaction__timeout_handle", None)
66
+ if handle is not None:
67
+ handle.cancel()
68
+ future = getattr(transaction, "_Transaction__future", None)
69
+ if future is not None and not future.done():
70
+ future.set_exception(stun.TransactionTimeout())
71
+ await ice.close()
72
+ await asyncio.sleep(0) # let the check tasks see their failures and exit
73
+
74
+
75
+ def quiet_aioice_errors(loop) -> None:
76
+ """A STUN retry on an already-closed socket is not an error worth a
77
+ traceback in someone's shell; everything else keeps the default handler."""
78
+ default = loop.default_exception_handler
79
+
80
+ def handler(loop, context):
81
+ exc = context.get("exception")
82
+ if isinstance(exc, (AttributeError, OSError)) and "Transaction" in repr(context.get("handle", "")):
83
+ return
84
+ default(context)
85
+
86
+ loop.set_exception_handler(handler)
87
+
53
88
  ALPN = "remoterf-direct/1"
54
89
  MAX_FRAME = 100 * 1024 * 1024 # the gRPC message ceiling
55
90
  IDLE_SECONDS = 600
@@ -307,7 +342,7 @@ class _Path:
307
342
  task.cancel()
308
343
  with contextlib.suppress(asyncio.CancelledError):
309
344
  await task
310
- await self.ice.close()
345
+ await close_ice(self.ice)
311
346
 
312
347
 
313
348
  async def _offer(key: str, user: str, remote: dict) -> dict:
@@ -327,7 +362,7 @@ async def _offer(key: str, user: str, remote: dict) -> dict:
327
362
  await ice.add_remote_candidate(Candidate.from_sdp(str(sdp)))
328
363
  await ice.add_remote_candidate(None)
329
364
  except Exception:
330
- await ice.close()
365
+ await close_ice(ice)
331
366
  raise
332
367
  path = _paths[key] = _Path(key, user, ice)
333
368
  path.task = asyncio.ensure_future(path.run())
@@ -343,6 +378,7 @@ def _get_loop() -> asyncio.AbstractEventLoop:
343
378
  with _lock:
344
379
  if _loop is None:
345
380
  _loop = asyncio.new_event_loop()
381
+ quiet_aioice_errors(_loop)
346
382
  threading.Thread(
347
383
  target=_loop.run_forever, name="remoterf-direct", daemon=True
348
384
  ).start()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: remoteRF-server
3
- Version: 1.1.0.dev47
3
+ Version: 1.1.0.dev48
4
4
  Summary: RemoteRF server-side control package
5
5
  License: GPL-3.0-or-later
6
6
  Classifier: Programming Language :: Python :: 3
@@ -56,7 +56,7 @@ remoteRF_server/server/commands.py,sha256=ccb_Ab1mbIkosBsFGJnDSccrjWtR_Lymvvn3Iq
56
56
  remoteRF_server/server/console.py,sha256=J91LfwPVmBgielOxfE740NOYduekggyZkqi-47y_A4w,4472
57
57
  remoteRF_server/server/control.py,sha256=Uq1Fk0zIoHHX_EXfz3OuNle8urvO_UhAiB5Lk5cs2e4,5177
58
58
  remoteRF_server/server/device_manager.py,sha256=PPuCwlPSmjfVpCqy_hCaOr9WvFgE8mqtLMhWOAgXNDA,39281
59
- remoteRF_server/server/direct_path.py,sha256=CQs0uPTANJq6Bn-TzsV0APmD3hYKH8xYvczXZZk1OXk,15229
59
+ remoteRF_server/server/direct_path.py,sha256=ry4wRbqMQdSSh-HVFlbbMdTCNM0XksTl-h9MORJ0PLM,16781
60
60
  remoteRF_server/server/dynamic_v2.py,sha256=AMhQEFhNAvCNcF-PdfCCQQLmeoaR7s1Os8et1KFGn_8,70814
61
61
  remoteRF_server/server/global_onboarding.py,sha256=NcKG8TYhCJEiaCtdXL1jEgVm-R_xWpOIj5KI4bWfkr0,39942
62
62
  remoteRF_server/server/grpc_server.py,sha256=91FpJubzN_Wfuk6fW_owIEzNCukd333sAGW68FUU8pk,46787
@@ -90,9 +90,9 @@ remoteRF_server/tools/gen_certs.py,sha256=Vbyu8JjRu__UYPVmyCRXt5SOw0Za1HV7g1md3G
90
90
  remoteRF_server/tools/gist_status.py,sha256=SFv2iQgQrIKT9gxKrU-_Dr7S0p0rE4wQM6J3OC6FcoM,4649
91
91
  remoteRF_server/tools/gist_status_testing.py,sha256=IYw7UkPjAUpKDTtIlnYGb5g6SJkwz4TRGUfJJ6f4LhQ,2690
92
92
  remoteRF_server/tools/introspect_uhd.py,sha256=vUpPb0rM9tsHPxWadS3EfMDE-gMd-TvNV0TjrZOQqBY,4531
93
- remoterf_server-1.1.0.dev47.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
94
- remoterf_server-1.1.0.dev47.dist-info/METADATA,sha256=jRJsAiJF90sOYqLqwlGY7P7wa5bohJWgoEnoN_KMqnI,42069
95
- remoterf_server-1.1.0.dev47.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
96
- remoterf_server-1.1.0.dev47.dist-info/entry_points.txt,sha256=_bbKk65PfYi-n6zUjqOiOwcalf_Ws1TCGATIe1TukxE,136
97
- remoterf_server-1.1.0.dev47.dist-info/top_level.txt,sha256=NuYWe8dSx3qdbxshWBwOgx68EHmJ9I8Zvxam4ARsQ_I,30
98
- remoterf_server-1.1.0.dev47.dist-info/RECORD,,
93
+ remoterf_server-1.1.0.dev48.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
94
+ remoterf_server-1.1.0.dev48.dist-info/METADATA,sha256=ZhdOC9w67CZe59Nn38BVHXVFsnyGESpLxDE5izAzi5s,42069
95
+ remoterf_server-1.1.0.dev48.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
96
+ remoterf_server-1.1.0.dev48.dist-info/entry_points.txt,sha256=_bbKk65PfYi-n6zUjqOiOwcalf_Ws1TCGATIe1TukxE,136
97
+ remoterf_server-1.1.0.dev48.dist-info/top_level.txt,sha256=NuYWe8dSx3qdbxshWBwOgx68EHmJ9I8Zvxam4ARsQ_I,30
98
+ remoterf_server-1.1.0.dev48.dist-info/RECORD,,