def _create_local_media(self, uri_path):
        transport = "TCP/TLS/MSRP" if uri_path[-1].use_tls else "TCP/MSRP"
        attributes = []
        path = " ".join(str(uri) for uri in uri_path)

        attributes.append(SDPAttribute(b"path", path.encode()))
        if self.direction not in [None, 'sendrecv']:
            attributes.append(SDPAttribute(self.direction.encode(), b''))
        if self.accept_types is not None:
            a_types = " ".join(self.accept_types)
            attributes.append(SDPAttribute(b"accept-types", a_types.encode()))
        if self.accept_wrapped_types is not None:
            a_w_types = " ".join(self.accept_wrapped_types)
            attributes.append(
                SDPAttribute(b"accept-wrapped-types", a_w_types.encode()))
        attributes.append(
            SDPAttribute(
                b"setup",
                self.local_role.encode() if self.local_role else None))
        local_ip = uri_path[-1].host
        connection = SDPConnection(local_ip.encode())
        return SDPMediaStream(self.media_type.encode(),
                              uri_path[-1].port or 2855,
                              transport.encode(),
                              connection=connection,
                              formats=[b"*"],
                              attributes=attributes)
Exemple #2
0
def content_to_sdpstream(content):
    if content.description is None:
        raise ValueError('Missing media description')
    if content.transport is None:
        raise ValueError('Missing media transport')
    media_stream = SDPMediaStream(str(content.description.media), 0, 'RTP/AVP')
    formats = []
    attributes = []
    for item in content.description.payloads:
        formats.append(item.id)
        attributes.append(SDPAttribute('rtpmap', '%d %s/%d' % (item.id, str(item.name), item.clockrate)))
        if item.maxptime:
            attributes.append(SDPAttribute('maxptime', str(item.maxptime)))
        if item.ptime:
            attributes.append(SDPAttribute('ptime', str(item.ptime)))
        if item.parameters:
            parameters_str = ';'.join(('%s=%s' % (p.name, p.value) for p in item.parameters))
            attributes.append(SDPAttribute('fmtp', '%d %s' % (item.id, str(parameters_str))))
    media_stream.formats = map(str, formats)
    media_stream.attributes = attributes  # set attributes so that _codec_list is generated
    if content.description.encryption:
        if content.description.encryption.required:
            media_stream.transport = 'RTP/SAVP'
        for crypto in content.description.encryption.cryptos:
            crypto_str = '%s %s %s' % (crypto.tag, crypto.crypto_suite, crypto.key_params)
            if crypto.session_params:
                crypto_str += ' %s' % crypto.session_params
            media_stream.attributes.append(SDPAttribute('crypto', str(crypto_str)))
    if isinstance(content.transport, jingle.IceUdpTransport):
        if content.transport.ufrag:
            media_stream.attributes.append(SDPAttribute('ice-ufrag', str(content.transport.ufrag)))
        if content.transport.password:
            media_stream.attributes.append(SDPAttribute('ice-pwd', str(content.transport.password)))
        for candidate in content.transport.candidates:
            if not ipv4_re.match(candidate.ip):
                continue
            candidate_str = '%s %d %s %d %s %d typ %s' % (candidate.foundation, candidate.component, candidate.protocol.upper(), candidate.priority, candidate.ip, candidate.port, candidate.typ)
            if candidate.related_addr and candidate.related_port:
                candidate_str += ' raddr %s rport %d' % (candidate.related_addr, candidate.related_port)
            media_stream.attributes.append(SDPAttribute('candidate', str(candidate_str)))
        if content.transport.remote_candidate:
            remote_candidate = content.transport.remote_candidate
            remote_candidates_str = '%d %s %d' % (remote_candidate.component, remote_candidate.ip, remote_candidate.port)
            media_stream.attributes.append(SDPAttribute('remote-candidates', str(remote_candidates_str)))
    elif isinstance(content.transport, jingle.RawUdpTransport):
        # Nothing to do here
        pass
    else:
        raise ValueError
    # Set the proper connection information, pick the first RTP candidate and use that
    try:
        candidate = next(c for c in content.transport.candidates if c.component == 1 and ipv4_re.match(c.ip))
    except StopIteration:
        raise ValueError
    media_stream.connection = SDPConnection(str(candidate.ip))
    media_stream.port = candidate.port

    return media_stream
Exemple #3
0
def content_to_sdpstream(content):
    if content.description is None or content.transport is None:
        raise ValueError
    media_stream = SDPMediaStream(str(content.description.media), 0, 'RTP/AVP')
    formats = []
    attributes = []
    for item in content.description.payloads:
        formats.append(item.id)
        attributes.append(SDPAttribute('rtpmap', '%d %s/%d' % (item.id, str(item.name), item.clockrate)))
        if item.maxptime:
            attributes.append(SDPAttribute('maxptime', str(item.maxptime)))
        if item.ptime:
            attributes.append(SDPAttribute('ptime', str(item.ptime)))
        if item.parameters:
            parameters_str = ';'.join(('%s=%s' % (p.name, p.value) for p in item.parameters))
            attributes.append(SDPAttribute('fmtp', '%d %s' % (item.id, str(parameters_str))))
    media_stream.formats = map(str, formats)
    media_stream.attributes = attributes  # set attributes so that _codec_list is generated
    if content.description.encryption:
        if content.description.encryption.required:
            media_stream.transport = 'RTP/SAVP'
        for crypto in content.description.encryption.cryptos:
            crypto_str = '%s %s %s' % (crypto.tag, crypto.crypto_suite, crypto.key_params)
            if crypto.session_params:
                crypto_str += ' %s' % crypto.session_params
            media_stream.attributes.append(SDPAttribute('crypto', str(crypto_str)))
    if isinstance(content.transport, jingle.IceUdpTransport):
        if content.transport.ufrag:
            media_stream.attributes.append(SDPAttribute('ice-ufrag', str(content.transport.ufrag)))
        if content.transport.password:
            media_stream.attributes.append(SDPAttribute('ice-pwd', str(content.transport.password)))
        for candidate in content.transport.candidates:
            if not ipv4_re.match(candidate.ip):
                continue
            candidate_str = '%s %d %s %d %s %d typ %s' % (candidate.foundation, candidate.component, candidate.protocol.upper(), candidate.priority, candidate.ip, candidate.port, candidate.typ)
            if candidate.related_addr and candidate.related_port:
                candidate_str += ' raddr %s rport %d' % (candidate.related_addr, candidate.related_port)
            media_stream.attributes.append(SDPAttribute('candidate', str(candidate_str)))
        if content.transport.remote_candidate:
            remote_candidate = content.transport.remote_candidate
            remote_candidates_str = '%d %s %d' % (remote_candidate.component, remote_candidate.ip, remote_candidate.port)
            media_stream.attributes.append(SDPAttribute('remote-candidates', str(remote_candidates_str)))
    elif isinstance(content.transport, jingle.RawUdpTransport):
        # Nothing to do here
        pass
    else:
        raise ValueError
    # Set the proper connection information, pick the first RTP candidate and use that
    try:
        candidate = next(c for c in content.transport.candidates if c.component == 1 and ipv4_re.match(c.ip))
    except StopIteration:
        raise ValueError
    media_stream.connection = SDPConnection(str(candidate.ip))
    media_stream.port = candidate.port

    return media_stream
Exemple #4
0
 def _create_local_media(self, uri_path):
     transport = "TCP/TLS/MSRP" if uri_path[-1].use_tls else "TCP/MSRP"
     attributes = [
         SDPAttribute("path", " ".join(str(uri) for uri in uri_path))
     ]
     if self.direction not in [None, 'sendrecv']:
         attributes.append(SDPAttribute(self.direction, ''))
     if self.accept_types is not None:
         attributes.append(
             SDPAttribute("accept-types", " ".join(self.accept_types)))
     if self.accept_wrapped_types is not None:
         attributes.append(
             SDPAttribute("accept-wrapped-types",
                          " ".join(self.accept_wrapped_types)))
     attributes.append(SDPAttribute("setup", self.local_role))
     local_ip = uri_path[-1].host
     connection = SDPConnection(local_ip)
     return SDPMediaStream(self.media_type,
                           uri_path[-1].port or 2855,
                           transport,
                           connection=connection,
                           formats=["*"],
                           attributes=attributes)
Exemple #5
0
    def _OH_AcceptOperation(self, operation):
        if self.state != 'incoming':
            return

        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()
        streams = operation.streams

        for stream in self.proposed_streams:
            if stream in streams:
                notification_center.add_observer(self, sender=stream)
                stream.initialize(self, direction='incoming')

        try:
            wait_count = len(self.proposed_streams)
            while wait_count > 0:
                notification = operation.channel.wait()
                if notification.name == 'MediaStreamDidInitialize':
                    wait_count -= 1

            remote_sdp = self._sdp_negotiator.current_remote
            local_ip = SIPConfig.local_ip.normalized
            local_sdp = SDPSession(local_ip, connection=SDPConnection(local_ip), name=settings.user_agent)
            stream_map = dict((stream.index, stream) for stream in self.proposed_streams)
            for index, media in enumerate(remote_sdp.media):
                stream = stream_map.get(index, None)
                if stream is not None:
                    media = stream.get_local_media(remote_sdp=remote_sdp, index=index)
                else:
                    media = SDPMediaStream.new(media)
                    media.port = 0
                    media.attributes = []
                local_sdp.media.append(media)
            try:
                self._sdp_negotiator.set_local_answer(local_sdp)
                self._sdp_negotiator.negotiate()
            except SIPCoreError, e:
                self._fail(originator='local', reason='incompatible-parameters', description=str(e))
                return

            self.local_focus = operation.is_focus

            notification_center.post_notification('JingleSessionWillStart', sender=self)

            # Get active SDPs (negotiator may make changes)
            local_sdp = self._sdp_negotiator.active_local
            remote_sdp = self._sdp_negotiator.active_remote

            # Build the payload and send it over
            payload = sdp_to_jingle(local_sdp)
            payload.sid = self._id
            if self.local_focus:
                payload.conference_info = jingle.ConferenceInfo(True)
            stanza = self._protocol.sessionAccept(self._local_jid, self._remote_jid, payload)
            d = self._send_stanza(stanza)
            block_on(d)

            wait_count = 0
            stream_map = dict((stream.index, stream) for stream in self.proposed_streams)
            for index, local_media in enumerate(local_sdp.media):
                remote_media = remote_sdp.media[index]
                stream = stream_map.get(index, None)
                if stream is not None:
                    if remote_media.port:
                        wait_count += 1
                        stream.start(local_sdp, remote_sdp, index)
                    else:
                        notification_center.remove_observer(self, sender=stream)
                        self.proposed_streams.remove(stream)
                        del stream_map[stream.index]
                        stream.deactivate()
                        stream.end()
            removed_streams = [stream for stream in self.proposed_streams if stream.index >= len(local_sdp.media)]
            for stream in removed_streams:
                notification_center.remove_observer(self, sender=stream)
                self.proposed_streams.remove(stream)
                del stream_map[stream.index]
                stream.deactivate()
                stream.end()
            with api.timeout(self.media_stream_timeout):
                while wait_count > 0:
                    notification = operation.channel.wait()
                    if notification.name == 'MediaStreamDidStart':
                        wait_count -= 1
Exemple #6
0
    def _OH_AcceptOperation(self, operation):
        if self.state != 'incoming':
            return

        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()
        streams = operation.streams

        for stream in self.proposed_streams:
            if stream in streams:
                notification_center.add_observer(self, sender=stream)
                stream.initialize(self, direction='incoming')

        try:
            wait_count = len(self.proposed_streams)
            while wait_count > 0:
                notification = operation.channel.wait()
                if notification.name == 'MediaStreamDidInitialize':
                    wait_count -= 1

            remote_sdp = self._sdp_negotiator.current_remote
            local_ip = SIPConfig.local_ip.normalized
            local_sdp = SDPSession(local_ip,
                                   connection=SDPConnection(local_ip),
                                   name=settings.user_agent)
            stream_map = dict(
                (stream.index, stream) for stream in self.proposed_streams)
            for index, media in enumerate(remote_sdp.media):
                stream = stream_map.get(index, None)
                if stream is not None:
                    media = stream.get_local_media(remote_sdp=remote_sdp,
                                                   index=index)
                else:
                    media = SDPMediaStream.new(media)
                    media.port = 0
                    media.attributes = []
                local_sdp.media.append(media)
            try:
                self._sdp_negotiator.set_local_answer(local_sdp)
                self._sdp_negotiator.negotiate()
            except SIPCoreError as e:
                self._fail(originator='local',
                           reason='incompatible-parameters',
                           description=str(e))
                return

            self.local_focus = operation.is_focus

            notification_center.post_notification('JingleSessionWillStart',
                                                  sender=self)

            # Get active SDPs (negotiator may make changes)
            local_sdp = self._sdp_negotiator.active_local
            remote_sdp = self._sdp_negotiator.active_remote

            # Build the payload and send it over
            payload = sdp_to_jingle(local_sdp)
            payload.sid = self._id
            if self.local_focus:
                payload.conference_info = jingle.ConferenceInfo(True)
            stanza = self._protocol.sessionAccept(self._local_jid,
                                                  self._remote_jid, payload)
            d = self._send_stanza(stanza)
            block_on(d)

            wait_count = 0
            stream_map = dict(
                (stream.index, stream) for stream in self.proposed_streams)
            for index, local_media in enumerate(local_sdp.media):
                remote_media = remote_sdp.media[index]
                stream = stream_map.get(index, None)
                if stream is not None:
                    if remote_media.port:
                        wait_count += 1
                        stream.start(local_sdp, remote_sdp, index)
                    else:
                        notification_center.remove_observer(self,
                                                            sender=stream)
                        self.proposed_streams.remove(stream)
                        del stream_map[stream.index]
                        stream.deactivate()
                        stream.end()
            removed_streams = [
                stream for stream in self.proposed_streams
                if stream.index >= len(local_sdp.media)
            ]
            for stream in removed_streams:
                notification_center.remove_observer(self, sender=stream)
                self.proposed_streams.remove(stream)
                del stream_map[stream.index]
                stream.deactivate()
                stream.end()
            with api.timeout(self.media_stream_timeout):
                while wait_count > 0:
                    notification = operation.channel.wait()
                    if notification.name == 'MediaStreamDidStart':
                        wait_count -= 1
        except (MediaStreamDidNotInitializeError, MediaStreamDidFailError,
                api.TimeoutError, IqTimeoutError, StanzaError) as e:
            for stream in self.proposed_streams:
                notification_center.remove_observer(self, sender=stream)
                stream.deactivate()
                stream.end()
            if isinstance(e, api.TimeoutError):
                error = 'media stream timed out while starting'
            elif isinstance(e, IqTimeoutError):
                error = 'timeout sending IQ stanza'
            elif isinstance(e, StanzaError):
                error = str(e.condition)
            else:
                error = 'media stream failed: %s' % e.data.reason
            self._fail(originator='local',
                       reason='failed-application',
                       description=error)
        else:
            self.state = 'connected'
            self.streams = self.proposed_streams
            self.proposed_streams = None
            self.start_time = datetime.now()
            notification_center.post_notification(
                'JingleSessionDidStart', self,
                NotificationData(streams=self.streams))