Exemple #1
0
 def _publish(self, state):
     if not self.active:
         return
     if state is None:
         self._command_channel.send(Command('unpublish'))
     else:
         self._command_channel.send(Command('publish', state=state))
Exemple #2
0
 def _CH_update_registrations(self, command):
     notification_center = NotificationCenter()
     settings = SIPSimpleSettings()
     if self._update_timer is not None and self._update_timer.active():
         self._update_timer.cancel()
     self._update_timer = None
     available_transports = settings.sip.transport_list
     old_files = []
     for file in (f for f in self._files[:] if isinstance(f, BonjourRegistrationFile) and f.transport not in available_transports):
         old_files.append(file)
         self._files.remove(file)
     self._select_proc.kill(RestartSelect)
     for file in old_files:
         file.close()
     update_failure = False
     for file in (f for f in self._files if isinstance(f, BonjourRegistrationFile)):
         try:
             contact = self.account.contact[NoGRUU, file.transport]
             instance_id = str(uuid.UUID(settings.instance_id))
             txtdata = dict(txtvers=1, name=self.account.display_name, contact="<%s>" % str(contact), instance_id=instance_id)
             state = self.account.presence_state
             if self.account.presence.enabled and state is not None:
                 txtdata['state'] = state.state
                 txtdata['note'] = state.note
             _bonjour.DNSServiceUpdateRecord(file.file, None, flags=0, rdata=_bonjour.TXTRecord(items=txtdata), ttl=0)
         except (_bonjour.BonjourError, KeyError) as e:
             notification_center.post_notification('BonjourAccountRegistrationUpdateDidFail', sender=self.account, data=NotificationData(reason=str(e), transport=file.transport))
             update_failure = True
     self._command_channel.send(Command('register'))
     if update_failure:
         self._update_timer = reactor.callLater(1, self._command_channel.send, Command('update_registrations', command.event))
     else:
         command.signal()
Exemple #3
0
 def play(self):
     if self._state != 'stopped':
         raise WavePlayerError('already playing')
     self._state = 'started'
     self._channel = coros.queue()
     self._current_loop = 0
     if self.initial_delay:
         reactor.callLater(self.initial_delay, self._channel.send,
                           Command('play'))
     else:
         self._channel.send(Command('play'))
     self._run().wait()
Exemple #4
0
 def _NH_CFGSettingsObjectDidChange(self, notification):
     if not self.started:
         return
     if 'enabled' in notification.data.modified:
         return # global account activation is handled separately by the account itself
     elif 'presence.enabled' in notification.data.modified:
         if self.account.presence.enabled:
             self.activate()
         else:
             self.deactivate()
     elif self.active and {'__id__', 'auth.password', 'auth.username', 'sip.outbound_proxy', 'sip.transport_list', 'sip.publish_interval'}.intersection(notification.data.modified):
         self._command_channel.send(Command('unpublish'))
         self._command_channel.send(Command('publish', state=self.state))
Exemple #5
0
    def _CH_probe_dns(self, command):
        if self._timer is not None and self._timer.active():
            self._timer.cancel()
        self._timer = None

        try:
            resolver = InternalResolver()
        except dns.resolver.NoResolverConfiguration as e:
            self._timer = reactor.callLater(15, self._channel.send,
                                            Command('probe_dns'))
            return

        self.domain = resolver.domain
        self.search = resolver.search
        local_nameservers = resolver.nameservers
        # probe local resolver
        resolver.timeout = 1
        resolver.lifetime = 3
        try:
            answer = resolver.query(self.probed_domain, rdatatype.NAPTR)
            if not any(record.rdtype == rdatatype.NAPTR
                       for record in answer.rrset):
                raise exception.DNSException("No NAPTR records found")
            answer = resolver.query("_sip._udp.%s" % self.probed_domain,
                                    rdatatype.SRV)
            if not any(record.rdtype == rdatatype.SRV
                       for record in answer.rrset):
                raise exception.DNSException("No SRV records found")
        except (dns.resolver.Timeout, exception.DNSException):
            pass
        else:
            self.nameservers = resolver.nameservers
            return
        # local resolver failed. probe google resolver
        resolver.nameservers = self.google_nameservers
        resolver.timeout = 2
        resolver.lifetime = 4
        try:
            answer = resolver.query(self.probed_domain, rdatatype.NAPTR)
            if not any(record.rdtype == rdatatype.NAPTR
                       for record in answer.rrset):
                raise exception.DNSException("No NAPTR records found")
        except (dns.resolver.Timeout, exception.DNSException):
            pass
        else:
            self.nameservers = resolver.nameservers
            return
        # google resolver failed. fallback to local resolver and schedule another probe for later
        self.nameservers = local_nameservers
        self._timer = reactor.callLater(15, self._channel.send,
                                        Command('probe_dns'))
 def activate(self):
     if not self.started:
         raise RuntimeError("not started")
     self.active = True
     self._command_channel.send(Command('subscribe'))
     notification_center = NotificationCenter()
     notification_center.post_notification(self.__class__.__name__ + 'DidActivate', sender=self)
Exemple #7
0
 def deactivate(self):
     if not self.started:
         raise RuntimeError("not started")
     self.active = False
     self._command_channel.send(Command('unpublish'))
     notification_center = NotificationCenter()
     notification_center.post_notification(self.__class__.__name__ + 'DidDeactivate', sender=self)
Exemple #8
0
 def subscribe(e):
     if self.active:
         self._command_channel.send(
             Command('subscribe',
                     command.event,
                     refresh_interval=e.refresh_interval))
     self._subscription_timer = None
Exemple #9
0
 def stop(self):
     if not self.started:
         return
     self.started = False
     self.active = False
     notification_center = NotificationCenter()
     notification_center.add_observer(self, sender=self)
     notification_center.post_notification(self.__class__.__name__ +
                                           'WillEnd',
                                           sender=self)
     notification_center.remove_observer(self,
                                         name='CFGSettingsObjectDidChange',
                                         sender=self.account)
     notification_center.remove_observer(self,
                                         name='CFGSettingsObjectDidChange',
                                         sender=SIPSimpleSettings())
     notification_center.remove_observer(self,
                                         name='NetworkConditionsDidChange')
     command = Command('terminate')
     self._command_channel.send(command)
     command.wait()
     self._command_proc = None
     notification_center.post_notification(self.__class__.__name__ +
                                           'DidDeactivate',
                                           sender=self)
     notification_center.post_notification(self.__class__.__name__ +
                                           'DidEnd',
                                           sender=self)
     notification_center.remove_observer(self, sender=self)
 def register():
     if self.active:
         self._command_channel.send(
             Command('register',
                     command.event,
                     refresh_interval=e.refresh_interval))
     self._registration_timer = None
Exemple #11
0
 def start(self):
     notification_center = NotificationCenter()
     notification_center.add_observer(self, name='SystemIPAddressDidChange')
     notification_center.add_observer(self, name='SystemDidWakeUpFromSleep')
     self._select_proc = proc.spawn(self._process_files)
     proc.spawn(self._handle_commands)
     # activate
     self._stopped = False
     self._command_channel.send(Command('discover'))
    def _CH_register(self, command):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()
        if self._register_timer is not None and self._register_timer.active():
            self._register_timer.cancel()
        self._register_timer = None
        supported_transports = set(
            transport for transport in settings.sip.transport_list
            if transport != 'tls' or self.account.tls.certificate is not None)
        registered_transports = set(
            file.transport for file in self._files
            if isinstance(file, BonjourRegistrationFile))
        missing_transports = supported_transports - registered_transports
        added_transports = set()

        if len(missing_transports) > 1 and 'udp' in missing_transports:
            missing_transports.remove('udp')

        for transport in missing_transports:
            notification_center.post_notification(
                'BonjourAccountWillRegister',
                sender=self.account,
                data=NotificationData(transport=transport))
            try:
                contact = self.account.contact[NoGRUU, transport]
                instance_id = str(uuid.UUID(settings.instance_id))
                txtdata = dict(txtvers=1,
                               name=self.account.display_name,
                               contact="<%s>" % str(contact),
                               instance_id=instance_id)
                state = self.account.presence_state
                if self.account.presence.enabled and state is not None:
                    txtdata['state'] = state.state
                    txtdata['note'] = state.note
                file = _bonjour.DNSServiceRegister(
                    name=str(contact),
                    regtype="_sipuri._%s" %
                    (transport if transport == 'udp' else 'tcp'),
                    port=contact.port,
                    callBack=self._register_cb,
                    txtRecord=_bonjour.TXTRecord(items=txtdata))
            except (_bonjour.BonjourError, KeyError) as e:
                notification_center.post_notification(
                    'BonjourAccountRegistrationDidFail',
                    sender=self.account,
                    data=NotificationData(reason=str(e), transport=transport))
            else:
                self._files.append(BonjourRegistrationFile(file, transport))
                added_transports.add(transport)
        if added_transports:
            self._select_proc.kill(RestartSelect)
        if added_transports != missing_transports:
            self._register_timer = reactor.callLater(
                1, self._command_channel.send,
                Command('register', command.event))
        else:
            command.signal()
Exemple #13
0
 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
Exemple #14
0
 def _process_files(self):
     while True:
         try:
             ready = select.select([f for f in self._files if not f.active and not f.closed], [], [])[0]
         except RestartSelect:
             continue
         else:
             for file in ready:
                 file.active = True
             self._command_channel.send(Command('process_results', files=[f for f in ready if not f.closed]))
Exemple #15
0
 def _CH_register(self, command):
     notification_center = NotificationCenter()
     settings = SIPSimpleSettings()
     if self._register_timer is not None and self._register_timer.active():
         self._register_timer.cancel()
     self._register_timer = None
     supported_transports = set(
         transport for transport in settings.sip.transport_list
         if transport != 'tls' or self.account.tls.certificate is not None)
     registered_transports = set(
         file.transport for file in self._files
         if isinstance(file, BonjourRegistrationFile))
     missing_transports = supported_transports - registered_transports
     added_transports = set()
     for transport in missing_transports:
         notification_center.post_notification(
             'BonjourServiceWillRegister',
             sender=self,
             data=NotificationData(transport=transport))
         try:
             contact_uri = self.account.contact[transport]
             contact_uri.user = self.uri_user
             if self.is_focus:
                 contact_uri.parameters['isfocus'] = None
             txtdata = dict(txtvers=1,
                            name=self.name,
                            contact="<%s>" % str(contact_uri),
                            instance_id=self.id)
             state = self.presence_state
             if state is not None:
                 txtdata['state'] = state.state
                 txtdata['note'] = state.note.encode('utf-8')
             file = _bonjour.DNSServiceRegister(
                 name=str(contact_uri),
                 regtype="_%s._%s" %
                 (self.service, transport if transport == 'udp' else 'tcp'),
                 port=contact_uri.port,
                 callBack=self._register_cb,
                 txtRecord=_bonjour.TXTRecord(items=txtdata))
         except (_bonjour.BonjourError, KeyError) as e:
             notification_center.post_notification(
                 'BonjourServiceRegistrationDidFail',
                 sender=self,
                 data=NotificationData(reason=str(e), transport=transport))
         else:
             self._files.append(BonjourRegistrationFile(file, transport))
             added_transports.add(transport)
     if added_transports:
         self._select_proc.kill(RestartSelect)
     if added_transports != missing_transports:
         self._register_timer = reactor.callLater(
             1, self._command_channel.send,
             Command('register', command.event))
     else:
         command.signal()
    def stop(self):
        # deactivate
        command = Command('stop')
        self._command_channel.send(command)
        command.wait()
        self._stopped = True

        notification_center = NotificationCenter()
        notification_center.remove_observer(self, name='SystemIPAddressDidChange')
        notification_center.remove_observer(self, name='SystemDidWakeUpFromSleep')
        self._select_proc.kill()
        self._command_channel.send_exception(api.GreenletExit)
Exemple #17
0
 def _browse_cb(self, file, flags, interface_index, error_code,
                service_name, regtype, reply_domain):
     notification_center = NotificationCenter()
     file = BonjourDiscoveryFile.find_by_file(file)
     service_description = BonjourServiceDescription(
         service_name, regtype, reply_domain)
     if error_code != bonjour.kDNSServiceErr_NoError:
         error = bonjour.BonjourError(error_code)
         notification_center.post_notification(
             'BonjourConferenceServicesDiscoveryDidFail',
             sender=self,
             data=TimestampedNotificationData(reason=str(error),
                                              transport=file.transport))
         removed_files = [file] + [
             f for f in self._files if isinstance(f, BonjourResolutionFile)
             and f.discovery_file == file
         ]
         for f in removed_files:
             self._files.remove(f)
         self._select_proc.kill(RestartSelect)
         for f in removed_files:
             f.close()
         if self._discover_timer is None:
             self._discover_timer = reactor.callLater(
                 1, self._command_channel.send, Command('discover'))
         return
     if reply_domain != 'local.':
         return
     if flags & bonjour.kDNSServiceFlagsAdd:
         try:
             resolution_file = (
                 f for f in self._files
                 if isinstance(f, BonjourResolutionFile)
                 and f.discovery_file == file
                 and f.service_description == service_description).next()
         except StopIteration:
             try:
                 resolution_file = bonjour.DNSServiceResolve(
                     0, interface_index, service_name, regtype,
                     reply_domain, self._resolve_cb)
             except bonjour.BonjourError, e:
                 notification_center.post_notification(
                     'BonjourConferenceServicesDiscoveryFailure',
                     sender=self,
                     data=TimestampedNotificationData(
                         error=str(e), transport=file.transport))
             else:
                 resolution_file = BonjourResolutionFile(
                     resolution_file,
                     discovery_file=file,
                     service_description=service_description)
                 self._files.append(resolution_file)
                 self._select_proc.kill(RestartSelect)
Exemple #18
0
 def _NH_CFGSettingsObjectDidChange(self, notification):
     if not self.started or not self.account.xcap.discovered:
         return
     if 'enabled' in notification.data.modified:
         return # global account activation is handled separately by the account itself
     elif 'presence.enabled' in notification.data.modified:
         if self.account.presence.enabled:
             self.activate()
         else:
             self.deactivate()
     elif self.active and {'__id__', 'auth.password', 'auth.username', 'sip.always_use_my_proxy', 'sip.outbound_proxy', 'sip.subscribe_interval', 'sip.transport_list'}.intersection(notification.data.modified):
         self._command_channel.send(Command('subscribe'))
 def _NH_CFGSettingsObjectDidChange(self, notification):
     if not self.started:
         return
     if 'enabled' in notification.data.modified:
         return # global account activation is handled separately by the account itself
     elif 'message_summary.enabled' in notification.data.modified:
         if self.account.message_summary.enabled:
             self.activate()
         else:
             self.deactivate()
     elif self.active and set(['__id__', 'auth.password', 'auth.username', 'message_summary.voicemail_uri', 'sip.always_use_my_proxy', 'sip.outbound_proxy',
                               'sip.subscribe_interval', 'sip.transport_list']).intersection(notification.data.modified):
         self._command_channel.send(Command('subscribe'))
Exemple #20
0
 def _register_cb(self, file, flags, error_code, name, regtype, domain):
     notification_center = NotificationCenter()
     file = BonjourRegistrationFile.find_by_file(file)
     if error_code == _bonjour.kDNSServiceErr_NoError:
         notification_center.post_notification(
             'BonjourServiceRegistrationDidSucceed',
             sender=self,
             data=NotificationData(name=name, transport=file.transport))
     else:
         error = _bonjour.BonjourError(error_code)
         notification_center.post_notification(
             'BonjourServiceRegistrationDidFail',
             sender=self,
             data=NotificationData(reason=str(error),
                                   transport=file.transport))
         self._files.remove(file)
         self._select_proc.kill(RestartSelect)
         file.close()
         if self._register_timer is None:
             self._register_timer = reactor.callLater(
                 1, self._command_channel.send, Command('register'))
 def _CH_discover(self, command):
     notification_center = NotificationCenter()
     settings = SIPSimpleSettings()
     if self._discover_timer is not None and self._discover_timer.active():
         self._discover_timer.cancel()
     self._discover_timer = None
     account = BonjourAccount()
     supported_transports = set(transport for transport in settings.sip.transport_list if transport!='tls' or account.tls.certificate is not None)
     discoverable_transports = set('tcp' if transport=='tls' else transport for transport in supported_transports)
     old_files = []
     for file in (f for f in self._files[:] if isinstance(f, (BonjourDiscoveryFile, BonjourResolutionFile)) and f.transport not in discoverable_transports):
         old_files.append(file)
         self._files.remove(file)
     self._select_proc.kill(RestartSelect)
     for file in old_files:
         file.close()
     for service_description in [service for service, description in self._servers.items() if description.uri.transport not in supported_transports]:
         del self._servers[service_description]
         notification_center.post_notification('BonjourConferenceServicesDidRemoveServer', sender=self, data=NotificationData(server=service_description))
     discovered_transports = set(file.transport for file in self._files if isinstance(file, BonjourDiscoveryFile))
     missing_transports = discoverable_transports - discovered_transports
     added_transports = set()
     for transport in missing_transports:
         notification_center.post_notification('BonjourConferenceServicesWillInitiateDiscovery', sender=self, data=NotificationData(transport=transport))
         try:
             file = _bonjour.DNSServiceBrowse(regtype="_sipfocus._%s" % transport, callBack=self._browse_cb)
         except _bonjour.BonjourError as e:
             notification_center.post_notification('BonjourConferenceServicesDiscoveryDidFail', sender=self, data=NotificationData(reason=str(e), transport=transport))
         else:
             self._files.append(BonjourDiscoveryFile(file, transport))
             added_transports.add(transport)
     if added_transports:
         self._select_proc.kill(RestartSelect)
     if added_transports != missing_transports:
         self._discover_timer = reactor.callLater(1, self._command_channel.send, Command('discover', command.event))
     else:
         command.signal()
Exemple #22
0
 def _NH_NetworkConditionsDidChange(self, notification):
     if self.active:
         self._command_channel.send(Command('unpublish'))
         self._command_channel.send(Command('publish', state=self.state))
Exemple #23
0
 def wakeup_action():
     self._proc.kill(InterruptCommand)
     self._channel.send(Command('probe_dns'))
     self._wakeup_timer = None
 def _NH_NetworkConditionsDidChange(self, notification):
     if self.active:
         self._command_channel.send(Command('unregister'))
         self._command_channel.send(Command('register'))
Exemple #25
0
 def _NH_SystemIPAddressDidChange(self, notification):
     self._proc.kill(InterruptCommand)
     self._channel.send(Command('probe_dns'))
Exemple #26
0
 def start(self):
     self._proc = proc.spawn(self._run)
     self._channel.send(Command('probe_dns'))
Exemple #27
0
 def handle_notification(self, notification):
     if self._channel is not None:
         self._channel.send(Command('reschedule'))
Exemple #28
0
 def _run(self):
     notification_center = NotificationCenter()
     try:
         while True:
             command = self._channel.wait()
             if command.name == 'play':
                 self._wave_file = WaveFile(self.mixer, self.filename)
                 notification_center.add_observer(
                     self,
                     sender=self._wave_file,
                     name='WaveFileDidFinishPlaying')
                 self._wave_file.volume = self.volume
                 try:
                     self._wave_file.start()
                 except SIPCoreError, e:
                     notification_center.post_notification(
                         'WavePlayerDidFail',
                         sender=self,
                         data=NotificationData(error=e))
                     raise WavePlayerError(e)
                 else:
                     if self._current_loop == 0:
                         notification_center.post_notification(
                             'WavePlayerDidStart', sender=self)
                     notification_center.post_notification(
                         'AudioPortDidChangeSlots',
                         sender=self,
                         data=NotificationData(
                             consumer_slot_changed=False,
                             producer_slot_changed=True,
                             old_producer_slot=None,
                             new_producer_slot=self._wave_file.slot))
             elif command.name == 'reschedule':
                 self._current_loop += 1
                 notification_center.remove_observer(
                     self,
                     sender=self._wave_file,
                     name='WaveFileDidFinishPlaying')
                 self._wave_file = None
                 notification_center.post_notification(
                     'AudioPortDidChangeSlots',
                     sender=self,
                     data=NotificationData(consumer_slot_changed=False,
                                           producer_slot_changed=True,
                                           old_producer_slot=None,
                                           new_producer_slot=None))
                 if self.loop_count == 0 or self._current_loop < self.loop_count:
                     reactor.callLater(self.pause_time, self._channel.send,
                                       Command('play'))
                 else:
                     notification_center.post_notification(
                         'WavePlayerDidEnd', sender=self)
                     break
             elif command.name == 'stop':
                 if self._wave_file is not None:
                     notification_center.remove_observer(
                         self,
                         sender=self._wave_file,
                         name='WaveFileDidFinishPlaying')
                     self._wave_file.stop()
                     self._wave_file = None
                     notification_center.post_notification(
                         'AudioPortDidChangeSlots',
                         sender=self,
                         data=NotificationData(consumer_slot_changed=False,
                                               producer_slot_changed=True,
                                               old_producer_slot=None,
                                               new_producer_slot=None))
                     notification_center.post_notification(
                         'WavePlayerDidEnd', sender=self)
                 break
 def deactivate(self):
     if not self.started:
         raise RuntimeError("not started")
     self.active = False
     self._command_channel.send(Command('unregister'))
Exemple #30
0
 def stop(self):
     if self._state != 'started':
         return
     self._channel.send(Command('stop'))