diff --git a/config.go b/config.go index 7b5a2556..665683a8 100644 --- a/config.go +++ b/config.go @@ -53,7 +53,7 @@ type config struct { BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"` RPCUser string `short:"u" long:"rpcuser" description:"Username for RPC connections"` RPCPass string `short:"P" long:"rpcpass" default-mask:"-" description:"Password for RPC connections"` - RPCPort string `short:"r" long:"rpcport" description:"Listen for JSON/RPC messages on this port"` + RPCListeners []string `long:"rpclisten" description:"Listen for RPC connections on this interface/port (default no listening. default port: 8334, testnet: 18334)"` DisableRPC bool `long:"norpc" description:"Disable built-in RPC server -- NOTE: The RPC server is disabled by default if no rpcuser/rpcpass is specified"` DisableDNSSeed bool `long:"nodnsseed" description:"Disable DNS seeding for peers"` Proxy string `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"` @@ -147,33 +147,6 @@ func normalizeAddresses(addrs []string, defaultPort string) []string { return removeDuplicateAddresses(addrs) } -// cleanListenAddresses returns a new slice with all the passed peer addresses -// normalized and duplicates removed. -func cleanListenAddresses(addrs []string) []string { - return normalizeAddresses(addrs, activeNetParams.listenPort) -} - -// cleanPeerAddresses returns a new slice with all the passed peer addresses -// normalized and duplicates removed. -func cleanPeerAddresses(addrs []string) []string { - return normalizeAddresses(addrs, activeNetParams.peerPort) -} - -// updateConfigWithActiveParams update the passed config with parameters -// from the active net params if the relevant options in the passed config -// object are the default so options specified by the user on the command line -// are not overridden. -func updateConfigWithActiveParams(cfg *config) { - // Even though there should only be one default, a duplicate might - // have been specified via the config file or CLI options. So, make - // sure to update all default entries rather than only the first one - // found. Duplicates are removed later. - - if cfg.RPCPort == netParams(defaultBtcnet).rpcPort { - cfg.RPCPort = activeNetParams.rpcPort - } -} - // filesExists reports whether the named file or directory exists. func fileExists(name string) bool { if _, err := os.Stat(name); err != nil { @@ -200,7 +173,6 @@ func loadConfig() (*config, []string, error) { // Default config. cfg := config{ DebugLevel: defaultLogLevel, - RPCPort: netParams(defaultBtcnet).rpcPort, MaxPeers: defaultMaxPeers, BanDuration: defaultBanDuration, ConfigFile: defaultConfigFile, @@ -268,7 +240,6 @@ func loadConfig() (*config, []string, error) { } else if cfg.RegressionTest { activeNetParams = netParams(btcwire.TestNet) } - updateConfigWithActiveParams(&cfg) // Validate debug log level. if !validLogLevel(cfg.DebugLevel) { @@ -363,14 +334,28 @@ func loadConfig() (*config, []string, error) { cfg.DisableRPC = true } - // Add default port to all listner addresses if needed and remove + if len(cfg.RPCListeners) == 0 { + cfg.RPCListeners = []string{ + net.JoinHostPort("", activeNetParams.rpcPort), + } + } + + // Add default port to all listener addresses if needed and remove // duplicate addresses. - cfg.Listeners = cleanListenAddresses(cfg.Listeners) + cfg.Listeners = normalizeAddresses(cfg.Listeners, + activeNetParams.listenPort) + + // Add default port to all rpc listener addresses if needed and remove + // duplicate addresses. + cfg.RPCListeners = normalizeAddresses(cfg.RPCListeners, + activeNetParams.rpcPort) // Add default port to all added peer addresses if needed and remove // duplicate addresses. - cfg.AddPeers = cleanPeerAddresses(cfg.AddPeers) - cfg.ConnectPeers = cleanPeerAddresses(cfg.ConnectPeers) + cfg.AddPeers = normalizeAddresses(cfg.AddPeers, + activeNetParams.peerPort) + cfg.ConnectPeers = normalizeAddresses(cfg.ConnectPeers, + activeNetParams.peerPort) return &cfg, remainingArgs, nil } diff --git a/rpcserver.go b/rpcserver.go index 750e844e..5f67da9e 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -44,7 +44,6 @@ type rpcServer struct { server *server ws wsContext wg sync.WaitGroup - rpcport string username string password string listeners []net.Listener @@ -313,13 +312,12 @@ func (s *rpcServer) Stop() error { } // newRPCServer returns a new instance of the rpcServer struct. -func newRPCServer(s *server) (*rpcServer, error) { +func newRPCServer(listenAddrs []string, s *server) (*rpcServer, error) { rpc := rpcServer{ server: s, quit: make(chan int), } // Get values from config - rpc.rpcport = cfg.RPCPort rpc.username = cfg.RPCUser rpc.password = cfg.RPCPass @@ -330,24 +328,33 @@ func newRPCServer(s *server) (*rpcServer, error) { rpc.ws.spentNotifications = make(map[btcwire.OutPoint]*list.List) rpc.ws.minedTxNotifications = make(map[btcwire.ShaHash]*list.List) - // 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 + // TODO(oga) this code is identical to that in server, should be + // factored into something shared. + ipv4ListenAddrs, ipv6ListenAddrs, err := parseListeners(listenAddrs) + listeners := make([]net.Listener, 0, + len(ipv6ListenAddrs)+len(ipv4ListenAddrs)) + for _, addr := range ipv4ListenAddrs { + listener, err := net.Listen("tcp4", addr) + if err != nil { + log.Warnf("RPCS: Can't listen on %s: %v", addr, + err) + continue + } + listeners = append(listeners, 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 + for _, addr := range ipv6ListenAddrs { + listener, err := net.Listen("tcp6", addr) + if err != nil { + log.Warnf("RPCS: Can't listen on %s: %v", addr, + err) + continue + } + listeners = append(listeners, listener) + } + if len(listeners) == 0 { + return nil, errors.New("RPCS: No valid listen address") } - listeners = append(listeners, listener6) rpc.listeners = listeners diff --git a/sample-btcd.conf b/sample-btcd.conf index 07a5bafc..dce3dd3b 100644 --- a/sample-btcd.conf +++ b/sample-btcd.conf @@ -127,7 +127,14 @@ ; norpc=1 ; The port used to listen for RPC connections. -; rpcport=8334 +; rpclisten=:8334 +; +; Listen on a given address on default port. +; rpclisten=1.2.3.4 +; +; Listen on a given address and port. +; rpclisten=1.2.3.4:8335 +; ; ------------------------------------------------------------------------------ diff --git a/server.go b/server.go index 8fbfc384..d1d61d49 100644 --- a/server.go +++ b/server.go @@ -871,7 +871,7 @@ func newServer(listenAddrs []string, db btcdb.Db, btcnet btcwire.BitcoinNet) (*s s.txMemPool = newTxMemPool(&s) if !cfg.DisableRPC { - s.rpcServer, err = newRPCServer(&s) + s.rpcServer, err = newRPCServer(cfg.RPCListeners, &s) if err != nil { return nil, err }