From 0a8cb9c68cd711b83597ec65da2042b61ffe70b0 Mon Sep 17 00:00:00 2001 From: ziggie Date: Mon, 30 Sep 2024 15:23:50 +0200 Subject: [PATCH] rpcclient: add timeout for http request. --- rpcclient/infrastructure.go | 135 +++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 65 deletions(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 891b517195..4fe1d894df 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -92,6 +92,10 @@ const ( // requestRetryInterval is the initial amount of time to wait in between // retries when sending HTTP POST requests. requestRetryInterval = time.Millisecond * 500 + + // defaultHTTPTimeout is the default timeout for an http request, so the + // request does not block indefinitely. + defaultHTTPTimeout = time.Minute ) // jsonRequest holds information about a json request that is used to properly @@ -775,7 +779,7 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest) { } var url string - switch parsedAddr.Network(){ + switch parsedAddr.Network() { case "unix", "unixpacket": // Using a placeholder URL because a non-empty URL is required. // The Unix domain socket is specified in the DialContext. @@ -1363,6 +1367,7 @@ func newHTTPClient(config *ConnConfig) (*http.Client, error) { return net.Dial(parsedAddr.Network(), parsedAddr.String()) }, }, + Timeout: defaultHTTPTimeout, } return &client, nil @@ -1733,74 +1738,74 @@ func (c *Client) Send() error { // connections. We accept a custom function to resolve any TCP addresses so // that caller is able control exactly how resolution is performed. func ParseAddressString(strAddress string) (net.Addr, error) { - var parsedNetwork, parsedAddr string - - // Addresses can either be in network://address:port format, - // network:address:port, address:port, or just port. We want to support - // all possible types. - if strings.Contains(strAddress, "://") { - parts := strings.Split(strAddress, "://") - parsedNetwork, parsedAddr = parts[0], parts[1] - } else if strings.Contains(strAddress, ":") { - parts := strings.Split(strAddress, ":") - parsedNetwork = parts[0] - parsedAddr = strings.Join(parts[1:], ":") - } else { - parsedAddr = strAddress - } - - // Only TCP and Unix socket addresses are valid. We can't use IP or - // UDP only connections for anything we do in lnd. - switch parsedNetwork { - case "unix", "unixpacket": - return net.ResolveUnixAddr(parsedNetwork, parsedAddr) - - case "tcp", "tcp4", "tcp6": - return net.ResolveTCPAddr(parsedNetwork, verifyPort(parsedAddr)) - - case "ip", "ip4", "ip6", "udp", "udp4", "udp6", "unixgram": - return nil, fmt.Errorf("only TCP or unix socket "+ - "addresses are supported: %s", parsedAddr) - - default: - // We'll now possibly use the local host short circuit - // or parse out an all interfaces listen. - addrWithPort := verifyPort(strAddress) - - // Otherwise, we'll attempt to resolve the host. - return net.ResolveTCPAddr("tcp", addrWithPort) - } + var parsedNetwork, parsedAddr string + + // Addresses can either be in network://address:port format, + // network:address:port, address:port, or just port. We want to support + // all possible types. + if strings.Contains(strAddress, "://") { + parts := strings.Split(strAddress, "://") + parsedNetwork, parsedAddr = parts[0], parts[1] + } else if strings.Contains(strAddress, ":") { + parts := strings.Split(strAddress, ":") + parsedNetwork = parts[0] + parsedAddr = strings.Join(parts[1:], ":") + } else { + parsedAddr = strAddress + } + + // Only TCP and Unix socket addresses are valid. We can't use IP or + // UDP only connections for anything we do in lnd. + switch parsedNetwork { + case "unix", "unixpacket": + return net.ResolveUnixAddr(parsedNetwork, parsedAddr) + + case "tcp", "tcp4", "tcp6": + return net.ResolveTCPAddr(parsedNetwork, verifyPort(parsedAddr)) + + case "ip", "ip4", "ip6", "udp", "udp4", "udp6", "unixgram": + return nil, fmt.Errorf("only TCP or unix socket "+ + "addresses are supported: %s", parsedAddr) + + default: + // We'll now possibly use the local host short circuit + // or parse out an all interfaces listen. + addrWithPort := verifyPort(strAddress) + + // Otherwise, we'll attempt to resolve the host. + return net.ResolveTCPAddr("tcp", addrWithPort) + } } // verifyPort makes sure that an address string has both a host and a port. // If the address is just a port, then we'll assume that the user is using the // short cut to specify a localhost:port address. func verifyPort(address string) string { - host, port, err := net.SplitHostPort(address) - if err != nil { - // If the address itself is just an integer, then we'll assume - // that we're mapping this directly to a localhost:port pair. - // This ensures we maintain the legacy behavior. - if _, err := strconv.Atoi(address); err == nil { - return net.JoinHostPort("localhost", address) - } - - // Otherwise, we'll assume that the address just failed to - // attach its own port, so we'll leave it as is. In the - // case of IPv6 addresses, if the host is already surrounded by - // brackets, then we'll avoid using the JoinHostPort function, - // since it will always add a pair of brackets. - if strings.HasPrefix(address, "[") { - return address - } - return net.JoinHostPort(address, "") - } - - // In the case that both the host and port are empty, we'll use the - // an empty port. - if host == "" && port == "" { - return ":" - } - - return address + host, port, err := net.SplitHostPort(address) + if err != nil { + // If the address itself is just an integer, then we'll assume + // that we're mapping this directly to a localhost:port pair. + // This ensures we maintain the legacy behavior. + if _, err := strconv.Atoi(address); err == nil { + return net.JoinHostPort("localhost", address) + } + + // Otherwise, we'll assume that the address just failed to + // attach its own port, so we'll leave it as is. In the + // case of IPv6 addresses, if the host is already surrounded by + // brackets, then we'll avoid using the JoinHostPort function, + // since it will always add a pair of brackets. + if strings.HasPrefix(address, "[") { + return address + } + return net.JoinHostPort(address, "") + } + + // In the case that both the host and port are empty, we'll use the + // an empty port. + if host == "" && port == "" { + return ":" + } + + return address }