Dateien nach „slixmpp/plugins/xep_0167“ hochladen
This commit is contained in:
parent
8abc9e4ab2
commit
ca6a3ce241
11
slixmpp/plugins/xep_0167/__init__.py
Normal file
11
slixmpp/plugins/xep_0167/__init__.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# slixmpp: The Slick XMPP Library
|
||||||
|
# Copyright (C) 2020 Emmanuel Gil Peyrot
|
||||||
|
# This file is part of slixmpp.
|
||||||
|
# See the file LICENSE for copying permission.
|
||||||
|
|
||||||
|
from slixmpp.plugins.base import register_plugin
|
||||||
|
|
||||||
|
from slixmpp.plugins.xep_0167.stanza import Description, PayloadType, RtcpMux, Encryption, Bandwidth, Parameter, Crypto #, RtcpFB --> xep_0293
|
||||||
|
from slixmpp.plugins.xep_0167.rtp import XEP_0167
|
||||||
|
|
||||||
|
register_plugin(XEP_0167)
|
150
slixmpp/plugins/xep_0167/rtp.py
Normal file
150
slixmpp/plugins/xep_0167/rtp.py
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
# slixmpp: The Slick XMPP Library
|
||||||
|
# Copyright (C) 2020 Emmanuel Gil Peyrot
|
||||||
|
# This file is part of slixmpp.
|
||||||
|
# See the file LICENSE for copying permission.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from typing import Iterable, Tuple, Optional
|
||||||
|
|
||||||
|
from slixmpp import JID, Iq
|
||||||
|
from slixmpp.plugins import BasePlugin
|
||||||
|
from slixmpp.xmlstream import register_stanza_plugin
|
||||||
|
from slixmpp.xmlstream.handler import Callback
|
||||||
|
from slixmpp.xmlstream.matcher import StanzaPath
|
||||||
|
from slixmpp.plugins.xep_0166 import Jingle, Content
|
||||||
|
from slixmpp.plugins.xep_0167 import stanza, Description, PayloadType, RtcpMux, Encryption, Bandwidth, Parameter, Crypto#, RtcpFB --> xep_0293
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class XEP_0167(BasePlugin):
|
||||||
|
|
||||||
|
name = 'xep_0167'
|
||||||
|
description = 'XEP-0167: Jingle'
|
||||||
|
dependencies = set(['xep_0166'])
|
||||||
|
stanza = stanza
|
||||||
|
|
||||||
|
def plugin_init(self):
|
||||||
|
register_stanza_plugin(Iq,Jingle)
|
||||||
|
register_stanza_plugin(Jingle,Content,True)
|
||||||
|
register_stanza_plugin(Content,Description)
|
||||||
|
register_stanza_plugin(Description,PayloadType,True)
|
||||||
|
register_stanza_plugin(Description,RtcpMux)
|
||||||
|
register_stanza_plugin(Description,Encryption)
|
||||||
|
register_stanza_plugin(Description,Bandwidth)
|
||||||
|
register_stanza_plugin(Description,RtcpMux)
|
||||||
|
register_stanza_plugin(PayloadType,Parameter,True)
|
||||||
|
# register_stanza_plugin(PayloadType,RtcpFB) --> xep_0293
|
||||||
|
register_stanza_plugin(Encryption,Crypto)
|
||||||
|
|
||||||
|
self.xmpp.register_handler(
|
||||||
|
Callback('Rtp Jingle Description',
|
||||||
|
StanzaPath('iq/jingle/content/description'),
|
||||||
|
self._handle_content_description))
|
||||||
|
|
||||||
|
|
||||||
|
# def session_bind(self, jid):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# def plugin_end(self):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
|
||||||
|
def _handle_content_description(self, message):
|
||||||
|
self.xmpp.event('jingle_content_description', message['jingle']['content']['description'])
|
||||||
|
|
||||||
|
def make_description(self,sdp,media):
|
||||||
|
m = re.search(r'^m='+media+' +(\d+) +([\w/]+)([ \d]*)\r$',sdp,re.M)
|
||||||
|
if m:
|
||||||
|
description = Description()
|
||||||
|
description['media'] = media
|
||||||
|
# if self.xmpp['xep_0294']:
|
||||||
|
# hdrexts = self.xmpp['xep_0294'].make_hdrexts(sdp)
|
||||||
|
# for hdrext in hdrexts:
|
||||||
|
# description.append(hdrext)
|
||||||
|
if m.group(3):
|
||||||
|
for id in m.group(3).split():
|
||||||
|
iter = re.finditer(r'^a=rtpmap:'+id+' +([\w\-.]+)(?:/(\d+)(?:/(\S+))?)?\r$',sdp,re.M)
|
||||||
|
m = re.search(r'^a=ptime:(\S+)\r$',sdp,re.M)
|
||||||
|
ptime = None
|
||||||
|
if m:
|
||||||
|
ptime = m.group(1)
|
||||||
|
m = re.search(r'^a=maxptime:(\S+)\r$',sdp,re.M)
|
||||||
|
maxptime = None
|
||||||
|
if m:
|
||||||
|
maxptime = m.group(1)
|
||||||
|
for m in iter:
|
||||||
|
payload = PayloadType()
|
||||||
|
payload['id'] = id
|
||||||
|
payload['name'] = m.group(1)
|
||||||
|
if m.group(2):
|
||||||
|
payload['clockrate'] = m.group(2)
|
||||||
|
if m.group(3):
|
||||||
|
payload['channels'] = m.group(3)
|
||||||
|
if ptime:
|
||||||
|
payload['ptime'] = ptime
|
||||||
|
if maxptime:
|
||||||
|
payload['maxptime'] = maxptime
|
||||||
|
m1 = re.search(r'^a=fmtp:'+id+' *(.*)\r$',sdp,re.M)
|
||||||
|
if m1:
|
||||||
|
for line in m1.groups():
|
||||||
|
m2 = re.findall(r' *; *([^=;\r]+(?:=[^; \r]+)?)',f';{line}')
|
||||||
|
if m2:
|
||||||
|
for p in m2:
|
||||||
|
if p:
|
||||||
|
parameter = Parameter()
|
||||||
|
s = p.split('=')
|
||||||
|
if len(s)>1:
|
||||||
|
parameter['name'] = s[0]
|
||||||
|
parameter['value'] = s[1]
|
||||||
|
else:
|
||||||
|
parameter['value'] = s[0]
|
||||||
|
payload.append(parameter)
|
||||||
|
if self.xmpp['xep_0293']:
|
||||||
|
ret = self.xmpp['xep_0293'].make_rtcpfb(sdp,id)
|
||||||
|
for rtcpfb in ret:
|
||||||
|
payload.append(rtcpfb)
|
||||||
|
description.append(payload)
|
||||||
|
m = re.search(r'^a=crypto:(\d+) +(\S+) +(\S+) +(\S+)\r$',sdp,re.M)
|
||||||
|
if m:
|
||||||
|
encryption = Encryption()
|
||||||
|
crypto = Crypto()
|
||||||
|
crypto['tag'] = m.group(1)
|
||||||
|
crypto['crypto-suite'] = m.group(2)
|
||||||
|
crypto['key-params'] = m.group(3)
|
||||||
|
crypto['session-params'] = m.group(4)
|
||||||
|
encryption.append(crypto)
|
||||||
|
description.append(encryption)
|
||||||
|
if self.xmpp['xep_0293']:
|
||||||
|
ret = self.xmpp['xep_0293'].make_rtcpfb(sdp)
|
||||||
|
for rtcpfb in ret:
|
||||||
|
payload.append(rtcpfb)
|
||||||
|
if self.xmpp['xep_0294']:
|
||||||
|
hdrexts = self.xmpp['xep_0294'].make_hdrexts(sdp)
|
||||||
|
for hdrext in hdrexts:
|
||||||
|
description.append(hdrext)
|
||||||
|
hdrextallowmixed = self.xmpp['xep_0294'].make_extmapallowmixed(sdp)
|
||||||
|
if hdrextallowmixed!=None:
|
||||||
|
description.append(hdrextallowmixed)
|
||||||
|
if self.xmpp['xep_0339']:
|
||||||
|
ret = self.xmpp['xep_0339'].make_ssrcgroup(sdp)
|
||||||
|
if ret:
|
||||||
|
description.append(ret[0])
|
||||||
|
for source in ret[1]:
|
||||||
|
description.append(source)
|
||||||
|
else:
|
||||||
|
source = self.xmpp['xep_0339'].make_source(sdp)
|
||||||
|
if source:
|
||||||
|
description.append(source)
|
||||||
|
# hier müsste noch geprüft werden, ob \w+ in "a=group:BUNDLE X Y" vorhkommt.
|
||||||
|
m = re.search(r'^a=mid: *\w+\r$',sdp,re.M)
|
||||||
|
if m:
|
||||||
|
rtcpmux = RtcpMux()
|
||||||
|
description.append(rtcpmux)
|
||||||
|
return description
|
||||||
|
return None
|
145
slixmpp/plugins/xep_0167/stanza.py
Normal file
145
slixmpp/plugins/xep_0167/stanza.py
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
# slixmpp: The Slick XMPP Library
|
||||||
|
# Copyright (C) 2020 Emmanuel Gil Peyrot
|
||||||
|
# This file is part of slixmpp.
|
||||||
|
# See the file LICENSE for copying permission.
|
||||||
|
|
||||||
|
from slixmpp.xmlstream import ElementBase
|
||||||
|
|
||||||
|
class Description(ElementBase):
|
||||||
|
name = 'description'
|
||||||
|
namespace = 'urn:xmpp:jingle:apps:rtp:1'
|
||||||
|
plugin_attrib = 'description'
|
||||||
|
interfaces = {'media','ssrc'}
|
||||||
|
|
||||||
|
def getSDP(self,port = None, cline = None):
|
||||||
|
ret = "\r\nm=%s %s " % (self['media'],port or '0')
|
||||||
|
if port==None:
|
||||||
|
ret += "UDP/"
|
||||||
|
if self.parent().get_plugin(name='ice-transport',check=True):
|
||||||
|
if self.parent()['ice-transport'].get_plugin(name='fingerprint',check=True):
|
||||||
|
ret += "TLS/RTP/SAVPF"
|
||||||
|
else:
|
||||||
|
ret += "TLS/RTP/SAVPF"
|
||||||
|
elif self.parent().get_plugin(name='raw-transport',check=True):
|
||||||
|
if self.parent()['raw-transport'].get_plugin(name='fingerprint',check=True):
|
||||||
|
ret += "TLS/RTP/SAVPF"
|
||||||
|
else:
|
||||||
|
ret += "RTP/AVP"
|
||||||
|
for rtcpfb in self['rtcp-fbs']: # Ist das überflüssig?
|
||||||
|
ret += rtcpfb.getSDP() or ''
|
||||||
|
tmp = ''
|
||||||
|
ptime_max = -1
|
||||||
|
maxptime_max = -1
|
||||||
|
if self['maxptime']:
|
||||||
|
maxptime_max = max(maxptime_max,int(self['maxptime']))
|
||||||
|
for payload in self['payload-types']:
|
||||||
|
ret += ' '+payload['id']
|
||||||
|
if payload['ptime']:
|
||||||
|
ptime_max = max(ptime_max,int(payload['ptime']))
|
||||||
|
if payload['maxptime']:
|
||||||
|
maxptime_max = max(maxptime_max,int(payload['maxptime']))
|
||||||
|
tmp += payload.getSDP()
|
||||||
|
if cline:
|
||||||
|
ret += cline
|
||||||
|
ret += tmp
|
||||||
|
if ptime_max>-1:
|
||||||
|
ret += "\r\na=ptime:%s" % (ptime_max)
|
||||||
|
if maxptime_max>-1:
|
||||||
|
ret += "\r\na=maxptime:%s" % (maxptime_max)
|
||||||
|
if self.get_plugin(name='hdrexts',check=True):
|
||||||
|
# ret += "\r\na=sendrecv"
|
||||||
|
for hdrext in self['hdrexts']:
|
||||||
|
ret += hdrext.getSDP() or ''
|
||||||
|
if self.get_plugin(name='extmap-allow-mixed',check=True):
|
||||||
|
ret += "\r\na=extmap-allow-mixed"
|
||||||
|
if self.get_plugin(name='ssrc-group',check=True):
|
||||||
|
ret += self['ssrc-group'].getSDP() or ''
|
||||||
|
for source in self['sources']:
|
||||||
|
ret += source.getSDP()
|
||||||
|
if self.get_plugin(name='encryption',check=True):
|
||||||
|
ret += self['encryption'].getSDP() or ''
|
||||||
|
return ret
|
||||||
|
|
||||||
|
class PayloadType(ElementBase):
|
||||||
|
name = 'payload-type'
|
||||||
|
namespace = 'urn:xmpp:jingle:apps:rtp:1'
|
||||||
|
plugin_attrib = 'payload-type'
|
||||||
|
interfaces = {'channels','clockrate','id','maxptime','name','ptime'}
|
||||||
|
plugin_multi_attrib = 'payload-types'
|
||||||
|
|
||||||
|
def getSDP(self):
|
||||||
|
ret = "\r\na=rtpmap:%s " % self['id']
|
||||||
|
# name optional in jingle if one of the standard payload ids required in sdp
|
||||||
|
# standard payload ids: https://en.m.wikipedia.org/wiki/RTP_payload_formats
|
||||||
|
if self['name']:
|
||||||
|
ret += "%s" % (self['name'])
|
||||||
|
if self['clockrate']:
|
||||||
|
ret += "/%s" % (self['clockrate'])
|
||||||
|
if self['channels']:
|
||||||
|
ret += "/%s" % (self['channels'])
|
||||||
|
# ptime, maxptime are not really usefull
|
||||||
|
if self.get_plugin(name='parameters',check=True):
|
||||||
|
ret += "\r\na=fmtp:%s " % (self['id'])
|
||||||
|
tmp = ''
|
||||||
|
for parameter in self['parameters']:
|
||||||
|
tmp += ';'+parameter.getSDP()
|
||||||
|
ret += tmp[1:]
|
||||||
|
for rtcpfb in self['rtcp-fbs']: # Ist das überflüssig?
|
||||||
|
ret += rtcpfb.getSDP(self['id']) or ''
|
||||||
|
return ret
|
||||||
|
|
||||||
|
class RtcpMux(ElementBase):
|
||||||
|
name = 'rtcp-mux'
|
||||||
|
namespace = 'urn:xmpp:jingle:apps:rtp:1'
|
||||||
|
plugin_attrib = 'rtcp-mux'
|
||||||
|
interfaces = {}
|
||||||
|
|
||||||
|
def getSDP(self):
|
||||||
|
return '\r\na=rtcp-mux'
|
||||||
|
|
||||||
|
class Encryption(ElementBase):
|
||||||
|
name = 'encryption'
|
||||||
|
namespace = 'urn:xmpp:jingle:apps:rtp:1'
|
||||||
|
plugin_attrib = 'encryption'
|
||||||
|
interfaces = {'required'}
|
||||||
|
|
||||||
|
def getSDP(self):
|
||||||
|
if self.get_plugin(name='crypto',check=True):
|
||||||
|
return self['crypto'].getSDP()
|
||||||
|
return None
|
||||||
|
|
||||||
|
class Crypto(ElementBase):
|
||||||
|
name = 'crypto'
|
||||||
|
namespace = 'urn:xmpp:jingle:apps:rtp:1'
|
||||||
|
plugin_attrib = 'crypto'
|
||||||
|
interfaces = {'crypto-suite','key-params','session-params','tag'}
|
||||||
|
|
||||||
|
def getSDP(self):
|
||||||
|
return "\r\na=crypto:%s %s %s %s" % (self['tag'],self['crypto-suite'],self['key-params'],self['session-params'])
|
||||||
|
|
||||||
|
class Bandwidth(ElementBase):
|
||||||
|
name = 'bandwidth'
|
||||||
|
namespace = 'urn:xmpp:jingle:apps:rtp:1'
|
||||||
|
plugin_attrib = 'bandwidth'
|
||||||
|
interfaces = {'type'}
|
||||||
|
|
||||||
|
class Parameter(ElementBase):
|
||||||
|
name = 'parameter'
|
||||||
|
namespace = 'urn:xmpp:jingle:apps:rtp:1'
|
||||||
|
plugin_attrib = 'parameter'
|
||||||
|
interfaces = {'name','value'}
|
||||||
|
plugin_multi_attrib = 'parameters'
|
||||||
|
|
||||||
|
def getSDP(self):
|
||||||
|
if self['name']:
|
||||||
|
return "%s=%s" % (self['name'],self['value'])
|
||||||
|
return "%s" % (self['value'])
|
||||||
|
|
||||||
|
#class RtcpFB(ElementBase): --> xep_0293
|
||||||
|
# name = 'rtcp-fb'
|
||||||
|
# namespace = 'urn:xmpp:jingle:apps:rtp:rtcp-fb:0'
|
||||||
|
# plugin_attrib = 'rtcp-fb'
|
||||||
|
# interfaces = {'subtype','type'}
|
||||||
|
#
|
||||||
|
# def getSDP(self):
|
||||||
|
# return self['type']
|
Loading…
x
Reference in New Issue
Block a user