OpenVPN v3 Dbus 客户端没有收到所有信号

OpenVPN v3 Dbus client not receiving all signals

我正在为 Linux Mint/Cinnamon 编写小程序来管理 OpenVPN v3 连接。

为了避免可能导致 DE 卡顿或冻结的同步调用,我正在使用 GJS. This allows an asynchronous, partly event-driven approach and should avoid any nasty side effects. It's my first time using any of these technologies but the OpenVPN DBus API is pretty well documented and the API docs for Gio and GLib 提供的 GioGLib 库编写一个简单的 DBus 客户端也不错

我遇到的问题是信号订阅,特别是 net.openvpn.v3.sessions 服务发布的 StatusChange 信号。每当建立、暂停、恢复或关闭连接时,都会发布这些信号。大多数信号都被我订阅的听众接收到,但不是全部。特别是,我没有收到 session closed 信号。

使用 dbus-monitor 命令行工具,您可以看到在建立连接(7 个信号)然后关闭(2 个信号)时发布的所有 StatusChange 信号:

$ sudo dbus-monitor --system "type='signal',interface='net.openvpn.v3.sessions',member='StatusChange'"
...

// Connect:
signal time=1625847543.107244 sender=:1.891 -> destination=:1.892 serial=2745 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
   uint32 3
   uint32 27
   string "session_path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49, backend_pid=42584"
signal time=1625847543.116395 sender=:1.891 -> destination=:1.892 serial=2762 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
   uint32 3
   uint32 17
   string "session_path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49 backend_busname=net.openvpn.v3.backends.be42585 backend_path=/net/openvpn/v3/backends/session"
signal time=1625847543.117286 sender=:1.891 -> destination=(null destination) serial=2764 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
   uint32 2
   uint32 2
   string "config_path=/net/openvpn/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232"
signal time=1625847543.638519 sender=:1.891 -> destination=(null destination) serial=2775 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
   uint32 2
   uint32 2
   string "config_path=/net/openvpn/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232"
signal time=1625847543.638533 sender=:1.891 -> destination=(null destination) serial=2776 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
   uint32 2
   uint32 6
   string ""
signal time=1625847543.735357 sender=:1.891 -> destination=(null destination) serial=2777 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
   uint32 2
   uint32 6
   string ""
signal time=1625847543.974784 sender=:1.891 -> destination=(null destination) serial=2778 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
   uint32 2
   uint32 7
   string ""


// Disconnect:
signal time=1625847646.846790 sender=:1.891 -> destination=:1.892 serial=2834 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
   uint32 3
   uint32 28
   string "Session closed"
signal time=1625847646.848262 sender=:1.891 -> destination=:1.892 serial=2839 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange
   uint32 3
   uint32 19
   string ""

下面的代码创建了一个订阅,据我所知,它应该接收到与上面相同的信号。请注意,我在这里使用较低级别的方法来获取订阅;订阅是在全局连接上进行的,而不是通过特定对象路径的 DBusProxy。我已经尝试了这两种方法(结果相同),但以下应该更接近上面的 dbus-monitor 命令。

    subscribeToStatusChangeSignals() {
        this.statusChangeHandlerId = Gio.DBus.system.signal_subscribe(
            'net.openvpn.v3.sessions',
            'net.openvpn.v3.sessions',
            'StatusChange',
            null,
            null,
            Gio.DBusSignalFlags.NONE,
            this._handleGlobalStatusChangeSignal
        );
    }

    _handleGlobalStatusChangeSignal(connection, sender, path, iface, signal, params) {
        let container = params.deep_unpack();
        let statusMajorCode = container[0];
        let statusMinorCode = container[1];
        let statusMajor = lookupStatusMajor(statusMajorCode);  // lookup the corresponding text
        let statusMinor = lookupStatusMinor(statusMinorCode);  // from something resembling an enum
        let message = container[2];

        global.log(`Received StatusChange signal
            path:         [${path}]
            Status Major: [${statusMajorCode} - ${statusMajor}]
            Status Minor: [${statusMinorCode} - ${statusMinor}]
            Message:      [${message}]`
        );
    }

打开和关闭与之前相同的连接时产生的日志:

// Connect:
Cjs-Message: 18:19:03.117: JS LOG: [LookingGlass/info] Received StatusChange signal
            path:         [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
            Status Major: [2 - CONNECTION]
            Status Minor: [2 - CFG_OK]
            Message:      [config_path=/net/openvpn/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232]
Cjs-Message: 18:19:03.638: JS LOG: [LookingGlass/info] Received StatusChange signal
            path:         [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
            Status Major: [2 - CONNECTION]
            Status Minor: [2 - CFG_OK]
            Message:      [config_path=/net/openvpn/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232]
Cjs-Message: 18:19:03.639: JS LOG: [LookingGlass/info] Received StatusChange signal
            path:         [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
            Status Major: [2 - CONNECTION]
            Status Minor: [6 - CONN_CONNECTING]
            Message:      []
Cjs-Message: 18:19:03.735: JS LOG: [LookingGlass/info] Received StatusChange signal
            path:         [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
            Status Major: [2 - CONNECTION]
            Status Minor: [6 - CONN_CONNECTING]
            Message:      []
Cjs-Message: 18:19:03.974: JS LOG: [LookingGlass/info] Received StatusChange signal
            path:         [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
            Status Major: [2 - CONNECTION]
            Status Minor: [7 - CONN_CONNECTED]
            Message:      []

// Disconnect:
<nada>

我注意到的一种模式是,我收到的信号在 dbus-monitor 输出中都有一个 null destination

... sender=:1.891 -> destination=(null destination) ...

而我收到的信号有一个特定的目的地:

... sender=:1.891 -> destination=:1.892 ...

大概这些是针对特定接收者的直接信号,而不是向所有感兴趣的订阅者广播的信号,但我没有在文档中的任何地方找到这个解释。

那么问题来了,为什么我收到了一些信号而不是全部?这是设计使然,还是 Gio 的问题,或者(更有可能)我使用它的方式的问题?

经过更多的挖掘,这种行为似乎是设计使然 - 携带目标值的信号被视为单播消息。预期收件人以外的订阅者只有在配置为 eavesdrop 时才会收到此类消息。大概是 dbus-monitor.

的情况

来源:DBus Specification (Message Routing)