From d7d2385fb0ac5797b787407499071b8fb7116638 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Tue, 29 Oct 2013 23:23:22 -0400 Subject: [PATCH] Return JSON id with errors when possible. This change unbreaks the case where an unknown command is sent to the RPC server. Instead of replying back with a nil JSON id, if the initial unmarshal was successful (and thus, the message was valid JSON-RPC), the unmarshaled id will be used in the error reply. --- rpcserver.go | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index b73fc759..8990c6ec 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -33,10 +33,6 @@ var ( // ErrBadParamsField describes an error where the parameters JSON // field cannot be properly parsed. ErrBadParamsField = errors.New("bad params field") - - // ErrMethodNotImplemented describes an error where the RPC or - // websocket JSON method is not implemented. - ErrMethodNotImplemented = errors.New("method not implemented") ) // rpcServer holds the items the rpc server may need to access (config, @@ -648,17 +644,30 @@ func handleStop(s *rpcServer, cmd btcjson.Cmd, walletNotification chan []byte) ( func jsonRead(body []byte, s *rpcServer, walletNotification chan []byte) (reply btcjson.Reply, err error) { cmd, err := btcjson.ParseMarshaledCmd(body) if err != nil { - jsonError := btcjson.ErrParse + var id interface{} + if cmd != nil { + // Unmarshaling a valid JSON-RPC message succeeded. Use + // the provided id for errors. + id = cmd.Id() + } - reply = btcjson.Reply{ - Result: nil, - Error: &jsonError, - Id: nil, + if jsonErr, ok := err.(btcjson.Error); ok { + reply = btcjson.Reply{ + Result: nil, + Error: &jsonErr, + Id: &id, + } + } else { + reply = btcjson.Reply{ + Result: nil, + Error: &jsonErr, + Id: &id, + } } log.Tracef("RPCS: reply: %v", reply) - return reply, jsonError + return reply, err } log.Tracef("RPCS: received: %v", cmd) @@ -671,7 +680,7 @@ func jsonRead(body []byte, s *rpcServer, walletNotification chan []byte) (reply Error: &btcjson.ErrMethodNotFound, Id: &id, } - return reply, ErrMethodNotImplemented + return reply, btcjson.ErrMethodNotFound } result, err := handler(s, cmd, walletNotification) @@ -914,7 +923,7 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b Id: &message.Id, } } - return ErrMethodNotImplemented + return btcjson.ErrMethodNotFound } // getDifficultyRatio returns the proof-of-work difficulty as a multiple of the @@ -1035,7 +1044,7 @@ func (s *rpcServer) websocketJSONHandler(walletNotification chan []byte, msg []b reply, err := jsonRead(msg, s, walletNotification) s.wg.Done() - if err != ErrMethodNotImplemented { + if err != btcjson.ErrMethodNotFound { replyBytes, err := json.Marshal(reply) if err != nil { log.Errorf("RPCS: Error marshalling reply: %v", err) @@ -1070,16 +1079,9 @@ func (s *rpcServer) websocketJSONHandler(walletNotification chan []byte, msg []b } } }() - - if err == ErrMethodNotImplemented { - // Try websocket extensions - s.wg.Add(1) - err = jsonWSRead(walletNotification, replychan, msg, s) - s.wg.Done() - } - if err != nil && err != ErrMethodNotImplemented { - log.Error(err) - } + s.wg.Add(1) + err = jsonWSRead(walletNotification, replychan, msg, s) + s.wg.Done() } // NotifyBlockConnected creates and marshalls a JSON message to notify