blob: 5e890e0a074fff187f72223842ba4a6a888a7c76 [file] [log] [blame]
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package dbusutil
import (
"fmt"
"strings"
"github.com/godbus/dbus"
)
// MatchSpec specifies messages that should be received by a D-Bus client.
// Empty fields are disregarded.
type MatchSpec struct {
// Type contains the message type, e.g. "signal".
Type string
// Path contains the path that the message is sent to (for method calls)
// or emitted from (for signals).
Path dbus.ObjectPath
// Sender contains the message sender (typically the sender's connection name, e.g. ":1.2").
Sender string
// Interface contains the interface that the message is sent to (for method calls)
// or emitted from (for signals).
Interface string
// Member contains the method or signal name. It does not include the interface.
Member string
// Arg0 contains the first argument in the message. Non-string arguments are unsupported.
// If empty, the argument is not compared.
Arg0 string
}
// String returns a match rule that can be passed to the bus's AddMatch or RemoveMatch
// method to start or stop receiving messages described by the spec.
func (ms MatchSpec) String() string {
parts := make([]string, 0)
f := func(name, val string) {
if val != "" {
parts = append(parts, fmt.Sprintf("%s='%s'", name, val))
}
}
f("type", ms.Type)
f("path", string(ms.Path))
f("sender", ms.Sender)
f("interface", ms.Interface)
f("member", ms.Member)
f("arg0", ms.Arg0)
return strings.Join(parts, ",")
}
// MatchesSignal returns true if sig is matched by the spec.
func (ms MatchSpec) MatchesSignal(sig *dbus.Signal) bool {
if ms.Type != "" && ms.Type != "signal" {
return false
}
if ms.Path != "" && sig.Path != ms.Path {
return false
}
if ms.Sender != "" && sig.Sender != ms.Sender {
return false
}
parts := strings.Split(sig.Name, ".")
if ms.Interface != "" && strings.Join(parts[:len(parts)-1], ".") != ms.Interface {
return false
}
if ms.Member != "" && parts[len(parts)-1] != ms.Member {
return false
}
if ms.Arg0 != "" {
if len(sig.Body) == 0 {
return false
}
if v, ok := sig.Body[0].(string); !ok || v != ms.Arg0 {
return false
}
}
return true
}