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.
This commit is contained in:
Josh Rickmar 2013-10-29 23:23:22 -04:00
parent 9442d96929
commit d7d2385fb0

View file

@ -33,10 +33,6 @@ var (
// ErrBadParamsField describes an error where the parameters JSON // ErrBadParamsField describes an error where the parameters JSON
// field cannot be properly parsed. // field cannot be properly parsed.
ErrBadParamsField = errors.New("bad params field") 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, // 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) { func jsonRead(body []byte, s *rpcServer, walletNotification chan []byte) (reply btcjson.Reply, err error) {
cmd, err := btcjson.ParseMarshaledCmd(body) cmd, err := btcjson.ParseMarshaledCmd(body)
if err != nil { 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{ if jsonErr, ok := err.(btcjson.Error); ok {
Result: nil, reply = btcjson.Reply{
Error: &jsonError, Result: nil,
Id: nil, Error: &jsonErr,
Id: &id,
}
} else {
reply = btcjson.Reply{
Result: nil,
Error: &jsonErr,
Id: &id,
}
} }
log.Tracef("RPCS: reply: %v", reply) log.Tracef("RPCS: reply: %v", reply)
return reply, jsonError return reply, err
} }
log.Tracef("RPCS: received: %v", cmd) log.Tracef("RPCS: received: %v", cmd)
@ -671,7 +680,7 @@ func jsonRead(body []byte, s *rpcServer, walletNotification chan []byte) (reply
Error: &btcjson.ErrMethodNotFound, Error: &btcjson.ErrMethodNotFound,
Id: &id, Id: &id,
} }
return reply, ErrMethodNotImplemented return reply, btcjson.ErrMethodNotFound
} }
result, err := handler(s, cmd, walletNotification) result, err := handler(s, cmd, walletNotification)
@ -914,7 +923,7 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
Id: &message.Id, Id: &message.Id,
} }
} }
return ErrMethodNotImplemented return btcjson.ErrMethodNotFound
} }
// getDifficultyRatio returns the proof-of-work difficulty as a multiple of the // 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) reply, err := jsonRead(msg, s, walletNotification)
s.wg.Done() s.wg.Done()
if err != ErrMethodNotImplemented { if err != btcjson.ErrMethodNotFound {
replyBytes, err := json.Marshal(reply) replyBytes, err := json.Marshal(reply)
if err != nil { if err != nil {
log.Errorf("RPCS: Error marshalling reply: %v", err) log.Errorf("RPCS: Error marshalling reply: %v", err)
@ -1070,16 +1079,9 @@ func (s *rpcServer) websocketJSONHandler(walletNotification chan []byte, msg []b
} }
} }
}() }()
s.wg.Add(1)
if err == ErrMethodNotImplemented { err = jsonWSRead(walletNotification, replychan, msg, s)
// Try websocket extensions s.wg.Done()
s.wg.Add(1)
err = jsonWSRead(walletNotification, replychan, msg, s)
s.wg.Done()
}
if err != nil && err != ErrMethodNotImplemented {
log.Error(err)
}
} }
// NotifyBlockConnected creates and marshalls a JSON message to notify // NotifyBlockConnected creates and marshalls a JSON message to notify