コード例 #1
0
ファイル: logging.py プロジェクト: pallabchow/blink-qt
class LogManager(object):
    __metaclass__ = Singleton

    implements(IObserver)

    def __init__(self):
        self.name = os.path.basename(sys.argv[0]).rsplit('.py', 1)[0]
        self.pid = os.getpid()
        self.msrp_level = log.level.INFO
        self.siptrace_file = Null
        self.msrptrace_file = Null
        self.pjsiptrace_file = Null
        self.notifications_file = Null
        self.event_queue = Null
        self.notification_queue = NotificationQueue()
        self._siptrace_start_time = None
        self._siptrace_packet_count = None

    def start(self):
        settings = SIPSimpleSettings()
        notification_center = NotificationCenter()
        notification_center.add_observer(self)
        if settings.logs.trace_sip:
            self.siptrace_file = LogFile(
                os.path.join(ApplicationData.directory, 'logs',
                             'sip_trace.txt'))
        if settings.logs.trace_msrp:
            self.msrptrace_file = LogFile(
                os.path.join(ApplicationData.directory, 'logs',
                             'msrp_trace.txt'))
        if settings.logs.trace_pjsip:
            self.pjsiptrace_file = LogFile(
                os.path.join(ApplicationData.directory, 'logs',
                             'pjsip_trace.txt'))
        if settings.logs.trace_notifications:
            self.notifications_file = LogFile(
                os.path.join(ApplicationData.directory, 'logs',
                             'notifications_trace.txt'))
        self._siptrace_start_time = datetime.now()
        self._siptrace_packet_count = 0
        self.event_queue = EventQueue(handler=self._process_notification,
                                      name='Blink LogManager')
        self.event_queue.start()
        while settings.logs.trace_notifications and self.notification_queue and self.notification_queue.notifications:
            notification = self.notification_queue.notifications.popleft()
            self.handle_notification(notification)
        self.notification_queue = None

    def stop(self):
        notification_center = NotificationCenter()
        notification_center.remove_observer(self)

        self.event_queue.stop()
        self.event_queue.join()
        self.event_queue = Null

        self.siptrace_file = Null
        self.msrptrace_file = Null
        self.pjsiptrace_file = Null
        self.notifications_file = Null

    def handle_notification(self, notification):
        self.event_queue.put(notification)

    def _process_notification(self, notification):
        handler = getattr(self, '_NH_%s' % notification.name, Null)
        handler(notification)

        handler = getattr(self, '_LH_%s' % notification.name, Null)
        handler(notification)

        settings = SIPSimpleSettings()
        if notification.name not in ('SIPEngineLog', 'SIPEngineSIPTrace'
                                     ) and settings.logs.trace_notifications:
            message = 'Notification name=%s sender=%s data=%s' % (
                notification.name, notification.sender,
                pformat(notification.data))
            try:
                self.notifications_file.write(
                    '%s [%s %d]: %s\n' %
                    (datetime.now(), self.name, self.pid, message))
                self.notifications_file.flush()
            except Exception:
                pass

    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 _LH_SIPEngineSIPTrace(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_sip:
            return
        self._siptrace_packet_count += 1
        if notification.data.received:
            direction = "RECEIVED"
        else:
            direction = "SENDING"
        buf = [
            "%s: Packet %d, +%s" %
            (direction, self._siptrace_packet_count,
             (notification.datetime - self._siptrace_start_time)),
            "%(source_ip)s:%(source_port)d -(SIP over %(transport)s)-> %(destination_ip)s:%(destination_port)d"
            % notification.data.__dict__, notification.data.data, '--'
        ]
        message = '\n'.join(buf)
        try:
            self.siptrace_file.write(
                '%s [%s %d]: %s\n' %
                (notification.datetime, self.name, self.pid, message))
            self.siptrace_file.flush()
        except Exception:
            pass

    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 _LH_DNSLookupTrace(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_sip:
            return
        message = 'DNS lookup %(query_type)s %(query_name)s' % notification.data.__dict__
        if notification.data.error is None:
            message += ' succeeded, ttl=%d: ' % notification.data.answer.ttl
            if notification.data.query_type == 'A':
                message += ", ".join(record.address
                                     for record in notification.data.answer)
            elif notification.data.query_type == 'SRV':
                message += ", ".join('%d %d %d %s' %
                                     (record.priority, record.weight,
                                      record.port, record.target)
                                     for record in notification.data.answer)
            elif notification.data.query_type == 'NAPTR':
                message += ", ".join(
                    '%d %d "%s" "%s" "%s" %s' %
                    (record.order, record.preference, record.flags,
                     record.service, record.regexp, record.replacement)
                    for record in notification.data.answer)
        else:
            import dns.resolver
            message_map = {
                dns.resolver.NXDOMAIN:
                'DNS record does not exist',
                dns.resolver.NoAnswer:
                'DNS response contains no answer',
                dns.resolver.NoNameservers:
                'no DNS name servers could be reached',
                dns.resolver.Timeout:
                'no DNS response received, the query has timed out'
            }
            message += ' failed: %s' % message_map.get(
                notification.data.error.__class__, '')
        try:
            self.siptrace_file.write(
                '%s [%s %d]: %s\n' %
                (notification.datetime, self.name, self.pid, message))
            self.siptrace_file.flush()
        except Exception:
            pass

    def _LH_MSRPTransportTrace(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_msrp:
            return
        arrow = {
            'incoming': '<--',
            'outgoing': '-->'
        }[notification.data.direction]
        local_address = '%s:%d' % (notification.data.local_address.host,
                                   notification.data.local_address.port)
        remote_address = '%s:%d' % (notification.data.remote_address.host,
                                    notification.data.remote_address.port)
        message = '%s %s %s\n' % (local_address, arrow,
                                  remote_address) + notification.data.data
        prefix = '[Illegal request!] ' if notification.data.illegal else ''
        try:
            self.msrptrace_file.write(
                '%s [%s %d]: %s%s\n' %
                (notification.datetime, self.name, self.pid, prefix, message))
            self.msrptrace_file.flush()
        except Exception:
            pass

    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
コード例 #2
0
ファイル: log.py プロジェクト: grengojbo/sipclients
class Logger(object):
    implements(IObserver)

    # public methods
    #

    def __init__(
        self,
        sip_to_stdout=False,
        msrp_to_stdout=False,
        pjsip_to_stdout=False,
        notifications_to_stdout=False,
        msrp_level=log.level.ERROR,
    ):
        self.sip_to_stdout = sip_to_stdout
        self.msrp_to_stdout = msrp_to_stdout
        self.pjsip_to_stdout = pjsip_to_stdout
        self.notifications_to_stdout = notifications_to_stdout
        self.msrp_level = msrp_level

        self._siptrace_filename = None
        self._siptrace_file = None
        self._siptrace_error = False
        self._siptrace_start_time = None
        self._siptrace_packet_count = 0

        self._msrptrace_filename = None
        self._msrptrace_file = None
        self._msrptrace_error = False

        self._pjsiptrace_filename = None
        self._pjsiptrace_file = None
        self._pjsiptrace_error = False

        self._notifications_filename = None
        self._notifications_file = None
        self._notifications_error = False

        self._event_queue = EventQueue(handler=self._process_notification, name="Log handling")
        self._log_directory_error = False

    def start(self):
        # try to create the log directory
        try:
            self._init_log_directory()
        except Exception:
            pass

        # register to receive log notifications
        notification_center = NotificationCenter()
        notification_center.add_observer(self)

        # start the thread processing the notifications
        self._event_queue.start()

    def stop(self):
        # stop the thread processing the notifications
        self._event_queue.stop()
        self._event_queue.join()

        # close sip trace file
        if self._siptrace_file is not None:
            self._siptrace_file.close()
            self._siptrace_file = None

        # close msrp trace file
        if self._msrptrace_file is not None:
            self._msrptrace_file.close()
            self._msrptrace_file = None

        # close pjsip trace file
        if self._pjsiptrace_file is not None:
            self._pjsiptrace_file.close()
            self._pjsiptrace_file = None

        # close notifications trace file
        if self._notifications_file is not None:
            self._notifications_file.close()
            self._notifications_file = None

        # unregister from receiving notifications
        notification_center = NotificationCenter()
        notification_center.remove_observer(self)

    def handle_notification(self, notification):
        self._event_queue.put(notification)

    def _process_notification(self, notification):
        settings = SIPSimpleSettings()
        handler = getattr(self, "_NH_%s" % notification.name, None)
        if handler is not None:
            handler(notification)

        handler = getattr(self, "_LH_%s" % notification.name, None)
        if handler is not None:
            handler(notification)

        if notification.name not in ("SIPEngineLog", "SIPEngineSIPTrace") and (
            self.notifications_to_stdout or settings.logs.trace_notifications
        ):
            message = "Notification name=%s sender=%s" % (notification.name, notification.sender)
            if notification.data is not None:
                message += "\n%s" % pformat(notification.data.__dict__)
            if self.notifications_to_stdout:
                print "%s: %s" % (datetime.datetime.now(), message)
            if settings.logs.trace_notifications:
                try:
                    self._init_log_file("notifications")
                except Exception:
                    pass
                else:
                    self._notifications_file.write(
                        "%s [%s %d]: %s\n"
                        % (datetime.datetime.now(), os.path.basename(sys.argv[0]).rstrip(".py"), os.getpid(), message)
                    )
                    self._notifications_file.flush()

    # notification handlers
    #

    def _NH_CFGSettingsObjectDidChange(self, notification):
        settings = SIPSimpleSettings()
        if notification.sender is settings:
            if "logs.directory" in notification.data.modified:
                # sip trace
                if self._siptrace_file is not None:
                    self._siptrace_file.close()
                    self._siptrace_file = None
                # pjsip trace
                if self._pjsiptrace_file is not None:
                    self._pjsiptrace_file.close()
                    self._pjsiptrace_file = None
                # notifications trace
                if self._notifications_file is not None:
                    self._notifications_file.close()
                    self._notifications_file = None
                # try to create the log directory
                try:
                    self._init_log_directory()
                except Exception:
                    pass

    # log handlers
    #

    def _LH_SIPEngineSIPTrace(self, notification):
        settings = SIPSimpleSettings()
        if not self.sip_to_stdout and not settings.logs.trace_sip:
            return
        if self._siptrace_start_time is None:
            self._siptrace_start_time = notification.data.timestamp
        self._siptrace_packet_count += 1
        if notification.data.received:
            direction = "RECEIVED"
        else:
            direction = "SENDING"
        buf = [
            "%s: Packet %d, +%s"
            % (direction, self._siptrace_packet_count, (notification.data.timestamp - self._siptrace_start_time))
        ]
        buf.append(
            "%(source_ip)s:%(source_port)d -(SIP over %(transport)s)-> %(destination_ip)s:%(destination_port)d"
            % notification.data.__dict__
        )
        buf.append(notification.data.data)
        buf.append("--")
        message = "\n".join(buf)
        if self.sip_to_stdout:
            print "%s: %s\n" % (notification.data.timestamp, message)
        if settings.logs.trace_sip:
            try:
                self._init_log_file("siptrace")
            except Exception:
                pass
            else:
                self._siptrace_file.write(
                    "%s [%s %d]: %s\n"
                    % (notification.data.timestamp, os.path.basename(sys.argv[0]).rstrip(".py"), os.getpid(), message)
                )
                self._siptrace_file.flush()

    def _LH_SIPEngineLog(self, notification):
        settings = SIPSimpleSettings()
        if not self.pjsip_to_stdout and not settings.logs.trace_pjsip:
            return
        message = "(%(level)d) %(sender)14s: %(message)s" % notification.data.__dict__
        if self.pjsip_to_stdout:
            print "%s %s" % (notification.data.timestamp, message)
        if settings.logs.trace_pjsip:
            try:
                self._init_log_file("pjsiptrace")
            except Exception:
                pass
            else:
                self._pjsiptrace_file.write(
                    "%s [%s %d] %s\n"
                    % (notification.data.timestamp, os.path.basename(sys.argv[0]).rstrip(".py"), os.getpid(), message)
                )
                self._pjsiptrace_file.flush()

    def _LH_DNSLookupTrace(self, notification):
        settings = SIPSimpleSettings()
        if not self.sip_to_stdout and not settings.logs.trace_sip:
            return
        message = "DNS lookup %(query_type)s %(query_name)s" % notification.data.__dict__
        if notification.data.error is None:
            message += " succeeded, ttl=%d: " % notification.data.answer.ttl
            if notification.data.query_type == "A":
                message += ", ".join(record.address for record in notification.data.answer)
            elif notification.data.query_type == "SRV":
                message += ", ".join(
                    "%d %d %d %s" % (record.priority, record.weight, record.port, record.target)
                    for record in notification.data.answer
                )
            elif notification.data.query_type == "NAPTR":
                message += ", ".join(
                    '%d %d "%s" "%s" "%s" %s'
                    % (record.order, record.preference, record.flags, record.service, record.regexp, record.replacement)
                    for record in notification.data.answer
                )
        else:
            import dns.resolver

            message_map = {
                dns.resolver.NXDOMAIN: "DNS record does not exist",
                dns.resolver.NoAnswer: "DNS response contains no answer",
                dns.resolver.NoNameservers: "no DNS name servers could be reached",
                dns.resolver.Timeout: "no DNS response received, the query has timed out",
            }
            message += " failed: %s" % message_map.get(notification.data.error.__class__, "")
        if self.sip_to_stdout:
            print "%s: %s" % (notification.data.timestamp, message)
        if settings.logs.trace_sip:
            try:
                self._init_log_file("siptrace")
            except Exception:
                pass
            else:
                self._siptrace_file.write(
                    "%s [%s %d]: %s\n"
                    % (notification.data.timestamp, os.path.basename(sys.argv[0]).rstrip(".py"), os.getpid(), message)
                )
                self._siptrace_file.flush()

    def _LH_MSRPTransportTrace(self, notification):
        settings = SIPSimpleSettings()
        if not self.msrp_to_stdout and not settings.logs.trace_msrp:
            return
        arrow = {"incoming": "<--", "outgoing": "-->"}[notification.data.direction]
        local_address = notification.sender.getHost()
        local_address = "%s:%d" % (local_address.host, local_address.port)
        remote_address = notification.sender.getPeer()
        remote_address = "%s:%d" % (remote_address.host, remote_address.port)
        message = "%s %s %s\n" % (local_address, arrow, remote_address) + notification.data.data
        if self.msrp_to_stdout:
            print "%s: %s" % (notification.data.timestamp, message)
        if settings.logs.trace_msrp:
            try:
                self._init_log_file("msrptrace")
            except Exception:
                pass
            else:
                self._msrptrace_file.write(
                    "%s [%s %d]: %s\n"
                    % (notification.data.timestamp, os.path.basename(sys.argv[0]).rstrip(".py"), os.getpid(), message)
                )
                self._msrptrace_file.flush()

    def _LH_MSRPLibraryLog(self, notification):
        settings = SIPSimpleSettings()
        if not self.msrp_to_stdout and not settings.logs.trace_msrp:
            return
        if notification.data.level < self.msrp_level:
            return
        message = "%s%s" % (notification.data.level.prefix, notification.data.message)
        if self.msrp_to_stdout:
            print "%s: %s" % (notification.data.timestamp, message)
        if settings.logs.trace_msrp:
            try:
                self._init_log_file("msrptrace")
            except Exception:
                pass
            else:
                self._msrptrace_file.write(
                    "%s [%s %d]: %s\n"
                    % (notification.data.timestamp, os.path.basename(sys.argv[0]).rstrip(".py"), os.getpid(), message)
                )
                self._msrptrace_file.flush()

    # private methods
    #

    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._siptrace_error = True
            self._pjsiptrace_error = True
            self._notifications_error = True
            raise
        else:
コード例 #3
0
ファイル: BlinkLogger.py プロジェクト: wilane/blink-cocoa
class FileLogger(object):
    implements(IObserver)

    # public methods
    #

    def __init__(self, msrp_level=log.level.INFO):
        self.msrp_level = msrp_level

        self._siptrace_filename = None
        self._siptrace_file = None
        self._siptrace_error = False
        self._siptrace_start_time = None
        self._siptrace_packet_count = 0

        self._msrptrace_filename = None
        self._msrptrace_file = None
        self._msrptrace_error = False

        self._pjsiptrace_filename = None
        self._pjsiptrace_file = None
        self._pjsiptrace_error = False

        self._notifications_filename = None
        self._notifications_file = None
        self._notifications_error = False

        self._event_queue = EventQueue(handler=self._process_notification, name='Log handling')
        self._log_directory_error = False

    def start(self):
        # try to create the log directory
        try:
            self._init_log_directory()
        except Exception:
            pass

        # register to receive log notifications
        notification_center = NotificationCenter()
        notification_center.add_observer(self)

        # start the thread processing the notifications
        self._event_queue.start()

    def stop(self):
        # stop the thread processing the notifications
        self._event_queue.stop()
        self._event_queue.join()

        # close sip trace file
        if self._siptrace_file is not None:
            self._siptrace_file.close()
            self._siptrace_file = None

        # close msrp trace file
        if self._msrptrace_file is not None:
            self._msrptrace_file.close()
            self._msrptrace_file = None

        # close pjsip trace file
        if self._pjsiptrace_file is not None:
            self._pjsiptrace_file.close()
            self._pjsiptrace_file = None

        # close notifications trace file
        if self._notifications_file is not None:
            self._notifications_file.close()
            self._notifications_file = None

        # unregister from receiving notifications
        notification_center = NotificationCenter()
        notification_center.remove_observer(self)

    def handle_notification(self, notification):
        self._event_queue.put(notification)

    @allocate_autorelease_pool
    def _process_notification(self, notification):
        settings = SIPSimpleSettings()
        handler = getattr(self, '_NH_%s' % notification.name, None)
        if handler is not None:
            handler(notification)

        handler = getattr(self, '_LH_%s' % notification.name, None)
        if handler is not None:
            handler(notification)

        if notification.name not in ('SIPEngineLog', 'SIPEngineSIPTrace') and settings.logs.trace_notifications:
            try:
                self._init_log_file('notifications')
            except Exception:
                pass
            else:
                message = 'Notification name=%s sender=%s data=%s' % (notification.name, notification.sender, pformat(notification.data))
                self._notifications_file.write('%s: %s\n' % (datetime.datetime.now(), message))
                self._notifications_file.flush()

    # notification handlers
    #

    def _NH_CFGSettingsObjectDidChange(self, notification):
        settings = SIPSimpleSettings()
        if notification.sender is settings:
            if 'logs.directory' in notification.data.modified:
                # sip trace
                if self._siptrace_file is not None:
                    self._siptrace_file.close()
                    self._siptrace_file = None
                # pjsip trace
                if self._pjsiptrace_file is not None:
                    self._pjsiptrace_file.close()
                    self._pjsiptrace_file = None
                # notifications trace
                if self._notifications_file is not None:
                    self._notifications_file.close()
                    self._notifications_file = None
                # try to create the log directory
                try:
                    self._init_log_directory()
                except Exception:
                    pass

    # log handlers
    #

    def _LH_SIPEngineSIPTrace(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_sip:
            return
        if self._siptrace_start_time is None:
            self._siptrace_start_time = notification.data.timestamp
        self._siptrace_packet_count += 1
        if notification.data.received:
            direction = "RECEIVED"
        else:
            direction = "SENDING"
        buf = ["%s: Packet %d, +%s" % (direction, self._siptrace_packet_count, (notification.data.timestamp - self._siptrace_start_time))]
        buf.append("%(source_ip)s:%(source_port)d -(SIP over %(transport)s)-> %(destination_ip)s:%(destination_port)d" % notification.data.__dict__)
        buf.append(notification.data.data)
        buf.append('--')
        message = '\n'.join(buf)
        try:
            self._init_log_file('siptrace')
        except Exception:
            pass
        else:
            self._siptrace_file.write('%s [%s %d]: %s\n' % (notification.data.timestamp, os.path.basename(sys.argv[0]).rstrip('.py'), os.getpid(), message))
            self._siptrace_file.flush()

    def _LH_SIPEngineLog(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_pjsip:
            return
        message = "(%(level)d) %(sender)14s: %(message)s" % notification.data.__dict__
        try:
            self._init_log_file('pjsiptrace')
        except Exception:
            pass
        else:
            self._pjsiptrace_file.write('%s [%s %d] %s\n' % (notification.data.timestamp, os.path.basename(sys.argv[0]).rstrip('.py'), os.getpid(), message))
            self._pjsiptrace_file.flush()

    def _LH_DNSLookupTrace(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_sip:
            return
        message = 'DNS lookup %(query_type)s %(query_name)s' % notification.data.__dict__
        if notification.data.error is None:
            message += ' succeeded, ttl=%d: ' % notification.data.answer.ttl
            if notification.data.query_type == 'A':
                message += ", ".join(record.address for record in notification.data.answer)
            elif notification.data.query_type == 'SRV':
                message += ", ".join('%d %d %d %s' % (record.priority, record.weight, record.port, record.target) for record in notification.data.answer)
            elif notification.data.query_type == 'NAPTR':
                message += ", ".join('%d %d "%s" "%s" "%s" %s' % (record.order, record.preference, record.flags, record.service, record.regexp, record.replacement) for record in notification.data.answer)
        else:
            import dns.resolver
            message_map = {dns.resolver.NXDOMAIN: 'DNS record does not exist',
                           dns.resolver.NoAnswer: 'DNS response contains no answer',
                           dns.resolver.NoNameservers: 'no DNS name servers could be reached',
                           dns.resolver.Timeout: 'no DNS response received, the query has timed out'}
            message += ' failed: %s' % message_map.get(notification.data.error.__class__, '')
        try:
            self._init_log_file('siptrace')
        except Exception:
            pass
        else:
            self._siptrace_file.write('%s [%s %d]: %s\n' % (notification.data.timestamp, os.path.basename(sys.argv[0]).rstrip('.py'), os.getpid(), message))
            self._siptrace_file.flush()

    def _LH_MSRPTransportTrace(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_msrp:
            return
        arrow = {'incoming': '<--', 'outgoing': '-->'}[notification.data.direction]
        local_address = notification.sender.getHost()
        local_address = '%s:%d' % (local_address.host, local_address.port)
        remote_address = notification.sender.getPeer()
        remote_address = '%s:%d' % (remote_address.host, remote_address.port)
        message = '%s %s %s\n' % (local_address, arrow, remote_address) + notification.data.data
        try:
            self._init_log_file('msrptrace')
        except Exception:
            pass
        else:
            self._msrptrace_file.write('%s [%s %d]: %s\n' % (notification.data.timestamp, os.path.basename(sys.argv[0]).rstrip('.py'), os.getpid(), message))
            self._msrptrace_file.flush()

    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.prefix, notification.data.message)
        try:
            self._init_log_file('msrptrace')
        except Exception:
            pass
        else:
            self._msrptrace_file.write('%s [%s %d]: %s\n' % (notification.data.timestamp, os.path.basename(sys.argv[0]).rstrip('.py'), os.getpid(), message))
            self._msrptrace_file.flush()

    # private methods
    #

    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._siptrace_error = True
            self._pjsiptrace_error = True
            self._notifications_error = True
            raise
        else:
コード例 #4
0
ファイル: BlinkLogger.py プロジェクト: AGProjects/blink-cocoa
class FileLogger(object, metaclass=Singleton):

    # public methods
    #

    def __init__(self, msrp_level=log.level.INFO):
        self.msrp_level = msrp_level

        self._siptrace_filename = None
        self._siptrace_file = None
        self._siptrace_error = False
        self._siptrace_start_time = None
        self._siptrace_packet_count = 0

        self._msrptrace_filename = None
        self._msrptrace_file = None
        self._msrptrace_error = False

        self._pjsiptrace_filename = None
        self._pjsiptrace_file = None
        self._pjsiptrace_error = False

        self._notifications_filename = None
        self._notifications_file = None
        self._notifications_error = False

        self._log_directory_error = False

        self._event_queue = None

    def start(self):
        # try to create the log directory
        try:
            self._init_log_directory()
        except Exception:
            pass

        # register to receive log notifications
        notification_center = NotificationCenter()
        notification_center.add_observer(self)

        # start the thread processing the notifications
        self._event_queue = EventQueue(handler=self._process_notification,
                                       name='Log handling')
        self._event_queue.start()

    def stop(self):
        # stop the thread processing the notifications
        self._event_queue.stop()
        self._event_queue.join()

        # close sip trace file
        if self._siptrace_file is not None:
            self._siptrace_file.close()
            self._siptrace_file = None

        # close msrp trace file
        if self._msrptrace_file is not None:
            self._msrptrace_file.close()
            self._msrptrace_file = None

        # close pjsip trace file
        if self._pjsiptrace_file is not None:
            self._pjsiptrace_file.close()
            self._pjsiptrace_file = None

        # close notifications trace file
        if self._notifications_file is not None:
            self._notifications_file.close()
            self._notifications_file = None

        # unregister from receiving notifications
        notification_center = NotificationCenter()
        notification_center.remove_observer(self)

    def handle_notification(self, notification):
        self._event_queue.put(notification)

    def _process_notification(self, notification):
        settings = SIPSimpleSettings()
        handler = getattr(self, '_NH_%s' % notification.name, None)
        if handler is not None:
            handler(notification)

        handler = getattr(self, '_LH_%s' % notification.name, None)
        if handler is not None:
            handler(notification)

        if notification.name not in (
                'SIPEngineLog', 'SIPEngineSIPTrace'
        ) and settings.logs.trace_notifications and settings.logs.trace_notifications_to_file:
            try:
                self._init_log_file('notifications')
            except Exception:
                pass
            else:
                message = 'Notification name=%s sender=%s data=%s' % (
                    notification.name, notification.sender,
                    pformat(notification.data))
                try:
                    self._notifications_file.write(
                        '%s: %s\n' % (datetime.datetime.now(), message))
                    self._notifications_file.flush()
                except Exception as e:
                    print('Write message failed: %s' % message)

    # notification handlers
    #

    def _NH_CFGSettingsObjectDidChange(self, notification):
        settings = SIPSimpleSettings()
        if notification.sender is settings:
            if 'logs.directory' in notification.data.modified:
                # sip trace
                if self._siptrace_file is not None:
                    self._siptrace_file.close()
                    self._siptrace_file = None
                # pjsip trace
                if self._pjsiptrace_file is not None:
                    self._pjsiptrace_file.close()
                    self._pjsiptrace_file = None
                # notifications trace
                if self._notifications_file is not None:
                    self._notifications_file.close()
                    self._notifications_file = None
                # try to create the log directory
                try:
                    self._init_log_directory()
                except Exception:
                    pass

    # log handlers
    #

    def _LH_SIPEngineSIPTrace(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_sip or not settings.logs.trace_sip_to_file:
            return
        if self._siptrace_start_time is None:
            self._siptrace_start_time = notification.datetime
        self._siptrace_packet_count += 1
        if notification.data.received:
            direction = "RECEIVED"
        else:
            direction = "SENDING"
        buf = [
            "%s: Packet %d, +%s" %
            (direction, self._siptrace_packet_count,
             (notification.datetime - self._siptrace_start_time))
        ]
        buf.append(
            "%(source_ip)s:%(source_port)d -(SIP over %(transport)s)-> %(destination_ip)s:%(destination_port)d"
            % notification.data.__dict__)
        buf.append(notification.data.data)
        buf.append('--')
        message = '\n'.join(buf)
        try:
            self._init_log_file('siptrace')
        except Exception:
            pass
        else:
            self._siptrace_file.write(
                '%s [%s %d]: %s\n' %
                (notification.datetime, os.path.basename(
                    sys.argv[0]).rstrip('.py'), os.getpid(), message))
            self._siptrace_file.flush()

    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 _LH_DNSLookupTrace(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_sip or not settings.logs.trace_sip_to_file:
            return
        message = 'DNS lookup %(query_type)s %(query_name)s' % notification.data.__dict__
        if notification.data.error is None:
            message += ' succeeded, ttl=%d: ' % notification.data.answer.ttl
            if notification.data.query_type == 'A':
                message += ", ".join(record.address
                                     for record in notification.data.answer)
            elif notification.data.query_type == 'SRV':
                message += ", ".join('%d %d %d %s' %
                                     (record.priority, record.weight,
                                      record.port, record.target)
                                     for record in notification.data.answer)
            elif notification.data.query_type == 'NAPTR':
                message += ", ".join(
                    '%d %d "%s" "%s" "%s" %s' %
                    (record.order, record.preference, record.flags,
                     record.service, record.regexp, record.replacement)
                    for record in notification.data.answer)
        else:
            import dns.resolver
            message_map = {
                dns.resolver.NXDOMAIN:
                'DNS record does not exist',
                dns.resolver.NoAnswer:
                'DNS response contains no answer',
                dns.resolver.NoNameservers:
                'no DNS name servers could be reached',
                dns.resolver.Timeout:
                'no DNS response received, the query has timed out'
            }
            message += ' failed: %s' % message_map.get(
                notification.data.error.__class__, '')
        try:
            self._init_log_file('siptrace')
        except Exception:
            pass
        else:
            self._siptrace_file.write(
                '%s [%s %d]: %s\n' %
                (notification.datetime, os.path.basename(
                    sys.argv[0]).rstrip('.py'), os.getpid(), message))
            self._siptrace_file.flush()

    def _LH_MSRPTransportTrace(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_msrp or not settings.logs.trace_msrp_to_file:
            return
        arrow = {
            'incoming': '<--',
            'outgoing': '-->'
        }[notification.data.direction]
        local_address = notification.sender.getHost()
        local_address = '%s:%d' % (local_address.host, local_address.port)
        remote_address = notification.sender.getPeer()
        remote_address = '%s:%d' % (remote_address.host, remote_address.port)
        message = '%s %s %s\n' % (local_address, arrow,
                                  remote_address) + notification.data.data
        try:
            self._init_log_file('msrptrace')
        except Exception:
            pass
        else:
            self._msrptrace_file.write(
                '%s [%s %d]: %s\n' %
                (notification.datetime, os.path.basename(
                    sys.argv[0]).rstrip('.py'), os.getpid(), message))
            self._msrptrace_file.flush()

    def _LH_MSRPLibraryLog(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_msrp or not settings.logs.trace_msrp_to_file:
            return
        if notification.data.level < self.msrp_level:
            return
        message = '%s%s' % (notification.data.level.prefix,
                            notification.data.message)
        try:
            self._init_log_file('msrptrace')
        except Exception:
            pass
        else:
            self._msrptrace_file.write(
                '%s [%s %d]: %s\n' %
                (notification.datetime, os.path.basename(
                    sys.argv[0]).rstrip('.py'), os.getpid(), message))
            self._msrptrace_file.flush()

    # private methods
    #

    def _init_log_directory(self):
        settings = SIPSimpleSettings()
        log_directory = settings.logs.directory.normalized
        try:
            makedirs(log_directory)
        except Exception as e:
            if not self._log_directory_error:
                print("failed to create logs directory '%s': %s" %
                      (log_directory, e))
                self._log_directory_error = True
            self._siptrace_error = True
            self._pjsiptrace_error = True
            self._notifications_error = True
            raise
        else:
            self._log_directory_error = False
            # sip trace
            if self._siptrace_filename is None:
                self._siptrace_filename = os.path.join(log_directory,
                                                       'sip_trace.txt')
                self._siptrace_error = False

            # msrp trace
            if self._msrptrace_filename is None:
                self._msrptrace_filename = os.path.join(
                    log_directory, 'msrp_trace.txt')
                self._msrptrace_error = False

            # pjsip trace
            if self._pjsiptrace_filename is None:
                self._pjsiptrace_filename = os.path.join(
                    log_directory, 'pjsip_trace.txt')
                self._pjsiptrace_error = False

            # notifications trace
            if self._notifications_filename is None:
                self._notifications_filename = os.path.join(
                    log_directory, 'notifications_trace.txt')
                self._notifications_error = False

    def _init_log_file(self, type):
        if getattr(self, '_%s_file' % type) is None:
            self._init_log_directory()
            filename = getattr(self, '_%s_filename' % type)
            try:
                setattr(self, '_%s_file' % type, open(filename, 'a'))
            except Exception as e:
                if not getattr(self, '_%s_error' % type):
                    print("failed to create log file '%s': %s" % (filename, e))
                    setattr(self, '_%s_error' % type, True)
                raise
            else:
                setattr(self, '_%s_error' % type, False)
コード例 #5
0
class RadiusDatabase(object):
    """Interface with the Radius database"""
    class RadiusTask(object):
        def __init__(self, deferred, tasktype, **kwargs):
            self.deferred = deferred
            self.tasktype = tasktype
            self.args = kwargs

    def __init__(self):
        self.queue = EventQueue(handler=self._handle_task, name='RadiusQueue')
        self.queue.start()

        credentials = RadiusDatabaseConfig.user and (
            "%s%s@" % (RadiusDatabaseConfig.user,
                       RadiusDatabaseConfig.password and ":%s" %
                       (RadiusDatabaseConfig.password) or '')) or ''
        self.conn = sqlobject.connectionForURI(
            "mysql://%s%s/%s" % (credentials, RadiusDatabaseConfig.host,
                                 RadiusDatabaseConfig.database))

    def close(self):
        return threads.deferToThread(self._close)

    def _close(self):
        self.queue.stop()
        self.queue.join()
        self.conn.close()

    def getTerminatedCalls(self, calls):
        """
        Retrieve those calls from the ones in progress that were already terminated by caller/called.

        Returns a Deferred. Callback will be called with list of call ids.
        """
        deferred = defer.Deferred()
        self.queue.put(
            RadiusDatabase.RadiusTask(deferred, 'terminated', calls=calls))
        return deferred

    def getTimedoutCalls(self, calls):
        """
        Retrieve those calls from the ones in progress that did timeout and were closed by mediaproxy.

        Returns a Deferred. Callback will be called with list of call ids.
        """
        deferred = defer.Deferred()
        self.queue.put(
            RadiusDatabase.RadiusTask(deferred, 'timedout', calls=calls))
        return deferred

    def query(self, task):
        def _unknown_task(task):
            raise RadiusDatabaseError("Got unknown task to handle: %s" %
                                      task.tasktype)

        return getattr(self, '_RD_%s' % task.tasktype, _unknown_task)(task)

    def _handle_task(self, task):
        try:
            reactor.callFromThread(task.deferred.callback, self.query(task))
        except Exception, e:
            reactor.callFromThread(task.deferred.errback, failure.Failure(e))
コード例 #6
0
ファイル: tracing.py プロジェクト: echeverrifm/op2-daemon
class TraceManager(object):
    __metaclass__ = Singleton

    implements(IObserver)

    def __init__(self):
        self.name = os.path.basename(sys.argv[0]).rsplit('.py', 1)[0]
        self.pid = os.getpid()
        self.msrp_level = log.level.INFO
        self.siptrace_file = Null
        self.msrptrace_file = Null
        self.pjsiptrace_file = Null
        self.notifications_file = Null
        self.event_queue = Null
        self.notification_queue = NotificationQueue()
        self._siptrace_start_time = None
        self._siptrace_packet_count = None

    def start(self):
        settings = SIPSimpleSettings()
        notification_center = NotificationCenter()
        notification_center.add_observer(self)
        self.siptrace_file = LogFile(os.path.join(ApplicationData.directory, 'logs', 'sip.log'))
        self.msrptrace_file = LogFile(os.path.join(ApplicationData.directory, 'logs', 'msrp.log'))
        self.pjsiptrace_file = LogFile(os.path.join(ApplicationData.directory, 'logs', 'pjsip.log'))
        self.notifications_file = LogFile(os.path.join(ApplicationData.directory, 'logs', 'notifications.log'))
        self._siptrace_start_time = datetime.now()
        self._siptrace_packet_count = 0
        self.event_queue = EventQueue(handler=self._process_notification, name='Log handling')
        self.event_queue.start()
        while settings.logs.trace_notifications and self.notification_queue and self.notification_queue.notifications:
            notification = self.notification_queue.notifications.popleft()
            self.handle_notification(notification)
        self.notification_queue = None

    def stop(self):
        notification_center = NotificationCenter()
        notification_center.remove_observer(self)

        self.event_queue.stop()
        self.event_queue.join()
        self.event_queue = Null

        self.siptrace_file = Null
        self.msrptrace_file = Null
        self.pjsiptrace_file = Null
        self.notifications_file = Null

    def handle_notification(self, notification):
        self.event_queue.put(notification)

    def _process_notification(self, notification):
        handler = getattr(self, '_NH_%s' % notification.name, Null)
        handler(notification)

        handler = getattr(self, '_LH_%s' % notification.name, Null)
        handler(notification)

        settings = SIPSimpleSettings()
        if notification.name not in ('SIPEngineLog', 'SIPEngineSIPTrace') and settings.logs.trace_notifications:
            message = 'Notification name=%s sender=%s data=%s' % (notification.name, notification.sender, pformat(notification.data))
            try:
                self.notifications_file.write('%s [%s %d]: %s\n' % (datetime.now(), self.name, self.pid, message))
            except Exception:
                pass

    def _LH_SIPEngineSIPTrace(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_sip:
            return
        self._siptrace_packet_count += 1
        if notification.data.received:
            direction = "RECEIVED"
        else:
            direction = "SENDING"
        buf = ["%s: Packet %d, +%s" % (direction, self._siptrace_packet_count, (notification.datetime - self._siptrace_start_time))]
        buf.append("%(source_ip)s:%(source_port)d -(SIP over %(transport)s)-> %(destination_ip)s:%(destination_port)d" % notification.data.__dict__)
        buf.append(notification.data.data)
        buf.append('--')
        message = '\n'.join(buf)
        try:
            self.siptrace_file.write('%s [%s %d]: %s\n' % (notification.datetime, self.name, self.pid, message))
        except Exception:
            pass

    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))
        except Exception:
            pass

    def _LH_DNSLookupTrace(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_sip:
            return
        message = 'DNS lookup %(query_type)s %(query_name)s' % notification.data.__dict__
        if notification.data.error is None:
            message += ' succeeded, ttl=%d: ' % notification.data.answer.ttl
            if notification.data.query_type == 'A':
                message += ", ".join(record.address for record in notification.data.answer)
            elif notification.data.query_type == 'SRV':
                message += ", ".join('%d %d %d %s' % (record.priority, record.weight, record.port, record.target) for record in notification.data.answer)
            elif notification.data.query_type == 'NAPTR':
                message += ", ".join('%d %d "%s" "%s" "%s" %s' % (record.order, record.preference, record.flags, record.service, record.regexp, record.replacement) for record in notification.data.answer)
        else:
            import dns.resolver
            message_map = {dns.resolver.NXDOMAIN: 'DNS record does not exist',
                           dns.resolver.NoAnswer: 'DNS response contains no answer',
                           dns.resolver.NoNameservers: 'no DNS name servers could be reached',
                           dns.resolver.Timeout: 'no DNS response received, the query has timed out'}
            message += ' failed: %s' % message_map.get(notification.data.error.__class__, '')
        try:
            self.siptrace_file.write('%s [%s %d]: %s\n' % (notification.datetime, self.name, self.pid, message))
        except Exception:
            pass

    def _LH_MSRPTransportTrace(self, notification):
        settings = SIPSimpleSettings()
        if not settings.logs.trace_msrp:
            return
        arrow = {'incoming': '<--', 'outgoing': '-->'}[notification.data.direction]
        local_address = notification.data.local_address
        local_address = '%s:%d' % (local_address.host, local_address.port)
        remote_address = notification.data.remote_address
        remote_address = '%s:%d' % (remote_address.host, remote_address.port)
        message = '%s %s %s\n' % (local_address, arrow, remote_address) + notification.data.data
        try:
            self.msrptrace_file.write('%s [%s %d]: %s\n' % (notification.datetime, self.name, self.pid, message))
        except Exception:
            pass

    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.prefix, notification.data.message)
        try:
            self.msrptrace_file.write('%s [%s %d]: %s\n' % (notification.datetime, self.name, self.pid, message))
        except Exception:
            pass
コード例 #7
0
ファイル: raddb.py プロジェクト: AGProjects/callcontrol
class RadiusDatabase(object):
    """Interface with the Radius database"""
    class RadiusTask(object):
        def __init__(self, deferred, tasktype, **kwargs):
            self.deferred = deferred
            self.tasktype = tasktype
            self.args = kwargs

    def __init__(self):
        self.queue = EventQueue(handler=self._handle_task, name='RadiusQueue')
        self.queue.start()

        credentials = RadiusDatabaseConfig.user and ( "%s%s@" % (RadiusDatabaseConfig.user, RadiusDatabaseConfig.password and ":%s" % (RadiusDatabaseConfig.password) or '') ) or ''
        self.conn = sqlobject.connectionForURI("mysql://%s%s/%s" % (credentials, RadiusDatabaseConfig.host, RadiusDatabaseConfig.database))

    def close(self):
        return threads.deferToThread(self._close)

    def _close(self):
        self.queue.stop()
        self.queue.join()
        self.conn.close()

    def getTerminatedCalls(self, calls):
        """
        Retrieve those calls from the ones in progress that were already terminated by caller/called.

        Returns a Deferred. Callback will be called with list of call ids.
        """
        deferred = defer.Deferred()
        self.queue.put(RadiusDatabase.RadiusTask(deferred, 'terminated', calls=calls))
        return deferred

    def getTimedoutCalls(self, calls):
        """
        Retrieve those calls from the ones in progress that did timeout and were closed by mediaproxy.

        Returns a Deferred. Callback will be called with list of call ids.
        """
        deferred = defer.Deferred()
        self.queue.put(RadiusDatabase.RadiusTask(deferred, 'timedout', calls=calls))
        return deferred

    def query(self, task):
        def _unknown_task(task):
            raise RadiusDatabaseError("Got unknown task to handle: %s" % task.tasktype)
        return getattr(self, '_RD_%s' % task.tasktype, _unknown_task)(task)

    def _handle_task(self, task):
        try:
            reactor.callFromThread(task.deferred.callback, self.query(task))
        except Exception as e:
            reactor.callFromThread(task.deferred.errback, failure.Failure(e))

    def _RD_terminated(self, task):
        calls = dict([(call.callid, call) for call in list(task.args['calls'].values()) if call.inprogress])
        if not calls:
            return {}
        ids = "(%s)" % ','.join(["'" + key + "'" for key in list(calls.keys())])
        query = """SELECT %(session_id_field)s AS callid, %(duration_field)s AS duration,
                          %(from_tag_field)s AS fromtag, %(to_tag_field)s AS totag
                   FROM   %(table)s
                   WHERE  %(session_id_field)s IN %(ids)s AND
                          (%(stop_info_field)s IS NOT NULL OR
                           %(stop_time_field)s IS NOT NULL)""" % {'session_id_field': RadiusDatabaseConfig.sessionIdField,
                                                                  'duration_field': RadiusDatabaseConfig.durationField,
                                                                  'from_tag_field': RadiusDatabaseConfig.fromTagField,
                                                                  'to_tag_field': RadiusDatabaseConfig.toTagField,
                                                                  'stop_info_field': RadiusDatabaseConfig.stopInfoField,
                                                                  'stop_time_field': RadiusDatabaseConfig.stopTimeField,
                                                                  'table': RadiusDatabaseConfig.table.normalized,
                                                                  'ids': ids}
        try:
            rows = self.conn.queryAll(query)
        except Exception as e:
            log.error("Query failed: %s" % query)
            raise RadiusDatabaseError("Exception while querying for terminated calls %s." % e)
        def find(row, calls):
            try:
                call = calls[row[0]]
            except KeyError:
                return False
            return call.fromtag==row[2] and call.totag==row[3]
        return dict([(row[0], {'callid': row[0], 'duration': row[1], 'fromtag': row[2], 'totag': row[3]}) for row in rows if find(row, calls)])

    def _RD_timedout(self, task):
        calls = dict([(call.callid, call) for call in list(task.args['calls'].values()) if call.inprogress])
        if not calls:
            return {}
        ids = "(%s)" % ','.join(["'" + key + "'" for key in list(calls.keys())])
        query = '''SELECT %(session_id_field)s AS callid, %(duration_field)s AS duration,
                          %(from_tag_field)s AS fromtag, %(to_tag_field)s AS totag
                   FROM   %(table)s
                   WHERE  %(session_id_field)s IN %(ids)s AND
                          %(media_info_field)s = 'timeout' AND
                          %(stop_info_field)s IS NULL''' % {'session_id_field': RadiusDatabaseConfig.sessionIdField,
                                                            'duration_field': RadiusDatabaseConfig.durationField,
                                                            'from_tag_field': RadiusDatabaseConfig.fromTagField,
                                                            'to_tag_field': RadiusDatabaseConfig.toTagField,
                                                            'media_info_field': RadiusDatabaseConfig.mediaInfoField,
                                                            'stop_info_field': RadiusDatabaseConfig.stopInfoField,
                                                            'table': RadiusDatabaseConfig.table.normalized,
                                                            'ids': ids}
        try:
            rows = self.conn.queryAll(query)
        except Exception as e:
            log.error("Query failed: %s" % query)
            raise RadiusDatabaseError("Exception while querying for timedout calls %s." % e)
        def find(row, calls):
            try:
                call = calls[row[0]]
            except KeyError:
                return False
            return call.fromtag==row[2] and call.totag==row[3]
        return dict([(row[0], {'callid': row[0], 'duration': row[1], 'fromtag': row[2], 'totag': row[3]}) for row in rows if find(row, calls)])