def save_certificates(self, sip_address, crt, key, ca): crt = crt.strip() + os.linesep key = key.strip() + os.linesep ca = ca.strip() + os.linesep X509Certificate(crt) X509PrivateKey(key) X509Certificate(ca) makedirs(ApplicationData.get('tls')) certificate_path = ApplicationData.get(os.path.join('tls', sip_address+'.crt')) file = open(certificate_path, 'w') os.chmod(certificate_path, 0600) file.write(crt+key) file.close() ca_path = ApplicationData.get(os.path.join('tls', 'ca.crt')) try: existing_cas = open(ca_path).read().strip() + os.linesep except: file = open(ca_path, 'w') file.write(ca) file.close() else: if ca not in existing_cas: file = open(ca_path, 'w') file.write(existing_cas+ca) file.close() settings = SIPSimpleSettings() settings.tls.ca_list = ca_path settings.save() return certificate_path
def _NH_XCAPManagerDidReloadData(self, notification): account = notification.sender.account settings = SIPSimpleSettings() offline_status = notification.data.offline_status status_icon = notification.data.status_icon try: offline_note = next(note for service in offline_status.pidf.services for note in service.notes) except (AttributeError, StopIteration): offline_note = None settings.presence_state.offline_note = offline_note settings.save() if status_icon: icon_hash = hashlib.sha512(status_icon.data).hexdigest() user_icon = UserIcon(status_icon.url, icon_hash) if not settings.presence_state.icon or settings.presence_state.icon.etag != icon_hash: # TODO: convert icon to PNG before saving it self.owner.saveUserIcon(status_icon.data, icon_hash) else: user_icon = None if settings.presence_state.icon: unlink(settings.presence_state.icon.path) settings.presence_state.icon = None settings.save() account.xcap.icon = user_icon account.save() # Cleanup old base64 encoded icons from payload if account.id not in self._cleanedup_accounts: self._cleanup_icons(account)
def _AH_GoogleContactsActionTriggered(self): settings = SIPSimpleSettings() if settings.google_contacts.authorization_token is not None: settings.google_contacts.authorization_token = None settings.save() self.google_contacts_dialog.hide() else: self.google_contacts_dialog.open()
def __init__(self): super(Blink, self).__init__(sys.argv) self.setAttribute(Qt.AA_DontShowIconsInMenus, False) self.sip_application = SIPApplication() self.first_run = False self.setOrganizationDomain("ag-projects.com") self.setOrganizationName("AG Projects") self.setApplicationName("Blink") self.setApplicationVersion(__version__) self.main_window = MainWindow() self.chat_window = ChatWindow() self.main_window.__closed__ = True self.chat_window.__closed__ = True self.main_window.installEventFilter(self) self.chat_window.installEventFilter(self) self.main_window.addAction(self.chat_window.control_button.actions.main_window) self.chat_window.addAction(self.main_window.quit_action) self.chat_window.addAction(self.main_window.help_action) self.chat_window.addAction(self.main_window.redial_action) self.chat_window.addAction(self.main_window.join_conference_action) self.chat_window.addAction(self.main_window.mute_action) self.chat_window.addAction(self.main_window.silent_action) self.chat_window.addAction(self.main_window.preferences_action) self.chat_window.addAction(self.main_window.transfers_window_action) self.chat_window.addAction(self.main_window.logs_window_action) self.chat_window.addAction(self.main_window.received_files_window_action) self.chat_window.addAction(self.main_window.screenshots_window_action) self.ip_address_monitor = IPAddressMonitor() self.log_manager = LogManager() self.presence_manager = PresenceManager() self.session_manager = SessionManager() self.update_manager = UpdateManager() # Prevent application from exiting after last window is closed if system tray was initialized if self.main_window.system_tray_icon: self.setQuitOnLastWindowClosed(False) self.main_window.check_for_updates_action.triggered.connect(self.update_manager.check_for_updates) self.main_window.check_for_updates_action.setVisible(self.update_manager != Null) if getattr(sys, "frozen", False): XMLDocument.schema_path = Resources.get("xml-schemas") Account.register_extension(AccountExtension) BonjourAccount.register_extension(BonjourAccountExtension) Contact.register_extension(ContactExtension) Group.register_extension(GroupExtension) SIPSimpleSettings.register_extension(SIPSimpleSettingsExtension) notification_center = NotificationCenter() notification_center.add_observer(self, sender=self.sip_application) branding.setup(self)
def _NH_CFGSettingsObjectDidChange(self, account, data): if isinstance(account, Account): if 'message_summary.enabled' in data.modified: if not account.message_summary.enabled: MWIData.remove(account) if 'audio.enable_aec' in data.modified: settings = SIPSimpleSettings() BlinkLogger().log_info(u"Acoustic Echo Canceller is %s" % ('enabled' if settings.audio.enable_aec else 'disabled')) settings.audio.tail_length = 15 if settings.audio.enable_aec else 0 settings.save()
def runModal(self): self.window.makeKeyAndOrderFront_(None) rc = NSApp.runModalForWindow_(self.window) self.window.orderOut_(self) if rc == NSOKButton: note = unicode(self.nameText.stringValue()) settings = SIPSimpleSettings() settings.presence_state.offline_note = note settings.save() return note return None
def init(self): Account.register_extension(AccountExtension) BonjourAccount.register_extension(BonjourAccountExtension) Contact.register_extension(BlinkContactExtension) Group.register_extension(BlinkGroupExtension) SIPSimpleSettings.register_extension(SIPSimpleSettingsExtension) self._app.start(FileStorage(ApplicationData.directory)) # start session mgr SessionManager()
def notificationsCheckboxClicked_(self, sender): settings = SIPSimpleSettings() settings.logs.trace_notifications_in_gui = bool(sender.state()) settings.logs.trace_notifications = settings.logs.trace_notifications_in_gui or settings.logs.trace_notifications_to_file settings.save() notification_center = NotificationCenter() if settings.logs.trace_notifications_in_gui: notification_center.add_observer(self) else: notification_center.discard_observer(self)
def _NH_SIPApplicationDidStart(self, notification): settings = SIPSimpleSettings() if settings.presence_state.timestamp is None: settings.presence_state.timestamp = ISOTimestamp.now() settings.save() self.get_location([account for account in AccountManager().iter_accounts() if account is not BonjourAccount()]) self.publish() idle_timer = NSTimer.timerWithTimeInterval_target_selector_userInfo_repeats_(1.0, self, "updateIdleTimer:", None, True) NSRunLoop.currentRunLoop().addTimer_forMode_(idle_timer, NSRunLoopCommonModes) NSRunLoop.currentRunLoop().addTimer_forMode_(idle_timer, NSEventTrackingRunLoopMode)
def msrpRadioClicked_(self, sender): trace = sender.selectedCell().tag() settings = SIPSimpleSettings() settings.logs.trace_msrp_in_gui = trace if trace == Disabled: settings.logs.trace_msrp = settings.logs.trace_msrp_to_file elif trace == Simplified: settings.logs.trace_msrp = True elif trace == Full: settings.logs.trace_msrp = True settings.save()
def __init__(self): self.application = SIPApplication() self.stopping = False self.stop_event = Event() Account.register_extension(AccountExtension) BonjourAccount.register_extension(BonjourAccountExtension) SIPSimpleSettings.register_extension(SIPSimpleSettingsExtension) self.account_model = AccountModel() self.bonjour_services = BonjourServices() self.hal = HardwareAbstractionLayer() self.session_manager = SessionManager() self.web_handler = WebHandler()
def _NH_CFGSettingsObjectDidChange(self, account, data): if isinstance(account, Account): if 'message_summary.enabled' in data.modified: if not account.message_summary.enabled: MWIData.remove(account) if 'audio.echo_canceller.enabled' in data.modified: settings = SIPSimpleSettings() settings.audio.sample_rate = 32000 if settings.audio.echo_canceller.enabled and settings.audio.sample_rate not in ('16000', '32000') else 48000 spectrum = settings.audio.sample_rate/1000/2 if settings.audio.sample_rate/1000/2 < 20 else 20 BlinkLogger().log_info(u"Audio sample rate is set to %dkHz covering 0-%dkHz spectrum" % (settings.audio.sample_rate/1000, spectrum)) BlinkLogger().log_info(u"Acoustic Echo Canceller is %s" % ('enabled' if settings.audio.echo_canceller.enabled else 'disabled')) if spectrum >=20: BlinkLogger().log_info(u"For studio quality disable the option 'Use ambient noise reduction' in System Preferences > Sound > Input section.") settings.save() elif 'audio.sample_rate' in data.modified: settings = SIPSimpleSettings() spectrum = settings.audio.sample_rate/1000/2 if settings.audio.sample_rate/1000/2 < 20 else 20 if settings.audio.sample_rate == 48000: settings.audio.echo_canceller.enabled = False settings.audio.enable_aec = False settings.save() else: settings.audio.echo_canceller.enabled = True settings.audio.enable_aec = True settings.save()
def _NH_SIPApplicationWillStart(self, sender, data): settings = SIPSimpleSettings() settings.user_agent = "%s %s (MacOSX)" % (NSApp.delegate().applicationName, self._version) BlinkLogger().log_info(u"Initializing SIP SIMPLE Client SDK %s" % sdk_version) build = str(NSBundle.mainBundle().infoDictionary().objectForKey_("CFBundleVersion")) date = str(NSBundle.mainBundle().infoDictionary().objectForKey_("BlinkVersionDate")) BlinkLogger().log_info(u"Build %s from %s" % (build, date)) self.migratePasswordsToKeychain() # Set audio settings compatible with AEC and Noise Supressor settings.audio.sample_rate = 16000 settings.audio.tail_length = 15 if settings.audio.enable_aec else 0 settings.save() BlinkLogger().log_info(u"Acoustic Echo Canceller is %s" % ('enabled' if settings.audio.enable_aec else 'disabled')) # Although this setting is set at enrollment time, people who have downloaded previous versions will not have it account_manager = AccountManager() for account in account_manager.iter_accounts(): must_save = False if account is not BonjourAccount() and account.sip.primary_proxy is None and account.sip.outbound_proxy and not account.sip.selected_proxy: account.sip.primary_proxy = account.sip.outbound_proxy must_save = True if account is not BonjourAccount() and settings.tls.verify_server != account.tls.verify_server: account.tls.verify_server = settings.tls.verify_server must_save = True if account.tls.certificate and os.path.basename(account.tls.certificate.normalized) != 'default.crt': account.tls.certificate = DefaultValue must_save = True if account.id.domain == "sip2sip.info": if account.server.settings_url is None: account.server.settings_url = "https://blink.sipthor.net/settings.phtml" must_save = True if not account.ldap.hostname: account.ldap.hostname = "ldap.sipthor.net" account.ldap.dn = "ou=addressbook, dc=sip2sip, dc=info" account.ldap.enabled = True must_save = True if must_save: account.save() logger = FileLogger() logger.start() self.ip_address_monitor.start()
def __init__(self): super(Blink, self).__init__(sys.argv) self.application = SIPApplication() self.auxiliary_thread = AuxiliaryThread() self.first_run = False self.main_window = MainWindow() self.update_manager = UpdateManager() self.main_window.check_for_updates_action.triggered.connect(self.update_manager.check_for_updates) self.main_window.check_for_updates_action.setVisible(self.update_manager != Null) Account.register_extension(AccountExtension) BonjourAccount.register_extension(BonjourAccountExtension) SIPSimpleSettings.register_extension(SIPSimpleSettingsExtension) session_manager = SessionManager() session_manager.initialize(self.main_window, self.main_window.session_model)
def init(self): self._version = str(NSBundle.mainBundle().infoDictionary().objectForKey_("CFBundleShortVersionString")) #first_start = not os.path.exists(ApplicationData.get('config')) Account.register_extension(AccountExtension) BonjourAccount.register_extension(BonjourAccountExtension) Contact.register_extension(BlinkContactExtension) ContactGroup.register_extension(BlinkContactGroupExtension) SIPSimpleSettings.register_extension(SIPSimpleSettingsExtension) self._app.start(FileStorage(ApplicationData.directory)) self.init_configurations() # start session mgr SessionManager()
def speechRecognizer_didRecognizeCommand_(self, recognizer, command): if command == u'Reject': self.decideForAllSessionRequests(REJECT) self.stopSpeechRecognition() elif command == u'Busy': self.decideForAllSessionRequests(BUSY) self.stopSpeechRecognition() elif command in (u'Accept', u'Answer'): self.decideForAllSessionRequests(ACCEPT) self.stopSpeechRecognition() elif command in (u'Voicemail', u'Answering machine'): settings = SIPSimpleSettings() settings.answering_machine.enabled = not settings.answering_machine.enabled settings.save() if settings.answering_machine.enabled: self.stopSpeechRecognition()
def sipRadioClicked_(self, sender): notification_center = NotificationCenter() trace = sender.selectedCell().tag() settings = SIPSimpleSettings() settings.logs.trace_sip_in_gui = trace if trace == Disabled: notification_center.discard_observer(self, name="DNSLookupTrace") settings.logs.trace_sip = settings.logs.trace_sip_to_file elif trace == Simplified: notification_center.add_observer(self, name="DNSLookupTrace") settings.logs.trace_sip = True elif trace == Full: notification_center.add_observer(self, name="DNSLookupTrace") settings.logs.trace_sip = True settings.save()
def handle_settings(): settings = SIPSimpleSettings() if request.method == 'GET': # Retrieve settings return jsonify(get_state(settings)) else: # Update settings state = get_json(request) if not state: return error_response(400, 'error processing PUT body') try: set_state(settings, state) except ValueError, e: # TODO: some settings may have been applied, what do we do? return error_response(400, str(e)) settings.save() return jsonify(get_state(settings))
def _set_default_account(self, account): if account is not None and not account.enabled: raise ValueError("account %s is not enabled" % account.id) notification_center = NotificationCenter() settings = SIPSimpleSettings() with self._lock: old_account = self.accounts.get(settings.default_account, None) if account is old_account: return if account is None: settings.default_account = None else: settings.default_account = account.id settings.save() # we need to post the notification in the file-io thread in order to have it serialized after the # SIPAccountManagerDidAddAccount notification that is triggered when the account is saved the first # time, because save is executed in the file-io thread while this runs in the current thread. -Dan call_in_thread('file-io', notification_center.post_notification, 'SIPAccountManagerDidChangeDefaultAccount', sender=self, data=NotificationData(old_account=old_account, account=account))
def pause(self): settings = SIPSimpleSettings() if not settings.audio.pause_music: return self.is_pausing = True self.itunes.pause() self.spotify.pause() #self.vlc.pause() self.is_pausing = False self.notification_center.post_notification('MusicPauseDidExecute', sender=self)
def init(self): if NSApp.delegate().account_extension: Account.register_extension(NSApp.delegate().account_extension) else: Account.register_extension(AccountExtension) BonjourAccount.register_extension(BonjourAccountExtension) Contact.register_extension(BlinkContactExtension) Group.register_extension(BlinkGroupExtension) ContactURI.register_extension(BlinkContactURIExtension) if NSApp.delegate().general_extension: SIPSimpleSettings.register_extension(NSApp.delegate().general_extension) else: SIPSimpleSettings.register_extension(SIPSimpleSettingsExtension) app = AppKit.NSApplication.sharedApplication() self._app.start(FileStorage(ApplicationData.directory)) # start session mgr SessionManager()
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.iteritems() if description.uri.transport not in supported_transports ]: del self._servers[service_description] notification_center.post_notification( 'BonjourConferenceServicesDidRemoveServer', sender=self, data=TimestampedNotificationData(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=TimestampedNotificationData(transport=transport)) try: file = bonjour.DNSServiceBrowse(regtype="_sipfocus._%s" % transport, callBack=self._browse_cb) except bonjour.BonjourError, e: notification_center.post_notification( 'BonjourConferenceServicesDiscoveryDidFail', sender=self, data=TimestampedNotificationData(reason=str(e), transport=transport)) else: self._files.append(BonjourDiscoveryFile(file, transport)) added_transports.add(transport)
def _NH_SIPApplicationDidStart(self, notification): self.ip_address_monitor.start() self.fetch_account() self.main_window.show() settings = SIPSimpleSettings() accounts = AccountManager().get_accounts() if not accounts or (self.first_run and accounts==[BonjourAccount()]): self.main_window.preferences_window.show_create_account_dialog() if settings.google_contacts.authorization_token is InvalidToken: self.main_window.google_contacts_dialog.open_for_incorrect_password() self.update_manager.initialize()
def _NH_CFGSettingsObjectDidChange(self, notification): settings = SIPSimpleSettings() if notification.sender is settings: if 'logs.trace_sip' in notification.data.modified: self.siptrace_file = LogFile(os.path.join(ApplicationData.directory, 'logs', 'sip_trace.txt')) if settings.logs.trace_sip else Null if 'logs.trace_msrp' in notification.data.modified: self.msrptrace_file = LogFile(os.path.join(ApplicationData.directory, 'logs', 'msrp_trace.txt')) if settings.logs.trace_msrp else Null if 'logs.trace_pjsip' in notification.data.modified: self.pjsiptrace_file = LogFile(os.path.join(ApplicationData.directory, 'logs', 'pjsip_trace.txt')) if settings.logs.trace_pjsip else Null if 'logs.trace_notifications' in notification.data.modified: self.notifications_file = LogFile(os.path.join(ApplicationData.directory, 'logs', 'notifications_trace.txt')) if settings.logs.trace_notifications else Null
def tls_credentials(self): # This property can be optimized to cache the credentials it loads from disk, # however this is not a time consuming operation (~ 3000 req/sec). -Luci settings = SIPSimpleSettings() tls_certificate = self.tls.certificate or settings.tls.certificate certificate = None private_key = None if tls_certificate is not None: try: certificate_data = open(tls_certificate.normalized).read() certificate = X509Certificate(certificate_data) private_key = X509PrivateKey(certificate_data) except (FileNotFoundError, GNUTLSError, UnicodeDecodeError): pass trusted_cas = [] ca_list = self.tls.ca_list or settings.tls.ca_list if ca_list is not None: if len(self.trusted_cas) > 0: trusted_cas = self.trusted_cas else: crt = None start = False try: ca_text = open(ca_list.normalized).read() except (FileNotFoundError, GNUTLSError, UnicodeDecodeError): ca_text = '' for line in ca_text.split("\n"): if "BEGIN CERT" in line: start = True crt = line + "\n" elif "END CERT" in line: crt = crt + line + "\n" end = True start = False try: trusted_cas.append(X509Certificate(crt)) except (GNUTLSError, ValueError) as e: continue elif start: crt = crt + line + "\n" self.trusted_cas = trusted_cas self.ca_list = ca_list credentials = X509Credentials(certificate, private_key, trusted_cas) credentials.verify_peer = self.tls.verify_server or settings.tls.certificate return credentials
def startOutgoing(self, is_update): if self.direction == "active": self.sessionController.log_info("Requesting remote screen...") else: self.sessionController.log_info("Offering local screen...") NSBundle.loadNibNamed_owner_("ScreenServerWindow", self) self.statusProgress.startAnimation_(None) self.statusWindow.setTitle_( NSLocalizedString("Screen Sharing with %s", "Window title") % self.sessionController.titleShort) settings = SIPSimpleSettings() if not settings.logs.trace_msrp: settings.logs.trace_msrp = True settings.save() self.must_reset_trace_msrp = True NotificationCenter().add_observer(self, name="MSRPTransportTrace") #self.statusItem.show(self) NotificationCenter().add_observer(self, sender=self.stream.handler) NotificationCenter().add_observer(self, sender=self.stream) self.changeStatus(STREAM_PROPOSING if is_update else STREAM_CONNECTING)
def _LH_SIPEngineLog(self, notification): settings = SIPSimpleSettings() if not settings.logs.trace_pjsip: return message = "(%(level)d) %(message)s" % notification.data.__dict__ try: self.pjsiptrace_file.write('[%s %d] %s\n' % (self.name, self.pid, message)) self.pjsiptrace_file.flush() except Exception: pass
def _NH_SIPApplicationDidStart(self, notification): settings = SIPSimpleSettings() local_ip = SIPConfig.local_ip log.info('SylkServer started; listening on:') for transport in settings.sip.transport_list: try: log.info(' %s:%d (%s)' % (local_ip, getattr(self.engine, '%s_port' % transport), transport.upper())) except TypeError: pass
def _create_transport(self, rtp_transport, remote_sdp=None, stream_index=None): settings = SIPSimpleSettings() codecs = list(self.session.account.rtp.video_codec_list or settings.rtp.video_codec_list) return VideoTransport(rtp_transport, remote_sdp=remote_sdp, sdp_index=stream_index or 0, codecs=codecs)
def update(self, local_sdp, remote_sdp, stream_index): with self._lock: connection = remote_sdp.media[ stream_index].connection or remote_sdp.connection if not self._rtp_transport.ice_active and ( connection.address != self._rtp_transport.remote_rtp_address_sdp or self._rtp_transport.remote_rtp_port_sdp != remote_sdp.media[stream_index].port): settings = SIPSimpleSettings() old_consumer_slot = self.consumer_slot old_producer_slot = self.producer_slot self.notification_center.remove_observer( self, sender=self._transport) self._transport.stop() try: self._transport = AudioTransport( self.mixer, self._rtp_transport, remote_sdp, stream_index, codecs=list(self.session.account.rtp.audio_codec_list or settings.rtp.audio_codec_list)) except SIPCoreError, e: self.state = "ENDED" self._failure_reason = e.args[0] self.notification_center.post_notification( 'MediaStreamDidFail', sender=self, data=NotificationData(reason=self._failure_reason)) return self.notification_center.add_observer(self, sender=self._transport) self._transport.start(local_sdp, remote_sdp, stream_index, timeout=settings.rtp.timeout) self.notification_center.post_notification( 'AudioPortDidChangeSlots', sender=self, data=NotificationData( consumer_slot_changed=True, producer_slot_changed=True, old_consumer_slot=old_consumer_slot, new_consumer_slot=self.consumer_slot, old_producer_slot=old_producer_slot, new_producer_slot=self.producer_slot)) if connection.address == '0.0.0.0' and remote_sdp.media[ stream_index].direction == 'sendrecv': self._transport.update_direction('recvonly') self._check_hold(self._transport.direction, False) self.notification_center.post_notification( 'RTPStreamDidChangeRTPParameters', sender=self) else:
def _LH_MSRPLibraryLog(self, notification): settings = SIPSimpleSettings() if not settings.logs.trace_msrp: return if notification.data.level < self.msrp_level: return message = '%s %s' % (notification.data.level, notification.data.message) try: self.msrptrace_file.write('%s [%s %d]: %s\n' % (notification.datetime, self.name, self.pid, message)) self.msrptrace_file.flush() except Exception: pass
def _init_log_directory(self): settings = SIPSimpleSettings() log_directory = settings.logs.directory.normalized try: makedirs(log_directory) except Exception, e: if not self._log_directory_error: print "failed to create logs directory '%s': %s" % ( log_directory, e) self._log_directory_error = True self._wstrace_error = True raise
def _NH_AudioDevicesDidChange(self, notification): for action in self.output_device_menu.actions(): self.output_devices_group.removeAction(action) self.output_device_menu.removeAction(action) for action in self.input_device_menu.actions(): self.input_devices_group.removeAction(action) self.input_device_menu.removeAction(action) for action in self.alert_device_menu.actions(): self.alert_devices_group.removeAction(action) self.alert_device_menu.removeAction(action) if self.session_model.active_sessions: old_devices = set(notification.data.old_devices) new_devices = set(notification.data.new_devices) added_devices = new_devices - old_devices if added_devices: new_device = added_devices.pop() settings = SIPSimpleSettings() settings.audio.input_device = new_device settings.audio.output_device = new_device settings.save() self.load_audio_devices()
def add_incoming(self, session, streams): settings = SIPSimpleSettings() stream_types = [s.type for s in streams] if 'audio' in stream_types and not settings.audio.silent: self.incoming_audio_sessions[session] = streams else: if 'chat' in stream_types: self.chat_sessions[session] = streams if 'file-transfer' in stream_types: self.filerecv_sessions[session] = streams NotificationCenter().add_observer(self, sender=session) self.update_playing_ringtones(session.account)
def showCollaborationEditor(self): settings = SIPSimpleSettings() frame = self.inputView.frame() self.splitterHeight = frame.size.height frame.size.height = 0 self.inputView.setFrame_(frame) script = """showCollaborationEditor("%s", "%s")""" % ( self.delegate.sessionController.collaboration_form_id, settings.server.collaboration_url) self.outputView.stringByEvaluatingJavaScriptFromString_(script)
def xcapRadioClicked_(self, sender): notification_center = NotificationCenter() trace = sender.selectedCell().tag() settings = SIPSimpleSettings() settings.logs.trace_xcap_in_gui = trace if trace == Disabled: notification_center.discard_observer(self, name="XCAPManagerDidDiscoverServerCapabilities") notification_center.discard_observer(self, name="XCAPSubscriptionGotNotify") notification_center.discard_observer(self, name="XCAPManagerDidChangeState") settings.logs.trace_xcap = settings.logs.trace_xcap_to_file elif trace == Simplified: notification_center.add_observer(self, name="XCAPManagerDidDiscoverServerCapabilities") notification_center.add_observer(self, name="XCAPManagerDidChangeState") settings.logs.trace_xcap = True elif trace == Full: notification_center.add_observer(self, name="XCAPManagerDidDiscoverServerCapabilities") notification_center.add_observer(self, name="XCAPManagerDidChangeState") notification_center.add_observer(self, name="XCAPSubscriptionGotNotify") settings.logs.trace_xcap = True settings.save()
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( '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.encode('utf-8'), 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.encode('utf-8') 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()
def start(self, local_sdp, remote_sdp, stream_index): with self._lock: if self.state != 'INITIALIZED': raise RuntimeError('AudioStream.start() may only be called in the INITIALIZED state') settings = SIPSimpleSettings() self._transport.start(local_sdp, remote_sdp, stream_index, timeout=settings.rtp.timeout) self._check_hold(self._transport.direction, True) if self._try_ice: self.state = 'WAIT_ICE' else: self.state = 'ESTABLISHED' self.notification_center.post_notification('MediaStreamDidStart', sender=self)
def start(self): 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='incoming', local_uri=format_identity_to_string(self.account) if self.account is not BonjourAccount() else 'bonjour.local', file_size=0, remote_uri=self.remote_identity, file_path=file_path) self.log_info("Pull File Transfer Request started %s" % file_path) self.status = NSLocalizedString("Requesting File...", "Label") self.ft_info.status = "requesting" 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) notification_center.post_notification("BlinkFileTransferNewOutgoing", self)
def enableAnsweringMachine(self, view, session, run_now=False): if session not in self.answeringMachineTimers: settings = SIPSimpleSettings() amLabel = view.viewWithTag_(15) delay = 0 if run_now else settings.answering_machine.answer_delay info = dict(delay = delay, session = session, label = amLabel, time = time.time()) timer = NSTimer.timerWithTimeInterval_target_selector_userInfo_repeats_(1.0, self, "timerTick:", info, True) NSRunLoop.currentRunLoop().addTimer_forMode_(timer, NSRunLoopCommonModes) NSRunLoop.currentRunLoop().addTimer_forMode_(timer, NSEventTrackingRunLoopMode) self.answeringMachineTimers[session] = timer self.timerTick_(timer) amLabel.setHidden_(False)
def notify(): if self.running: settings = SIPSimpleSettings() if 'tcp' in settings.sip.transport_list: self.engine.set_tcp_port(None) self.engine.set_tcp_port(settings.sip.tcp_port) if 'tls' in settings.sip.transport_list: self._initialize_tls() notification_center = NotificationCenter() notification_center.post_notification( 'NetworkConditionsDidChange', sender=self) self._timer = None
def add_certificate_authority(self, ca): # not used anymore, let users add CAs in keychain instead try: X509Certificate(ca) except GNUTLSError as e: BlinkLogger().log_error("Invalid Certificate Authority: %s" % e) return False settings = SIPSimpleSettings() must_save_ca = False if settings.tls.ca_list is not None: ca_path = settings.tls.ca_list.normalized else: tls_folder = ApplicationData.get('tls') if not os.path.exists(tls_folder): os.mkdir(tls_folder, 0o700) ca_path = os.path.join(tls_folder, 'ca.crt') must_save_ca = True try: existing_cas = open(ca_path, "r").read().strip() + os.linesep except: existing_cas = None ca_list = ca else: ca_list = existing_cas if ca in existing_cas else existing_cas + ca if ca_list != existing_cas: f = open(ca_path, "w") os.chmod(ca_path, 0o600) f.write(ca_list) f.close() BlinkLogger().log_debug("Added new Certificate Authority to %s" % ca_path) must_save_ca = True if must_save_ca: settings.tls.ca_list = ca_path settings.save() return True
def _NH_SIPApplicationWillStart(self, sender, data): settings = SIPSimpleSettings() _version = str(NSBundle.mainBundle().infoDictionary().objectForKey_("CFBundleShortVersionString")) settings.user_agent = "%s %s (MacOSX)" % (NSApp.delegate().applicationName, _version) BlinkLogger().log_info(u"SIP User Agent: %s" % settings.user_agent) self.migratePasswordsToKeychain() self.cleanupIcons() # Set audio settings compatible with AEC and Noise Supressor settings.audio.sample_rate = 32000 if settings.audio.echo_canceller.enabled else 48000 if NSApp.delegate().applicationName == 'SIP2SIP': settings.service_provider.help_url = 'http://wiki.sip2sip.info' settings.service_provider.name = 'SIP2SIP' settings.save() BlinkLogger().log_info(u"Audio engine sampling rate %dKHz covering 0-%dKHz spectrum" % (settings.audio.sample_rate/1000, settings.audio.sample_rate/1000/2)) BlinkLogger().log_info(u"Acoustic Echo Canceller is %s" % ('enabled' if settings.audio.echo_canceller.enabled else 'disabled')) # Although this setting is set at enrollment time, people who have downloaded previous versions will not have it account_manager = AccountManager() for account in account_manager.iter_accounts(): must_save = False if account is not BonjourAccount() and account.sip.primary_proxy is None and account.sip.outbound_proxy and not account.sip.selected_proxy: account.sip.primary_proxy = account.sip.outbound_proxy must_save = True if account is not BonjourAccount() and settings.tls.verify_server != account.tls.verify_server: account.tls.verify_server = settings.tls.verify_server must_save = True if account.tls.certificate and os.path.basename(account.tls.certificate.normalized) != 'default.crt': account.tls.certificate = DefaultValue must_save = True if must_save: account.save() logger = FileLogger() logger.start() self.ip_address_monitor.start()
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_uri = self.account.contact[file.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') _bonjour.DNSServiceUpdateRecord( file.file, None, flags=0, rdata=_bonjour.TXTRecord(items=txtdata), ttl=0) except (_bonjour.BonjourError, KeyError) as e: notification_center.post_notification( 'BonjourServiceRegistrationUpdateDidFail', sender=self, 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()
def _LH_SIPEngineLog(self, notification): settings = SIPSimpleSettings() if not settings.logs.trace_pjsip or not settings.logs.trace_pjsip_to_file: return message = "(%(level)d) %(message)s" % notification.data.__dict__ try: self._init_log_file('pjsiptrace') except Exception: pass else: self._pjsiptrace_file.write('[%s %d] %s\n' % (os.path.basename( sys.argv[0]).rstrip('.py'), os.getpid(), message)) self._pjsiptrace_file.flush()
def _NH_ChatViewControllerDidDisplayMessage(self, notification): data = notification.data settings = SIPSimpleSettings() if not settings.audio.silent: now = time.time() if now - self.chat_beep_time > CHAT_TONE_THROTLE_DELAY and not data.history_entry: if data.direction == 'outgoing' and self.chat_message_outgoing_sound: self.chat_message_outgoing_sound.stop() self.chat_message_outgoing_sound.start() elif self.chat_message_incoming_sound: self.chat_message_incoming_sound.stop() self.chat_message_incoming_sound.start() self.chat_beep_time = now
def init_configurations(self): account_manager = AccountManager() settings = SIPSimpleSettings() self.notification_center.add_observer(self, sender=settings) # fixup default account self._selected_account = account_manager.default_account if self._selected_account is None: self._selected_account = account_manager.get_accounts()[0] default_ca = open(Resources.get('ca.crt'), "r").read().strip() self.set_default_certificate_authority(default_ca)
def resources_directory(cls): binary_directory = os.path.dirname(os.path.realpath(sys.argv[0])) if os.path.basename(binary_directory) == 'bin': application_directory = os.path.dirname(binary_directory) else: application_directory = binary_directory from sipsimple.configuration.settings import SIPSimpleSettings settings = SIPSimpleSettings() if os.path.basename(binary_directory) == 'bin': resources_component = settings.resources_directory or 'share/sipclients' else: resources_component = settings.resources_directory or 'resources' return os.path.realpath(os.path.join(application_directory, resources_component))
def _resolve_cb(self, file, flags, interface_index, error_code, fullname, host_target, port, txtrecord): notification_center = NotificationCenter() settings = SIPSimpleSettings() file = BonjourResolutionFile.find_by_file(file) if error_code == _bonjour.kDNSServiceErr_NoError: service_description = file.service_description try: record = BonjourNeighbourRecord( service_description, host_target, _bonjour.TXTRecord.parse(txtrecord)) except SIPCoreError: pass else: transport = record.uri.transport supported_transport = transport in settings.sip.transport_list and ( transport != 'tls' or self.account.tls.certificate is not None) if not supported_transport and service_description in self._neighbours: record = self._neighbours.pop(service_description) notification_center.post_notification( 'BonjourAccountDidRemoveNeighbour', sender=self.account, data=NotificationData(neighbour=service_description, record=record)) elif supported_transport: try: our_contact_uri = self.account.contact[NoGRUU, transport] except KeyError: return if str(record.uri) != str(our_contact_uri): had_neighbour = service_description in self._neighbours self._neighbours[service_description] = record notification_name = 'BonjourAccountDidUpdateNeighbour' if had_neighbour else 'BonjourAccountDidAddNeighbour' notification_data = NotificationData( neighbour=service_description, record=record) notification_center.post_notification( notification_name, sender=self.account, data=notification_data) else: self._files.remove(file) self._select_proc.kill(RestartSelect) file.close() error = _bonjour.BonjourError(error_code) notification_center.post_notification( 'BonjourAccountDiscoveryFailure', sender=self.account, data=NotificationData(error=str(error), transport=file.transport))
def _NH_SIPApplicationDidStart(self, sender, data): settings = SIPSimpleSettings() BlinkLogger().log_info(u"SIP User Agent %s" % settings.user_agent) BlinkLogger().log_info(u"SIP Device ID %s" % settings.instance_id) bonjour_account = BonjourAccount() if bonjour_account.enabled: for transport in settings.sip.transport_list: try: BlinkLogger().log_info(u'Bonjour Account listens on %s' % bonjour_account.contact[transport]) except KeyError: pass
def _SH_MuteButtonClicked(self, muted): settings = SIPSimpleSettings() settings.audio.muted = muted settings.save()
def _AH_VideoDeviceChanged(self, action): settings = SIPSimpleSettings() settings.video.device = action.data() settings.save()
with open(ca_path, "w") as f: os.chmod(ca_path, 0600) f.write(ca) BlinkLogger().log_debug(u"Added default Certificate Authority to %s" % ca_path) settings.tls.ca_list = ca_path settings.save() def add_certificate_authority(self, ca): # not used anymore, let users add CAs in keychain instead try: X509Certificate(ca) except GNUTLSError, e: BlinkLogger().log_error(u"Invalid Certificate Authority: %s" % e) return False settings = SIPSimpleSettings() must_save_ca = False if settings.tls.ca_list is not None: ca_path = settings.tls.ca_list.normalized else: tls_folder = ApplicationData.get('tls') if not os.path.exists(tls_folder): os.mkdir(tls_folder, 0700) ca_path = os.path.join(tls_folder, 'ca.crt') must_save_ca = True try: existing_cas = open(ca_path, "r").read().strip() + os.linesep except: existing_cas = None ca_list = ca
def _AH_AutoAcceptChatActionTriggered(self, checked): settings = SIPSimpleSettings() settings.chat.auto_accept = checked settings.save()
def _AH_ReceivedMessagesSoundActionTriggered(self, checked): settings = SIPSimpleSettings() settings.sounds.play_message_alerts = checked settings.save()
def _AH_EnableAnsweringMachineActionTriggered(self, checked): settings = SIPSimpleSettings() settings.answering_machine.enabled = checked settings.save()
def _SH_SilentButtonClicked(self, silent): settings = SIPSimpleSettings() settings.audio.silent = silent settings.save()
def engineCheckboxClicked_(self, sender): settings = SIPSimpleSettings() settings.logs.trace_pjsip_in_gui = bool(sender.state()) settings.logs.trace_pjsip = settings.logs.trace_pjsip_in_gui or settings.logs.trace_pjsip_to_file settings.save()