diff --git a/vendor.conf b/vendor.conf
index 93c078e6..f0bae23a 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -71,7 +71,7 @@ github.com/Microsoft/hcsshim 43f9725307998e09f2e3816c2c0c36dc98f0c982
github.com/emicklei/go-restful ff4f55a206334ef123e4f79bbf348980da81ca46
github.com/emicklei/go-restful-swagger12 1.0.1
github.com/pkg/errors v0.8.0
-github.com/godbus/dbus v4.0.0
+github.com/godbus/dbus a389bdde4dd695d414e47b755e95e72b7826432c
github.com/urfave/cli v1.20.0
github.com/vbatts/tar-split v0.10.1
github.com/renstrom/dedent v1.0.0
diff --git a/vendor/github.com/containers/storage/pkg/archive/example_changes.go b/vendor/github.com/containers/storage/pkg/archive/example_changes.go
deleted file mode 100644
index 70f9c556..00000000
--- a/vendor/github.com/containers/storage/pkg/archive/example_changes.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// +build ignore
-
-// Simple tool to create an archive stream from an old and new directory
-//
-// By default it will stream the comparison of two temporary directories with junk files
-package main
-
-import (
- "flag"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path"
-
- "github.com/containers/storage/pkg/archive"
- "github.com/sirupsen/logrus"
-)
-
-var (
- flDebug = flag.Bool("D", false, "debugging output")
- flNewDir = flag.String("newdir", "", "")
- flOldDir = flag.String("olddir", "", "")
- log = logrus.New()
-)
-
-func main() {
- flag.Usage = func() {
- fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)")
- fmt.Printf("%s [OPTIONS]\n", os.Args[0])
- flag.PrintDefaults()
- }
- flag.Parse()
- log.Out = os.Stderr
- if (len(os.Getenv("DEBUG")) > 0) || *flDebug {
- logrus.SetLevel(logrus.DebugLevel)
- }
- var newDir, oldDir string
-
- if len(*flNewDir) == 0 {
- var err error
- newDir, err = ioutil.TempDir("", "storage-test-newDir")
- if err != nil {
- log.Fatal(err)
- }
- defer os.RemoveAll(newDir)
- if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil {
- log.Fatal(err)
- }
- } else {
- newDir = *flNewDir
- }
-
- if len(*flOldDir) == 0 {
- oldDir, err := ioutil.TempDir("", "storage-test-oldDir")
- if err != nil {
- log.Fatal(err)
- }
- defer os.RemoveAll(oldDir)
- } else {
- oldDir = *flOldDir
- }
-
- changes, err := archive.ChangesDirs(newDir, oldDir)
- if err != nil {
- log.Fatal(err)
- }
-
- a, err := archive.ExportChanges(newDir, changes)
- if err != nil {
- log.Fatal(err)
- }
- defer a.Close()
-
- i, err := io.Copy(os.Stdout, a)
- if err != nil && err != io.EOF {
- log.Fatal(err)
- }
- fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i)
-}
-
-func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) {
- fileData := []byte("fooo")
- for n := 0; n < numberOfFiles; n++ {
- fileName := fmt.Sprintf("file-%d", n)
- if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil {
- return 0, err
- }
- if makeLinks {
- if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil {
- return 0, err
- }
- }
- }
- totalSize := numberOfFiles * len(fileData)
- return totalSize, nil
-}
diff --git a/vendor/github.com/docker/docker/hack/README.md b/vendor/github.com/docker/docker/hack/README.md
deleted file mode 100644
index 802395d5..00000000
--- a/vendor/github.com/docker/docker/hack/README.md
+++ /dev/null
@@ -1,60 +0,0 @@
-## About
-
-This directory contains a collection of scripts used to build and manage this
-repository. If there are any issues regarding the intention of a particular
-script (or even part of a certain script), please reach out to us.
-It may help us either refine our current scripts, or add on new ones
-that are appropriate for a given use case.
-
-## DinD (dind.sh)
-
-DinD is a wrapper script which allows Docker to be run inside a Docker
-container. DinD requires the container to
-be run with privileged mode enabled.
-
-## Generate Authors (generate-authors.sh)
-
-Generates AUTHORS; a file with all the names and corresponding emails of
-individual contributors. AUTHORS can be found in the home directory of
-this repository.
-
-## Make
-
-There are two make files, each with different extensions. Neither are supposed
-to be called directly; only invoke `make`. Both scripts run inside a Docker
-container.
-
-### make.ps1
-
-- The Windows native build script that uses PowerShell semantics; it is limited
-unlike `hack\make.sh` since it does not provide support for the full set of
-operations provided by the Linux counterpart, `make.sh`. However, `make.ps1`
-does provide support for local Windows development and Windows to Windows CI.
-More information is found within `make.ps1` by the author, @jhowardmsft
-
-### make.sh
-
-- Referenced via `make test` when running tests on a local machine,
-or directly referenced when running tests inside a Docker development container.
-- When running on a local machine, `make test` to run all tests found in
-`test`, `test-unit`, `test-integration-cli`, and `test-docker-py` on
-your local machine. The default timeout is set in `make.sh` to 60 minutes
-(`${TIMEOUT:=60m}`), since it currently takes up to an hour to run
-all of the tests.
-- When running inside a Docker development container, `hack/make.sh` does
-not have a single target that runs all the tests. You need to provide a
-single command line with multiple targets that performs the same thing.
-An example referenced from [Run targets inside a development container](https://docs.docker.com/opensource/project/test-and-docs/#run-targets-inside-a-development-container): `root@5f8630b873fe:/go/src/github.com/moby/moby# hack/make.sh dynbinary binary cross test-unit test-integration-cli test-docker-py`
-- For more information related to testing outside the scope of this README,
-refer to
-[Run tests and test documentation](https://docs.docker.com/opensource/project/test-and-docs/)
-
-## Release (release.sh)
-
-Releases any bundles built by `make` on a public AWS S3 bucket.
-For information regarding configuration, please view `release.sh`.
-
-## Vendor (vendor.sh)
-
-A shell script that is a wrapper around Vndr. For information on how to use
-this, please refer to [vndr's README](https://github.com/LK4D4/vndr/blob/master/README.md)
diff --git a/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/README.md b/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/README.md
deleted file mode 100644
index 1cea5252..00000000
--- a/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/README.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# Integration Testing on Swarm
-
-IT on Swarm allows you to execute integration test in parallel across a Docker Swarm cluster
-
-## Architecture
-
-### Master service
-
- - Works as a funker caller
- - Calls a worker funker (`-worker-service`) with a chunk of `-check.f` filter strings (passed as a file via `-input` flag, typically `/mnt/input`)
-
-### Worker service
-
- - Works as a funker callee
- - Executes an equivalent of `TESTFLAGS=-check.f TestFoo|TestBar|TestBaz ... make test-integration-cli` using the bind-mounted API socket (`docker.sock`)
-
-### Client
-
- - Controls master and workers via `docker stack`
- - No need to have a local daemon
-
-Typically, the master and workers are supposed to be running on a cloud environment,
-while the client is supposed to be running on a laptop, e.g. Docker for Mac/Windows.
-
-## Requirement
-
- - Docker daemon 1.13 or later
- - Private registry for distributed execution with multiple nodes
-
-## Usage
-
-### Step 1: Prepare images
-
- $ make build-integration-cli-on-swarm
-
-Following environment variables are known to work in this step:
-
- - `BUILDFLAGS`
- - `DOCKER_INCREMENTAL_BINARY`
-
-Note: during the transition into Moby Project, you might need to create a symbolic link `$GOPATH/src/github.com/docker/docker` to `$GOPATH/src/github.com/moby/moby`.
-
-### Step 2: Execute tests
-
- $ ./hack/integration-cli-on-swarm/integration-cli-on-swarm -replicas 40 -push-worker-image YOUR_REGISTRY.EXAMPLE.COM/integration-cli-worker:latest
-
-Following environment variables are known to work in this step:
-
- - `DOCKER_GRAPHDRIVER`
- - `DOCKER_EXPERIMENTAL`
-
-#### Flags
-
-Basic flags:
-
- - `-replicas N`: the number of worker service replicas. i.e. degree of parallelism.
- - `-chunks N`: the number of chunks. By default, `chunks` == `replicas`.
- - `-push-worker-image REGISTRY/IMAGE:TAG`: push the worker image to the registry. Note that if you have only single node and hence you do not need a private registry, you do not need to specify `-push-worker-image`.
-
-Experimental flags for mitigating makespan nonuniformity:
-
- - `-shuffle`: Shuffle the test filter strings
-
-Flags for debugging IT on Swarm itself:
-
- - `-rand-seed N`: the random seed. This flag is useful for deterministic replaying. By default(0), the timestamp is used.
- - `-filters-file FILE`: the file contains `-check.f` strings. By default, the file is automatically generated.
- - `-dry-run`: skip the actual workload
- - `keep-executor`: do not auto-remove executor containers, which is used for running privileged programs on Swarm
diff --git a/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/agent/vendor.conf b/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/agent/vendor.conf
deleted file mode 100644
index efd6d6d0..00000000
--- a/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/agent/vendor.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-# dependencies specific to worker (i.e. github.com/docker/docker/...) are not vendored here
-github.com/bfirsh/funker-go eaa0a2e06f30e72c9a0b7f858951e581e26ef773
diff --git a/vendor/github.com/godbus/dbus/README.markdown b/vendor/github.com/godbus/dbus/README.markdown
index 0a6e7e5b..d37f4e2e 100644
--- a/vendor/github.com/godbus/dbus/README.markdown
+++ b/vendor/github.com/godbus/dbus/README.markdown
@@ -1,3 +1,5 @@
+[![Build Status](https://travis-ci.org/godbus/dbus.svg?branch=master)](https://travis-ci.org/godbus/dbus)
+
dbus
----
@@ -29,6 +31,7 @@ gives a short overview over the basic usage.
#### Projects using godbus
- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
+- [go-bluetooth](https://github.com/muka/go-bluetooth) provides a bluetooth client over bluez dbus API.
Please note that the API is considered unstable for now and may change without
further notice.
diff --git a/vendor/github.com/godbus/dbus/conn.go b/vendor/github.com/godbus/dbus/conn.go
index 9aa2e128..5720e2eb 100644
--- a/vendor/github.com/godbus/dbus/conn.go
+++ b/vendor/github.com/godbus/dbus/conn.go
@@ -9,8 +9,6 @@ import (
"sync"
)
-const defaultSystemBusAddress = "unix:path=/var/run/dbus/system_bus_socket"
-
var (
systemBus *Conn
systemBusLck sync.Mutex
@@ -47,15 +45,13 @@ type Conn struct {
calls map[uint32]*Call
callsLck sync.RWMutex
- handlers map[ObjectPath]map[string]exportedObj
- handlersLck sync.RWMutex
+ handler Handler
out chan *Message
closed bool
outLck sync.RWMutex
- signals []chan<- *Signal
- signalsLck sync.Mutex
+ signalHandler SignalHandler
eavesdropped chan<- *Message
eavesdroppedLck sync.Mutex
@@ -90,16 +86,33 @@ func SessionBus() (conn *Conn, err error) {
return
}
-// SessionBusPrivate returns a new private connection to the session bus.
-func SessionBusPrivate() (*Conn, error) {
+func getSessionBusAddress() (string, error) {
sessionEnvLck.Lock()
defer sessionEnvLck.Unlock()
address := os.Getenv("DBUS_SESSION_BUS_ADDRESS")
if address != "" && address != "autolaunch:" {
- return Dial(address)
+ return address, nil
+ }
+ return getSessionBusPlatformAddress()
+}
+
+// SessionBusPrivate returns a new private connection to the session bus.
+func SessionBusPrivate() (*Conn, error) {
+ address, err := getSessionBusAddress()
+ if err != nil {
+ return nil, err
}
- return sessionBusPlatform()
+ return Dial(address)
+}
+
+// SessionBusPrivate returns a new private connection to the session bus.
+func SessionBusPrivateHandler(handler Handler, signalHandler SignalHandler) (*Conn, error) {
+ address, err := getSessionBusAddress()
+ if err != nil {
+ return nil, err
+ }
+ return DialHandler(address, handler, signalHandler)
}
// SystemBus returns a shared connection to the system bus, connecting to it if
@@ -133,11 +146,12 @@ func SystemBus() (conn *Conn, err error) {
// SystemBusPrivate returns a new private connection to the system bus.
func SystemBusPrivate() (*Conn, error) {
- address := os.Getenv("DBUS_SYSTEM_BUS_ADDRESS")
- if address != "" {
- return Dial(address)
- }
- return Dial(defaultSystemBusAddress)
+ return Dial(getSystemBusPlatformAddress())
+}
+
+// SystemBusPrivateHandler returns a new private connection to the system bus, using the provided handlers.
+func SystemBusPrivateHandler(handler Handler, signalHandler SignalHandler) (*Conn, error) {
+ return DialHandler(getSystemBusPlatformAddress(), handler, signalHandler)
}
// Dial establishes a new private connection to the message bus specified by address.
@@ -146,21 +160,36 @@ func Dial(address string) (*Conn, error) {
if err != nil {
return nil, err
}
- return newConn(tr)
+ return newConn(tr, NewDefaultHandler(), NewDefaultSignalHandler())
+}
+
+// DialHandler establishes a new private connection to the message bus specified by address, using the supplied handlers.
+func DialHandler(address string, handler Handler, signalHandler SignalHandler) (*Conn, error) {
+ tr, err := getTransport(address)
+ if err != nil {
+ return nil, err
+ }
+ return newConn(tr, handler, signalHandler)
}
// NewConn creates a new private *Conn from an already established connection.
func NewConn(conn io.ReadWriteCloser) (*Conn, error) {
- return newConn(genericTransport{conn})
+ return NewConnHandler(conn, NewDefaultHandler(), NewDefaultSignalHandler())
+}
+
+// NewConnHandler creates a new private *Conn from an already established connection, using the supplied handlers.
+func NewConnHandler(conn io.ReadWriteCloser, handler Handler, signalHandler SignalHandler) (*Conn, error) {
+ return newConn(genericTransport{conn}, handler, signalHandler)
}
// newConn creates a new *Conn from a transport.
-func newConn(tr transport) (*Conn, error) {
+func newConn(tr transport, handler Handler, signalHandler SignalHandler) (*Conn, error) {
conn := new(Conn)
conn.transport = tr
conn.calls = make(map[uint32]*Call)
conn.out = make(chan *Message, 10)
- conn.handlers = make(map[ObjectPath]map[string]exportedObj)
+ conn.handler = handler
+ conn.signalHandler = signalHandler
conn.nextSerial = 1
conn.serialUsed = map[uint32]bool{0: true}
conn.busObj = conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
@@ -188,16 +217,21 @@ func (conn *Conn) Close() error {
close(conn.out)
conn.closed = true
conn.outLck.Unlock()
- conn.signalsLck.Lock()
- for _, ch := range conn.signals {
- close(ch)
+
+ if term, ok := conn.signalHandler.(Terminator); ok {
+ term.Terminate()
}
- conn.signalsLck.Unlock()
+
+ if term, ok := conn.handler.(Terminator); ok {
+ term.Terminate()
+ }
+
conn.eavesdroppedLck.Lock()
if conn.eavesdropped != nil {
close(conn.eavesdropped)
}
conn.eavesdroppedLck.Unlock()
+
return conn.transport.Close()
}
@@ -334,17 +368,7 @@ func (conn *Conn) inWorker() {
conn.namesLck.Unlock()
}
}
- signal := &Signal{
- Sender: sender,
- Path: msg.Headers[FieldPath].value.(ObjectPath),
- Name: iface + "." + member,
- Body: msg.Body,
- }
- conn.signalsLck.Lock()
- for _, ch := range conn.signals {
- ch <- signal
- }
- conn.signalsLck.Unlock()
+ conn.handleSignal(msg)
case TypeMethodCall:
go conn.handleCall(msg)
}
@@ -365,6 +389,21 @@ func (conn *Conn) inWorker() {
}
}
+func (conn *Conn) handleSignal(msg *Message) {
+ iface := msg.Headers[FieldInterface].value.(string)
+ member := msg.Headers[FieldMember].value.(string)
+ // as per http://dbus.freedesktop.org/doc/dbus-specification.html ,
+ // sender is optional for signals.
+ sender, _ := msg.Headers[FieldSender].value.(string)
+ signal := &Signal{
+ Sender: sender,
+ Path: msg.Headers[FieldPath].value.(ObjectPath),
+ Name: iface + "." + member,
+ Body: msg.Body,
+ }
+ conn.signalHandler.DeliverSignal(iface, member, signal)
+}
+
// Names returns the list of all names that are currently owned by this
// connection. The slice is always at least one element long, the first element
// being the unique name of the connection.
@@ -455,7 +494,19 @@ func (conn *Conn) Send(msg *Message, ch chan *Call) *Call {
// sendError creates an error message corresponding to the parameters and sends
// it to conn.out.
-func (conn *Conn) sendError(e Error, dest string, serial uint32) {
+func (conn *Conn) sendError(err error, dest string, serial uint32) {
+ var e *Error
+ switch em := err.(type) {
+ case Error:
+ e = &em
+ case *Error:
+ e = em
+ case DBusError:
+ name, body := em.DBusError()
+ e = NewError(name, body)
+ default:
+ e = MakeFailedError(err)
+ }
msg := new(Message)
msg.Type = TypeError
msg.serial = conn.getSerial()
@@ -498,6 +549,14 @@ func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) {
conn.outLck.RUnlock()
}
+func (conn *Conn) defaultSignalAction(fn func(h *defaultSignalHandler, ch chan<- *Signal), ch chan<- *Signal) {
+ if !isDefaultSignalHandler(conn.signalHandler) {
+ return
+ }
+ handler := conn.signalHandler.(*defaultSignalHandler)
+ fn(handler, ch)
+}
+
// Signal registers the given channel to be passed all received signal messages.
// The caller has to make sure that ch is sufficiently buffered; if a message
// arrives when a write to c is not possible, it is discarded.
@@ -508,22 +567,12 @@ func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) {
// channel for eavesdropped messages, this channel receives all signals, and
// none of the channels passed to Signal will receive any signals.
func (conn *Conn) Signal(ch chan<- *Signal) {
- conn.signalsLck.Lock()
- conn.signals = append(conn.signals, ch)
- conn.signalsLck.Unlock()
+ conn.defaultSignalAction((*defaultSignalHandler).addSignal, ch)
}
// RemoveSignal removes the given channel from the list of the registered channels.
func (conn *Conn) RemoveSignal(ch chan<- *Signal) {
- conn.signalsLck.Lock()
- for i := len(conn.signals) - 1; i >= 0; i-- {
- if ch == conn.signals[i] {
- copy(conn.signals[i:], conn.signals[i+1:])
- conn.signals[len(conn.signals)-1] = nil
- conn.signals = conn.signals[:len(conn.signals)-1]
- }
- }
- conn.signalsLck.Unlock()
+ conn.defaultSignalAction((*defaultSignalHandler).removeSignal, ch)
}
// SupportsUnixFDs returns whether the underlying transport supports passing of
diff --git a/vendor/github.com/godbus/dbus/conn_darwin.go b/vendor/github.com/godbus/dbus/conn_darwin.go
index b67bb1b8..c015f80c 100644
--- a/vendor/github.com/godbus/dbus/conn_darwin.go
+++ b/vendor/github.com/godbus/dbus/conn_darwin.go
@@ -2,20 +2,32 @@ package dbus
import (
"errors"
+ "fmt"
+ "os"
"os/exec"
)
-func sessionBusPlatform() (*Conn, error) {
+const defaultSystemBusAddress = "unix:path=/opt/local/var/run/dbus/system_bus_socket"
+
+func getSessionBusPlatformAddress() (string, error) {
cmd := exec.Command("launchctl", "getenv", "DBUS_LAUNCHD_SESSION_BUS_SOCKET")
b, err := cmd.CombinedOutput()
if err != nil {
- return nil, err
+ return "", err
}
if len(b) == 0 {
- return nil, errors.New("dbus: couldn't determine address of session bus")
+ return "", errors.New("dbus: couldn't determine address of session bus")
}
- return Dial("unix:path=" + string(b[:len(b)-1]))
+ return "unix:path=" + string(b[:len(b)-1]), nil
+}
+
+func getSystemBusPlatformAddress() string {
+ address := os.Getenv("DBUS_LAUNCHD_SESSION_BUS_SOCKET")
+ if address != "" {
+ return fmt.Sprintf("unix:path=%s", address)
+ }
+ return defaultSystemBusAddress
}
diff --git a/vendor/github.com/godbus/dbus/conn_other.go b/vendor/github.com/godbus/dbus/conn_other.go
index 289e8c5d..254c9f2e 100644
--- a/vendor/github.com/godbus/dbus/conn_other.go
+++ b/vendor/github.com/godbus/dbus/conn_other.go
@@ -5,27 +5,38 @@ package dbus
import (
"bytes"
"errors"
+ "fmt"
"os"
"os/exec"
)
-func sessionBusPlatform() (*Conn, error) {
+const defaultSystemBusAddress = "unix:path=/var/run/dbus/system_bus_socket"
+
+func getSessionBusPlatformAddress() (string, error) {
cmd := exec.Command("dbus-launch")
b, err := cmd.CombinedOutput()
if err != nil {
- return nil, err
+ return "", err
}
i := bytes.IndexByte(b, '=')
j := bytes.IndexByte(b, '\n')
if i == -1 || j == -1 {
- return nil, errors.New("dbus: couldn't determine address of session bus")
+ return "", errors.New("dbus: couldn't determine address of session bus")
}
env, addr := string(b[0:i]), string(b[i+1:j])
os.Setenv(env, addr)
- return Dial(addr)
+ return addr, nil
+}
+
+func getSystemBusPlatformAddress() string {
+ address := os.Getenv("DBUS_SYSTEM_BUS_ADDRESS")
+ if address != "" {
+ return fmt.Sprintf("unix:path=%s", address)
+ }
+ return defaultSystemBusAddress
}
diff --git a/vendor/github.com/godbus/dbus/dbus.go b/vendor/github.com/godbus/dbus/dbus.go
index 2ce68735..c6d0d3ce 100644
--- a/vendor/github.com/godbus/dbus/dbus.go
+++ b/vendor/github.com/godbus/dbus/dbus.go
@@ -2,6 +2,7 @@ package dbus
import (
"errors"
+ "fmt"
"reflect"
"strings"
)
@@ -12,6 +13,8 @@ var (
uint8Type = reflect.TypeOf(uint8(0))
int16Type = reflect.TypeOf(int16(0))
uint16Type = reflect.TypeOf(uint16(0))
+ intType = reflect.TypeOf(int(0))
+ uintType = reflect.TypeOf(uint(0))
int32Type = reflect.TypeOf(int32(0))
uint32Type = reflect.TypeOf(uint32(0))
int64Type = reflect.TypeOf(int64(0))
@@ -22,6 +25,7 @@ var (
objectPathType = reflect.TypeOf(ObjectPath(""))
variantType = reflect.TypeOf(Variant{Signature{""}, nil})
interfacesType = reflect.TypeOf([]interface{}{})
+ interfaceType = reflect.TypeOf((*interface{})(nil)).Elem()
unixFDType = reflect.TypeOf(UnixFD(0))
unixFDIndexType = reflect.TypeOf(UnixFDIndex(0))
)
@@ -46,86 +50,251 @@ func Store(src []interface{}, dest ...interface{}) error {
}
for i := range src {
- if err := store(src[i], dest[i]); err != nil {
+ if err := storeInterfaces(src[i], dest[i]); err != nil {
return err
}
}
return nil
}
-func store(src, dest interface{}) error {
- if reflect.TypeOf(dest).Elem() == reflect.TypeOf(src) {
- reflect.ValueOf(dest).Elem().Set(reflect.ValueOf(src))
- return nil
- } else if hasStruct(dest) {
- rv := reflect.ValueOf(dest).Elem()
- switch rv.Kind() {
- case reflect.Struct:
- vs, ok := src.([]interface{})
- if !ok {
- return errors.New("dbus.Store: type mismatch")
- }
- t := rv.Type()
- ndest := make([]interface{}, 0, rv.NumField())
- for i := 0; i < rv.NumField(); i++ {
- field := t.Field(i)
- if field.PkgPath == "" && field.Tag.Get("dbus") != "-" {
- ndest = append(ndest, rv.Field(i).Addr().Interface())
- }
- }
- if len(vs) != len(ndest) {
- return errors.New("dbus.Store: type mismatch")
- }
- err := Store(vs, ndest...)
- if err != nil {
- return errors.New("dbus.Store: type mismatch")
- }
- case reflect.Slice:
- sv := reflect.ValueOf(src)
- if sv.Kind() != reflect.Slice {
- return errors.New("dbus.Store: type mismatch")
- }
- rv.Set(reflect.MakeSlice(rv.Type(), sv.Len(), sv.Len()))
- for i := 0; i < sv.Len(); i++ {
- if err := store(sv.Index(i).Interface(), rv.Index(i).Addr().Interface()); err != nil {
- return err
- }
- }
- case reflect.Map:
- sv := reflect.ValueOf(src)
- if sv.Kind() != reflect.Map {
- return errors.New("dbus.Store: type mismatch")
- }
- keys := sv.MapKeys()
- rv.Set(reflect.MakeMap(sv.Type()))
- for _, key := range keys {
- v := reflect.New(sv.Type().Elem())
- if err := store(v, sv.MapIndex(key).Interface()); err != nil {
- return err
- }
- rv.SetMapIndex(key, v.Elem())
- }
- default:
- return errors.New("dbus.Store: type mismatch")
- }
- return nil
- } else {
- return errors.New("dbus.Store: type mismatch")
+func storeInterfaces(src, dest interface{}) error {
+ return store(reflect.ValueOf(dest), reflect.ValueOf(src))
+}
+
+func store(dest, src reflect.Value) error {
+ if dest.Kind() == reflect.Ptr {
+ return store(dest.Elem(), src)
+ }
+ switch src.Kind() {
+ case reflect.Slice:
+ return storeSlice(dest, src)
+ case reflect.Map:
+ return storeMap(dest, src)
+ default:
+ return storeBase(dest, src)
}
}
-func hasStruct(v interface{}) bool {
- t := reflect.TypeOf(v)
- for {
- switch t.Kind() {
- case reflect.Struct:
- return true
- case reflect.Slice, reflect.Ptr, reflect.Map:
- t = t.Elem()
- default:
- return false
+func storeBase(dest, src reflect.Value) error {
+ return setDest(dest, src)
+}
+
+func setDest(dest, src reflect.Value) error {
+ if !isVariant(src.Type()) && isVariant(dest.Type()) {
+ //special conversion for dbus.Variant
+ dest.Set(reflect.ValueOf(MakeVariant(src.Interface())))
+ return nil
+ }
+ if isVariant(src.Type()) && !isVariant(dest.Type()) {
+ src = getVariantValue(src)
+ }
+ if !src.Type().ConvertibleTo(dest.Type()) {
+ return fmt.Errorf(
+ "dbus.Store: type mismatch: cannot convert %s to %s",
+ src.Type(), dest.Type())
+ }
+ dest.Set(src.Convert(dest.Type()))
+ return nil
+}
+
+func kindsAreCompatible(dest, src reflect.Type) bool {
+ switch {
+ case isVariant(dest):
+ return true
+ case dest.Kind() == reflect.Interface:
+ return true
+ default:
+ return dest.Kind() == src.Kind()
+ }
+}
+
+func isConvertibleTo(dest, src reflect.Type) bool {
+ switch {
+ case isVariant(dest):
+ return true
+ case dest.Kind() == reflect.Interface:
+ return true
+ case dest.Kind() == reflect.Slice:
+ return src.Kind() == reflect.Slice &&
+ isConvertibleTo(dest.Elem(), src.Elem())
+ case dest.Kind() == reflect.Struct:
+ return src == interfacesType
+ default:
+ return src.ConvertibleTo(dest)
+ }
+}
+
+func storeMap(dest, src reflect.Value) error {
+ switch {
+ case !kindsAreCompatible(dest.Type(), src.Type()):
+ return fmt.Errorf(
+ "dbus.Store: type mismatch: "+
+ "map: cannot store a value of %s into %s",
+ src.Type(), dest.Type())
+ case isVariant(dest.Type()):
+ return storeMapIntoVariant(dest, src)
+ case dest.Kind() == reflect.Interface:
+ return storeMapIntoInterface(dest, src)
+ case isConvertibleTo(dest.Type().Key(), src.Type().Key()) &&
+ isConvertibleTo(dest.Type().Elem(), src.Type().Elem()):
+ return storeMapIntoMap(dest, src)
+ default:
+ return fmt.Errorf(
+ "dbus.Store: type mismatch: "+
+ "map: cannot convert a value of %s into %s",
+ src.Type(), dest.Type())
+ }
+}
+
+func storeMapIntoVariant(dest, src reflect.Value) error {
+ dv := reflect.MakeMap(src.Type())
+ err := store(dv, src)
+ if err != nil {
+ return err
+ }
+ return storeBase(dest, dv)
+}
+
+func storeMapIntoInterface(dest, src reflect.Value) error {
+ var dv reflect.Value
+ if isVariant(src.Type().Elem()) {
+ //Convert variants to interface{} recursively when converting
+ //to interface{}
+ dv = reflect.MakeMap(
+ reflect.MapOf(src.Type().Key(), interfaceType))
+ } else {
+ dv = reflect.MakeMap(src.Type())
+ }
+ err := store(dv, src)
+ if err != nil {
+ return err
+ }
+ return storeBase(dest, dv)
+}
+
+func storeMapIntoMap(dest, src reflect.Value) error {
+ if dest.IsNil() {
+ dest.Set(reflect.MakeMap(dest.Type()))
+ }
+ keys := src.MapKeys()
+ for _, key := range keys {
+ dkey := key.Convert(dest.Type().Key())
+ dval := reflect.New(dest.Type().Elem()).Elem()
+ err := store(dval, getVariantValue(src.MapIndex(key)))
+ if err != nil {
+ return err
+ }
+ dest.SetMapIndex(dkey, dval)
+ }
+ return nil
+}
+
+func storeSlice(dest, src reflect.Value) error {
+ switch {
+ case src.Type() == interfacesType && dest.Kind() == reflect.Struct:
+ //The decoder always decodes structs as slices of interface{}
+ return storeStruct(dest, src)
+ case !kindsAreCompatible(dest.Type(), src.Type()):
+ return fmt.Errorf(
+ "dbus.Store: type mismatch: "+
+ "slice: cannot store a value of %s into %s",
+ src.Type(), dest.Type())
+ case isVariant(dest.Type()):
+ return storeSliceIntoVariant(dest, src)
+ case dest.Kind() == reflect.Interface:
+ return storeSliceIntoInterface(dest, src)
+ case isConvertibleTo(dest.Type().Elem(), src.Type().Elem()):
+ return storeSliceIntoSlice(dest, src)
+ default:
+ return fmt.Errorf(
+ "dbus.Store: type mismatch: "+
+ "slice: cannot convert a value of %s into %s",
+ src.Type(), dest.Type())
+ }
+}
+
+func storeStruct(dest, src reflect.Value) error {
+ if isVariant(dest.Type()) {
+ return storeBase(dest, src)
+ }
+ dval := make([]interface{}, 0, dest.NumField())
+ dtype := dest.Type()
+ for i := 0; i < dest.NumField(); i++ {
+ field := dest.Field(i)
+ ftype := dtype.Field(i)
+ if ftype.PkgPath != "" {
+ continue
+ }
+ if ftype.Tag.Get("dbus") == "-" {
+ continue
+ }
+ dval = append(dval, field.Addr().Interface())
+ }
+ if src.Len() != len(dval) {
+ return fmt.Errorf(
+ "dbus.Store: type mismatch: "+
+ "destination struct does not have "+
+ "enough fields need: %d have: %d",
+ src.Len(), len(dval))
+ }
+ return Store(src.Interface().([]interface{}), dval...)
+}
+
+func storeSliceIntoVariant(dest, src reflect.Value) error {
+ dv := reflect.MakeSlice(src.Type(), src.Len(), src.Cap())
+ err := store(dv, src)
+ if err != nil {
+ return err
+ }
+ return storeBase(dest, dv)
+}
+
+func storeSliceIntoInterface(dest, src reflect.Value) error {
+ var dv reflect.Value
+ if isVariant(src.Type().Elem()) {
+ //Convert variants to interface{} recursively when converting
+ //to interface{}
+ dv = reflect.MakeSlice(reflect.SliceOf(interfaceType),
+ src.Len(), src.Cap())
+ } else {
+ dv = reflect.MakeSlice(src.Type(), src.Len(), src.Cap())
+ }
+ err := store(dv, src)
+ if err != nil {
+ return err
+ }
+ return storeBase(dest, dv)
+}
+
+func storeSliceIntoSlice(dest, src reflect.Value) error {
+ if dest.IsNil() || dest.Len() < src.Len() {
+ dest.Set(reflect.MakeSlice(dest.Type(), src.Len(), src.Cap()))
+ }
+ if dest.Len() != src.Len() {
+ return fmt.Errorf(
+ "dbus.Store: type mismatch: "+
+ "slices are different lengths "+
+ "need: %d have: %d",
+ src.Len(), dest.Len())
+ }
+ for i := 0; i < src.Len(); i++ {
+ err := store(dest.Index(i), getVariantValue(src.Index(i)))
+ if err != nil {
+ return err
}
}
+ return nil
+}
+
+func getVariantValue(in reflect.Value) reflect.Value {
+ if isVariant(in.Type()) {
+ return reflect.ValueOf(in.Interface().(Variant).Value())
+ }
+ return in
+}
+
+func isVariant(t reflect.Type) bool {
+ return t == variantType
}
// An ObjectPath is an object path as defined by the D-Bus spec.
@@ -177,15 +346,15 @@ func alignment(t reflect.Type) int {
return 4
case signatureType:
return 1
- case interfacesType: // sometimes used for structs
- return 8
+ case interfacesType:
+ return 4
}
switch t.Kind() {
case reflect.Uint8:
return 1
case reflect.Uint16, reflect.Int16:
return 2
- case reflect.Uint32, reflect.Int32, reflect.String, reflect.Array, reflect.Slice, reflect.Map:
+ case reflect.Uint, reflect.Int, reflect.Uint32, reflect.Int32, reflect.String, reflect.Array, reflect.Slice, reflect.Map:
return 4
case reflect.Uint64, reflect.Int64, reflect.Float64, reflect.Struct:
return 8
@@ -200,7 +369,7 @@ func isKeyType(t reflect.Type) bool {
switch t.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float64,
- reflect.String:
+ reflect.String, reflect.Uint, reflect.Int:
return true
}
diff --git a/vendor/github.com/godbus/dbus/default_handler.go b/vendor/github.com/godbus/dbus/default_handler.go
new file mode 100644
index 00000000..e81f73ac
--- /dev/null
+++ b/vendor/github.com/godbus/dbus/default_handler.go
@@ -0,0 +1,291 @@
+package dbus
+
+import (
+ "bytes"
+ "reflect"
+ "strings"
+ "sync"
+)
+
+func newIntrospectIntf(h *defaultHandler) *exportedIntf {
+ methods := make(map[string]Method)
+ methods["Introspect"] = exportedMethod{
+ reflect.ValueOf(func(msg Message) (string, *Error) {
+ path := msg.Headers[FieldPath].value.(ObjectPath)
+ return h.introspectPath(path), nil
+ }),
+ }
+ return newExportedIntf(methods, true)
+}
+
+//NewDefaultHandler returns an instance of the default
+//call handler. This is useful if you want to implement only
+//one of the two handlers but not both.
+func NewDefaultHandler() *defaultHandler {
+ h := &defaultHandler{
+ objects: make(map[ObjectPath]*exportedObj),
+ defaultIntf: make(map[string]*exportedIntf),
+ }
+ h.defaultIntf["org.freedesktop.DBus.Introspectable"] = newIntrospectIntf(h)
+ return h
+}
+
+type defaultHandler struct {
+ sync.RWMutex
+ objects map[ObjectPath]*exportedObj
+ defaultIntf map[string]*exportedIntf
+}
+
+func (h *defaultHandler) PathExists(path ObjectPath) bool {
+ _, ok := h.objects[path]
+ return ok
+}
+
+func (h *defaultHandler) introspectPath(path ObjectPath) string {
+ subpath := make(map[string]struct{})
+ var xml bytes.Buffer
+ xml.WriteString("")
+ for obj, _ := range h.objects {
+ p := string(path)
+ if p != "/" {
+ p += "/"
+ }
+ if strings.HasPrefix(string(obj), p) {
+ node_name := strings.Split(string(obj[len(p):]), "/")[0]
+ subpath[node_name] = struct{}{}
+ }
+ }
+ for s, _ := range subpath {
+ xml.WriteString("\n\t")
+ }
+ xml.WriteString("\n")
+ return xml.String()
+}
+
+func (h *defaultHandler) LookupObject(path ObjectPath) (ServerObject, bool) {
+ h.RLock()
+ defer h.RUnlock()
+ object, ok := h.objects[path]
+ if ok {
+ return object, ok
+ }
+
+ // If an object wasn't found for this exact path,
+ // look for a matching subtree registration
+ subtreeObject := newExportedObject()
+ path = path[:strings.LastIndex(string(path), "/")]
+ for len(path) > 0 {
+ object, ok = h.objects[path]
+ if ok {
+ for name, iface := range object.interfaces {
+ // Only include this handler if it registered for the subtree
+ if iface.isFallbackInterface() {
+ subtreeObject.interfaces[name] = iface
+ }
+ }
+ break
+ }
+
+ path = path[:strings.LastIndex(string(path), "/")]
+ }
+
+ for name, intf := range h.defaultIntf {
+ if _, exists := subtreeObject.interfaces[name]; exists {
+ continue
+ }
+ subtreeObject.interfaces[name] = intf
+ }
+
+ return subtreeObject, true
+}
+
+func (h *defaultHandler) AddObject(path ObjectPath, object *exportedObj) {
+ h.Lock()
+ h.objects[path] = object
+ h.Unlock()
+}
+
+func (h *defaultHandler) DeleteObject(path ObjectPath) {
+ h.Lock()
+ delete(h.objects, path)
+ h.Unlock()
+}
+
+type exportedMethod struct {
+ reflect.Value
+}
+
+func (m exportedMethod) Call(args ...interface{}) ([]interface{}, error) {
+ t := m.Type()
+
+ params := make([]reflect.Value, len(args))
+ for i := 0; i < len(args); i++ {
+ params[i] = reflect.ValueOf(args[i]).Elem()
+ }
+
+ ret := m.Value.Call(params)
+
+ err := ret[t.NumOut()-1].Interface().(*Error)
+ ret = ret[:t.NumOut()-1]
+ out := make([]interface{}, len(ret))
+ for i, val := range ret {
+ out[i] = val.Interface()
+ }
+ if err == nil {
+ //concrete type to interface nil is a special case
+ return out, nil
+ }
+ return out, err
+}
+
+func (m exportedMethod) NumArguments() int {
+ return m.Value.Type().NumIn()
+}
+
+func (m exportedMethod) ArgumentValue(i int) interface{} {
+ return reflect.Zero(m.Type().In(i)).Interface()
+}
+
+func (m exportedMethod) NumReturns() int {
+ return m.Value.Type().NumOut()
+}
+
+func (m exportedMethod) ReturnValue(i int) interface{} {
+ return reflect.Zero(m.Type().Out(i)).Interface()
+}
+
+func newExportedObject() *exportedObj {
+ return &exportedObj{
+ interfaces: make(map[string]*exportedIntf),
+ }
+}
+
+type exportedObj struct {
+ interfaces map[string]*exportedIntf
+}
+
+func (obj *exportedObj) LookupInterface(name string) (Interface, bool) {
+ if name == "" {
+ return obj, true
+ }
+ intf, exists := obj.interfaces[name]
+ return intf, exists
+}
+
+func (obj *exportedObj) AddInterface(name string, iface *exportedIntf) {
+ obj.interfaces[name] = iface
+}
+
+func (obj *exportedObj) DeleteInterface(name string) {
+ delete(obj.interfaces, name)
+}
+
+func (obj *exportedObj) LookupMethod(name string) (Method, bool) {
+ for _, intf := range obj.interfaces {
+ method, exists := intf.LookupMethod(name)
+ if exists {
+ return method, exists
+ }
+ }
+ return nil, false
+}
+
+func (obj *exportedObj) isFallbackInterface() bool {
+ return false
+}
+
+func newExportedIntf(methods map[string]Method, includeSubtree bool) *exportedIntf {
+ return &exportedIntf{
+ methods: methods,
+ includeSubtree: includeSubtree,
+ }
+}
+
+type exportedIntf struct {
+ methods map[string]Method
+
+ // Whether or not this export is for the entire subtree
+ includeSubtree bool
+}
+
+func (obj *exportedIntf) LookupMethod(name string) (Method, bool) {
+ out, exists := obj.methods[name]
+ return out, exists
+}
+
+func (obj *exportedIntf) isFallbackInterface() bool {
+ return obj.includeSubtree
+}
+
+//NewDefaultSignalHandler returns an instance of the default
+//signal handler. This is useful if you want to implement only
+//one of the two handlers but not both.
+func NewDefaultSignalHandler() *defaultSignalHandler {
+ return &defaultSignalHandler{}
+}
+
+func isDefaultSignalHandler(handler SignalHandler) bool {
+ _, ok := handler.(*defaultSignalHandler)
+ return ok
+}
+
+type defaultSignalHandler struct {
+ sync.RWMutex
+ closed bool
+ signals []chan<- *Signal
+}
+
+func (sh *defaultSignalHandler) DeliverSignal(intf, name string, signal *Signal) {
+ go func() {
+ sh.RLock()
+ defer sh.RUnlock()
+ if sh.closed {
+ return
+ }
+ for _, ch := range sh.signals {
+ ch <- signal
+ }
+ }()
+}
+
+func (sh *defaultSignalHandler) Init() error {
+ sh.Lock()
+ sh.signals = make([]chan<- *Signal, 0)
+ sh.Unlock()
+ return nil
+}
+
+func (sh *defaultSignalHandler) Terminate() {
+ sh.Lock()
+ sh.closed = true
+ for _, ch := range sh.signals {
+ close(ch)
+ }
+ sh.signals = nil
+ sh.Unlock()
+}
+
+func (sh *defaultSignalHandler) addSignal(ch chan<- *Signal) {
+ sh.Lock()
+ defer sh.Unlock()
+ if sh.closed {
+ return
+ }
+ sh.signals = append(sh.signals, ch)
+
+}
+
+func (sh *defaultSignalHandler) removeSignal(ch chan<- *Signal) {
+ sh.Lock()
+ defer sh.Unlock()
+ if sh.closed {
+ return
+ }
+ for i := len(sh.signals) - 1; i >= 0; i-- {
+ if ch == sh.signals[i] {
+ copy(sh.signals[i:], sh.signals[i+1:])
+ sh.signals[len(sh.signals)-1] = nil
+ sh.signals = sh.signals[:len(sh.signals)-1]
+ }
+ }
+}
diff --git a/vendor/github.com/godbus/dbus/doc.go b/vendor/github.com/godbus/dbus/doc.go
index deff554a..895036a8 100644
--- a/vendor/github.com/godbus/dbus/doc.go
+++ b/vendor/github.com/godbus/dbus/doc.go
@@ -19,6 +19,8 @@ respective D-Bus equivalents:
bool | BOOLEAN
int16 | INT16
uint16 | UINT16
+ int | INT32
+ uint | UINT32
int32 | INT32
uint32 | UINT32
int64 | INT64
@@ -28,6 +30,7 @@ respective D-Bus equivalents:
ObjectPath | OBJECT_PATH
Signature | SIGNATURE
Variant | VARIANT
+ interface{} | VARIANT
UnixFDIndex | UNIX_FD
Slices and arrays encode as ARRAYs of their element type.
@@ -41,6 +44,9 @@ be skipped.
Pointers encode as the value they're pointed to.
+Types convertible to one of the base types above will be mapped as the
+base type.
+
Trying to encode any other type or a slice, map or struct containing an
unsupported type will result in an InvalidTypeError.
diff --git a/vendor/github.com/godbus/dbus/encoder.go b/vendor/github.com/godbus/dbus/encoder.go
index 9f0a9e89..8bb71776 100644
--- a/vendor/github.com/godbus/dbus/encoder.go
+++ b/vendor/github.com/godbus/dbus/encoder.go
@@ -96,10 +96,10 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
case reflect.Uint16:
enc.binwrite(uint16(v.Uint()))
enc.pos += 2
- case reflect.Int32:
+ case reflect.Int, reflect.Int32:
enc.binwrite(int32(v.Int()))
enc.pos += 4
- case reflect.Uint32:
+ case reflect.Uint, reflect.Uint32:
enc.binwrite(uint32(v.Uint()))
enc.pos += 4
case reflect.Int64:
@@ -202,6 +202,8 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
panic(err)
}
enc.pos += length
+ case reflect.Interface:
+ enc.encode(reflect.ValueOf(MakeVariant(v.Interface())), depth)
default:
panic(InvalidTypeError{v.Type()})
}
diff --git a/vendor/github.com/godbus/dbus/export.go b/vendor/github.com/godbus/dbus/export.go
index 6c335220..aae97088 100644
--- a/vendor/github.com/godbus/dbus/export.go
+++ b/vendor/github.com/godbus/dbus/export.go
@@ -1,7 +1,6 @@
package dbus
import (
- "bytes"
"errors"
"fmt"
"reflect"
@@ -9,32 +8,29 @@ import (
)
var (
- errmsgInvalidArg = Error{
+ ErrMsgInvalidArg = Error{
"org.freedesktop.DBus.Error.InvalidArgs",
[]interface{}{"Invalid type / number of args"},
}
- errmsgNoObject = Error{
+ ErrMsgNoObject = Error{
"org.freedesktop.DBus.Error.NoSuchObject",
[]interface{}{"No such object"},
}
- errmsgUnknownMethod = Error{
+ 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"},
+ }
)
-// exportedObj represents an exported object. It stores a precomputed
-// method table that represents the methods exported on the bus.
-type exportedObj struct {
- methods map[string]reflect.Value
-
- // Whether or not this export is for the entire subtree
- includeSubtree bool
-}
-
-func (obj exportedObj) Method(name string) (reflect.Value, bool) {
- out, exists := obj.methods[name]
- return out, exists
+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
@@ -63,7 +59,7 @@ func getMethods(in interface{}, mapping map[string]string) map[string]reflect.Va
// 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) ||
+ t.Out(t.NumOut()-1) != reflect.TypeOf(&ErrMsgInvalidArg) ||
methtype.PkgPath != "" {
continue
}
@@ -73,119 +69,12 @@ func getMethods(in interface{}, mapping map[string]string) map[string]reflect.Va
return methods
}
-// searchHandlers will look through all registered handlers looking for one
-// to handle the given path. If a verbatim one isn't found, it will check for
-// a subtree registration for the path as well.
-func (conn *Conn) searchHandlers(path ObjectPath) (map[string]exportedObj, bool) {
- conn.handlersLck.RLock()
- defer conn.handlersLck.RUnlock()
+func standardMethodArgumentDecode(m Method, sender string, msg *Message, body []interface{}) ([]interface{}, error) {
+ pointers := make([]interface{}, m.NumArguments())
+ decode := make([]interface{}, 0, len(body))
- handlers, ok := conn.handlers[path]
- if ok {
- return handlers, ok
- }
-
- // If handlers weren't found for this exact path, look for a matching subtree
- // registration
- handlers = make(map[string]exportedObj)
- path = path[:strings.LastIndex(string(path), "/")]
- for len(path) > 0 {
- var subtreeHandlers map[string]exportedObj
- subtreeHandlers, ok = conn.handlers[path]
- if ok {
- for iface, handler := range subtreeHandlers {
- // Only include this handler if it registered for the subtree
- if handler.includeSubtree {
- handlers[iface] = handler
- }
- }
-
- break
- }
-
- path = path[:strings.LastIndex(string(path), "/")]
- }
-
- return handlers, ok
-}
-
-// 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, hasIface := 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
- } else if ifaceName == "org.freedesktop.DBus.Introspectable" && name == "Introspect" {
- if _, ok := conn.handlers[path]; !ok {
- subpath := make(map[string]struct{})
- var xml bytes.Buffer
- xml.WriteString("")
- for h, _ := range conn.handlers {
- p := string(path)
- if p != "/" {
- p += "/"
- }
- if strings.HasPrefix(string(h), p) {
- node_name := strings.Split(string(h[len(p):]), "/")[0]
- subpath[node_name] = struct{}{}
- }
- }
- for s, _ := range subpath {
- xml.WriteString("\n\t")
- }
- xml.WriteString("\n")
- conn.sendReply(sender, serial, xml.String())
- return
- }
- }
- if len(name) == 0 {
- conn.sendError(errmsgUnknownMethod, sender, serial)
- }
-
- // Find the exported handler (if any) for this path
- handlers, ok := conn.searchHandlers(path)
- if !ok {
- conn.sendError(errmsgNoObject, sender, serial)
- return
- }
-
- var m reflect.Value
- var exists bool
- if hasIface {
- iface := handlers[ifaceName]
- m, exists = iface.Method(name)
- } else {
- for _, v := range handlers {
- m, exists = v.Method(name)
- if exists {
- break
- }
- }
- }
-
- if !exists {
- conn.sendError(errmsgUnknownMethod, sender, serial)
- return
- }
-
- t := m.Type()
- vs := msg.Body
- pointers := make([]interface{}, t.NumIn())
- decode := make([]interface{}, 0, len(vs))
- for i := 0; i < t.NumIn(); i++ {
- tp := t.In(i)
+ 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() {
@@ -197,26 +86,73 @@ func (conn *Conn) handleCall(msg *Message) {
}
}
- if len(decode) != len(vs) {
- conn.sendError(errmsgInvalidArg, sender, serial)
+ 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
}
- if err := Store(vs, decode...); err != nil {
- conn.sendError(errmsgInvalidArg, sender, serial)
+ iface, exists := object.LookupInterface(ifaceName)
+ if !exists {
+ conn.sendError(ErrMsgUnknownInterface, sender, serial)
return
}
- // Extract parameters
- params := make([]reflect.Value, len(pointers))
- for i := 0; i < len(pointers); i++ {
- params[i] = reflect.ValueOf(pointers[i]).Elem()
+ 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
}
- // Call method
- ret := m.Call(params)
- if em := ret[t.NumOut()-1].Interface().(*Error); em != nil {
- conn.sendError(*em, sender, serial)
+ ret, err := m.Call(args...)
+ if err != nil {
+ conn.sendError(err, sender, serial)
return
}
@@ -229,13 +165,11 @@ func (conn *Conn) handleCall(msg *Message) {
reply.Headers[FieldDestination] = msg.Headers[FieldSender]
}
reply.Headers[FieldReplySerial] = MakeVariant(msg.serial)
- reply.Body = make([]interface{}, len(ret)-1)
- for i := 0; i < len(ret)-1; i++ {
- reply.Body[i] = ret[i].Interface()
- }
- if len(ret) != 1 {
- reply.Headers[FieldSignature] = MakeVariant(SignatureOf(reply.Body...))
+ 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.outLck.RLock()
if !conn.closed {
conn.out <- reply
@@ -375,7 +309,7 @@ func (conn *Conn) exportMethodTable(methods map[string]interface{}, path ObjectP
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) {
+ t.Out(t.NumOut()-1) != reflect.TypeOf(&ErrMsgInvalidArg) {
continue
}
out[name] = rval
@@ -383,38 +317,49 @@ func (conn *Conn) exportMethodTable(methods map[string]interface{}, path ObjectP
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)
}
- conn.handlersLck.Lock()
- defer conn.handlersLck.Unlock()
-
// Remove a previous export if the interface is nil
if methods == nil {
- if _, ok := conn.handlers[path]; ok {
- delete(conn.handlers[path], iface)
- if len(conn.handlers[path]) == 0 {
- delete(conn.handlers, path)
- }
- }
-
- return 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 _, ok := conn.handlers[path]; !ok {
- conn.handlers[path] = make(map[string]exportedObj)
+ 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
- conn.handlers[path][iface] = exportedObj{
- methods: methods,
- includeSubtree: includeSubtree,
- }
+ obj := h.objects[path]
+ obj.AddInterface(iface, newExportedIntf(exportedMethods, includeSubtree))
return nil
}
diff --git a/vendor/github.com/godbus/dbus/object.go b/vendor/github.com/godbus/dbus/object.go
index 9573b709..6d95583d 100644
--- a/vendor/github.com/godbus/dbus/object.go
+++ b/vendor/github.com/godbus/dbus/object.go
@@ -43,7 +43,8 @@ func (o *Object) AddMatchSignal(iface, member string) *Call {
// will be allocated. Otherwise, ch has to be buffered or Go will panic.
//
// If the flags include FlagNoReplyExpected, ch is ignored and a Call structure
-// is returned of which only the Err member is valid.
+// is returned with any error in Err and a closed channel in Done containing
+// the returned Call as it's one entry.
//
// If the method parameter contains a dot ('.'), the part before the last dot
// specifies the interface on which the method is called.
@@ -97,11 +98,21 @@ func (o *Object) Go(method string, flags Flags, ch chan *Call, args ...interface
}
o.conn.outLck.RLock()
defer o.conn.outLck.RUnlock()
+ done := make(chan *Call, 1)
+ call := &Call{
+ Err: nil,
+ Done: done,
+ }
+ defer func() {
+ call.Done <- call
+ close(done)
+ }()
if o.conn.closed {
- return &Call{Err: ErrClosed}
+ call.Err = ErrClosed
+ return call
}
o.conn.out <- msg
- return &Call{Err: nil}
+ return call
}
// GetProperty calls org.freedesktop.DBus.Properties.GetProperty on the given
@@ -125,12 +136,12 @@ func (o *Object) GetProperty(p string) (Variant, error) {
return result, nil
}
-// Destination returns the destination that calls on o are sent to.
+// Destination returns the destination that calls on (o *Object) are sent to.
func (o *Object) Destination() string {
return o.dest
}
-// Path returns the path that calls on o are sent to.
+// Path returns the path that calls on (o *Object") are sent to.
func (o *Object) Path() ObjectPath {
return o.path
}
diff --git a/vendor/github.com/godbus/dbus/server_interfaces.go b/vendor/github.com/godbus/dbus/server_interfaces.go
new file mode 100644
index 00000000..091948ae
--- /dev/null
+++ b/vendor/github.com/godbus/dbus/server_interfaces.go
@@ -0,0 +1,89 @@
+package dbus
+
+// Terminator allows a handler to implement a shutdown mechanism that
+// is called when the connection terminates.
+type Terminator interface {
+ Terminate()
+}
+
+// Handler is the representation of a D-Bus Application.
+//
+// The Handler must have a way to lookup objects given
+// an ObjectPath. The returned object must implement the
+// ServerObject interface.
+type Handler interface {
+ LookupObject(path ObjectPath) (ServerObject, bool)
+}
+
+// ServerObject is the representation of an D-Bus Object.
+//
+// Objects are registered at a path for a given Handler.
+// The Objects implement D-Bus interfaces. The semantics
+// of Interface lookup is up to the implementation of
+// the ServerObject. The ServerObject implementation may
+// choose to implement empty string as a valid interface
+// represeting all methods or not per the D-Bus specification.
+type ServerObject interface {
+ LookupInterface(name string) (Interface, bool)
+}
+
+// An Interface is the representation of a D-Bus Interface.
+//
+// Interfaces are a grouping of methods implemented by the Objects.
+// Interfaces are responsible for routing method calls.
+type Interface interface {
+ LookupMethod(name string) (Method, bool)
+}
+
+// A Method represents the exposed methods on D-Bus.
+type Method interface {
+ // Call requires that all arguments are decoded before being passed to it.
+ Call(args ...interface{}) ([]interface{}, error)
+ NumArguments() int
+ NumReturns() int
+ // ArgumentValue returns a representative value for the argument at position
+ // it should be of the proper type. reflect.Zero would be a good mechanism
+ // to use for this Value.
+ ArgumentValue(position int) interface{}
+ // ReturnValue returns a representative value for the return at position
+ // it should be of the proper type. reflect.Zero would be a good mechanism
+ // to use for this Value.
+ ReturnValue(position int) interface{}
+}
+
+// An Argument Decoder can decode arguments using the non-standard mechanism
+//
+// If a method implements this interface then the non-standard
+// decoder will be used.
+//
+// Method arguments must be decoded from the message.
+// The mechanism for doing this will vary based on the
+// implementation of the method. A normal approach is provided
+// as part of this library, but may be replaced with
+// any other decoding scheme.
+type ArgumentDecoder interface {
+ // To decode the arguments of a method the sender and message are
+ // provided incase the semantics of the implementer provides access
+ // to these as part of the method invocation.
+ DecodeArguments(conn *Conn, sender string, msg *Message, args []interface{}) ([]interface{}, error)
+}
+
+// A SignalHandler is responsible for delivering a signal.
+//
+// Signal delivery may be changed from the default channel
+// based approach by Handlers implementing the SignalHandler
+// interface.
+type SignalHandler interface {
+ DeliverSignal(iface, name string, signal *Signal)
+}
+
+// A DBusError is used to convert a generic object to a D-Bus error.
+//
+// Any custom error mechanism may implement this interface to provide
+// a custom encoding of the error on D-Bus. By default if a normal
+// error is returned, it will be encoded as the generic
+// "org.freedesktop.DBus.Error.Failed" error. By implementing this
+// interface as well a custom encoding may be provided.
+type DBusError interface {
+ DBusError() (string, []interface{})
+}
diff --git a/vendor/github.com/godbus/dbus/sig.go b/vendor/github.com/godbus/dbus/sig.go
index f45b53ce..c1b80920 100644
--- a/vendor/github.com/godbus/dbus/sig.go
+++ b/vendor/github.com/godbus/dbus/sig.go
@@ -57,12 +57,12 @@ func getSignature(t reflect.Type) string {
return "n"
case reflect.Uint16:
return "q"
- case reflect.Int32:
+ case reflect.Int, reflect.Int32:
if t == unixFDType {
return "h"
}
return "i"
- case reflect.Uint32:
+ case reflect.Uint, reflect.Uint32:
if t == unixFDIndexType {
return "h"
}
@@ -101,6 +101,8 @@ func getSignature(t reflect.Type) string {
panic(InvalidTypeError{t})
}
return "a{" + getSignature(t.Key()) + getSignature(t.Elem()) + "}"
+ case reflect.Interface:
+ return "v"
}
panic(InvalidTypeError{t})
}
@@ -162,7 +164,7 @@ func (e SignatureError) Error() string {
return fmt.Sprintf("dbus: invalid signature: %q (%s)", e.Sig, e.Reason)
}
-// Try to read a single type from this string. If it was successfull, err is nil
+// Try to read a single type from this string. If it was successful, err is nil
// and rem is the remaining unparsed part. Otherwise, err is a non-nil
// SignatureError and rem is "". depth is the current recursion depth which may
// not be greater than 64 and should be given as 0 on the first call.
diff --git a/vendor/github.com/godbus/dbus/transport_generic.go b/vendor/github.com/godbus/dbus/transport_generic.go
index 46f8f49d..3fad859a 100644
--- a/vendor/github.com/godbus/dbus/transport_generic.go
+++ b/vendor/github.com/godbus/dbus/transport_generic.go
@@ -4,8 +4,23 @@ import (
"encoding/binary"
"errors"
"io"
+ "unsafe"
)
+var nativeEndian binary.ByteOrder
+
+func detectEndianness() binary.ByteOrder {
+ var x uint32 = 0x01020304
+ if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
+ return binary.BigEndian
+ }
+ return binary.LittleEndian
+}
+
+func init() {
+ nativeEndian = detectEndianness()
+}
+
type genericTransport struct {
io.ReadWriteCloser
}
@@ -31,5 +46,5 @@ func (t genericTransport) SendMessage(msg *Message) error {
return errors.New("dbus: unix fd passing not enabled")
}
}
- return msg.EncodeTo(t, binary.LittleEndian)
+ return msg.EncodeTo(t, nativeEndian)
}
diff --git a/vendor/github.com/godbus/dbus/transport_unix.go b/vendor/github.com/godbus/dbus/transport_unix.go
index a1d00cbc..e56d5ca9 100644
--- a/vendor/github.com/godbus/dbus/transport_unix.go
+++ b/vendor/github.com/godbus/dbus/transport_unix.go
@@ -175,7 +175,7 @@ func (t *unixTransport) SendMessage(msg *Message) error {
msg.Headers[FieldUnixFDs] = MakeVariant(uint32(len(fds)))
oob := syscall.UnixRights(fds...)
buf := new(bytes.Buffer)
- msg.EncodeTo(buf, binary.LittleEndian)
+ msg.EncodeTo(buf, nativeEndian)
n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil)
if err != nil {
return err
@@ -184,7 +184,7 @@ func (t *unixTransport) SendMessage(msg *Message) error {
return io.ErrShortWrite
}
} else {
- if err := msg.EncodeTo(t, binary.LittleEndian); err != nil {
+ if err := msg.EncodeTo(t, nativeEndian); err != nil {
return nil
}
}
diff --git a/vendor/github.com/godbus/dbus/transport_unixcred_freebsd.go b/vendor/github.com/godbus/dbus/transport_unixcred_freebsd.go
new file mode 100644
index 00000000..0fc5b927
--- /dev/null
+++ b/vendor/github.com/godbus/dbus/transport_unixcred_freebsd.go
@@ -0,0 +1,91 @@
+// The UnixCredentials system call is currently only implemented on Linux
+// http://golang.org/src/pkg/syscall/sockcmsg_linux.go
+// https://golang.org/s/go1.4-syscall
+// http://code.google.com/p/go/source/browse/unix/sockcmsg_linux.go?repo=sys
+
+// Local implementation of the UnixCredentials system call for FreeBSD
+
+package dbus
+
+/*
+const int sizeofPtr = sizeof(void*);
+#define _WANT_UCRED
+#include
+*/
+import "C"
+
+import (
+ "io"
+ "os"
+ "syscall"
+ "unsafe"
+)
+
+// http://golang.org/src/pkg/syscall/ztypes_linux_amd64.go
+// https://golang.org/src/syscall/ztypes_freebsd_amd64.go
+type Ucred struct {
+ Pid int32
+ Uid uint32
+ Gid uint32
+}
+
+// http://golang.org/src/pkg/syscall/types_linux.go
+// https://golang.org/src/syscall/types_freebsd.go
+// https://github.com/freebsd/freebsd/blob/master/sys/sys/ucred.h
+const (
+ SizeofUcred = C.sizeof_struct_ucred
+)
+
+// http://golang.org/src/pkg/syscall/sockcmsg_unix.go
+func cmsgAlignOf(salen int) int {
+ salign := C.sizeofPtr
+
+ return (salen + salign - 1) & ^(salign - 1)
+}
+
+// http://golang.org/src/pkg/syscall/sockcmsg_unix.go
+func cmsgData(h *syscall.Cmsghdr) unsafe.Pointer {
+ return unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(cmsgAlignOf(syscall.SizeofCmsghdr)))
+}
+
+// http://golang.org/src/pkg/syscall/sockcmsg_linux.go
+// UnixCredentials encodes credentials into a socket control message
+// for sending to another process. This can be used for
+// authentication.
+func UnixCredentials(ucred *Ucred) []byte {
+ b := make([]byte, syscall.CmsgSpace(SizeofUcred))
+ h := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
+ h.Level = syscall.SOL_SOCKET
+ h.Type = syscall.SCM_CREDS
+ h.SetLen(syscall.CmsgLen(SizeofUcred))
+ *((*Ucred)(cmsgData(h))) = *ucred
+ return b
+}
+
+// http://golang.org/src/pkg/syscall/sockcmsg_linux.go
+// ParseUnixCredentials decodes a socket control message that contains
+// credentials in a Ucred structure. To receive such a message, the
+// SO_PASSCRED option must be enabled on the socket.
+func ParseUnixCredentials(m *syscall.SocketControlMessage) (*Ucred, error) {
+ if m.Header.Level != syscall.SOL_SOCKET {
+ return nil, syscall.EINVAL
+ }
+ if m.Header.Type != syscall.SCM_CREDS {
+ return nil, syscall.EINVAL
+ }
+ ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0]))
+ return &ucred, nil
+}
+
+func (t *unixTransport) SendNullByte() error {
+ ucred := &Ucred{Pid: int32(os.Getpid()), Uid: uint32(os.Getuid()), Gid: uint32(os.Getgid())}
+ b := UnixCredentials(ucred)
+ _, oobn, err := t.UnixConn.WriteMsgUnix([]byte{0}, b, nil)
+ if err != nil {
+ return err
+ }
+ if oobn != len(b) {
+ return io.ErrShortWrite
+ }
+ return nil
+}
diff --git a/vendor/github.com/godbus/dbus/transport_unixcred_openbsd.go b/vendor/github.com/godbus/dbus/transport_unixcred_openbsd.go
new file mode 100644
index 00000000..af7bafdf
--- /dev/null
+++ b/vendor/github.com/godbus/dbus/transport_unixcred_openbsd.go
@@ -0,0 +1,14 @@
+package dbus
+
+import "io"
+
+func (t *unixTransport) SendNullByte() error {
+ n, _, err := t.UnixConn.WriteMsgUnix([]byte{0}, nil, nil)
+ if err != nil {
+ return err
+ }
+ if n != 1 {
+ return io.ErrShortWrite
+ }
+ return nil
+}
diff --git a/vendor/github.com/godbus/dbus/variant.go b/vendor/github.com/godbus/dbus/variant.go
index b7b13ae9..0ca123b0 100644
--- a/vendor/github.com/godbus/dbus/variant.go
+++ b/vendor/github.com/godbus/dbus/variant.go
@@ -17,7 +17,12 @@ type Variant struct {
// MakeVariant converts the given value to a Variant. It panics if v cannot be
// represented as a D-Bus type.
func MakeVariant(v interface{}) Variant {
- return Variant{SignatureOf(v), v}
+ return MakeVariantWithSignature(v, SignatureOf(v))
+}
+
+// MakeVariantWithSignature converts the given value to a Variant.
+func MakeVariantWithSignature(v interface{}, s Signature) Variant {
+ return Variant{s, v}
}
// ParseVariant parses the given string as a variant as described at