def _NH_IncomingFileTransferHandlerDidEnd(self, notification): notification.center.remove_observer(self, sender=self) remote_hash = self.file_selector.hash if not self.transfer_finished: log.msg('File transfer of %s cancelled' % os.path.basename(self.filename)) self.remove_bogus_file(self.filename) self.status = 'INCOMPLETE' else: local_hash = 'sha1:' + ':'.join(re.findall(r'..', self.hash.hexdigest().upper())) if local_hash != remote_hash: log.warning('Hash of transferred file does not match the remote hash (file may have changed).') self.status = 'HASH_MISSMATCH' self.remove_bogus_file(self.filename) else: self.status = 'OK' self_uri = SIPURI.new(self.session.local_identity.uri) self_uri.parameters.clear() sender_uri = SIPURI.new(self.session.remote_identity.uri) sender_uri.parameters.clear() self.session = None self.stream = None file = File(self.filename, remote_hash, self.file_selector.size) notification.center.post_notification('IncomingFileTransferHandlerGotFile', sender=self, data=NotificationData(local_uri=self_uri, remote_uri=sender_uri, file=file))
def lookup_destination(self, target_uri): assert isinstance(target_uri, SIPURI) lookup = DNSLookup() self.notification_center.add_observer(self, sender=lookup) settings = SIPSimpleSettings() if isinstance(self.account, Account) and self.account.sip.outbound_proxy is not None: uri = SIPURI(host=self.account.sip.outbound_proxy.host, port=self.account.sip.outbound_proxy.port, parameters={ 'transport': self.account.sip.outbound_proxy.transport }) self.log_info(u"Starting DNS lookup for %s through proxy %s" % (target_uri.host, uri)) elif isinstance(self.account, Account) and self.account.sip.always_use_my_proxy: uri = SIPURI(host=self.account.id.domain) self.log_info( u"Starting DNS lookup for %s via proxy of account %s" % (target_uri.host, self.account.id)) else: uri = target_uri self.log_info(u"Starting DNS lookup for %s" % target_uri.host) lookup.lookup_sip_proxy(uri, settings.sip.transport_list)
def start(self): if not self.refer_to_uri.startswith(('sip:', 'sips:')): self.refer_to_uri = 'sip:%s' % self.refer_to_uri try: self.refer_to_uri = SIPURI.parse(self.refer_to_uri) except SIPCoreError: log.msg('Room %s - failed to add %s' % (self.room_uri_str, self.refer_to_uri)) self._refer_request.reject(488) return notification_center = NotificationCenter() notification_center.add_observer(self, sender=self._refer_request) if self.method == 'INVITE': self._refer_request.accept() settings = SIPSimpleSettings() account = DefaultAccount() if account.sip.outbound_proxy is not None: uri = SIPURI(host=account.sip.outbound_proxy.host, port=account.sip.outbound_proxy.port, parameters={'transport': account.sip.outbound_proxy.transport}) else: uri = self.refer_to_uri lookup = DNSLookup() notification_center.add_observer(self, sender=lookup) lookup.lookup_sip_proxy(uri, settings.sip.transport_list) elif self.method == 'BYE': log.msg('Room %s - %s removed %s from the room' % (self.room_uri_str, self._refer_headers.get('From').uri, self.refer_to_uri)) self._refer_request.accept() conference_application = ConferenceApplication() conference_application.remove_participant(self.refer_to_uri, self.room_uri) self._refer_request.end(200) else: self._refer_request.reject(488)
def _CH_publish(self, command): if command.state is None or self._publication is None and command.state is SameState: command.signal() return notification_center = NotificationCenter() settings = SIPSimpleSettings() if self._publication_timer is not None and self._publication_timer.active( ): self._publication_timer.cancel() self._publication_timer = None if self._publication is None: duration = command.refresh_interval or self.account.sip.publish_interval from_header = FromHeader(self.account.uri, self.account.display_name) self._publication = Publication( from_header, self.event, self.payload_type.content_type, credentials=self.account.credentials, duration=duration, extra_headers=self.extra_headers) notification_center.add_observer(self, sender=self._publication) notification_center.post_notification( self.__class__.__name__ + 'WillPublish', sender=self, data=NotificationData(state=command.state, duration=duration)) else: notification_center.post_notification( self.__class__.__name__ + 'WillRefresh', sender=self, data=NotificationData(state=command.state)) try: # Lookup routes valid_transports = self.__transports__.intersection( settings.sip.transport_list) if self.account.sip.outbound_proxy is not None and self.account.sip.outbound_proxy.transport in valid_transports: uri = SIPURI(host=self.account.sip.outbound_proxy.host, port=self.account.sip.outbound_proxy.port, parameters={ 'transport': self.account.sip.outbound_proxy.transport }) else: uri = SIPURI(host=self.account.id.domain) lookup = DNSLookup() try: routes = lookup.lookup_sip_proxy(uri, valid_transports).wait() except DNSLookupError, e: retry_after = random.uniform(self._dns_wait, 2 * self._dns_wait) self._dns_wait = limit(2 * self._dns_wait, max=30) raise PublicationError('DNS lookup failed: %s' % e, retry_after=retry_after) else:
def start(self, restart=False): notification_center = NotificationCenter() file_path = self._file_selector.name.decode() if isinstance( self._file_selector.name, bytes) else self._file_selector.name self.ft_info = FileTransferInfo( transfer_id=str(uuid.uuid4()), direction='outgoing', file_size=self._file_selector.size, local_uri=format_identity_to_string(self.account) if self.account is not BonjourAccount() else 'bonjour.local', remote_uri=self.remote_identity, file_path=file_path) self.status = NSLocalizedString("Offering File...", "Label") self.ft_info.status = "proposing" self.log_info("Initiating DNS Lookup of %s to %s" % (self.account, self.target_uri)) lookup = DNSLookup() notification_center.add_observer(self, sender=lookup) if isinstance(self.account, Account) and self.account.sip.outbound_proxy is not None: uri = SIPURI(host=self.account.sip.outbound_proxy.host, port=self.account.sip.outbound_proxy.port, parameters={ 'transport': self.account.sip.outbound_proxy.transport }) self.log_info("Initiating DNS Lookup for %s (through proxy %s)" % (self.target_uri, uri)) elif isinstance(self.account, Account) and self.account.sip.always_use_my_proxy: uri = SIPURI(host=self.account.id.domain) self.log_info( "Initiating DNS Lookup for %s (through account %s proxy)" % (self.target_uri, self.account.id)) else: uri = self.target_uri self.log_info("Initiating DNS Lookup for %s" % self.target_uri) settings = SIPSimpleSettings() tls_name = None if isinstance(self.account, Account): tls_name = self.account.sip.tls_name or self.account.id.domain lookup.lookup_sip_proxy(uri, settings.sip.transport_list, tls_name=tls_name) if restart: notification_center.post_notification( "BlinkFileTransferWillRestart", self) else: notification_center.post_notification( "BlinkFileTransferNewOutgoing", sender=self)
def validate(self, value): if value.startswith(('sip:', 'sips:')): uri = value else: uri = 'sip:' + value try: SIPURI.parse(uri) except SIPCoreError: raise ValueError('invalid SIP URI: {}'.format(value)) return value
def validate(self, value): prefix, sep, suffix = value.partition(':') if sep and prefix in ('sip', 'sips'): aor = suffix else: aor = value try: SIPURI.parse('sip:' + aor) except SIPCoreError: raise ValueError('invalid SIP URI: {}'.format(value)) return aor
def get_audio_recordings(self): result = [] historydir = self.get_audio_recordings_directory() for acct in os.listdir(historydir): dirname = historydir + "/" + acct if not os.path.isdir(dirname): continue files = [ dirname + "/" + f for f in os.listdir(dirname) if f.endswith(".wav") ] for file in files: try: toks = file.split("/")[-1].split("-", 2) if len(toks) == 3: date, time, rest = toks timestamp = date[:4] + "/" + date[4:6] + "/" + date[ 6:8] + " " + time[:2] + ":" + time[2:4] pos = rest.rfind("-") if pos >= 0: remote = rest[:pos] else: remote = rest try: identity = SIPURI.parse('sip:' + str(remote)) remote_party = format_identity_to_string( identity, check_contact=True) except SIPCoreError: remote_party = "%s" % (remote) else: try: identity = SIPURI.parse('sip:' + str(file[:-4])) remote_party = format_identity_to_string( identity, check_contact=True) except SIPCoreError: remote_party = file[:-4] timestamp = datetime.fromtimestamp(int( stat.st_ctime)).strftime("%E %T") stat = os.stat(file) result.append((timestamp, remote_party, file)) except: import traceback traceback.print_exc() pass result.sort(lambda a, b: cmp(a[0], b[0])) return result
def start(self): notification_center = NotificationCenter() self.greenlet = api.getcurrent() settings = SIPSimpleSettings() account = AccountManager().sylkserver_account if account.sip.outbound_proxy is not None: uri = SIPURI( host=account.sip.outbound_proxy.host, port=account.sip.outbound_proxy.port, parameters={'transport': account.sip.outbound_proxy.transport}) else: uri = self.destination_uri lookup = DNSLookup() try: routes = lookup.lookup_sip_proxy( uri, settings.sip.transport_list).wait() except DNSLookupError: notification_center.post_notification( 'OutgoingFileTransferHandlerDidFail', sender=self) return self.session = Session(account) self.stream = FileTransferStream(self.file_selector, 'sendonly') notification_center.add_observer(self, sender=self.session) notification_center.add_observer(self, sender=self.stream) from_header = FromHeader(self.sender_uri, u'SIPStache File Transfer') to_header = ToHeader(self.destination_uri) transport = routes[0].transport parameters = {} if transport == 'udp' else {'transport': transport} contact_header = ContactHeader( SIPURI(user=self.sender_uri.user, host=SIPConfig.local_ip.normalized, port=getattr(Engine(), '%s_port' % transport), parameters=parameters)) extra_headers = [] if ThorNodeConfig.enabled: extra_headers.append(Header('Thor-Scope', 'sipstache-file')) extra_headers.append( Header('X-Originator-From', str(self.destination_uri))) self.session.connect(from_header, to_header, contact_header=contact_header, routes=routes, streams=[self.stream], is_focus=False, extra_headers=extra_headers) notification_center.post_notification( 'OutgoingFileTransferHandlerDidStart', sender=self)
def __init__(self, account, target_uri, filename, hash): self.account = account self._file_selector = FileSelector(name=os.path.basename(filename), hash=hash) self.remote_identity = format_identity_to_string(target_uri) self.target_uri = SIPURI.new(target_uri) self._ended = False
def send_publish(self, uri, body): if self.outbound_proxy is None: return uri = self.sip_prefix_re.sub('', uri) publication = Publication( FromHeader(SIPURI(uri)), "xcap-diff", "application/xcap-diff+xml", duration=0, extra_headers=[Header('Thor-Scope', 'publish-xcap')]) NotificationCenter().add_observer(self, sender=publication) route_header = RouteHeader( SIPURI(host=self.outbound_proxy.host, port=self.outbound_proxy.port, parameters=dict(transport=self.outbound_proxy.transport))) publication.publish(body, route_header, timeout=5)
def __init__(self, request): self.finished = False request.notifyFinish().addCallbacks(self._responseSucceeded, self._responseFailed) jsondata = request.content.getvalue() try: data = jsonlib.loads(jsondata) except (jsonlib.DecodeError, ValueError): if not self.finished: request.setResponseCode(400, 'Could not decode JSON data') request.finish() return try: target_uri = data.get('target_uri', '') if not re.match('^(sip:|sips:)', target_uri): target_uri = 'sip:%s' % target_uri target_uri = SIPURI.parse(target_uri) except SIPCoreError: if not self.finished: request.setResponseCode(400, 'Supplied SIP URI is invalid') request.finish() return cache = DataCache() data = cache.get(str(target_uri)) if data is not None: if not self.finished: request.setHeader('Content-Type', 'application/json') request.write(jsonlib.dumps(data)) request.finish() return self._target_uri = target_uri self._request = request self._handler = SIPOptionsRequestHandler(target_uri) NotificationCenter().add_observer(self, sender=self._handler) self._handler.start()
def parse(cls, value): if isinstance(value, BaseSIPURI): user = unicode(value.user) host = unicode(value.host) resource = unicode(value.parameters.get('gr', '')) or None return cls(user, host, resource) elif isinstance(value, JID): user = value.user host = value.host resource = value.resource return cls(user, host, resource) elif not isinstance(value, basestring): raise TypeError('uri needs to be a string') if not value.startswith(('sip:', 'sips:', 'xmpp:')): raise ValueError('invalid uri scheme for %s' % value) if value.startswith(('sip:', 'sips:')): try: uri = SIPURI.parse(value) except SIPCoreError: raise ValueError('invalid SIP uri: %s' % value) user = unicode(uri.user) host = unicode(uri.host) resource = unicode(uri.parameters.get('gr', '')) or None else: try: jid = JID(value[5:]) except Exception: raise ValueError('invalid XMPP uri: %s' % value) user = jid.user host = jid.host resource = jid.resource return cls(user, host, resource)
def _start_outgoing_sip_session(self, streams): notification_center = NotificationCenter() # self.xmpp_identity is our local identity on the SIP side from_uri = self.xmpp_identity.uri.as_sip_uri() from_uri.parameters.pop('gr', None) # no GRUU in From header to_uri = self.sip_identity.uri.as_sip_uri() to_uri.parameters.pop('gr', None) # no GRUU in To header # TODO: need to fix GRUU in the proxy #contact_uri = self.xmpp_identity.uri.as_sip_uri() #contact_uri.parameters['gr'] = encode_resource(contact_uri.parameters['gr'].decode('utf-8')) lookup = DNSLookup() settings = SIPSimpleSettings() account = DefaultAccount() if account.sip.outbound_proxy is not None: uri = SIPURI(host=account.sip.outbound_proxy.host, port=account.sip.outbound_proxy.port, parameters={'transport': account.sip.outbound_proxy.transport}) else: uri = to_uri try: routes = lookup.lookup_sip_proxy(uri, settings.sip.transport_list).wait() except DNSLookupError: log.warning('DNS lookup error while looking for %s proxy' % uri) notification_center.post_notification('MedialSessionHandlerDidFail', sender=self, data=NotificationData(reason='DNS lookup error')) return route = routes.pop(0) from_header = FromHeader(from_uri) to_header = ToHeader(to_uri) self.sip_session = Session(account) notification_center.add_observer(self, sender=self.sip_session) self.sip_session.connect(from_header, to_header, route=route, streams=streams)
def is_anonymous(uri): """ Check if the given URI is an anonymous uri """ anon_users = ('asterisk', 'unknown', 'anonymous') if isinstance(uri, (SIPURI, FrozenSIPURI)): if uri.user.lower() in anon_users: return True return (uri.user is None or uri.user.lower() == 'anonymous') and ( uri.host is None or uri.host.lower() == 'anonymous.invalid') else: if not (uri.startswith('sip:') or uri.startswith('sips:')): uri = "sip:%s" % uri try: sip_uri = SIPURI.parse(str(uri)) except: return False else: if sip_uri.user is not None and sip_uri.user.decode().lower( ) in anon_users: return True return (sip_uri.user is None or sip_uri.user.decode().lower() == 'anonymous') and (sip_uri.host is None or sip_uri.host.decode().lower() == 'anonymous.invalid')
def _start_outgoing_sip_session(self, target_uri): notification_center = NotificationCenter() # self.xmpp_identity is our local identity from_uri = self.xmpp_identity.uri.as_sip_uri() del from_uri.parameters['gr'] # no GRUU in From header contact_uri = self.xmpp_identity.uri.as_sip_uri() contact_uri.parameters['gr'] = encode_resource(contact_uri.parameters['gr'].decode('utf-8')) to_uri = target_uri.as_sip_uri() lookup = DNSLookup() settings = SIPSimpleSettings() account = DefaultAccount() if account.sip.outbound_proxy is not None: uri = SIPURI(host=account.sip.outbound_proxy.host, port=account.sip.outbound_proxy.port, parameters={'transport': account.sip.outbound_proxy.transport}) else: uri = to_uri try: routes = lookup.lookup_sip_proxy(uri, settings.sip.transport_list).wait() except DNSLookupError: log.warning('DNS lookup error while looking for %s proxy' % uri) notification_center.post_notification('ChatSessionDidFail', sender=self, data=NotificationData(reason='DNS lookup error')) return self.msrp_stream = MediaStreamRegistry.get('chat')() route = routes.pop(0) from_header = FromHeader(from_uri) to_header = ToHeader(to_uri) contact_header = ContactHeader(contact_uri) self.sip_session = Session(account) notification_center.add_observer(self, sender=self.sip_session) notification_center.add_observer(self, sender=self.msrp_stream) self.sip_session.connect(from_header, to_header, contact_header=contact_header, route=route, streams=[self.msrp_stream])
def get_recordings(self, filter_uris=[]): result = [] historydir = self.get_recordings_directory() for acct in os.listdir(historydir): dirname = historydir + "/" + acct if not os.path.isdir(dirname): continue files = [dirname+"/"+f for f in os.listdir(dirname)] for file in files: try: recording_type = "audio" if file.endswith(".wav") else "video" stat = os.stat(file) toks = file.split("/")[-1].split("-", 2) if len(toks) == 3: date, time, rest = toks timestamp = date[:4]+"/"+date[4:6]+"/"+date[6:8]+" "+time[:2]+":"+time[2:4] pos = rest.rfind(".") if pos >= 0: remote = rest[:pos] else: remote = rest try: identity = SIPURI.parse('sip:'+str(remote)) remote_party = format_identity_to_string(identity, check_contact=True) except SIPCoreError: remote_party = "%s" % (remote) else: try: identity = SIPURI.parse('sip:'+str(file[:-4])) remote_party = format_identity_to_string(identity, check_contact=True) except SIPCoreError: remote_party = file[:-4] timestamp = datetime.fromtimestamp(int(stat.st_ctime)).strftime("%E %T") if filter_uris and remote_party not in filter_uris: continue result.append((timestamp, remote_party, file, recording_type)) except Exception: pass sorted(result, key=lambda x: x[0]) return result
def sendReplicationMessage(self, response_code, content, content_type="message/cpim", timestamp=None): timestamp = timestamp or ISOTimestamp.now() # Lookup routes if self.account.sip.outbound_proxy is not None: uri = SIPURI(host=self.account.sip.outbound_proxy.host, port=self.account.sip.outbound_proxy.port, parameters={ 'transport': self.account.sip.outbound_proxy.transport }) else: uri = SIPURI(host=self.account.id.domain) route = None if self.last_route is None: lookup = DNSLookup() settings = SIPSimpleSettings() try: routes = lookup.lookup_sip_proxy( uri, settings.sip.transport_list).wait() except DNSLookupError: pass else: route = routes[0] else: route = self.last_route if route: extra_headers = [ Header("X-Offline-Storage", "no"), Header("X-Replication-Code", str(response_code)), Header("X-Replication-Timestamp", str(ISOTimestamp.now())) ] message_request = Message(FromHeader(self.account.uri, self.account.display_name), ToHeader(self.account.uri), RouteHeader(route.uri), content_type, content, credentials=self.account.credentials, extra_headers=extra_headers) message_request.send( 15 if content_type != "application/im-iscomposing+xml" else 5)
def incoming_message(self, message_request, data): content_type = data.headers.get('Content-Type', Null).content_type from_header = data.headers.get('From', Null) to_header = data.headers.get('To', Null) if Null in (content_type, from_header, to_header): message_request.answer(400) return log.info('New SIP Message from %s to %s' % (from_header.uri, to_header.uri)) # Check domain if from_header.uri.host not in XMPPGatewayConfig.domains: log.info('Message rejected: From domain is not a local XMPP domain') message_request.answer(606) return if content_type == 'message/cpim': try: cpim_message = CPIMPayload.decode(data.body) except CPIMParserError: log.info('Message rejected: CPIM parse error') message_request.answer(400) return else: body = cpim_message.content content_type = cpim_message.content_type sender = cpim_message.sender or from_header from_uri = sender.uri else: body = data.body from_uri = from_header.uri to_uri = str(to_header.uri) message_request.answer(200) if from_uri.parameters.get('gr', None) is None: from_uri = SIPURI.new(from_uri) from_uri.parameters['gr'] = generate_sylk_resource() sender = Identity(FrozenURI.parse(from_uri)) recipient = Identity(FrozenURI.parse(to_uri)) if content_type in ('text/plain', 'text/html'): if content_type == 'text/plain': html_body = None else: html_body = body body = None if XMPPGatewayConfig.use_msrp_for_chat: message = NormalMessage(sender, recipient, body, html_body, use_receipt=False) self.xmpp_manager.send_stanza(message) else: message = ChatMessage(sender, recipient, body, html_body, use_receipt=False) self.xmpp_manager.send_stanza(message) elif content_type == IsComposingDocument.content_type: if not XMPPGatewayConfig.use_msrp_for_chat: try: msg = IsComposingMessage.parse(body) except ParserError: pass else: state = 'composing' if msg.state == 'active' else 'paused' message = ChatComposingIndication(sender, recipient, state, use_receipt=False) self.xmpp_manager.send_stanza(message)
def incoming_message(self, message_request, data): content_type = data.headers.get('Content-Type', Null).content_type from_header = data.headers.get('From', Null) to_header = data.headers.get('To', Null) if Null in (content_type, from_header, to_header): message_request.answer(400) return log.msg('New SIP Message from %s to %s' % (from_header.uri, to_header.uri)) # Check domain if from_header.uri.host not in XMPPGatewayConfig.domains: log.msg('Message rejected: From domain is not a local XMPP domain') message_request.answer(606) return if content_type == 'message/cpim': try: cpim_message = CPIMMessage.parse(data.body) except CPIMParserError: log.msg('Message rejected: CPIM parse error') message_request.answer(400) return else: body = cpim_message.body content_type = cpim_message.content_type sender = cpim_message.sender or from_header from_uri = sender.uri else: body = data.body from_uri = from_header.uri to_uri = str(to_header.uri) message_request.answer(200) if from_uri.parameters.get('gr', None) is None: from_uri = SIPURI.new(from_uri) from_uri.parameters['gr'] = generate_sylk_resource() sender = Identity(FrozenURI.parse(from_uri)) recipient = Identity(FrozenURI.parse(to_uri)) if content_type in ('text/plain', 'text/html'): if content_type == 'text/plain': html_body = None else: html_body = body body = None if XMPPGatewayConfig.use_msrp_for_chat: message = NormalMessage(sender, recipient, body, html_body, use_receipt=False) self.xmpp_manager.send_stanza(message) else: message = ChatMessage(sender, recipient, body, html_body, use_receipt=False) self.xmpp_manager.send_stanza(message) elif content_type == IsComposingDocument.content_type: if not XMPPGatewayConfig.use_msrp_for_chat: try: msg = IsComposingMessage.parse(body) except ParserError: pass else: state = 'composing' if msg.state == 'active' else 'paused' message = ChatComposingIndication(sender, recipient, state, use_receipt=False) self.xmpp_manager.send_stanza(message)
def incoming_message(self, message_request, data): content_type = data.headers.get("Content-Type", Null).content_type from_header = data.headers.get("From", Null) to_header = data.headers.get("To", Null) if Null in (content_type, from_header, to_header): message_request.answer(400) return log.msg("New SIP Message from %s to %s" % (from_header.uri, to_header.uri)) # Check domain if from_header.uri.host not in XMPPGatewayConfig.domains: log.msg("Message rejected: From domain is not a local XMPP domain") message_request.answer(606) return if content_type == "message/cpim": try: cpim_message = CPIMPayload.decode(data.body) except CPIMParserError: log.msg("Message rejected: CPIM parse error") message_request.answer(400) return else: body = cpim_message.content content_type = cpim_message.content_type sender = cpim_message.sender or from_header from_uri = sender.uri else: body = data.body from_uri = from_header.uri to_uri = str(to_header.uri) message_request.answer(200) if from_uri.parameters.get("gr", None) is None: from_uri = SIPURI.new(from_uri) from_uri.parameters["gr"] = generate_sylk_resource() sender = Identity(FrozenURI.parse(from_uri)) recipient = Identity(FrozenURI.parse(to_uri)) if content_type in ("text/plain", "text/html"): if content_type == "text/plain": html_body = None else: html_body = body body = None if XMPPGatewayConfig.use_msrp_for_chat: message = NormalMessage(sender, recipient, body, html_body, use_receipt=False) self.xmpp_manager.send_stanza(message) else: message = ChatMessage(sender, recipient, body, html_body, use_receipt=False) self.xmpp_manager.send_stanza(message) elif content_type == IsComposingDocument.content_type: if not XMPPGatewayConfig.use_msrp_for_chat: try: msg = IsComposingMessage.parse(body) except ParserError: pass else: state = "composing" if msg.state == "active" else "paused" message = ChatComposingIndication(sender, recipient, state, use_receipt=False) self.xmpp_manager.send_stanza(message)
def get_audio_recordings(self, filter_uris=[]): result = [] historydir = self.get_audio_recordings_directory() for acct in os.listdir(historydir): dirname = historydir + "/" + acct if not os.path.isdir(dirname): continue files = [dirname+"/"+f for f in os.listdir(dirname) if f.endswith(".wav")] for file in files: try: stat = os.stat(file) toks = file.split("/")[-1].split("-", 2) if len(toks) == 3: date, time, rest = toks timestamp = date[:4]+"/"+date[4:6]+"/"+date[6:8]+" "+time[:2]+":"+time[2:4] pos = rest.rfind("-") if pos >= 0: remote = rest[:pos] else: remote = rest try: identity = SIPURI.parse('sip:'+str(remote)) remote_party = format_identity_to_string(identity, check_contact=True) except SIPCoreError: remote_party = "%s" % (remote) else: try: identity = SIPURI.parse('sip:'+str(file[:-4])) remote_party = format_identity_to_string(identity, check_contact=True) except SIPCoreError: remote_party = file[:-4] timestamp = datetime.fromtimestamp(int(stat.st_ctime)).strftime("%E %T") if filter_uris and remote_party not in filter_uris: continue result.append((timestamp, remote_party, file)) except Exception: pass result.sort(lambda a,b: cmp(a[0],b[0])) return result
def send_publish(self, uri, body): uri = re.sub("^(sip:|sips:)", "", uri) destination_node = self.provisioning.lookup(uri) if destination_node is not None: # TODO: add configuration settings for SIP transport. -Saul publication = Publication( FromHeader(SIPURI(uri)), "xcap-diff", "application/xcap-diff+xml", duration=0, extra_headers=[Header('Thor-Scope', 'publish-xcap')]) NotificationCenter().add_observer(self, sender=publication) route_header = RouteHeader( SIPURI(host=str(destination_node), port='5060', parameters=dict(transport='udp'))) publication.publish(body, route_header, timeout=5)
def _CH_register(self, command): notification_center = NotificationCenter() settings = SIPSimpleSettings() if self._registration_timer is not None and self._registration_timer.active( ): self._registration_timer.cancel() self._registration_timer = None # Initialize the registration if self._registration is None: duration = command.refresh_interval or self.account.sip.register_interval self._registration = Registration( FromHeader(self.account.uri, self.account.display_name), credentials=self.account.credentials, duration=duration, extra_headers=[Header('Supported', 'gruu')]) notification_center.add_observer(self, sender=self._registration) notification_center.post_notification('SIPAccountWillRegister', sender=self.account) else: notification_center.post_notification( 'SIPAccountRegistrationWillRefresh', sender=self.account) try: # Lookup routes if self.account.sip.outbound_proxy is not None and self.account.sip.outbound_proxy.transport in settings.sip.transport_list: uri = SIPURI(host=self.account.sip.outbound_proxy.host, port=self.account.sip.outbound_proxy.port, parameters={ 'transport': self.account.sip.outbound_proxy.transport }) else: uri = SIPURI(host=self.account.id.domain) lookup = DNSLookup() try: routes = lookup.lookup_sip_proxy( uri, settings.sip.transport_list).wait() except DNSLookupError, e: retry_after = random.uniform(self._dns_wait, 2 * self._dns_wait) self._dns_wait = limit(2 * self._dns_wait, max=30) raise RegistrationError('DNS lookup failed: %s' % e, retry_after=retry_after) else:
def _NH_BlinkFileTransferDidComputeHash(self, sender, data): notification_center = NotificationCenter() settings = SIPSimpleSettings() self.stream = FileTransferStream(self.account, self.file_selector, 'sendonly') self.session = Session(self.account) notification_center.add_observer(self, sender=self.session) notification_center.add_observer(self, sender=self.stream) self.status = "Offering File..." self.ft_info.status = "proposing" BlinkLogger().log_info(u"Initiating DNS Lookup of %s to %s" % (self.account, self.target_uri)) lookup = DNSLookup() notification_center.add_observer(self, sender=lookup) if isinstance(self.account, Account) and self.account.sip.outbound_proxy is not None: uri = SIPURI(host=self.account.sip.outbound_proxy.host, port=self.account.sip.outbound_proxy.port, parameters={ 'transport': self.account.sip.outbound_proxy.transport }) BlinkLogger().log_info( u"Initiating DNS Lookup for SIP routes of %s (through proxy %s)" % (self.target_uri, uri)) elif isinstance(self.account, Account) and self.account.sip.always_use_my_proxy: uri = SIPURI(host=self.account.id.domain) BlinkLogger().log_info( u"Initiating DNS Lookup for SIP routes of %s (through account %s proxy)" % (self.target_uri, self.account.id)) else: uri = self.target_uri BlinkLogger().log_info( u"Initiating DNS Lookup for SIP routes of %s" % self.target_uri) notification_center.post_notification( "BlinkFileTransferInitiated", self, data=TimestampedNotificationData()) lookup.lookup_sip_proxy(uri, settings.sip.transport_list)
def checkURI(self, uri): if checkValidPhoneNumber(uri): return True if uri.startswith(('https:', 'http:')): url = urllib.parse.urlparse(uri) if url.scheme not in ('http', 'https'): return False return True if not uri.startswith(('sip:', 'sips:')): uri = "sip:%s" % uri try: SIPURI.parse(str(uri)) except SIPCoreError: return False return True
def validateParticipant(uri): if not (uri.startswith('sip:') or uri.startswith('sips:')): uri = "sip:%s" % uri try: sip_uri = SIPURI.parse(str(uri)) except SIPCoreError: return False else: return sip_uri.user is not None and sip_uri.host is not None
def checkURI(self, uri): if checkValidPhoneNumber(uri): return True if uri.startswith(('https:', 'http:')): url = urlparse.urlparse(uri) if url.scheme not in (u'http', u'https'): return False return True if not uri.startswith(('sip:', 'sips:')): uri = "sip:%s" % uri try: SIPURI.parse(str(uri)) except SIPCoreError: return False return True
def send(self): lookup = DNSLookup() settings = SIPSimpleSettings() account = DefaultAccount() if account.sip.outbound_proxy is not None: uri = SIPURI( host=account.sip.outbound_proxy.host, port=account.sip.outbound_proxy.port, parameters={'transport': account.sip.outbound_proxy.transport}) else: uri = self.to_uri try: routes = lookup.lookup_sip_proxy( uri, settings.sip.transport_list).wait() except DNSLookupError: msg = 'DNS lookup error while looking for %s proxy' % uri log.warning(msg) raise SIPMessageError(0, msg) else: route = routes.pop(0) from_header = FromHeader(self.from_uri) to_header = ToHeader(self.to_uri) route_header = RouteHeader(route.uri) notification_center = NotificationCenter() for chunk in chunks(self.body, 1000): if self.use_cpim: additional_headers = [] payload = CPIMPayload( self.body.encode('utf-8'), self.content_type, charset='utf-8', sender=ChatIdentity(self.from_uri, None), recipients=[ChatIdentity(self.to_uri, None)], additional_headers=additional_headers) payload, content_type = payload.encode() else: content_type = self.content_type payload = self.body.encode('utf-8') request = SIPMessageRequest(from_header, to_header, route_header, content_type, payload) notification_center.add_observer(self, sender=request) self._requests.add(request) request.send() error = None count = len(self._requests) while count > 0: notification = self._channel.wait() if notification.name == 'SIPMessageDidFail': error = (notification.data.code, notification.data.reason) count -= 1 self._requests.clear() if error is not None: raise SIPMessageError(*error)
def normalize_sip_uri_for_outgoing_session(target_uri, account): def format_uri(uri, default_domain, idd_prefix=None, prefix=None, strip_digits=None): if default_domain is not None: if "@" not in uri: if _pstn_match_regexp.match(uri): username = strip_addressbook_special_characters(uri) if idd_prefix: username = _pstn_plus_regexp.sub(idd_prefix, username) if strip_digits and len(username) > strip_digits: username = username[strip_digits:] if prefix: username = prefix + username else: username = uri uri = "%s@%s" % (username, default_domain) elif "." not in uri.split("@", 1)[1]: uri += "." + default_domain if not uri.startswith("sip:") and not uri.startswith("sips:"): uri = "sip:%s" % uri return uri try: target_uri = str(target_uri) except: show_error_panel( NSLocalizedString( "SIP address must not contain unicode characters: %s", "Label") % target_uri) return None if '@' not in target_uri and isinstance(account, BonjourAccount): show_error_panel( NSLocalizedString( "SIP address must contain host in bonjour mode: %s", "Label") % target_uri) return None target_uri = format_uri( target_uri, account.id.domain if not isinstance(account, BonjourAccount) else None, account.pstn.idd_prefix if not isinstance(account, BonjourAccount) else None, account.pstn.prefix if not isinstance(account, BonjourAccount) else None, account.pstn.strip_digits if not isinstance(account, BonjourAccount) else None) try: target_uri = SIPURI.parse(target_uri) except SIPCoreError: show_error_panel( NSLocalizedString("Invalid SIP address: %s", "Label") % target_uri) return None return target_uri
def incoming_sip_message(self, message_request, data): # Handle incoming MESSAGE from_header = data.headers.get('From', Null) to_header = data.headers.get('To', Null) content_type = data.headers.get('Content-Type', Null)[0] if from_header is Null or to_header is Null: message_request.answer(400) return message_request.answer(200) if content_type not in ('text/plain', 'text/html'): return source_uri = SIPURI.new(to_header.uri) destination_uri = SIPURI.new(from_header.uri) try: fact = self.facts.next() except StopIteration: return else: self.send_chuck_norris_fact(source_uri, destination_uri, fact)
def _refresh(self): account = DefaultAccount() transport = self.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) contact_header = ContactHeader(contact_uri) self._referral.refresh(contact_header=contact_header, timeout=2)
def get_uri(self): from sipsimple.core import SIPURI if self.transport in ('udp', 'tcp') and self.port == 5060: port = None elif self.transport == 'tls' and self.port == 5061: port = None else: port = self.port parameters = {'transport': self.transport} if self.transport != 'udp' else {} return SIPURI(host=self.address, port=port, parameters=parameters)
def _setup_new_subscriptions(self, urilist): # TODO: Add check to see active subscriptions so it doesn't subscribe twice # sets up a new subscription with the given list of URI's for uri in urilist: tempuri = uri if tempuri is None: tempuri = ToHeader( SIPURI(user=self.account.id.username, host=self.account.id.domain)) else: if '@' not in tempuri: tempuri = '%s@%s' % (tempuri, self.account.id.domain) if not uri.startswith('sip:') and not tempuri.startswith( 'sips:'): tempuri = 'sip:' + tempuri try: tempuri = ToHeader(SIPURI.parse(tempuri)) except SIPCoreError: self.output.put('Illegal SIP URI: %s' % tempuri) return 1 self.subscriptionqueue.append(tempuri) #reactor.callLater(0, self._subscribe) settings = SIPSimpleSettings() self._subscription_timeout = time() + 30 lookup = DNSLookup() notification_center = NotificationCenter() notification_center.add_observer(self, sender=lookup) proxyuri = None if self.account.sip.outbound_proxy is not None: proxyuri = SIPURI(host=self.account.sip.outbound_proxy.host, port=self.account.sip.outbound_proxy.port, parameters={ 'transport': self.account.sip.outbound_proxy.transport }) elif self.account.sip.always_use_my_proxy: proxyuri = SIPURI(host=self.account.id.domain) else: proxyuri = self.subscriptionqueue[0].uri lookup.lookup_sip_proxy(proxyuri, settings.sip.transport_list)
def sendReplicationMessage(self, response_code, text, content_type="message/cpim", timestamp=None): timestamp = timestamp or datetime.datetime.now(tzlocal()) # Lookup routes if self.account.sip.outbound_proxy is not None: uri = SIPURI(host=self.account.sip.outbound_proxy.host, port=self.account.sip.outbound_proxy.port, parameters={ 'transport': self.account.sip.outbound_proxy.transport }) else: uri = SIPURI(host=self.account.id.domain) lookup = DNSLookup() settings = SIPSimpleSettings() try: routes = lookup.lookup_sip_proxy( uri, settings.sip.transport_list).wait() except DNSLookupError: pass else: utf8_encode = content_type not in ( 'application/im-iscomposing+xml', 'message/cpim') extra_headers = [ Header("X-Offline-Storage", "no"), Header("X-Replication-Code", str(response_code)), Header("X-Replication-Timestamp", str(Timestamp(datetime.datetime.now()))) ] message_request = Message( FromHeader(self.account.uri, self.account.display_name), ToHeader(self.account.uri), RouteHeader(routes[0].get_uri()), content_type, text.encode('utf-8') if utf8_encode else text, credentials=self.account.credentials, extra_headers=extra_headers) message_request.send( 15 if content_type != "application/im-iscomposing+xml" else 5)
def create_uri(cls, account, address): if not address.startswith(('sip:', 'sips:')): address = 'sip:' + address username, separator, domain = address.partition('@') if not domain and isinstance(account, Account): domain = account.id.domain elif '.' not in domain and isinstance(account, Account): domain += '.' + account.id.domain elif not domain: raise ValueError('SIP address without domain') address = username + '@' + domain return SIPURI.parse(str(address))
def _start_outgoing_jingle_session(self, streams): if self.xmpp_identity.uri.resource is not None: self.sip_session.reject() return xmpp_manager = XMPPManager() local_jid = self.sip_identity.uri.as_xmpp_jid() remote_jid = self.xmpp_identity.uri.as_xmpp_jid() # If this was an invitation to a conference, use the information in the Referred-By header if self.sip_identity.uri.host in xmpp_manager.muc_domains and self.sip_session.transfer_info and self.sip_session.transfer_info.referred_by: try: referred_by_uri = SIPURI.parse(self.sip_session.transfer_info.referred_by) except SIPCoreError: self.sip_session.reject(488) return else: inviter_uri = FrozenURI(referred_by_uri.user, referred_by_uri.host) local_jid = inviter_uri.as_xmpp_jid() # Use disco to gather potential JIDs to call d = xmpp_manager.disco_client_protocol.requestItems(remote_jid, sender=local_jid) try: items = block_on(d) except Exception: items = [] if not items: self.sip_session.reject(480) return # Check which items support Jingle valid = [] for item in items: d = xmpp_manager.disco_client_protocol.requestInfo(item.entity, nodeIdentifier=item.nodeIdentifier, sender=local_jid) try: info = block_on(d) except Exception: continue if jingle.NS_JINGLE in info.features and jingle.NS_JINGLE_APPS_RTP in info.features: valid.append(item.entity) if not valid: self.sip_session.reject(480) return # TODO: start multiple sessions? self._xmpp_identity = Identity(FrozenURI.parse(valid[0])) notification_center = NotificationCenter() if self.sip_identity.uri.host in xmpp_manager.muc_domains: self.jingle_session = JingleSession(xmpp_manager.jingle_coin_protocol) else: self.jingle_session = JingleSession(xmpp_manager.jingle_protocol) notification_center.add_observer(self, sender=self.jingle_session) self.jingle_session.connect(self.sip_identity, self.xmpp_identity, streams, is_focus=self.sip_session.remote_focus)
def privmsg(self, user, channel, message): if channel == '*': return username = user.split('!', 1)[0] if username == self.nickname: return if channel == self.nickname: self.msg(username, "Sorry, I don't support private messages, I'm a bot.") return uri = SIPURI.parse('sip:%s@%s' % (urllib.quote(username), self.factory.config.server[0])) irc_message = IRCMessage(username, uri, message.decode('utf-8')) data = NotificationData(message=irc_message) NotificationCenter().post_notification('IRCBotGotMessage', self.factory, data)
def parse(cls, value): match = cls._re_format.match(value) if not match: raise ValueError('Cannot parse message/cpim identity header value: %r' % value) groupdict = match.groupdict() display_name = groupdict['display_name'] uri = groupdict['uri'] # FIXME: silly hack for sip-chatserver which sends incorrect URIs. -Luci if not uri.startswith(u'sip:') and not uri.startswith(u'sips:'): uri = u'sip:' + uri # FIXME: SIPURI is not unicode friendly and expects a str. -Luci uri = SIPURI.parse(str(uri)) return cls(uri, display_name)
def resolveAvatarUrl(self, url): if url.startswith("/avatar/"): uri = SIPURI.parse(url[8:].decode("hex")) # TODO: see if there is an official way to get this, including notification of changes # also needs fixing of webodf, allowing custom avatar renderer if self.account.uri == uri: avatar = IconManager().get('avatar') return avatar.filename if avatar != None else self.default_user_icon_filename contact, contact_uri = URIUtils.find_contact(uri) return contact.icon.filename return ""
def __eq__(self, other): if isinstance(other, ChatIdentity): return self.uri.user == other.uri.user and self.uri.host == other.uri.host elif isinstance(other, BaseSIPURI): return self.uri.user == other.user and self.uri.host == other.host elif isinstance(other, basestring): try: other_uri = SIPURI.parse(other) except Exception: return False else: return self.uri.user == other_uri.user and self.uri.host == other_uri.host else: return NotImplemented
def is_anonymous(uri): """ Check if the given URI is an anonymous uri """ if isinstance(uri, (SIPURI, FrozenSIPURI)): return (uri.user is None or uri.user.lower() == 'anonymous') and (uri.host is None or uri.host.lower() == 'anonymous.invalid') else: if not (uri.startswith('sip:') or uri.startswith('sips:')): uri = "sip:%s" % uri try: sip_uri = SIPURI.parse(str(uri)) except: return False else: return (sip_uri.user is None or sip_uri.user.lower() == 'anonymous') and (sip_uri.host is None or sip_uri.host.lower() == 'anonymous.invalid')
def is_sip_aor_format(uri): """ Check if the given URI is a full SIP URI with username and host. """ if isinstance(uri, (SIPURI, FrozenSIPURI)): return uri.user is not None and uri.host is not None else: if not (uri.startswith('sip:') or uri.startswith('sips:')): uri = "sip:%s" % uri try: sip_uri = SIPURI.parse(str(uri)) except: return False else: return sip_uri.user is not None and sip_uri.host is not None
def __init__(self, account, target_uri, filename, hash): self.account = account self.end_session_when_done = True self.error = False self.file_selector = FileSelector(name=filename, hash=hash) self.finished_transfer = False self.hash = hashlib.sha1() self.interrupted = False self.remote_identity = format_identity_to_string(target_uri) self.session = None self.session_ended = False self.started = False self.stream = None self.target_uri = SIPURI.new(target_uri) self.timer = None self.transfer_id = str(uuid.uuid1())
def _NH_DNSLookupDidSucceed(self, notification): notification_center = NotificationCenter() notification_center.remove_observer(self, sender=notification.sender) account = DefaultAccount() conference_application = ConferenceApplication() try: room = conference_application.get_room(self.room_uri) except RoomNotFoundError: log.msg("Room %s - failed to add %s" % (self.room_uri_str, self.refer_to_uri)) self._refer_request.end(500) return active_media = set(room.active_media).intersection(("audio", "chat")) if not active_media: log.msg("Room %s - failed to add %s" % (self.room_uri_str, self.refer_to_uri)) self._refer_request.end(500) return registry = MediaStreamRegistry() for stream_type in active_media: self.streams.append(registry.get(stream_type)()) self.session = Session(account) notification_center.add_observer(self, sender=self.session) original_from_header = self._refer_headers.get("From") if original_from_header.display_name: original_identity = "%s <%s@%s>" % ( original_from_header.display_name, original_from_header.uri.user, original_from_header.uri.host, ) else: original_identity = "%s@%s" % (original_from_header.uri.user, original_from_header.uri.host) from_header = FromHeader(SIPURI.new(self.room_uri), u"Conference Call") to_header = ToHeader(self.refer_to_uri) extra_headers = [] if self._refer_headers.get("Referred-By", None) is not None: extra_headers.append(Header.new(self._refer_headers.get("Referred-By"))) else: extra_headers.append(Header("Referred-By", str(original_from_header.uri))) if ThorNodeConfig.enabled: extra_headers.append(Header("Thor-Scope", "conference-invitation")) extra_headers.append(Header("X-Originator-From", str(original_from_header.uri))) extra_headers.append(SubjectHeader(u"Join conference request from %s" % original_identity)) route = notification.data.result[0] self.session.connect( from_header, to_header, route=route, streams=self.streams, is_focus=True, extra_headers=extra_headers )
def _lookup_sip_proxy(self, account): sip_uri = SIPURI.parse('sip:%s' % account) # The proxy dance: Sofia-SIP seems to do a DNS lookup per SIP message when a domain is passed # as the proxy, so do the resolution ourselves and give it pre-resolver proxy URL. Since we use # caching to avoid long delays, we randomize the results matching the highest priority route's # transport. proxy = GeneralConfig.outbound_sip_proxy if proxy is not None: proxy_uri = SIPURI(host=proxy.host, port=proxy.port, parameters={'transport': proxy.transport}) else: proxy_uri = SIPURI(host=sip_uri.host) settings = SIPSimpleSettings() try: routes = self.resolver.lookup_sip_proxy(proxy_uri, settings.sip.transport_list).wait() except DNSLookupError, e: raise DNSLookupError('DNS lookup error: %s' % e)
def normalize_sip_uri_for_outgoing_session(target_uri, account): def format_uri(uri, default_domain, idd_prefix = None, prefix = None, strip_digits=None): if default_domain is not None: if "@" not in uri: if _pstn_match_regexp.match(uri): username = strip_addressbook_special_characters(uri) if idd_prefix: username = _pstn_plus_regexp.sub(idd_prefix, username) if strip_digits and len(username) > strip_digits: username = username[strip_digits:] if prefix: username = prefix + username else: username = uri uri = "%s@%s" % (username, default_domain) elif "." not in uri.split("@", 1)[1]: uri += "." + default_domain if not uri.startswith("sip:") and not uri.startswith("sips:"): uri = "sip:%s" % uri return uri try: target_uri = str(target_uri) except: show_error_panel(NSLocalizedString("SIP address must not contain unicode characters: %s", "Label") % target_uri) return None if '@' not in target_uri and isinstance(account, BonjourAccount): show_error_panel(NSLocalizedString("SIP address must contain host in bonjour mode: %s", "Label") % target_uri) return None target_uri = format_uri(target_uri, account.id.domain if not isinstance(account, BonjourAccount) else None, account.pstn.idd_prefix if not isinstance(account, BonjourAccount) else None, account.pstn.prefix if not isinstance(account, BonjourAccount) else None, account.pstn.strip_digits if not isinstance(account, BonjourAccount) else None) try: target_uri = SIPURI.parse(target_uri) except SIPCoreError: show_error_panel(NSLocalizedString("Invalid SIP address: %s", "Label") % target_uri) return None return target_uri
def _OH_account_add(self, data): transaction = data.get('transaction', None) if transaction is None: log.warn('Transaction not specified!') return try: try: account = data['account'] password = data['password'] except KeyError: raise APIError('Invalid parameters: "account" and "password" must be specified') if account in self.accounts_map: log.warn('Account %s already added' % account) data = dict(sylkrtc='error', transaction=transaction, error='Account already added') self._send_data(json.dumps(data)) return # Validate URI uri = 'sip:%s' % account try: sip_uri = SIPURI.parse(uri) except SIPCoreError: raise APIError('Invalid account specified: %s' % account) if not {'*', sip_uri.host}.intersection(GeneralConfig.sip_domains): raise APIError('SIP domain not allowed: %s' % sip_uri.host) # Create and store our mapping account_info = AccountInfo(account, password) self.accounts_map[account_info.id] = account_info data = dict(sylkrtc='ack', transaction=transaction) self._send_data(json.dumps(data)) log.msg('Account %s added' % account) except APIError, e: log.error('account_add: %s' % e) data = dict(sylkrtc='error', transaction=transaction, error=str(e)) self._send_data(json.dumps(data))
def call(self, account_name, callee, wave_file, length=None): logging.info("calling from: %s - to: %s", account_name, callee) # Setup wave playback self.player = WavePlayer(SIPApplication.voice_audio_mixer, wave_file, loop_count=0, initial_play=False) # configure callee and route to him/her callee_header = ToHeader(SIPURI.parse(callee)) routes = [Route("62.220.31.184", 5060, "udp")] # locate caller account = self.accounts.get(account_name, None) if account is None: raise Exception("No account with that name found") # finally make the call session = Session(account) session.connect(callee_header, routes, [AudioStream()]) # if we got a length, end the call after it if not length is None: time.sleep(length) session.end()
def is_anonymous(uri): """ Check if the given URI is an anonymous uri """ anon_users = ('asterisk', 'unknown', 'anonymous') if isinstance(uri, (SIPURI, FrozenSIPURI)): if uri.user.lower() in anon_users: return True return (uri.user is None or uri.user.lower() == 'anonymous') and (uri.host is None or uri.host.lower() == 'anonymous.invalid') else: if not (uri.startswith('sip:') or uri.startswith('sips:')): uri = "sip:%s" % uri try: sip_uri = SIPURI.parse(str(uri)) except: return False else: if sip_uri.user is not None and sip_uri.user.lower() in anon_users: return True return (sip_uri.user is None or sip_uri.user.lower() == 'anonymous') and (sip_uri.host is None or sip_uri.host.lower() == 'anonymous.invalid')
continue else: notification_data = NotificationData(code=notification.data.code, reason=notification.data.reason, registration=self._registration, registrar=route) notification_center.post_notification('SIPAccountRegistrationGotAnswer', sender=self.account, data=notification_data) self.registered = True # Save GRUU try: header = next(header for header in notification.data.contact_header_list if header.parameters.get('+sip.instance', '').strip('"<>') == settings.instance_id) except StopIteration: self.account.contact.public_gruu = None self.account.contact.temporary_gruu = None else: public_gruu = header.parameters.get('pub-gruu', None) temporary_gruu = header.parameters.get('temp-gruu', None) try: self.account.contact.public_gruu = SIPURI.parse(public_gruu.strip('"')) except (AttributeError, SIPCoreError): self.account.contact.public_gruu = None try: self.account.contact.temporary_gruu = SIPURI.parse(temporary_gruu.strip('"')) except (AttributeError, SIPCoreError): self.account.contact.temporary_gruu = None notification_data = NotificationData(contact_header=notification.data.contact_header, contact_header_list=notification.data.contact_header_list, expires=notification.data.expires_in, registrar=route) notification_center.post_notification('SIPAccountRegistrationDidSucceed', sender=self.account, data=notification_data) self._register_wait = 1 command.signal() break else: # There are no more routes to try, reschedule the registration
def _NH_SIPEngineGotMessage(self, sender, data): account = AccountManager().find_account(data.request_uri) if not account: BlinkLogger().log_warning(u"Could not find recipient account for message to %s, using default" % data.request_uri) account = AccountManager().default_account is_cpim = False cpim_message = None replication_message = False if data.content_type == 'message/cpim': try: cpim_message = CPIMMessage.parse(data.body) except CPIMParserError: BlinkLogger().log_warning(u"SMS from %s has invalid CPIM content" % format_identity_to_string(data.from_header)) return else: is_cpim = True body = cpim_message.body content_type = cpim_message.content_type sender_identity = cpim_message.sender or data.from_header if cpim_message.sender and data.from_header.uri == data.to_header.uri and data.from_header.uri == cpim_message.sender.uri: replication_message = True window_tab_identity = cpim_message.recipients[0] if cpim_message.recipients else data.to_header else: window_tab_identity = data.from_header else: body = data.body.decode('utf-8') content_type = data.content_type sender_identity = data.from_header window_tab_identity = sender_identity is_html = content_type == 'text/html' if content_type in ('text/plain', 'text/html'): BlinkLogger().log_info(u"Got SMS from %s" % format_identity_to_string(sender_identity)) elif content_type == 'application/im-iscomposing+xml': # body must not be utf-8 decoded body = cpim_message.body if is_cpim else data.body msg = IsComposingMessage.parse(body) state = msg.state.value refresh = msg.refresh.value if msg.refresh is not None else None content_type = msg.content_type.value if msg.content_type is not None else None last_active = msg.last_active.value if msg.last_active is not None else None viewer = self.openMessageWindow(SIPURI.new(window_tab_identity.uri), window_tab_identity.display_name, account, create_if_needed=False, note_new_message=False) if viewer: viewer.gotIsComposing(self.windowForViewer(viewer), state, refresh, last_active) return else: BlinkLogger().log_warning(u"SMS from %s has unknown content-type %s" % (format_identity_to_string(data.from_header), data.content_type)) return # display the message note_new_message = False if replication_message else True viewer = self.openMessageWindow(SIPURI.new(window_tab_identity.uri), window_tab_identity.display_name, account, note_new_message=note_new_message) self.windowForViewer(viewer).noteNewMessageForSession_(viewer) replication_state = None replication_timestamp = None if replication_message: replicated_response_code = data.headers.get('X-Replication-Code', Null).body if replicated_response_code == '202': replication_state = 'deferred' elif replicated_response_code == '200': replication_state = 'delivered' else: replication_state = 'failed' replicated_timestamp = data.headers.get('X-Replication-Timestamp', Null).body try: replication_timestamp = Timestamp.parse(replicated_timestamp) except (TypeError, ValueError): replication_timestamp = Timestamp(datetime.datetime.now(tzlocal())) viewer.gotMessage(sender_identity, body, is_html, replication_state, replication_timestamp) self.windowForViewer(viewer).noteView_isComposing_(viewer, False) if replication_message: return if not self.windowForViewer(viewer).window().isKeyWindow(): # notify growl growl_data = TimestampedNotificationData() if is_html: growl_data.content = html2txt(body) else: growl_data.content = body growl_data.sender = format_identity_to_string(sender_identity, format='compact') self.notification_center.post_notification("GrowlGotSMS", sender=self, data=growl_data)
def incoming_chat_session(self, session): # Check if this session is really an invitation to add a participant to a conference room / muc if ( session.remote_identity.uri.host in self.xmpp_manager.muc_domains and "isfocus" in session._invitation.remote_contact_header.parameters ): try: referred_by_uri = SIPURI.parse(session.transfer_info.referred_by) except SIPCoreError: log.msg("SIP multiparty session invitation %s failed: invalid Referred-By header" % session.call_id) session.reject(488) return muc_uri = FrozenURI(session.remote_identity.uri.user, session.remote_identity.uri.host) inviter_uri = FrozenURI(referred_by_uri.user, referred_by_uri.host) recipient_uri = FrozenURI(session.local_identity.uri.user, session.local_identity.uri.host) sender = Identity(muc_uri) recipient = Identity(recipient_uri) inviter = Identity(inviter_uri) try: handler = self.s2x_muc_add_participant_handlers[(muc_uri, recipient_uri)] except KeyError: handler = S2XMucInvitationHandler(session, sender, recipient, inviter) self.s2x_muc_add_participant_handlers[(muc_uri, recipient_uri)] = handler NotificationCenter().add_observer(self, sender=handler) handler.start() else: log.msg( "SIP multiparty session invitation %s failed: there is another invitation in progress from %s to %s" % (session.call_id, format_uri(inviter_uri, "sip"), format_uri(recipient_uri, "xmpp")) ) session.reject(480) return # Check domain if session.remote_identity.uri.host not in XMPPGatewayConfig.domains: log.msg("Session rejected: From domain is not a local XMPP domain") session.reject(606, "Not Acceptable") return # Get URI representing the SIP side contact_uri = session._invitation.remote_contact_header.uri if contact_uri.parameters.get("gr") is not None: sip_leg_uri = FrozenURI(contact_uri.user, contact_uri.host, contact_uri.parameters.get("gr")) else: tmp = session.remote_identity.uri sip_leg_uri = FrozenURI(tmp.user, tmp.host, generate_sylk_resource()) # Get URI representing the XMPP side request_uri = session.request_uri remote_resource = request_uri.parameters.get("gr", None) if remote_resource is not None: try: remote_resource = decode_resource(remote_resource) except (TypeError, UnicodeError): remote_resource = None xmpp_leg_uri = FrozenURI(request_uri.user, request_uri.host, remote_resource) try: handler = self.pending_sessions[(sip_leg_uri, xmpp_leg_uri)] except KeyError: pass else: # There is another pending session with same identifiers, can't accept this one log.msg("Session rejected: other session with same identifiers in progress") session.reject(488) return sip_identity = Identity(sip_leg_uri, session.remote_identity.display_name) handler = ChatSessionHandler.new_from_sip_session(sip_identity, session) NotificationCenter().add_observer(self, sender=handler) key = (sip_leg_uri, xmpp_leg_uri) self.pending_sessions[key] = handler if xmpp_leg_uri.resource is not None: # Incoming session target contained GRUU, so create XMPPChatSession immediately xmpp_session = XMPPChatSession(local_identity=handler.sip_identity, remote_identity=Identity(xmpp_leg_uri)) handler.xmpp_identity = xmpp_session.remote_identity handler.xmpp_session = xmpp_session
def as_sip_uri(self): uri = SIPURI(user=str(self.user), host=str(self.host)) if self.resource is not None: uri.parameters['gr'] = self.resource.encode('utf-8') return uri
def URIValidator(value): account = SIP_PREFIX_RE.sub('', value) try: SIPURI.parse('sip:%s' % account) except SIPCoreError: raise errors.ValidationError('invalid account: %s' % value)