From da2901a4fd0aa5ca055adbede1414d6692b8f5d8 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Tue, 29 Oct 2013 17:18:53 +0000 Subject: [PATCH] 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. --- rpcserver.go | 25 ++++++++++++++++++++- server.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/rpcserver.go b/rpcserver.go index 9204000b..8d98ca28 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -311,6 +311,7 @@ func jsonRPCRead(w http.ResponseWriter, r *http.Request, s *rpcServer) { type commandHandler func(*rpcServer, btcjson.Cmd, chan []byte) (interface{}, error) var handlers = map[string]commandHandler{ + "addnode": handleAddNode, "decoderawtransaction": handleDecodeRawTransaction, "getbestblockhash": handleGetBestBlockHash, "getblock": handleGetBlock, @@ -328,6 +329,28 @@ var handlers = map[string]commandHandler{ "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. func handleDecodeRawTransaction(s *rpcServer, cmd btcjson.Cmd, walletNotification chan []byte) (interface{}, error) { @@ -469,7 +492,7 @@ func handleGetHashesPerSec(s *rpcServer, cmd btcjson.Cmd, walletNotification cha // handleGetPeerInfo implements the getpeerinfo command. 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. diff --git a/server.go b/server.go index 83aad7e3..df95f337 100644 --- a/server.go +++ b/server.go @@ -6,6 +6,7 @@ package main import ( "container/list" + "errors" "fmt" "github.com/conformal/btcdb" "github.com/conformal/btcwire" @@ -223,6 +224,16 @@ type getPeerInfoMsg struct { 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) { switch msg := querymsg.(type) { @@ -265,6 +276,41 @@ func (s *server) handleQuery(querymsg interface{}, peers *list.List, bannedPeers infos = append(infos, info) } 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 } +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. func (s *server) Start() { // Already started?