Beispiel #1
0
 def _start_outgoing_sip_session(self, target_uri):
     notification_center = NotificationCenter()
     # self.xmpp_identity is our local identity
     from_uri = self.xmpp_identity.uri.as_sip_uri()
     del from_uri.parameters['gr']    # no GRUU in From header
     contact_uri = self.xmpp_identity.uri.as_sip_uri()
     contact_uri.parameters['gr'] = encode_resource(contact_uri.parameters['gr'].decode('utf-8'))
     to_uri = target_uri.as_sip_uri()
     lookup = DNSLookup()
     settings = SIPSimpleSettings()
     account = DefaultAccount()
     if account.sip.outbound_proxy is not None:
         uri = SIPURI(host=account.sip.outbound_proxy.host,
                      port=account.sip.outbound_proxy.port,
                      parameters={'transport': account.sip.outbound_proxy.transport})
     else:
         uri = to_uri
     try:
         routes = lookup.lookup_sip_proxy(uri, settings.sip.transport_list).wait()
     except DNSLookupError:
         log.warning('DNS lookup error while looking for %s proxy' % uri)
         notification_center.post_notification('ChatSessionDidFail', sender=self, data=NotificationData(reason='DNS lookup error'))
         return
     self.msrp_stream = MediaStreamRegistry.get('chat')()
     route = routes.pop(0)
     from_header = FromHeader(from_uri)
     to_header = ToHeader(to_uri)
     contact_header = ContactHeader(contact_uri)
     self.sip_session = Session(account)
     notification_center.add_observer(self, sender=self.sip_session)
     notification_center.add_observer(self, sender=self.msrp_stream)
     self.sip_session.connect(from_header, to_header, contact_header=contact_header, route=route, streams=[self.msrp_stream])
Beispiel #2
0
 def _start_outgoing_sip_session(self, streams):
     notification_center = NotificationCenter()
     # self.xmpp_identity is our local identity on the SIP side
     from_uri = self.xmpp_identity.uri.as_sip_uri()
     from_uri.parameters.pop('gr', None)    # no GRUU in From header
     to_uri = self.sip_identity.uri.as_sip_uri()
     to_uri.parameters.pop('gr', None)      # no GRUU in To header
     # TODO: need to fix GRUU in the proxy
     #contact_uri = self.xmpp_identity.uri.as_sip_uri()
     #contact_uri.parameters['gr'] = encode_resource(contact_uri.parameters['gr'].decode('utf-8'))
     lookup = DNSLookup()
     settings = SIPSimpleSettings()
     account = DefaultAccount()
     if account.sip.outbound_proxy is not None:
         uri = SIPURI(host=account.sip.outbound_proxy.host,
                      port=account.sip.outbound_proxy.port,
                      parameters={'transport': account.sip.outbound_proxy.transport})
     else:
         uri = to_uri
     try:
         routes = lookup.lookup_sip_proxy(uri, settings.sip.transport_list).wait()
     except DNSLookupError:
         log.warning('DNS lookup error while looking for %s proxy' % uri)
         notification_center.post_notification('MedialSessionHandlerDidFail', sender=self, data=NotificationData(reason='DNS lookup error'))
         return
     route = routes.pop(0)
     from_header = FromHeader(from_uri)
     to_header = ToHeader(to_uri)
     self.sip_session = Session(account)
     notification_center.add_observer(self, sender=self.sip_session)
     self.sip_session.connect(from_header, to_header, route=route, streams=streams)
    def _sendMessage(self, msgid, text, content_type="text/plain"):

        utf8_encode = content_type not in ('application/im-iscomposing+xml',
                                           'message/cpim')
        message_request = Message(
            FromHeader(self.account.uri, self.account.display_name),
            ToHeader(self.target_uri),
            RouteHeader(self.routes[0].get_uri()),
            content_type,
            text.encode('utf-8') if utf8_encode else text,
            credentials=self.account.credentials)
        self.notification_center.add_observer(self, sender=message_request)
        message_request.send(
            15 if content_type != "application/im-iscomposing+xml" else 5)

        id = str(message_request)
        if content_type != "application/im-iscomposing+xml":
            BlinkLogger().log_info(u"Sent %s SMS message to %s" %
                                   (content_type, self.target_uri))
            self.enableIsComposing = True
            message = self.messages.pop(msgid)
            message.status = 'sent'
        else:
            message = MessageInfo(id, content_type=content_type)

        self.messages[id] = message
        return message
Beispiel #4
0
    def send(self):
        lookup = DNSLookup()
        settings = SIPSimpleSettings()
        account = DefaultAccount()
        if account.sip.outbound_proxy is not None:
            uri = SIPURI(
                host=account.sip.outbound_proxy.host,
                port=account.sip.outbound_proxy.port,
                parameters={'transport': account.sip.outbound_proxy.transport})
        else:
            uri = self.to_uri
        try:
            routes = lookup.lookup_sip_proxy(
                uri, settings.sip.transport_list).wait()
        except DNSLookupError:
            msg = 'DNS lookup error while looking for %s proxy' % uri
            log.warning(msg)
            raise SIPMessageError(0, msg)
        else:
            route = routes.pop(0)
            from_header = FromHeader(self.from_uri)
            to_header = ToHeader(self.to_uri)
            route_header = RouteHeader(route.uri)
            notification_center = NotificationCenter()
            for chunk in chunks(self.body, 1000):
                if self.use_cpim:
                    additional_headers = []
                    payload = CPIMPayload(
                        self.body.encode('utf-8'),
                        self.content_type,
                        charset='utf-8',
                        sender=ChatIdentity(self.from_uri, None),
                        recipients=[ChatIdentity(self.to_uri, None)],
                        additional_headers=additional_headers)

                    payload, content_type = payload.encode()
                else:
                    content_type = self.content_type
                    payload = self.body.encode('utf-8')

                request = SIPMessageRequest(from_header, to_header,
                                            route_header, content_type,
                                            payload)
                notification_center.add_observer(self, sender=request)
                self._requests.add(request)
                request.send()
            error = None
            count = len(self._requests)
            while count > 0:
                notification = self._channel.wait()
                if notification.name == 'SIPMessageDidFail':
                    error = (notification.data.code, notification.data.reason)
                count -= 1
            self._requests.clear()
            if error is not None:
                raise SIPMessageError(*error)
Beispiel #5
0
    def _setup_new_subscriptions(self, urilist):
        # TODO: Add check to see active subscriptions so it doesn't subscribe twice
        # sets up a new subscription with the given list of URI's
        for uri in urilist:
            tempuri = uri
            if tempuri is None:
                tempuri = ToHeader(
                    SIPURI(user=self.account.id.username,
                           host=self.account.id.domain))
            else:
                if '@' not in tempuri:
                    tempuri = '%s@%s' % (tempuri, self.account.id.domain)
                if not uri.startswith('sip:') and not tempuri.startswith(
                        'sips:'):
                    tempuri = 'sip:' + tempuri
                try:
                    tempuri = ToHeader(SIPURI.parse(tempuri))
                except SIPCoreError:
                    self.output.put('Illegal SIP URI: %s' % tempuri)
                    return 1
            self.subscriptionqueue.append(tempuri)
        #reactor.callLater(0, self._subscribe)
        settings = SIPSimpleSettings()

        self._subscription_timeout = time() + 30

        lookup = DNSLookup()
        notification_center = NotificationCenter()
        notification_center.add_observer(self, sender=lookup)
        proxyuri = None
        if self.account.sip.outbound_proxy is not None:
            proxyuri = SIPURI(host=self.account.sip.outbound_proxy.host,
                              port=self.account.sip.outbound_proxy.port,
                              parameters={
                                  'transport':
                                  self.account.sip.outbound_proxy.transport
                              })
        elif self.account.sip.always_use_my_proxy:
            proxyuri = SIPURI(host=self.account.id.domain)
        else:
            proxyuri = self.subscriptionqueue[0].uri
        lookup.lookup_sip_proxy(proxyuri, settings.sip.transport_list)
 def _NH_DNSLookupDidSucceed(self, sender, data):
     notification_center = NotificationCenter()
     notification_center.remove_observer(self, sender=sender)
     if self.interrupted:
         notification_center.post_notification(
             "BlinkFileTransferDidFail",
             sender=self,
             data=TimestampedNotificationData())
         return
     self.session.connect(ToHeader(self.target_uri), data.result,
                          [self.stream])
Beispiel #7
0
    def _send_message(self, message):
        if (not self.last_route):
            self.log_info('No route found')
            return

        message.timestamp = ISOTimestamp.now()

        if not isinstance(message, OTRInternalMessage):
            try:
                content = self.encryption.otr_session.handle_output(
                    message.content, message.content_type)
            except OTRError as e:
                if 'has ended the private conversation' in str(e):
                    self.log_info(
                        'Encryption has been disabled by remote party, please resend the message again'
                    )
                    self.encryption.stop()
                else:
                    self.log_info('Failed to encrypt outgoing message: %s' %
                                  str(e))
                return

        timeout = 5
        if message.content_type != "application/im-iscomposing+xml":
            self.enableIsComposing = True
            timeout = 15

        message_request = Message(FromHeader(self.account.uri,
                                             self.account.display_name),
                                  ToHeader(self.target_uri),
                                  RouteHeader(self.last_route.uri),
                                  message.content_type,
                                  message.content,
                                  credentials=self.account.credentials)

        self.notification_center.add_observer(self, sender=message_request)

        message_request.send(timeout)
        message.status = 'sent'
        message.call_id = message_request._request.call_id.decode()

        if not isinstance(message, OTRInternalMessage):
            if self.encryption.active:
                self.log_info(
                    'Sending encrypted %s message %s to %s' %
                    (message.content_type, message.id, self.last_route.uri))
            else:
                self.log_info(
                    'Sending %s message %s to %s' %
                    (message.content_type, message.id, self.last_route.uri))

        id = str(message_request)
        self.messages[id] = message
Beispiel #8
0
 def _NH_DNSLookupDidSucceed(self, notification):
     notification_center = NotificationCenter()
     notification_center.remove_observer(self, sender=notification.sender)
     account = DefaultAccount()
     conference_application = ConferenceApplication()
     try:
         room = conference_application.get_room(self.room_uri)
     except RoomNotFoundError:
         log.info('Room %s - failed to add %s' %
                  (self.room_uri_str, self.refer_to_uri))
         self._refer_request.end(500)
         return
     active_media = set(room.active_media).intersection(('audio', 'chat'))
     if not active_media:
         log.info('Room %s - failed to add %s' %
                  (self.room_uri_str, self.refer_to_uri))
         self._refer_request.end(500)
         return
     for stream_type in active_media:
         self.streams.append(MediaStreamRegistry.get(stream_type)())
     self.session = Session(account)
     notification_center.add_observer(self, sender=self.session)
     original_from_header = self._refer_headers.get('From')
     if original_from_header.display_name:
         original_identity = "%s <%s@%s>" % (
             original_from_header.display_name,
             original_from_header.uri.user, original_from_header.uri.host)
     else:
         original_identity = "%s@%s" % (original_from_header.uri.user,
                                        original_from_header.uri.host)
     from_header = FromHeader(SIPURI.new(self.room_uri), u'Conference Call')
     to_header = ToHeader(self.refer_to_uri)
     extra_headers = []
     if self._refer_headers.get('Referred-By', None) is not None:
         extra_headers.append(
             Header.new(self._refer_headers.get('Referred-By')))
     else:
         extra_headers.append(
             Header('Referred-By', str(original_from_header.uri)))
     if ThorNodeConfig.enabled:
         extra_headers.append(Header('Thor-Scope', 'conference-invitation'))
     extra_headers.append(
         Header('X-Originator-From', str(original_from_header.uri)))
     extra_headers.append(
         SubjectHeader(u'Join conference request from %s' %
                       original_identity))
     route = notification.data.result[0]
     self.session.connect(from_header,
                          to_header,
                          route=route,
                          streams=self.streams,
                          is_focus=True,
                          extra_headers=extra_headers)
Beispiel #9
0
 def _send_options(self):
     notification_center = NotificationCenter()
     route = self._routes.popleft()
     route_header = RouteHeader(route.get_uri())
     try:
         local_uri = self._contact_factory[route.transport]
     except KeyError:
         notification_center.post_notification('SIPOptionsRequestDidFail', sender=self, data=TimestampedNotificationData(code=0, reason='Could not build local URI'))
         return
     self.options_request = Options(FromHeader(local_uri),
                                    ToHeader(self.target_uri),
                                    route_header)
     notification_center.add_observer(self, sender=self.options_request)
     self.options_request.send(3)
Beispiel #10
0
 def _send_message(self, targeturi, messagebody, route):
     ## sends a message to the target URI
     notification_center = NotificationCenter()
     if route:
         uri = targeturi
         if uri is None:
             uri = ToHeader(
                 SIPURI(user=self.account.id.username,
                        host=self.account.id.domain))
         identity = str(self.account.uri)
         if self.account.display_name:
             identity = '"%s" <%s>' % (self.account.display_name, identity)
         self.output.put(
             "Sending MESSAGE from '%s' to '%s' using proxy %s" %
             (identity, targeturi, route))
         message_request = Message(
             FromHeader(self.account.uri, self.account.display_name),
             ToHeader(uri), RouteHeader(route.uri), 'text/plain',
             messagebody, self.account.credentials, [])
         notification_center.add_observer(self, sender=message_request)
         message_request.send()
     else:
         self.output.put('No route to try. Aborting.\n')
         return
Beispiel #11
0
 def send_chuck_norris_fact(self, source_uri, destination_uri, fact):
     lookup = DNSLookup()
     settings = SIPSimpleSettings()
     try:
         routes = lookup.lookup_sip_proxy(
             destination_uri, settings.sip.transport_list).wait()
     except DNSLookupError:
         print "DNS lookup error while looking for %s proxy\n" % destination_uri
     else:
         route = routes.pop(0)
         message_request = Message(FromHeader(source_uri),
                                   ToHeader(destination_uri),
                                   RouteHeader(route.get_uri()),
                                   'text/plain', fact)
         message_request.send()
Beispiel #12
0
    def start(self):
        notification_center = NotificationCenter()
        self.greenlet = api.getcurrent()
        settings = SIPSimpleSettings()
        account = AccountManager().sylkserver_account
        if account.sip.outbound_proxy is not None:
            uri = SIPURI(
                host=account.sip.outbound_proxy.host,
                port=account.sip.outbound_proxy.port,
                parameters={'transport': account.sip.outbound_proxy.transport})
        else:
            uri = self.destination_uri
        lookup = DNSLookup()
        try:
            routes = lookup.lookup_sip_proxy(
                uri, settings.sip.transport_list).wait()
        except DNSLookupError:
            notification_center.post_notification(
                'OutgoingFileTransferHandlerDidFail', sender=self)
            return

        self.session = Session(account)
        self.stream = FileTransferStream(self.file_selector, 'sendonly')
        notification_center.add_observer(self, sender=self.session)
        notification_center.add_observer(self, sender=self.stream)
        from_header = FromHeader(self.sender_uri, u'SIPStache File Transfer')
        to_header = ToHeader(self.destination_uri)
        transport = routes[0].transport
        parameters = {} if transport == 'udp' else {'transport': transport}
        contact_header = ContactHeader(
            SIPURI(user=self.sender_uri.user,
                   host=SIPConfig.local_ip.normalized,
                   port=getattr(Engine(), '%s_port' % transport),
                   parameters=parameters))
        extra_headers = []
        if ThorNodeConfig.enabled:
            extra_headers.append(Header('Thor-Scope', 'sipstache-file'))
        extra_headers.append(
            Header('X-Originator-From', str(self.destination_uri)))
        self.session.connect(from_header,
                             to_header,
                             contact_header=contact_header,
                             routes=routes,
                             streams=[self.stream],
                             is_focus=False,
                             extra_headers=extra_headers)
        notification_center.post_notification(
            'OutgoingFileTransferHandlerDidStart', sender=self)
 def _NH_DNSLookupDidSucceed(self, notification):
     notification.center.remove_observer(self, sender=notification.sender)
     if self._ended:
         return
     routes = notification.data.result
     if not routes:
         self._terminate(failure_reason="Destination not found")
         return
     self.session = Session(self.account)
     self.stream = FileTransferStream(self._file_selector,
                                      'recvonly',
                                      transfer_id=self.ft_info.transfer_id)
     self.handler = self.stream.handler
     notification.center.add_observer(self, sender=self.stream)
     notification.center.add_observer(self, sender=self.handler)
     self.session.connect(ToHeader(self.target_uri), routes, [self.stream])
Beispiel #14
0
    def sendReplicationMessage(self,
                               response_code,
                               content,
                               content_type="message/cpim",
                               timestamp=None):
        timestamp = timestamp or ISOTimestamp.now()
        # Lookup routes
        if self.account.sip.outbound_proxy is not None:
            uri = SIPURI(host=self.account.sip.outbound_proxy.host,
                         port=self.account.sip.outbound_proxy.port,
                         parameters={
                             'transport':
                             self.account.sip.outbound_proxy.transport
                         })
        else:
            uri = SIPURI(host=self.account.id.domain)

        route = None
        if self.last_route is None:
            lookup = DNSLookup()
            settings = SIPSimpleSettings()
            try:
                routes = lookup.lookup_sip_proxy(
                    uri, settings.sip.transport_list).wait()
            except DNSLookupError:
                pass
            else:
                route = routes[0]
        else:
            route = self.last_route

        if route:
            extra_headers = [
                Header("X-Offline-Storage", "no"),
                Header("X-Replication-Code", str(response_code)),
                Header("X-Replication-Timestamp", str(ISOTimestamp.now()))
            ]
            message_request = Message(FromHeader(self.account.uri,
                                                 self.account.display_name),
                                      ToHeader(self.account.uri),
                                      RouteHeader(route.uri),
                                      content_type,
                                      content,
                                      credentials=self.account.credentials,
                                      extra_headers=extra_headers)
            message_request.send(
                15 if content_type != "application/im-iscomposing+xml" else 5)
Beispiel #15
0
 def _NH_DNSLookupDidSucceed(self, notification):
     notification.center.remove_observer(self, sender=notification.sender)
     if self._ended:
         self.log_info("File transfer was already cancelled")
         return
     routes = notification.data.result
     if not routes:
         self._terminate(failure_reason="Destination not found")
         return
     self.session = Session(self.account)
     self.stream = FileTransferStream(self._file_selector,
                                      'sendonly',
                                      transfer_id=self.ft_info.transfer_id)
     self.handler = self.stream.handler
     notification.center.add_observer(self, sender=self.stream)
     notification.center.add_observer(self, sender=self.handler)
     self.log_info("Sending push file transfer request via %s..." %
                   routes[0])
     self.session.connect(ToHeader(self.target_uri), routes, [self.stream])
Beispiel #16
0
 def sendReplicationMessage(self,
                            response_code,
                            text,
                            content_type="message/cpim",
                            timestamp=None):
     timestamp = timestamp or datetime.datetime.now(tzlocal())
     # Lookup routes
     if self.account.sip.outbound_proxy is not None:
         uri = SIPURI(host=self.account.sip.outbound_proxy.host,
                      port=self.account.sip.outbound_proxy.port,
                      parameters={
                          'transport':
                          self.account.sip.outbound_proxy.transport
                      })
     else:
         uri = SIPURI(host=self.account.id.domain)
     lookup = DNSLookup()
     settings = SIPSimpleSettings()
     try:
         routes = lookup.lookup_sip_proxy(
             uri, settings.sip.transport_list).wait()
     except DNSLookupError:
         pass
     else:
         utf8_encode = content_type not in (
             'application/im-iscomposing+xml', 'message/cpim')
         extra_headers = [
             Header("X-Offline-Storage", "no"),
             Header("X-Replication-Code", str(response_code)),
             Header("X-Replication-Timestamp",
                    str(Timestamp(datetime.datetime.now())))
         ]
         message_request = Message(
             FromHeader(self.account.uri, self.account.display_name),
             ToHeader(self.account.uri),
             RouteHeader(routes[0].get_uri()),
             content_type,
             text.encode('utf-8') if utf8_encode else text,
             credentials=self.account.credentials,
             extra_headers=extra_headers)
         message_request.send(
             15 if content_type != "application/im-iscomposing+xml" else 5)
Beispiel #17
0
    def _send(self):
        if self.session.routes:
            from_uri = self.account.uri
            content = self.content if isinstance(
                self.content, bytes) else self.content.encode()
            additional_sip_headers = []
            if self.account.sms.use_cpim:
                ns = CPIMNamespace('urn:ietf:params:imdn', 'imdn')
                additional_headers = [CPIMHeader('Message-ID', ns, self.id)]
                if self.account.sms.enable_imdn and self.content_type not in self.__disabled_imdn_content_types__:
                    additional_headers.append(
                        CPIMHeader('Disposition-Notification', ns,
                                   'positive-delivery, display'))
                payload = CPIMPayload(
                    content,
                    self.content_type,
                    charset='utf-8',
                    sender=ChatIdentity(from_uri, self.account.display_name),
                    recipients=[ChatIdentity(self.sip_uri, None)],
                    timestamp=str(self.timestamp),
                    additional_headers=additional_headers)
                payload, content_type = payload.encode()
            else:
                payload = content
                content_type = self.content_type

            route = self.session.routes[0]
            message_request = Message(FromHeader(from_uri,
                                                 self.account.display_name),
                                      ToHeader(self.sip_uri),
                                      RouteHeader(route.uri),
                                      content_type,
                                      payload,
                                      credentials=self.account.credentials,
                                      extra_headers=additional_sip_headers)
            notification_center = NotificationCenter()
            notification_center.add_observer(self, sender=message_request)
            message_request.send()
        else:
            pass
Beispiel #18
0
    async def send_request(self, arc_name: str, scaip_request: ScaipRequest):
        logger.info(f"send_request to {arc_name}: {scaip_request}")

        config = self.config
        arc_config = config.get_arc_config(arc_name)

        if not arc_config:
            raise ValueError(f"no configuration found for ARC {arc_name}")

        xml_model = scaip_request.to_xml_model()
        xml_str = self.serializer.render(xml_model)

        result = self.new_result_future(scaip_request.reference)
        if scaip_request.caller_id.startswith(
                "sip") and scaip_request.caller_id != "sip:":
            caller_id = URI(scaip_request.caller_id)
            sender = SIPURI(user=caller_id.user,
                            host=caller_id.host,
                            port=caller_id.port)
        else:
            sender = self.get_user_agent_uri()

        receiver = SIPURI(user=arc_config.username,
                          host=arc_config.hostname,
                          port=arc_config.port)
        message = Message(FromHeader(sender), ToHeader(receiver),
                          RouteHeader(receiver), 'application/scaip+xml',
                          xml_str)
        message.send()
        logger.info(f"sent message: {xml_str}")

        scaip_response = await result

        logger.info(f"received response: {scaip_response}")

        return scaip_response
Beispiel #19
0
    def _sip_subscription_handler(self, command):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        account = DefaultAccount()
        refresh_interval = getattr(command, 'refresh_interval',
                                   None) or account.sip.subscribe_interval

        try:
            # Lookup routes
            if account.sip.outbound_proxy is not None:
                uri = SIPURI(host=account.sip.outbound_proxy.host,
                             port=account.sip.outbound_proxy.port,
                             parameters={
                                 'transport':
                                 account.sip.outbound_proxy.transport
                             })
            else:
                uri = SIPURI(host=self.sip_identity.uri.as_sip_uri().host)
            lookup = DNSLookup()
            try:
                routes = lookup.lookup_sip_proxy(
                    uri, settings.sip.transport_list).wait()
            except DNSLookupError as e:
                timeout = random.uniform(15, 30)
                raise SubscriptionError(error='DNS lookup failed: %s' % e,
                                        timeout=timeout)

            timeout = time() + 30
            for route in routes:
                remaining_time = timeout - time()
                if remaining_time > 0:
                    transport = route.transport
                    parameters = {} if transport == 'udp' else {
                        'transport': transport
                    }
                    contact_uri = SIPURI(user=account.contact.username,
                                         host=SIPConfig.local_ip.normalized,
                                         port=getattr(Engine(),
                                                      '%s_port' % transport),
                                         parameters=parameters)
                    subscription_uri = self.sip_identity.uri.as_sip_uri()
                    subscription = Subscription(
                        subscription_uri,
                        FromHeader(self.xmpp_identity.uri.as_sip_uri()),
                        ToHeader(subscription_uri),
                        ContactHeader(contact_uri),
                        'presence',
                        RouteHeader(route.uri),
                        refresh=refresh_interval)
                    notification_center.add_observer(self, sender=subscription)
                    try:
                        subscription.subscribe(
                            timeout=limit(remaining_time, min=1, max=5))
                    except SIPCoreError:
                        notification_center.remove_observer(
                            self, sender=subscription)
                        raise SubscriptionError(error='Internal error',
                                                timeout=5)
                    self._sip_subscription = subscription
                    try:
                        while True:
                            notification = self._data_channel.wait()
                            if notification.sender is subscription and notification.name == 'SIPSubscriptionDidStart':
                                break
                    except SIPSubscriptionDidFail as e:
                        notification_center.remove_observer(
                            self, sender=subscription)
                        self._sip_subscription = None
                        if e.data.code == 407:
                            # Authentication failed, so retry the subscription in some time
                            raise SubscriptionError(
                                error='Authentication failed',
                                timeout=random.uniform(60, 120))
                        elif e.data.code == 403:
                            # Forbidden
                            raise SubscriptionError(error='Forbidden',
                                                    timeout=None,
                                                    fatal=True)
                        elif e.data.code == 423:
                            # Get the value of the Min-Expires header
                            if e.data.min_expires is not None and e.data.min_expires > refresh_interval:
                                interval = e.data.min_expires
                            else:
                                interval = None
                            raise SubscriptionError(error='Interval too short',
                                                    timeout=random.uniform(
                                                        60, 120),
                                                    refresh_interval=interval)
                        elif e.data.code in (405, 406, 489):
                            raise SubscriptionError(
                                error='Method or event not supported',
                                timeout=None,
                                fatal=True)
                        elif e.data.code == 1400:
                            raise SubscriptionError(error=e.data.reason,
                                                    timeout=None,
                                                    fatal=True)
                        else:
                            # Otherwise just try the next route
                            continue
                    else:
                        self.subscribed = True
                        command.signal()
                        break
            else:
                # There are no more routes to try, give up
                raise SubscriptionError(error='No more routes to try',
                                        timeout=None,
                                        fatal=True)
            # At this point it is subscribed. Handle notifications and ending/failures.
            try:
                while True:
                    notification = self._data_channel.wait()
                    if notification.sender is not self._sip_subscription:
                        continue
                    if self._xmpp_subscription is None:
                        continue
                    if notification.name == 'SIPSubscriptionGotNotify':
                        if notification.data.event == 'presence':
                            subscription_state = notification.data.headers.get(
                                'Subscription-State').state
                            if subscription_state == 'active' and self._xmpp_subscription.state != 'active':
                                self._xmpp_subscription.accept()
                            elif subscription_state == 'pending' and self._xmpp_subscription.state == 'active':
                                # The state went from active to pending, hide the presence state?
                                pass
                            if notification.data.body:
                                if XMPPGatewayConfig.log_presence:
                                    log.info(
                                        'SIP NOTIFY from %s to %s' %
                                        (format_uri(self.sip_identity.uri,
                                                    'sip'),
                                         format_uri(self.xmpp_identity.uri,
                                                    'xmpp')))
                                self._process_pidf(notification.data.body)
                    elif notification.name == 'SIPSubscriptionDidEnd':
                        break
            except SIPSubscriptionDidFail as e:
                if e.data.code == 0 and e.data.reason == 'rejected':
                    self._xmpp_subscription.reject()
                else:
                    self._command_channel.send(Command('subscribe'))
            notification_center.remove_observer(self,
                                                sender=self._sip_subscription)
        except InterruptSubscription as e:
            if not self.subscribed:
                command.signal(e)
            if self._sip_subscription is not None:
                notification_center.remove_observer(
                    self, sender=self._sip_subscription)
                try:
                    self._sip_subscription.end(timeout=2)
                except SIPCoreError:
                    pass
        except TerminateSubscription as e:
            if not self.subscribed:
                command.signal(e)
            if self._sip_subscription is not None:
                try:
                    self._sip_subscription.end(timeout=2)
                except SIPCoreError:
                    pass
                else:
                    try:
                        while True:
                            notification = self._data_channel.wait()
                            if notification.sender is self._sip_subscription and notification.name == 'SIPSubscriptionDidEnd':
                                break
                    except SIPSubscriptionDidFail:
                        pass
                finally:
                    notification_center.remove_observer(
                        self, sender=self._sip_subscription)
        except SubscriptionError as e:
            if not e.fatal:
                self._sip_subscription_timer = reactor.callLater(
                    e.timeout, self._command_channel.send,
                    Command('subscribe',
                            command.event,
                            refresh_interval=e.refresh_interval))
        finally:
            self.subscribed = False
            self._sip_subscription = None
            self._sip_subscription_proc = None
            reactor.callLater(0, self.end)
Beispiel #20
0
    def _subscription_handler(self, command):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        subscription_uri = self.subscription_uri
        refresh_interval = command.refresh_interval or self.account.sip.subscribe_interval
        valid_transports = self.__transports__.intersection(
            settings.sip.transport_list)

        try:
            if Host.default_ip is None:
                raise SubscriptionError('No IP address', retry_after=60)

            # Lookup routes
            if self.account.sip.outbound_proxy is not None and self.account.sip.outbound_proxy.transport in valid_transports:
                uri = SIPURI(host=self.account.sip.outbound_proxy.host,
                             port=self.account.sip.outbound_proxy.port,
                             parameters={
                                 'transport':
                                 self.account.sip.outbound_proxy.transport
                             })
            elif self.account.sip.always_use_my_proxy:
                uri = SIPURI(host=self.account.id.domain)
            else:
                uri = SIPURI(host=subscription_uri.domain)

            lookup = DNSLookup()
            try:
                routes = lookup.lookup_sip_proxy(
                    uri, valid_transports,
                    tls_name=self.account.sip.tls_name).wait()
            except DNSLookupError as e:
                raise SubscriptionError('DNS lookup failed: %s' % e,
                                        retry_after=random.uniform(15, 30))

            subscription_uri = SIPURI(user=subscription_uri.username,
                                      host=subscription_uri.domain)
            content = self.content

            timeout = time() + 30
            for route in routes:
                if Host.default_ip is None:
                    raise SubscriptionError('No IP address', retry_after=60)

                remaining_time = timeout - time()
                if remaining_time > 0:
                    try:
                        contact_uri = self.account.contact[NoGRUU, route]
                    except KeyError:
                        continue
                    subscription = Subscription(
                        subscription_uri,
                        FromHeader(self.account.uri,
                                   self.account.display_name),
                        ToHeader(subscription_uri),
                        ContactHeader(contact_uri),
                        self.event.encode(),
                        RouteHeader(route.uri),
                        credentials=self.account.credentials,
                        refresh=refresh_interval)
                    notification_center.add_observer(self, sender=subscription)
                    try:
                        subscription.subscribe(
                            body=content.body,
                            content_type=content.type,
                            extra_headers=self.extra_headers,
                            timeout=limit(remaining_time, min=1, max=5))
                    except SIPCoreError:
                        notification_center.remove_observer(
                            self, sender=subscription)
                        raise SubscriptionError('Internal error',
                                                retry_after=5)
                    self._subscription = subscription
                    try:
                        while True:
                            notification = self._data_channel.wait()
                            if notification.name == 'SIPSubscriptionDidStart':
                                break
                    except SIPSubscriptionDidFail as e:
                        notification_center.remove_observer(
                            self, sender=subscription)
                        self._subscription = None
                        if e.data.code == 407:
                            # Authentication failed, so retry the subscription in some time
                            raise SubscriptionError('Authentication failed',
                                                    retry_after=random.uniform(
                                                        60, 120))
                        elif e.data.code == 423:
                            # Get the value of the Min-Expires header
                            if e.data.min_expires is not None and e.data.min_expires > self.account.sip.subscribe_interval:
                                refresh_interval = e.data.min_expires
                            else:
                                refresh_interval = None
                            raise SubscriptionError(
                                'Interval too short',
                                retry_after=random.uniform(60, 120),
                                refresh_interval=refresh_interval)
                        elif e.data.code in (405, 406, 489):
                            raise SubscriptionError(
                                'Method or event not supported',
                                retry_after=3600)
                        elif e.data.code == 1400:
                            raise SubscriptionError(e.data.reason,
                                                    retry_after=3600)
                        else:
                            # Otherwise just try the next route
                            continue
                    else:
                        self.subscribed = True
                        command.signal()
                        break
            else:
                # There are no more routes to try, reschedule the subscription
                raise SubscriptionError('No more routes to try',
                                        retry_after=random.uniform(60, 180))
            # At this point it is subscribed. Handle notifications and ending/failures.
            notification_center.post_notification(self.__nickname__ +
                                                  'SubscriptionDidStart',
                                                  sender=self)
            try:
                while True:
                    notification = self._data_channel.wait()
                    if notification.name == 'SIPSubscriptionGotNotify':
                        notification_center.post_notification(
                            self.__nickname__ + 'SubscriptionGotNotify',
                            sender=self,
                            data=notification.data)
                    elif notification.name == 'SIPSubscriptionDidEnd':
                        notification_center.post_notification(
                            self.__nickname__ + 'SubscriptionDidEnd',
                            sender=self,
                            data=NotificationData(originator='remote'))
                        if self.active:
                            self._command_channel.send(Command('subscribe'))
                        break
            except SIPSubscriptionDidFail:
                notification_center.post_notification(self.__nickname__ +
                                                      'SubscriptionDidFail',
                                                      sender=self)
                if self.active:
                    self._command_channel.send(Command('subscribe'))
            notification_center.remove_observer(self,
                                                sender=self._subscription)
        except InterruptSubscription as e:
            if not self.subscribed:
                command.signal(e)
            if self._subscription is not None:
                notification_center.remove_observer(self,
                                                    sender=self._subscription)
                try:
                    self._subscription.end(timeout=2)
                except SIPCoreError:
                    pass
                finally:
                    notification_center.post_notification(
                        self.__nickname__ + 'SubscriptionDidEnd',
                        sender=self,
                        data=NotificationData(originator='local'))
        except TerminateSubscription as e:
            if not self.subscribed:
                command.signal(e)
            if self._subscription is not None:
                try:
                    self._subscription.end(timeout=2)
                except SIPCoreError:
                    pass
                else:
                    try:
                        while True:
                            notification = self._data_channel.wait()
                            if notification.name == 'SIPSubscriptionDidEnd':
                                break
                    except SIPSubscriptionDidFail:
                        pass
                finally:
                    notification_center.remove_observer(
                        self, sender=self._subscription)
                    notification_center.post_notification(
                        self.__nickname__ + 'SubscriptionDidEnd',
                        sender=self,
                        data=NotificationData(originator='local'))
        except SubscriptionError as e:

            def subscribe(e):
                if self.active:
                    self._command_channel.send(
                        Command('subscribe',
                                command.event,
                                refresh_interval=e.refresh_interval))
                self._subscription_timer = None

            self._subscription_timer = reactor.callLater(
                e.retry_after, subscribe, e)
            notification_center.post_notification(self.__nickname__ +
                                                  'SubscriptionDidFail',
                                                  sender=self)
        finally:
            self.subscribed = False
            self._subscription = None
            self._subscription_proc = None
    def _subscription_handler(self, command):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        subscription_uri = self.subscription_uri
        refresh_interval = command.refresh_interval or self.account.sip.subscribe_interval
        valid_transports = self.__transports__.intersection(settings.sip.transport_list)

        try:
            # Lookup routes
            if self.account.sip.outbound_proxy is not None and self.account.sip.outbound_proxy.transport in valid_transports:
                uri = SIPURI(host=self.account.sip.outbound_proxy.host, port=self.account.sip.outbound_proxy.port, parameters={'transport': self.account.sip.outbound_proxy.transport})
            elif self.account.sip.always_use_my_proxy:
                uri = SIPURI(host=self.account.id.domain)
            else:
                uri = SIPURI(host=subscription_uri.domain)
            lookup = DNSLookup()
            try:
                routes = lookup.lookup_sip_proxy(uri, valid_transports).wait()
            except DNSLookupError, e:
                raise SubscriptionError('DNS lookup failed: %s' % e, retry_after=random.uniform(15, 30))

            subscription_uri = SIPURI(user=subscription_uri.username, host=subscription_uri.domain)
            content = self.content

            timeout = time() + 30
            for route in routes:
                remaining_time = timeout - time()
                if remaining_time > 0:
                    try:
                        contact_uri = self.account.contact[NoGRUU, route]
                    except KeyError:
                        continue
                    subscription = Subscription(subscription_uri, FromHeader(self.account.uri, self.account.display_name),
                                                ToHeader(subscription_uri),
                                                ContactHeader(contact_uri),
                                                self.event,
                                                RouteHeader(route.uri),
                                                credentials=self.account.credentials,
                                                refresh=refresh_interval)
                    notification_center.add_observer(self, sender=subscription)
                    try:
                        subscription.subscribe(body=content.body, content_type=content.type, extra_headers=self.extra_headers, timeout=limit(remaining_time, min=1, max=5))
                    except SIPCoreError:
                        notification_center.remove_observer(self, sender=subscription)
                        raise SubscriptionError('Internal error', retry_after=5)
                    self._subscription = subscription
                    try:
                        while True:
                            notification = self._data_channel.wait()
                            if notification.name == 'SIPSubscriptionDidStart':
                                break
                    except SIPSubscriptionDidFail, e:
                        notification_center.remove_observer(self, sender=subscription)
                        self._subscription = None
                        if e.data.code == 407:
                            # Authentication failed, so retry the subscription in some time
                            raise SubscriptionError('Authentication failed', retry_after=random.uniform(60, 120))
                        elif e.data.code == 423:
                            # Get the value of the Min-Expires header
                            if e.data.min_expires is not None and e.data.min_expires > self.account.sip.subscribe_interval:
                                refresh_interval = e.data.min_expires
                            else:
                                refresh_interval = None
                            raise SubscriptionError('Interval too short', retry_after=random.uniform(60, 120), refresh_interval=refresh_interval)
                        elif e.data.code in (405, 406, 489):
                            raise SubscriptionError('Method or event not supported', retry_after=3600)
                        elif e.data.code == 1400:
                            raise SubscriptionError(e.data.reason, retry_after=3600)
                        else:
                            # Otherwise just try the next route
                            continue
                    else:
                        self.subscribed = True
                        command.signal()
                        break
Beispiel #22
0
    def _sip_subscription_handler(self, command):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        account = DefaultAccount()
        refresh_interval =  getattr(command, 'refresh_interval', None) or account.sip.subscribe_interval

        try:
            # Lookup routes
            if account.sip.outbound_proxy is not None:
                uri = SIPURI(host=account.sip.outbound_proxy.host,
                             port=account.sip.outbound_proxy.port,
                             parameters={'transport': account.sip.outbound_proxy.transport})
            else:
                uri = SIPURI(host=self.sip_identity.uri.as_sip_uri().host)
            lookup = DNSLookup()
            try:
                routes = lookup.lookup_sip_proxy(uri, settings.sip.transport_list).wait()
            except DNSLookupError, e:
                timeout = random.uniform(15, 30)
                raise SubscriptionError(error='DNS lookup failed: %s' % e, timeout=timeout)

            timeout = time() + 30
            for route in routes:
                remaining_time = timeout - time()
                if remaining_time > 0:
                    transport = route.transport
                    parameters = {} if transport=='udp' else {'transport': transport}
                    contact_uri = SIPURI(user=account.contact.username, host=SIPConfig.local_ip.normalized, port=getattr(Engine(), '%s_port' % transport), parameters=parameters)
                    subscription_uri = self.sip_identity.uri.as_sip_uri()
                    subscription = Subscription(subscription_uri, FromHeader(self.xmpp_identity.uri.as_sip_uri()),
                                                ToHeader(subscription_uri),
                                                ContactHeader(contact_uri),
                                                'presence',
                                                RouteHeader(route.uri),
                                                refresh=refresh_interval)
                    notification_center.add_observer(self, sender=subscription)
                    try:
                        subscription.subscribe(timeout=limit(remaining_time, min=1, max=5))
                    except SIPCoreError:
                        notification_center.remove_observer(self, sender=subscription)
                        raise SubscriptionError(error='Internal error', timeout=5)
                    self._sip_subscription = subscription
                    try:
                        while True:
                            notification = self._data_channel.wait()
                            if notification.sender is subscription and notification.name == 'SIPSubscriptionDidStart':
                                break
                    except SIPSubscriptionDidFail, e:
                        notification_center.remove_observer(self, sender=subscription)
                        self._sip_subscription = None
                        if e.data.code == 407:
                            # Authentication failed, so retry the subscription in some time
                            raise SubscriptionError(error='Authentication failed', timeout=random.uniform(60, 120))
                        elif e.data.code == 403:
                            # Forbidden
                            raise SubscriptionError(error='Forbidden', timeout=None, fatal=True)
                        elif e.data.code == 423:
                            # Get the value of the Min-Expires header
                            if e.data.min_expires is not None and e.data.min_expires > refresh_interval:
                                interval = e.data.min_expires
                            else:
                                interval = None
                            raise SubscriptionError(error='Interval too short', timeout=random.uniform(60, 120), refresh_interval=interval)
                        elif e.data.code in (405, 406, 489):
                            raise SubscriptionError(error='Method or event not supported', timeout=None, fatal=True)
                        elif e.data.code == 1400:
                            raise SubscriptionError(error=e.data.reason, timeout=None, fatal=True)
                        else:
                            # Otherwise just try the next route
                            continue
                    else:
                        self.subscribed = True
                        command.signal()
                        break
Beispiel #23
0
    def _run(self):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        sender_uri = self.sender.uri.as_sip_uri()
        recipient_uri = self.recipient.uri.as_sip_uri()
        participant_uri = self.participant.uri.as_sip_uri()

        try:
            # Lookup routes
            account = DefaultAccount()
            if account.sip.outbound_proxy is not None and account.sip.outbound_proxy.transport in settings.sip.transport_list:
                uri = SIPURI(host=account.sip.outbound_proxy.host,
                             port=account.sip.outbound_proxy.port,
                             parameters={
                                 'transport':
                                 account.sip.outbound_proxy.transport
                             })
            elif account.sip.always_use_my_proxy:
                uri = SIPURI(host=account.id.domain)
            else:
                uri = SIPURI.new(recipient_uri)
            lookup = DNSLookup()
            try:
                routes = lookup.lookup_sip_proxy(
                    uri, settings.sip.transport_list).wait()
            except DNSLookupError as e:
                raise ReferralError(error='DNS lookup failed: %s' % e)

            timeout = time() + 30
            for route in routes:
                self.route = route
                remaining_time = timeout - time()
                if remaining_time > 0:
                    transport = route.transport
                    parameters = {} if transport == 'udp' else {
                        'transport': transport
                    }
                    contact_uri = SIPURI(user=account.contact.username,
                                         host=SIPConfig.local_ip.normalized,
                                         port=getattr(Engine(),
                                                      '%s_port' % transport),
                                         parameters=parameters)
                    refer_to_header = ReferToHeader(str(participant_uri))
                    refer_to_header.parameters['method'] = 'INVITE'
                    referral = Referral(recipient_uri, FromHeader(sender_uri),
                                        ToHeader(recipient_uri),
                                        refer_to_header,
                                        ContactHeader(contact_uri),
                                        RouteHeader(route.uri),
                                        account.credentials)
                    notification_center.add_observer(self, sender=referral)
                    try:
                        referral.send_refer(
                            timeout=limit(remaining_time, min=1, max=5))
                    except SIPCoreError:
                        notification_center.remove_observer(self,
                                                            sender=referral)
                        timeout = 5
                        raise ReferralError(error='Internal error')
                    self._referral = referral
                    try:
                        while True:
                            notification = self._channel.wait()
                            if notification.name == 'SIPReferralDidStart':
                                break
                    except SIPReferralDidFail as e:
                        notification_center.remove_observer(self,
                                                            sender=referral)
                        self._referral = None
                        if e.data.code in (403, 405):
                            raise ReferralError(
                                error=sip_status_messages[e.data.code],
                                code=e.data.code)
                        else:
                            # Otherwise just try the next route
                            continue
                    else:
                        break
            else:
                self.route = None
                raise ReferralError(error='No more routes to try')
            # At this point it is subscribed. Handle notifications and ending/failures.
            try:
                self.active = True
                while True:
                    notification = self._channel.wait()
                    if notification.name == 'SIPReferralDidEnd':
                        break
            except SIPReferralDidFail as e:
                notification_center.remove_observer(self,
                                                    sender=self._referral)
                raise ReferralError(error=e.data.reason, code=e.data.code)
            else:
                notification_center.remove_observer(self,
                                                    sender=self._referral)
            finally:
                self.active = False
        except ReferralError as e:
            self._failure = MucInvitationFailure(e.code, e.error)
        finally:
            notification_center.remove_observer(
                self, name='NetworkConditionsDidChange')
            self._referral = None
            if self._failure is not None:
                notification_center.post_notification(
                    'X2SMucInvitationHandlerDidFail',
                    sender=self,
                    data=NotificationData(failure=self._failure))
            else:
                notification_center.post_notification(
                    'X2SMucInvitationHandlerDidEnd', sender=self)