def _NH_BlinkFileTransferDidComputeHash(self, sender, data):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        self.stream = FileTransferStream(self.file_selector, 'sendonly')
        self.session = Session(self.account)

        notification_center.add_observer(self, sender=self.session)
        notification_center.add_observer(self, sender=self.stream)

        self.status = "Offering File..."
        self.ft_info.status = "proposing"

        self.log_info(u"Initiating DNS Lookup of %s to %s" % (self.account, self.target_uri))
        lookup = DNSLookup()
        notification_center.add_observer(self, sender=lookup)

        if isinstance(self.account, Account) and 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})
            self.log_info(u"Initiating DNS Lookup for SIP routes of %s (through proxy %s)" % (self.target_uri, uri))
        elif isinstance(self.account, Account) and self.account.sip.always_use_my_proxy:
            uri = SIPURI(host=self.account.id.domain)
            self.log_info(u"Initiating DNS Lookup for SIP routes of %s (through account %s proxy)" % (self.target_uri, self.account.id))
        else:
            uri = self.target_uri
            self.log_info(u"Initiating DNS Lookup for SIP routes of %s" % self.target_uri)
        notification_center.post_notification("BlinkFileTransferInitiated", self)
        lookup.lookup_sip_proxy(uri, settings.sip.transport_list)
示例#2
0
文件: im.py 项目: madhawa/sylkserver
 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])
示例#3
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)
示例#4
0
    def initialize(self, session, direction):
        with self._lock:
            if self.state != "NULL":
                raise RuntimeError("%sStream.initialize() may only be called in the NULL state" % self.type.capitalize())
            self.state = "INITIALIZING"
            self.session = session
            local_encryption_policy = session.account.rtp.encryption.key_negotiation if session.account.rtp.encryption.enabled else None
            if hasattr(self, "_incoming_remote_sdp"):
                # ICE attributes could come at the session level or at the media level
                remote_stream = self._incoming_remote_sdp.media[self._incoming_stream_index]
                self._try_ice = self.session.account.nat_traversal.use_ice and ((remote_stream.has_ice_attributes or self._incoming_remote_sdp.has_ice_attributes) and remote_stream.has_ice_candidates)
                if self._incoming_stream_encryption is not None and local_encryption_policy == 'opportunistic':
                    self._srtp_encryption = self._incoming_stream_encryption
                else:
                    self._srtp_encryption = 'zrtp' if local_encryption_policy == 'opportunistic' else local_encryption_policy
                del self._incoming_stream_encryption
            else:
                self._try_ice = self.session.account.nat_traversal.use_ice
                self._srtp_encryption = 'zrtp' if local_encryption_policy == 'opportunistic' else local_encryption_policy

            if self._try_ice:
                if self.session.account.nat_traversal.stun_server_list:
                    stun_servers = list((server.host, server.port) for server in self.session.account.nat_traversal.stun_server_list)
                    self._init_rtp_transport(stun_servers)
                elif not isinstance(self.session.account, BonjourAccount):
                    dns_lookup = DNSLookup()
                    self.notification_center.add_observer(self, sender=dns_lookup)
                    dns_lookup.lookup_service(SIPURI(self.session.account.id.domain), "stun")
            else:
                self._init_rtp_transport()
示例#5
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)
示例#6
0
    def lookup_destination(self, target_uri):
        assert isinstance(target_uri, SIPURI)

        lookup = DNSLookup()
        self.notification_center.add_observer(self, sender=lookup)
        settings = SIPSimpleSettings()

        if isinstance(self.account,
                      Account) and 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
                         })
            self.log_info(u"Starting DNS lookup for %s through proxy %s" %
                          (target_uri.host, uri))
        elif isinstance(self.account,
                        Account) and self.account.sip.always_use_my_proxy:
            uri = SIPURI(host=self.account.id.domain)
            self.log_info(
                u"Starting DNS lookup for %s via proxy of account %s" %
                (target_uri.host, self.account.id))
        else:
            uri = target_uri
            self.log_info(u"Starting DNS lookup for %s" % target_uri.host)
        lookup.lookup_sip_proxy(uri, settings.sip.transport_list)
示例#7
0
    def _CH_register(self, command):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        if self._registration_timer is not None and self._registration_timer.active():
            self._registration_timer.cancel()
        self._registration_timer = None

        # Initialize the registration
        if self._registration is None:
            duration = command.refresh_interval or self.account.sip.register_interval
            self._registration = Registration(FromHeader(self.account.uri, self.account.display_name), credentials=self.account.credentials, duration=duration, extra_headers=[Header('Supported', 'gruu')])
            notification_center.add_observer(self, sender=self._registration)
            notification_center.post_notification('SIPAccountWillRegister', sender=self.account)
        else:
            notification_center.post_notification('SIPAccountRegistrationWillRefresh', sender=self.account)

        try:
            # Lookup routes
            if self.account.sip.outbound_proxy is not None and self.account.sip.outbound_proxy.transport in settings.sip.transport_list:
                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()
            try:
                routes = lookup.lookup_sip_proxy(uri, settings.sip.transport_list).wait()
            except DNSLookupError, e:
                retry_after = random.uniform(self._dns_wait, 2*self._dns_wait)
                self._dns_wait = limit(2*self._dns_wait, max=30)
                raise RegistrationError('DNS lookup failed: %s' % e, retry_after=retry_after)
            else:
示例#8
0
 def start(self):
     if not self.refer_to_uri.startswith(('sip:', 'sips:')):
         self.refer_to_uri = 'sip:%s' % self.refer_to_uri
     try:
         self.refer_to_uri = SIPURI.parse(self.refer_to_uri)
     except SIPCoreError:
         log.msg('Room %s - failed to add %s' % (self.room_uri_str, self.refer_to_uri))
         self._refer_request.reject(488)
         return
     notification_center = NotificationCenter()
     notification_center.add_observer(self, sender=self._refer_request)
     if self.method == 'INVITE':
         self._refer_request.accept()
         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.refer_to_uri
         lookup = DNSLookup()
         notification_center.add_observer(self, sender=lookup)
         lookup.lookup_sip_proxy(uri, settings.sip.transport_list)
     elif self.method == 'BYE':
         log.msg('Room %s - %s removed %s from the room' % (self.room_uri_str, self._refer_headers.get('From').uri, self.refer_to_uri))
         self._refer_request.accept()
         conference_application = ConferenceApplication()
         conference_application.remove_participant(self.refer_to_uri, self.room_uri)
         self._refer_request.end(200)
     else:
         self._refer_request.reject(488)
示例#9
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])
示例#10
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)
示例#11
0
    def start(self, restart=False):
        notification_center = NotificationCenter()
        file_path = self._file_selector.name.decode() if isinstance(
            self._file_selector.name, bytes) else self._file_selector.name

        self.ft_info = FileTransferInfo(
            transfer_id=str(uuid.uuid4()),
            direction='outgoing',
            file_size=self._file_selector.size,
            local_uri=format_identity_to_string(self.account)
            if self.account is not BonjourAccount() else 'bonjour.local',
            remote_uri=self.remote_identity,
            file_path=file_path)

        self.status = NSLocalizedString("Offering File...", "Label")
        self.ft_info.status = "proposing"

        self.log_info("Initiating DNS Lookup of %s to %s" %
                      (self.account, self.target_uri))
        lookup = DNSLookup()
        notification_center.add_observer(self, sender=lookup)

        if isinstance(self.account,
                      Account) and 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
                         })
            self.log_info("Initiating DNS Lookup for %s (through proxy %s)" %
                          (self.target_uri, uri))
        elif isinstance(self.account,
                        Account) and self.account.sip.always_use_my_proxy:
            uri = SIPURI(host=self.account.id.domain)
            self.log_info(
                "Initiating DNS Lookup for %s (through account %s proxy)" %
                (self.target_uri, self.account.id))
        else:
            uri = self.target_uri
            self.log_info("Initiating DNS Lookup for %s" % self.target_uri)

        settings = SIPSimpleSettings()

        tls_name = None
        if isinstance(self.account, Account):
            tls_name = self.account.sip.tls_name or self.account.id.domain

        lookup.lookup_sip_proxy(uri,
                                settings.sip.transport_list,
                                tls_name=tls_name)

        if restart:
            notification_center.post_notification(
                "BlinkFileTransferWillRestart", self)
        else:
            notification_center.post_notification(
                "BlinkFileTransferNewOutgoing", sender=self)
示例#12
0
    def _CH_publish(self, command):
        if command.state is None or self._publication is None and command.state is SameState:
            command.signal()
            return

        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        if self._publication_timer is not None and self._publication_timer.active(
        ):
            self._publication_timer.cancel()
        self._publication_timer = None

        if self._publication is None:
            duration = command.refresh_interval or self.account.sip.publish_interval
            from_header = FromHeader(self.account.uri,
                                     self.account.display_name)
            self._publication = Publication(
                from_header,
                self.event,
                self.payload_type.content_type,
                credentials=self.account.credentials,
                duration=duration,
                extra_headers=self.extra_headers)
            notification_center.add_observer(self, sender=self._publication)
            notification_center.post_notification(
                self.__class__.__name__ + 'WillPublish',
                sender=self,
                data=NotificationData(state=command.state, duration=duration))
        else:
            notification_center.post_notification(
                self.__class__.__name__ + 'WillRefresh',
                sender=self,
                data=NotificationData(state=command.state))

        try:
            # Lookup routes
            valid_transports = self.__transports__.intersection(
                settings.sip.transport_list)
            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
                             })
            else:
                uri = SIPURI(host=self.account.id.domain)
            lookup = DNSLookup()
            try:
                routes = lookup.lookup_sip_proxy(uri, valid_transports).wait()
            except DNSLookupError, e:
                retry_after = random.uniform(self._dns_wait,
                                             2 * self._dns_wait)
                self._dns_wait = limit(2 * self._dns_wait, max=30)
                raise PublicationError('DNS lookup failed: %s' % e,
                                       retry_after=retry_after)
            else:
示例#13
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)
 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()
示例#15
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()
示例#16
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)
示例#17
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)
示例#18
0
    def _NH_BlinkFileTransferDidComputeHash(self, sender, data):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        self.stream = FileTransferStream(self.account, self.file_selector,
                                         'sendonly')
        self.session = Session(self.account)

        notification_center.add_observer(self, sender=self.session)
        notification_center.add_observer(self, sender=self.stream)

        self.status = "Offering File..."
        self.ft_info.status = "proposing"

        BlinkLogger().log_info(u"Initiating DNS Lookup of %s to %s" %
                               (self.account, self.target_uri))
        lookup = DNSLookup()
        notification_center.add_observer(self, sender=lookup)

        if isinstance(self.account,
                      Account) and 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
                         })
            BlinkLogger().log_info(
                u"Initiating DNS Lookup for SIP routes of %s (through proxy %s)"
                % (self.target_uri, uri))
        elif isinstance(self.account,
                        Account) and self.account.sip.always_use_my_proxy:
            uri = SIPURI(host=self.account.id.domain)
            BlinkLogger().log_info(
                u"Initiating DNS Lookup for SIP routes of %s (through account %s proxy)"
                % (self.target_uri, self.account.id))
        else:
            uri = self.target_uri
            BlinkLogger().log_info(
                u"Initiating DNS Lookup for SIP routes of %s" %
                self.target_uri)
        notification_center.post_notification(
            "BlinkFileTransferInitiated",
            self,
            data=TimestampedNotificationData())
        lookup.lookup_sip_proxy(uri, settings.sip.transport_list)
示例#19
0
    def initialize(self, session, direction):
        with self._lock:
            if self.state != "NULL":
                raise RuntimeError(
                    "%sStream.initialize() may only be called in the NULL state"
                    % self.type.capitalize())
            self.state = "INITIALIZING"
            self.session = session
            local_encryption_policy = session.account.rtp.encryption.key_negotiation if session.account.rtp.encryption.enabled else None
            if hasattr(self, "_incoming_remote_sdp") and hasattr(
                    self, '_incoming_stream_index'):
                # ICE attributes could come at the session level or at the media level
                remote_stream = self._incoming_remote_sdp.media[
                    self._incoming_stream_index]
                self._try_ice = self.session.account.nat_traversal.use_ice and (
                    (remote_stream.has_ice_attributes
                     or self._incoming_remote_sdp.has_ice_attributes)
                    and remote_stream.has_ice_candidates)
                if "zrtp-hash" in remote_stream.attributes:
                    incoming_stream_encryption = 'zrtp'
                elif "crypto" in remote_stream.attributes:
                    incoming_stream_encryption = 'sdes_mandatory' if remote_stream.transport == 'RTP/SAVP' else 'sdes_optional'
                else:
                    incoming_stream_encryption = None
                if incoming_stream_encryption is not None and local_encryption_policy == 'opportunistic':
                    self._srtp_encryption = incoming_stream_encryption
                else:
                    self._srtp_encryption = 'zrtp' if local_encryption_policy == 'opportunistic' else local_encryption_policy
            else:
                self._try_ice = self.session.account.nat_traversal.use_ice
                self._srtp_encryption = 'zrtp' if local_encryption_policy == 'opportunistic' else local_encryption_policy

            if self._try_ice:
                if self.session.account.nat_traversal.stun_server_list:
                    stun_servers = list(
                        (server.host, server.port) for server in
                        self.session.account.nat_traversal.stun_server_list)
                    self._init_rtp_transport(stun_servers)
                elif not isinstance(self.session.account, BonjourAccount):
                    dns_lookup = DNSLookup()
                    self.notification_center.add_observer(self,
                                                          sender=dns_lookup)
                    dns_lookup.lookup_service(
                        SIPURI(self.session.account.id.domain), "stun")
            else:
                self._init_rtp_transport()
    def _CH_register(self, command):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        if self._registration_timer is not None and self._registration_timer.active(
        ):
            self._registration_timer.cancel()
        self._registration_timer = None

        # Initialize the registration
        if self._registration is None:
            duration = command.refresh_interval or self.account.sip.register_interval
            self._registration = Registration(
                FromHeader(self.account.uri, self.account.display_name),
                credentials=self.account.credentials,
                duration=duration,
                extra_headers=[Header('Supported', 'gruu')])
            notification_center.add_observer(self, sender=self._registration)
            notification_center.post_notification('SIPAccountWillRegister',
                                                  sender=self.account)
        else:
            notification_center.post_notification(
                'SIPAccountRegistrationWillRefresh', sender=self.account)

        try:
            # Lookup routes
            if self.account.sip.outbound_proxy is not None and self.account.sip.outbound_proxy.transport in settings.sip.transport_list:
                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()
            try:
                routes = lookup.lookup_sip_proxy(
                    uri, settings.sip.transport_list).wait()
            except DNSLookupError, e:
                retry_after = random.uniform(self._dns_wait,
                                             2 * self._dns_wait)
                self._dns_wait = limit(2 * self._dns_wait, max=30)
                raise RegistrationError('DNS lookup failed: %s' % e,
                                        retry_after=retry_after)
            else:
示例#21
0
 def connect(self):
     self.offer_in_progress = True
     account = self.session.account
     settings = SIPSimpleSettings()
     if isinstance(account, Account):
         if account.sip.outbound_proxy is not None:
             proxy = account.sip.outbound_proxy
             uri = SIPURI(host=proxy.host, port=proxy.port, parameters={'transport': proxy.transport})
         elif account.sip.always_use_my_proxy:
             uri = SIPURI(host=account.id.domain)
         else:
             uri = self.uri
     else:
         uri = self.uri
     self.status = u'Looking up destination'
     lookup = DNSLookup()
     self.notification_center.add_observer(self, sender=lookup)
     lookup.lookup_sip_proxy(uri, settings.sip.transport_list)
示例#22
0
    def lookup_destination(self, target_uri):
        assert isinstance(target_uri, SIPURI)

        lookup = DNSLookup()
        self.notification_center.add_observer(self, sender=lookup)
        settings = SIPSimpleSettings()

        if isinstance(self.account, Account) and 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})
            self.log_info(u"Starting DNS lookup for %s through proxy %s" % (target_uri.host, uri))
        elif isinstance(self.account, Account) and self.account.sip.always_use_my_proxy:
            uri = SIPURI(host=self.account.id.domain)
            self.log_info(u"Starting DNS lookup for %s via proxy of account %s" % (target_uri.host, self.account.id))
        else:
            uri = target_uri
            self.log_info(u"Starting DNS lookup for %s" % target_uri.host)
        lookup.lookup_sip_proxy(uri, settings.sip.transport_list)
    def start(self):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        download_folder = unicodedata.normalize('NFC', NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory, NSUserDomainMask, True)[0])
        for name in self.filename_generator(os.path.join(download_folder, self.file_name)):
            if not os.path.exists(name) and not os.path.exists(name+".download"):
                self.file_path = name + '.download'
                break

        self.log_info(u"File will be written to %s" % self.file_path)
        self.file_selector.fd = open(self.file_path, "w+")

        self.ft_info = FileTransferInfo(transfer_id=self.transfer_id, direction='incoming', local_uri=format_identity_to_string(self.account) if self.account is not BonjourAccount() else 'bonjour' , file_size=self.file_size, remote_uri=self.remote_identity, file_path=self.file_path)

        self.log_info("Pull File Transfer Request started %s" % self.file_path)

        self.stream = FileTransferStream(self.file_selector, 'recvonly')
        self.session = Session(self.account)

        notification_center.add_observer(self, sender=self)
        notification_center.add_observer(self, sender=self.session)
        notification_center.add_observer(self, sender=self.stream)

        self.status = "Requesting File..."
        self.ft_info.status = "requesting"

        self.log_info(u"Initiating DNS Lookup of %s to %s" % (self.account, self.target_uri))
        lookup = DNSLookup()
        notification_center.add_observer(self, sender=lookup)

        if isinstance(self.account, Account) and 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})
            self.log_info(u"Initiating DNS Lookup for SIP routes of %s (through proxy %s)" % (self.target_uri, uri))
        elif isinstance(self.account, Account) and self.account.sip.always_use_my_proxy:
            uri = SIPURI(host=self.account.id.domain)
            self.log_info(u"Initiating DNS Lookup for SIP routes of %s (through account %s proxy)" % (self.target_uri, self.account.id))
        else:
            uri = self.target_uri
            self.log_info(u"Initiating DNS Lookup for SIP routes of %s" % self.target_uri)
        notification_center.post_notification("BlinkFileTransferInitializing", self)
        notification_center.post_notification("BlinkFileTransferInitiated", self)
        lookup.lookup_sip_proxy(uri, settings.sip.transport_list)
示例#24
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)
示例#25
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)
示例#26
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)
示例#27
0
    def _lookup(self):
        settings = SIPSimpleSettings()
        if isinstance(self.account, Account):
            if self.account.sip.outbound_proxy is not None:
                proxy = self.account.sip.outbound_proxy
                uri = SIPURI(host=proxy.host,
                             port=proxy.port,
                             parameters={'transport': proxy.transport})
            elif self.account.sip.always_use_my_proxy:
                uri = SIPURI(host=self.account.id.domain)
            else:
                uri = self.sip_uri
        else:
            uri = self.sip_uri

        self.lookup = DNSLookup()
        notification_center = NotificationCenter()
        notification_center.add_observer(self, sender=self.lookup)
        self.lookup.lookup_sip_proxy(uri,
                                     settings.sip.transport_list,
                                     tls_name=self.account.sip.tls_name
                                     or uri.host)
示例#28
0
文件: im.py 项目: madhawa/sylkserver
 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):
             request = SIPMessageRequest(from_header, to_header, route_header, self.content_type, self.body)
             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)
示例#29
0
    def _CH_publish(self, command):
        if command.state is None or self._publication is None and command.state is SameState:
            command.signal()
            return

        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        if self._publication_timer is not None and self._publication_timer.active():
            self._publication_timer.cancel()
        self._publication_timer = None

        if self._publication is None:
            duration = command.refresh_interval or self.account.sip.publish_interval
            from_header = FromHeader(self.account.uri, self.account.display_name)
            self._publication = Publication(from_header, self.event, self.payload_type.content_type, credentials=self.account.credentials, duration=duration, extra_headers=self.extra_headers)
            notification_center.add_observer(self, sender=self._publication)
            notification_center.post_notification(self.__class__.__name__ + 'WillPublish', sender=self, data=NotificationData(state=command.state, duration=duration))
        else:
            notification_center.post_notification(self.__class__.__name__ + 'WillRefresh', sender=self, data=NotificationData(state=command.state))

        try:
            # Lookup routes
            valid_transports = self.__transports__.intersection(settings.sip.transport_list)
            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})
            else:
                uri = SIPURI(host=self.account.id.domain)
            lookup = DNSLookup()
            try:
                routes = lookup.lookup_sip_proxy(uri, valid_transports).wait()
            except DNSLookupError, e:
                retry_after = random.uniform(self._dns_wait, 2*self._dns_wait)
                self._dns_wait = limit(2*self._dns_wait, max=30)
                raise PublicationError('DNS lookup failed: %s' % e, retry_after=retry_after)
            else:
示例#30
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
示例#31
0
 def start(self):
     lookup = DNSLookup()
     NotificationCenter().add_observer(self, sender=lookup)
     from sipwping.app import SIPOptionsApplication
     lookup.lookup_sip_proxy(self.target_uri, SIPOptionsApplication().supported_transports)
示例#32
0
    def _CH_register(self, command):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        if self._registration_timer is not None and self._registration_timer.active(
        ):
            self._registration_timer.cancel()
        self._registration_timer = None

        # Initialize the registration
        if self._registration is None:
            duration = command.refresh_interval or self.account.sip.register_interval
            self._registration = Registration(
                FromHeader(self.account.uri, self.account.display_name),
                credentials=self.account.credentials,
                duration=duration,
                extra_headers=[Header('Supported', 'gruu')])
            notification_center.add_observer(self, sender=self._registration)
            notification_center.post_notification('SIPAccountWillRegister',
                                                  sender=self.account)
        else:
            notification_center.post_notification(
                'SIPAccountRegistrationWillRefresh', sender=self.account)

        try:
            # Lookup routes
            if self.account.sip.outbound_proxy is not None and self.account.sip.outbound_proxy.transport in settings.sip.transport_list:
                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()
            try:
                routes = lookup.lookup_sip_proxy(
                    uri, settings.sip.transport_list).wait()
            except DNSLookupError as e:
                retry_after = random.uniform(self._dns_wait,
                                             2 * self._dns_wait)
                self._dns_wait = limit(2 * self._dns_wait, max=30)
                raise RegistrationError('DNS lookup failed: %s' % e,
                                        retry_after=retry_after)
            else:
                self._dns_wait = 1

            # Register by trying each route in turn
            register_timeout = time() + 30
            for route in routes:
                remaining_time = register_timeout - time()
                if remaining_time > 0:
                    try:
                        contact_uri = self.account.contact[NoGRUU, route]
                    except KeyError:
                        continue
                    contact_header = ContactHeader(contact_uri)
                    contact_header.parameters[
                        '+sip.instance'] = '"<%s>"' % settings.instance_id
                    if self.account.nat_traversal.use_ice:
                        contact_header.parameters['+sip.ice'] = None
                    route_header = RouteHeader(route.uri)
                    try:
                        self._registration.register(contact_header,
                                                    route_header,
                                                    timeout=limit(
                                                        remaining_time,
                                                        min=1,
                                                        max=10))
                    except SIPCoreError:
                        raise RegistrationError('Internal error',
                                                retry_after=5)
                    try:
                        while True:
                            notification = self._data_channel.wait()
                            if notification.name == 'SIPRegistrationDidSucceed':
                                break
                            if notification.name == 'SIPRegistrationDidEnd':
                                raise RegistrationError(
                                    'Registration expired', retry_after=0
                                )  # registration expired while we were trying to re-register
                    except SIPRegistrationDidFail as e:
                        notification_data = NotificationData(
                            code=e.data.code,
                            reason=e.data.reason,
                            registration=self._registration,
                            registrar=route)
                        notification_center.post_notification(
                            'SIPAccountRegistrationGotAnswer',
                            sender=self.account,
                            data=notification_data)
                        if e.data.code == 401:
                            # Authentication failed, so retry the registration in some time
                            raise RegistrationError('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.register_interval:
                                refresh_interval = e.data.min_expires
                            else:
                                refresh_interval = None
                            raise RegistrationError(
                                'Interval too short',
                                retry_after=random.uniform(60, 120),
                                refresh_interval=refresh_interval)
                        else:
                            # Otherwise just try the next route
                            continue
                    else:
                        notification_data = NotificationData(
                            code=notification.data.code,
                            reason=notification.data.reason,
                            registration=self._registration,
                            registrar=route)
                        notification_center.post_notification(
                            'SIPAccountRegistrationGotAnswer',
                            sender=self.account,
                            data=notification_data)
                        self.registered = True
                        # Save GRUU
                        try:
                            header = next(
                                header for header in
                                notification.data.contact_header_list
                                if header.parameters.get('+sip.instance', '').
                                strip('"<>') == settings.instance_id)
                        except StopIteration:
                            self.account.contact.public_gruu = None
                            self.account.contact.temporary_gruu = None
                        else:
                            public_gruu = header.parameters.get(
                                'pub-gruu', None)
                            temporary_gruu = header.parameters.get(
                                'temp-gruu', None)
                            try:
                                self.account.contact.public_gruu = SIPURI.parse(
                                    public_gruu.strip('"'))
                            except (AttributeError, SIPCoreError):
                                self.account.contact.public_gruu = None
                            try:
                                self.account.contact.temporary_gruu = SIPURI.parse(
                                    temporary_gruu.strip('"'))
                            except (AttributeError, SIPCoreError):
                                self.account.contact.temporary_gruu = None
                        notification_data = NotificationData(
                            contact_header=notification.data.contact_header,
                            contact_header_list=notification.data.
                            contact_header_list,
                            expires=notification.data.expires_in,
                            registrar=route)
                        notification_center.post_notification(
                            'SIPAccountRegistrationDidSucceed',
                            sender=self.account,
                            data=notification_data)
                        self._register_wait = 1
                        command.signal()
                        break
            else:
                # There are no more routes to try, reschedule the registration
                retry_after = random.uniform(self._register_wait,
                                             2 * self._register_wait)
                self._register_wait = limit(self._register_wait * 2, max=30)
                raise RegistrationError('No more routes to try',
                                        retry_after=retry_after)
        except RegistrationError as e:
            self.registered = False
            notification_center.remove_observer(self,
                                                sender=self._registration)
            notification_center.post_notification(
                'SIPAccountRegistrationDidFail',
                sender=self.account,
                data=NotificationData(error=e.error,
                                      retry_after=e.retry_after))

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

            self._registration_timer = reactor.callLater(
                e.retry_after, register)
            self._registration = None
            self.account.contact.public_gruu = None
            self.account.contact.temporary_gruu = None
示例#33
0
class OutgoingMessage(object):
    __ignored_content_types__ = {
        IsComposingDocument.content_type, IMDNDocument.content_type
    }  # Content types to ignore in notifications
    __disabled_imdn_content_types__ = {
        'text/pgp-public-key', 'text/pgp-private-key'
    }.union(
        __ignored_content_types__)  # Content types to ignore in notifications

    def __init__(self,
                 account,
                 contact,
                 content,
                 content_type='text/plain',
                 recipients=None,
                 courtesy_recipients=None,
                 subject=None,
                 timestamp=None,
                 required=None,
                 additional_headers=None,
                 id=None):
        self.lookup = None
        self.account = account
        self.uri = contact.uri.uri
        self.content_type = content_type
        self.content = content
        self.id = id if id is not None else str(uuid.uuid4())
        self.timestamp = timestamp if timestamp is not None else ISOTimestamp.now(
        )
        self.sip_uri = SIPURI.parse('sip:%s' % self.uri)

    @property
    def message(self):
        return BlinkMessage(self.content,
                            self.content_type,
                            self.account,
                            timestamp=self.timestamp,
                            id=self.id)

    def _lookup(self):
        settings = SIPSimpleSettings()
        if isinstance(self.account, Account):
            if self.account.sip.outbound_proxy is not None:
                proxy = self.account.sip.outbound_proxy
                uri = SIPURI(host=proxy.host,
                             port=proxy.port,
                             parameters={'transport': proxy.transport})
            elif self.account.sip.always_use_my_proxy:
                uri = SIPURI(host=self.account.id.domain)
            else:
                uri = self.sip_uri
        else:
            uri = self.sip_uri

        self.lookup = DNSLookup()
        notification_center = NotificationCenter()
        notification_center.add_observer(self, sender=self.lookup)
        self.lookup.lookup_sip_proxy(uri,
                                     settings.sip.transport_list,
                                     tls_name=self.account.sip.tls_name
                                     or uri.host)

    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
            # TODO

    def send(self, session):
        self.session = session
        if self.content_type.lower(
        ) not in self.__disabled_imdn_content_types__:
            notification_center = NotificationCenter()
            notification_center.post_notification('BlinkMessageIsPending',
                                                  sender=self.session,
                                                  data=NotificationData(
                                                      message=self.message,
                                                      id=self.id))
        if self.session.routes:
            self._send()
        else:
            self._lookup()

    @run_in_gui_thread
    def handle_notification(self, notification):
        handler = getattr(self, '_NH_%s' % notification.name, Null)
        handler(notification)

    def _NH_DNSLookupDidSucceed(self, notification):
        notification.center.remove_observer(self, sender=notification.sender)
        if notification.sender is self.lookup:
            routes = notification.data.result
            self.session.routes = routes
            self._send()

    def _NH_DNSLookupDidFail(self, notification):
        notification.center.remove_observer(self, sender=notification.sender)
        if self.content_type.lower() == IsComposingDocument.content_type:
            return

        notification_center = NotificationCenter()
        notification_center.post_notification(
            'BlinkMessageDidFail',
            sender=self.session,
            data=NotificationData(data=NotificationData(
                code=404, reason=notification.data.error),
                                  id=self.id))

    def _NH_SIPMessageDidSucceed(self, notification):
        notification_center = NotificationCenter()
        if self.content_type.lower() in self.__ignored_content_types__:
            if self.content_type.lower() == IMDNDocument.content_type:
                document = IMDNDocument.parse(self.content)
                imdn_message_id = document.message_id.value
                imdn_status = document.notification.status.__str__()
                notification_center.post_notification(
                    'BlinkDidSendDispositionNotification',
                    sender=self.session,
                    data=NotificationData(id=imdn_message_id,
                                          status=imdn_status))
            return

        notification_center.post_notification('BlinkMessageDidSucceed',
                                              sender=self.session,
                                              data=NotificationData(
                                                  data=notification.data,
                                                  id=self.id))

    def _NH_SIPMessageDidFail(self, notification):
        if self.content_type.lower() in self.__ignored_content_types__:
            return

        notification_center = NotificationCenter()
        notification_center.post_notification('BlinkMessageDidFail',
                                              sender=self.session,
                                              data=NotificationData(
                                                  data=notification.data,
                                                  id=self.id))
示例#34
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
示例#35
0
    def start(self):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        download_folder = unicodedata.normalize(
            'NFC',
            NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory,
                                                NSUserDomainMask, True)[0])
        for name in self.filename_generator(
                os.path.join(download_folder, self.file_name)):
            if not os.path.exists(name) and not os.path.exists(name +
                                                               ".download"):
                self.file_path = name + '.download'
                break

        BlinkLogger().log_info(u"File will be written to %s" % self.file_path)
        self.file_selector.fd = open(self.file_path, "w+")

        self.ft_info = FileTransferInfo(
            transfer_id=self.transfer_id,
            direction='incoming',
            local_uri=format_identity_to_string(self.account)
            if self.account is not BonjourAccount() else 'bonjour',
            file_size=self.file_size,
            remote_uri=self.remote_identity,
            file_path=self.file_path)

        BlinkLogger().log_info("Pull File Transfer Request started %s" %
                               self.file_path)

        self.stream = FileTransferStream(self.account, self.file_selector,
                                         'recvonly')
        self.session = Session(self.account)

        notification_center.add_observer(self, sender=self)
        notification_center.add_observer(self, sender=self.session)
        notification_center.add_observer(self, sender=self.stream)

        self.status = "Requesting File..."
        self.ft_info.status = "requesting"

        BlinkLogger().log_info(u"Initiating DNS Lookup of %s to %s" %
                               (self.account, self.target_uri))
        lookup = DNSLookup()
        notification_center.add_observer(self, sender=lookup)

        if isinstance(self.account,
                      Account) and 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
                         })
            BlinkLogger().log_info(
                u"Initiating DNS Lookup for SIP routes of %s (through proxy %s)"
                % (self.target_uri, uri))
        elif isinstance(self.account,
                        Account) and self.account.sip.always_use_my_proxy:
            uri = SIPURI(host=self.account.id.domain)
            BlinkLogger().log_info(
                u"Initiating DNS Lookup for SIP routes of %s (through account %s proxy)"
                % (self.target_uri, self.account.id))
        else:
            uri = self.target_uri
            BlinkLogger().log_info(
                u"Initiating DNS Lookup for SIP routes of %s" %
                self.target_uri)
        notification_center.post_notification(
            "BlinkFileTransferInitializing",
            self,
            data=TimestampedNotificationData())
        notification_center.post_notification(
            "BlinkFileTransferInitiated",
            self,
            data=TimestampedNotificationData())
        lookup.lookup_sip_proxy(uri, settings.sip.transport_list)
示例#36
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)
示例#37
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:
            # 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
示例#38
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:
            # 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
示例#39
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
示例#40
0
    def _CH_publish(self, command):
        if command.state is None or self._publication is None and command.state is SameState:
            command.signal()
            return

        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        if self._publication_timer is not None and self._publication_timer.active():
            self._publication_timer.cancel()
        self._publication_timer = None

        if self._publication is None:
            duration = command.refresh_interval or self.account.sip.publish_interval
            from_header = FromHeader(self.account.uri, self.account.display_name)
            self._publication = Publication(from_header, self.event, self.payload_type.content_type, credentials=self.account.credentials, duration=duration, extra_headers=self.extra_headers)
            notification_center.add_observer(self, sender=self._publication)
            notification_center.post_notification(self.__class__.__name__ + 'WillPublish', sender=self, data=NotificationData(state=command.state, duration=duration))
        else:
            notification_center.post_notification(self.__class__.__name__ + 'WillRefresh', sender=self, data=NotificationData(state=command.state))

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

            # Lookup routes
            valid_transports = self.__transports__.intersection(settings.sip.transport_list)
            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})
            else:
                uri = SIPURI(host=self.account.id.domain)

            lookup = DNSLookup()
            try:
                routes = lookup.lookup_sip_proxy(uri, valid_transports, tls_name=self.account.sip.tls_name).wait()
            except DNSLookupError as e:
                retry_after = random.uniform(self._dns_wait, 2*self._dns_wait)
                self._dns_wait = limit(2*self._dns_wait, max=30)
                raise PublicationError('DNS lookup failed: %s' % e, retry_after=retry_after)
            else:
                self._dns_wait = 1

            body = None if command.state is SameState else command.state.toxml()

            # Publish by trying each route in turn
            publish_timeout = time() + 30
            for route in routes:
                if Host.default_ip is None:
                    raise PublicationError('No IP address', retry_after=60)

                remaining_time = publish_timeout-time()
                if remaining_time > 0:
                    try:
                        try:
                            self._publication.publish(body, RouteHeader(route.uri), timeout=limit(remaining_time, min=1, max=10))
                        except ValueError as e:  # this happens for an initial PUBLISH with body=None
                            raise PublicationError(str(e), retry_after=0)
                        except PublicationETagError:
                            state = self.state # access self.state only once to avoid race conditions
                            if state is not None:
                                self._publication.publish(state.toxml(), RouteHeader(route.uri), timeout=limit(remaining_time, min=1, max=10))
                            else:
                                command.signal()
                                return
                    except SIPCoreError:
                        raise PublicationError('Internal error', retry_after=5)

                    try:
                        while True:
                            notification = self._data_channel.wait()
                            if notification.name == 'SIPPublicationDidSucceed':
                                break
                            if notification.name == 'SIPPublicationDidEnd':
                                raise PublicationError('Publication expired', retry_after=random.uniform(60, 120))  # publication expired while we were trying to re-publish
                    except SIPPublicationDidFail as e:
                        if e.data.code == 407:
                            # Authentication failed, so retry the publication in some time
                            raise PublicationError('Authentication failed', retry_after=random.uniform(60, 120))
                        elif e.data.code == 412:
                            raise PublicationError('Conditional request failed', retry_after=0)
                        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.publish_interval:
                                refresh_interval = e.data.min_expires
                            else:
                                refresh_interval = None
                            raise PublicationError('Interval too short', retry_after=random.uniform(60, 120), refresh_interval=refresh_interval)
                        elif e.data.code in (405, 406, 489):
                            raise PublicationError('Method or event not supported', retry_after=3600)
                        else:
                            # Otherwise just try the next route
                            continue
                    else:
                        self.publishing = True
                        self._publish_wait = 1
                        command.signal()
                        break
            else:
                # There are no more routes to try, reschedule the publication
                retry_after = random.uniform(self._publish_wait, 2*self._publish_wait)
                self._publish_wait = limit(self._publish_wait*2, max=30)
                raise PublicationError('No more routes to try', retry_after=retry_after)
        except PublicationError as e:
            self.publishing = False
            notification_center.remove_observer(self, sender=self._publication)
            def publish(e):
                if self.active:
                    self._command_channel.send(Command('publish', event=command.event, state=self.state, refresh_interval=e.refresh_interval))
                else:
                    command.signal()
                self._publication_timer = None
            self._publication_timer = reactor.callLater(e.retry_after, publish, e)
            self._publication = None
            notification_center.post_notification(self.__nickname__ + 'PublicationDidFail', sender=self, data=NotificationData(reason=e.error))
        else:
            notification_center.post_notification(self.__nickname__ + 'PublicationDidSucceed', sender=self)
示例#41
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)