Exemplo n.º 1
0
 def add_sip_subscription(self, subscription):
     # If s subscription is received after the handle has ended but before
     # S2XPresenceHandlerDidEnd has been processed we need to ignore it and wait for a retransmission
     # which we will handle by creating a new S2XPresenceHandler
     if self.ended:
         return
     self._sip_subscriptions.append(subscription)
     NotificationCenter().add_observer(self, sender=subscription)
     if self._xmpp_subscription.state == 'active':
         pidf_doc = self._pidf
         content_type = pidf.PIDFDocument.content_type if pidf_doc is not None else None
         try:
             subscription.accept(content_type, pidf_doc)
         except SIPCoreError as e:
             log.warning('Error accepting SIP subscription: %s' % e)
             subscription.end()
     else:
         try:
             subscription.accept_pending()
         except SIPCoreError as e:
             log.warning('Error accepting SIP subscription: %s' % e)
             subscription.end()
     if XMPPGatewayConfig.log_presence:
         log.info(
             'SIP subscription from %s to %s added to presence flow 0x%x (%d subs)'
             % (format_uri(self.sip_identity.uri, 'sip'),
                format_uri(self.xmpp_identity.uri,
                           'xmpp'), id(self), len(self._sip_subscriptions)))
Exemplo n.º 2
0
 def _NH_SIPSessionDidStart(self, notification):
     log.info("SIP session %s started" % self.sip_session.call_id)
     if self.sip_session.direction == 'outgoing':
         # Time to accept the Jingle session and bridge them together
         try:
             audio_stream = next(stream
                                 for stream in self.sip_session.streams
                                 if stream.type == 'audio')
         except StopIteration:
             pass
         else:
             self._audio_bidge.add(audio_stream)
         self.jingle_session.accept(self.jingle_session.proposed_streams,
                                    is_focus=self.sip_session.remote_focus)
     else:
         # Both sessions have been accepted now
         self.started = True
         try:
             audio_stream = next(stream
                                 for stream in self.sip_session.streams
                                 if stream.type == 'audio')
         except StopIteration:
             pass
         else:
             self._audio_bidge.add(audio_stream)
Exemplo n.º 3
0
 def _NH_SIPIncomingSubscriptionDidTimeout(self, notification):
     if XMPPGatewayConfig.log_presence:
         log.info(
             'SIP subscription from %s to %s timed out for presence flow 0x%x (%d subs)'
             % (format_uri(self.sip_identity.uri, 'sip'),
                format_uri(self.xmpp_identity.uri,
                           'xmpp'), id(self), len(self._sip_subscriptions)))
Exemplo n.º 4
0
 def _NH_SIPIncomingSubscriptionGotUnsubscribe(self, notification):
     if XMPPGatewayConfig.log_presence:
         log.info(
             'SIP subscription from %s to %s was terminated by user for presence flow 1x%x (%d subs)'
             % (format_uri(self.sip_identity.uri, 'sip'),
                format_uri(self.xmpp_identity.uri,
                           'xmpp'), id(self), len(self._sip_subscriptions)))
Exemplo n.º 5
0
    def _NH_XMPPGotComposingIndication(self, notification):
        composing_indication = notification.data.composing_indication
        sender = composing_indication.sender
        recipient = composing_indication.recipient
        if not XMPPGatewayConfig.use_msrp_for_chat:
            state = 'active' if composing_indication.state == 'composing' else 'idle'
            try:
                interval = composing_indication.interval
            except AttributeError:
                interval = 60

            body = IsComposingMessage(
                state=State(state),
                refresh=Refresh(interval),
                last_active=LastActive(ISOTimestamp.now()),
                content_type=ContentType('text')).toxml()
            message = NormalMessage(sender, recipient, body)
            sip_message_sender = SIPMessageSender(
                message,
                content_type=IsComposingDocument.content_type,
                use_cpim=XMPPGatewayConfig.use_cpim)
            if XMPPGatewayConfig.log_iscomposing:
                log.info('xmpp:%s to sip:%s chat is %s' %
                         (sender, recipient, composing_indication.state))

            try:
                sip_message_sender.send().wait()
            except SIPMessageError as e:
                if XMPPGatewayConfig.log_iscomposing:
                    log.error('SIP Message from %s to %s failed: %s (%s)' %
                              (sender, recipient, e.reason, e.code))
Exemplo n.º 6
0
 def _NH_X2SMucHandlerDidEnd(self, notification):
     handler = notification.sender
     log.info('Multiparty session ended xmpp:%s --> sip:%s' %
              (handler.xmpp_identity.uri, handler.sip_identity.uri))
     self.x2s_muc_sessions.pop(
         (handler.xmpp_identity.uri, handler.sip_identity.uri), None)
     notification.center.remove_observer(self, sender=handler)
Exemplo n.º 7
0
 def _NH_SIPSessionDidFail(self, notification):
     log.info("SIP session %s failed" % self.sip_session.call_id)
     notification.center.remove_observer(self, sender=self.sip_session)
     notification.center.remove_observer(self, sender=self.msrp_stream)
     self.sip_session = None
     self.msrp_stream = None
     self.end()
Exemplo n.º 8
0
 def _NH_X2SPresenceHandlerDidEnd(self, notification):
     handler = notification.sender
     self.x2s_presence_subscriptions.pop((handler.xmpp_identity.uri, handler.sip_identity.uri), None)
     notification.center.remove_observer(self, sender=handler)
     if XMPPGatewayConfig.log_presence:
         log.info('Presence flow 0x%x ended %s --> %s' % (id(handler), format_uri(handler.xmpp_identity.uri, 'xmpp'), format_uri(handler.sip_identity.uri, 'sip')))
         log.info('%d SIP --> XMPP and %d XMPP --> SIP presence flows are active' % (len(self.s2x_presence_subscriptions), len(self.x2s_presence_subscriptions)))
Exemplo n.º 9
0
 def _NH_SIPSessionDidEnd(self, notification):
     log.info("SIP multiparty session %s ended" % self._sip_session.call_id)
     notification.center.remove_observer(self, sender=self._sip_session)
     notification.center.remove_observer(self, sender=self._msrp_stream)
     self._sip_session = None
     self._msrp_stream = None
     self.end()
Exemplo n.º 10
0
 def _NH_SIPIncomingSubscriptionNotifyDidFail(self, notification):
     if XMPPGatewayConfig.log_presence:
         log.info(
             'Sending SIP NOTIFY failed from %s to %s for presence flow 0x%x: %s (%s)'
             % (format_uri(self.xmpp_identity.uri, 'xmpp'),
                format_uri(self.sip_identity.uri, 'sip'), id(self),
                notification.data.code, notification.data.reason))
Exemplo n.º 11
0
 def _NH_S2XMucInvitationHandlerDidFail(self, notification):
     handler = notification.sender
     muc_uri = handler.sender.uri
     inviter_uri = handler.inviter.uri
     recipient_uri = handler.recipient.uri
     log.info('%s could not add %s to multiparty chat %s: %s' % (format_uri(inviter_uri, 'sip'), format_uri(recipient_uri, 'xmpp'), format_uri(muc_uri, 'sip'), str(notification.data.failure)))
     del self.s2x_muc_add_participant_handlers[(muc_uri, recipient_uri)]
     notification.center.remove_observer(self, sender=handler)
Exemplo n.º 12
0
 def _NH_X2SMucInvitationHandlerDidStart(self, notification):
     handler = notification.sender
     sender_uri = handler.sender.uri
     muc_uri = handler.recipient.uri
     participant_uri = handler.participant.uri
     log.info('%s invited %s to multiparty chat %s' %
              (format_uri(sender_uri, 'xmpp'), format_uri(participant_uri),
               format_uri(muc_uri, 'sip')))
Exemplo n.º 13
0
 def _NH_X2SMucInvitationHandlerDidEnd(self, notification):
     handler = notification.sender
     sender_uri = handler.sender.uri
     muc_uri = handler.recipient.uri
     participant_uri = handler.participant.uri
     log.info('%s added %s to multiparty chat %s' % (format_uri(sender_uri, 'xmpp'), format_uri(participant_uri), format_uri(muc_uri, 'sip')))
     del self.x2s_muc_add_participant_handlers[(muc_uri, participant_uri)]
     notification.center.remove_observer(self, sender=handler)
Exemplo n.º 14
0
 def _NH_ChatSessionDidStart(self, notification):
     handler = notification.sender
     log.info('Chat session established sip:%s <--> xmpp:%s' % (handler.sip_identity.uri, handler.xmpp_identity.uri))
     for k,v in self.pending_sessions.items():
         if v is handler:
             del self.pending_sessions[k]
             break
     self.chat_sessions.add(handler)
Exemplo n.º 15
0
 def _NH_S2XMucInvitationHandlerDidStart(self, notification):
     handler = notification.sender
     muc_uri = handler.sender.uri
     inviter_uri = handler.inviter.uri
     recipient_uri = handler.recipient.uri
     log.info(
         "%s invited %s to multiparty chat %s" %
         (format_uri(inviter_uri, 'sip'), format_uri(
             recipient_uri, 'xmpp'), format_uri(muc_uri, 'sip')))
Exemplo n.º 16
0
    def incoming_media_session(self, session):
        if session.remote_identity.uri.host not in self.xmpp_manager.domains|self.xmpp_manager.muc_domains:
            log.info('Session rejected: From domain is not a local XMPP domain')
            session.reject(403)
            return

        handler = MediaSessionHandler.new_from_sip_session(session)
        if handler is not None:
            NotificationCenter().add_observer(self, sender=handler)
Exemplo n.º 17
0
 def _NH_SIPSessionDidStart(self, notification):
     log.info("SIP multiparty session %s started" %
              self._sip_session.call_id)
     if not self._sip_session.remote_focus or not self._msrp_stream.nickname_allowed:
         self.end()
         return
     message_id = self._msrp_stream.set_local_nickname(self.nickname)
     self._pending_nicknames_map[message_id] = (self.nickname,
                                                self._first_stanza)
     self._first_stanza = None
Exemplo n.º 18
0
 def _NH_S2XPresenceHandlerDidStart(self, notification):
     handler = notification.sender
     if XMPPGatewayConfig.log_presence:
         log.info('Presence flow 0x%x established %s --> %s' %
                  (id(handler), format_uri(handler.sip_identity.uri, 'sip'),
                   format_uri(handler.xmpp_identity.uri, 'xmpp')))
         log.info(
             '%d SIP --> XMPP and %d XMPP --> SIP presence flows are active'
             % (len(self.s2x_presence_subscriptions),
                len(self.x2s_presence_subscriptions)))
Exemplo n.º 19
0
    def start(self):
        self.stopped = False
        # noinspection PyUnresolvedReferences
        interface = XMPPGatewayConfig.local_ip
        port = XMPPGatewayConfig.local_port
        cert_path = XMPPGatewayConfig.certificate.normalized if XMPPGatewayConfig.certificate else None
        cert_chain_path = XMPPGatewayConfig.ca_file.normalized if XMPPGatewayConfig.ca_file else None

        if XMPPGatewayConfig.transport == 'tls':
            if cert_path is not None:
                if not os.path.isfile(cert_path):
                    log.error('Certificate file %s could not be found' %
                              cert_path)
                    return
                try:
                    ssl_ctx_factory = ssl.DefaultOpenSSLContextFactory(
                        cert_path, cert_path)
                except Exception:
                    log.exception('Creating TLS context')
                    return
                if cert_chain_path is not None:
                    if not os.path.isfile(cert_chain_path):
                        log.error(
                            'Certificate chain file %s could not be found' %
                            cert_chain_path)
                        return
                    ssl_ctx = ssl_ctx_factory.getContext()
                    try:
                        ssl_ctx.use_certificate_chain_file(cert_chain_path)
                    except Exception:
                        log.exception('Setting TLS certificate chain file')
                        return
                self._s2s_listener = reactor.listenSSL(port,
                                                       self._s2s_factory,
                                                       ssl_ctx_factory,
                                                       interface=interface)
        else:
            self._s2s_listener = reactor.listenTCP(port,
                                                   self._s2s_factory,
                                                   interface=interface)

        port = self._s2s_listener.getHost().port
        listen_address = self._s2s_listener.getHost()
        log.info("XMPP S2S component listening on %s:%d (%s)" %
                 (listen_address.host, listen_address.port,
                  XMPPGatewayConfig.transport.upper()))
        self.chat_session_manager.start()
        self.muc_session_manager.start()
        self.subscription_manager.start()
        self.jingle_session_manager.start()
        notification_center = NotificationCenter()
        notification_center.add_observer(self, sender=self._internal_component)
        notification_center.add_observer(self, sender=self._muc_component)
        self._internal_component.startService()
        self._muc_component.startService()
Exemplo n.º 20
0
 def _NH_ChatSessionDidFail(self, notification):
     handler = notification.sender
     uris = None
     for k,v in self.pending_sessions.items():
         if v is handler:
             uris = k
             del self.pending_sessions[k]
             break
     sip_uri, xmpp_uri = uris
     log.info('Chat session failed sip:%s <--> xmpp:%s (%s)' % (sip_uri, xmpp_uri, notification.data.reason))
     notification.center.remove_observer(self, sender=handler)
Exemplo n.º 21
0
 def _NH_SIPIncomingSubscriptionDidEnd(self, notification):
     subscription = notification.sender
     notification.center.remove_observer(self, sender=subscription)
     self._sip_subscriptions.remove(subscription)
     if XMPPGatewayConfig.log_presence:
         log.info(
             'SIP subscription from %s to %s removed from presence flow 0x%x (%d subs)'
             % (format_uri(self.sip_identity.uri, 'sip'),
                format_uri(self.xmpp_identity.uri,
                           'xmpp'), id(self), len(self._sip_subscriptions)))
     if not self._sip_subscriptions:
         self.end()
Exemplo n.º 22
0
 def start(self):
     self.stopped = False
     # noinspection PyUnresolvedReferences
     self._s2s_listener = reactor.listenTCP(XMPPGatewayConfig.local_port, self._s2s_factory, interface=XMPPGatewayConfig.local_ip)
     listen_address = self._s2s_listener.getHost()
     log.info("XMPP listener started on %s:%d" % (listen_address.host, listen_address.port))
     self.chat_session_manager.start()
     self.muc_session_manager.start()
     self.subscription_manager.start()
     self.jingle_session_manager.start()
     notification_center = NotificationCenter()
     notification_center.add_observer(self, sender=self._internal_component)
     notification_center.add_observer(self, sender=self._muc_component)
     self._internal_component.startService()
     self._muc_component.startService()
Exemplo n.º 23
0
    def _NH_SIPSessionDidStart(self, notification):
        log.info("SIP session %s started" % self.sip_session.call_id)
        self._sip_session_timer = reactor.callLater(SESSION_TIMEOUT,
                                                    self._inactivity_timeout)

        if self.sip_session.direction == 'outgoing':
            # Time to set sip_identity and create the XMPPChatSession
            contact_uri = self.sip_session._invitation.remote_contact_header.uri
            if contact_uri.parameters.get('gr') is not None:
                sip_leg_uri = FrozenURI(contact_uri.user, contact_uri.host,
                                        contact_uri.parameters.get('gr'))
            else:
                tmp = self.sip_session.remote_identity.uri
                sip_leg_uri = FrozenURI(tmp.user, tmp.host,
                                        generate_sylk_resource())
            self.sip_identity = Identity(
                sip_leg_uri, self.sip_session.remote_identity.display_name)
            session = XMPPChatSession(local_identity=self.sip_identity,
                                      remote_identity=self.xmpp_identity)
            self.xmpp_session = session
            # Session is now established on both ends
            self.started = True
            # Try to wakeup XMPP clients
            self.xmpp_session.send_composing_indication('active')
            self.xmpp_session.send_message(' ', 'text/plain')
        else:
            if self.xmpp_session is not None:
                # Session is now established on both ends
                self.started = True
                # Try to wakeup XMPP clients
                self.xmpp_session.send_composing_indication('active')
                self.xmpp_session.send_message(' ', 'text/plain')
            else:
                # Try to wakeup XMPP clients
                sender = self.sip_identity
                tmp = self.sip_session.local_identity.uri
                recipient_uri = FrozenURI(tmp.user, tmp.host)
                recipient = Identity(recipient_uri)
                xmpp_manager = XMPPManager()
                xmpp_manager.send_stanza(
                    ChatMessage(sender, recipient, ' ', 'text/plain'))
                # Send queued messages
                self._send_queued_messages()
Exemplo n.º 24
0
 def _NH_JingleSessionDidStart(self, notification):
     log.info("Jingle session %s started" % notification.sender.id)
     if self.jingle_session.direction == 'incoming':
         # Both sessions have been accepted now
         self.started = True
         try:
             audio_stream = next(stream for stream in self.jingle_session.streams if stream.type=='audio')
         except StopIteration:
             pass
         else:
             self._audio_bidge.add(audio_stream)
     else:
         # Time to accept the Jingle session and bridge them together
         try:
             audio_stream = next(stream for stream in self.jingle_session.streams if stream.type=='audio')
         except StopIteration:
             pass
         else:
             self._audio_bidge.add(audio_stream)
         self.sip_session.accept(self.sip_session.proposed_streams)
Exemplo n.º 25
0
    def incoming_message(self, message_request, data):
        content_type = data.headers.get('Content-Type', Null).content_type
        from_header = data.headers.get('From', Null)
        to_header = data.headers.get('To', Null)
        if Null in (content_type, from_header, to_header):
            message_request.answer(400)
            return
        log.info('New SIP Message from %s to %s' % (from_header.uri, to_header.uri))

        # Check domain
        if from_header.uri.host not in XMPPGatewayConfig.domains:
            log.info('Message rejected: From domain is not a local XMPP domain')
            message_request.answer(606)
            return

        if content_type == 'message/cpim':
            try:
                cpim_message = CPIMPayload.decode(data.body)
            except CPIMParserError:
                log.info('Message rejected: CPIM parse error')
                message_request.answer(400)
                return
            else:
                body = cpim_message.content
                content_type = cpim_message.content_type
                sender = cpim_message.sender or from_header
                from_uri = sender.uri
        else:
            body = data.body
            from_uri = from_header.uri
        to_uri = str(to_header.uri)
        message_request.answer(200)
        if from_uri.parameters.get('gr', None) is None:
            from_uri = SIPURI.new(from_uri)
            from_uri.parameters['gr'] = generate_sylk_resource()
        sender = Identity(FrozenURI.parse(from_uri))
        recipient = Identity(FrozenURI.parse(to_uri))
        if content_type in ('text/plain', 'text/html'):
            if content_type == 'text/plain':
                html_body = None
            else:
                html_body = body
                body = None
            if XMPPGatewayConfig.use_msrp_for_chat:
                message = NormalMessage(sender, recipient, body, html_body, use_receipt=False)
                self.xmpp_manager.send_stanza(message)
            else:
                message = ChatMessage(sender, recipient, body, html_body, use_receipt=False)
                self.xmpp_manager.send_stanza(message)
        elif content_type == IsComposingDocument.content_type:
            if not XMPPGatewayConfig.use_msrp_for_chat:
                try:
                    msg = IsComposingMessage.parse(body)
                except ParserError:
                    pass
                else:
                    state = 'composing' if msg.state == 'active' else 'paused'
                    message = ChatComposingIndication(sender, recipient, state, use_receipt=False)
                    self.xmpp_manager.send_stanza(message)
Exemplo n.º 26
0
 def _NH_XMPPSubscriptionGotNotify(self, notification):
     stanza = notification.data.presence
     self._stanza_cache[stanza.sender.uri] = stanza
     stanza.timestamp = ISOTimestamp.now(
     )  # TODO: mirror the one in the stanza, if present
     pidf_doc = self._build_pidf()
     if XMPPGatewayConfig.log_presence:
         log.info('XMPP notification from %s to %s for presence flow 0x%x' %
                  (format_uri(self.xmpp_identity.uri, 'xmpp'),
                   format_uri(self.sip_identity.uri, 'sip'), id(self)))
     for subscription in self._sip_subscriptions:
         try:
             subscription.push_content(pidf.PIDFDocument.content_type,
                                       pidf_doc)
         except SIPCoreError as e:
             if XMPPGatewayConfig.log_presence:
                 log.info(
                     'Failed to send SIP NOTIFY from %s to %s for presence flow 0x%x: %s'
                     % (format_uri(self.xmpp_identity.uri, 'xmpp'),
                        format_uri(self.sip_identity.uri,
                                   'sip'), id(self), e))
     if not stanza.available:
         # Only inform once about this device being unavailable
         del self._stanza_cache[stanza.sender.uri]
Exemplo n.º 27
0
 def incoming_session(self, session):
     stream_types = set(stream.type for stream in session.proposed_streams)
     if 'chat' in stream_types:
         log.info('New chat session from %s to %s' % (session.remote_identity.uri, session.local_identity.uri))
         self.incoming_chat_session(session)
     elif 'audio' in stream_types:
         log.info('New audio session from %s to %s' % (session.remote_identity.uri, session.local_identity.uri))
         self.incoming_media_session(session)
     else:
         log.info('New session from %s to %s rejected. Unsupported media: %s ' % (session.remote_identity.uri, session.local_identity.uri, stream_types))
         session.reject(488)
Exemplo n.º 28
0
    def incoming_subscription(self, subscribe_request, data):
        from_header = data.headers.get('From', Null)
        to_header = data.headers.get('To', Null)
        if Null in (from_header, to_header):
            subscribe_request.reject(400)
            return

        if XMPPGatewayConfig.log_presence:
            log.info('SIP subscription from %s to %s' % (format_uri(
                from_header.uri, 'sip'), format_uri(to_header.uri, 'xmpp')))

        if subscribe_request.event != 'presence':
            if XMPPGatewayConfig.log_presence:
                log.info(
                    'SIP subscription rejected: only presence event is supported'
                )
            subscribe_request.reject(489)
            return

        # Check domain
        remote_identity_uri = data.headers['From'].uri
        if remote_identity_uri.host not in XMPPGatewayConfig.domains:
            if XMPPGatewayConfig.log_presence:
                log.info(
                    'SIP subscription rejected: From domain is not a local XMPP domain'
                )
            subscribe_request.reject(606)
            return

        # Get URI representing the SIP side
        sip_leg_uri = FrozenURI(remote_identity_uri.user,
                                remote_identity_uri.host)

        # Get URI representing the XMPP side
        request_uri = data.request_uri
        xmpp_leg_uri = FrozenURI(request_uri.user, request_uri.host)

        try:
            handler = self.s2x_presence_subscriptions[(sip_leg_uri,
                                                       xmpp_leg_uri)]
        except KeyError:
            sip_identity = Identity(sip_leg_uri,
                                    data.headers['From'].display_name)
            xmpp_identity = Identity(xmpp_leg_uri)
            handler = S2XPresenceHandler(sip_identity, xmpp_identity)
            self.s2x_presence_subscriptions[(sip_leg_uri,
                                             xmpp_leg_uri)] = handler
            NotificationCenter().add_observer(self, sender=handler)
            handler.start()

        handler.add_sip_subscription(subscribe_request)
Exemplo n.º 29
0
 def _inactivity_timeout(self):
     log.info("Ending SIP session %s due to inactivity" %
              self.sip_session.call_id)
     self.sip_session.end()
Exemplo n.º 30
0
 def _NH_JingleSessionDidFail(self, notification):
     log.info("Jingle session %s failed (%s)" %
              (notification.sender.id, notification.data.reason))
     notification.center.remove_observer(self, sender=self.jingle_session)
     self.jingle_session = None
     self.end()