Separate ws command handlers into separate funcs.
This commit is contained in:
parent
53e1c2d6bd
commit
1f087adf15
1 changed files with 359 additions and 278 deletions
185
rpcserver.go
185
rpcserver.go
|
@ -305,6 +305,7 @@ func jsonRPCRead(w http.ResponseWriter, r *http.Request, s *rpcServer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type commandHandler func(*rpcServer, btcjson.Cmd, chan []byte) (interface{}, error)
|
type commandHandler func(*rpcServer, btcjson.Cmd, chan []byte) (interface{}, error)
|
||||||
|
type wsCommandHandler func(*rpcServer, *btcjson.Message, chan []byte, chan *btcjson.Reply) error
|
||||||
|
|
||||||
var handlers = map[string]commandHandler{
|
var handlers = map[string]commandHandler{
|
||||||
"addnode": handleAddNode,
|
"addnode": handleAddNode,
|
||||||
|
@ -325,6 +326,14 @@ var handlers = map[string]commandHandler{
|
||||||
"stop": handleStop,
|
"stop": handleStop,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var wsHandlers = map[string]wsCommandHandler{
|
||||||
|
"getcurrentnet": handleGetCurrentNet,
|
||||||
|
"getbestblock": handleGetBestBlock,
|
||||||
|
"rescan": handleRescan,
|
||||||
|
"notifynewtxs": handleNotifyNewTxs,
|
||||||
|
"notifyspent": handleNotifySpent,
|
||||||
|
}
|
||||||
|
|
||||||
// handleDecodeRawTransaction handles decoderawtransaction commands.
|
// handleDecodeRawTransaction handles decoderawtransaction commands.
|
||||||
func handleAddNode(s *rpcServer, cmd btcjson.Cmd,
|
func handleAddNode(s *rpcServer, cmd btcjson.Cmd,
|
||||||
walletNotification chan []byte) (interface{}, error) {
|
walletNotification chan []byte) (interface{}, error) {
|
||||||
|
@ -723,93 +732,91 @@ func jsonRead(body []byte, s *rpcServer, walletNotification chan []byte) (reply
|
||||||
return reply, err
|
return reply, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, body []byte, s *rpcServer) error {
|
// handleGetCurrentNet implements the getcurrentnet command extension
|
||||||
var message btcjson.Message
|
// for websocket connections.
|
||||||
err := json.Unmarshal(body, &message)
|
func handleGetCurrentNet(s *rpcServer, message *btcjson.Message,
|
||||||
if err != nil {
|
walletNotification chan []byte, replychan chan *btcjson.Reply) error {
|
||||||
reply := btcjson.Reply{
|
|
||||||
Result: nil,
|
|
||||||
Error: &btcjson.ErrParse,
|
|
||||||
Id: nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Tracef("RPCS: reply: %v", reply)
|
|
||||||
|
|
||||||
replychan <- &reply
|
|
||||||
return fmt.Errorf("RPCS: Error unmarshalling json message: %v", err)
|
|
||||||
}
|
|
||||||
log.Tracef("RPCS: received: %v", message)
|
|
||||||
|
|
||||||
var rawReply btcjson.Reply
|
|
||||||
defer func() {
|
|
||||||
replychan <- &rawReply
|
|
||||||
close(replychan)
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Deal with commands
|
|
||||||
switch message.Method {
|
|
||||||
case "getcurrentnet":
|
|
||||||
var net btcwire.BitcoinNet
|
var net btcwire.BitcoinNet
|
||||||
if cfg.TestNet3 {
|
if cfg.TestNet3 {
|
||||||
net = btcwire.TestNet3
|
net = btcwire.TestNet3
|
||||||
} else {
|
} else {
|
||||||
net = btcwire.MainNet
|
net = btcwire.MainNet
|
||||||
}
|
}
|
||||||
rawReply = btcjson.Reply{
|
|
||||||
|
rawReply := &btcjson.Reply{
|
||||||
Result: float64(net),
|
Result: float64(net),
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleGetBestBlock implements the getbestblock command extension
|
||||||
|
// for websocket connections.
|
||||||
|
func handleGetBestBlock(s *rpcServer, message *btcjson.Message,
|
||||||
|
walletNotification chan []byte, replychan chan *btcjson.Reply) error {
|
||||||
|
|
||||||
case "getbestblock":
|
|
||||||
// All other "get block" commands give either the height, the
|
// All other "get block" commands give either the height, the
|
||||||
// hash, or both but require the block SHA. This gets both for
|
// hash, or both but require the block SHA. This gets both for
|
||||||
// the best block.
|
// the best block.
|
||||||
sha, height, err := s.server.db.NewestSha()
|
sha, height, err := s.server.db.NewestSha()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("RPCS: Error getting newest block: %v", err)
|
log.Errorf("RPCS: Error getting newest block: %v", err)
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &btcjson.ErrBestBlockHash,
|
Error: &btcjson.ErrBestBlockHash,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: map[string]interface{}{
|
Result: map[string]interface{}{
|
||||||
"hash": sha.String(),
|
"hash": sha.String(),
|
||||||
"height": height,
|
"height": height,
|
||||||
},
|
},
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleRescan implements the rescan command extension for websocket
|
||||||
|
// connections.
|
||||||
|
func handleRescan(s *rpcServer, message *btcjson.Message,
|
||||||
|
walletNotification chan []byte, replychan chan *btcjson.Reply) error {
|
||||||
|
|
||||||
case "rescan":
|
|
||||||
minblock, maxblock := int64(0), btcdb.AllShas
|
minblock, maxblock := int64(0), btcdb.AllShas
|
||||||
params, ok := message.Params.([]interface{})
|
params, ok := message.Params.([]interface{})
|
||||||
if !ok || len(params) < 2 {
|
if !ok || len(params) < 2 {
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &btcjson.ErrInvalidParams,
|
Error: &btcjson.ErrInvalidParams,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
return ErrBadParamsField
|
return ErrBadParamsField
|
||||||
}
|
}
|
||||||
fminblock, ok := params[0].(float64)
|
fminblock, ok := params[0].(float64)
|
||||||
if !ok {
|
if !ok {
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &btcjson.ErrInvalidParams,
|
Error: &btcjson.ErrInvalidParams,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
return ErrBadParamsField
|
return ErrBadParamsField
|
||||||
}
|
}
|
||||||
minblock = int64(fminblock)
|
minblock = int64(fminblock)
|
||||||
iaddrs, ok := params[1].([]interface{})
|
iaddrs, ok := params[1].([]interface{})
|
||||||
if !ok {
|
if !ok {
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &btcjson.ErrInvalidParams,
|
Error: &btcjson.ErrInvalidParams,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
return ErrBadParamsField
|
return ErrBadParamsField
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,21 +825,23 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
|
||||||
for i := range iaddrs {
|
for i := range iaddrs {
|
||||||
addr, ok := iaddrs[i].(string)
|
addr, ok := iaddrs[i].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &btcjson.ErrInvalidParams,
|
Error: &btcjson.ErrInvalidParams,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
return ErrBadParamsField
|
return ErrBadParamsField
|
||||||
}
|
}
|
||||||
|
|
||||||
addrhash, _, err := btcutil.DecodeAddress(addr)
|
addrhash, _, err := btcutil.DecodeAddress(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &btcjson.ErrInvalidParams,
|
Error: &btcjson.ErrInvalidParams,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
return ErrBadParamsField
|
return ErrBadParamsField
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,11 +851,12 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
|
||||||
if len(params) > 2 {
|
if len(params) > 2 {
|
||||||
fmaxblock, ok := params[2].(float64)
|
fmaxblock, ok := params[2].(float64)
|
||||||
if !ok {
|
if !ok {
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &btcjson.ErrInvalidParams,
|
Error: &btcjson.ErrInvalidParams,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
return ErrBadParamsField
|
return ErrBadParamsField
|
||||||
}
|
}
|
||||||
maxblock = int64(fmaxblock)
|
maxblock = int64(fmaxblock)
|
||||||
|
@ -890,7 +900,7 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if ok := addrHashes[string(txaddrhash)]; ok {
|
if ok := addrHashes[string(txaddrhash)]; ok {
|
||||||
reply := btcjson.Reply{
|
reply := &btcjson.Reply{
|
||||||
Result: struct {
|
Result: struct {
|
||||||
Sender string `json:"sender"`
|
Sender string `json:"sender"`
|
||||||
Receiver string `json:"receiver"`
|
Receiver string `json:"receiver"`
|
||||||
|
@ -915,7 +925,7 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
|
||||||
Error: nil,
|
Error: nil,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
replychan <- &reply
|
replychan <- reply
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -928,31 +938,40 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: nil,
|
Error: nil,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
|
|
||||||
log.Debug("RPCS: Finished rescan")
|
log.Debug("RPCS: Finished rescan")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleNotifyNewTxs implements the notifynewtxs command extension for
|
||||||
|
// websocket connections.
|
||||||
|
func handleNotifyNewTxs(s *rpcServer, message *btcjson.Message,
|
||||||
|
walletNotification chan []byte, replychan chan *btcjson.Reply) error {
|
||||||
|
|
||||||
case "notifynewtxs":
|
|
||||||
params, ok := message.Params.([]interface{})
|
params, ok := message.Params.([]interface{})
|
||||||
if !ok || len(params) != 1 {
|
if !ok || len(params) != 1 {
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &btcjson.ErrInvalidParams,
|
Error: &btcjson.ErrInvalidParams,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
return ErrBadParamsField
|
return ErrBadParamsField
|
||||||
}
|
}
|
||||||
addr, ok := params[0].(string)
|
addr, ok := params[0].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &btcjson.ErrInvalidParams,
|
Error: &btcjson.ErrInvalidParams,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
return ErrBadParamsField
|
return ErrBadParamsField
|
||||||
}
|
}
|
||||||
addrhash, _, err := btcutil.DecodeAddress(addr)
|
addrhash, _, err := btcutil.DecodeAddress(addr)
|
||||||
|
@ -961,39 +980,49 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
|
||||||
Code: btcjson.ErrInvalidParams.Code,
|
Code: btcjson.ErrInvalidParams.Code,
|
||||||
Message: "Cannot decode address",
|
Message: "Cannot decode address",
|
||||||
}
|
}
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &jsonError,
|
Error: &jsonError,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
return ErrBadParamsField
|
return ErrBadParamsField
|
||||||
}
|
}
|
||||||
s.ws.requests.AddTxRequest(walletNotification, string(addrhash), message.Id)
|
s.ws.requests.AddTxRequest(walletNotification, string(addrhash), message.Id)
|
||||||
|
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: nil,
|
Error: nil,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleNotifySpent implements the notifyspent command extension for
|
||||||
|
// websocket connections.
|
||||||
|
func handleNotifySpent(s *rpcServer, message *btcjson.Message,
|
||||||
|
walletNotification chan []byte, replychan chan *btcjson.Reply) error {
|
||||||
|
|
||||||
case "notifyspent":
|
|
||||||
params, ok := message.Params.([]interface{})
|
params, ok := message.Params.([]interface{})
|
||||||
if !ok || len(params) != 2 {
|
if !ok || len(params) != 2 {
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &btcjson.ErrInvalidParams,
|
Error: &btcjson.ErrInvalidParams,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
return ErrBadParamsField
|
return ErrBadParamsField
|
||||||
}
|
}
|
||||||
hashBE, ok1 := params[0].(string)
|
hashBE, ok1 := params[0].(string)
|
||||||
index, ok2 := params[1].(float64)
|
index, ok2 := params[1].(float64)
|
||||||
if !ok1 || !ok2 {
|
if !ok1 || !ok2 {
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &btcjson.ErrInvalidParams,
|
Error: &btcjson.ErrInvalidParams,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
return ErrBadParamsField
|
return ErrBadParamsField
|
||||||
}
|
}
|
||||||
hash, err := btcwire.NewShaHashFromStr(hashBE)
|
hash, err := btcwire.NewShaHashFromStr(hashBE)
|
||||||
|
@ -1002,30 +1031,82 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
|
||||||
Code: btcjson.ErrInvalidParams.Code,
|
Code: btcjson.ErrInvalidParams.Code,
|
||||||
Message: "Hash string cannot be parsed.",
|
Message: "Hash string cannot be parsed.",
|
||||||
}
|
}
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &jsonError,
|
Error: &jsonError,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
return ErrBadParamsField
|
return ErrBadParamsField
|
||||||
}
|
}
|
||||||
op := btcwire.NewOutPoint(hash, uint32(index))
|
op := btcwire.NewOutPoint(hash, uint32(index))
|
||||||
s.ws.requests.AddSpentRequest(walletNotification, op, message.Id)
|
s.ws.requests.AddSpentRequest(walletNotification, op, message.Id)
|
||||||
|
|
||||||
rawReply = btcjson.Reply{
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: nil,
|
Error: nil,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
|
replychan <- rawReply
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, body []byte, s *rpcServer) error {
|
||||||
rawReply = btcjson.Reply{
|
var message btcjson.Message
|
||||||
|
err := json.Unmarshal(body, &message)
|
||||||
|
if err != nil {
|
||||||
|
reply := btcjson.Reply{
|
||||||
|
Result: nil,
|
||||||
|
Error: &btcjson.ErrParse,
|
||||||
|
Id: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Tracef("RPCS: reply: %v", reply)
|
||||||
|
|
||||||
|
replychan <- &reply
|
||||||
|
return fmt.Errorf("RPCS: Error unmarshalling json message: %v", err)
|
||||||
|
}
|
||||||
|
log.Tracef("RPCS: received: %v", message)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
close(replychan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
wsHandler, ok := wsHandlers[message.Method]
|
||||||
|
if !ok {
|
||||||
|
rawReply := &btcjson.Reply{
|
||||||
Result: nil,
|
Result: nil,
|
||||||
Error: &btcjson.ErrMethodNotFound,
|
Error: &btcjson.ErrMethodNotFound,
|
||||||
Id: &message.Id,
|
Id: &message.Id,
|
||||||
}
|
}
|
||||||
}
|
replychan <- rawReply
|
||||||
return btcjson.ErrMethodNotFound
|
return btcjson.ErrMethodNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := wsHandler(s, &message, walletNotification, replychan); err != nil {
|
||||||
|
if jsonErr, ok := err.(btcjson.Error); ok {
|
||||||
|
rawReply := &btcjson.Reply{
|
||||||
|
Error: &jsonErr,
|
||||||
|
Id: &message.Id,
|
||||||
|
}
|
||||||
|
replychan <- rawReply
|
||||||
|
err = errors.New(jsonErr.Message)
|
||||||
|
} else {
|
||||||
|
// In the case where we did not have a btcjson
|
||||||
|
// error to begin with, make a new one to send,
|
||||||
|
// but this really should not happen.
|
||||||
|
rawJSONError := btcjson.Error{
|
||||||
|
Code: btcjson.ErrInternal.Code,
|
||||||
|
Message: err.Error(),
|
||||||
|
}
|
||||||
|
rawReply := &btcjson.Reply{
|
||||||
|
Error: &rawJSONError,
|
||||||
|
Id: &message.Id,
|
||||||
|
}
|
||||||
|
replychan <- rawReply
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// getDifficultyRatio returns the proof-of-work difficulty as a multiple of the
|
// getDifficultyRatio returns the proof-of-work difficulty as a multiple of the
|
||||||
|
|
Loading…
Reference in a new issue