diff options
author | Felix Lange <fjl@twurst.com> | 2016-07-12 23:47:15 +0800 |
---|---|---|
committer | Felix Lange <fjl@twurst.com> | 2016-07-23 05:21:27 +0800 |
commit | 91b769042857f542b2792b23ec407e1c9bd4fe8d (patch) | |
tree | f6730b3e85a7ac5ca98f9a716505349958fcacd3 /rpc/json.go | |
parent | bb01bea4e276dad359815c682a2dee730737f4dc (diff) | |
download | dexon-91b769042857f542b2792b23ec407e1c9bd4fe8d.tar.gz dexon-91b769042857f542b2792b23ec407e1c9bd4fe8d.tar.zst dexon-91b769042857f542b2792b23ec407e1c9bd4fe8d.zip |
rpc: add new client, use it everywhere
The new client implementation supports concurrent requests,
subscriptions and replaces the various ad hoc RPC clients
throughout go-ethereum.
Diffstat (limited to 'rpc/json.go')
-rw-r--r-- | rpc/json.go | 61 |
1 files changed, 33 insertions, 28 deletions
diff --git a/rpc/json.go b/rpc/json.go index ee931bc87..a7053e3f5 100644 --- a/rpc/json.go +++ b/rpc/json.go @@ -30,49 +30,43 @@ import ( ) const ( - JSONRPCVersion = "2.0" + jsonrpcVersion = "2.0" serviceMethodSeparator = "_" subscribeMethod = "eth_subscribe" unsubscribeMethod = "eth_unsubscribe" notificationMethod = "eth_subscription" ) -// JSON-RPC request -type JSONRequest struct { +type jsonRequest struct { Method string `json:"method"` Version string `json:"jsonrpc"` Id json.RawMessage `json:"id,omitempty"` Payload json.RawMessage `json:"params,omitempty"` } -// JSON-RPC response -type JSONSuccessResponse struct { +type jsonSuccessResponse struct { Version string `json:"jsonrpc"` Id interface{} `json:"id,omitempty"` Result interface{} `json:"result"` } -// JSON-RPC error object -type JSONError struct { +type jsonError struct { Code int `json:"code"` Message string `json:"message"` Data interface{} `json:"data,omitempty"` } -// JSON-RPC error response -type JSONErrResponse struct { +type jsonErrResponse struct { Version string `json:"jsonrpc"` Id interface{} `json:"id,omitempty"` - Error JSONError `json:"error"` + Error jsonError `json:"error"` } -// JSON-RPC notification payload type jsonSubscription struct { Subscription string `json:"subscription"` Result interface{} `json:"result,omitempty"` } -// JSON-RPC notification type jsonNotification struct { Version string `json:"jsonrpc"` Method string `json:"method"` @@ -91,6 +85,17 @@ type jsonCodec struct { rw io.ReadWriteCloser // connection } +func (err *jsonError) Error() string { + if err.Message == "" { + return fmt.Sprintf("json-rpc error %d", err.Code) + } + return err.Message +} + +func (err *jsonError) ErrorCode() int { + return err.Code +} + // NewJSONCodec creates a new RPC server codec with support for JSON-RPC 2.0 func NewJSONCodec(rwc io.ReadWriteCloser) ServerCodec { d := json.NewDecoder(rwc) @@ -113,7 +118,7 @@ func isBatch(msg json.RawMessage) bool { // ReadRequestHeaders will read new requests without parsing the arguments. It will // return a collection of requests, an indication if these requests are in batch // form or an error when the incoming message could not be read/parsed. -func (c *jsonCodec) ReadRequestHeaders() ([]rpcRequest, bool, RPCError) { +func (c *jsonCodec) ReadRequestHeaders() ([]rpcRequest, bool, Error) { c.decMu.Lock() defer c.decMu.Unlock() @@ -148,8 +153,8 @@ func checkReqId(reqId json.RawMessage) error { // parseRequest will parse a single request from the given RawMessage. It will return // the parsed request, an indication if the request was a batch or an error when // the request could not be parsed. -func parseRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, RPCError) { - var in JSONRequest +func parseRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, Error) { + var in jsonRequest if err := json.Unmarshal(incomingMsg, &in); err != nil { return nil, false, &invalidMessageError{err.Error()} } @@ -197,8 +202,8 @@ func parseRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, RPCError) { // parseBatchRequest will parse a batch request into a collection of requests from the given RawMessage, an indication // if the request was a batch or an error when the request could not be read. -func parseBatchRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, RPCError) { - var in []JSONRequest +func parseBatchRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, Error) { + var in []jsonRequest if err := json.Unmarshal(incomingMsg, &in); err != nil { return nil, false, &invalidMessageError{err.Error()} } @@ -253,7 +258,7 @@ func parseBatchRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, RPCErro // ParseRequestArguments tries to parse the given params (json.RawMessage) with the given types. It returns the parsed // values or an error when the parsing failed. -func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interface{}) ([]reflect.Value, RPCError) { +func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interface{}) ([]reflect.Value, Error) { if args, ok := params.(json.RawMessage); !ok { return nil, &invalidParamsError{"Invalid params supplied"} } else { @@ -264,7 +269,7 @@ func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interf // parsePositionalArguments tries to parse the given args to an array of values with the given types. // It returns the parsed values or an error when the args could not be parsed. Missing optional arguments // are returned as reflect.Zero values. -func parsePositionalArguments(args json.RawMessage, callbackArgs []reflect.Type) ([]reflect.Value, RPCError) { +func parsePositionalArguments(args json.RawMessage, callbackArgs []reflect.Type) ([]reflect.Value, Error) { params := make([]interface{}, 0, len(callbackArgs)) for _, t := range callbackArgs { params = append(params, reflect.New(t).Interface()) @@ -302,31 +307,31 @@ func parsePositionalArguments(args json.RawMessage, callbackArgs []reflect.Type) // CreateResponse will create a JSON-RPC success response with the given id and reply as result. func (c *jsonCodec) CreateResponse(id interface{}, reply interface{}) interface{} { if isHexNum(reflect.TypeOf(reply)) { - return &JSONSuccessResponse{Version: JSONRPCVersion, Id: id, Result: fmt.Sprintf(`%#x`, reply)} + return &jsonSuccessResponse{Version: jsonrpcVersion, Id: id, Result: fmt.Sprintf(`%#x`, reply)} } - return &JSONSuccessResponse{Version: JSONRPCVersion, Id: id, Result: reply} + return &jsonSuccessResponse{Version: jsonrpcVersion, Id: id, Result: reply} } // CreateErrorResponse will create a JSON-RPC error response with the given id and error. -func (c *jsonCodec) CreateErrorResponse(id interface{}, err RPCError) interface{} { - return &JSONErrResponse{Version: JSONRPCVersion, Id: id, Error: JSONError{Code: err.Code(), Message: err.Error()}} +func (c *jsonCodec) CreateErrorResponse(id interface{}, err Error) interface{} { + return &jsonErrResponse{Version: jsonrpcVersion, Id: id, Error: jsonError{Code: err.ErrorCode(), Message: err.Error()}} } // CreateErrorResponseWithInfo will create a JSON-RPC error response with the given id and error. // info is optional and contains additional information about the error. When an empty string is passed it is ignored. -func (c *jsonCodec) CreateErrorResponseWithInfo(id interface{}, err RPCError, info interface{}) interface{} { - return &JSONErrResponse{Version: JSONRPCVersion, Id: id, - Error: JSONError{Code: err.Code(), Message: err.Error(), Data: info}} +func (c *jsonCodec) CreateErrorResponseWithInfo(id interface{}, err Error, info interface{}) interface{} { + return &jsonErrResponse{Version: jsonrpcVersion, Id: id, + Error: jsonError{Code: err.ErrorCode(), Message: err.Error(), Data: info}} } // CreateNotification will create a JSON-RPC notification with the given subscription id and event as params. func (c *jsonCodec) CreateNotification(subid string, event interface{}) interface{} { if isHexNum(reflect.TypeOf(event)) { - return &jsonNotification{Version: JSONRPCVersion, Method: notificationMethod, + return &jsonNotification{Version: jsonrpcVersion, Method: notificationMethod, Params: jsonSubscription{Subscription: subid, Result: fmt.Sprintf(`%#x`, event)}} } - return &jsonNotification{Version: JSONRPCVersion, Method: notificationMethod, + return &jsonNotification{Version: jsonrpcVersion, Method: notificationMethod, Params: jsonSubscription{Subscription: subid, Result: event}} } |