Appease the vndr God
Adjust paths that were not canonical. Add nested vendors that are required. Now no errors with latest `vndr`. Signed-off-by: Justin Cormack <justin.cormack@docker.com>
This commit is contained in:
		
							
								
								
									
										625
									
								
								vendor/github.com/godbus/dbus/conn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										625
									
								
								vendor/github.com/godbus/dbus/conn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,625 @@
 | 
			
		||||
package dbus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const defaultSystemBusAddress = "unix:path=/var/run/dbus/system_bus_socket"
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	systemBus     *Conn
 | 
			
		||||
	systemBusLck  sync.Mutex
 | 
			
		||||
	sessionBus    *Conn
 | 
			
		||||
	sessionBusLck sync.Mutex
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ErrClosed is the error returned by calls on a closed connection.
 | 
			
		||||
var ErrClosed = errors.New("dbus: connection closed by user")
 | 
			
		||||
 | 
			
		||||
// Conn represents a connection to a message bus (usually, the system or
 | 
			
		||||
// session bus).
 | 
			
		||||
//
 | 
			
		||||
// Connections are either shared or private. Shared connections
 | 
			
		||||
// are shared between calls to the functions that return them. As a result,
 | 
			
		||||
// the methods Close, Auth and Hello must not be called on them.
 | 
			
		||||
//
 | 
			
		||||
// Multiple goroutines may invoke methods on a connection simultaneously.
 | 
			
		||||
type Conn struct {
 | 
			
		||||
	transport
 | 
			
		||||
 | 
			
		||||
	busObj BusObject
 | 
			
		||||
	unixFD bool
 | 
			
		||||
	uuid   string
 | 
			
		||||
 | 
			
		||||
	names    []string
 | 
			
		||||
	namesLck sync.RWMutex
 | 
			
		||||
 | 
			
		||||
	serialLck  sync.Mutex
 | 
			
		||||
	nextSerial uint32
 | 
			
		||||
	serialUsed map[uint32]bool
 | 
			
		||||
 | 
			
		||||
	calls    map[uint32]*Call
 | 
			
		||||
	callsLck sync.RWMutex
 | 
			
		||||
 | 
			
		||||
	handlers    map[ObjectPath]map[string]exportWithMapping
 | 
			
		||||
	handlersLck sync.RWMutex
 | 
			
		||||
 | 
			
		||||
	out    chan *Message
 | 
			
		||||
	closed bool
 | 
			
		||||
	outLck sync.RWMutex
 | 
			
		||||
 | 
			
		||||
	signals    []chan<- *Signal
 | 
			
		||||
	signalsLck sync.Mutex
 | 
			
		||||
 | 
			
		||||
	eavesdropped    chan<- *Message
 | 
			
		||||
	eavesdroppedLck sync.Mutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SessionBus returns a shared connection to the session bus, connecting to it
 | 
			
		||||
// if not already done.
 | 
			
		||||
func SessionBus() (conn *Conn, err error) {
 | 
			
		||||
	sessionBusLck.Lock()
 | 
			
		||||
	defer sessionBusLck.Unlock()
 | 
			
		||||
	if sessionBus != nil {
 | 
			
		||||
		return sessionBus, nil
 | 
			
		||||
	}
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if conn != nil {
 | 
			
		||||
			sessionBus = conn
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	conn, err = SessionBusPrivate()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if err = conn.Auth(nil); err != nil {
 | 
			
		||||
		conn.Close()
 | 
			
		||||
		conn = nil
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if err = conn.Hello(); err != nil {
 | 
			
		||||
		conn.Close()
 | 
			
		||||
		conn = nil
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SessionBusPrivate returns a new private connection to the session bus.
 | 
			
		||||
func SessionBusPrivate() (*Conn, error) {
 | 
			
		||||
	address := os.Getenv("DBUS_SESSION_BUS_ADDRESS")
 | 
			
		||||
	if address != "" && address != "autolaunch:" {
 | 
			
		||||
		return Dial(address)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sessionBusPlatform()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SystemBus returns a shared connection to the system bus, connecting to it if
 | 
			
		||||
// not already done.
 | 
			
		||||
func SystemBus() (conn *Conn, err error) {
 | 
			
		||||
	systemBusLck.Lock()
 | 
			
		||||
	defer systemBusLck.Unlock()
 | 
			
		||||
	if systemBus != nil {
 | 
			
		||||
		return systemBus, nil
 | 
			
		||||
	}
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if conn != nil {
 | 
			
		||||
			systemBus = conn
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	conn, err = SystemBusPrivate()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if err = conn.Auth(nil); err != nil {
 | 
			
		||||
		conn.Close()
 | 
			
		||||
		conn = nil
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if err = conn.Hello(); err != nil {
 | 
			
		||||
		conn.Close()
 | 
			
		||||
		conn = nil
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Dial establishes a new private connection to the message bus specified by address.
 | 
			
		||||
func Dial(address string) (*Conn, error) {
 | 
			
		||||
	tr, err := getTransport(address)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return newConn(tr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewConn creates a new private *Conn from an already established connection.
 | 
			
		||||
func NewConn(conn io.ReadWriteCloser) (*Conn, error) {
 | 
			
		||||
	return newConn(genericTransport{conn})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newConn creates a new *Conn from a transport.
 | 
			
		||||
func newConn(tr transport) (*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]exportWithMapping)
 | 
			
		||||
	conn.nextSerial = 1
 | 
			
		||||
	conn.serialUsed = map[uint32]bool{0: true}
 | 
			
		||||
	conn.busObj = conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
 | 
			
		||||
	return conn, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BusObject returns the object owned by the bus daemon which handles
 | 
			
		||||
// administrative requests.
 | 
			
		||||
func (conn *Conn) BusObject() BusObject {
 | 
			
		||||
	return conn.busObj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close closes the connection. Any blocked operations will return with errors
 | 
			
		||||
// and the channels passed to Eavesdrop and Signal are closed. This method must
 | 
			
		||||
// not be called on shared connections.
 | 
			
		||||
func (conn *Conn) Close() error {
 | 
			
		||||
	conn.outLck.Lock()
 | 
			
		||||
	if conn.closed {
 | 
			
		||||
		// inWorker calls Close on read error, the read error may
 | 
			
		||||
		// be caused by another caller calling Close to shutdown the
 | 
			
		||||
		// dbus connection, a double-close scenario we prevent here.
 | 
			
		||||
		conn.outLck.Unlock()
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	close(conn.out)
 | 
			
		||||
	conn.closed = true
 | 
			
		||||
	conn.outLck.Unlock()
 | 
			
		||||
	conn.signalsLck.Lock()
 | 
			
		||||
	for _, ch := range conn.signals {
 | 
			
		||||
		close(ch)
 | 
			
		||||
	}
 | 
			
		||||
	conn.signalsLck.Unlock()
 | 
			
		||||
	conn.eavesdroppedLck.Lock()
 | 
			
		||||
	if conn.eavesdropped != nil {
 | 
			
		||||
		close(conn.eavesdropped)
 | 
			
		||||
	}
 | 
			
		||||
	conn.eavesdroppedLck.Unlock()
 | 
			
		||||
	return conn.transport.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Eavesdrop causes conn to send all incoming messages to the given channel
 | 
			
		||||
// without further processing. Method replies, errors and signals will not be
 | 
			
		||||
// sent to the appropiate channels and method calls will not be handled. If nil
 | 
			
		||||
// is passed, the normal behaviour is restored.
 | 
			
		||||
//
 | 
			
		||||
// The caller has to make sure that ch is sufficiently buffered;
 | 
			
		||||
// if a message arrives when a write to ch is not possible, the message is
 | 
			
		||||
// discarded.
 | 
			
		||||
func (conn *Conn) Eavesdrop(ch chan<- *Message) {
 | 
			
		||||
	conn.eavesdroppedLck.Lock()
 | 
			
		||||
	conn.eavesdropped = ch
 | 
			
		||||
	conn.eavesdroppedLck.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getSerial returns an unused serial.
 | 
			
		||||
func (conn *Conn) getSerial() uint32 {
 | 
			
		||||
	conn.serialLck.Lock()
 | 
			
		||||
	defer conn.serialLck.Unlock()
 | 
			
		||||
	n := conn.nextSerial
 | 
			
		||||
	for conn.serialUsed[n] {
 | 
			
		||||
		n++
 | 
			
		||||
	}
 | 
			
		||||
	conn.serialUsed[n] = true
 | 
			
		||||
	conn.nextSerial = n + 1
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Hello sends the initial org.freedesktop.DBus.Hello call. This method must be
 | 
			
		||||
// called after authentication, but before sending any other messages to the
 | 
			
		||||
// bus. Hello must not be called for shared connections.
 | 
			
		||||
func (conn *Conn) Hello() error {
 | 
			
		||||
	var s string
 | 
			
		||||
	err := conn.busObj.Call("org.freedesktop.DBus.Hello", 0).Store(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	conn.namesLck.Lock()
 | 
			
		||||
	conn.names = make([]string, 1)
 | 
			
		||||
	conn.names[0] = s
 | 
			
		||||
	conn.namesLck.Unlock()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// inWorker runs in an own goroutine, reading incoming messages from the
 | 
			
		||||
// transport and dispatching them appropiately.
 | 
			
		||||
func (conn *Conn) inWorker() {
 | 
			
		||||
	for {
 | 
			
		||||
		msg, err := conn.ReadMessage()
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			conn.eavesdroppedLck.Lock()
 | 
			
		||||
			if conn.eavesdropped != nil {
 | 
			
		||||
				select {
 | 
			
		||||
				case conn.eavesdropped <- msg:
 | 
			
		||||
				default:
 | 
			
		||||
				}
 | 
			
		||||
				conn.eavesdroppedLck.Unlock()
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			conn.eavesdroppedLck.Unlock()
 | 
			
		||||
			dest, _ := msg.Headers[FieldDestination].value.(string)
 | 
			
		||||
			found := false
 | 
			
		||||
			if dest == "" {
 | 
			
		||||
				found = true
 | 
			
		||||
			} else {
 | 
			
		||||
				conn.namesLck.RLock()
 | 
			
		||||
				if len(conn.names) == 0 {
 | 
			
		||||
					found = true
 | 
			
		||||
				}
 | 
			
		||||
				for _, v := range conn.names {
 | 
			
		||||
					if dest == v {
 | 
			
		||||
						found = true
 | 
			
		||||
						break
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				conn.namesLck.RUnlock()
 | 
			
		||||
			}
 | 
			
		||||
			if !found {
 | 
			
		||||
				// Eavesdropped a message, but no channel for it is registered.
 | 
			
		||||
				// Ignore it.
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			switch msg.Type {
 | 
			
		||||
			case TypeMethodReply, TypeError:
 | 
			
		||||
				serial := msg.Headers[FieldReplySerial].value.(uint32)
 | 
			
		||||
				conn.callsLck.Lock()
 | 
			
		||||
				if c, ok := conn.calls[serial]; ok {
 | 
			
		||||
					if msg.Type == TypeError {
 | 
			
		||||
						name, _ := msg.Headers[FieldErrorName].value.(string)
 | 
			
		||||
						c.Err = Error{name, msg.Body}
 | 
			
		||||
					} else {
 | 
			
		||||
						c.Body = msg.Body
 | 
			
		||||
					}
 | 
			
		||||
					c.Done <- c
 | 
			
		||||
					conn.serialLck.Lock()
 | 
			
		||||
					delete(conn.serialUsed, serial)
 | 
			
		||||
					conn.serialLck.Unlock()
 | 
			
		||||
					delete(conn.calls, serial)
 | 
			
		||||
				}
 | 
			
		||||
				conn.callsLck.Unlock()
 | 
			
		||||
			case TypeSignal:
 | 
			
		||||
				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)
 | 
			
		||||
				if iface == "org.freedesktop.DBus" && sender == "org.freedesktop.DBus" {
 | 
			
		||||
					if member == "NameLost" {
 | 
			
		||||
						// If we lost the name on the bus, remove it from our
 | 
			
		||||
						// tracking list.
 | 
			
		||||
						name, ok := msg.Body[0].(string)
 | 
			
		||||
						if !ok {
 | 
			
		||||
							panic("Unable to read the lost name")
 | 
			
		||||
						}
 | 
			
		||||
						conn.namesLck.Lock()
 | 
			
		||||
						for i, v := range conn.names {
 | 
			
		||||
							if v == name {
 | 
			
		||||
								conn.names = append(conn.names[:i],
 | 
			
		||||
									conn.names[i+1:]...)
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						conn.namesLck.Unlock()
 | 
			
		||||
					} else if member == "NameAcquired" {
 | 
			
		||||
						// If we acquired the name on the bus, add it to our
 | 
			
		||||
						// tracking list.
 | 
			
		||||
						name, ok := msg.Body[0].(string)
 | 
			
		||||
						if !ok {
 | 
			
		||||
							panic("Unable to read the acquired name")
 | 
			
		||||
						}
 | 
			
		||||
						conn.namesLck.Lock()
 | 
			
		||||
						conn.names = append(conn.names, name)
 | 
			
		||||
						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()
 | 
			
		||||
			case TypeMethodCall:
 | 
			
		||||
				go conn.handleCall(msg)
 | 
			
		||||
			}
 | 
			
		||||
		} else if _, ok := err.(InvalidMessageError); !ok {
 | 
			
		||||
			// Some read error occured (usually EOF); we can't really do
 | 
			
		||||
			// anything but to shut down all stuff and returns errors to all
 | 
			
		||||
			// pending replies.
 | 
			
		||||
			conn.Close()
 | 
			
		||||
			conn.callsLck.RLock()
 | 
			
		||||
			for _, v := range conn.calls {
 | 
			
		||||
				v.Err = err
 | 
			
		||||
				v.Done <- v
 | 
			
		||||
			}
 | 
			
		||||
			conn.callsLck.RUnlock()
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		// invalid messages are ignored
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
func (conn *Conn) Names() []string {
 | 
			
		||||
	conn.namesLck.RLock()
 | 
			
		||||
	// copy the slice so it can't be modified
 | 
			
		||||
	s := make([]string, len(conn.names))
 | 
			
		||||
	copy(s, conn.names)
 | 
			
		||||
	conn.namesLck.RUnlock()
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Object returns the object identified by the given destination name and path.
 | 
			
		||||
func (conn *Conn) Object(dest string, path ObjectPath) BusObject {
 | 
			
		||||
	return &Object{conn, dest, path}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// outWorker runs in an own goroutine, encoding and sending messages that are
 | 
			
		||||
// sent to conn.out.
 | 
			
		||||
func (conn *Conn) outWorker() {
 | 
			
		||||
	for msg := range conn.out {
 | 
			
		||||
		err := conn.SendMessage(msg)
 | 
			
		||||
		conn.callsLck.RLock()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if c := conn.calls[msg.serial]; c != nil {
 | 
			
		||||
				c.Err = err
 | 
			
		||||
				c.Done <- c
 | 
			
		||||
			}
 | 
			
		||||
			conn.serialLck.Lock()
 | 
			
		||||
			delete(conn.serialUsed, msg.serial)
 | 
			
		||||
			conn.serialLck.Unlock()
 | 
			
		||||
		} else if msg.Type != TypeMethodCall {
 | 
			
		||||
			conn.serialLck.Lock()
 | 
			
		||||
			delete(conn.serialUsed, msg.serial)
 | 
			
		||||
			conn.serialLck.Unlock()
 | 
			
		||||
		}
 | 
			
		||||
		conn.callsLck.RUnlock()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Send sends the given message to the message bus. You usually don't need to
 | 
			
		||||
// use this; use the higher-level equivalents (Call / Go, Emit and Export)
 | 
			
		||||
// instead. If msg is a method call and NoReplyExpected is not set, a non-nil
 | 
			
		||||
// call is returned and the same value is sent to ch (which must be buffered)
 | 
			
		||||
// once the call is complete. Otherwise, ch is ignored and a Call structure is
 | 
			
		||||
// returned of which only the Err member is valid.
 | 
			
		||||
func (conn *Conn) Send(msg *Message, ch chan *Call) *Call {
 | 
			
		||||
	var call *Call
 | 
			
		||||
 | 
			
		||||
	msg.serial = conn.getSerial()
 | 
			
		||||
	if msg.Type == TypeMethodCall && msg.Flags&FlagNoReplyExpected == 0 {
 | 
			
		||||
		if ch == nil {
 | 
			
		||||
			ch = make(chan *Call, 5)
 | 
			
		||||
		} else if cap(ch) == 0 {
 | 
			
		||||
			panic("dbus: unbuffered channel passed to (*Conn).Send")
 | 
			
		||||
		}
 | 
			
		||||
		call = new(Call)
 | 
			
		||||
		call.Destination, _ = msg.Headers[FieldDestination].value.(string)
 | 
			
		||||
		call.Path, _ = msg.Headers[FieldPath].value.(ObjectPath)
 | 
			
		||||
		iface, _ := msg.Headers[FieldInterface].value.(string)
 | 
			
		||||
		member, _ := msg.Headers[FieldMember].value.(string)
 | 
			
		||||
		call.Method = iface + "." + member
 | 
			
		||||
		call.Args = msg.Body
 | 
			
		||||
		call.Done = ch
 | 
			
		||||
		conn.callsLck.Lock()
 | 
			
		||||
		conn.calls[msg.serial] = call
 | 
			
		||||
		conn.callsLck.Unlock()
 | 
			
		||||
		conn.outLck.RLock()
 | 
			
		||||
		if conn.closed {
 | 
			
		||||
			call.Err = ErrClosed
 | 
			
		||||
			call.Done <- call
 | 
			
		||||
		} else {
 | 
			
		||||
			conn.out <- msg
 | 
			
		||||
		}
 | 
			
		||||
		conn.outLck.RUnlock()
 | 
			
		||||
	} else {
 | 
			
		||||
		conn.outLck.RLock()
 | 
			
		||||
		if conn.closed {
 | 
			
		||||
			call = &Call{Err: ErrClosed}
 | 
			
		||||
		} else {
 | 
			
		||||
			conn.out <- msg
 | 
			
		||||
			call = &Call{Err: nil}
 | 
			
		||||
		}
 | 
			
		||||
		conn.outLck.RUnlock()
 | 
			
		||||
	}
 | 
			
		||||
	return 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) {
 | 
			
		||||
	msg := new(Message)
 | 
			
		||||
	msg.Type = TypeError
 | 
			
		||||
	msg.serial = conn.getSerial()
 | 
			
		||||
	msg.Headers = make(map[HeaderField]Variant)
 | 
			
		||||
	if dest != "" {
 | 
			
		||||
		msg.Headers[FieldDestination] = MakeVariant(dest)
 | 
			
		||||
	}
 | 
			
		||||
	msg.Headers[FieldErrorName] = MakeVariant(e.Name)
 | 
			
		||||
	msg.Headers[FieldReplySerial] = MakeVariant(serial)
 | 
			
		||||
	msg.Body = e.Body
 | 
			
		||||
	if len(e.Body) > 0 {
 | 
			
		||||
		msg.Headers[FieldSignature] = MakeVariant(SignatureOf(e.Body...))
 | 
			
		||||
	}
 | 
			
		||||
	conn.outLck.RLock()
 | 
			
		||||
	if !conn.closed {
 | 
			
		||||
		conn.out <- msg
 | 
			
		||||
	}
 | 
			
		||||
	conn.outLck.RUnlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// sendReply creates a method reply message corresponding to the parameters and
 | 
			
		||||
// sends it to conn.out.
 | 
			
		||||
func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) {
 | 
			
		||||
	msg := new(Message)
 | 
			
		||||
	msg.Type = TypeMethodReply
 | 
			
		||||
	msg.serial = conn.getSerial()
 | 
			
		||||
	msg.Headers = make(map[HeaderField]Variant)
 | 
			
		||||
	if dest != "" {
 | 
			
		||||
		msg.Headers[FieldDestination] = MakeVariant(dest)
 | 
			
		||||
	}
 | 
			
		||||
	msg.Headers[FieldReplySerial] = MakeVariant(serial)
 | 
			
		||||
	msg.Body = values
 | 
			
		||||
	if len(values) > 0 {
 | 
			
		||||
		msg.Headers[FieldSignature] = MakeVariant(SignatureOf(values...))
 | 
			
		||||
	}
 | 
			
		||||
	conn.outLck.RLock()
 | 
			
		||||
	if !conn.closed {
 | 
			
		||||
		conn.out <- msg
 | 
			
		||||
	}
 | 
			
		||||
	conn.outLck.RUnlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
//
 | 
			
		||||
// Multiple of these channels can be registered at the same time. Passing a
 | 
			
		||||
// channel that already is registered will remove it from the list of the
 | 
			
		||||
// registered channels.
 | 
			
		||||
//
 | 
			
		||||
// These channels are "overwritten" by Eavesdrop; i.e., if there currently is a
 | 
			
		||||
// 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()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SupportsUnixFDs returns whether the underlying transport supports passing of
 | 
			
		||||
// unix file descriptors. If this is false, method calls containing unix file
 | 
			
		||||
// descriptors will return an error and emitted signals containing them will
 | 
			
		||||
// not be sent.
 | 
			
		||||
func (conn *Conn) SupportsUnixFDs() bool {
 | 
			
		||||
	return conn.unixFD
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Error represents a D-Bus message of type Error.
 | 
			
		||||
type Error struct {
 | 
			
		||||
	Name string
 | 
			
		||||
	Body []interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewError(name string, body []interface{}) *Error {
 | 
			
		||||
	return &Error{name, body}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e Error) Error() string {
 | 
			
		||||
	if len(e.Body) >= 1 {
 | 
			
		||||
		s, ok := e.Body[0].(string)
 | 
			
		||||
		if ok {
 | 
			
		||||
			return s
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return e.Name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Signal represents a D-Bus message of type Signal. The name member is given in
 | 
			
		||||
// "interface.member" notation, e.g. org.freedesktop.D-Bus.NameLost.
 | 
			
		||||
type Signal struct {
 | 
			
		||||
	Sender string
 | 
			
		||||
	Path   ObjectPath
 | 
			
		||||
	Name   string
 | 
			
		||||
	Body   []interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// transport is a D-Bus transport.
 | 
			
		||||
type transport interface {
 | 
			
		||||
	// Read and Write raw data (for example, for the authentication protocol).
 | 
			
		||||
	io.ReadWriteCloser
 | 
			
		||||
 | 
			
		||||
	// Send the initial null byte used for the EXTERNAL mechanism.
 | 
			
		||||
	SendNullByte() error
 | 
			
		||||
 | 
			
		||||
	// Returns whether this transport supports passing Unix FDs.
 | 
			
		||||
	SupportsUnixFDs() bool
 | 
			
		||||
 | 
			
		||||
	// Signal the transport that Unix FD passing is enabled for this connection.
 | 
			
		||||
	EnableUnixFDs()
 | 
			
		||||
 | 
			
		||||
	// Read / send a message, handling things like Unix FDs.
 | 
			
		||||
	ReadMessage() (*Message, error)
 | 
			
		||||
	SendMessage(*Message) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	transports = make(map[string]func(string) (transport, error))
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func getTransport(address string) (transport, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	var t transport
 | 
			
		||||
 | 
			
		||||
	addresses := strings.Split(address, ";")
 | 
			
		||||
	for _, v := range addresses {
 | 
			
		||||
		i := strings.IndexRune(v, ':')
 | 
			
		||||
		if i == -1 {
 | 
			
		||||
			err = errors.New("dbus: invalid bus address (no transport)")
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		f := transports[v[:i]]
 | 
			
		||||
		if f == nil {
 | 
			
		||||
			err = errors.New("dbus: invalid bus address (invalid or unsupported transport)")
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		t, err = f(v[i+1:])
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			return t, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// dereferenceAll returns a slice that, assuming that vs is a slice of pointers
 | 
			
		||||
// of arbitrary types, containes the values that are obtained from dereferencing
 | 
			
		||||
// all elements in vs.
 | 
			
		||||
func dereferenceAll(vs []interface{}) []interface{} {
 | 
			
		||||
	for i := range vs {
 | 
			
		||||
		v := reflect.ValueOf(vs[i])
 | 
			
		||||
		v = v.Elem()
 | 
			
		||||
		vs[i] = v.Interface()
 | 
			
		||||
	}
 | 
			
		||||
	return vs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getKey gets a key from a the list of keys. Returns "" on error / not found...
 | 
			
		||||
func getKey(s, key string) string {
 | 
			
		||||
	i := strings.Index(s, key)
 | 
			
		||||
	if i == -1 {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	if i+len(key)+1 >= len(s) || s[i+len(key)] != '=' {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	j := strings.Index(s, ",")
 | 
			
		||||
	if j == -1 {
 | 
			
		||||
		j = len(s)
 | 
			
		||||
	}
 | 
			
		||||
	return s[i+len(key)+1 : j]
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user