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 len(name) == 0 {
		conn.sendError(ErrMsgUnknownMethod, sender, 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(MakeUnknownMethodError(name), sender, serial)
		}
		return
	}
	object, ok := conn.handler.LookupObject(path)
	if !ok {
		conn.sendError(MakeNoObjectError(path), sender, serial)
		return
	}
	iface, exists := object.LookupInterface(ifaceName)
	if !exists {
		conn.sendError(MakeUnknownInterfaceError(ifaceName), sender, serial)
		return
	}
	m, exists := iface.LookupMethod(name)
	if !exists {
		conn.sendError(MakeUnknownMethodError(name), sender, serial)
		return
	}
	args, err := conn.decodeArguments(m, sender, msg)
	if err != nil {
		conn.sendError(err, sender, serial)
		return
	}
	ret, err := m.Call(args...)
	if err != nil {
		conn.sendError(err, sender, serial)
		return
	}
	if msg.Flags&FlagNoReplyExpected == 0 {
		reply := new(Message)
		reply.Type = TypeMethodReply
		reply.Headers = make(map[HeaderField]Variant)
		if hasSender {
			reply.Headers[FieldDestination] = msg.Headers[FieldSender]
		}
		reply.Headers[FieldReplySerial] = MakeVariant(msg.serial)
		reply.Body = make([]interface{}, len(ret))
		for i := 0; i < len(ret); i++ {
			reply.Body[i] = ret[i]
		}
		reply.Headers[FieldSignature] = MakeVariant(SignatureOf(reply.Body...))
		conn.sendMessageAndIfClosed(reply, nil)
	}
}
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).
package dbus
import (
	"errors"
	"fmt"
	"reflect"
	"strings"
)
var (
	ErrMsgInvalidArg = Error{
		"org.freedesktop.DBus.Error.InvalidArgs",
		[]interface{}{"Invalid type / number of args"},
	}
	ErrMsgNoObject = Error{
		"org.freedesktop.DBus.Error.NoSuchObject",
		[]interface{}{"No such object"},
	}
	ErrMsgUnknownMethod = Error{
		"org.freedesktop.DBus.Error.UnknownMethod",
		[]interface{}{"Unknown / invalid method"},
	}
	ErrMsgUnknownInterface = Error{
		"org.freedesktop.DBus.Error.UnknownInterface",
		[]interface{}{"Object does not implement the interface"},
	}
)
func MakeNoObjectError(path ObjectPath) Error {
	return Error{
		"org.freedesktop.DBus.Error.NoSuchObject",
		[]interface{}{fmt.Sprintf("No such object '%s'", string(path))},
	}
}
func MakeUnknownMethodError(methodName string) Error {
	return Error{
		"org.freedesktop.DBus.Error.UnknownMethod",
		[]interface{}{fmt.Sprintf("Unknown / invalid method '%s'", methodName)},
	}
}
func MakeUnknownInterfaceError(ifaceName string) Error {
	return Error{
		"org.freedesktop.DBus.Error.UnknownInterface",
		[]interface{}{fmt.Sprintf("Object does not implement the interface '%s'", ifaceName)},
	}
}
func MakeFailedError(err error) *Error {
	return &Error{
		"org.freedesktop.DBus.Error.Failed",
		[]interface{}{err.Error()},
	}
}
type Sender string
func computeMethodName(name string, mapping map[string]string) string {
	newname, ok := mapping[name]
	if ok {
		name = newname
	}
	return name
}
func getMethods(in interface{}, mapping map[string]string) map[string]reflect.Value {
	if in == nil {
		return nil
	}
	methods := make(map[string]reflect.Value)
	val := reflect.ValueOf(in)
	typ := val.Type()
	for i := 0; i < typ.NumMethod(); i++ {
		methtype := typ.Method(i)
		method := val.Method(i)
		t := method.Type()
		if t.NumOut() == 0 ||
			t.Out(t.NumOut()-1) != reflect.TypeOf(&ErrMsgInvalidArg) ||
			methtype.PkgPath != "" {
			continue
		}
		methods[computeMethodName(methtype.Name, mapping)] = method
	}
	return methods
}
func getAllMethods(in interface{}, mapping map[string]string) map[string]reflect.Value {
	if in == nil {
		return nil
	}
	methods := make(map[string]reflect.Value)
	val := reflect.ValueOf(in)
	typ := val.Type()
	for i := 0; i < typ.NumMethod(); i++ {
		methtype := typ.Method(i)
		method := val.Method(i)
		methods[computeMethodName(methtype.Name, mapping)] = method
	}
	return methods
}
func standardMethodArgumentDecode(m Method, sender string, msg *Message, body []interface{}) ([]interface{}, error) {
	pointers := make([]interface{}, m.NumArguments())
	decode := make([]interface{}, 0, len(body))
	for i := 0; i < m.NumArguments(); i++ {
		tp := reflect.TypeOf(m.ArgumentValue(i))
		val := reflect.New(tp)
		pointers[i] = val.Interface()
		if tp == reflect.TypeOf((*Sender)(nil)).Elem() {
			val.Elem().SetString(sender)
		} else if tp == reflect.TypeOf((*Message)(nil)).Elem() {
			val.Elem().Set(reflect.ValueOf(*msg))
		} else {
			decode = append(decode, pointers[i])
		}
	}
	if len(decode) != len(body) {
		return nil, ErrMsgInvalidArg
	}
	if err := Store(body, decode...); err != nil {
		return nil, ErrMsgInvalidArg
	}
	return pointers, nil
}
func (conn *Conn) decodeArguments(m Method, sender string, msg *Message) ([]interface{}, error) {
	if decoder, ok := m.(ArgumentDecoder); ok {
		return decoder.DecodeArguments(conn, sender, msg, msg.Body)
	}
	return standardMethodArgumentDecode(m, sender, msg, msg.Body)
}