Add support for the addnode command

Currently this acts on the list of all peers, and not just the list of
permanent peers. this will be changed shortly.
This commit is contained in:
Owain G. Ainsworth 2013-10-29 17:18:53 +00:00
parent b1f14732b1
commit da2901a4fd
2 changed files with 86 additions and 1 deletions

View file

@ -311,6 +311,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)
var handlers = map[string]commandHandler{ var handlers = map[string]commandHandler{
"addnode": handleAddNode,
"decoderawtransaction": handleDecodeRawTransaction, "decoderawtransaction": handleDecodeRawTransaction,
"getbestblockhash": handleGetBestBlockHash, "getbestblockhash": handleGetBestBlockHash,
"getblock": handleGetBlock, "getblock": handleGetBlock,
@ -328,6 +329,28 @@ var handlers = map[string]commandHandler{
"stop": handleStop, "stop": handleStop,
} }
// handleDecodeRawTransaction handles decoderawtransaction commands.
func handleAddNode(s *rpcServer, cmd btcjson.Cmd,
walletNotification chan []byte) (interface{}, error) {
c := cmd.(*btcjson.AddNodeCmd)
addr := normalizePeerAddress(c.Addr)
var err error
switch c.SubCmd {
case "add":
err = s.server.AddAddr(addr, true)
case "remove":
err = s.server.RemoveAddr(addr)
case "onetry":
err = s.server.AddAddr(addr, false)
default:
err = errors.New("Invalid subcommand for addnode")
}
// no data returned unless an error.
return nil, err
}
// handleDecodeRawTransaction handles decoderawtransaction commands. // handleDecodeRawTransaction handles decoderawtransaction commands.
func handleDecodeRawTransaction(s *rpcServer, cmd btcjson.Cmd, func handleDecodeRawTransaction(s *rpcServer, cmd btcjson.Cmd,
walletNotification chan []byte) (interface{}, error) { walletNotification chan []byte) (interface{}, error) {
@ -469,7 +492,7 @@ func handleGetHashesPerSec(s *rpcServer, cmd btcjson.Cmd, walletNotification cha
// handleGetPeerInfo implements the getpeerinfo command. // handleGetPeerInfo implements the getpeerinfo command.
func handleGetPeerInfo(s *rpcServer, cmd btcjson.Cmd, walletNotification chan []byte) (interface{}, error) { func handleGetPeerInfo(s *rpcServer, cmd btcjson.Cmd, walletNotification chan []byte) (interface{}, error) {
return s.server.PeerInfo(), nil return s.server.PeerInfo(), nil
} }
// handleGetRawMempool implements the getrawmempool command. // handleGetRawMempool implements the getrawmempool command.

View file

@ -6,6 +6,7 @@ package main
import ( import (
"container/list" "container/list"
"errors"
"fmt" "fmt"
"github.com/conformal/btcdb" "github.com/conformal/btcdb"
"github.com/conformal/btcwire" "github.com/conformal/btcwire"
@ -223,6 +224,16 @@ type getPeerInfoMsg struct {
reply chan []*PeerInfo reply chan []*PeerInfo
} }
type addNodeMsg struct {
addr string
permanent bool
reply chan error
}
type delNodeMsg struct {
addr string
reply chan error
}
func (s *server) handleQuery(querymsg interface{}, peers *list.List, bannedPeers map[string]time.Time) { func (s *server) handleQuery(querymsg interface{}, peers *list.List, bannedPeers map[string]time.Time) {
switch msg := querymsg.(type) { switch msg := querymsg.(type) {
@ -265,6 +276,41 @@ func (s *server) handleQuery(querymsg interface{}, peers *list.List, bannedPeers
infos = append(infos, info) infos = append(infos, info)
} }
msg.reply <- infos msg.reply <- infos
case addNodeMsg:
// TODO(oga) really these checks only apply to permanent peers.
for e := peers.Front(); e != nil; e = e.Next() {
peer := e.Value.(*peer)
if peer.addr == msg.addr {
msg.reply <- errors.New("peer already connected")
return
}
}
// TODO(oga) if too many, nuke a non-perm peer.
if s.handleAddPeerMsg(peers, bannedPeers,
newOutboundPeer(s, msg.addr, msg.permanent)) {
msg.reply <- nil
} else {
msg.reply <- errors.New("failed to add peer")
}
case delNodeMsg:
found := false
// TODO(oga) really these checks only apply to permanent peers.
for e := peers.Front(); e != nil; e = e.Next() {
peer := e.Value.(*peer)
if peer.addr == msg.addr {
peer.persistent = false // XXX hack!
peer.Disconnect()
found = true
break
}
}
if found {
msg.reply <- nil
} else {
msg.reply <- errors.New("peer not found")
}
} }
} }
@ -545,6 +591,22 @@ func (s *server) PeerInfo() []*PeerInfo {
return <-replyChan return <-replyChan
} }
func (s *server) AddAddr(addr string, permanent bool) error {
replyChan := make(chan error)
s.query <- addNodeMsg{addr: addr, permanent: permanent, reply: replyChan}
return <-replyChan
}
func (s *server) RemoveAddr(addr string) error {
replyChan := make(chan error)
s.query <- delNodeMsg{addr: addr, reply: replyChan}
return <-replyChan
}
// Start begins accepting connections from peers. // Start begins accepting connections from peers.
func (s *server) Start() { func (s *server) Start() {
// Already started? // Already started?