func (e *Endpoint) serve_response(msg *Message) error { e.client.mutex.Lock() call, found := e.client.pending[msg.ID] delete(e.client.pending, msg.ID) e.client.mutex.Unlock() if !found { return fmt.Errorf("Server responded with unknown seq %v", msg.ID) } if msg.Error == nil { if call.Reply != nil { err := e.codec.UnmarshalResult(msg, call.Reply) if err != nil { call.Error = fmt.Errorf("Unmarshaling result: %v", err) } } } else { call.Error = rpc.ServerError(msg.Error.Msg) } // notify the caller, but never block select { case call.Done <- call: default: } return nil }
func extractError(resp ErrorResponse) error { if resp.Error != "" { if resp.Fatal { return platform.FatalError{errors.New(resp.Error)} } return rpc.ServerError(resp.Error) } return nil }
// CallWithCodec is used to perform the same actions as rpc.Client.Call but // in a much cheaper way. It assumes the underlying connection is not being // shared with multiple concurrent RPCs. The request/response must be syncronous. func CallWithCodec(cc rpc.ClientCodec, method string, args interface{}, resp interface{}) error { request := rpc.Request{ Seq: atomic.AddUint64(&nextCallSeq, 1), ServiceMethod: method, } if err := cc.WriteRequest(&request, args); err != nil { return err } var response rpc.Response if err := cc.ReadResponseHeader(&response); err != nil { return err } if err := cc.ReadResponseBody(resp); err != nil { return err } if response.Error != "" { return rpc.ServerError(response.Error) } return nil }