// 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, nil, &Error{nil, "Error occurred while receiving a response"} } msgId, result, _err := HandleRPCResponse(data) if _err != nil { return 0, nil, _err } return msgId, result, nil }
// Goes into the event loop to get ready to serve. func (self *Server) Run() *Server { lchan := make(chan int) self.listeners.Do(func(listener interface{}) { _listener := listener.(net.Listener) go (func() { for { conn, err := _listener.Accept() if err != nil { self.log.Println(err.String()) continue } if self.lchan == nil { conn.Close() break } go (func() { for { data, _, err := msgpack.UnpackReflected(conn) var arguments, retvals []reflect.Value if err == os.EOF { break } else if err != nil { self.log.Println(err.String()) break } msgId, funcName, _arguments, xerr := HandleRPCRequest(data) if xerr != nil { self.log.Println(xerr.String()) break } f, xerr := self.resolver.Resolve(funcName, _arguments) if xerr != nil { msg := xerr.String() self.log.Println(msg) SendErrorResponseMessage(conn, msgId, msg) } funcType := f.Type() if funcType.NumIn() != 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) goto next } 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") goto next } if self.autoCoercing { arguments = make([]reflect.Value, funcType.NumIn()) for i, v := range _arguments { ft := funcType.In(i) vt := v.Type() if ft == vt { arguments[i] = v } else { if ft != nil { _vt := v.Type() if _vt.Kind() == reflect.Array || _vt.Kind() == reflect.Slice { et := _vt.Elem() if et != nil && et.Kind() == reflect.Uint8 { arguments[i] = reflect.ValueOf(string(v.Interface().([]byte))) continue } } } 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) goto next } } } else { for i, v := range _arguments { ft := funcType.In(i) vt := v.Type() if ft != vt { 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) goto next } } arguments = _arguments } retvals = f.Call(arguments) if funcType.NumOut() == 2 { var errMsg stringizable = nil var ok bool _errMsg := retvals[1].Interface() if _errMsg != nil { errMsg, ok = _errMsg.(stringizable) if !ok { self.log.Println("The second argument must have an interface { String() string }") SendErrorResponseMessage(conn, msgId, "Internal server error") goto next } } if errMsg == nil { if self.autoCoercing { _retval := retvals[0] if _retval.Kind() == reflect.String { retvals[0] = reflect.ValueOf([]byte(_retval.String())) } } SendResponseMessage(conn, msgId, retvals[0]) } else { SendErrorResponseMessage(conn, msgId, errMsg.String()) } } else { SendResponseMessage(conn, msgId, retvals[0]) } next: } conn.Close() })() } })() }) self.lchan = lchan <-lchan self.listeners.Do(func(listener interface{}) { listener.(net.Listener).Close() }) return self }