From 764c958c52edb427f39530f53623e85d34409904 Mon Sep 17 00:00:00 2001 From: Emil Engler Date: Mon, 8 Aug 2022 23:58:20 +0200 Subject: [PATCH] refactor: split resolve_server() into functions This commit splits the branch-heavy resolve_server() function into various sub-functions, in order to reduce the amount of nested if/else-statements. Beside this, it also removes many else-sequences, by returning in the previous if-statement. Closes #9283 --- lib/url.c | 266 +++++++++++++++++++++++++++++------------------------- 1 file changed, 145 insertions(+), 121 deletions(-) diff --git a/lib/url.c b/lib/url.c index a57c8da9f..14a920078 100644 --- a/lib/url.c +++ b/lib/url.c @@ -3414,6 +3414,146 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, return result; } +#ifdef USE_UNIX_SOCKETS +static CURLcode resolve_unix(struct Curl_easy *data, + struct connectdata *conn, + char *unix_path) +{ + struct Curl_dns_entry *hostaddr = NULL; + bool longpath = FALSE; + + DEBUGASSERT(unix_path); + DEBUGASSERT(conn->dns_entry == NULL); + + /* Unix domain sockets are local. The host gets ignored, just use the + * specified domain socket address. Do not cache "DNS entries". There is + * no DNS involved and we already have the filesystem path available. */ + hostaddr = calloc(1, sizeof(struct Curl_dns_entry)); + if(!hostaddr) + return CURLE_OUT_OF_MEMORY; + + hostaddr->addr = Curl_unix2addr(unix_path, &longpath, + conn->bits.abstract_unix_socket); + if(!hostaddr->addr) { + if(longpath) + /* Long paths are not supported for now */ + failf(data, "Unix socket path too long: '%s'", unix_path); + free(hostaddr); + return longpath ? CURLE_COULDNT_RESOLVE_HOST : CURLE_OUT_OF_MEMORY; + } + + hostaddr->inuse++; + conn->dns_entry = hostaddr; + return CURLE_OK; +} +#endif + +#ifndef CURL_DISABLE_PROXY +static CURLcode resolve_proxy(struct Curl_easy *data, + struct connectdata *conn, + bool *async) +{ + struct Curl_dns_entry *hostaddr = NULL; + struct hostname *host; + timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); + int rc; + + DEBUGASSERT(conn->dns_entry == NULL); + + host = conn->bits.socksproxy ? &conn->socks_proxy.host : + &conn->http_proxy.host; + + conn->hostname_resolve = strdup(host->name); + if(!conn->hostname_resolve) + return CURLE_OUT_OF_MEMORY; + + rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port, + &hostaddr, timeout_ms); + conn->dns_entry = hostaddr; + if(rc == CURLRESOLV_PENDING) + *async = TRUE; + else if(rc == CURLRESOLV_TIMEDOUT) + return CURLE_OPERATION_TIMEDOUT; + else if(!hostaddr) { + failf(data, "Couldn't resolve proxy '%s'", host->dispname); + return CURLE_COULDNT_RESOLVE_PROXY; + } + + return CURLE_OK; +} +#endif + +static CURLcode resolve_ip(struct Curl_easy *data, + struct connectdata *conn, + bool *async) +{ + struct Curl_dns_entry *hostaddr = NULL; + struct hostname *connhost; + timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); + int rc; + + DEBUGASSERT(conn->dns_entry == NULL); + + connhost = conn->bits.conn_to_host ? &conn->conn_to_host : &conn->host; + + /* If not connecting via a proxy, extract the port from the URL, if it is + * there, thus overriding any defaults that might have been set above. */ + conn->port = conn->bits.conn_to_port ? conn->conn_to_port : + conn->remote_port; + + /* Resolve target host right on */ + conn->hostname_resolve = strdup(connhost->name); + if(!conn->hostname_resolve) + return CURLE_OUT_OF_MEMORY; + + rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port, + &hostaddr, timeout_ms); + conn->dns_entry = hostaddr; + if(rc == CURLRESOLV_PENDING) + *async = TRUE; + else if(rc == CURLRESOLV_TIMEDOUT) { + failf(data, "Failed to resolve host '%s' with timeout after %ld ms", + connhost->dispname, + Curl_timediff(Curl_now(), data->progress.t_startsingle)); + return CURLE_OPERATION_TIMEDOUT; + } + else if(!hostaddr) { + failf(data, "Could not resolve host: %s", connhost->dispname); + return CURLE_COULDNT_RESOLVE_HOST; + } + + return CURLE_OK; +} + +/* Perform a fresh resolve */ +static CURLcode resolve_fresh(struct Curl_easy *data, + struct connectdata *conn, + bool *async) +{ +#ifdef USE_UNIX_SOCKETS + char *unix_path = conn->unix_domain_socket; + +#ifndef CURL_DISABLE_PROXY + if(!unix_path && conn->socks_proxy.host.name && + !strncmp(UNIX_SOCKET_PREFIX"/", + conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX))) + unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1; +#endif + + if(unix_path) { + conn->transport = TRNSPRT_UNIX; + return resolve_unix(data, conn, unix_path); + } +#endif + +#ifndef CURL_DISABLE_PROXY + if(CONN_IS_PROXIED(conn)) + return resolve_proxy(data, conn, async); +#endif + + return resolve_ip(data, conn, async); +} + /************************************************************* * Resolve the address of the server or proxy *************************************************************/ @@ -3421,135 +3561,19 @@ static CURLcode resolve_server(struct Curl_easy *data, struct connectdata *conn, bool *async) { - CURLcode result = CURLE_OK; - timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); - DEBUGASSERT(conn); DEBUGASSERT(data); - /************************************************************* - * Resolve the name of the server or proxy - *************************************************************/ - if(conn->bits.reuse) + + /* Resolve the name of the server or proxy */ + if(conn->bits.reuse) { /* We're reusing the connection - no need to resolve anything, and idnconvert_hostname() was called already in create_conn() for the re-use case. */ *async = FALSE; - - else { - /* this is a fresh connect */ - int rc; - struct Curl_dns_entry *hostaddr = NULL; - -#ifdef USE_UNIX_SOCKETS - char *unix_path = NULL; - - if(conn->unix_domain_socket) - unix_path = conn->unix_domain_socket; -#ifndef CURL_DISABLE_PROXY - else if(conn->socks_proxy.host.name - && !strncmp(UNIX_SOCKET_PREFIX"/", - conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX))) - unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1; -#endif - - if(unix_path) { - /* Unix domain sockets are local. The host gets ignored, just use the - * specified domain socket address. Do not cache "DNS entries". There is - * no DNS involved and we already have the filesystem path available */ - - hostaddr = calloc(1, sizeof(struct Curl_dns_entry)); - if(!hostaddr) - result = CURLE_OUT_OF_MEMORY; - else { - bool longpath = FALSE; - hostaddr->addr = Curl_unix2addr(unix_path, &longpath, - conn->bits.abstract_unix_socket); - if(hostaddr->addr) - hostaddr->inuse++; - else { - /* Long paths are not supported for now */ - if(longpath) { - failf(data, "Unix socket path too long: '%s'", unix_path); - result = CURLE_COULDNT_RESOLVE_HOST; - } - else - result = CURLE_OUT_OF_MEMORY; - free(hostaddr); - hostaddr = NULL; - } - conn->transport = TRNSPRT_UNIX; - } - } - else -#endif - - if(!CONN_IS_PROXIED(conn)) { - struct hostname *connhost; - if(conn->bits.conn_to_host) - connhost = &conn->conn_to_host; - else - connhost = &conn->host; - - /* If not connecting via a proxy, extract the port from the URL, if it is - * there, thus overriding any defaults that might have been set above. */ - if(conn->bits.conn_to_port) - conn->port = conn->conn_to_port; - else - conn->port = conn->remote_port; - - /* Resolve target host right on */ - conn->hostname_resolve = strdup(connhost->name); - if(!conn->hostname_resolve) - return CURLE_OUT_OF_MEMORY; - rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port, - &hostaddr, timeout_ms); - if(rc == CURLRESOLV_PENDING) - *async = TRUE; - - else if(rc == CURLRESOLV_TIMEDOUT) { - failf(data, "Failed to resolve host '%s' with timeout after %ld ms", - connhost->dispname, - Curl_timediff(Curl_now(), data->progress.t_startsingle)); - result = CURLE_OPERATION_TIMEDOUT; - } - else if(!hostaddr) { - failf(data, "Could not resolve host: %s", connhost->dispname); - result = CURLE_COULDNT_RESOLVE_HOST; - /* don't return yet, we need to clean up the timeout first */ - } - } -#ifndef CURL_DISABLE_PROXY - else { - /* This is a proxy that hasn't been resolved yet. */ - - struct hostname * const host = conn->bits.socksproxy ? - &conn->socks_proxy.host : &conn->http_proxy.host; - - /* resolve proxy */ - conn->hostname_resolve = strdup(host->name); - if(!conn->hostname_resolve) - return CURLE_OUT_OF_MEMORY; - rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port, - &hostaddr, timeout_ms); - - if(rc == CURLRESOLV_PENDING) - *async = TRUE; - - else if(rc == CURLRESOLV_TIMEDOUT) - result = CURLE_OPERATION_TIMEDOUT; - - else if(!hostaddr) { - failf(data, "Couldn't resolve proxy '%s'", host->dispname); - result = CURLE_COULDNT_RESOLVE_PROXY; - /* don't return yet, we need to clean up the timeout first */ - } - } -#endif - DEBUGASSERT(conn->dns_entry == NULL); - conn->dns_entry = hostaddr; + return CURLE_OK; } - return result; + return resolve_fresh(data, conn, async); } /*