comparison libervia/backend/plugins/plugin_xep_0167/mapping.py @ 4240:79c8a70e1813

backend, frontend: prepare remote control: This is a series of changes necessary to prepare the implementation of remote control feature: - XEP-0166: add a `priority` attribute to `ApplicationData`: this is needed when several applications are working in a same session, to know which one must be handled first. Will be used to make Remote Control have precedence over Call content. - XEP-0166: `_call_plugins` is now async and is not used with `DeferredList` anymore: the benefit to have methods called in parallels is very low, and it cause a lot of trouble as we can't predict order. Methods are now called sequentially so workflow can be predicted. - XEP-0167: fix `senders` XMPP attribute <=> SDP mapping - XEP-0234: preflight acceptance key is now `pre-accepted` instead of `file-accepted`, so the same key can be used with other jingle applications. - XEP-0167, XEP-0343: move some method to XEP-0167 - XEP-0353: use new `priority` feature to call preflight methods of applications according to it. - frontend (webrtc): refactor the sources/sink handling with a more flexible mechanism based on Pydantic models. It is now possible to have has many Data Channel as necessary, to have them in addition to A/V streams, to specify manually GStreamer sources and sinks, etc. - frontend (webrtc): rework of the pipeline to reduce latency. - frontend: new `portal_desktop` method. Screenshare portal handling has been moved there, and RemoteDesktop portal has been added. - frontend (webrtc): fix `extract_ufrag_pwd` method. rel 436
author Goffi <goffi@goffi.org>
date Sat, 11 May 2024 13:52:41 +0200
parents e11b13418ba6
children 0d7bb4df2343
comparison
equal deleted inserted replaced
4239:a38559e6d6e2 4240:79c8a70e1813
35 """Returns appropriate SDP attribute corresponding to Jingle senders attribute""" 35 """Returns appropriate SDP attribute corresponding to Jingle senders attribute"""
36 if senders == "both": 36 if senders == "both":
37 return "a=sendrecv" 37 return "a=sendrecv"
38 elif senders == "none": 38 elif senders == "none":
39 return "a=inactive" 39 return "a=inactive"
40 elif session["role"] == senders: 40 elif session["role"] != senders:
41 return "a=sendonly" 41 return "a=sendonly"
42 else: 42 else:
43 return "a=recvonly" 43 return "a=recvonly"
44 44
45 45
111 session, 111 session,
112 local, 112 local,
113 sdp_lines, 113 sdp_lines,
114 triggers_no_cancel=True 114 triggers_no_cancel=True
115 ) 115 )
116 116 content_names = sorted(contents)
117 for content_name, content_data in contents.items(): 117
118 for content_name, content_data in [(n, contents[n]) for n in content_names]: # contents.items():
118 app_data_key = "local_data" if local else "peer_data" 119 app_data_key = "local_data" if local else "peer_data"
119 application_data = content_data["application_data"] 120 application_data = content_data["application_data"]
120 media_data = application_data[app_data_key] 121 media_data = application_data[app_data_key]
121 media = application_data["media"] 122 media = application_data["media"]
122 payload_types = media_data.get("payload_types", {}) 123 payload_types = media_data.get("payload_types", {})
239 240
240 # Combine SDP lines and return the result 241 # Combine SDP lines and return the result
241 return "\r\n".join(sdp_lines) + "\r\n" 242 return "\r\n".join(sdp_lines) + "\r\n"
242 243
243 244
244 def parse_sdp(sdp: str) -> dict: 245 def parse_sdp(sdp: str, role: str) -> dict:
245 """Parse SDP string. 246 """Parse SDP string.
246 247
247 @param sdp: The SDP string to parse. 248 @param sdp: The SDP string to parse.
248 249 @param role: Role of the entities which produces the SDP.
249 @return: A dictionary containing parsed session data. 250 @return: A dictionary containing parsed session data.
250 """ 251 """
251 # FIXME: to be removed once host is accessible from global var 252 # FIXME: to be removed once host is accessible from global var
252 assert host is not None 253 assert host is not None
253 lines = sdp.strip().split("\r\n") 254 lines = sdp.strip().split("\r\n")
261 transport_data: Optional[Dict[str, Any]] = None 262 transport_data: Optional[Dict[str, Any]] = None
262 fingerprint_data: Optional[Dict[str, str]] = None 263 fingerprint_data: Optional[Dict[str, str]] = None
263 ice_pwd: Optional[str] = None 264 ice_pwd: Optional[str] = None
264 ice_ufrag: Optional[str] = None 265 ice_ufrag: Optional[str] = None
265 payload_types: Optional[Dict[int, dict]] = None 266 payload_types: Optional[Dict[int, dict]] = None
267 # default value, will be be modified by SDP
268 senders: str = "both"
266 269
267 for line in lines: 270 for line in lines:
268 try: 271 try:
269 parts = line.split() 272 parts = line.split()
270 prefix = parts[0][:2] # Extract the 'a=', 'm=', etc., prefix 273 prefix = parts[0][:2] # Extract the 'a=', 'm=', etc., prefix
293 if ice_ufrag is not None: 296 if ice_ufrag is not None:
294 transport_data["ufrag"] = ice_ufrag 297 transport_data["ufrag"] = ice_ufrag
295 media_data = call_data[media_type] = { 298 media_data = call_data[media_type] = {
296 "application_data": application_data, 299 "application_data": application_data,
297 "transport_data": transport_data, 300 "transport_data": transport_data,
301 "senders": senders
298 } 302 }
299 303
300 elif prefix == "a=": 304 elif prefix == "a=":
301 if ":" in parts[0]: 305 if ":" in parts[0]:
302 attribute, parts[0] = parts[0].split(":", 1) 306 attribute, parts[0] = parts[0].split(":", 1)
424 428
425 elif attribute == "ice-pwd": 429 elif attribute == "ice-pwd":
426 if transport_data is not None: 430 if transport_data is not None:
427 transport_data["pwd"] = parts[0] 431 transport_data["pwd"] = parts[0]
428 432
433 elif attribute in ("sendrecv", "sendonly", "recvonly", "inactive"):
434 if attribute == "sendrecv":
435 value = "both"
436 elif attribute == "sendonly":
437 value = role
438 elif attribute == "recvonly":
439 value = "responder" if role == "initiator" else "initiator"
440 else:
441 value = "none"
442
443 if application_data is None:
444 # this is a global value, we use is as new default value
445 senders = value
446 else:
447 # this is a media specific value, it will replace the one used as
448 # default for this media
449 application_data["senders"] = value
450
429 host.trigger.point( 451 host.trigger.point(
430 "XEP-0167_parse_sdp_a", 452 "XEP-0167_parse_sdp_a",
431 attribute, 453 attribute,
432 parts, 454 parts,
433 call_data, 455 call_data,