func (conn *Conn) AddMatchSignal(options ...MatchOption) error {
	options = append([]MatchOption{withMatchType("signal")}, options...)
	return conn.busObj.Call(
		"org.freedesktop.DBus.AddMatch", 0,
		formatMatchOptions(options),
	).Store()
}
AddMatchSignal registers the given match rule to receive broadcast
signals based on their contents.
package dbus
import (
	"context"
	"errors"
	"io"
	"os"
	"reflect"
	"strings"
	"sync"
)
var (
	systemBus     *Conn
	systemBusLck  sync.Mutex
	sessionBus    *Conn
	sessionBusLck sync.Mutex
)
var ErrClosed = errors.New("dbus: connection closed by user")
type Conn struct {
	transport
	busObj BusObject
	unixFD bool
	uuid   string
	handler       Handler
	signalHandler SignalHandler
	serialGen     SerialGenerator
	names      *nameTracker
	calls      *callTracker
	outHandler *outputHandler
	eavesdropped    chan<- *Message
	eavesdroppedLck sync.Mutex
}
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
}
func getSessionBusAddress() (string, error) {
	if address := os.Getenv("DBUS_SESSION_BUS_ADDRESS"); address != "" && address != "autolaunch:" {
		return address, nil
	} else if address := tryDiscoverDbusSessionBusAddress(); address != "" {
		os.Setenv("DBUS_SESSION_BUS_ADDRESS", address)
		return address, nil
	}
	return getSessionBusPlatformAddress()
}
func SessionBusPrivate(opts ...ConnOption) (*Conn, error) {
	address, err := getSessionBusAddress()
	if err != nil {
		return nil, err
	}
	return Dial(address, opts...)
}
func SessionBusPrivateHandler(handler Handler, signalHandler SignalHandler) (*Conn, error) {
	return SessionBusPrivate(WithHandler(handler), WithSignalHandler(signalHandler))
}
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
}
func SystemBusPrivate(opts ...ConnOption) (*Conn, error) {
	return Dial(getSystemBusPlatformAddress(), opts...)
}
func SystemBusPrivateHandler(handler Handler, signalHandler SignalHandler) (*Conn, error) {
	return SystemBusPrivate(WithHandler(handler), WithSignalHandler(signalHandler))
}
func Dial(address string, opts ...ConnOption) (*Conn, error) {
	tr, err := getTransport(address)
	if err != nil {
		return nil, err
	}
	return newConn(tr, opts...)
}
func DialHandler(address string, handler Handler, signalHandler SignalHandler) (*Conn, error) {
	return Dial(address, WithSignalHandler(signalHandler))
}
type ConnOption func(conn *Conn) error
func WithHandler(handler Handler) ConnOption {
	return func(conn *Conn) error {
		conn.handler = handler
		return nil
	}
}
func WithSignalHandler(handler SignalHandler) ConnOption {
	return func(conn *Conn) error {
		conn.signalHandler = handler
		return nil
	}
}
func WithSerialGenerator(gen SerialGenerator) ConnOption {
	return func(conn *Conn) error {
		conn.serialGen = gen
		return nil
	}
}
func NewConn(conn io.ReadWriteCloser, opts ...ConnOption) (*Conn, error) {
	return newConn(genericTransport{conn}, opts...)
}
func NewConnHandler(conn io.ReadWriteCloser, handler Handler, signalHandler SignalHandler) (*Conn, error) {
	return NewConn(genericTransport{conn}, WithHandler(handler), WithSignalHandler(signalHandler))
}
func newConn(tr transport, opts ...ConnOption) (*Conn, error) {
	conn := new(Conn)
	conn.transport = tr
	for _, opt := range opts {
		if err := opt(conn); err != nil {
			return nil, err
		}
	}
	conn.calls = newCallTracker()
	if conn.handler == nil {
		conn.handler = NewDefaultHandler()
	}
	if conn.signalHandler == nil {
		conn.signalHandler = NewDefaultSignalHandler()
	}
	if conn.serialGen == nil {
		conn.serialGen = newSerialGenerator()
	}
	conn.outHandler = &outputHandler{conn: conn}
	conn.names = newNameTracker()
	conn.busObj = conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
	return conn, nil
}
func (conn *Conn) BusObject() BusObject {
	return conn.busObj
}
func (conn *Conn) Close() error {
	conn.outHandler.close()
	if term, ok := conn.signalHandler.(Terminator); ok {
		term.Terminate()
	}
	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()
}
func (conn *Conn) Eavesdrop(ch chan<- *Message) {
	conn.eavesdroppedLck.Lock()
	conn.eavesdropped = ch
	conn.eavesdroppedLck.Unlock()
}
func (conn *Conn) getSerial() uint32 {
	return conn.serialGen.GetSerial()
}
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.names.acquireUniqueConnectionName(s)
	return nil
}
func (conn *Conn) inWorker() {
	for {
		msg, err := conn.ReadMessage()
		if err != nil {
			if _, ok := err.(InvalidMessageError); !ok {
				conn.Close()
				conn.calls.finalizeAllWithError(err)
				return
			}
			continue
		}
		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 := dest == "" ||
			!conn.names.uniqueNameIsKnown() ||
			conn.names.isKnownName(dest)
		if !found {
			continue
		}
		switch msg.Type {
		case TypeError:
			conn.serialGen.RetireSerial(conn.calls.handleDBusError(msg))
		case TypeMethodReply:
			conn.serialGen.RetireSerial(conn.calls.handleReply(msg))
		case TypeSignal:
			conn.handleSignal(msg)
		case TypeMethodCall:
			go conn.handleCall(msg)
		}
	}
}
func (conn *Conn) handleSignal(msg *Message) {
	iface := msg.Headers[FieldInterface].value.(string)
	member := msg.Headers[FieldMember].value.(string)
	sender, _ := msg.Headers[FieldSender].value.(string)
	if iface == "org.freedesktop.DBus" && sender == "org.freedesktop.DBus" {
		if member == "NameLost" {
			name, ok := msg.Body[0].(string)
			if !ok {
				panic("Unable to read the lost name")
			}
			conn.names.loseName(name)
		} else if member == "NameAcquired" {
			name, ok := msg.Body[0].(string)
			if !ok {
				panic("Unable to read the acquired name")
			}
			conn.names.acquireName(name)
		}
	}
	signal := &Signal{
		Sender: sender,
		Path:   msg.Headers[FieldPath].value.(ObjectPath),
		Name:   iface + "." + member,
		Body:   msg.Body,
	}
	conn.signalHandler.DeliverSignal(iface, member, signal)
}
func (conn *Conn) Names() []string {
	return conn.names.listKnownNames()
}
func (conn *Conn) Object(dest string, path ObjectPath) BusObject {
	return &Object{conn, dest, path}
}
func (conn *Conn) sendMessage(msg *Message) {
	conn.sendMessageAndIfClosed(msg, func() {})
}
func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) {
	err := conn.outHandler.sendAndIfClosed(msg, ifClosed)
	conn.calls.handleSendError(msg, err)
	if err != nil {
		conn.serialGen.RetireSerial(msg.serial)
	} else if msg.Type != TypeMethodCall {
		conn.serialGen.RetireSerial(msg.serial)
	}
}
func (conn *Conn) Send(msg *Message, ch chan *Call) *Call {
	return conn.send(context.Background(), msg, ch)
}
func (conn *Conn) SendWithContext(ctx context.Context, msg *Message, ch chan *Call) *Call {
	return conn.send(ctx, msg, ch)
}
func (conn *Conn) send(ctx context.Context, msg *Message, ch chan *Call) *Call {
	if ctx == nil {
		panic("nil context")
	}
	var call *Call
	ctx, canceler := context.WithCancel(ctx)
	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
		call.ctx = ctx
		call.ctxCanceler = canceler
		conn.calls.track(msg.serial, call)
		go func() {
			<-ctx.Done()
			conn.calls.handleSendError(msg, ctx.Err())
		}()
		conn.sendMessageAndIfClosed(msg, func() {
			conn.calls.handleSendError(msg, ErrClosed)
			canceler()
		})
	} else {
		canceler()
		call = &Call{Err: nil}
		conn.sendMessageAndIfClosed(msg, func() {
			call = &Call{Err: ErrClosed}
		})
	}
	return call
}
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()
	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.sendMessage(msg)
}
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.sendMessage(msg)
}