// This is a low-level function that is not supposed to be called directly // by the user. Change this if the MessagePack protocol is updated. func ReceiveResponse(reader io.Reader) (int, reflect.Value, error) { data, _, err := msgpack.UnpackReflected(reader) if err != nil { return 0, reflect.Value{}, errors.New("Error occurred while receiving a response") } msgId, result, err := HandleRPCResponse(data) if err != nil { return 0, reflect.Value{}, err } return msgId, result, nil }
// Goes into the event loop to get ready to serve. func (self *RpcServer) Run() *RpcServer { lchan := make(chan int) for _, listener := range self.listeners { go (func(listener net.Listener) { for { conn, err := listener.Accept() if err != nil { self.log.Println(err) continue } if self.lchan == nil { conn.Close() break } go (func() { NextRequest: for { data, _, err := msgpack.UnpackReflected(conn) if err == io.EOF { break } else if err != nil { self.log.Println(err) break } msgId, funcName, _arguments, xerr := HandleRPCRequest(data) if xerr != nil { self.log.Println(xerr) continue NextRequest } service, f, xerr := self.resolver.Resolve(funcName, _arguments) if xerr != nil { self.log.Println(xerr) SendErrorResponseMessage(conn, msgId, xerr.Error()) continue NextRequest } funcType := f.Type() if funcType.NumIn()-1 != len(_arguments) { msg := fmt.Sprintf("The number of the given arguments (%d) doesn't match the arity (%d)", len(_arguments), funcType.NumIn()) self.log.Println(msg) SendErrorResponseMessage(conn, msgId, msg) continue NextRequest } if funcType.NumOut() != 1 && funcType.NumOut() != 2 { self.log.Println("The number of return values must be 1 or 2") SendErrorResponseMessage(conn, msgId, "Internal server error") continue NextRequest } arguments := make([]reflect.Value, funcType.NumIn()) arguments[0] = reflect.ValueOf(service) for i, v := range _arguments { key := i + 1 ft := funcType.In(key) vt := v.Type() if vt.AssignableTo(ft) { arguments[key] = v } else if pv, ok := integerPromote(ft, v); ok { arguments[key] = pv } else if self.autoCoercing && ft != nil && ft.Kind() == reflect.String && (v.Type().Kind() == reflect.Array || v.Type().Kind() == reflect.Slice) && (v.Type().Elem().Kind() == reflect.Uint8) { arguments[key] = reflect.ValueOf(string(v.Interface().([]byte))) } else { msg := fmt.Sprintf("The type of argument #%d doesn't match (%s expected, got %s)", i, ft.String(), vt.String()) self.log.Println(msg) SendErrorResponseMessage(conn, msgId, msg) continue NextRequest } } retvals := f.Call(arguments) if funcType.NumOut() == 1 { SendResponseMessage(conn, msgId, retvals[0]) continue NextRequest } var errMsg fmt.Stringer = nil _errMsg := retvals[1].Interface() if _errMsg != nil { var ok bool errMsg, ok = _errMsg.(fmt.Stringer) if !ok { self.log.Println("The second argument must have an interface { String() string }") SendErrorResponseMessage(conn, msgId, "Internal server error") continue NextRequest } } if errMsg != nil { SendErrorResponseMessage(conn, msgId, errMsg.String()) continue NextRequest } if self.autoCoercing { _retval := retvals[0] if _retval.Kind() == reflect.String { retvals[0] = reflect.ValueOf([]byte(_retval.String())) } } SendResponseMessage(conn, msgId, retvals[0]) } conn.Close() })() } })(listener) } self.lchan = lchan <-lchan for _, listener := range self.listeners { listener.Close() } return self }