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,
|
||||
// shutdown, main server, etc.)
|
||||
type rpcServer struct {
|
||||
started bool
|
||||
shutdown bool
|
||||
server *server
|
||||
wg sync.WaitGroup
|
||||
rpcport string
|
||||
username string
|
||||
password string
|
||||
listener net.Listener
|
||||
started bool
|
||||
shutdown bool
|
||||
server *server
|
||||
wg sync.WaitGroup
|
||||
rpcport string
|
||||
username string
|
||||
password string
|
||||
listeners []net.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) {
|
||||
jsonRpcRead(w, r, s)
|
||||
})
|
||||
listenAddr := net.JoinHostPort("", s.rpcport)
|
||||
httpServer := &http.Server{Addr: listenAddr}
|
||||
go func() {
|
||||
log.Infof("[RPCS] RPC server listening on %s", s.listener.Addr())
|
||||
httpServer.Serve(s.listener)
|
||||
s.wg.Done()
|
||||
}()
|
||||
s.wg.Add(1)
|
||||
httpServer := &http.Server{}
|
||||
for _, listener := range s.listeners {
|
||||
go func(listener net.Listener) {
|
||||
log.Infof("[RPCS] RPC server listening on %s", listener.Addr())
|
||||
httpServer.Serve(listener)
|
||||
log.Tracef("[RPCS] RPC listener done for %s", listener.Addr())
|
||||
s.wg.Done()
|
||||
}(listener)
|
||||
s.wg.Add(1)
|
||||
}
|
||||
s.started = true
|
||||
}
|
||||
|
||||
|
@ -60,10 +62,12 @@ func (s *rpcServer) Stop() error {
|
|||
return nil
|
||||
}
|
||||
log.Warnf("[RPCS] RPC server shutting down")
|
||||
err := s.listener.Close()
|
||||
if err != nil {
|
||||
log.Errorf("[RPCS] Problem shutting down rpc: %v", err)
|
||||
return err
|
||||
for _, listener := range s.listeners {
|
||||
err := listener.Close()
|
||||
if err != nil {
|
||||
log.Errorf("[RPCS] Problem shutting down rpc: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.Infof("[RPCS] RPC server shutdown complete")
|
||||
s.wg.Wait()
|
||||
|
@ -81,13 +85,26 @@ func newRpcServer(s *server) (*rpcServer, error) {
|
|||
rpc.username = cfg.RpcUser
|
||||
rpc.password = cfg.RpcPass
|
||||
|
||||
listenAddr := net.JoinHostPort("", rpc.rpcport)
|
||||
listener, err := net.Listen("tcp", listenAddr)
|
||||
// IPv4 listener.
|
||||
var listeners []net.Listener
|
||||
listenAddr4 := net.JoinHostPort("127.0.0.1", rpc.rpcport)
|
||||
listener4, err := net.Listen("tcp4", listenAddr4)
|
||||
if err != nil {
|
||||
log.Errorf("[RPCS] Couldn't create listener: %v", 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
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ type broadcastMsg struct {
|
|||
// bitcoin peers.
|
||||
type server struct {
|
||||
nonce uint64
|
||||
listener net.Listener
|
||||
listeners []net.Listener
|
||||
btcnet btcwire.BitcoinNet
|
||||
started 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
|
||||
// server. It must be run as a goroutine.
|
||||
func (s *server) listenHandler() {
|
||||
log.Infof("[SRVR] Server listening on %s", s.listener.Addr())
|
||||
func (s *server) listenHandler(listener net.Listener) {
|
||||
log.Infof("[SRVR] Server listening on %s", listener.Addr())
|
||||
for !s.shutdown {
|
||||
conn, err := s.listener.Accept()
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
// Only log the error if we're not forcibly shutting down.
|
||||
if !s.shutdown {
|
||||
|
@ -176,14 +176,14 @@ func (s *server) listenHandler() {
|
|||
s.AddPeer(newPeer(s, conn, true, false))
|
||||
}
|
||||
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
|
||||
// peers to and from the server, banning peers, and broadcasting messages to
|
||||
// peers. It must be run a a goroutine.
|
||||
func (s *server) peerHandler() {
|
||||
log.Tracef("[SRVR] Starting peer handler for %s", s.listener.Addr())
|
||||
log.Tracef("[SRVR] Starting peer handler")
|
||||
peers := list.New()
|
||||
bannedPeers := make(map[string]time.Time)
|
||||
|
||||
|
@ -218,7 +218,7 @@ func (s *server) peerHandler() {
|
|||
}
|
||||
}
|
||||
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.
|
||||
|
@ -283,9 +283,12 @@ func (s *server) Start() {
|
|||
}
|
||||
|
||||
log.Trace("[SRVR] Starting server")
|
||||
go s.listenHandler()
|
||||
for _, listener := range s.listeners {
|
||||
go s.listenHandler(listener)
|
||||
s.wg.Add(1)
|
||||
}
|
||||
go s.peerHandler()
|
||||
s.wg.Add(2)
|
||||
s.wg.Add(1)
|
||||
s.addrManager.Start()
|
||||
s.blockManager.Start()
|
||||
if !cfg.DisableRpc {
|
||||
|
@ -305,15 +308,17 @@ func (s *server) Stop() error {
|
|||
|
||||
log.Warnf("[SRVR] Server shutting down")
|
||||
s.shutdown = true
|
||||
s.quit <- true
|
||||
close(s.quit)
|
||||
if !cfg.DisableRpc {
|
||||
s.rpcServer.Stop()
|
||||
}
|
||||
s.addrManager.Stop()
|
||||
s.blockManager.Stop()
|
||||
err := s.listener.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
for _, listener := range s.listeners {
|
||||
err := listener.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -374,14 +379,24 @@ func newServer(addr string, db btcdb.Db, btcnet btcwire.BitcoinNet) (*server, er
|
|||
return nil, err
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", addr)
|
||||
// IPv4 listener.
|
||||
var listeners []net.Listener
|
||||
listener4, err := net.Listen("tcp4", addr)
|
||||
if err != nil {
|
||||
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{
|
||||
nonce: nonce,
|
||||
listener: listener,
|
||||
listeners: listeners,
|
||||
btcnet: btcnet,
|
||||
addrManager: NewAddrManager(),
|
||||
newPeers: make(chan *peer, cfg.MaxPeers),
|
||||
|
|
Loading…
Reference in a new issue