def _NH_DNSLookupDidSucceed(self, notification): # create subscriptions for everyone in the queue and register to get notifications from it self._subscription_routes = deque(notification.data.result) route = self._subscription_routes[0] route_header = RouteHeader(route.uri) for waitingsubscription in self.subscriptionqueue: # Creates a subscription for the waiting subscription newsubscription = Subscription( waitingsubscription.uri, FromHeader(self.account.uri, self.account.display_name), waitingsubscription, ContactHeader(self.account.contact[route]), "presence", route_header, credentials=self.account.credentials, refresh=self.account.sip.subscribe_interval) # Sets up an event listener for this new subscription notification_center = NotificationCenter() notification_center.add_observer(self, sender=newsubscription) # Starts the subscribe newsubscription.subscribe(timeout=5) # Adds this subscription to the active subscriptions list self.subscriptions.append(newsubscription) # Debug stuff self.output.put("Started new subscription with " + waitingsubscription.uri.user) # Clears all of the waiting subscriptions self.subscriptionqueue = []
def _subscription_handler(self, command): notification_center = NotificationCenter() settings = SIPSimpleSettings() subscription_uri = self.subscription_uri refresh_interval = command.refresh_interval or self.account.sip.subscribe_interval valid_transports = self.__transports__.intersection( settings.sip.transport_list) try: if Host.default_ip is None: raise SubscriptionError('No IP address', retry_after=60) # Lookup routes if self.account.sip.outbound_proxy is not None and self.account.sip.outbound_proxy.transport in valid_transports: uri = SIPURI(host=self.account.sip.outbound_proxy.host, port=self.account.sip.outbound_proxy.port, parameters={ 'transport': self.account.sip.outbound_proxy.transport }) elif self.account.sip.always_use_my_proxy: uri = SIPURI(host=self.account.id.domain) else: uri = SIPURI(host=subscription_uri.domain) lookup = DNSLookup() try: routes = lookup.lookup_sip_proxy( uri, valid_transports, tls_name=self.account.sip.tls_name).wait() except DNSLookupError as e: raise SubscriptionError('DNS lookup failed: %s' % e, retry_after=random.uniform(15, 30)) subscription_uri = SIPURI(user=subscription_uri.username, host=subscription_uri.domain) content = self.content timeout = time() + 30 for route in routes: if Host.default_ip is None: raise SubscriptionError('No IP address', retry_after=60) remaining_time = timeout - time() if remaining_time > 0: try: contact_uri = self.account.contact[NoGRUU, route] except KeyError: continue subscription = Subscription( subscription_uri, FromHeader(self.account.uri, self.account.display_name), ToHeader(subscription_uri), ContactHeader(contact_uri), self.event.encode(), RouteHeader(route.uri), credentials=self.account.credentials, refresh=refresh_interval) notification_center.add_observer(self, sender=subscription) try: subscription.subscribe( body=content.body, content_type=content.type, extra_headers=self.extra_headers, timeout=limit(remaining_time, min=1, max=5)) except SIPCoreError: notification_center.remove_observer( self, sender=subscription) raise SubscriptionError('Internal error', retry_after=5) self._subscription = subscription try: while True: notification = self._data_channel.wait() if notification.name == 'SIPSubscriptionDidStart': break except SIPSubscriptionDidFail as e: notification_center.remove_observer( self, sender=subscription) self._subscription = None if e.data.code == 407: # Authentication failed, so retry the subscription in some time raise SubscriptionError('Authentication failed', retry_after=random.uniform( 60, 120)) elif e.data.code == 423: # Get the value of the Min-Expires header if e.data.min_expires is not None and e.data.min_expires > self.account.sip.subscribe_interval: refresh_interval = e.data.min_expires else: refresh_interval = None raise SubscriptionError( 'Interval too short', retry_after=random.uniform(60, 120), refresh_interval=refresh_interval) elif e.data.code in (405, 406, 489): raise SubscriptionError( 'Method or event not supported', retry_after=3600) elif e.data.code == 1400: raise SubscriptionError(e.data.reason, retry_after=3600) else: # Otherwise just try the next route continue else: self.subscribed = True command.signal() break else: # There are no more routes to try, reschedule the subscription raise SubscriptionError('No more routes to try', retry_after=random.uniform(60, 180)) # At this point it is subscribed. Handle notifications and ending/failures. notification_center.post_notification(self.__nickname__ + 'SubscriptionDidStart', sender=self) try: while True: notification = self._data_channel.wait() if notification.name == 'SIPSubscriptionGotNotify': notification_center.post_notification( self.__nickname__ + 'SubscriptionGotNotify', sender=self, data=notification.data) elif notification.name == 'SIPSubscriptionDidEnd': notification_center.post_notification( self.__nickname__ + 'SubscriptionDidEnd', sender=self, data=NotificationData(originator='remote')) if self.active: self._command_channel.send(Command('subscribe')) break except SIPSubscriptionDidFail: notification_center.post_notification(self.__nickname__ + 'SubscriptionDidFail', sender=self) if self.active: self._command_channel.send(Command('subscribe')) notification_center.remove_observer(self, sender=self._subscription) except InterruptSubscription as e: if not self.subscribed: command.signal(e) if self._subscription is not None: notification_center.remove_observer(self, sender=self._subscription) try: self._subscription.end(timeout=2) except SIPCoreError: pass finally: notification_center.post_notification( self.__nickname__ + 'SubscriptionDidEnd', sender=self, data=NotificationData(originator='local')) except TerminateSubscription as e: if not self.subscribed: command.signal(e) if self._subscription is not None: try: self._subscription.end(timeout=2) except SIPCoreError: pass else: try: while True: notification = self._data_channel.wait() if notification.name == 'SIPSubscriptionDidEnd': break except SIPSubscriptionDidFail: pass finally: notification_center.remove_observer( self, sender=self._subscription) notification_center.post_notification( self.__nickname__ + 'SubscriptionDidEnd', sender=self, data=NotificationData(originator='local')) except SubscriptionError as e: def subscribe(e): if self.active: self._command_channel.send( Command('subscribe', command.event, refresh_interval=e.refresh_interval)) self._subscription_timer = None self._subscription_timer = reactor.callLater( e.retry_after, subscribe, e) notification_center.post_notification(self.__nickname__ + 'SubscriptionDidFail', sender=self) finally: self.subscribed = False self._subscription = None self._subscription_proc = None
def _subscription_handler(self, command): notification_center = NotificationCenter() settings = SIPSimpleSettings() subscription_uri = self.subscription_uri refresh_interval = command.refresh_interval or self.account.sip.subscribe_interval valid_transports = self.__transports__.intersection(settings.sip.transport_list) try: # Lookup routes if self.account.sip.outbound_proxy is not None and self.account.sip.outbound_proxy.transport in valid_transports: uri = SIPURI(host=self.account.sip.outbound_proxy.host, port=self.account.sip.outbound_proxy.port, parameters={'transport': self.account.sip.outbound_proxy.transport}) elif self.account.sip.always_use_my_proxy: uri = SIPURI(host=self.account.id.domain) else: uri = SIPURI(host=subscription_uri.domain) lookup = DNSLookup() try: routes = lookup.lookup_sip_proxy(uri, valid_transports).wait() except DNSLookupError, e: raise SubscriptionError('DNS lookup failed: %s' % e, retry_after=random.uniform(15, 30)) subscription_uri = SIPURI(user=subscription_uri.username, host=subscription_uri.domain) content = self.content timeout = time() + 30 for route in routes: remaining_time = timeout - time() if remaining_time > 0: try: contact_uri = self.account.contact[NoGRUU, route] except KeyError: continue subscription = Subscription(subscription_uri, FromHeader(self.account.uri, self.account.display_name), ToHeader(subscription_uri), ContactHeader(contact_uri), self.event, RouteHeader(route.uri), credentials=self.account.credentials, refresh=refresh_interval) notification_center.add_observer(self, sender=subscription) try: subscription.subscribe(body=content.body, content_type=content.type, extra_headers=self.extra_headers, timeout=limit(remaining_time, min=1, max=5)) except SIPCoreError: notification_center.remove_observer(self, sender=subscription) raise SubscriptionError('Internal error', retry_after=5) self._subscription = subscription try: while True: notification = self._data_channel.wait() if notification.name == 'SIPSubscriptionDidStart': break except SIPSubscriptionDidFail, e: notification_center.remove_observer(self, sender=subscription) self._subscription = None if e.data.code == 407: # Authentication failed, so retry the subscription in some time raise SubscriptionError('Authentication failed', retry_after=random.uniform(60, 120)) elif e.data.code == 423: # Get the value of the Min-Expires header if e.data.min_expires is not None and e.data.min_expires > self.account.sip.subscribe_interval: refresh_interval = e.data.min_expires else: refresh_interval = None raise SubscriptionError('Interval too short', retry_after=random.uniform(60, 120), refresh_interval=refresh_interval) elif e.data.code in (405, 406, 489): raise SubscriptionError('Method or event not supported', retry_after=3600) elif e.data.code == 1400: raise SubscriptionError(e.data.reason, retry_after=3600) else: # Otherwise just try the next route continue else: self.subscribed = True command.signal() break
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
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
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)