show_notice('%s Encrypted message %s to %s failed on %s: %s (%d)' % (datetime.now().replace(microsecond=0), message.id, self.remote_uri, server or client, notification.data.reason.decode(), notification.data.code))
else:
show_notice('%s Message %s to %s failed on %s: %s (%d)' % (datetime.now().replace(microsecond=0), message.id, self.remote_uri, server or client, notification.data.reason.decode() if isinstance(notification.data.reason, bytes) else notification.data.reason, notification.data.code))
self.question = Question("Incoming file transfer for %s from '%s', do you want to accept? (a)ccept/(r)eject" % (os.path.basename(self.filename), identity), 'ari', bold=True)
SIPApplication.start(self, FileStorage(options.config_directory or config_directory))
except ConfigurationError as e:
show_notice("Failed to load sipclient's configuration: %s\n" % str(e), bold=False)
show_notice("If an old configuration file is in place, delete it or move it and recreate the configuration using the sip_settings script.", bold=False)
ui.stop()
self.stopped_event.set()
else:
show_notice("SDK version %s, core version %s, PJSIP version %s (%s)" % (version, CORE_REVISION, PJ_VERSION.decode(), PJ_SVN_REVISION))
possible_accounts = [account for account in account_manager.iter_accounts() if self.options.account in account.id and account.enabled]
if len(possible_accounts) > 1:
show_notice('More than one account exists which matches %s: %s' % (self.options.account, ', '.join(sorted(account.id for account in possible_accounts))), bold=False)
self.stop()
return
elif len(possible_accounts) == 0:
show_notice('No enabled account which matches %s was found. Available and enabled accounts: %s' % (self.options.account, ', '.join(sorted(account.id for account in account_manager.get_accounts() if account.enabled))), bold=False)
lines = ['%s Registered contact "%s" of %s at %s:%d;transport=%s for %d seconds' % (now, contact_header.uri, account.id, registrar.address, registrar.port, registrar.transport, expires)]
if len(contact_header_list) > 1:
lines.append('%s Other registered contacts of %s:' % (now, account.id))
lines.extend('%s %s of %s for %s seconds' % (now, str(other_contact_header.uri), account.id, other_contact_header.expires) for other_contact_header in contact_header_list if other_contact_header.uri != notification.data.contact_header.uri)
if account.contact.public_gruu is not None:
lines.append('%s Public GRUU: %s' % (now, account.contact.public_gruu))
if content.startswith('-----BEGIN PGP MESSAGE-----') and content.endswith('-----END PGP MESSAGE-----') and not private_key:
show_notice("%s %s wrote: %s (%s)" % (datetime.now().replace(microsecond=0), identity, 'Received a PGP message for which we have no private key', msg_id))
if data.question == self.smp_verification_question:
try:
audio_stream = next(stream for stream in session.streams if stream.type=='audio' and stream.encryption.type=='ZRTP' and stream.encryption.active and stream.encryption.zrtp.verified)
except StopIteration:
stream.encryption.smp_abort()
else:
show_notice("OTR verification requested by remote and replied automatically using ZRTP SAS", bold=False)
audio_stream = next(stream for stream in session.streams if stream.type=='audio' and stream.encryption.type=='ZRTP' and stream.encryption.active and stream.encryption.zrtp.verified)
show_notice('No camera present, video is disabled')
self.enable_video = False
def _CH_help(self):
self._print_help()
def _CH_quit(self):
self.stop()
def _CH_eof(self):
ui = UI()
if self.active_session is not None:
if self.active_session in self.sessions_with_proposals:
ui.status = 'Cancelling proposal...'
self.active_session.cancel_proposal()
else:
ui.status = 'Ending SIP session...'
self.active_session.end()
elif self.outgoing_session is not None:
ui.status = 'Cancelling SIP session...'
self.outgoing_session.end()
else:
self.stop()
def _CH_hangup(self):
if self.active_session is not None:
show_notice('Ending SIP session...')
self.active_session.end()
elif self.outgoing_session is not None:
show_notice('Cancelling SIP session...')
self.outgoing_session.end()
else:
try:
message_session = next((session for session in self.message_sessions if session.target == self.message_session_to and self.account == session.account))
except StopIteration:
pass
else:
message_session.end()
try:
self.message_sessions.remove(message_session)
except KeyError:
show_notice('Message session not found')
pass
@run_in_green_thread
def _CH_dtmf(self, tones):
if self.active_session is not None:
audio_stream = next((stream for stream in self.active_session.streams if stream.type == 'audio'), None)
show_notice('Accounts available: %s' % ", ".join(account.id for account in account_manager.iter_accounts() if account != self.account and account.enabled))
possible_accounts = [account for account in account_manager.iter_accounts() if new_account in account.id and account.enabled]
if len(possible_accounts) > 1:
show_notice('More than one account exists which matches %s: %s' % (new_account, ', '.join(sorted(account.id for account in possible_accounts))), bold=False)
elif len(possible_accounts) == 0:
show_notice('No enabled account which matches %s was found. Available and enabled accounts: %s' % (self.options.account, ', '.join(sorted(possible_accounts))), bold=False)
parser.add_option('-a', '--account', type='string', dest='account', help='The account name to use for any outgoing traffic. If not supplied, the default account will be used.', metavar='NAME')
parser.add_option('-c', '--config-directory', type='string', dest='config_directory', help='The configuration directory to use. This overrides the default location.')
parser.add_option('-p', '--playback-dir', type='string', dest='playback_dir', help='Directory with wav files to be played after calling. The destination SIP address is taken from the filename. After playback the call is hangup')
parser.add_option('-s', '--trace-sip', action='store_true', dest='trace_sip', default=False, help='Dump the raw contents of incoming and outgoing SIP messages.')
parser.add_option('-m', '--trace-msrp', action='store_true', dest='trace_msrp', default=False, help='Dump msrp logging information and the raw contents of incoming and outgoing MSRP messages.')
parser.add_option('-n', '--trace-notifications', action='store_true', dest='trace_notifications', default=False, help='Print all notifications (disabled by default).')
parser.add_option('-S', '--disable-sound', action='store_true', dest='disable_sound', default=False, help='Disables initializing the sound card.')
parser.set_default('auto_answer_interval', None)
parser.add_option('--auto-answer', action='callback', callback=parse_handle_call_option, callback_args=('auto_answer_interval',), help='Interval after which to answer an incoming session (disabled by default). If the option is specified but the interval is not, it defaults to 0 (accept the session as soon as it starts ringing).', metavar='[INTERVAL]')
parser.set_default('auto_hangup_interval', None)
parser.add_option('--auto-hangup', action='callback', callback=parse_handle_call_option, callback_args=('auto_hangup_interval',), help='Interval after which to hang up an established session (disabled by default). If the option is specified but the interval is not, it defaults to 0 (hangup the session as soon as it connects).', metavar='[INTERVAL]')