Example #1
0
// 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
}
Example #2
0
// 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
}