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