comparison libervia/backend/plugins/plugin_xep_0176.py @ 4275:29fda1340078

plugin XEP-0176: Send ICE candidates buffer for initiator: - ICE buffer is now sent also for initiator. - If `ice_candidates_new_cb` is set in `session`, it will be used instead of using the `ice_candidates_new` signal. This is useful to handle internally the workflow, and will be used in incoming `Conferences` component. rel 445
author Goffi <goffi@goffi.org>
date Fri, 05 Jul 2024 17:18:32 +0200
parents 0d7bb4df2343
children 4837ec911c43
comparison
equal deleted inserted replaced
4274:2992f9d1e039 4275:29fda1340078
228 content_data = session["contents"][content_name] 228 content_data = session["contents"][content_name]
229 transport_data = content_data["transport_data"] 229 transport_data = content_data["transport_data"]
230 ice_data = transport_data["local_ice_data"] 230 ice_data = transport_data["local_ice_data"]
231 return self.build_transport(ice_data) 231 return self.build_transport(ice_data)
232 232
233 async def _send_ice_buffer(
234 self,
235 client: SatXMPPEntity,
236 session: dict,
237 content_name: str,
238 content_data: dict,
239 ) -> None:
240 """Send ``transport-info`` actions with buffered ICE candidates.
241
242 @param client: Libervia client instance.
243 @param session: Jingle session.
244 @param content_name: Name (ID) of the content.
245 @param content_data: Data of the content.
246 @param media_type: Type of media of the content.
247 """
248 media_type = content_data["application_data"].get("media")
249 # we check if we have any buffered ICE candidates, and send them if it's the case
250 try:
251 buffer = session["XEP-0176_ice_buffer"]
252 buffered_ice_data = buffer.pop(media_type)
253 except KeyError:
254 pass
255 else:
256 if not buffer:
257 del session["XEP-0176_ice_buffer"]
258 transport_elt = self.build_transport(buffered_ice_data)
259 iq_elt, __ = self._j.build_action(
260 client,
261 self._j.A_TRANSPORT_INFO,
262 session,
263 content_name,
264 context_elt=transport_elt,
265 )
266 self.host.trigger.point(
267 "XEP-0176_jingle_handler_send_buffer",
268 client,
269 session,
270 content_name,
271 content_data,
272 transport_elt,
273 iq_elt,
274 )
275 await iq_elt.send()
276
233 async def jingle_handler( 277 async def jingle_handler(
234 self, 278 self,
235 client: SatXMPPEntity, 279 client: SatXMPPEntity,
236 action: str, 280 action: str,
237 session: dict, 281 session: dict,
259 buffer = session.pop("XEP-0176_handler_buffer", None) 303 buffer = session.pop("XEP-0176_handler_buffer", None)
260 if buffer: 304 if buffer:
261 log.debug("replaying buffered events") 305 log.debug("replaying buffered events")
262 for args in buffer: 306 for args in buffer:
263 await self.jingle_handler(*args) 307 await self.jingle_handler(*args)
308 await self._send_ice_buffer(client, session, content_name, content_data)
264 elif action == self._j.A_PREPARE_RESPONDER: 309 elif action == self._j.A_PREPARE_RESPONDER:
265 pass 310 pass
266 311
267 elif action == self._j.A_SESSION_ACCEPT: 312 elif action == self._j.A_SESSION_ACCEPT:
268 # we check if we have any buffered ICE candidates, and send them if it's the 313 await self._send_ice_buffer(client, session, content_name, content_data)
269 # case
270 media_type = content_data["application_data"].get("media")
271 try:
272 buffer = session["XEP-0176_buffer"]
273 buffered_ice_data = buffer.pop(media_type)
274 except KeyError:
275 pass
276 else:
277 if not buffer:
278 del session["XEP-0176_buffer"]
279 transport_elt = self.build_transport(buffered_ice_data)
280 iq_elt, __ = self._j.build_action(
281 client,
282 self._j.A_TRANSPORT_INFO,
283 session,
284 content_name,
285 context_elt=transport_elt,
286 )
287 self.host.trigger.point(
288 "XEP-0176_jingle_handler_send_buffer",
289 client,
290 session,
291 content_name,
292 content_data,
293 transport_elt,
294 iq_elt,
295 )
296 await iq_elt.send()
297 314
298 elif action == self._j.A_START: 315 elif action == self._j.A_START:
299 pass 316 pass
300 317
301 elif action == self._j.A_SESSION_INITIATE: 318 elif action == self._j.A_SESSION_INITIATE:
318 f"Peer ICE restart detected on session {session['id']} " 335 f"Peer ICE restart detected on session {session['id']} "
319 f"[{client.profile}]" 336 f"[{client.profile}]"
320 ) 337 )
321 self.host.bridge.ice_restart(session["id"], "peer", client.profile) 338 self.host.bridge.ice_restart(session["id"], "peer", client.profile)
322 339
323 self.host.bridge.ice_candidates_new( 340 ice_candidates_new_cb = session.get("ice_candidates_new_cb")
324 session["id"], 341 ice_candidates_data = {media_type: new_ice_data}
325 data_format.serialise({media_type: new_ice_data}), 342 if ice_candidates_new_cb is None:
326 client.profile, 343 self.host.bridge.ice_candidates_new(
327 ) 344 session["id"],
345 data_format.serialise(ice_candidates_data),
346 client.profile,
347 )
348 else:
349 ice_candidates_new_cb(client, session, ice_candidates_data)
328 elif action == self._j.A_DESTROY: 350 elif action == self._j.A_DESTROY:
329 pass 351 pass
330 else: 352 else:
331 log.warning("FIXME: unmanaged action {}".format(action)) 353 log.warning("FIXME: unmanaged action {}".format(action))
332 354
369 ice_data["candidates"] = new_ice_data["candidates"] 391 ice_data["candidates"] = new_ice_data["candidates"]
370 return True 392 return True
371 return False 393 return False
372 394
373 async def ice_candidates_add( 395 async def ice_candidates_add(
374 self, client: SatXMPPEntity, session_id: str, media_ice_data: Dict[str, dict] 396 self, client: SatXMPPEntity, session_id: str, media_ice_data: dict[str, dict]
375 ) -> None: 397 ) -> None:
376 """Called when a new ICE candidates are available for a session 398 """Called when a new ICE candidates are available for a session
377 399
378 @param session_id: Session ID 400 @param session_id: Session ID
379 @param media_ice_data: a map from media type (audio, video) to ICE data 401 @param media_ice_data: a map from media type (audio, video) to ICE data
385 content_data: dict | None = None 407 content_data: dict | None = None
386 408
387 for media_type, new_ice_data in media_ice_data.items(): 409 for media_type, new_ice_data in media_ice_data.items():
388 if session["state"] == self._j.STATE_PENDING: 410 if session["state"] == self._j.STATE_PENDING:
389 log.debug(f"session not active, buffering") 411 log.debug(f"session not active, buffering")
390 buffer = session.setdefault("XEP-0176_buffer", {}) 412 buffer = session.setdefault("XEP-0176_ice_buffer", {})
391 media_buffer = buffer.setdefault(media_type, {}) 413 media_buffer = buffer.setdefault(media_type, {})
392 414
393 for key in ["ufrag", "pwd"]: 415 for key in ["ufrag", "pwd"]:
394 if key not in media_buffer: 416 if key not in media_buffer:
395 media_buffer[key] = new_ice_data[key] 417 media_buffer[key] = new_ice_data[key]