diff --git a/connmgr/tor.go b/connmgr/tor.go index ddd2c4af9..bc73a9541 100644 --- a/connmgr/tor.go +++ b/connmgr/tor.go @@ -102,7 +102,7 @@ func TorLookupIP(host, proxy string) ([]net.IP, error) { if int(buf[1]) > len(torStatusErrors) { err = ErrTorInvalidProxyResponse } else { - err := torStatusErrors[buf[1]] + err = torStatusErrors[buf[1]] if err == nil { err = ErrTorInvalidProxyResponse } diff --git a/rpcserver.go b/rpcserver.go index 3f9868b53..2615bd6d1 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -919,18 +919,24 @@ func handleGetAddedNodeInfo(s *rpcServer, cmd interface{}, closeChan <-chan stru host = peer.Addr() } - // Do a DNS lookup for the address. If the lookup fails, just - // use the host. var ipList []string - ips, err := btcdLookup(host) - if err == nil { + switch { + case net.ParseIP(host) != nil, strings.HasSuffix(host, ".onion"): + ipList = make([]string, 1) + ipList[0] = host + default: + // Do a DNS lookup for the address. If the lookup fails, just + // use the host. + ips, err := btcdLookup(host) + if err != nil { + ipList = make([]string, 1) + ipList[0] = host + break + } ipList = make([]string, 0, len(ips)) for _, ip := range ips { ipList = append(ipList, ip.String()) } - } else { - ipList = make([]string, 1) - ipList[0] = host } // Add the addresses and connection info to the result. diff --git a/server.go b/server.go index 352233fb0..1bed7e264 100644 --- a/server.go +++ b/server.go @@ -65,6 +65,28 @@ var ( userAgentVersion = fmt.Sprintf("%d.%d.%d", appMajor, appMinor, appPatch) ) +// onionAddr implements the net.Addr interface and represents a tor address. +type onionAddr struct { + addr string +} + +// String returns the onion address. +// +// This is part of the net.Addr interface. +func (oa *onionAddr) String() string { + return oa.addr +} + +// Network returns "onion". +// +// This is part of the net.Addr interface. +func (oa *onionAddr) Network() string { + return "onion" +} + +// Ensure onionAddr implements the net.Addr interface. +var _ net.Addr = (*onionAddr)(nil) + // broadcastMsg provides the ability to house a bitcoin message to be broadcast // to all connected peers except specified excluded peers. type broadcastMsg struct { @@ -2469,13 +2491,13 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param permanentPeers = cfg.AddPeers } for _, addr := range permanentPeers { - tcpAddr, err := addrStringToNetAddr(addr) + netAddr, err := addrStringToNetAddr(addr) if err != nil { return nil, err } go s.connManager.Connect(&connmgr.ConnReq{ - Addr: tcpAddr, + Addr: netAddr, Permanent: true, }) } @@ -2499,16 +2521,38 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param // addrStringToNetAddr takes an address in the form of 'host:port' and returns // a net.Addr which maps to the original address with any host names resolved -// to IP addresses. +// to IP addresses. It also handles tor addresses properly by returning a +// net.Addr that encapsulates the address. func addrStringToNetAddr(addr string) (net.Addr, error) { host, strPort, err := net.SplitHostPort(addr) if err != nil { return nil, err } + port, err := strconv.Atoi(strPort) + if err != nil { + return nil, err + } + + // Skip if host is already an IP address. + if ip := net.ParseIP(host); ip != nil { + return &net.TCPAddr{ + IP: ip, + Port: port, + }, nil + } + + // Tor addresses cannot be resolved to an IP, so just return an onion + // address instead. + if strings.HasSuffix(host, ".onion") { + if cfg.NoOnion { + return nil, errors.New("tor has been disabled") + } + + return &onionAddr{addr: addr}, nil + } + // Attempt to look up an IP address associated with the parsed host. - // The btcdLookup function will transparently handle performing the - // lookup over Tor if necessary. ips, err := btcdLookup(host) if err != nil { return nil, err @@ -2517,11 +2561,6 @@ func addrStringToNetAddr(addr string) (net.Addr, error) { return nil, fmt.Errorf("no addresses found for %s", host) } - port, err := strconv.Atoi(strPort) - if err != nil { - return nil, err - } - return &net.TCPAddr{ IP: ips[0], Port: port,