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
	}
	if len(name) == 0 {
		conn.sendError(errmsgUnknownMethod, sender, serial)
	}
	handlers, ok := conn.searchHandlers(path)
	if !ok {
		conn.sendError(errmsgNoObject, sender, serial)
		return
	}
	var m reflect.Value
	if hasIface {
		iface := handlers[ifaceName]
		m = exportedMethod(iface, name)
	} else {
		for _, v := range handlers {
			m = exportedMethod(v, name)
			if m.IsValid() {
				break
			}
		}
	}
	if !m.IsValid() {
		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)
		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(vs) {
		conn.sendError(errmsgInvalidArg, sender, serial)
		return
	}
	if err := Store(vs, decode...); err != nil {
		conn.sendError(errmsgInvalidArg, sender, serial)
		return
	}
	params := make([]reflect.Value, len(pointers))
	for i := 0; i < len(pointers); i++ {
		params[i] = reflect.ValueOf(pointers[i]).Elem()
	}
	ret := m.Call(params)
	if em := ret[t.NumOut()-1].Interface().(*Error); em != nil {
		conn.sendError(*em, sender, serial)
		return
	}
	if msg.Flags&FlagNoReplyExpected == 0 {
		reply := new(Message)
		reply.Type = TypeMethodReply
		reply.serial = conn.getSerial()
		reply.Headers = make(map[HeaderField]Variant)
		if hasSender {
			reply.Headers[FieldDestination] = msg.Headers[FieldSender]
		}
		reply.Headers[FieldReplySerial] = MakeVariant(msg.serial)
		reply.Body = make([]interface{}, len(ret)-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...))
		}
		conn.outLck.RLock()
		if !conn.closed {
			conn.out <- reply
		}
		conn.outLck.RUnlock()
	}
}
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"},
	}
)
type exportWithMapping struct {
	export interface{}
	mapping map[string]string
	includeSubtree bool
}
type Sender string
func exportedMethod(export exportWithMapping, name string) reflect.Value {
	if export.export == nil {
		return reflect.Value{}
	}
	if export.mapping != nil {
		for key, value := range export.mapping {
			if value == name {
				name = key
				break
			}
			if key == name {
				return reflect.Value{}
			}
		}
	}
	value := reflect.ValueOf(export.export)
	m := value.MethodByName(name)
	method, ok := value.Type().MethodByName(name)
	if !m.IsValid() || !ok || method.PkgPath != "" {
		return reflect.Value{}
	}
	t := m.Type()
	if t.NumOut() == 0 ||
		t.Out(t.NumOut()-1) != reflect.TypeOf(&errmsgInvalidArg) {
		return reflect.Value{}
	}
	return m
}
func (conn *Conn) searchHandlers(path ObjectPath) (map[string]exportWithMapping, bool) {
	conn.handlersLck.RLock()
	defer conn.handlersLck.RUnlock()
	handlers, ok := conn.handlers[path]
	if ok {
		return handlers, ok
	}
	handlers = make(map[string]exportWithMapping)
	path = path[:strings.LastIndex(string(path), "/")]
	for len(path) > 0 {
		var subtreeHandlers map[string]exportWithMapping
		subtreeHandlers, ok = conn.handlers[path]
		if ok {
			for iface, handler := range subtreeHandlers {
				if handler.includeSubtree {
					handlers[iface] = handler
				}
			}
			break
		}
		path = path[:strings.LastIndex(string(path), "/")]
	}
	return handlers, ok
}