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 wsCommandHandler func(*rpcServer, *btcjson.Message, chan []byte, chan *btcjson.Reply) error
|
||||
|
||||
var handlers = map[string]commandHandler{
|
||||
"addnode": handleAddNode,
|
||||
|
@ -325,6 +326,14 @@ var handlers = map[string]commandHandler{
|
|||
"stop": handleStop,
|
||||
}
|
||||
|
||||
var wsHandlers = map[string]wsCommandHandler{
|
||||
"getcurrentnet": handleGetCurrentNet,
|
||||
"getbestblock": handleGetBestBlock,
|
||||
"rescan": handleRescan,
|
||||
"notifynewtxs": handleNotifyNewTxs,
|
||||
"notifyspent": handleNotifySpent,
|
||||
}
|
||||
|
||||
// handleDecodeRawTransaction handles decoderawtransaction commands.
|
||||
func handleAddNode(s *rpcServer, cmd btcjson.Cmd,
|
||||
walletNotification chan []byte) (interface{}, error) {
|
||||
|
@ -723,93 +732,91 @@ func jsonRead(body []byte, s *rpcServer, walletNotification chan []byte) (reply
|
|||
return reply, err
|
||||
}
|
||||
|
||||
func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, body []byte, s *rpcServer) error {
|
||||
var message btcjson.Message
|
||||
err := json.Unmarshal(body, &message)
|
||||
if err != nil {
|
||||
reply := btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &btcjson.ErrParse,
|
||||
Id: nil,
|
||||
}
|
||||
// handleGetCurrentNet implements the getcurrentnet command extension
|
||||
// for websocket connections.
|
||||
func handleGetCurrentNet(s *rpcServer, message *btcjson.Message,
|
||||
walletNotification chan []byte, replychan chan *btcjson.Reply) error {
|
||||
|
||||
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
|
||||
if cfg.TestNet3 {
|
||||
net = btcwire.TestNet3
|
||||
} else {
|
||||
net = btcwire.MainNet
|
||||
}
|
||||
rawReply = btcjson.Reply{
|
||||
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: float64(net),
|
||||
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
|
||||
// hash, or both but require the block SHA. This gets both for
|
||||
// the best block.
|
||||
sha, height, err := s.server.db.NewestSha()
|
||||
if err != nil {
|
||||
log.Errorf("RPCS: Error getting newest block: %v", err)
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &btcjson.ErrBestBlockHash,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return err
|
||||
}
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: map[string]interface{}{
|
||||
"hash": sha.String(),
|
||||
"height": height,
|
||||
},
|
||||
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
|
||||
params, ok := message.Params.([]interface{})
|
||||
if !ok || len(params) < 2 {
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &btcjson.ErrInvalidParams,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return ErrBadParamsField
|
||||
}
|
||||
fminblock, ok := params[0].(float64)
|
||||
if !ok {
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &btcjson.ErrInvalidParams,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return ErrBadParamsField
|
||||
}
|
||||
minblock = int64(fminblock)
|
||||
iaddrs, ok := params[1].([]interface{})
|
||||
if !ok {
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &btcjson.ErrInvalidParams,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return ErrBadParamsField
|
||||
}
|
||||
|
||||
|
@ -818,21 +825,23 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
|
|||
for i := range iaddrs {
|
||||
addr, ok := iaddrs[i].(string)
|
||||
if !ok {
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &btcjson.ErrInvalidParams,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return ErrBadParamsField
|
||||
}
|
||||
|
||||
addrhash, _, err := btcutil.DecodeAddress(addr)
|
||||
if err != nil {
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &btcjson.ErrInvalidParams,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return ErrBadParamsField
|
||||
}
|
||||
|
||||
|
@ -842,11 +851,12 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
|
|||
if len(params) > 2 {
|
||||
fmaxblock, ok := params[2].(float64)
|
||||
if !ok {
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &btcjson.ErrInvalidParams,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return ErrBadParamsField
|
||||
}
|
||||
maxblock = int64(fmaxblock)
|
||||
|
@ -890,7 +900,7 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
|
|||
return err
|
||||
}
|
||||
if ok := addrHashes[string(txaddrhash)]; ok {
|
||||
reply := btcjson.Reply{
|
||||
reply := &btcjson.Reply{
|
||||
Result: struct {
|
||||
Sender string `json:"sender"`
|
||||
Receiver string `json:"receiver"`
|
||||
|
@ -915,7 +925,7 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
|
|||
Error: nil,
|
||||
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,
|
||||
Error: nil,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
|
||||
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{})
|
||||
if !ok || len(params) != 1 {
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &btcjson.ErrInvalidParams,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return ErrBadParamsField
|
||||
}
|
||||
addr, ok := params[0].(string)
|
||||
if !ok {
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &btcjson.ErrInvalidParams,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return ErrBadParamsField
|
||||
}
|
||||
addrhash, _, err := btcutil.DecodeAddress(addr)
|
||||
|
@ -961,39 +980,49 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
|
|||
Code: btcjson.ErrInvalidParams.Code,
|
||||
Message: "Cannot decode address",
|
||||
}
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &jsonError,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return ErrBadParamsField
|
||||
}
|
||||
s.ws.requests.AddTxRequest(walletNotification, string(addrhash), message.Id)
|
||||
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: nil,
|
||||
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{})
|
||||
if !ok || len(params) != 2 {
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &btcjson.ErrInvalidParams,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return ErrBadParamsField
|
||||
}
|
||||
hashBE, ok1 := params[0].(string)
|
||||
index, ok2 := params[1].(float64)
|
||||
if !ok1 || !ok2 {
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &btcjson.ErrInvalidParams,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return ErrBadParamsField
|
||||
}
|
||||
hash, err := btcwire.NewShaHashFromStr(hashBE)
|
||||
|
@ -1002,32 +1031,84 @@ func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, b
|
|||
Code: btcjson.ErrInvalidParams.Code,
|
||||
Message: "Hash string cannot be parsed.",
|
||||
}
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: &jsonError,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return ErrBadParamsField
|
||||
}
|
||||
op := btcwire.NewOutPoint(hash, uint32(index))
|
||||
s.ws.requests.AddSpentRequest(walletNotification, op, message.Id)
|
||||
|
||||
rawReply = btcjson.Reply{
|
||||
rawReply := &btcjson.Reply{
|
||||
Result: nil,
|
||||
Error: nil,
|
||||
Id: &message.Id,
|
||||
}
|
||||
replychan <- rawReply
|
||||
return nil
|
||||
}
|
||||
|
||||
default:
|
||||
rawReply = btcjson.Reply{
|
||||
func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, body []byte, s *rpcServer) error {
|
||||
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,
|
||||
Error: &btcjson.ErrMethodNotFound,
|
||||
Id: &message.Id,
|
||||
}
|
||||
}
|
||||
replychan <- rawReply
|
||||
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
|
||||
// minimum difficulty using the passed bits field from the header of a block.
|
||||
func getDifficultyRatio(bits uint32) float64 {
|
||||
|
|
Loading…
Reference in a new issue