Make IPv4 and IPv6 listen on different sockets.
This commit implements support for listening on multiple sockets and changes the default listen code to use one socket per address family (IPv4 and IPv6). In addition, it changes the default listen binding for the RPC server to localhost so only local clients can connect to it. There need to be several options added to allow customization of these settings and those will be in future commits. Fixes #3.
This commit is contained in:
parent
c526c3af59
commit
ca8496e66d
2 changed files with 70 additions and 38 deletions
|
@ -22,14 +22,14 @@ import (
|
||||||
// rpcServer holds the items the rpc server may need to access (config,
|
// rpcServer holds the items the rpc server may need to access (config,
|
||||||
// shutdown, main server, etc.)
|
// shutdown, main server, etc.)
|
||||||
type rpcServer struct {
|
type rpcServer struct {
|
||||||
started bool
|
started bool
|
||||||
shutdown bool
|
shutdown bool
|
||||||
server *server
|
server *server
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
rpcport string
|
rpcport string
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
listener net.Listener
|
listeners []net.Listener
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start is used by server.go to start the rpc listener.
|
// Start is used by server.go to start the rpc listener.
|
||||||
|
@ -42,14 +42,16 @@ func (s *rpcServer) Start() {
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
jsonRpcRead(w, r, s)
|
jsonRpcRead(w, r, s)
|
||||||
})
|
})
|
||||||
listenAddr := net.JoinHostPort("", s.rpcport)
|
httpServer := &http.Server{}
|
||||||
httpServer := &http.Server{Addr: listenAddr}
|
for _, listener := range s.listeners {
|
||||||
go func() {
|
go func(listener net.Listener) {
|
||||||
log.Infof("[RPCS] RPC server listening on %s", s.listener.Addr())
|
log.Infof("[RPCS] RPC server listening on %s", listener.Addr())
|
||||||
httpServer.Serve(s.listener)
|
httpServer.Serve(listener)
|
||||||
s.wg.Done()
|
log.Tracef("[RPCS] RPC listener done for %s", listener.Addr())
|
||||||
}()
|
s.wg.Done()
|
||||||
s.wg.Add(1)
|
}(listener)
|
||||||
|
s.wg.Add(1)
|
||||||
|
}
|
||||||
s.started = true
|
s.started = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,10 +62,12 @@ func (s *rpcServer) Stop() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
log.Warnf("[RPCS] RPC server shutting down")
|
log.Warnf("[RPCS] RPC server shutting down")
|
||||||
err := s.listener.Close()
|
for _, listener := range s.listeners {
|
||||||
if err != nil {
|
err := listener.Close()
|
||||||
log.Errorf("[RPCS] Problem shutting down rpc: %v", err)
|
if err != nil {
|
||||||
return err
|
log.Errorf("[RPCS] Problem shutting down rpc: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log.Infof("[RPCS] RPC server shutdown complete")
|
log.Infof("[RPCS] RPC server shutdown complete")
|
||||||
s.wg.Wait()
|
s.wg.Wait()
|
||||||
|
@ -81,13 +85,26 @@ func newRpcServer(s *server) (*rpcServer, error) {
|
||||||
rpc.username = cfg.RpcUser
|
rpc.username = cfg.RpcUser
|
||||||
rpc.password = cfg.RpcPass
|
rpc.password = cfg.RpcPass
|
||||||
|
|
||||||
listenAddr := net.JoinHostPort("", rpc.rpcport)
|
// IPv4 listener.
|
||||||
listener, err := net.Listen("tcp", listenAddr)
|
var listeners []net.Listener
|
||||||
|
listenAddr4 := net.JoinHostPort("127.0.0.1", rpc.rpcport)
|
||||||
|
listener4, err := net.Listen("tcp4", listenAddr4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("[RPCS] Couldn't create listener: %v", err)
|
log.Errorf("[RPCS] Couldn't create listener: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
rpc.listener = listener
|
listeners = append(listeners, listener4)
|
||||||
|
|
||||||
|
// IPv6 listener.
|
||||||
|
listenAddr6 := net.JoinHostPort("::1", rpc.rpcport)
|
||||||
|
listener6, err := net.Listen("tcp6", listenAddr6)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("[RPCS] Couldn't create listener: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
listeners = append(listeners, listener6)
|
||||||
|
|
||||||
|
rpc.listeners = listeners
|
||||||
return &rpc, err
|
return &rpc, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ type broadcastMsg struct {
|
||||||
// bitcoin peers.
|
// bitcoin peers.
|
||||||
type server struct {
|
type server struct {
|
||||||
nonce uint64
|
nonce uint64
|
||||||
listener net.Listener
|
listeners []net.Listener
|
||||||
btcnet btcwire.BitcoinNet
|
btcnet btcwire.BitcoinNet
|
||||||
started bool
|
started bool
|
||||||
shutdown bool
|
shutdown bool
|
||||||
|
@ -162,10 +162,10 @@ func (s *server) handleBroadcastMsg(peers *list.List, bmsg *broadcastMsg) {
|
||||||
|
|
||||||
// listenHandler is the main listener which accepts incoming connections for the
|
// listenHandler is the main listener which accepts incoming connections for the
|
||||||
// server. It must be run as a goroutine.
|
// server. It must be run as a goroutine.
|
||||||
func (s *server) listenHandler() {
|
func (s *server) listenHandler(listener net.Listener) {
|
||||||
log.Infof("[SRVR] Server listening on %s", s.listener.Addr())
|
log.Infof("[SRVR] Server listening on %s", listener.Addr())
|
||||||
for !s.shutdown {
|
for !s.shutdown {
|
||||||
conn, err := s.listener.Accept()
|
conn, err := listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Only log the error if we're not forcibly shutting down.
|
// Only log the error if we're not forcibly shutting down.
|
||||||
if !s.shutdown {
|
if !s.shutdown {
|
||||||
|
@ -176,14 +176,14 @@ func (s *server) listenHandler() {
|
||||||
s.AddPeer(newPeer(s, conn, true, false))
|
s.AddPeer(newPeer(s, conn, true, false))
|
||||||
}
|
}
|
||||||
s.wg.Done()
|
s.wg.Done()
|
||||||
log.Tracef("[SRVR] Listener handler done for %s", s.listener.Addr())
|
log.Tracef("[SRVR] Listener handler done for %s", listener.Addr())
|
||||||
}
|
}
|
||||||
|
|
||||||
// peerHandler is used to handle peer operations such as adding and removing
|
// peerHandler is used to handle peer operations such as adding and removing
|
||||||
// peers to and from the server, banning peers, and broadcasting messages to
|
// peers to and from the server, banning peers, and broadcasting messages to
|
||||||
// peers. It must be run a a goroutine.
|
// peers. It must be run a a goroutine.
|
||||||
func (s *server) peerHandler() {
|
func (s *server) peerHandler() {
|
||||||
log.Tracef("[SRVR] Starting peer handler for %s", s.listener.Addr())
|
log.Tracef("[SRVR] Starting peer handler")
|
||||||
peers := list.New()
|
peers := list.New()
|
||||||
bannedPeers := make(map[string]time.Time)
|
bannedPeers := make(map[string]time.Time)
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ func (s *server) peerHandler() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.wg.Done()
|
s.wg.Done()
|
||||||
log.Tracef("[SRVR] Peer handler done on %s", s.listener.Addr())
|
log.Tracef("[SRVR] Peer handler done")
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddPeer adds a new peer that has already been connected to the server.
|
// AddPeer adds a new peer that has already been connected to the server.
|
||||||
|
@ -283,9 +283,12 @@ func (s *server) Start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Trace("[SRVR] Starting server")
|
log.Trace("[SRVR] Starting server")
|
||||||
go s.listenHandler()
|
for _, listener := range s.listeners {
|
||||||
|
go s.listenHandler(listener)
|
||||||
|
s.wg.Add(1)
|
||||||
|
}
|
||||||
go s.peerHandler()
|
go s.peerHandler()
|
||||||
s.wg.Add(2)
|
s.wg.Add(1)
|
||||||
s.addrManager.Start()
|
s.addrManager.Start()
|
||||||
s.blockManager.Start()
|
s.blockManager.Start()
|
||||||
if !cfg.DisableRpc {
|
if !cfg.DisableRpc {
|
||||||
|
@ -305,15 +308,17 @@ func (s *server) Stop() error {
|
||||||
|
|
||||||
log.Warnf("[SRVR] Server shutting down")
|
log.Warnf("[SRVR] Server shutting down")
|
||||||
s.shutdown = true
|
s.shutdown = true
|
||||||
s.quit <- true
|
close(s.quit)
|
||||||
if !cfg.DisableRpc {
|
if !cfg.DisableRpc {
|
||||||
s.rpcServer.Stop()
|
s.rpcServer.Stop()
|
||||||
}
|
}
|
||||||
s.addrManager.Stop()
|
s.addrManager.Stop()
|
||||||
s.blockManager.Stop()
|
s.blockManager.Stop()
|
||||||
err := s.listener.Close()
|
for _, listener := range s.listeners {
|
||||||
if err != nil {
|
err := listener.Close()
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -374,14 +379,24 @@ func newServer(addr string, db btcdb.Db, btcnet btcwire.BitcoinNet) (*server, er
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
listener, err := net.Listen("tcp", addr)
|
// IPv4 listener.
|
||||||
|
var listeners []net.Listener
|
||||||
|
listener4, err := net.Listen("tcp4", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
listeners = append(listeners, listener4)
|
||||||
|
|
||||||
|
// IPv6 listener.
|
||||||
|
listener6, err := net.Listen("tcp6", addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
listeners = append(listeners, listener6)
|
||||||
|
|
||||||
s := server{
|
s := server{
|
||||||
nonce: nonce,
|
nonce: nonce,
|
||||||
listener: listener,
|
listeners: listeners,
|
||||||
btcnet: btcnet,
|
btcnet: btcnet,
|
||||||
addrManager: NewAddrManager(),
|
addrManager: NewAddrManager(),
|
||||||
newPeers: make(chan *peer, cfg.MaxPeers),
|
newPeers: make(chan *peer, cfg.MaxPeers),
|
||||||
|
|
Loading…
Reference in a new issue