summaryrefslogtreecommitdiff
path: root/vendor/github.com/godbus/dbus/v5/export.go
diff options
context:
space:
mode:
authorValentin Rothberg <rothberg@redhat.com>2020-03-10 18:18:58 +0100
committerValentin Rothberg <rothberg@redhat.com>2020-03-10 18:34:55 +0100
commit450361fc640751c2a33210a02ceff0874c9f449b (patch)
treeeb0f958a0c46f769e344faf8732e5327b9458ca0 /vendor/github.com/godbus/dbus/v5/export.go
parent3d48940927b1133e2bfd1c3accba84345cc56ee6 (diff)
downloadpodman-450361fc640751c2a33210a02ceff0874c9f449b.tar.gz
podman-450361fc640751c2a33210a02ceff0874c9f449b.tar.bz2
podman-450361fc640751c2a33210a02ceff0874c9f449b.zip
update systemd & dbus dependencies
Update the outdated systemd and dbus dependencies which are now provided as go modules. This will further tighten our dependencies and releases and pave the way for the upcoming auto-update feature. Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
Diffstat (limited to 'vendor/github.com/godbus/dbus/v5/export.go')
-rw-r--r--vendor/github.com/godbus/dbus/v5/export.go412
1 files changed, 412 insertions, 0 deletions
diff --git a/vendor/github.com/godbus/dbus/v5/export.go b/vendor/github.com/godbus/dbus/v5/export.go
new file mode 100644
index 000000000..c277ab142
--- /dev/null
+++ b/vendor/github.com/godbus/dbus/v5/export.go
@@ -0,0 +1,412 @@
+package dbus
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "strings"
+)
+
+var (
+ ErrMsgInvalidArg = Error{
+ "org.freedesktop.DBus.Error.InvalidArgs",
+ []interface{}{"Invalid type / number of args"},
+ }
+ ErrMsgNoObject = Error{
+ "org.freedesktop.DBus.Error.NoSuchObject",
+ []interface{}{"No such object"},
+ }
+ ErrMsgUnknownMethod = Error{
+ "org.freedesktop.DBus.Error.UnknownMethod",
+ []interface{}{"Unknown / invalid method"},
+ }
+ ErrMsgUnknownInterface = Error{
+ "org.freedesktop.DBus.Error.UnknownInterface",
+ []interface{}{"Object does not implement the interface"},
+ }
+)
+
+func MakeFailedError(err error) *Error {
+ return &Error{
+ "org.freedesktop.DBus.Error.Failed",
+ []interface{}{err.Error()},
+ }
+}
+
+// Sender is a type which can be used in exported methods to receive the message
+// sender.
+type Sender string
+
+func computeMethodName(name string, mapping map[string]string) string {
+ newname, ok := mapping[name]
+ if ok {
+ name = newname
+ }
+ return name
+}
+
+func getMethods(in interface{}, mapping map[string]string) map[string]reflect.Value {
+ if in == nil {
+ return nil
+ }
+ methods := make(map[string]reflect.Value)
+ val := reflect.ValueOf(in)
+ typ := val.Type()
+ for i := 0; i < typ.NumMethod(); i++ {
+ methtype := typ.Method(i)
+ method := val.Method(i)
+ t := method.Type()
+ // only track valid methods must return *Error as last arg
+ // and must be exported
+ if t.NumOut() == 0 ||
+ t.Out(t.NumOut()-1) != reflect.TypeOf(&ErrMsgInvalidArg) ||
+ methtype.PkgPath != "" {
+ continue
+ }
+ // map names while building table
+ methods[computeMethodName(methtype.Name, mapping)] = method
+ }
+ return methods
+}
+
+func standardMethodArgumentDecode(m Method, sender string, msg *Message, body []interface{}) ([]interface{}, error) {
+ pointers := make([]interface{}, m.NumArguments())
+ decode := make([]interface{}, 0, len(body))
+
+ for i := 0; i < m.NumArguments(); i++ {
+ tp := reflect.TypeOf(m.ArgumentValue(i))
+ val := reflect.New(tp)
+ pointers[i] = val.Interface()
+ if tp == reflect.TypeOf((*Sender)(nil)).Elem() {
+ val.Elem().SetString(sender)
+ } else if tp == reflect.TypeOf((*Message)(nil)).Elem() {
+ val.Elem().Set(reflect.ValueOf(*msg))
+ } else {
+ decode = append(decode, pointers[i])
+ }
+ }
+
+ if len(decode) != len(body) {
+ return nil, ErrMsgInvalidArg
+ }
+
+ if err := Store(body, decode...); err != nil {
+ return nil, ErrMsgInvalidArg
+ }
+
+ return pointers, nil
+}
+
+func (conn *Conn) decodeArguments(m Method, sender string, msg *Message) ([]interface{}, error) {
+ if decoder, ok := m.(ArgumentDecoder); ok {
+ return decoder.DecodeArguments(conn, sender, msg, msg.Body)
+ }
+ return standardMethodArgumentDecode(m, sender, msg, msg.Body)
+}
+
+// handleCall handles the given method call (i.e. looks if it's one of the
+// pre-implemented ones and searches for a corresponding handler if not).
+func (conn *Conn) handleCall(msg *Message) {
+ name := msg.Headers[FieldMember].value.(string)
+ path := msg.Headers[FieldPath].value.(ObjectPath)
+ ifaceName, _ := msg.Headers[FieldInterface].value.(string)
+ sender, hasSender := msg.Headers[FieldSender].value.(string)
+ serial := msg.serial
+ if ifaceName == "org.freedesktop.DBus.Peer" {
+ switch name {
+ case "Ping":
+ conn.sendReply(sender, serial)
+ case "GetMachineId":
+ conn.sendReply(sender, serial, conn.uuid)
+ default:
+ conn.sendError(ErrMsgUnknownMethod, sender, serial)
+ }
+ return
+ }
+ if len(name) == 0 {
+ conn.sendError(ErrMsgUnknownMethod, sender, serial)
+ }
+
+ object, ok := conn.handler.LookupObject(path)
+ if !ok {
+ conn.sendError(ErrMsgNoObject, sender, serial)
+ return
+ }
+
+ iface, exists := object.LookupInterface(ifaceName)
+ if !exists {
+ conn.sendError(ErrMsgUnknownInterface, sender, serial)
+ return
+ }
+
+ m, exists := iface.LookupMethod(name)
+ if !exists {
+ conn.sendError(ErrMsgUnknownMethod, sender, serial)
+ return
+ }
+ args, err := conn.decodeArguments(m, sender, msg)
+ if err != nil {
+ conn.sendError(err, sender, serial)
+ return
+ }
+
+ ret, err := m.Call(args...)
+ if err != nil {
+ conn.sendError(err, sender, serial)
+ return
+ }
+
+ if msg.Flags&FlagNoReplyExpected == 0 {
+ reply := new(Message)
+ reply.Type = TypeMethodReply
+ reply.serial = conn.getSerial()
+ reply.Headers = make(map[HeaderField]Variant)
+ if hasSender {
+ reply.Headers[FieldDestination] = msg.Headers[FieldSender]
+ }
+ reply.Headers[FieldReplySerial] = MakeVariant(msg.serial)
+ reply.Body = make([]interface{}, len(ret))
+ for i := 0; i < len(ret); i++ {
+ reply.Body[i] = ret[i]
+ }
+ reply.Headers[FieldSignature] = MakeVariant(SignatureOf(reply.Body...))
+
+ conn.sendMessageAndIfClosed(reply, nil)
+ }
+}
+
+// Emit emits the given signal on the message bus. The name parameter must be
+// formatted as "interface.member", e.g., "org.freedesktop.DBus.NameLost".
+func (conn *Conn) Emit(path ObjectPath, name string, values ...interface{}) error {
+ if !path.IsValid() {
+ return errors.New("dbus: invalid object path")
+ }
+ i := strings.LastIndex(name, ".")
+ if i == -1 {
+ return errors.New("dbus: invalid method name")
+ }
+ iface := name[:i]
+ member := name[i+1:]
+ if !isValidMember(member) {
+ return errors.New("dbus: invalid method name")
+ }
+ if !isValidInterface(iface) {
+ return errors.New("dbus: invalid interface name")
+ }
+ msg := new(Message)
+ msg.Type = TypeSignal
+ msg.serial = conn.getSerial()
+ msg.Headers = make(map[HeaderField]Variant)
+ msg.Headers[FieldInterface] = MakeVariant(iface)
+ msg.Headers[FieldMember] = MakeVariant(member)
+ msg.Headers[FieldPath] = MakeVariant(path)
+ msg.Body = values
+ if len(values) > 0 {
+ msg.Headers[FieldSignature] = MakeVariant(SignatureOf(values...))
+ }
+
+ var closed bool
+ conn.sendMessageAndIfClosed(msg, func() {
+ closed = true
+ })
+ if closed {
+ return ErrClosed
+ }
+ return nil
+}
+
+// Export registers the given value to be exported as an object on the
+// message bus.
+//
+// If a method call on the given path and interface is received, an exported
+// method with the same name is called with v as the receiver if the
+// parameters match and the last return value is of type *Error. If this
+// *Error is not nil, it is sent back to the caller as an error.
+// Otherwise, a method reply is sent with the other return values as its body.
+//
+// Any parameters with the special type Sender are set to the sender of the
+// dbus message when the method is called. Parameters of this type do not
+// contribute to the dbus signature of the method (i.e. the method is exposed
+// as if the parameters of type Sender were not there).
+//
+// Similarly, any parameters with the type Message are set to the raw message
+// received on the bus. Again, parameters of this type do not contribute to the
+// dbus signature of the method.
+//
+// Every method call is executed in a new goroutine, so the method may be called
+// in multiple goroutines at once.
+//
+// Method calls on the interface org.freedesktop.DBus.Peer will be automatically
+// handled for every object.
+//
+// Passing nil as the first parameter will cause conn to cease handling calls on
+// the given combination of path and interface.
+//
+// Export returns an error if path is not a valid path name.
+func (conn *Conn) Export(v interface{}, path ObjectPath, iface string) error {
+ return conn.ExportWithMap(v, nil, path, iface)
+}
+
+// ExportWithMap works exactly like Export but provides the ability to remap
+// method names (e.g. export a lower-case method).
+//
+// The keys in the map are the real method names (exported on the struct), and
+// the values are the method names to be exported on DBus.
+func (conn *Conn) ExportWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string) error {
+ return conn.export(getMethods(v, mapping), path, iface, false)
+}
+
+// ExportSubtree works exactly like Export but registers the given value for
+// an entire subtree rather under the root path provided.
+//
+// In order to make this useful, one parameter in each of the value's exported
+// methods should be a Message, in which case it will contain the raw message
+// (allowing one to get access to the path that caused the method to be called).
+//
+// Note that more specific export paths take precedence over less specific. For
+// example, a method call using the ObjectPath /foo/bar/baz will call a method
+// exported on /foo/bar before a method exported on /foo.
+func (conn *Conn) ExportSubtree(v interface{}, path ObjectPath, iface string) error {
+ return conn.ExportSubtreeWithMap(v, nil, path, iface)
+}
+
+// ExportSubtreeWithMap works exactly like ExportSubtree but provides the
+// ability to remap method names (e.g. export a lower-case method).
+//
+// The keys in the map are the real method names (exported on the struct), and
+// the values are the method names to be exported on DBus.
+func (conn *Conn) ExportSubtreeWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string) error {
+ return conn.export(getMethods(v, mapping), path, iface, true)
+}
+
+// ExportMethodTable like Export registers the given methods as an object
+// on the message bus. Unlike Export the it uses a method table to define
+// the object instead of a native go object.
+//
+// The method table is a map from method name to function closure
+// representing the method. This allows an object exported on the bus to not
+// necessarily be a native go object. It can be useful for generating exposed
+// methods on the fly.
+//
+// Any non-function objects in the method table are ignored.
+func (conn *Conn) ExportMethodTable(methods map[string]interface{}, path ObjectPath, iface string) error {
+ return conn.exportMethodTable(methods, path, iface, false)
+}
+
+// Like ExportSubtree, but with the same caveats as ExportMethodTable.
+func (conn *Conn) ExportSubtreeMethodTable(methods map[string]interface{}, path ObjectPath, iface string) error {
+ return conn.exportMethodTable(methods, path, iface, true)
+}
+
+func (conn *Conn) exportMethodTable(methods map[string]interface{}, path ObjectPath, iface string, includeSubtree bool) error {
+ out := make(map[string]reflect.Value)
+ for name, method := range methods {
+ rval := reflect.ValueOf(method)
+ if rval.Kind() != reflect.Func {
+ continue
+ }
+ t := rval.Type()
+ // only track valid methods must return *Error as last arg
+ if t.NumOut() == 0 ||
+ t.Out(t.NumOut()-1) != reflect.TypeOf(&ErrMsgInvalidArg) {
+ continue
+ }
+ out[name] = rval
+ }
+ return conn.export(out, path, iface, includeSubtree)
+}
+
+func (conn *Conn) unexport(h *defaultHandler, path ObjectPath, iface string) error {
+ if h.PathExists(path) {
+ obj := h.objects[path]
+ obj.DeleteInterface(iface)
+ if len(obj.interfaces) == 0 {
+ h.DeleteObject(path)
+ }
+ }
+ return nil
+}
+
+// exportWithMap is the worker function for all exports/registrations.
+func (conn *Conn) export(methods map[string]reflect.Value, path ObjectPath, iface string, includeSubtree bool) error {
+ h, ok := conn.handler.(*defaultHandler)
+ if !ok {
+ return fmt.Errorf(
+ `dbus: export only allowed on the default hander handler have %T"`,
+ conn.handler)
+ }
+
+ if !path.IsValid() {
+ return fmt.Errorf(`dbus: Invalid path name: "%s"`, path)
+ }
+
+ // Remove a previous export if the interface is nil
+ if methods == nil {
+ return conn.unexport(h, path, iface)
+ }
+
+ // If this is the first handler for this path, make a new map to hold all
+ // handlers for this path.
+ if !h.PathExists(path) {
+ h.AddObject(path, newExportedObject())
+ }
+
+ exportedMethods := make(map[string]Method)
+ for name, method := range methods {
+ exportedMethods[name] = exportedMethod{method}
+ }
+
+ // Finally, save this handler
+ obj := h.objects[path]
+ obj.AddInterface(iface, newExportedIntf(exportedMethods, includeSubtree))
+
+ return nil
+}
+
+// ReleaseName calls org.freedesktop.DBus.ReleaseName and awaits a response.
+func (conn *Conn) ReleaseName(name string) (ReleaseNameReply, error) {
+ var r uint32
+ err := conn.busObj.Call("org.freedesktop.DBus.ReleaseName", 0, name).Store(&r)
+ if err != nil {
+ return 0, err
+ }
+ return ReleaseNameReply(r), nil
+}
+
+// RequestName calls org.freedesktop.DBus.RequestName and awaits a response.
+func (conn *Conn) RequestName(name string, flags RequestNameFlags) (RequestNameReply, error) {
+ var r uint32
+ err := conn.busObj.Call("org.freedesktop.DBus.RequestName", 0, name, flags).Store(&r)
+ if err != nil {
+ return 0, err
+ }
+ return RequestNameReply(r), nil
+}
+
+// ReleaseNameReply is the reply to a ReleaseName call.
+type ReleaseNameReply uint32
+
+const (
+ ReleaseNameReplyReleased ReleaseNameReply = 1 + iota
+ ReleaseNameReplyNonExistent
+ ReleaseNameReplyNotOwner
+)
+
+// RequestNameFlags represents the possible flags for a RequestName call.
+type RequestNameFlags uint32
+
+const (
+ NameFlagAllowReplacement RequestNameFlags = 1 << iota
+ NameFlagReplaceExisting
+ NameFlagDoNotQueue
+)
+
+// RequestNameReply is the reply to a RequestName call.
+type RequestNameReply uint32
+
+const (
+ RequestNameReplyPrimaryOwner RequestNameReply = 1 + iota
+ RequestNameReplyInQueue
+ RequestNameReplyExists
+ RequestNameReplyAlreadyOwner
+)