Example #1
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)
Example #2
0
 def end(self):
     if self.ended:
         return
     notification_center = NotificationCenter()
     if self._xmpp_muc_session is not None:
         notification_center.remove_observer(self,
                                             sender=self._xmpp_muc_session)
         # Send indication that the user has been kicked from the room
         sender = Identity(
             FrozenURI(self.sip_identity.uri.user,
                       self.sip_identity.uri.host, self.nickname))
         stanza = MUCAvailabilityPresence(sender,
                                          self.xmpp_identity,
                                          available=False)
         stanza.jid = self.xmpp_identity
         stanza.muc_statuses.append('307')
         xmpp_manager = XMPPManager()
         xmpp_manager.send_muc_stanza(stanza)
         self._xmpp_muc_session.end()
         self._xmpp_muc_session = None
     if self._sip_session is not None:
         notification_center.remove_observer(self, sender=self._sip_session)
         self._sip_session.end()
         self._sip_session = None
     self.ended = True
     notification_center.post_notification('X2SMucHandlerDidEnd',
                                           sender=self)
Example #3
0
 def _NH_ChatStreamGotMessage(self, notification):
     # Notification is sent by the MSRP stream
     if not self._xmpp_muc_session:
         return
     message = notification.data.message
     content_type = message.content_type.lower()
     if content_type not in ('text/plain', 'text/html'):
         return
     if content_type == 'text/plain':
         html_body = None
         body = message.content
     else:
         html_body = message.content
         body = None
     resource = message.sender.display_name or str(message.sender.uri)
     sender = Identity(
         FrozenURI(self.sip_identity.uri.user, self.sip_identity.uri.host,
                   resource))
     self._xmpp_muc_session.send_message(sender,
                                         body,
                                         html_body,
                                         message_id='MUC.' +
                                         uuid.uuid4().hex)
     self._msrp_stream.msrp_session.send_report(notification.data.chunk,
                                                200, 'OK')
Example #4
0
 def _NH_ChatStreamDidDeliverMessage(self, notification):
     # Echo back the message to the sender
     stanza = self._pending_messages_map.pop(notification.data.message_id)
     stanza.sender, stanza.recipient = stanza.recipient, stanza.sender
     stanza.sender.uri = FrozenURI(stanza.sender.uri.user,
                                   stanza.sender.uri.host, self.nickname)
     xmpp_manager = XMPPManager()
     xmpp_manager.send_muc_stanza(stanza)
Example #5
0
 def _NH_XMPPGotMucAddParticipantRequest(self, notification):
     sender = notification.data.sender
     recipient = notification.data.recipient
     participant = notification.data.participant
     muc_uri = FrozenURI(recipient.uri.user, recipient.uri.host)
     sender_uri = FrozenURI(sender.uri.user, sender.uri.host)
     participant_uri = FrozenURI(participant.uri.user, participant.uri.host)
     sender = Identity(sender_uri)
     recipient = Identity(muc_uri)
     participant = Identity(participant_uri)
     try:
         handler = self.x2s_muc_add_participant_handlers[(muc_uri, participant_uri)]
     except KeyError:
         handler = X2SMucInvitationHandler(sender, recipient, participant)
         self.x2s_muc_add_participant_handlers[(muc_uri, participant_uri)] = handler
         notification.center.add_observer(self, sender=handler)
         handler.start()
Example #6
0
 def _NH_SIPSessionGotConferenceInfo(self, notification):
     # Translate to XMPP payload
     xmpp_manager = XMPPManager()
     own_uri = FrozenURI(self.xmpp_identity.uri.user,
                         self.xmpp_identity.uri.host)
     conference_info = notification.data.conference_info
     new_participants = set()
     for user in conference_info.users:
         user_uri = FrozenURI.parse(user.entity if user.entity.startswith((
             'sip:', 'sips:')) else 'sip:' + user.entity)
         nickname = user.display_text.value if user.display_text else user.entity
         new_participants.add((user_uri, nickname))
     # Remove participants that are no longer in the room
     for uri, nickname in self._participants - new_participants:
         sender = Identity(
             FrozenURI(self.sip_identity.uri.user,
                       self.sip_identity.uri.host, nickname))
         stanza = MUCAvailabilityPresence(sender,
                                          self.xmpp_identity,
                                          available=False)
         xmpp_manager.send_muc_stanza(stanza)
     # Send presence for current participants
     for uri, nickname in new_participants:
         if uri == own_uri:
             continue
         sender = Identity(
             FrozenURI(self.sip_identity.uri.user,
                       self.sip_identity.uri.host, nickname))
         stanza = MUCAvailabilityPresence(sender,
                                          self.xmpp_identity,
                                          available=True)
         stanza.jid = Identity(uri)
         xmpp_manager.send_muc_stanza(stanza)
     self._participants = new_participants
     # Send own status last
     sender = Identity(
         FrozenURI(self.sip_identity.uri.user, self.sip_identity.uri.host,
                   self.nickname))
     stanza = MUCAvailabilityPresence(sender,
                                      self.xmpp_identity,
                                      available=True)
     stanza.jid = self.xmpp_identity
     stanza.muc_statuses.append('110')
     xmpp_manager.send_muc_stanza(stanza)
Example #7
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()
Example #8
0
 def _NH_XMPPMucGotGroupChat(self, notification):
     message = notification.data.message
     muc_uri = FrozenURI(message.recipient.uri.user, message.recipient.uri.host)
     try:
         session = self.muc_session_manager.incoming[(muc_uri, message.sender.uri)]
     except KeyError:
         # Ignore groupchat messages if there was no session created
         pass
     else:
         session.channel.send(message)
Example #9
0
 def _NH_XMPPGotMucJoinRequest(self, notification):
     stanza = notification.data.stanza
     muc_uri = FrozenURI(stanza.recipient.uri.user, stanza.recipient.uri.host)
     nickname = stanza.recipient.uri.resource
     try:
         handler = self.x2s_muc_sessions[(stanza.sender.uri, muc_uri)]
     except KeyError:
         xmpp_identity = stanza.sender
         sip_identity = stanza.recipient
         sip_identity.uri = muc_uri
         handler = X2SMucHandler(sip_identity, xmpp_identity, nickname)
         handler._first_stanza = stanza
         notification.center.add_observer(self, sender=handler)
         handler.start()
         # Check if there was a pending join request on the SIP side
         try:
             handler = self.s2x_muc_add_participant_handlers[(muc_uri, FrozenURI(stanza.sender.uri.user, stanza.sender.uri.host))]
         except KeyError:
             pass
         else:
             handler.stop()
Example #10
0
    def _start_outgoing_jingle_session(self, streams):
        if self.xmpp_identity.uri.resource is not None:
            self.sip_session.reject()
            return
        xmpp_manager = XMPPManager()
        local_jid = self.sip_identity.uri.as_xmpp_jid()
        remote_jid = self.xmpp_identity.uri.as_xmpp_jid()

        # If this was an invitation to a conference, use the information in the Referred-By header
        if self.sip_identity.uri.host in xmpp_manager.muc_domains and self.sip_session.transfer_info and self.sip_session.transfer_info.referred_by:
            try:
                referred_by_uri = SIPURI.parse(self.sip_session.transfer_info.referred_by)
            except SIPCoreError:
                self.sip_session.reject(488)
                return
            else:
                inviter_uri = FrozenURI(referred_by_uri.user, referred_by_uri.host)
                local_jid = inviter_uri.as_xmpp_jid()

        # Use disco to gather potential JIDs to call
        d = xmpp_manager.disco_client_protocol.requestItems(remote_jid, sender=local_jid)
        try:
            items = block_on(d)
        except Exception:
            items = []
        if not items:
            self.sip_session.reject(480)
            return

        # Check which items support Jingle
        valid = []
        for item in items:
            d = xmpp_manager.disco_client_protocol.requestInfo(item.entity, nodeIdentifier=item.nodeIdentifier, sender=local_jid)
            try:
                info = block_on(d)
            except Exception:
                continue
            if jingle.NS_JINGLE in info.features and jingle.NS_JINGLE_APPS_RTP in info.features:
                valid.append(item.entity)
        if not valid:
            self.sip_session.reject(480)
            return

        # TODO: start multiple sessions?
        self._xmpp_identity = Identity(FrozenURI.parse(valid[0]))

        notification_center = NotificationCenter()
        if self.sip_identity.uri.host in xmpp_manager.muc_domains:
            self.jingle_session = JingleSession(xmpp_manager.jingle_coin_protocol)
        else:
            self.jingle_session = JingleSession(xmpp_manager.jingle_protocol)
        notification_center.add_observer(self, sender=self.jingle_session)
        self.jingle_session.connect(self.sip_identity, self.xmpp_identity, streams, is_focus=self.sip_session.remote_focus)
Example #11
0
 def new_from_sip_session(cls, session):
     proposed_stream_types = set(
         [stream.type for stream in session.proposed_streams])
     streams = []
     for stream_type in proposed_stream_types:
         try:
             klass = JingleMediaStreamRegistry.get(stream_type)
         except Exception:
             continue
         streams.append(klass())
     if not streams:
         session.reject(488)
         return None
     session.send_ring_indication()
     instance = cls()
     NotificationCenter().add_observer(instance, sender=session)
     # Get URI representing the SIP side
     contact_uri = 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 = session.remote_identity.uri
         sip_leg_uri = FrozenURI(tmp.user, tmp.host,
                                 generate_sylk_resource())
     instance._sip_identity = Identity(sip_leg_uri)
     # Get URI representing the XMPP side
     request_uri = session.request_uri
     remote_resource = request_uri.parameters.get('gr', None)
     if remote_resource is not None:
         try:
             remote_resource = decode_resource(remote_resource)
         except (TypeError, UnicodeError):
             remote_resource = None
     xmpp_leg_uri = FrozenURI(request_uri.user, request_uri.host,
                              remote_resource)
     instance._xmpp_identity = Identity(xmpp_leg_uri)
     instance.sip_session = session
     instance._start_outgoing_jingle_session(streams)
     return instance
Example #12
0
 def _NH_XMPPGotPresenceProbe(self, notification):
     stanza = notification.data.presence_stanza
     if stanza.recipient.uri.resource is not None:
         # Skip directed presence
         return
     sender_uri = stanza.sender.uri
     sender_uri_bare = FrozenURI(sender_uri.user, sender_uri.host)
     try:
         subscription = self.subscription_manager.incoming_subscriptions[(stanza.recipient.uri, sender_uri_bare)]
     except KeyError:
         notification.center.post_notification('XMPPGotPresenceSubscriptionRequest', sender=self, data=NotificationData(stanza=stanza))
     else:
         subscription.channel.send(stanza)
Example #13
0
 def _NH_XMPPMucGotPresenceAvailability(self, notification):
     stanza = notification.data.presence_stanza
     if not stanza.sender.uri.resource:
         return
     muc_uri = FrozenURI(stanza.recipient.uri.user, stanza.recipient.uri.host)
     try:
         session = self.muc_session_manager.incoming[(muc_uri, stanza.sender.uri)]
     except KeyError:
         if stanza.available:
             notification.center.post_notification('XMPPGotMucJoinRequest', sender=self, data=NotificationData(stanza=stanza))
         else:
             notification.center.post_notification('XMPPGotMucLeaveRequest', sender=self, data=NotificationData(stanza=stanza))
     else:
         session.channel.send(stanza)
Example #14
0
 def _NH_XMPPGotPresenceAvailability(self, notification):
     stanza = notification.data.presence_stanza
     if stanza.recipient.uri.resource is not None:
         # Skip directed presence
         return
     sender_uri = stanza.sender.uri
     sender_uri_bare = FrozenURI(sender_uri.user, sender_uri.host)
     try:
         subscription = self.subscription_manager.outgoing_subscriptions[(stanza.recipient.uri, sender_uri_bare)]
     except KeyError:
         # Ignore incoming presence stanzas if there is no subscription
         pass
     else:
         subscription.channel.send(stanza)
Example #15
0
 def _NH_XMPPGotPresenceSubscriptionRequest(self, notification):
     stanza = notification.data.stanza
     # Disregard the resource part, the presence request could be a probe instead of a subscribe
     sender_uri = stanza.sender.uri
     sender_uri_bare = FrozenURI(sender_uri.user, sender_uri.host)
     try:
         handler = self.x2s_presence_subscriptions[(sender_uri_bare, stanza.recipient.uri)]
     except KeyError:
         xmpp_identity = stanza.sender
         xmpp_identity.uri = sender_uri_bare
         sip_identity = stanza.recipient
         handler = X2SPresenceHandler(sip_identity, xmpp_identity)
         self.x2s_presence_subscriptions[(sender_uri_bare, stanza.recipient.uri)] = handler
         notification.center.add_observer(self, sender=handler)
         handler.start()
Example #16
0
    def incoming_chat_session(self, session):
        # Check if this session is really an invitation to add a participant to a conference room / muc
        if session.remote_identity.uri.host in self.xmpp_manager.muc_domains and 'isfocus' in session._invitation.remote_contact_header.parameters:
            try:
                referred_by_uri = SIPURI.parse(
                    session.transfer_info.referred_by)
            except SIPCoreError:
                log.info(
                    "SIP multiparty session invitation %s failed: invalid Referred-By header"
                    % session.call_id)
                session.reject(488)
                return
            muc_uri = FrozenURI(session.remote_identity.uri.user,
                                session.remote_identity.uri.host)
            inviter_uri = FrozenURI(referred_by_uri.user, referred_by_uri.host)
            recipient_uri = FrozenURI(session.local_identity.uri.user,
                                      session.local_identity.uri.host)
            sender = Identity(muc_uri)
            recipient = Identity(recipient_uri)
            inviter = Identity(inviter_uri)
            try:
                handler = self.s2x_muc_add_participant_handlers[(
                    muc_uri, recipient_uri)]
            except KeyError:
                handler = S2XMucInvitationHandler(session, sender, recipient,
                                                  inviter)
                self.s2x_muc_add_participant_handlers[(
                    muc_uri, recipient_uri)] = handler
                NotificationCenter().add_observer(self, sender=handler)
                handler.start()
            else:
                log.info(
                    "SIP multiparty session invitation %s failed: there is another invitation in progress from %s to %s"
                    % (session.call_id, format_uri(inviter_uri, 'sip'),
                       format_uri(recipient_uri, 'xmpp')))
                session.reject(480)
            return

        # Check domain
        if session.remote_identity.uri.host not in XMPPGatewayConfig.domains:
            log.info(
                'Session rejected: From domain is not a local XMPP domain')
            session.reject(606, 'Not Acceptable')
            return

        # Get URI representing the SIP side
        contact_uri = 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 = session.remote_identity.uri
            sip_leg_uri = FrozenURI(tmp.user, tmp.host,
                                    generate_sylk_resource())

        # Get URI representing the XMPP side
        request_uri = session.request_uri
        remote_resource = request_uri.parameters.get('gr', None)
        if remote_resource is not None:
            try:
                remote_resource = decode_resource(remote_resource)
            except (TypeError, UnicodeError):
                remote_resource = None
        xmpp_leg_uri = FrozenURI(request_uri.user, request_uri.host,
                                 remote_resource)

        try:
            handler = self.pending_sessions[(sip_leg_uri, xmpp_leg_uri)]
        except KeyError:
            pass
        else:
            # There is another pending session with same identifiers, can't accept this one
            log.info(
                'Session rejected: other session with same identifiers in progress'
            )
            session.reject(488)
            return

        sip_identity = Identity(sip_leg_uri,
                                session.remote_identity.display_name)
        handler = ChatSessionHandler.new_from_sip_session(
            sip_identity, session)
        NotificationCenter().add_observer(self, sender=handler)
        key = (sip_leg_uri, xmpp_leg_uri)
        self.pending_sessions[key] = handler

        if xmpp_leg_uri.resource is not None:
            # Incoming session target contained GRUU, so create XMPPChatSession immediately
            xmpp_session = XMPPChatSession(
                local_identity=handler.sip_identity,
                remote_identity=Identity(xmpp_leg_uri))
            handler.xmpp_identity = xmpp_session.remote_identity
            handler.xmpp_session = xmpp_session
Example #17
0
 def _NH_XMPPGotChatMessage(self, notification):
     # This notification is only processed here untill the ChatSessionHandler
     # has both (SIP and XMPP) sessions established
     message = notification.data.message
     sender = message.sender
     recipient = message.recipient
     if XMPPGatewayConfig.use_msrp_for_chat:
         if recipient.uri.resource is None:
             # If recipient resource is not set the session is started from
             # the XMPP side
             sip_leg_uri = FrozenURI.new(recipient.uri)
             xmpp_leg_uri = FrozenURI.new(sender.uri)
             try:
                 handler = self.pending_sessions[(sip_leg_uri,
                                                  xmpp_leg_uri)]
                 handler.enqueue_xmpp_message(message)
             except KeyError:
                 # Check if we have any already open chat session and dispatch it there
                 try:
                     handler = next(
                         h for h in self.chat_sessions
                         if h.xmpp_identity.uri.user == xmpp_leg_uri.user
                         and h.xmpp_identity.uri.host == xmpp_leg_uri.host
                         and h.sip_identity.uri.user == sip_leg_uri.user
                         and h.sip_identity.uri.host == sip_leg_uri.host)
                 except StopIteration:
                     # Not found, need to create a new handler and a outgoing SIP session
                     xmpp_identity = Identity(xmpp_leg_uri)
                     handler = ChatSessionHandler.new_from_xmpp_stanza(
                         xmpp_identity, sip_leg_uri)
                     key = (sip_leg_uri, xmpp_leg_uri)
                     self.pending_sessions[key] = handler
                     NotificationCenter().add_observer(self, sender=handler)
                 handler.enqueue_xmpp_message(message)
         else:
             # Find handler pending XMPP confirmation
             sip_leg_uri = FrozenURI.new(recipient.uri)
             xmpp_leg_uri = FrozenURI(sender.uri.user, sender.uri.host)
             try:
                 handler = self.pending_sessions[(sip_leg_uri,
                                                  xmpp_leg_uri)]
             except KeyError:
                 # Find handler pending XMPP confirmation
                 sip_leg_uri = FrozenURI(recipient.uri.user,
                                         recipient.uri.host)
                 xmpp_leg_uri = FrozenURI.new(sender.uri)
                 try:
                     handler = self.pending_sessions[(sip_leg_uri,
                                                      xmpp_leg_uri)]
                 except KeyError:
                     # Try harder, maybe the XMPP client changed his from
                     try:
                         handler = next(
                             h for h in self.chat_sessions
                             if h.xmpp_identity.uri.user ==
                             xmpp_leg_uri.user and h.xmpp_identity.uri.host
                             == xmpp_leg_uri.host and
                             h.sip_identity.uri.user == sip_leg_uri.user and
                             h.sip_identity.uri.host == sip_leg_uri.host)
                     except StopIteration:
                         # It's a new XMPP session to a full JID, disregard the full JID and start a new SIP session to the bare JID
                         xmpp_identity = Identity(xmpp_leg_uri)
                         handler = ChatSessionHandler.new_from_xmpp_stanza(
                             xmpp_identity, sip_leg_uri)
                         key = (sip_leg_uri, xmpp_leg_uri)
                         self.pending_sessions[key] = handler
                         NotificationCenter().add_observer(self,
                                                           sender=handler)
                 handler.enqueue_xmpp_message(message)
             else:
                 # Found handle, create XMPP session and establish session
                 session = XMPPChatSession(local_identity=recipient,
                                           remote_identity=sender)
                 handler.enqueue_xmpp_message(message)
                 handler.xmpp_identity = session.remote_identity
                 handler.xmpp_session = session
     else:
         sip_message_sender = SIPMessageSender(message)
         try:
             sip_message_sender.send().wait()
         except SIPMessageError as e:
             # TODO report back an error stanza
             log.error('Error sending SIP Message: %s' % e)