用Python编写的自定义D-Bus监视器不接收所有消息

时间:2017-10-11 12:46:53

标签: python monitor dbus

我写了一个python D-Bus监控工具,它应该接收会话总线上的所有消息。 问题是如果短时间内有多条消息(信号,方法调用,方法返回),我只会收到第一个消息。我用dbus-monitor测试了这个,它显示了总线上的所有消息。

这是我的剧本:

import sys
import os
import time

import dbus
import dbus.service
import _dbus_bindings
import gobject

# This creates a GLib main context which is later used by a GLib mainloop to process events that dbus-python associates with that context. 
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)

def print_message(m):
    print(m)

class Input:
    def start(self):
        pass

    def run(self):
        #print "Input=", self.__class__
        self.start()

        self.out.start()

        self.run_inner()

        self.out.stop()
        self.stop()

    def run_inner(self):
        pass

    def stop(self):
        pass

class Output:
    def start(self):
        pass

    def message_dictionary_handler(self, message_dictionary):
        pass

    def stop(self):
        pass

class Handler(Output):
    def __init__(self, message_dictionary_handler):
        """message_dictionary_handler: callable"""
        self.message_dictionary_handler = message_dictionary_handler

class Monitor(Input):
    def __init__(self, which_bus, out):
        """which_bus: "system" or "session"
        out: Output"""
        if which_bus == "system":
            self.bus = dbus.SystemBus()
        else:
            self.bus = dbus.SessionBus()
        self.out = out

    def start(self):
        """
        Start monitoring the bus
        """
        # Arrange for this application to receive all messages on the bus.
        self.bus.add_match_string("eavesdrop='true'")
        # Add message filter. Filter are handlers that are run on all incoming messages.
        self.bus.add_message_filter(self.msg_filter)

    def stop(self):
        """
        Stop monitoring the bus
        """
        # Remove message filter
        self.bus.remove_message_filter(self.msg_filter)
        # Remove string matching
        self.bus.remove_match_string("eavesdrop='true'")

    def message_dictionary_maker(self, m):
        """
        m: received message
        """

        dump=m
        return dump

    def msg_filter(self, abus, msg):
        """
        abus: bus session
        msg: received message
        """

        message_dictionary = self.message_dictionary_maker(msg)
        self.out.message_dictionary_handler(message_dictionary)


    def run_inner(self):
        loop = gobject.MainLoop()
        print("Press Ctrl-C to stop.")
        try:
            loop.run()
        except:
            print(" Loop exited")

    def reset(self):
        pass


out = Handler(print_message)
input = Monitor("session", out)
input.run()

来自我的监视器的消息:

dbus.lowlevel.**MethodCall**Message path: /com/mydbus/pydbus/clientserver, iface: com.mydbus.pydbus.clientserver, member: Data dest: com.mydbus.pydbus.clientserver

dbus.lowlevel.**MethodRetur**nMessage object at 0x76d582e0

dbus.lowlevel.**Signa**lMessage path: /org/freedesktop/DBus, iface: org.freedesktop.DBus, member: NameOwnerChanged, dest: (broadcast)

来自dbus-monitor的消息:

**method call** time=1507725081.508751 sender=:1.34 -> destination=com.mydbus.pydbus.clientserver serial=3 path=/com/mydbus/pydbus/clientserver; interface=com.mydbus.pydbus.clientserver; member=Data
   string "HelloDBUSServerThisIsClient1"

**method return** time=1507725082.511337 sender=:1.31 -> destination=:1.34 serial=7 reply_serial=3
   string "Return von DBUS-Server:HelloDBUSServerThisIsClient1"

**signal** time=1507725082.557260 sender=org.freedesktop.DBus -> destination=:1.34 serial=11 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameLost
   string ":1.34"

**signal** time=1507725082.558629 sender=org.freedesktop.DBus -> destination=(null destination) serial=5 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
   string ":1.34"
   string ":1.34"
   string ""

另一个例子:

来自我的监视器的消息:

dbus.lowlevel.**Signal**Message path: /org/freedesktop/DBus, iface: org.freedesktop.DBus, member: NameAcquired, dest: :1.33

dbus.lowlevel.**MethodCall**Message path: /org/freedesktop/DBus, iface: org.freedesktop.DBus, member: AddMatch dest: org.freedesktop.DBus

dbus.lowlevel.**Signal**Message path: /org/freedesktop/DBus, iface: org.freedesktop.DBus, member: NameOwnerChanged, dest: (broadcast)

dbus.lowlevel.**MethodCall**Message path: /org/freedesktop/DBus, iface: org.freedesktop.DBus, member: Hello dest: org.freedesktop.DBus

来自dbus-monitor的消息:

**signal** time=1507725076.981426 sender=org.freedesktop.DBus -> destination=:1.33 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired
   string ":1.33"

**method call** time=1507725076.982076 sender=:1.33 -> destination=org.freedesktop.DBus serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
   string "eavesdrop='true'"

**method return** time=1507725076.982138 sender=org.freedesktop.DBus -> destination=:1.33 serial=3 reply_serial=2

**method call** time=1507725081.489070 sender=:1.34 -> destination=org.freedesktop.DBus serial=1 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=Hello

**method return** time=1507725081.489177 sender=org.freedesktop.DBus -> destination=:1.34 serial=1 reply_serial=1
   string ":1.34"

1 个答案:

答案 0 :(得分:0)

监控总线的推荐方法是使用org.freedesktop.DBus.Monitoring.BecomeMonitor()方法,而不是试图窃听每条消息(这会使您的代码变得脆弱,取决于窃听的总线配置规则)。

请参阅D-Bus specification on eavesdropping

  

窃听与具有非平凡访问控制限制的总线交互不良,并且已被弃用。 BecomeMonitor方法(参见the section called “org.freedesktop.DBus.Monitoring.BecomeMonitor”)提供了一种监控总线的更好方法。

这可能会导致匹配过滤器无法看到某些消息。如果这不是问题,那么你的主循环可能有问题,虽然我无法快速查看它。

总的来说,当dbus-monitor已经存在(并且显然有效)时,我不得不问你为什么要重新实现一个总线监视器?