quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

url.c (124164B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 
     25 #include "curl_setup.h"
     26 
     27 #ifdef HAVE_NETINET_IN_H
     28 #include <netinet/in.h>
     29 #endif
     30 #ifdef HAVE_NETDB_H
     31 #include <netdb.h>
     32 #endif
     33 #ifdef HAVE_ARPA_INET_H
     34 #include <arpa/inet.h>
     35 #endif
     36 #ifdef HAVE_NET_IF_H
     37 #include <net/if.h>
     38 #endif
     39 #ifdef HAVE_IPHLPAPI_H
     40 #include <Iphlpapi.h>
     41 #endif
     42 #ifdef HAVE_SYS_IOCTL_H
     43 #include <sys/ioctl.h>
     44 #endif
     45 #ifdef HAVE_SYS_PARAM_H
     46 #include <sys/param.h>
     47 #endif
     48 
     49 #ifdef __VMS
     50 #include <in.h>
     51 #include <inet.h>
     52 #endif
     53 
     54 #ifdef HAVE_SYS_UN_H
     55 #include <sys/un.h>
     56 #endif
     57 
     58 #ifndef HAVE_SOCKET
     59 #error "We cannot compile without socket() support!"
     60 #endif
     61 
     62 #if defined(HAVE_IF_NAMETOINDEX) && defined(_WIN32)
     63 #include <iphlpapi.h>
     64 #endif
     65 
     66 #include <limits.h>
     67 
     68 #include "doh.h"
     69 #include "urldata.h"
     70 #include "netrc.h"
     71 #include "formdata.h"
     72 #include "mime.h"
     73 #include "vtls/vtls.h"
     74 #include "hostip.h"
     75 #include "transfer.h"
     76 #include "sendf.h"
     77 #include "progress.h"
     78 #include "cookie.h"
     79 #include "strcase.h"
     80 #include "strerror.h"
     81 #include "escape.h"
     82 #include "share.h"
     83 #include "content_encoding.h"
     84 #include "http_digest.h"
     85 #include "http_negotiate.h"
     86 #include "select.h"
     87 #include "multiif.h"
     88 #include "easyif.h"
     89 #include "speedcheck.h"
     90 #include "curlx/warnless.h"
     91 #include "getinfo.h"
     92 #include "pop3.h"
     93 #include "urlapi-int.h"
     94 #include "system_win32.h"
     95 #include "hsts.h"
     96 #include "noproxy.h"
     97 #include "cfilters.h"
     98 #include "curl_krb5.h"
     99 #include "idn.h"
    100 
    101 /* And now for the protocols */
    102 #include "ftp.h"
    103 #include "dict.h"
    104 #include "telnet.h"
    105 #include "tftp.h"
    106 #include "http.h"
    107 #include "http2.h"
    108 #include "file.h"
    109 #include "curl_ldap.h"
    110 #include "vssh/ssh.h"
    111 #include "imap.h"
    112 #include "url.h"
    113 #include "connect.h"
    114 #include "http_ntlm.h"
    115 #include "curl_rtmp.h"
    116 #include "gopher.h"
    117 #include "mqtt.h"
    118 #include "http_proxy.h"
    119 #include "conncache.h"
    120 #include "multihandle.h"
    121 #include "strdup.h"
    122 #include "setopt.h"
    123 #include "altsvc.h"
    124 #include "curlx/dynbuf.h"
    125 #include "headers.h"
    126 #include "curlx/strparse.h"
    127 /* The last 3 #include files should be in this order */
    128 #include "curl_printf.h"
    129 #include "curl_memory.h"
    130 #include "memdebug.h"
    131 
    132 #ifdef USE_NGHTTP2
    133 static void data_priority_cleanup(struct Curl_easy *data);
    134 #else
    135 #define data_priority_cleanup(x)
    136 #endif
    137 
    138 /* Some parts of the code (e.g. chunked encoding) assume this buffer has at
    139  * more than just a few bytes to play with. Do not let it become too small or
    140  * bad things will happen.
    141  */
    142 #if READBUFFER_SIZE < READBUFFER_MIN
    143 # error READBUFFER_SIZE is too small
    144 #endif
    145 
    146 #ifdef USE_UNIX_SOCKETS
    147 #define UNIX_SOCKET_PREFIX "localhost"
    148 #endif
    149 
    150 /* Reject URLs exceeding this length */
    151 #define MAX_URL_LEN 0xffff
    152 
    153 /*
    154 * get_protocol_family()
    155 *
    156 * This is used to return the protocol family for a given protocol.
    157 *
    158 * Parameters:
    159 *
    160 * 'h'  [in]  - struct Curl_handler pointer.
    161 *
    162 * Returns the family as a single bit protocol identifier.
    163 */
    164 static curl_prot_t get_protocol_family(const struct Curl_handler *h)
    165 {
    166   DEBUGASSERT(h);
    167   DEBUGASSERT(h->family);
    168   return h->family;
    169 }
    170 
    171 void Curl_freeset(struct Curl_easy *data)
    172 {
    173   /* Free all dynamic strings stored in the data->set substructure. */
    174   enum dupstring i;
    175   enum dupblob j;
    176 
    177   for(i = (enum dupstring)0; i < STRING_LAST; i++) {
    178     Curl_safefree(data->set.str[i]);
    179   }
    180 
    181   for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
    182     Curl_safefree(data->set.blobs[j]);
    183   }
    184 
    185   if(data->state.referer_alloc) {
    186     Curl_safefree(data->state.referer);
    187     data->state.referer_alloc = FALSE;
    188   }
    189   data->state.referer = NULL;
    190   if(data->state.url_alloc) {
    191     Curl_safefree(data->state.url);
    192     data->state.url_alloc = FALSE;
    193   }
    194   data->state.url = NULL;
    195 
    196   Curl_mime_cleanpart(&data->set.mimepost);
    197 
    198 #ifndef CURL_DISABLE_COOKIES
    199   curl_slist_free_all(data->state.cookielist);
    200   data->state.cookielist = NULL;
    201 #endif
    202 }
    203 
    204 /* free the URL pieces */
    205 static void up_free(struct Curl_easy *data)
    206 {
    207   struct urlpieces *up = &data->state.up;
    208   Curl_safefree(up->scheme);
    209   Curl_safefree(up->hostname);
    210   Curl_safefree(up->port);
    211   Curl_safefree(up->user);
    212   Curl_safefree(up->password);
    213   Curl_safefree(up->options);
    214   Curl_safefree(up->path);
    215   Curl_safefree(up->query);
    216   curl_url_cleanup(data->state.uh);
    217   data->state.uh = NULL;
    218 }
    219 
    220 /*
    221  * This is the internal function curl_easy_cleanup() calls. This should
    222  * cleanup and free all resources associated with this sessionhandle.
    223  *
    224  * We ignore SIGPIPE when this is called from curl_easy_cleanup.
    225  */
    226 
    227 CURLcode Curl_close(struct Curl_easy **datap)
    228 {
    229   struct Curl_easy *data;
    230 
    231   if(!datap || !*datap)
    232     return CURLE_OK;
    233 
    234   data = *datap;
    235   *datap = NULL;
    236 
    237   if(!data->state.internal && data->multi) {
    238     /* This handle is still part of a multi handle, take care of this first
    239        and detach this handle from there.
    240        This detaches the connection. */
    241     curl_multi_remove_handle(data->multi, data);
    242   }
    243   else {
    244     /* Detach connection if any is left. This should not be normal, but can be
    245        the case for example with CONNECT_ONLY + recv/send (test 556) */
    246     Curl_detach_connection(data);
    247     if(!data->state.internal && data->multi_easy) {
    248       /* when curl_easy_perform() is used, it creates its own multi handle to
    249          use and this is the one */
    250       curl_multi_cleanup(data->multi_easy);
    251       data->multi_easy = NULL;
    252     }
    253   }
    254   DEBUGASSERT(!data->conn || data->state.internal);
    255 
    256   Curl_expire_clear(data); /* shut off any timers left */
    257 
    258   data->magic = 0; /* force a clear AFTER the possibly enforced removal from
    259                       the multi handle, since that function uses the magic
    260                       field! */
    261 
    262   if(data->state.rangestringalloc)
    263     free(data->state.range);
    264 
    265   /* freed here just in case DONE was not called */
    266   Curl_req_free(&data->req, data);
    267 
    268   /* Close down all open SSL info and sessions */
    269   Curl_ssl_close_all(data);
    270   Curl_safefree(data->state.first_host);
    271   Curl_ssl_free_certinfo(data);
    272 
    273   if(data->state.referer_alloc) {
    274     Curl_safefree(data->state.referer);
    275     data->state.referer_alloc = FALSE;
    276   }
    277   data->state.referer = NULL;
    278 
    279   up_free(data);
    280   curlx_dyn_free(&data->state.headerb);
    281   Curl_flush_cookies(data, TRUE);
    282 #ifndef CURL_DISABLE_ALTSVC
    283   Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]);
    284   Curl_altsvc_cleanup(&data->asi);
    285 #endif
    286 #ifndef CURL_DISABLE_HSTS
    287   Curl_hsts_save(data, data->hsts, data->set.str[STRING_HSTS]);
    288   if(!data->share || !data->share->hsts)
    289     Curl_hsts_cleanup(&data->hsts);
    290   curl_slist_free_all(data->state.hstslist); /* clean up list */
    291 #endif
    292 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
    293   Curl_http_auth_cleanup_digest(data);
    294 #endif
    295   Curl_safefree(data->state.most_recent_ftp_entrypath);
    296   Curl_safefree(data->info.contenttype);
    297   Curl_safefree(data->info.wouldredirect);
    298 
    299   /* release any resolve information this transfer kept */
    300   Curl_async_destroy(data);
    301   Curl_resolv_unlink(data, &data->state.dns[0]); /* done with this */
    302   Curl_resolv_unlink(data, &data->state.dns[1]);
    303 
    304   data_priority_cleanup(data);
    305 
    306   /* No longer a dirty share, if it exists */
    307   if(data->share) {
    308     Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
    309     data->share->dirty--;
    310     Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
    311   }
    312 
    313   Curl_hash_destroy(&data->meta_hash);
    314 #ifndef CURL_DISABLE_PROXY
    315   Curl_safefree(data->state.aptr.proxyuserpwd);
    316 #endif
    317   Curl_safefree(data->state.aptr.uagent);
    318   Curl_safefree(data->state.aptr.userpwd);
    319   Curl_safefree(data->state.aptr.accept_encoding);
    320   Curl_safefree(data->state.aptr.te);
    321   Curl_safefree(data->state.aptr.rangeline);
    322   Curl_safefree(data->state.aptr.ref);
    323   Curl_safefree(data->state.aptr.host);
    324 #ifndef CURL_DISABLE_COOKIES
    325   Curl_safefree(data->state.aptr.cookiehost);
    326 #endif
    327 #ifndef CURL_DISABLE_RTSP
    328   Curl_safefree(data->state.aptr.rtsp_transport);
    329 #endif
    330   Curl_safefree(data->state.aptr.user);
    331   Curl_safefree(data->state.aptr.passwd);
    332 #ifndef CURL_DISABLE_PROXY
    333   Curl_safefree(data->state.aptr.proxyuser);
    334   Curl_safefree(data->state.aptr.proxypasswd);
    335 #endif
    336 
    337 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_FORM_API)
    338   Curl_mime_cleanpart(data->state.formp);
    339   Curl_safefree(data->state.formp);
    340 #endif
    341 
    342   /* destruct wildcard structures if it is needed */
    343   Curl_wildcard_dtor(&data->wildcard);
    344   Curl_freeset(data);
    345   Curl_headers_cleanup(data);
    346   Curl_netrc_cleanup(&data->state.netrc);
    347   free(data);
    348   return CURLE_OK;
    349 }
    350 
    351 /*
    352  * Initialize the UserDefined fields within a Curl_easy.
    353  * This may be safely called on a new or existing Curl_easy.
    354  */
    355 CURLcode Curl_init_userdefined(struct Curl_easy *data)
    356 {
    357   struct UserDefined *set = &data->set;
    358   CURLcode result = CURLE_OK;
    359 
    360   set->out = stdout; /* default output to stdout */
    361   set->in_set = stdin;  /* default input from stdin */
    362   set->err  = stderr;  /* default stderr to stderr */
    363 
    364   /* use fwrite as default function to store output */
    365   set->fwrite_func = (curl_write_callback)fwrite;
    366 
    367   /* use fread as default function to read input */
    368   set->fread_func_set = (curl_read_callback)fread;
    369   set->is_fread_set = 0;
    370 
    371   set->seek_client = ZERO_NULL;
    372 
    373   set->filesize = -1;        /* we do not know the size */
    374   set->postfieldsize = -1;   /* unknown size */
    375   set->maxredirs = 30;       /* sensible default */
    376 
    377   set->method = HTTPREQ_GET; /* Default HTTP request */
    378 #ifndef CURL_DISABLE_RTSP
    379   set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
    380 #endif
    381 #ifndef CURL_DISABLE_FTP
    382   set->ftp_use_epsv = TRUE;   /* FTP defaults to EPSV operations */
    383   set->ftp_use_eprt = TRUE;   /* FTP defaults to EPRT operations */
    384   set->ftp_use_pret = FALSE;  /* mainly useful for drftpd servers */
    385   set->ftp_filemethod = FTPFILE_MULTICWD;
    386   set->ftp_skip_ip = TRUE;    /* skip PASV IP by default */
    387 #endif
    388   set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
    389 
    390   /* Timeout every 24 hours by default */
    391   set->general_ssl.ca_cache_timeout = 24 * 60 * 60;
    392 
    393   set->httpauth = CURLAUTH_BASIC;  /* defaults to basic */
    394 
    395 #ifndef CURL_DISABLE_PROXY
    396   set->proxyport = 0;
    397   set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
    398   set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
    399   /* SOCKS5 proxy auth defaults to username/password + GSS-API */
    400   set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI;
    401 #endif
    402 
    403   Curl_mime_initpart(&set->mimepost);
    404 
    405   Curl_ssl_easy_config_init(data);
    406 #ifndef CURL_DISABLE_DOH
    407   set->doh_verifyhost = TRUE;
    408   set->doh_verifypeer = TRUE;
    409 #endif
    410 #ifdef USE_SSH
    411   /* defaults to any auth type */
    412   set->ssh_auth_types = CURLSSH_AUTH_DEFAULT;
    413   set->new_directory_perms = 0755; /* Default permissions */
    414 #endif
    415 
    416   set->new_file_perms = 0644;    /* Default permissions */
    417   set->allowed_protocols = (curl_prot_t) CURLPROTO_ALL;
    418   set->redir_protocols = CURLPROTO_REDIR;
    419 
    420 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
    421   /*
    422    * disallow unprotected protection negotiation NEC reference implementation
    423    * seem not to follow rfc1961 section 4.3/4.4
    424    */
    425   set->socks5_gssapi_nec = FALSE;
    426 #endif
    427 
    428   /* Set the default CA cert bundle/path detected/specified at build time.
    429    *
    430    * If Schannel is the selected SSL backend then these locations are ignored.
    431    * We allow setting CA location for Schannel when explicitly specified by
    432    * the user via CURLOPT_CAINFO / --cacert.
    433    */
    434   if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
    435 #ifdef CURL_CA_BUNDLE
    436     result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
    437     if(result)
    438       return result;
    439 #ifndef CURL_DISABLE_PROXY
    440     result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
    441                             CURL_CA_BUNDLE);
    442     if(result)
    443       return result;
    444 #endif
    445 #endif
    446 #ifdef CURL_CA_PATH
    447     result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
    448     if(result)
    449       return result;
    450 #ifndef CURL_DISABLE_PROXY
    451     result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
    452     if(result)
    453       return result;
    454 #endif
    455 #endif
    456   }
    457 
    458 #ifndef CURL_DISABLE_FTP
    459   set->wildcard_enabled = FALSE;
    460   set->chunk_bgn      = ZERO_NULL;
    461   set->chunk_end      = ZERO_NULL;
    462   set->fnmatch = ZERO_NULL;
    463 #endif
    464   set->tcp_keepalive = FALSE;
    465   set->tcp_keepintvl = 60;
    466   set->tcp_keepidle = 60;
    467   set->tcp_keepcnt = 9;
    468   set->tcp_fastopen = FALSE;
    469   set->tcp_nodelay = TRUE;
    470   set->ssl_enable_alpn = TRUE;
    471   set->expect_100_timeout = 1000L; /* Wait for a second by default. */
    472   set->sep_headers = TRUE; /* separated header lists by default */
    473   set->buffer_size = READBUFFER_SIZE;
    474   set->upload_buffer_size = UPLOADBUFFER_DEFAULT;
    475   set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
    476   set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT;
    477   set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
    478   set->conn_max_idle_ms = 118 * 1000;
    479   set->conn_max_age_ms = 0;
    480   set->http09_allowed = FALSE;
    481   set->httpwant = CURL_HTTP_VERSION_NONE
    482     ;
    483 #if defined(USE_HTTP2) || defined(USE_HTTP3)
    484   memset(&set->priority, 0, sizeof(set->priority));
    485 #endif
    486   set->quick_exit = 0L;
    487 #ifndef CURL_DISABLE_WEBSOCKETS
    488   set->ws_raw_mode = FALSE;
    489   set->ws_no_auto_pong = FALSE;
    490 #endif
    491 
    492   return result;
    493 }
    494 
    495 /* easy->meta_hash destructor. Should never be called as elements
    496  * MUST be added with their own destructor */
    497 static void easy_meta_freeentry(void *p)
    498 {
    499   (void)p;
    500   /* Will always be FALSE. Cannot use a 0 assert here since compilers
    501    * are not in agreement if they then want a NORETURN attribute or
    502    * not. *sigh* */
    503   DEBUGASSERT(p == NULL);
    504 }
    505 
    506 /**
    507  * Curl_open()
    508  *
    509  * @param curl is a pointer to a sessionhandle pointer that gets set by this
    510  * function.
    511  * @return CURLcode
    512  */
    513 
    514 CURLcode Curl_open(struct Curl_easy **curl)
    515 {
    516   CURLcode result;
    517   struct Curl_easy *data;
    518 
    519   /* simple start-up: alloc the struct, init it with zeroes and return */
    520   data = calloc(1, sizeof(struct Curl_easy));
    521   if(!data) {
    522     /* this is a serious error */
    523     DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n"));
    524     return CURLE_OUT_OF_MEMORY;
    525   }
    526 
    527   data->magic = CURLEASY_MAGIC_NUMBER;
    528   /* most recent connection is not yet defined */
    529   data->state.lastconnect_id = -1;
    530   data->state.recent_conn_id = -1;
    531   /* and not assigned an id yet */
    532   data->id = -1;
    533   data->mid = UINT_MAX;
    534   data->master_mid = UINT_MAX;
    535   data->progress.hide = TRUE;
    536   data->state.current_speed = -1; /* init to negative == impossible */
    537 
    538   Curl_hash_init(&data->meta_hash, 23,
    539                  Curl_hash_str, curlx_str_key_compare, easy_meta_freeentry);
    540   curlx_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
    541   Curl_req_init(&data->req);
    542   Curl_initinfo(data);
    543 #ifndef CURL_DISABLE_HTTP
    544   Curl_llist_init(&data->state.httphdrs, NULL);
    545 #endif
    546   Curl_netrc_init(&data->state.netrc);
    547 
    548   result = Curl_init_userdefined(data);
    549 
    550   if(result) {
    551     curlx_dyn_free(&data->state.headerb);
    552     Curl_freeset(data);
    553     Curl_req_free(&data->req, data);
    554     Curl_hash_destroy(&data->meta_hash);
    555     data->magic = 0;
    556     free(data);
    557     data = NULL;
    558   }
    559   else
    560     *curl = data;
    561   return result;
    562 }
    563 
    564 void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn)
    565 {
    566   size_t i;
    567 
    568   DEBUGASSERT(conn);
    569 
    570   if(conn->handler && conn->handler->disconnect &&
    571      !conn->bits.shutdown_handler)
    572     conn->handler->disconnect(data, conn, TRUE);
    573 
    574   for(i = 0; i < CURL_ARRAYSIZE(conn->cfilter); ++i) {
    575     Curl_conn_cf_discard_all(data, conn, (int)i);
    576   }
    577 
    578   Curl_free_idnconverted_hostname(&conn->host);
    579   Curl_free_idnconverted_hostname(&conn->conn_to_host);
    580 #ifndef CURL_DISABLE_PROXY
    581   Curl_free_idnconverted_hostname(&conn->http_proxy.host);
    582   Curl_free_idnconverted_hostname(&conn->socks_proxy.host);
    583   Curl_safefree(conn->http_proxy.user);
    584   Curl_safefree(conn->socks_proxy.user);
    585   Curl_safefree(conn->http_proxy.passwd);
    586   Curl_safefree(conn->socks_proxy.passwd);
    587   Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
    588   Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
    589 #endif
    590   Curl_sec_conn_destroy(conn);
    591   Curl_safefree(conn->user);
    592   Curl_safefree(conn->passwd);
    593   Curl_safefree(conn->sasl_authzid);
    594   Curl_safefree(conn->options);
    595   Curl_safefree(conn->oauth_bearer);
    596   Curl_safefree(conn->host.rawalloc); /* hostname buffer */
    597   Curl_safefree(conn->conn_to_host.rawalloc); /* hostname buffer */
    598   Curl_safefree(conn->hostname_resolve);
    599   Curl_safefree(conn->secondaryhostname);
    600   Curl_safefree(conn->localdev);
    601   Curl_ssl_conn_config_cleanup(conn);
    602 
    603 #ifdef USE_UNIX_SOCKETS
    604   Curl_safefree(conn->unix_domain_socket);
    605 #endif
    606   Curl_safefree(conn->destination);
    607   Curl_uint_spbset_destroy(&conn->xfers_attached);
    608   Curl_hash_destroy(&conn->meta_hash);
    609 
    610   free(conn); /* free all the connection oriented data */
    611 }
    612 
    613 /*
    614  * xfer_may_multiplex()
    615  *
    616  * Return a TRUE, iff the transfer can be done over an (appropriate)
    617  * multiplexed connection.
    618  */
    619 static bool xfer_may_multiplex(const struct Curl_easy *data,
    620                                const struct connectdata *conn)
    621 {
    622 #ifndef CURL_DISABLE_HTTP
    623   /* If an HTTP protocol and multiplexing is enabled */
    624   if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
    625      (!conn->bits.protoconnstart || !conn->bits.close)) {
    626 
    627     if(Curl_multiplex_wanted(data->multi) &&
    628        (data->state.http_neg.allowed & (CURL_HTTP_V2x|CURL_HTTP_V3x)))
    629       /* allows HTTP/2 or newer */
    630       return TRUE;
    631   }
    632 #else
    633   (void)data;
    634   (void)conn;
    635 #endif
    636   return FALSE;
    637 }
    638 
    639 #ifndef CURL_DISABLE_PROXY
    640 static bool
    641 proxy_info_matches(const struct proxy_info *data,
    642                    const struct proxy_info *needle)
    643 {
    644   if((data->proxytype == needle->proxytype) &&
    645      (data->port == needle->port) &&
    646      curl_strequal(data->host.name, needle->host.name))
    647     return TRUE;
    648 
    649   return FALSE;
    650 }
    651 
    652 static bool
    653 socks_proxy_info_matches(const struct proxy_info *data,
    654                          const struct proxy_info *needle)
    655 {
    656   if(!proxy_info_matches(data, needle))
    657     return FALSE;
    658 
    659   /* the user information is case-sensitive
    660      or at least it is not defined as case-insensitive
    661      see https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1 */
    662 
    663   /* curl_strequal does a case insensitive comparison,
    664      so do not use it here! */
    665   if(Curl_timestrcmp(data->user, needle->user) ||
    666      Curl_timestrcmp(data->passwd, needle->passwd))
    667     return FALSE;
    668   return TRUE;
    669 }
    670 #else
    671 /* disabled, will not get called */
    672 #define proxy_info_matches(x,y) FALSE
    673 #define socks_proxy_info_matches(x,y) FALSE
    674 #endif
    675 
    676 /* A connection has to have been idle for less than 'conn_max_idle_ms'
    677    (the success rate is just too low after this), or created less than
    678    'conn_max_age_ms' ago, to be subject for reuse. */
    679 static bool conn_maxage(struct Curl_easy *data,
    680                         struct connectdata *conn,
    681                         struct curltime now)
    682 {
    683   timediff_t age_ms;
    684 
    685   if(data->set.conn_max_idle_ms) {
    686     age_ms = curlx_timediff(now, conn->lastused);
    687     if(age_ms > data->set.conn_max_idle_ms) {
    688       infof(data, "Too old connection (%" FMT_TIMEDIFF_T
    689             " ms idle, max idle is %" FMT_TIMEDIFF_T " ms), disconnect it",
    690             age_ms, data->set.conn_max_idle_ms);
    691       return TRUE;
    692     }
    693   }
    694 
    695   if(data->set.conn_max_age_ms) {
    696     age_ms = curlx_timediff(now, conn->created);
    697     if(age_ms > data->set.conn_max_age_ms) {
    698       infof(data,
    699             "Too old connection (created %" FMT_TIMEDIFF_T
    700             " ms ago, max lifetime is %" FMT_TIMEDIFF_T " ms), disconnect it",
    701             age_ms, data->set.conn_max_age_ms);
    702       return TRUE;
    703     }
    704   }
    705 
    706   return FALSE;
    707 }
    708 
    709 /*
    710  * Return TRUE iff the given connection is considered dead.
    711  */
    712 bool Curl_conn_seems_dead(struct connectdata *conn,
    713                           struct Curl_easy *data,
    714                           struct curltime *pnow)
    715 {
    716   DEBUGASSERT(!data->conn);
    717   if(!CONN_INUSE(conn)) {
    718     /* The check for a dead socket makes sense only if the connection is not in
    719        use */
    720     bool dead;
    721     struct curltime now;
    722     if(!pnow) {
    723       now = curlx_now();
    724       pnow = &now;
    725     }
    726 
    727     if(conn_maxage(data, conn, *pnow)) {
    728       /* avoid check if already too old */
    729       dead = TRUE;
    730     }
    731     else if(conn->handler->connection_check) {
    732       /* The protocol has a special method for checking the state of the
    733          connection. Use it to check if the connection is dead. */
    734       unsigned int state;
    735 
    736       /* briefly attach the connection to this transfer for the purpose of
    737          checking it */
    738       Curl_attach_connection(data, conn);
    739 
    740       state = conn->handler->connection_check(data, conn, CONNCHECK_ISDEAD);
    741       dead = (state & CONNRESULT_DEAD);
    742       /* detach the connection again */
    743       Curl_detach_connection(data);
    744 
    745     }
    746     else {
    747       bool input_pending = FALSE;
    748 
    749       Curl_attach_connection(data, conn);
    750       dead = !Curl_conn_is_alive(data, conn, &input_pending);
    751       if(input_pending) {
    752         /* For reuse, we want a "clean" connection state. The includes
    753          * that we expect - in general - no waiting input data. Input
    754          * waiting might be a TLS Notify Close, for example. We reject
    755          * that.
    756          * For protocols where data from other end may arrive at
    757          * any time (HTTP/2 PING for example), the protocol handler needs
    758          * to install its own `connection_check` callback.
    759          */
    760         DEBUGF(infof(data, "connection has input pending, not reusable"));
    761         dead = TRUE;
    762       }
    763       Curl_detach_connection(data);
    764     }
    765 
    766     if(dead) {
    767       /* remove connection from cpool */
    768       infof(data, "Connection %" FMT_OFF_T " seems to be dead",
    769             conn->connection_id);
    770       return TRUE;
    771     }
    772   }
    773   return FALSE;
    774 }
    775 
    776 CURLcode Curl_conn_upkeep(struct Curl_easy *data,
    777                           struct connectdata *conn,
    778                           struct curltime *now)
    779 {
    780   CURLcode result = CURLE_OK;
    781   if(curlx_timediff(*now, conn->keepalive) <= data->set.upkeep_interval_ms)
    782     return result;
    783 
    784   /* briefly attach for action */
    785   Curl_attach_connection(data, conn);
    786   if(conn->handler->connection_check) {
    787     /* Do a protocol-specific keepalive check on the connection. */
    788     unsigned int rc;
    789     rc = conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE);
    790     if(rc & CONNRESULT_DEAD)
    791       result = CURLE_RECV_ERROR;
    792   }
    793   else {
    794     /* Do the generic action on the FIRSTSOCKET filter chain */
    795     result = Curl_conn_keep_alive(data, conn, FIRSTSOCKET);
    796   }
    797   Curl_detach_connection(data);
    798 
    799   conn->keepalive = *now;
    800   return result;
    801 }
    802 
    803 #ifdef USE_SSH
    804 static bool ssh_config_matches(struct connectdata *one,
    805                                struct connectdata *two)
    806 {
    807   struct ssh_conn *sshc1, *sshc2;
    808 
    809   sshc1 = Curl_conn_meta_get(one, CURL_META_SSH_CONN);
    810   sshc2 = Curl_conn_meta_get(two, CURL_META_SSH_CONN);
    811   return (sshc1 && sshc2 && Curl_safecmp(sshc1->rsa, sshc2->rsa) &&
    812           Curl_safecmp(sshc1->rsa_pub, sshc2->rsa_pub));
    813 }
    814 #endif
    815 
    816 struct url_conn_match {
    817   struct connectdata *found;
    818   struct Curl_easy *data;
    819   struct connectdata *needle;
    820   BIT(may_multiplex);
    821   BIT(want_ntlm_http);
    822   BIT(want_proxy_ntlm_http);
    823 
    824   BIT(wait_pipe);
    825   BIT(force_reuse);
    826   BIT(seen_pending_conn);
    827   BIT(seen_single_use_conn);
    828   BIT(seen_multiplex_conn);
    829 };
    830 
    831 static bool url_match_connect_config(struct connectdata *conn,
    832                                      struct url_conn_match *m)
    833 {
    834   /* connect-only or to-be-closed connections will not be reused */
    835   if(conn->connect_only || conn->bits.close)
    836     return FALSE;
    837 
    838   /* ip_version must match */
    839   if(m->data->set.ipver != CURL_IPRESOLVE_WHATEVER
    840      && m->data->set.ipver != conn->ip_version)
    841     return FALSE;
    842 
    843   if(m->needle->localdev || m->needle->localport) {
    844     /* If we are bound to a specific local end (IP+port), we must not reuse a
    845        random other one, although if we did not ask for a particular one we
    846        can reuse one that was bound.
    847 
    848        This comparison is a bit rough and too strict. Since the input
    849        parameters can be specified in numerous ways and still end up the same
    850        it would take a lot of processing to make it really accurate. Instead,
    851        this matching will assume that reuses of bound connections will most
    852        likely also reuse the exact same binding parameters and missing out a
    853        few edge cases should not hurt anyone much.
    854     */
    855     if((conn->localport != m->needle->localport) ||
    856        (conn->localportrange != m->needle->localportrange) ||
    857        (m->needle->localdev &&
    858         (!conn->localdev || strcmp(conn->localdev, m->needle->localdev))))
    859       return FALSE;
    860   }
    861 
    862   if(m->needle->bits.conn_to_host != conn->bits.conn_to_host)
    863     /* do not mix connections that use the "connect to host" feature and
    864      * connections that do not use this feature */
    865     return FALSE;
    866 
    867   if(m->needle->bits.conn_to_port != conn->bits.conn_to_port)
    868     /* do not mix connections that use the "connect to port" feature and
    869      * connections that do not use this feature */
    870     return FALSE;
    871 
    872   /* Does `conn` use the correct protocol? */
    873 #ifdef USE_UNIX_SOCKETS
    874   if(m->needle->unix_domain_socket) {
    875     if(!conn->unix_domain_socket)
    876       return FALSE;
    877     if(strcmp(m->needle->unix_domain_socket, conn->unix_domain_socket))
    878       return FALSE;
    879     if(m->needle->bits.abstract_unix_socket != conn->bits.abstract_unix_socket)
    880       return FALSE;
    881   }
    882   else if(conn->unix_domain_socket)
    883     return FALSE;
    884 #endif
    885 
    886   return TRUE;
    887 }
    888 
    889 static bool url_match_fully_connected(struct connectdata *conn,
    890                                       struct url_conn_match *m)
    891 {
    892   if(!Curl_conn_is_connected(conn, FIRSTSOCKET) ||
    893      conn->bits.asks_multiplex) {
    894     /* Not yet connected, or not yet decided if it multiplexes. The later
    895      * happens for HTTP/2 Upgrade: requests that need a response. */
    896     if(m->may_multiplex) {
    897       m->seen_pending_conn = TRUE;
    898       /* Do not pick a connection that has not connected yet */
    899       infof(m->data, "Connection #%" FMT_OFF_T
    900             " is not open enough, cannot reuse", conn->connection_id);
    901     }
    902     /* Do not pick a connection that has not connected yet */
    903     return FALSE;
    904   }
    905   return TRUE;
    906 }
    907 
    908 static bool url_match_multi(struct connectdata *conn,
    909                             struct url_conn_match *m)
    910 {
    911   if(CONN_INUSE(conn)) {
    912     DEBUGASSERT(conn->attached_multi);
    913     if(conn->attached_multi != m->data->multi)
    914       return FALSE;
    915   }
    916   return TRUE;
    917 }
    918 
    919 static bool url_match_multiplex_needs(struct connectdata *conn,
    920                                       struct url_conn_match *m)
    921 {
    922   if(CONN_INUSE(conn)) {
    923     if(!conn->bits.multiplex) {
    924       /* conn busy and conn cannot take more transfers */
    925       m->seen_single_use_conn = TRUE;
    926       return FALSE;
    927     }
    928     m->seen_multiplex_conn = TRUE;
    929     if(!m->may_multiplex || !url_match_multi(conn, m))
    930       /* conn busy and transfer cannot be multiplexed */
    931       return FALSE;
    932   }
    933   return TRUE;
    934 }
    935 
    936 static bool url_match_multiplex_limits(struct connectdata *conn,
    937                                        struct url_conn_match *m)
    938 {
    939   if(CONN_INUSE(conn) && m->may_multiplex) {
    940     DEBUGASSERT(conn->bits.multiplex);
    941     /* If multiplexed, make sure we do not go over concurrency limit */
    942     if(CONN_ATTACHED(conn) >=
    943             Curl_multi_max_concurrent_streams(m->data->multi)) {
    944       infof(m->data, "client side MAX_CONCURRENT_STREAMS reached"
    945             ", skip (%u)", CONN_ATTACHED(conn));
    946       return FALSE;
    947     }
    948     if(CONN_ATTACHED(conn) >=
    949             Curl_conn_get_max_concurrent(m->data, conn, FIRSTSOCKET)) {
    950       infof(m->data, "MAX_CONCURRENT_STREAMS reached, skip (%u)",
    951             CONN_ATTACHED(conn));
    952       return FALSE;
    953     }
    954     /* When not multiplexed, we have a match here! */
    955     infof(m->data, "Multiplexed connection found");
    956   }
    957   return TRUE;
    958 }
    959 
    960 static bool url_match_ssl_use(struct connectdata *conn,
    961                               struct url_conn_match *m)
    962 {
    963   if(m->needle->handler->flags&PROTOPT_SSL) {
    964     /* We are looking for SSL, if `conn` does not do it, not a match. */
    965     if(!Curl_conn_is_ssl(conn, FIRSTSOCKET))
    966       return FALSE;
    967   }
    968   else if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
    969     /* We are not *requiring* SSL, however `conn` has it. If the
    970      * protocol *family* is not the same, not a match. */
    971     if(get_protocol_family(conn->handler) != m->needle->handler->protocol)
    972       return FALSE;
    973   }
    974   return TRUE;
    975 }
    976 
    977 #ifndef CURL_DISABLE_PROXY
    978 static bool url_match_proxy_use(struct connectdata *conn,
    979                                 struct url_conn_match *m)
    980 {
    981   if(m->needle->bits.httpproxy != conn->bits.httpproxy ||
    982      m->needle->bits.socksproxy != conn->bits.socksproxy)
    983     return FALSE;
    984 
    985   if(m->needle->bits.socksproxy &&
    986     !socks_proxy_info_matches(&m->needle->socks_proxy,
    987                               &conn->socks_proxy))
    988     return FALSE;
    989 
    990   if(m->needle->bits.httpproxy) {
    991     if(m->needle->bits.tunnel_proxy != conn->bits.tunnel_proxy)
    992       return FALSE;
    993 
    994     if(!proxy_info_matches(&m->needle->http_proxy, &conn->http_proxy))
    995       return FALSE;
    996 
    997     if(IS_HTTPS_PROXY(m->needle->http_proxy.proxytype)) {
    998       /* https proxies come in different types, http/1.1, h2, ... */
    999       if(m->needle->http_proxy.proxytype != conn->http_proxy.proxytype)
   1000         return FALSE;
   1001       /* match SSL config to proxy */
   1002       if(!Curl_ssl_conn_config_match(m->data, conn, TRUE)) {
   1003         DEBUGF(infof(m->data,
   1004           "Connection #%" FMT_OFF_T
   1005           " has different SSL proxy parameters, cannot reuse",
   1006           conn->connection_id));
   1007         return FALSE;
   1008       }
   1009       /* the SSL config to the server, which may apply here is checked
   1010        * further below */
   1011     }
   1012   }
   1013   return TRUE;
   1014 }
   1015 #else
   1016 #define url_match_proxy_use(c,m)    ((void)c, (void)m, TRUE)
   1017 #endif
   1018 
   1019 #ifndef CURL_DISABLE_HTTP
   1020 static bool url_match_http_multiplex(struct connectdata *conn,
   1021                                      struct url_conn_match *m)
   1022 {
   1023   if(m->may_multiplex &&
   1024      (m->data->state.http_neg.allowed & (CURL_HTTP_V2x|CURL_HTTP_V3x)) &&
   1025      (m->needle->handler->protocol & CURLPROTO_HTTP) &&
   1026      !conn->httpversion_seen) {
   1027     if(m->data->set.pipewait) {
   1028       infof(m->data, "Server upgrade does not support multiplex yet, wait");
   1029       m->found = NULL;
   1030       m->wait_pipe = TRUE;
   1031       return TRUE; /* stop searching, we want to wait */
   1032     }
   1033     infof(m->data, "Server upgrade cannot be used");
   1034     return FALSE;
   1035   }
   1036   return TRUE;
   1037 }
   1038 
   1039 static bool url_match_http_version(struct connectdata *conn,
   1040                                    struct url_conn_match *m)
   1041 {
   1042   /* If looking for HTTP and the HTTP versions allowed do not include
   1043    * the HTTP version of conn, continue looking. */
   1044   if((m->needle->handler->protocol & PROTO_FAMILY_HTTP)) {
   1045     switch(Curl_conn_http_version(m->data, conn)) {
   1046     case 30:
   1047       if(!(m->data->state.http_neg.allowed & CURL_HTTP_V3x)) {
   1048         DEBUGF(infof(m->data, "not reusing conn #%" CURL_FORMAT_CURL_OFF_T
   1049                ", we do not want h3", conn->connection_id));
   1050         return FALSE;
   1051       }
   1052       break;
   1053     case 20:
   1054       if(!(m->data->state.http_neg.allowed & CURL_HTTP_V2x)) {
   1055         DEBUGF(infof(m->data, "not reusing conn #%" CURL_FORMAT_CURL_OFF_T
   1056                ", we do not want h2", conn->connection_id));
   1057         return FALSE;
   1058       }
   1059       break;
   1060     default:
   1061       if(!(m->data->state.http_neg.allowed & CURL_HTTP_V1x)) {
   1062         DEBUGF(infof(m->data, "not reusing conn #%" CURL_FORMAT_CURL_OFF_T
   1063                ", we do not want h1", conn->connection_id));
   1064         return FALSE;
   1065       }
   1066       break;
   1067     }
   1068   }
   1069   return TRUE;
   1070 }
   1071 #else
   1072 #define url_match_http_multiplex(c,m)    ((void)c, (void)m, TRUE)
   1073 #define url_match_http_version(c,m)      ((void)c, (void)m, TRUE)
   1074 #endif
   1075 
   1076 static bool url_match_proto_config(struct connectdata *conn,
   1077                                    struct url_conn_match *m)
   1078 {
   1079   if(!url_match_http_version(conn, m))
   1080     return FALSE;
   1081 
   1082 #ifdef USE_SSH
   1083   if(get_protocol_family(m->needle->handler) & PROTO_FAMILY_SSH) {
   1084     if(!ssh_config_matches(m->needle, conn))
   1085       return FALSE;
   1086   }
   1087 #endif
   1088 #ifndef CURL_DISABLE_FTP
   1089   else if(get_protocol_family(m->needle->handler) & PROTO_FAMILY_FTP) {
   1090     if(!ftp_conns_match(m->needle, conn))
   1091       return FALSE;
   1092   }
   1093 #endif
   1094   return TRUE;
   1095 }
   1096 
   1097 static bool url_match_auth(struct connectdata *conn,
   1098                            struct url_conn_match *m)
   1099 {
   1100   if(!(m->needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
   1101     /* This protocol requires credentials per connection,
   1102        so verify that we are using the same name and password as well */
   1103     if(Curl_timestrcmp(m->needle->user, conn->user) ||
   1104        Curl_timestrcmp(m->needle->passwd, conn->passwd) ||
   1105        Curl_timestrcmp(m->needle->sasl_authzid, conn->sasl_authzid) ||
   1106        Curl_timestrcmp(m->needle->oauth_bearer, conn->oauth_bearer)) {
   1107       /* one of them was different */
   1108       return FALSE;
   1109     }
   1110   }
   1111 #ifdef HAVE_GSSAPI
   1112   /* GSS delegation differences do not actually affect every connection
   1113      and auth method, but this check takes precaution before efficiency */
   1114   if(m->needle->gssapi_delegation != conn->gssapi_delegation)
   1115     return FALSE;
   1116 #endif
   1117 
   1118   return TRUE;
   1119 }
   1120 
   1121 static bool url_match_destination(struct connectdata *conn,
   1122                                   struct url_conn_match *m)
   1123 {
   1124   /* Additional match requirements if talking TLS OR
   1125    * not talking to an HTTP proxy OR using a tunnel through a proxy */
   1126   if((m->needle->handler->flags&PROTOPT_SSL)
   1127 #ifndef CURL_DISABLE_PROXY
   1128      || !m->needle->bits.httpproxy || m->needle->bits.tunnel_proxy
   1129 #endif
   1130     ) {
   1131     if(!curl_strequal(m->needle->handler->scheme, conn->handler->scheme)) {
   1132       /* `needle` and `conn` do not have the same scheme... */
   1133       if(get_protocol_family(conn->handler) != m->needle->handler->protocol) {
   1134         /* and `conn`s protocol family is not the protocol `needle` wants.
   1135          * IMAPS would work for IMAP, but no vice versa. */
   1136         return FALSE;
   1137       }
   1138       /* We are in an IMAPS vs IMAP like case. We expect `conn` to have SSL */
   1139       if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
   1140         DEBUGF(infof(m->data,
   1141           "Connection #%" FMT_OFF_T " has compatible protocol family, "
   1142           "but no SSL, no match", conn->connection_id));
   1143         return FALSE;
   1144       }
   1145     }
   1146 
   1147     /* If needle has "conn_to_*" set, conn must match this */
   1148     if((m->needle->bits.conn_to_host && !curl_strequal(
   1149         m->needle->conn_to_host.name, conn->conn_to_host.name)) ||
   1150        (m->needle->bits.conn_to_port &&
   1151          m->needle->conn_to_port != conn->conn_to_port))
   1152       return FALSE;
   1153 
   1154     /* hostname and port must match */
   1155     if(!curl_strequal(m->needle->host.name, conn->host.name) ||
   1156        m->needle->remote_port != conn->remote_port)
   1157       return FALSE;
   1158   }
   1159   return TRUE;
   1160 }
   1161 
   1162 static bool url_match_ssl_config(struct connectdata *conn,
   1163                                  struct url_conn_match *m)
   1164 {
   1165   /* If talking TLS, conn needs to use the same SSL options. */
   1166   if((m->needle->handler->flags & PROTOPT_SSL) &&
   1167      !Curl_ssl_conn_config_match(m->data, conn, FALSE)) {
   1168     DEBUGF(infof(m->data,
   1169                  "Connection #%" FMT_OFF_T
   1170                  " has different SSL parameters, cannot reuse",
   1171                  conn->connection_id));
   1172     return FALSE;
   1173   }
   1174   return TRUE;
   1175 }
   1176 
   1177 #ifdef USE_NTLM
   1178 static bool url_match_auth_ntlm(struct connectdata *conn,
   1179                                 struct url_conn_match *m)
   1180 {
   1181   /* If we are looking for an HTTP+NTLM connection, check if this is
   1182      already authenticating with the right credentials. If not, keep
   1183      looking so that we can reuse NTLM connections if
   1184      possible. (Especially we must not reuse the same connection if
   1185      partway through a handshake!) */
   1186   if(m->want_ntlm_http) {
   1187     if(Curl_timestrcmp(m->needle->user, conn->user) ||
   1188        Curl_timestrcmp(m->needle->passwd, conn->passwd)) {
   1189 
   1190       /* we prefer a credential match, but this is at least a connection
   1191          that can be reused and "upgraded" to NTLM */
   1192       if(conn->http_ntlm_state == NTLMSTATE_NONE)
   1193         m->found = conn;
   1194       return FALSE;
   1195     }
   1196   }
   1197   else if(conn->http_ntlm_state != NTLMSTATE_NONE) {
   1198     /* Connection is using NTLM auth but we do not want NTLM */
   1199     return FALSE;
   1200   }
   1201 
   1202 #ifndef CURL_DISABLE_PROXY
   1203   /* Same for Proxy NTLM authentication */
   1204   if(m->want_proxy_ntlm_http) {
   1205     /* Both conn->http_proxy.user and conn->http_proxy.passwd can be
   1206      * NULL */
   1207     if(!conn->http_proxy.user || !conn->http_proxy.passwd)
   1208       return FALSE;
   1209 
   1210     if(Curl_timestrcmp(m->needle->http_proxy.user,
   1211                        conn->http_proxy.user) ||
   1212        Curl_timestrcmp(m->needle->http_proxy.passwd,
   1213                        conn->http_proxy.passwd))
   1214       return FALSE;
   1215   }
   1216   else if(conn->proxy_ntlm_state != NTLMSTATE_NONE) {
   1217     /* Proxy connection is using NTLM auth but we do not want NTLM */
   1218     return FALSE;
   1219   }
   1220 #endif
   1221   if(m->want_ntlm_http || m->want_proxy_ntlm_http) {
   1222     /* Credentials are already checked, we may use this connection.
   1223      * With NTLM being weird as it is, we MUST use a
   1224      * connection where it has already been fully negotiated.
   1225      * If it has not, we keep on looking for a better one. */
   1226     m->found = conn;
   1227 
   1228     if((m->want_ntlm_http &&
   1229        (conn->http_ntlm_state != NTLMSTATE_NONE)) ||
   1230         (m->want_proxy_ntlm_http &&
   1231          (conn->proxy_ntlm_state != NTLMSTATE_NONE))) {
   1232       /* We must use this connection, no other */
   1233       m->force_reuse = TRUE;
   1234       return TRUE;
   1235     }
   1236     /* Continue look up for a better connection */
   1237     return FALSE;
   1238   }
   1239   return TRUE;
   1240 }
   1241 #else
   1242 #define url_match_auth_ntlm(c,m)    ((void)c, (void)m, TRUE)
   1243 #endif
   1244 
   1245 static bool url_match_conn(struct connectdata *conn, void *userdata)
   1246 {
   1247   struct url_conn_match *m = userdata;
   1248   /* Check if `conn` can be used for transfer `m->data` */
   1249 
   1250   /* general connect config setting match? */
   1251   if(!url_match_connect_config(conn, m))
   1252     return FALSE;
   1253 
   1254   if(!url_match_destination(conn, m))
   1255     return FALSE;
   1256 
   1257   if(!url_match_fully_connected(conn, m))
   1258     return FALSE;
   1259 
   1260   if(!url_match_multiplex_needs(conn, m))
   1261     return FALSE;
   1262 
   1263   if(!url_match_ssl_use(conn, m))
   1264     return FALSE;
   1265   if(!url_match_proxy_use(conn, m))
   1266     return FALSE;
   1267   if(!url_match_ssl_config(conn, m))
   1268     return FALSE;
   1269 
   1270   if(!url_match_http_multiplex(conn, m))
   1271     return FALSE;
   1272   else if(m->wait_pipe)
   1273     /* we decided to wait on PIPELINING */
   1274     return TRUE;
   1275 
   1276   if(!url_match_auth(conn, m))
   1277     return FALSE;
   1278 
   1279   if(!url_match_proto_config(conn, m))
   1280     return FALSE;
   1281 
   1282   if(!url_match_auth_ntlm(conn, m))
   1283     return FALSE;
   1284   else if(m->force_reuse)
   1285     return TRUE;
   1286 
   1287   if(!url_match_multiplex_limits(conn, m))
   1288     return FALSE;
   1289 
   1290   if(!CONN_INUSE(conn) && Curl_conn_seems_dead(conn, m->data, NULL)) {
   1291     /* remove and disconnect. */
   1292     Curl_conn_terminate(m->data, conn, FALSE);
   1293     return FALSE;
   1294   }
   1295 
   1296   /* conn matches our needs. */
   1297   m->found = conn;
   1298   return TRUE;
   1299 }
   1300 
   1301 static bool url_match_result(bool result, void *userdata)
   1302 {
   1303   struct url_conn_match *match = userdata;
   1304   (void)result;
   1305   if(match->found) {
   1306     /* Attach it now while still under lock, so the connection does
   1307      * no longer appear idle and can be reaped. */
   1308     Curl_attach_connection(match->data, match->found);
   1309     return TRUE;
   1310   }
   1311   else if(match->seen_single_use_conn && !match->seen_multiplex_conn) {
   1312     /* We've seen a single-use, existing connection to the destination and
   1313      * no multiplexed one. It seems safe to assume that the server does
   1314      * not support multiplexing. */
   1315     match->wait_pipe = FALSE;
   1316   }
   1317   else if(match->seen_pending_conn && match->data->set.pipewait) {
   1318     infof(match->data,
   1319           "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set");
   1320     match->wait_pipe = TRUE;
   1321   }
   1322   match->force_reuse = FALSE;
   1323   return FALSE;
   1324 }
   1325 
   1326 /*
   1327  * Given one filled in connection struct (named needle), this function should
   1328  * detect if there already is one that has all the significant details
   1329  * exactly the same and thus should be used instead.
   1330  *
   1331  * If there is a match, this function returns TRUE - and has marked the
   1332  * connection as 'in-use'. It must later be called with ConnectionDone() to
   1333  * return back to 'idle' (unused) state.
   1334  *
   1335  * The force_reuse flag is set if the connection must be used.
   1336  */
   1337 static bool
   1338 ConnectionExists(struct Curl_easy *data,
   1339                  struct connectdata *needle,
   1340                  struct connectdata **usethis,
   1341                  bool *force_reuse,
   1342                  bool *waitpipe)
   1343 {
   1344   struct url_conn_match match;
   1345   bool result;
   1346 
   1347   memset(&match, 0, sizeof(match));
   1348   match.data = data;
   1349   match.needle = needle;
   1350   match.may_multiplex = xfer_may_multiplex(data, needle);
   1351 
   1352 #ifdef USE_NTLM
   1353   match.want_ntlm_http = ((data->state.authhost.want & CURLAUTH_NTLM) &&
   1354                           (needle->handler->protocol & PROTO_FAMILY_HTTP));
   1355 #ifndef CURL_DISABLE_PROXY
   1356   match.want_proxy_ntlm_http =
   1357     (needle->bits.proxy_user_passwd &&
   1358      (data->state.authproxy.want & CURLAUTH_NTLM) &&
   1359      (needle->handler->protocol & PROTO_FAMILY_HTTP));
   1360 #endif
   1361 #endif
   1362 
   1363   /* Find a connection in the pool that matches what "data + needle"
   1364    * requires. If a suitable candidate is found, it is attached to "data". */
   1365   result = Curl_cpool_find(data, needle->destination,
   1366                            url_match_conn, url_match_result, &match);
   1367 
   1368   /* wait_pipe is TRUE if we encounter a bundle that is undecided. There
   1369    * is no matching connection then, yet. */
   1370   *usethis = match.found;
   1371   *force_reuse = match.force_reuse;
   1372   *waitpipe = match.wait_pipe;
   1373   return result;
   1374 }
   1375 
   1376 /*
   1377  * verboseconnect() displays verbose information after a connect
   1378  */
   1379 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   1380 void Curl_verboseconnect(struct Curl_easy *data,
   1381                          struct connectdata *conn, int sockindex)
   1382 {
   1383   if(data->set.verbose && sockindex == SECONDARYSOCKET)
   1384     infof(data, "Connected 2nd connection to %s port %u",
   1385           conn->secondary.remote_ip, conn->secondary.remote_port);
   1386   else
   1387     infof(data, "Connected to %s (%s) port %u",
   1388           CURL_CONN_HOST_DISPNAME(conn), conn->primary.remote_ip,
   1389           conn->primary.remote_port);
   1390 #ifndef CURL_DISABLE_HTTP
   1391     if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
   1392       switch(conn->alpn) {
   1393       case CURL_HTTP_VERSION_3:
   1394         infof(data, "using HTTP/3");
   1395         break;
   1396       case CURL_HTTP_VERSION_2:
   1397         infof(data, "using HTTP/2");
   1398         break;
   1399       default:
   1400         infof(data, "using HTTP/1.x");
   1401         break;
   1402       }
   1403     }
   1404 #endif
   1405 }
   1406 #endif
   1407 
   1408 /*
   1409  * Allocate and initialize a new connectdata object.
   1410  */
   1411 static struct connectdata *allocate_conn(struct Curl_easy *data)
   1412 {
   1413   struct connectdata *conn = calloc(1, sizeof(struct connectdata));
   1414   if(!conn)
   1415     return NULL;
   1416 
   1417   /* and we setup a few fields in case we end up actually using this struct */
   1418 
   1419   conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;     /* no file descriptor */
   1420   conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
   1421   conn->sockfd = CURL_SOCKET_BAD;
   1422   conn->writesockfd = CURL_SOCKET_BAD;
   1423   conn->connection_id = -1;    /* no ID */
   1424   conn->primary.remote_port = -1; /* unknown at this point */
   1425   conn->remote_port = -1; /* unknown at this point */
   1426 
   1427   /* Default protocol-independent behavior does not support persistent
   1428      connections, so we set this to force-close. Protocols that support
   1429      this need to set this to FALSE in their "curl_do" functions. */
   1430   connclose(conn, "Default to force-close");
   1431 
   1432   /* Store creation time to help future close decision making */
   1433   conn->created = curlx_now();
   1434 
   1435   /* Store current time to give a baseline to keepalive connection times. */
   1436   conn->keepalive = conn->created;
   1437 
   1438 #ifndef CURL_DISABLE_PROXY
   1439   conn->http_proxy.proxytype = data->set.proxytype;
   1440   conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
   1441 
   1442   /* note that these two proxy bits are now just on what looks to be
   1443      requested, they may be altered down the road */
   1444   conn->bits.proxy = (data->set.str[STRING_PROXY] &&
   1445                       *data->set.str[STRING_PROXY]);
   1446   conn->bits.httpproxy = (conn->bits.proxy &&
   1447                           (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
   1448                            conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
   1449                            IS_HTTPS_PROXY(conn->http_proxy.proxytype)));
   1450   conn->bits.socksproxy = (conn->bits.proxy && !conn->bits.httpproxy);
   1451 
   1452   if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) {
   1453     conn->bits.proxy = TRUE;
   1454     conn->bits.socksproxy = TRUE;
   1455   }
   1456 
   1457   conn->bits.proxy_user_passwd = !!data->state.aptr.proxyuser;
   1458   conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
   1459 #endif /* CURL_DISABLE_PROXY */
   1460 
   1461 #ifndef CURL_DISABLE_FTP
   1462   conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
   1463   conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
   1464 #endif
   1465   conn->ip_version = data->set.ipver;
   1466   conn->connect_only = data->set.connect_only;
   1467   conn->transport_wanted = TRNSPRT_TCP; /* most of them are TCP streams */
   1468 
   1469   /* Initialize the attached xfers bitset */
   1470   Curl_uint_spbset_init(&conn->xfers_attached);
   1471 
   1472 #ifdef HAVE_GSSAPI
   1473   conn->data_prot = PROT_CLEAR;
   1474 #endif
   1475 
   1476   /* Store the local bind parameters that will be used for this connection */
   1477   if(data->set.str[STRING_DEVICE]) {
   1478     conn->localdev = strdup(data->set.str[STRING_DEVICE]);
   1479     if(!conn->localdev)
   1480       goto error;
   1481   }
   1482 #ifndef CURL_DISABLE_BINDLOCAL
   1483   conn->localportrange = data->set.localportrange;
   1484   conn->localport = data->set.localport;
   1485 #endif
   1486 
   1487   /* the close socket stuff needs to be copied to the connection struct as
   1488      it may live on without (this specific) Curl_easy */
   1489   conn->fclosesocket = data->set.fclosesocket;
   1490   conn->closesocket_client = data->set.closesocket_client;
   1491   conn->lastused = conn->created;
   1492 #ifdef HAVE_GSSAPI
   1493   conn->gssapi_delegation = data->set.gssapi_delegation;
   1494 #endif
   1495   return conn;
   1496 error:
   1497 
   1498   free(conn->localdev);
   1499   free(conn);
   1500   return NULL;
   1501 }
   1502 
   1503 const struct Curl_handler *Curl_get_scheme_handler(const char *scheme)
   1504 {
   1505   return Curl_getn_scheme_handler(scheme, strlen(scheme));
   1506 }
   1507 
   1508 /* returns the handler if the given scheme is built-in */
   1509 const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme,
   1510                                                     size_t len)
   1511 {
   1512   /* table generated by schemetable.c:
   1513      1. gcc schemetable.c && ./a.out
   1514      2. check how small the table gets
   1515      3. tweak the hash algorithm, then rerun from 1
   1516      4. when the table is good enough
   1517      5. copy the table into this source code
   1518      6. make sure this function uses the same hash function that worked for
   1519      schemetable.c
   1520      7. if needed, adjust the #ifdefs in schemetable.c and rerun
   1521      */
   1522   static const struct Curl_handler * const protocols[67] = {
   1523 #ifndef CURL_DISABLE_FILE
   1524     &Curl_handler_file,
   1525 #else
   1526     NULL,
   1527 #endif
   1528     NULL, NULL,
   1529 #if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)
   1530     &Curl_handler_gophers,
   1531 #else
   1532     NULL,
   1533 #endif
   1534     NULL,
   1535 #ifdef USE_LIBRTMP
   1536     &Curl_handler_rtmpe,
   1537 #else
   1538     NULL,
   1539 #endif
   1540 #ifndef CURL_DISABLE_SMTP
   1541     &Curl_handler_smtp,
   1542 #else
   1543     NULL,
   1544 #endif
   1545 #ifdef USE_SSH
   1546     &Curl_handler_sftp,
   1547 #else
   1548     NULL,
   1549 #endif
   1550 #if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
   1551   (SIZEOF_CURL_OFF_T > 4)
   1552     &Curl_handler_smb,
   1553 #else
   1554     NULL,
   1555 #endif
   1556 #if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)
   1557     &Curl_handler_smtps,
   1558 #else
   1559     NULL,
   1560 #endif
   1561 #ifndef CURL_DISABLE_TELNET
   1562     &Curl_handler_telnet,
   1563 #else
   1564     NULL,
   1565 #endif
   1566 #ifndef CURL_DISABLE_GOPHER
   1567     &Curl_handler_gopher,
   1568 #else
   1569     NULL,
   1570 #endif
   1571 #ifndef CURL_DISABLE_TFTP
   1572     &Curl_handler_tftp,
   1573 #else
   1574     NULL,
   1575 #endif
   1576     NULL, NULL, NULL,
   1577 #if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
   1578     &Curl_handler_ftps,
   1579 #else
   1580     NULL,
   1581 #endif
   1582 #ifndef CURL_DISABLE_HTTP
   1583     &Curl_handler_http,
   1584 #else
   1585     NULL,
   1586 #endif
   1587 #ifndef CURL_DISABLE_IMAP
   1588     &Curl_handler_imap,
   1589 #else
   1590     NULL,
   1591 #endif
   1592 #ifdef USE_LIBRTMP
   1593     &Curl_handler_rtmps,
   1594 #else
   1595     NULL,
   1596 #endif
   1597 #ifdef USE_LIBRTMP
   1598     &Curl_handler_rtmpt,
   1599 #else
   1600     NULL,
   1601 #endif
   1602     NULL, NULL, NULL,
   1603 #if !defined(CURL_DISABLE_LDAP) && \
   1604   !defined(CURL_DISABLE_LDAPS) && \
   1605   ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
   1606    (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
   1607     &Curl_handler_ldaps,
   1608 #else
   1609     NULL,
   1610 #endif
   1611 #if !defined(CURL_DISABLE_WEBSOCKETS) &&                \
   1612   defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
   1613     &Curl_handler_wss,
   1614 #else
   1615     NULL,
   1616 #endif
   1617 #if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
   1618     &Curl_handler_https,
   1619 #else
   1620     NULL,
   1621 #endif
   1622     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   1623 #ifndef CURL_DISABLE_RTSP
   1624     &Curl_handler_rtsp,
   1625 #else
   1626     NULL,
   1627 #endif
   1628 #if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \
   1629   defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4)
   1630     &Curl_handler_smbs,
   1631 #else
   1632     NULL,
   1633 #endif
   1634 #if defined(USE_SSH) && !defined(USE_WOLFSSH)
   1635     &Curl_handler_scp,
   1636 #else
   1637     NULL,
   1638 #endif
   1639     NULL, NULL, NULL,
   1640 #ifndef CURL_DISABLE_POP3
   1641     &Curl_handler_pop3,
   1642 #else
   1643     NULL,
   1644 #endif
   1645     NULL, NULL,
   1646 #ifdef USE_LIBRTMP
   1647     &Curl_handler_rtmp,
   1648 #else
   1649     NULL,
   1650 #endif
   1651     NULL, NULL, NULL,
   1652 #ifdef USE_LIBRTMP
   1653     &Curl_handler_rtmpte,
   1654 #else
   1655     NULL,
   1656 #endif
   1657     NULL, NULL, NULL,
   1658 #ifndef CURL_DISABLE_DICT
   1659     &Curl_handler_dict,
   1660 #else
   1661     NULL,
   1662 #endif
   1663     NULL, NULL, NULL,
   1664 #ifndef CURL_DISABLE_MQTT
   1665     &Curl_handler_mqtt,
   1666 #else
   1667     NULL,
   1668 #endif
   1669 #if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)
   1670     &Curl_handler_pop3s,
   1671 #else
   1672     NULL,
   1673 #endif
   1674 #if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)
   1675     &Curl_handler_imaps,
   1676 #else
   1677     NULL,
   1678 #endif
   1679     NULL,
   1680 #if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
   1681     &Curl_handler_ws,
   1682 #else
   1683     NULL,
   1684 #endif
   1685     NULL,
   1686 #ifdef USE_LIBRTMP
   1687     &Curl_handler_rtmpts,
   1688 #else
   1689     NULL,
   1690 #endif
   1691 #ifndef CURL_DISABLE_LDAP
   1692     &Curl_handler_ldap,
   1693 #else
   1694     NULL,
   1695 #endif
   1696     NULL, NULL,
   1697 #ifndef CURL_DISABLE_FTP
   1698     &Curl_handler_ftp,
   1699 #else
   1700     NULL,
   1701 #endif
   1702   };
   1703 
   1704   if(len && (len <= 7)) {
   1705     const char *s = scheme;
   1706     size_t l = len;
   1707     const struct Curl_handler *h;
   1708     unsigned int c = 978;
   1709     while(l) {
   1710       c <<= 5;
   1711       c += (unsigned int)Curl_raw_tolower(*s);
   1712       s++;
   1713       l--;
   1714     }
   1715 
   1716     h = protocols[c % 67];
   1717     if(h && curl_strnequal(scheme, h->scheme, len) && !h->scheme[len])
   1718       return h;
   1719   }
   1720   return NULL;
   1721 }
   1722 
   1723 static CURLcode findprotocol(struct Curl_easy *data,
   1724                              struct connectdata *conn,
   1725                              const char *protostr)
   1726 {
   1727   const struct Curl_handler *p = Curl_get_scheme_handler(protostr);
   1728 
   1729   if(p && /* Protocol found in table. Check if allowed */
   1730      (data->set.allowed_protocols & p->protocol)) {
   1731 
   1732     /* it is allowed for "normal" request, now do an extra check if this is
   1733        the result of a redirect */
   1734     if(data->state.this_is_a_follow &&
   1735        !(data->set.redir_protocols & p->protocol))
   1736       /* nope, get out */
   1737       ;
   1738     else {
   1739       /* Perform setup complement if some. */
   1740       conn->handler = conn->given = p;
   1741       /* 'port' and 'remote_port' are set in setup_connection_internals() */
   1742       return CURLE_OK;
   1743     }
   1744   }
   1745 
   1746   /* The protocol was not found in the table, but we do not have to assign it
   1747      to anything since it is already assigned to a dummy-struct in the
   1748      create_conn() function when the connectdata struct is allocated. */
   1749   failf(data, "Protocol \"%s\" %s%s", protostr,
   1750         p ? "disabled" : "not supported",
   1751         data->state.this_is_a_follow ? " (in redirect)":"");
   1752 
   1753   return CURLE_UNSUPPORTED_PROTOCOL;
   1754 }
   1755 
   1756 
   1757 CURLcode Curl_uc_to_curlcode(CURLUcode uc)
   1758 {
   1759   switch(uc) {
   1760   default:
   1761     return CURLE_URL_MALFORMAT;
   1762   case CURLUE_UNSUPPORTED_SCHEME:
   1763     return CURLE_UNSUPPORTED_PROTOCOL;
   1764   case CURLUE_OUT_OF_MEMORY:
   1765     return CURLE_OUT_OF_MEMORY;
   1766   case CURLUE_USER_NOT_ALLOWED:
   1767     return CURLE_LOGIN_DENIED;
   1768   }
   1769 }
   1770 
   1771 #ifdef USE_IPV6
   1772 /*
   1773  * If the URL was set with an IPv6 numerical address with a zone id part, set
   1774  * the scope_id based on that!
   1775  */
   1776 
   1777 static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
   1778                          struct connectdata *conn)
   1779 {
   1780   char *zoneid;
   1781   CURLUcode uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0);
   1782 #ifdef CURL_DISABLE_VERBOSE_STRINGS
   1783   (void)data;
   1784 #endif
   1785 
   1786   if(!uc && zoneid) {
   1787     const char *p = zoneid;
   1788     curl_off_t scope;
   1789     if(!curlx_str_number(&p, &scope, UINT_MAX))
   1790       /* A plain number, use it directly as a scope id. */
   1791       conn->scope_id = (unsigned int)scope;
   1792 #ifdef HAVE_IF_NAMETOINDEX
   1793     else {
   1794 #elif defined(_WIN32)
   1795     else if(Curl_if_nametoindex) {
   1796 #endif
   1797 
   1798 #if defined(HAVE_IF_NAMETOINDEX) || defined(_WIN32)
   1799       /* Zone identifier is not numeric */
   1800       unsigned int scopeidx = 0;
   1801 #ifdef HAVE_IF_NAMETOINDEX
   1802       scopeidx = if_nametoindex(zoneid);
   1803 #else
   1804       scopeidx = Curl_if_nametoindex(zoneid);
   1805 #endif
   1806       if(!scopeidx) {
   1807 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   1808         char buffer[STRERROR_LEN];
   1809         infof(data, "Invalid zoneid: %s; %s", zoneid,
   1810               Curl_strerror(errno, buffer, sizeof(buffer)));
   1811 #endif
   1812       }
   1813       else
   1814         conn->scope_id = scopeidx;
   1815     }
   1816 #endif /* HAVE_IF_NAMETOINDEX || _WIN32 */
   1817 
   1818     free(zoneid);
   1819   }
   1820 }
   1821 #else
   1822 #define zonefrom_url(a,b,c) Curl_nop_stmt
   1823 #endif
   1824 
   1825 /*
   1826  * Parse URL and fill in the relevant members of the connection struct.
   1827  */
   1828 static CURLcode parseurlandfillconn(struct Curl_easy *data,
   1829                                     struct connectdata *conn)
   1830 {
   1831   CURLcode result;
   1832   CURLU *uh;
   1833   CURLUcode uc;
   1834   char *hostname;
   1835   bool use_set_uh = (data->set.uh && !data->state.this_is_a_follow);
   1836 
   1837   up_free(data); /* cleanup previous leftovers first */
   1838 
   1839   /* parse the URL */
   1840   if(use_set_uh) {
   1841     uh = data->state.uh = curl_url_dup(data->set.uh);
   1842   }
   1843   else {
   1844     uh = data->state.uh = curl_url();
   1845   }
   1846 
   1847   if(!uh)
   1848     return CURLE_OUT_OF_MEMORY;
   1849 
   1850   if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
   1851      !Curl_is_absolute_url(data->state.url, NULL, 0, TRUE)) {
   1852     char *url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
   1853                         data->state.url);
   1854     if(!url)
   1855       return CURLE_OUT_OF_MEMORY;
   1856     if(data->state.url_alloc)
   1857       free(data->state.url);
   1858     data->state.url = url;
   1859     data->state.url_alloc = TRUE;
   1860   }
   1861 
   1862   if(!use_set_uh) {
   1863     char *newurl;
   1864     uc = curl_url_set(uh, CURLUPART_URL, data->state.url, (unsigned int)
   1865                       (CURLU_GUESS_SCHEME |
   1866                        CURLU_NON_SUPPORT_SCHEME |
   1867                        (data->set.disallow_username_in_url ?
   1868                         CURLU_DISALLOW_USER : 0) |
   1869                        (data->set.path_as_is ? CURLU_PATH_AS_IS : 0)));
   1870     if(uc) {
   1871       failf(data, "URL rejected: %s", curl_url_strerror(uc));
   1872       return Curl_uc_to_curlcode(uc);
   1873     }
   1874 
   1875     /* after it was parsed, get the generated normalized version */
   1876     uc = curl_url_get(uh, CURLUPART_URL, &newurl, 0);
   1877     if(uc)
   1878       return Curl_uc_to_curlcode(uc);
   1879     if(data->state.url_alloc)
   1880       free(data->state.url);
   1881     data->state.url = newurl;
   1882     data->state.url_alloc = TRUE;
   1883   }
   1884 
   1885   uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
   1886   if(uc)
   1887     return Curl_uc_to_curlcode(uc);
   1888 
   1889   uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
   1890   if(uc) {
   1891     if(!curl_strequal("file", data->state.up.scheme))
   1892       return CURLE_OUT_OF_MEMORY;
   1893   }
   1894   else if(strlen(data->state.up.hostname) > MAX_URL_LEN) {
   1895     failf(data, "Too long hostname (maximum is %d)", MAX_URL_LEN);
   1896     return CURLE_URL_MALFORMAT;
   1897   }
   1898   hostname = data->state.up.hostname;
   1899 
   1900   if(hostname && hostname[0] == '[') {
   1901     /* This looks like an IPv6 address literal. See if there is an address
   1902        scope. */
   1903     size_t hlen;
   1904     conn->bits.ipv6_ip = TRUE;
   1905     /* cut off the brackets! */
   1906     hostname++;
   1907     hlen = strlen(hostname);
   1908     hostname[hlen - 1] = 0;
   1909 
   1910     zonefrom_url(uh, data, conn);
   1911   }
   1912 
   1913   /* make sure the connect struct gets its own copy of the hostname */
   1914   conn->host.rawalloc = strdup(hostname ? hostname : "");
   1915   if(!conn->host.rawalloc)
   1916     return CURLE_OUT_OF_MEMORY;
   1917   conn->host.name = conn->host.rawalloc;
   1918 
   1919   /*************************************************************
   1920    * IDN-convert the hostnames
   1921    *************************************************************/
   1922   result = Curl_idnconvert_hostname(&conn->host);
   1923   if(result)
   1924     return result;
   1925 
   1926 #ifndef CURL_DISABLE_HSTS
   1927   /* HSTS upgrade */
   1928   if(data->hsts && curl_strequal("http", data->state.up.scheme)) {
   1929     /* This MUST use the IDN decoded name */
   1930     if(Curl_hsts(data->hsts, conn->host.name, strlen(conn->host.name), TRUE)) {
   1931       char *url;
   1932       Curl_safefree(data->state.up.scheme);
   1933       uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0);
   1934       if(uc)
   1935         return Curl_uc_to_curlcode(uc);
   1936       if(data->state.url_alloc)
   1937         Curl_safefree(data->state.url);
   1938       /* after update, get the updated version */
   1939       uc = curl_url_get(uh, CURLUPART_URL, &url, 0);
   1940       if(uc)
   1941         return Curl_uc_to_curlcode(uc);
   1942       uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
   1943       if(uc) {
   1944         free(url);
   1945         return Curl_uc_to_curlcode(uc);
   1946       }
   1947       data->state.url = url;
   1948       data->state.url_alloc = TRUE;
   1949       infof(data, "Switched from HTTP to HTTPS due to HSTS => %s",
   1950             data->state.url);
   1951     }
   1952   }
   1953 #endif
   1954 
   1955   result = findprotocol(data, conn, data->state.up.scheme);
   1956   if(result)
   1957     return result;
   1958 
   1959   /*
   1960    * username and password set with their own options override the credentials
   1961    * possibly set in the URL, but netrc does not.
   1962    */
   1963   if(!data->state.aptr.passwd || (data->state.creds_from != CREDS_OPTION)) {
   1964     uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
   1965     if(!uc) {
   1966       char *decoded;
   1967       result = Curl_urldecode(data->state.up.password, 0, &decoded, NULL,
   1968                               conn->handler->flags&PROTOPT_USERPWDCTRL ?
   1969                               REJECT_ZERO : REJECT_CTRL);
   1970       if(result)
   1971         return result;
   1972       conn->passwd = decoded;
   1973       result = Curl_setstropt(&data->state.aptr.passwd, decoded);
   1974       if(result)
   1975         return result;
   1976       data->state.creds_from = CREDS_URL;
   1977     }
   1978     else if(uc != CURLUE_NO_PASSWORD)
   1979       return Curl_uc_to_curlcode(uc);
   1980   }
   1981 
   1982   if(!data->state.aptr.user || (data->state.creds_from != CREDS_OPTION)) {
   1983     /* we do not use the URL API's URL decoder option here since it rejects
   1984        control codes and we want to allow them for some schemes in the user
   1985        and password fields */
   1986     uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0);
   1987     if(!uc) {
   1988       char *decoded;
   1989       result = Curl_urldecode(data->state.up.user, 0, &decoded, NULL,
   1990                               conn->handler->flags&PROTOPT_USERPWDCTRL ?
   1991                               REJECT_ZERO : REJECT_CTRL);
   1992       if(result)
   1993         return result;
   1994       conn->user = decoded;
   1995       result = Curl_setstropt(&data->state.aptr.user, decoded);
   1996       data->state.creds_from = CREDS_URL;
   1997     }
   1998     else if(uc != CURLUE_NO_USER)
   1999       return Curl_uc_to_curlcode(uc);
   2000     if(result)
   2001       return result;
   2002   }
   2003 
   2004   uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options,
   2005                     CURLU_URLDECODE);
   2006   if(!uc) {
   2007     conn->options = strdup(data->state.up.options);
   2008     if(!conn->options)
   2009       return CURLE_OUT_OF_MEMORY;
   2010   }
   2011   else if(uc != CURLUE_NO_OPTIONS)
   2012     return Curl_uc_to_curlcode(uc);
   2013 
   2014   uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path,
   2015                     CURLU_URLENCODE);
   2016   if(uc)
   2017     return Curl_uc_to_curlcode(uc);
   2018 
   2019   uc = curl_url_get(uh, CURLUPART_PORT, &data->state.up.port,
   2020                     CURLU_DEFAULT_PORT);
   2021   if(uc) {
   2022     if(!curl_strequal("file", data->state.up.scheme))
   2023       return CURLE_OUT_OF_MEMORY;
   2024   }
   2025   else {
   2026     curl_off_t port;
   2027     bool valid = TRUE;
   2028     if(data->set.use_port && data->state.allow_port)
   2029       port = data->set.use_port;
   2030     else {
   2031       const char *p = data->state.up.port;
   2032       if(curlx_str_number(&p, &port, 0xffff))
   2033         valid = FALSE;
   2034     }
   2035     if(valid)
   2036       conn->primary.remote_port = conn->remote_port = (unsigned short)port;
   2037   }
   2038 
   2039   (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
   2040 
   2041 #ifdef USE_IPV6
   2042   if(data->set.scope_id)
   2043     /* Override any scope that was set above.  */
   2044     conn->scope_id = data->set.scope_id;
   2045 #endif
   2046 
   2047   return CURLE_OK;
   2048 }
   2049 
   2050 
   2051 /*
   2052  * If we are doing a resumed transfer, we need to setup our stuff
   2053  * properly.
   2054  */
   2055 static CURLcode setup_range(struct Curl_easy *data)
   2056 {
   2057   struct UrlState *s = &data->state;
   2058   s->resume_from = data->set.set_resume_from;
   2059   if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
   2060     if(s->rangestringalloc)
   2061       free(s->range);
   2062 
   2063     if(s->resume_from)
   2064       s->range = aprintf("%" FMT_OFF_T "-", s->resume_from);
   2065     else
   2066       s->range = strdup(data->set.str[STRING_SET_RANGE]);
   2067 
   2068     if(!s->range)
   2069       return CURLE_OUT_OF_MEMORY;
   2070 
   2071     s->rangestringalloc = TRUE;
   2072 
   2073     /* tell ourselves to fetch this range */
   2074     s->use_range = TRUE;        /* enable range download */
   2075   }
   2076   else
   2077     s->use_range = FALSE; /* disable range download */
   2078 
   2079   return CURLE_OK;
   2080 }
   2081 
   2082 
   2083 /*
   2084  * setup_connection_internals() -
   2085  *
   2086  * Setup connection internals specific to the requested protocol in the
   2087  * Curl_easy. This is inited and setup before the connection is made but
   2088  * is about the particular protocol that is to be used.
   2089  *
   2090  * This MUST get called after proxy magic has been figured out.
   2091  */
   2092 static CURLcode setup_connection_internals(struct Curl_easy *data,
   2093                                            struct connectdata *conn)
   2094 {
   2095   const struct Curl_handler *p;
   2096   const char *hostname;
   2097   int port;
   2098   CURLcode result;
   2099 
   2100   /* Perform setup complement if some. */
   2101   p = conn->handler;
   2102 
   2103   if(p->setup_connection) {
   2104     result = (*p->setup_connection)(data, conn);
   2105 
   2106     if(result)
   2107       return result;
   2108 
   2109     p = conn->handler;              /* May have changed. */
   2110   }
   2111 
   2112   if(conn->primary.remote_port < 0)
   2113     /* we check for -1 here since if proxy was detected already, this was
   2114        likely already set to the proxy port */
   2115     conn->primary.remote_port = p->defport;
   2116 
   2117   /* Now create the destination name */
   2118 #ifndef CURL_DISABLE_PROXY
   2119   if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
   2120     hostname = conn->http_proxy.host.name;
   2121     port = conn->primary.remote_port;
   2122   }
   2123   else
   2124 #endif
   2125   {
   2126     port = conn->remote_port;
   2127     if(conn->bits.conn_to_host)
   2128       hostname = conn->conn_to_host.name;
   2129     else
   2130       hostname = conn->host.name;
   2131   }
   2132 
   2133 #ifdef USE_IPV6
   2134   conn->destination = aprintf("%u/%d/%s", conn->scope_id, port, hostname);
   2135 #else
   2136   conn->destination = aprintf("%d/%s", port, hostname);
   2137 #endif
   2138   if(!conn->destination)
   2139     return CURLE_OUT_OF_MEMORY;
   2140 
   2141   Curl_strntolower(conn->destination, conn->destination,
   2142                    strlen(conn->destination));
   2143 
   2144   return CURLE_OK;
   2145 }
   2146 
   2147 
   2148 #ifndef CURL_DISABLE_PROXY
   2149 
   2150 #ifndef CURL_DISABLE_HTTP
   2151 /****************************************************************
   2152 * Detect what (if any) proxy to use. Remember that this selects a host
   2153 * name and is not limited to HTTP proxies only.
   2154 * The returned pointer must be freed by the caller (unless NULL)
   2155 ****************************************************************/
   2156 static char *detect_proxy(struct Curl_easy *data,
   2157                           struct connectdata *conn)
   2158 {
   2159   char *proxy = NULL;
   2160 
   2161   /* If proxy was not specified, we check for default proxy environment
   2162    * variables, to enable i.e Lynx compliance:
   2163    *
   2164    * http_proxy=http://some.server.dom:port/
   2165    * https_proxy=http://some.server.dom:port/
   2166    * ftp_proxy=http://some.server.dom:port/
   2167    * no_proxy=domain1.dom,host.domain2.dom
   2168    *   (a comma-separated list of hosts which should
   2169    *   not be proxied, or an asterisk to override
   2170    *   all proxy variables)
   2171    * all_proxy=http://some.server.dom:port/
   2172    *   (seems to exist for the CERN www lib. Probably
   2173    *   the first to check for.)
   2174    *
   2175    * For compatibility, the all-uppercase versions of these variables are
   2176    * checked if the lowercase versions do not exist.
   2177    */
   2178   char proxy_env[20];
   2179   const char *envp = proxy_env;
   2180 #ifdef CURL_DISABLE_VERBOSE_STRINGS
   2181   (void)data;
   2182 #endif
   2183 
   2184   msnprintf(proxy_env, sizeof(proxy_env), "%s_proxy", conn->handler->scheme);
   2185 
   2186   /* read the protocol proxy: */
   2187   proxy = curl_getenv(proxy_env);
   2188 
   2189   /*
   2190    * We do not try the uppercase version of HTTP_PROXY because of
   2191    * security reasons:
   2192    *
   2193    * When curl is used in a webserver application
   2194    * environment (cgi or php), this environment variable can
   2195    * be controlled by the web server user by setting the
   2196    * http header 'Proxy:' to some value.
   2197    *
   2198    * This can cause 'internal' http/ftp requests to be
   2199    * arbitrarily redirected by any external attacker.
   2200    */
   2201   if(!proxy && !curl_strequal("http_proxy", proxy_env)) {
   2202     /* There was no lowercase variable, try the uppercase version: */
   2203     Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
   2204     proxy = curl_getenv(proxy_env);
   2205   }
   2206 
   2207   if(!proxy) {
   2208 #ifndef CURL_DISABLE_WEBSOCKETS
   2209     /* websocket proxy fallbacks */
   2210     if(curl_strequal("ws_proxy", proxy_env)) {
   2211       proxy = curl_getenv("http_proxy");
   2212     }
   2213     else if(curl_strequal("wss_proxy", proxy_env)) {
   2214       proxy = curl_getenv("https_proxy");
   2215       if(!proxy)
   2216         proxy = curl_getenv("HTTPS_PROXY");
   2217     }
   2218     if(!proxy) {
   2219 #endif
   2220       envp = "all_proxy";
   2221       proxy = curl_getenv(envp); /* default proxy to use */
   2222       if(!proxy) {
   2223         envp = "ALL_PROXY";
   2224         proxy = curl_getenv(envp);
   2225       }
   2226 #ifndef CURL_DISABLE_WEBSOCKETS
   2227     }
   2228 #endif
   2229   }
   2230   if(proxy)
   2231     infof(data, "Uses proxy env variable %s == '%s'", envp, proxy);
   2232 
   2233   return proxy;
   2234 }
   2235 #endif /* CURL_DISABLE_HTTP */
   2236 
   2237 /*
   2238  * If this is supposed to use a proxy, we need to figure out the proxy
   2239  * hostname, so that we can reuse an existing connection
   2240  * that may exist registered to the same proxy host.
   2241  */
   2242 static CURLcode parse_proxy(struct Curl_easy *data,
   2243                             struct connectdata *conn, char *proxy,
   2244                             curl_proxytype proxytype)
   2245 {
   2246   char *portptr = NULL;
   2247   int port = -1;
   2248   char *proxyuser = NULL;
   2249   char *proxypasswd = NULL;
   2250   char *host = NULL;
   2251   bool sockstype;
   2252   CURLUcode uc;
   2253   struct proxy_info *proxyinfo;
   2254   CURLU *uhp = curl_url();
   2255   CURLcode result = CURLE_OK;
   2256   char *scheme = NULL;
   2257 #ifdef USE_UNIX_SOCKETS
   2258   char *path = NULL;
   2259   bool is_unix_proxy = FALSE;
   2260 #endif
   2261 
   2262 
   2263   if(!uhp) {
   2264     result = CURLE_OUT_OF_MEMORY;
   2265     goto error;
   2266   }
   2267 
   2268   /* When parsing the proxy, allowing non-supported schemes since we have
   2269      these made up ones for proxies. Guess scheme for URLs without it. */
   2270   uc = curl_url_set(uhp, CURLUPART_URL, proxy,
   2271                     CURLU_NON_SUPPORT_SCHEME|CURLU_GUESS_SCHEME);
   2272   if(!uc) {
   2273     /* parsed okay as a URL */
   2274     uc = curl_url_get(uhp, CURLUPART_SCHEME, &scheme, 0);
   2275     if(uc) {
   2276       result = CURLE_OUT_OF_MEMORY;
   2277       goto error;
   2278     }
   2279 
   2280     if(curl_strequal("https", scheme)) {
   2281       if(proxytype != CURLPROXY_HTTPS2)
   2282         proxytype = CURLPROXY_HTTPS;
   2283       else
   2284         proxytype = CURLPROXY_HTTPS2;
   2285     }
   2286     else if(curl_strequal("socks5h", scheme))
   2287       proxytype = CURLPROXY_SOCKS5_HOSTNAME;
   2288     else if(curl_strequal("socks5", scheme))
   2289       proxytype = CURLPROXY_SOCKS5;
   2290     else if(curl_strequal("socks4a", scheme))
   2291       proxytype = CURLPROXY_SOCKS4A;
   2292     else if(curl_strequal("socks4", scheme) ||
   2293             curl_strequal("socks", scheme))
   2294       proxytype = CURLPROXY_SOCKS4;
   2295     else if(curl_strequal("http", scheme))
   2296       ; /* leave it as HTTP or HTTP/1.0 */
   2297     else {
   2298       /* Any other xxx:// reject! */
   2299       failf(data, "Unsupported proxy scheme for \'%s\'", proxy);
   2300       result = CURLE_COULDNT_CONNECT;
   2301       goto error;
   2302     }
   2303   }
   2304   else {
   2305     failf(data, "Unsupported proxy syntax in \'%s\': %s", proxy,
   2306           curl_url_strerror(uc));
   2307     result = CURLE_COULDNT_RESOLVE_PROXY;
   2308     goto error;
   2309   }
   2310 
   2311 #ifdef USE_SSL
   2312   if(!Curl_ssl_supports(data, SSLSUPP_HTTPS_PROXY))
   2313 #endif
   2314     if(IS_HTTPS_PROXY(proxytype)) {
   2315       failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
   2316             "HTTPS-proxy support.", proxy);
   2317       result = CURLE_NOT_BUILT_IN;
   2318       goto error;
   2319     }
   2320 
   2321   sockstype =
   2322     proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
   2323     proxytype == CURLPROXY_SOCKS5 ||
   2324     proxytype == CURLPROXY_SOCKS4A ||
   2325     proxytype == CURLPROXY_SOCKS4;
   2326 
   2327   proxyinfo = sockstype ? &conn->socks_proxy : &conn->http_proxy;
   2328   proxyinfo->proxytype = (unsigned char)proxytype;
   2329 
   2330   /* Is there a username and password given in this proxy url? */
   2331   uc = curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE);
   2332   if(uc && (uc != CURLUE_NO_USER))
   2333     goto error;
   2334   uc = curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE);
   2335   if(uc && (uc != CURLUE_NO_PASSWORD))
   2336     goto error;
   2337 
   2338   if(proxyuser || proxypasswd) {
   2339     free(proxyinfo->user);
   2340     proxyinfo->user = proxyuser;
   2341     result = Curl_setstropt(&data->state.aptr.proxyuser, proxyuser);
   2342     proxyuser = NULL;
   2343     if(result)
   2344       goto error;
   2345     Curl_safefree(proxyinfo->passwd);
   2346     if(!proxypasswd) {
   2347       proxypasswd = strdup("");
   2348       if(!proxypasswd) {
   2349         result = CURLE_OUT_OF_MEMORY;
   2350         goto error;
   2351       }
   2352     }
   2353     proxyinfo->passwd = proxypasswd;
   2354     result = Curl_setstropt(&data->state.aptr.proxypasswd, proxypasswd);
   2355     proxypasswd = NULL;
   2356     if(result)
   2357       goto error;
   2358     conn->bits.proxy_user_passwd = TRUE; /* enable it */
   2359   }
   2360 
   2361   (void)curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
   2362 
   2363   if(portptr) {
   2364     curl_off_t num;
   2365     const char *p = portptr;
   2366     if(!curlx_str_number(&p, &num, 0xffff))
   2367       port = (int)num;
   2368     free(portptr);
   2369   }
   2370   else {
   2371     if(data->set.proxyport)
   2372       /* None given in the proxy string, then get the default one if it is
   2373          given */
   2374       port = (int)data->set.proxyport;
   2375     else {
   2376       if(IS_HTTPS_PROXY(proxytype))
   2377         port = CURL_DEFAULT_HTTPS_PROXY_PORT;
   2378       else
   2379         port = CURL_DEFAULT_PROXY_PORT;
   2380     }
   2381   }
   2382   if(port >= 0) {
   2383     proxyinfo->port = port;
   2384     if(conn->primary.remote_port < 0 || sockstype ||
   2385        !conn->socks_proxy.host.rawalloc)
   2386       conn->primary.remote_port = port;
   2387   }
   2388 
   2389   /* now, clone the proxy hostname */
   2390   uc = curl_url_get(uhp, CURLUPART_HOST, &host, CURLU_URLDECODE);
   2391   if(uc) {
   2392     result = CURLE_OUT_OF_MEMORY;
   2393     goto error;
   2394   }
   2395 #ifdef USE_UNIX_SOCKETS
   2396   if(sockstype && curl_strequal(UNIX_SOCKET_PREFIX, host)) {
   2397     uc = curl_url_get(uhp, CURLUPART_PATH, &path, CURLU_URLDECODE);
   2398     if(uc) {
   2399       result = CURLE_OUT_OF_MEMORY;
   2400       goto error;
   2401     }
   2402     /* path will be "/", if no path was found */
   2403     if(strcmp("/", path)) {
   2404       is_unix_proxy = TRUE;
   2405       free(host);
   2406       host = aprintf(UNIX_SOCKET_PREFIX"%s", path);
   2407       if(!host) {
   2408         result = CURLE_OUT_OF_MEMORY;
   2409         goto error;
   2410       }
   2411       free(proxyinfo->host.rawalloc);
   2412       proxyinfo->host.rawalloc = host;
   2413       proxyinfo->host.name = host;
   2414       host = NULL;
   2415     }
   2416   }
   2417 
   2418   if(!is_unix_proxy) {
   2419 #endif
   2420     free(proxyinfo->host.rawalloc);
   2421     proxyinfo->host.rawalloc = host;
   2422     if(host[0] == '[') {
   2423       /* this is a numerical IPv6, strip off the brackets */
   2424       size_t len = strlen(host);
   2425       host[len-1] = 0; /* clear the trailing bracket */
   2426       host++;
   2427       zonefrom_url(uhp, data, conn);
   2428     }
   2429     proxyinfo->host.name = host;
   2430     host = NULL;
   2431 #ifdef USE_UNIX_SOCKETS
   2432   }
   2433 #endif
   2434 
   2435 error:
   2436   free(proxyuser);
   2437   free(proxypasswd);
   2438   free(host);
   2439   free(scheme);
   2440 #ifdef USE_UNIX_SOCKETS
   2441   free(path);
   2442 #endif
   2443   curl_url_cleanup(uhp);
   2444   return result;
   2445 }
   2446 
   2447 /*
   2448  * Extract the user and password from the authentication string
   2449  */
   2450 static CURLcode parse_proxy_auth(struct Curl_easy *data,
   2451                                  struct connectdata *conn)
   2452 {
   2453   const char *proxyuser = data->state.aptr.proxyuser ?
   2454     data->state.aptr.proxyuser : "";
   2455   const char *proxypasswd = data->state.aptr.proxypasswd ?
   2456     data->state.aptr.proxypasswd : "";
   2457   CURLcode result = CURLE_OUT_OF_MEMORY;
   2458 
   2459   conn->http_proxy.user = strdup(proxyuser);
   2460   if(conn->http_proxy.user) {
   2461     conn->http_proxy.passwd = strdup(proxypasswd);
   2462     if(conn->http_proxy.passwd)
   2463       result = CURLE_OK;
   2464     else
   2465       Curl_safefree(conn->http_proxy.user);
   2466   }
   2467   return result;
   2468 }
   2469 
   2470 /* create_conn helper to parse and init proxy values. to be called after Unix
   2471    socket init but before any proxy vars are evaluated. */
   2472 static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
   2473                                               struct connectdata *conn)
   2474 {
   2475   char *proxy = NULL;
   2476   char *socksproxy = NULL;
   2477   char *no_proxy = NULL;
   2478   CURLcode result = CURLE_OK;
   2479 
   2480   /*************************************************************
   2481    * Extract the user and password from the authentication string
   2482    *************************************************************/
   2483   if(conn->bits.proxy_user_passwd) {
   2484     result = parse_proxy_auth(data, conn);
   2485     if(result)
   2486       goto out;
   2487   }
   2488 
   2489   /*************************************************************
   2490    * Detect what (if any) proxy to use
   2491    *************************************************************/
   2492   if(data->set.str[STRING_PROXY]) {
   2493     proxy = strdup(data->set.str[STRING_PROXY]);
   2494     /* if global proxy is set, this is it */
   2495     if(!proxy) {
   2496       failf(data, "memory shortage");
   2497       result = CURLE_OUT_OF_MEMORY;
   2498       goto out;
   2499     }
   2500   }
   2501 
   2502   if(data->set.str[STRING_PRE_PROXY]) {
   2503     socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
   2504     /* if global socks proxy is set, this is it */
   2505     if(!socksproxy) {
   2506       failf(data, "memory shortage");
   2507       result = CURLE_OUT_OF_MEMORY;
   2508       goto out;
   2509     }
   2510   }
   2511 
   2512   if(!data->set.str[STRING_NOPROXY]) {
   2513     const char *p = "no_proxy";
   2514     no_proxy = curl_getenv(p);
   2515     if(!no_proxy) {
   2516       p = "NO_PROXY";
   2517       no_proxy = curl_getenv(p);
   2518     }
   2519     if(no_proxy) {
   2520       infof(data, "Uses proxy env variable %s == '%s'", p, no_proxy);
   2521     }
   2522   }
   2523 
   2524   if(Curl_check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
   2525                         data->set.str[STRING_NOPROXY] : no_proxy)) {
   2526     Curl_safefree(proxy);
   2527     Curl_safefree(socksproxy);
   2528   }
   2529 #ifndef CURL_DISABLE_HTTP
   2530   else if(!proxy && !socksproxy)
   2531     /* if the host is not in the noproxy list, detect proxy. */
   2532     proxy = detect_proxy(data, conn);
   2533 #endif /* CURL_DISABLE_HTTP */
   2534   Curl_safefree(no_proxy);
   2535 
   2536 #ifdef USE_UNIX_SOCKETS
   2537   /* For the time being do not mix proxy and Unix domain sockets. See #1274 */
   2538   if(proxy && conn->unix_domain_socket) {
   2539     free(proxy);
   2540     proxy = NULL;
   2541   }
   2542 #endif
   2543 
   2544   if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
   2545     free(proxy);  /* Do not bother with an empty proxy string or if the
   2546                      protocol does not work with network */
   2547     proxy = NULL;
   2548   }
   2549   if(socksproxy && (!*socksproxy ||
   2550                     (conn->handler->flags & PROTOPT_NONETWORK))) {
   2551     free(socksproxy);  /* Do not bother with an empty socks proxy string or if
   2552                           the protocol does not work with network */
   2553     socksproxy = NULL;
   2554   }
   2555 
   2556   /***********************************************************************
   2557    * If this is supposed to use a proxy, we need to figure out the proxy host
   2558    * name, proxy type and port number, so that we can reuse an existing
   2559    * connection that may exist registered to the same proxy host.
   2560    ***********************************************************************/
   2561   if(proxy || socksproxy) {
   2562     curl_proxytype ptype = (curl_proxytype)conn->http_proxy.proxytype;
   2563     if(proxy) {
   2564       result = parse_proxy(data, conn, proxy, ptype);
   2565       Curl_safefree(proxy); /* parse_proxy copies the proxy string */
   2566       if(result)
   2567         goto out;
   2568     }
   2569 
   2570     if(socksproxy) {
   2571       result = parse_proxy(data, conn, socksproxy, ptype);
   2572       /* parse_proxy copies the socks proxy string */
   2573       Curl_safefree(socksproxy);
   2574       if(result)
   2575         goto out;
   2576     }
   2577 
   2578     if(conn->http_proxy.host.rawalloc) {
   2579 #ifdef CURL_DISABLE_HTTP
   2580       /* asking for an HTTP proxy is a bit funny when HTTP is disabled... */
   2581       result = CURLE_UNSUPPORTED_PROTOCOL;
   2582       goto out;
   2583 #else
   2584       /* force this connection's protocol to become HTTP if compatible */
   2585       if(!(conn->handler->protocol & PROTO_FAMILY_HTTP)) {
   2586         if((conn->handler->flags & PROTOPT_PROXY_AS_HTTP) &&
   2587            !conn->bits.tunnel_proxy)
   2588           conn->handler = &Curl_handler_http;
   2589         else
   2590           /* if not converting to HTTP over the proxy, enforce tunneling */
   2591           conn->bits.tunnel_proxy = TRUE;
   2592       }
   2593       conn->bits.httpproxy = TRUE;
   2594 #endif
   2595     }
   2596     else {
   2597       conn->bits.httpproxy = FALSE; /* not an HTTP proxy */
   2598       conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
   2599     }
   2600 
   2601     if(conn->socks_proxy.host.rawalloc) {
   2602       if(!conn->http_proxy.host.rawalloc) {
   2603         /* once a socks proxy */
   2604         if(!conn->socks_proxy.user) {
   2605           conn->socks_proxy.user = conn->http_proxy.user;
   2606           conn->http_proxy.user = NULL;
   2607           free(conn->socks_proxy.passwd);
   2608           conn->socks_proxy.passwd = conn->http_proxy.passwd;
   2609           conn->http_proxy.passwd = NULL;
   2610         }
   2611       }
   2612       conn->bits.socksproxy = TRUE;
   2613     }
   2614     else
   2615       conn->bits.socksproxy = FALSE; /* not a socks proxy */
   2616   }
   2617   else {
   2618     conn->bits.socksproxy = FALSE;
   2619     conn->bits.httpproxy = FALSE;
   2620   }
   2621   conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
   2622 
   2623   if(!conn->bits.proxy) {
   2624     /* we are not using the proxy after all... */
   2625     conn->bits.proxy = FALSE;
   2626     conn->bits.httpproxy = FALSE;
   2627     conn->bits.socksproxy = FALSE;
   2628     conn->bits.proxy_user_passwd = FALSE;
   2629     conn->bits.tunnel_proxy = FALSE;
   2630     /* CURLPROXY_HTTPS does not have its own flag in conn->bits, yet we need
   2631        to signal that CURLPROXY_HTTPS is not used for this connection */
   2632     conn->http_proxy.proxytype = CURLPROXY_HTTP;
   2633   }
   2634 
   2635 out:
   2636 
   2637   free(socksproxy);
   2638   free(proxy);
   2639   return result;
   2640 }
   2641 #endif /* CURL_DISABLE_PROXY */
   2642 
   2643 /*
   2644  * Curl_parse_login_details()
   2645  *
   2646  * This is used to parse a login string for username, password and options in
   2647  * the following formats:
   2648  *
   2649  *   user
   2650  *   user:password
   2651  *   user:password;options
   2652  *   user;options
   2653  *   user;options:password
   2654  *   :password
   2655  *   :password;options
   2656  *   ;options
   2657  *   ;options:password
   2658  *
   2659  * Parameters:
   2660  *
   2661  * login    [in]     - login string.
   2662  * len      [in]     - length of the login string.
   2663  * userp    [in/out] - address where a pointer to newly allocated memory
   2664  *                     holding the user will be stored upon completion.
   2665  * passwdp  [in/out] - address where a pointer to newly allocated memory
   2666  *                     holding the password will be stored upon completion.
   2667  * optionsp [in/out] - OPTIONAL address where a pointer to newly allocated
   2668  *                     memory holding the options will be stored upon
   2669  *                     completion.
   2670  *
   2671  * Returns CURLE_OK on success.
   2672  */
   2673 CURLcode Curl_parse_login_details(const char *login, const size_t len,
   2674                                   char **userp, char **passwdp,
   2675                                   char **optionsp)
   2676 {
   2677   char *ubuf = NULL;
   2678   char *pbuf = NULL;
   2679   const char *psep = NULL;
   2680   const char *osep = NULL;
   2681   size_t ulen;
   2682   size_t plen;
   2683   size_t olen;
   2684 
   2685   DEBUGASSERT(userp);
   2686   DEBUGASSERT(passwdp);
   2687 
   2688   /* Attempt to find the password separator */
   2689   psep = memchr(login, ':', len);
   2690 
   2691   /* Attempt to find the options separator */
   2692   if(optionsp)
   2693     osep = memchr(login, ';', len);
   2694 
   2695   /* Calculate the portion lengths */
   2696   ulen = (psep ?
   2697           (size_t)(osep && psep > osep ? osep - login : psep - login) :
   2698           (osep ? (size_t)(osep - login) : len));
   2699   plen = (psep ?
   2700           (osep && osep > psep ? (size_t)(osep - psep) :
   2701            (size_t)(login + len - psep)) - 1 : 0);
   2702   olen = (osep ?
   2703           (psep && psep > osep ? (size_t)(psep - osep) :
   2704            (size_t)(login + len - osep)) - 1 : 0);
   2705 
   2706   /* Clone the user portion buffer, which can be zero length */
   2707   ubuf = Curl_memdup0(login, ulen);
   2708   if(!ubuf)
   2709     goto error;
   2710 
   2711   /* Clone the password portion buffer */
   2712   if(psep) {
   2713     pbuf = Curl_memdup0(&psep[1], plen);
   2714     if(!pbuf)
   2715       goto error;
   2716   }
   2717 
   2718   /* Allocate the options portion buffer */
   2719   if(optionsp) {
   2720     char *obuf = NULL;
   2721     if(olen) {
   2722       obuf = Curl_memdup0(&osep[1], olen);
   2723       if(!obuf)
   2724         goto error;
   2725     }
   2726     *optionsp = obuf;
   2727   }
   2728   *userp = ubuf;
   2729   *passwdp = pbuf;
   2730   return CURLE_OK;
   2731 error:
   2732   free(ubuf);
   2733   free(pbuf);
   2734   return CURLE_OUT_OF_MEMORY;
   2735 }
   2736 
   2737 /*************************************************************
   2738  * Figure out the remote port number and fix it in the URL
   2739  *
   2740  * No matter if we use a proxy or not, we have to figure out the remote
   2741  * port number of various reasons.
   2742  *
   2743  * The port number embedded in the URL is replaced, if necessary.
   2744  *************************************************************/
   2745 static CURLcode parse_remote_port(struct Curl_easy *data,
   2746                                   struct connectdata *conn)
   2747 {
   2748 
   2749   if(data->set.use_port && data->state.allow_port) {
   2750     /* if set, we use this instead of the port possibly given in the URL */
   2751     char portbuf[16];
   2752     CURLUcode uc;
   2753     conn->remote_port = data->set.use_port;
   2754     msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port);
   2755     uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
   2756     if(uc)
   2757       return CURLE_OUT_OF_MEMORY;
   2758   }
   2759 
   2760   return CURLE_OK;
   2761 }
   2762 
   2763 #ifndef CURL_DISABLE_NETRC
   2764 static bool str_has_ctrl(const char *input)
   2765 {
   2766   if(input) {
   2767     const unsigned char *str = (const unsigned char *)input;
   2768     while(*str) {
   2769       if(*str < 0x20)
   2770         return TRUE;
   2771       str++;
   2772     }
   2773   }
   2774   return FALSE;
   2775 }
   2776 #endif
   2777 
   2778 /*
   2779  * Override the login details from the URL with that in the CURLOPT_USERPWD
   2780  * option or a .netrc file, if applicable.
   2781  */
   2782 static CURLcode override_login(struct Curl_easy *data,
   2783                                struct connectdata *conn)
   2784 {
   2785   CURLUcode uc;
   2786   char **userp = &conn->user;
   2787   char **passwdp = &conn->passwd;
   2788   char **optionsp = &conn->options;
   2789 
   2790   if(data->set.str[STRING_OPTIONS]) {
   2791     free(*optionsp);
   2792     *optionsp = strdup(data->set.str[STRING_OPTIONS]);
   2793     if(!*optionsp)
   2794       return CURLE_OUT_OF_MEMORY;
   2795   }
   2796 
   2797 #ifndef CURL_DISABLE_NETRC
   2798   if(data->set.use_netrc == CURL_NETRC_REQUIRED) {
   2799     Curl_safefree(*userp);
   2800     Curl_safefree(*passwdp);
   2801   }
   2802   conn->bits.netrc = FALSE;
   2803   if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) {
   2804     bool url_provided = FALSE;
   2805 
   2806     if(data->state.aptr.user &&
   2807        (data->state.creds_from != CREDS_NETRC)) {
   2808       /* there was a username with a length in the URL. Use the URL decoded
   2809          version */
   2810       userp = &data->state.aptr.user;
   2811       url_provided = TRUE;
   2812     }
   2813 
   2814     if(!*passwdp) {
   2815       NETRCcode ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
   2816                                       userp, passwdp,
   2817                                       data->set.str[STRING_NETRC_FILE]);
   2818       if(ret && ((ret == NETRC_NO_MATCH) ||
   2819                  (data->set.use_netrc == CURL_NETRC_OPTIONAL))) {
   2820         infof(data, "Couldn't find host %s in the %s file; using defaults",
   2821               conn->host.name,
   2822               (data->set.str[STRING_NETRC_FILE] ?
   2823                data->set.str[STRING_NETRC_FILE] : ".netrc"));
   2824       }
   2825       else if(ret) {
   2826         const char *m = Curl_netrc_strerror(ret);
   2827         failf(data, ".netrc error: %s", m);
   2828         return CURLE_READ_ERROR;
   2829       }
   2830       else {
   2831         if(!(conn->handler->flags&PROTOPT_USERPWDCTRL)) {
   2832           /* if the protocol can't handle control codes in credentials, make
   2833              sure there are none */
   2834           if(str_has_ctrl(*userp) || str_has_ctrl(*passwdp)) {
   2835             failf(data, "control code detected in .netrc credentials");
   2836             return CURLE_READ_ERROR;
   2837           }
   2838         }
   2839         /* set bits.netrc TRUE to remember that we got the name from a .netrc
   2840            file, so that it is safe to use even if we followed a Location: to a
   2841            different host or similar. */
   2842         conn->bits.netrc = TRUE;
   2843       }
   2844     }
   2845     if(url_provided) {
   2846       free(conn->user);
   2847       conn->user = strdup(*userp);
   2848       if(!conn->user)
   2849         return CURLE_OUT_OF_MEMORY;
   2850     }
   2851     /* no user was set but a password, set a blank user */
   2852     if(!*userp && *passwdp) {
   2853       *userp = strdup("");
   2854       if(!*userp)
   2855         return CURLE_OUT_OF_MEMORY;
   2856     }
   2857   }
   2858 #endif
   2859 
   2860   /* for updated strings, we update them in the URL */
   2861   if(*userp) {
   2862     CURLcode result;
   2863     if(data->state.aptr.user != *userp) {
   2864       /* nothing to do then */
   2865       result = Curl_setstropt(&data->state.aptr.user, *userp);
   2866       if(result)
   2867         return result;
   2868       data->state.creds_from = CREDS_NETRC;
   2869     }
   2870   }
   2871   if(data->state.aptr.user) {
   2872     uc = curl_url_set(data->state.uh, CURLUPART_USER, data->state.aptr.user,
   2873                       CURLU_URLENCODE);
   2874     if(uc)
   2875       return Curl_uc_to_curlcode(uc);
   2876     if(!*userp) {
   2877       *userp = strdup(data->state.aptr.user);
   2878       if(!*userp)
   2879         return CURLE_OUT_OF_MEMORY;
   2880     }
   2881   }
   2882   if(*passwdp) {
   2883     CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp);
   2884     if(result)
   2885       return result;
   2886     data->state.creds_from = CREDS_NETRC;
   2887   }
   2888   if(data->state.aptr.passwd) {
   2889     uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD,
   2890                       data->state.aptr.passwd, CURLU_URLENCODE);
   2891     if(uc)
   2892       return Curl_uc_to_curlcode(uc);
   2893     if(!*passwdp) {
   2894       *passwdp = strdup(data->state.aptr.passwd);
   2895       if(!*passwdp)
   2896         return CURLE_OUT_OF_MEMORY;
   2897     }
   2898   }
   2899 
   2900   return CURLE_OK;
   2901 }
   2902 
   2903 /*
   2904  * Set the login details so they are available in the connection
   2905  */
   2906 static CURLcode set_login(struct Curl_easy *data,
   2907                           struct connectdata *conn)
   2908 {
   2909   CURLcode result = CURLE_OK;
   2910   const char *setuser = CURL_DEFAULT_USER;
   2911   const char *setpasswd = CURL_DEFAULT_PASSWORD;
   2912 
   2913   /* If our protocol needs a password and we have none, use the defaults */
   2914   if((conn->handler->flags & PROTOPT_NEEDSPWD) && !data->state.aptr.user)
   2915     ;
   2916   else {
   2917     setuser = "";
   2918     setpasswd = "";
   2919   }
   2920   /* Store the default user */
   2921   if(!conn->user) {
   2922     conn->user = strdup(setuser);
   2923     if(!conn->user)
   2924       return CURLE_OUT_OF_MEMORY;
   2925   }
   2926 
   2927   /* Store the default password */
   2928   if(!conn->passwd) {
   2929     conn->passwd = strdup(setpasswd);
   2930     if(!conn->passwd)
   2931       result = CURLE_OUT_OF_MEMORY;
   2932   }
   2933 
   2934   return result;
   2935 }
   2936 
   2937 /*
   2938  * Parses a "host:port" string to connect to.
   2939  * The hostname and the port may be empty; in this case, NULL is returned for
   2940  * the hostname and -1 for the port.
   2941  */
   2942 static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
   2943                                            const char *host,
   2944                                            char **hostname_result,
   2945                                            int *port_result)
   2946 {
   2947   char *host_dup;
   2948   char *hostptr;
   2949   char *host_portno;
   2950   char *portptr;
   2951   int port = -1;
   2952   CURLcode result = CURLE_OK;
   2953 
   2954 #ifdef CURL_DISABLE_VERBOSE_STRINGS
   2955   (void) data;
   2956 #endif
   2957 
   2958   *hostname_result = NULL;
   2959   *port_result = -1;
   2960 
   2961   if(!host || !*host)
   2962     return CURLE_OK;
   2963 
   2964   host_dup = strdup(host);
   2965   if(!host_dup)
   2966     return CURLE_OUT_OF_MEMORY;
   2967 
   2968   hostptr = host_dup;
   2969 
   2970   /* start scanning for port number at this point */
   2971   portptr = hostptr;
   2972 
   2973   /* detect and extract RFC6874-style IPv6-addresses */
   2974   if(*hostptr == '[') {
   2975 #ifdef USE_IPV6
   2976     char *ptr = ++hostptr; /* advance beyond the initial bracket */
   2977     while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
   2978       ptr++;
   2979     if(*ptr == '%') {
   2980       /* There might be a zone identifier */
   2981       if(strncmp("%25", ptr, 3))
   2982         infof(data, "Please URL encode %% as %%25, see RFC 6874.");
   2983       ptr++;
   2984       /* Allow unreserved characters as defined in RFC 3986 */
   2985       while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
   2986                      (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
   2987         ptr++;
   2988     }
   2989     if(*ptr == ']')
   2990       /* yeps, it ended nicely with a bracket as well */
   2991       *ptr++ = '\0';
   2992     else
   2993       infof(data, "Invalid IPv6 address format");
   2994     portptr = ptr;
   2995     /* Note that if this did not end with a bracket, we still advanced the
   2996      * hostptr first, but I cannot see anything wrong with that as no host
   2997      * name nor a numeric can legally start with a bracket.
   2998      */
   2999 #else
   3000     failf(data, "Use of IPv6 in *_CONNECT_TO without IPv6 support built-in");
   3001     result = CURLE_NOT_BUILT_IN;
   3002     goto error;
   3003 #endif
   3004   }
   3005 
   3006   /* Get port number off server.com:1080 */
   3007   host_portno = strchr(portptr, ':');
   3008   if(host_portno) {
   3009     *host_portno = '\0'; /* cut off number from hostname */
   3010     host_portno++;
   3011     if(*host_portno) {
   3012       curl_off_t portparse;
   3013       const char *p = host_portno;
   3014       if(curlx_str_number(&p, &portparse, 0xffff)) {
   3015         failf(data, "No valid port number in connect to host string (%s)",
   3016               host_portno);
   3017         result = CURLE_SETOPT_OPTION_SYNTAX;
   3018         goto error;
   3019       }
   3020       port = (int)portparse; /* we know it will fit */
   3021     }
   3022   }
   3023 
   3024   /* now, clone the cleaned hostname */
   3025   DEBUGASSERT(hostptr);
   3026   *hostname_result = strdup(hostptr);
   3027   if(!*hostname_result) {
   3028     result = CURLE_OUT_OF_MEMORY;
   3029     goto error;
   3030   }
   3031 
   3032   *port_result = port;
   3033 
   3034 error:
   3035   free(host_dup);
   3036   return result;
   3037 }
   3038 
   3039 /*
   3040  * Parses one "connect to" string in the form:
   3041  * "HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT".
   3042  */
   3043 static CURLcode parse_connect_to_string(struct Curl_easy *data,
   3044                                         struct connectdata *conn,
   3045                                         const char *conn_to_host,
   3046                                         char **host_result,
   3047                                         int *port_result)
   3048 {
   3049   CURLcode result = CURLE_OK;
   3050   const char *ptr = conn_to_host;
   3051   bool host_match = FALSE;
   3052   bool port_match = FALSE;
   3053 
   3054   *host_result = NULL;
   3055   *port_result = -1;
   3056 
   3057   if(*ptr == ':') {
   3058     /* an empty hostname always matches */
   3059     host_match = TRUE;
   3060     ptr++;
   3061   }
   3062   else {
   3063     /* check whether the URL's hostname matches */
   3064     size_t hostname_to_match_len;
   3065     char *hostname_to_match = aprintf("%s%s%s",
   3066                                       conn->bits.ipv6_ip ? "[" : "",
   3067                                       conn->host.name,
   3068                                       conn->bits.ipv6_ip ? "]" : "");
   3069     if(!hostname_to_match)
   3070       return CURLE_OUT_OF_MEMORY;
   3071     hostname_to_match_len = strlen(hostname_to_match);
   3072     host_match = curl_strnequal(ptr, hostname_to_match,
   3073                                 hostname_to_match_len);
   3074     free(hostname_to_match);
   3075     ptr += hostname_to_match_len;
   3076 
   3077     host_match = host_match && *ptr == ':';
   3078     ptr++;
   3079   }
   3080 
   3081   if(host_match) {
   3082     if(*ptr == ':') {
   3083       /* an empty port always matches */
   3084       port_match = TRUE;
   3085       ptr++;
   3086     }
   3087     else {
   3088       /* check whether the URL's port matches */
   3089       char *ptr_next = strchr(ptr, ':');
   3090       if(ptr_next) {
   3091         curl_off_t port_to_match;
   3092         if(!curlx_str_number(&ptr, &port_to_match, 0xffff) &&
   3093            (port_to_match == (curl_off_t)conn->remote_port))
   3094           port_match = TRUE;
   3095         ptr = ptr_next + 1;
   3096       }
   3097     }
   3098   }
   3099 
   3100   if(host_match && port_match) {
   3101     /* parse the hostname and port to connect to */
   3102     result = parse_connect_to_host_port(data, ptr, host_result, port_result);
   3103   }
   3104 
   3105   return result;
   3106 }
   3107 
   3108 /*
   3109  * Processes all strings in the "connect to" slist, and uses the "connect
   3110  * to host" and "connect to port" of the first string that matches.
   3111  */
   3112 static CURLcode parse_connect_to_slist(struct Curl_easy *data,
   3113                                        struct connectdata *conn,
   3114                                        struct curl_slist *conn_to_host)
   3115 {
   3116   CURLcode result = CURLE_OK;
   3117   char *host = NULL;
   3118   int port = -1;
   3119 
   3120   while(conn_to_host && !host && port == -1) {
   3121     result = parse_connect_to_string(data, conn, conn_to_host->data,
   3122                                      &host, &port);
   3123     if(result)
   3124       return result;
   3125 
   3126     if(host && *host) {
   3127       conn->conn_to_host.rawalloc = host;
   3128       conn->conn_to_host.name = host;
   3129       conn->bits.conn_to_host = TRUE;
   3130 
   3131       infof(data, "Connecting to hostname: %s", host);
   3132     }
   3133     else {
   3134       /* no "connect to host" */
   3135       conn->bits.conn_to_host = FALSE;
   3136       Curl_safefree(host);
   3137     }
   3138 
   3139     if(port >= 0) {
   3140       conn->conn_to_port = port;
   3141       conn->bits.conn_to_port = TRUE;
   3142       infof(data, "Connecting to port: %d", port);
   3143     }
   3144     else {
   3145       /* no "connect to port" */
   3146       conn->bits.conn_to_port = FALSE;
   3147       port = -1;
   3148     }
   3149 
   3150     conn_to_host = conn_to_host->next;
   3151   }
   3152 
   3153 #ifndef CURL_DISABLE_ALTSVC
   3154   if(data->asi && !host && (port == -1) &&
   3155      ((conn->handler->protocol == CURLPROTO_HTTPS) ||
   3156 #ifdef DEBUGBUILD
   3157       /* allow debug builds to circumvent the HTTPS restriction */
   3158       getenv("CURL_ALTSVC_HTTP")
   3159 #else
   3160       0
   3161 #endif
   3162        )) {
   3163     /* no connect_to match, try alt-svc! */
   3164     enum alpnid srcalpnid = ALPN_none;
   3165     bool hit = FALSE;
   3166     struct altsvc *as = NULL;
   3167     int allowed_alpns = ALPN_none;
   3168     struct http_negotiation *neg = &data->state.http_neg;
   3169 
   3170     DEBUGF(infof(data, "Alt-svc check wanted=%x, allowed=%x",
   3171                  neg->wanted, neg->allowed));
   3172 #ifdef USE_HTTP3
   3173     if(neg->allowed & CURL_HTTP_V3x)
   3174       allowed_alpns |= ALPN_h3;
   3175 #endif
   3176 #ifdef USE_HTTP2
   3177     if(neg->allowed & CURL_HTTP_V2x)
   3178       allowed_alpns |= ALPN_h2;
   3179 #endif
   3180     if(neg->allowed & CURL_HTTP_V1x)
   3181       allowed_alpns |= ALPN_h1;
   3182     allowed_alpns &= (int)data->asi->flags;
   3183 
   3184     host = conn->host.rawalloc;
   3185     DEBUGF(infof(data, "check Alt-Svc for host %s", host));
   3186 #ifdef USE_HTTP3
   3187     if(!hit && (neg->wanted & CURL_HTTP_V3x)) {
   3188       srcalpnid = ALPN_h3;
   3189       hit = Curl_altsvc_lookup(data->asi,
   3190                                ALPN_h3, host, conn->remote_port, /* from */
   3191                                &as /* to */,
   3192                                allowed_alpns);
   3193     }
   3194  #endif
   3195  #ifdef USE_HTTP2
   3196     if(!hit && (neg->wanted & CURL_HTTP_V2x) &&
   3197        !neg->h2_prior_knowledge) {
   3198       srcalpnid = ALPN_h2;
   3199       hit = Curl_altsvc_lookup(data->asi,
   3200                                ALPN_h2, host, conn->remote_port, /* from */
   3201                                &as /* to */,
   3202                                allowed_alpns);
   3203     }
   3204  #endif
   3205     if(!hit && (neg->wanted & CURL_HTTP_V1x) &&
   3206        !neg->only_10) {
   3207       srcalpnid = ALPN_h1;
   3208       hit = Curl_altsvc_lookup(data->asi,
   3209                                ALPN_h1, host, conn->remote_port, /* from */
   3210                                &as /* to */,
   3211                                allowed_alpns);
   3212     }
   3213 
   3214     if(hit) {
   3215       char *hostd = strdup((char *)as->dst.host);
   3216       if(!hostd)
   3217         return CURLE_OUT_OF_MEMORY;
   3218       conn->conn_to_host.rawalloc = hostd;
   3219       conn->conn_to_host.name = hostd;
   3220       conn->bits.conn_to_host = TRUE;
   3221       conn->conn_to_port = as->dst.port;
   3222       conn->bits.conn_to_port = TRUE;
   3223       conn->bits.altused = TRUE;
   3224       infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d",
   3225             Curl_alpnid2str(srcalpnid), host, conn->remote_port,
   3226             Curl_alpnid2str(as->dst.alpnid), hostd, as->dst.port);
   3227       if(srcalpnid != as->dst.alpnid) {
   3228         /* protocol version switch */
   3229         switch(as->dst.alpnid) {
   3230         case ALPN_h1:
   3231           neg->wanted = neg->allowed = CURL_HTTP_V1x;
   3232           neg->only_10 = FALSE;
   3233           break;
   3234         case ALPN_h2:
   3235           neg->wanted = neg->allowed = CURL_HTTP_V2x;
   3236           break;
   3237         case ALPN_h3:
   3238           conn->transport_wanted = TRNSPRT_QUIC;
   3239           neg->wanted = neg->allowed = CURL_HTTP_V3x;
   3240           break;
   3241         default: /* should not be possible */
   3242           break;
   3243         }
   3244       }
   3245     }
   3246   }
   3247 #endif
   3248 
   3249   return result;
   3250 }
   3251 
   3252 #ifdef USE_UNIX_SOCKETS
   3253 static CURLcode resolve_unix(struct Curl_easy *data,
   3254                              struct connectdata *conn,
   3255                              char *unix_path,
   3256                              struct Curl_dns_entry **pdns)
   3257 {
   3258   struct Curl_dns_entry *hostaddr;
   3259   bool longpath = FALSE;
   3260 
   3261   DEBUGASSERT(unix_path);
   3262   *pdns = NULL;
   3263 
   3264   /* Unix domain sockets are local. The host gets ignored, just use the
   3265    * specified domain socket address. Do not cache "DNS entries". There is
   3266    * no DNS involved and we already have the filesystem path available. */
   3267   hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
   3268   if(!hostaddr)
   3269     return CURLE_OUT_OF_MEMORY;
   3270 
   3271   hostaddr->addr = Curl_unix2addr(unix_path, &longpath,
   3272                                   conn->bits.abstract_unix_socket);
   3273   if(!hostaddr->addr) {
   3274     if(longpath)
   3275       /* Long paths are not supported for now */
   3276       failf(data, "Unix socket path too long: '%s'", unix_path);
   3277     free(hostaddr);
   3278     return longpath ? CURLE_COULDNT_RESOLVE_HOST : CURLE_OUT_OF_MEMORY;
   3279   }
   3280 
   3281   hostaddr->refcount = 1; /* connection is the only one holding this */
   3282   *pdns = hostaddr;
   3283   return CURLE_OK;
   3284 }
   3285 #endif
   3286 
   3287 /*************************************************************
   3288  * Resolve the address of the server or proxy
   3289  *************************************************************/
   3290 static CURLcode resolve_server(struct Curl_easy *data,
   3291                                struct connectdata *conn,
   3292                                bool *async,
   3293                                struct Curl_dns_entry **pdns)
   3294 {
   3295   struct hostname *ehost;
   3296   timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
   3297   const char *peertype = "host";
   3298   CURLcode result;
   3299 
   3300   *pdns = NULL;
   3301 
   3302 #ifdef USE_UNIX_SOCKETS
   3303   {
   3304     char *unix_path = conn->unix_domain_socket;
   3305 
   3306 #ifndef CURL_DISABLE_PROXY
   3307     if(!unix_path && CONN_IS_PROXIED(conn) && conn->socks_proxy.host.name &&
   3308        !strncmp(UNIX_SOCKET_PREFIX"/",
   3309                 conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX)))
   3310       unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1;
   3311 #endif
   3312 
   3313     if(unix_path) {
   3314       /* This only works if previous transport is TRNSPRT_TCP. Check it? */
   3315       conn->transport_wanted = TRNSPRT_UNIX;
   3316       return resolve_unix(data, conn, unix_path, pdns);
   3317     }
   3318   }
   3319 #endif
   3320 
   3321 #ifndef CURL_DISABLE_PROXY
   3322   if(CONN_IS_PROXIED(conn)) {
   3323     ehost = conn->bits.socksproxy ? &conn->socks_proxy.host :
   3324       &conn->http_proxy.host;
   3325     peertype = "proxy";
   3326   }
   3327   else
   3328 #endif
   3329   {
   3330     ehost = conn->bits.conn_to_host ? &conn->conn_to_host : &conn->host;
   3331     /* If not connecting via a proxy, extract the port from the URL, if it is
   3332      * there, thus overriding any defaults that might have been set above. */
   3333     conn->primary.remote_port = conn->bits.conn_to_port ? conn->conn_to_port :
   3334       conn->remote_port;
   3335   }
   3336 
   3337   /* Resolve target host right on */
   3338   conn->hostname_resolve = strdup(ehost->name);
   3339   if(!conn->hostname_resolve)
   3340     return CURLE_OUT_OF_MEMORY;
   3341 
   3342   result = Curl_resolv_timeout(data, conn->hostname_resolve,
   3343                                conn->primary.remote_port, conn->ip_version,
   3344                                pdns, timeout_ms);
   3345   DEBUGASSERT(!result || !*pdns);
   3346   if(result == CURLE_AGAIN) {
   3347     *async = TRUE;
   3348     return CURLE_OK;
   3349   }
   3350   else if(result == CURLE_OPERATION_TIMEDOUT) {
   3351     failf(data, "Failed to resolve %s '%s' with timeout after %"
   3352           FMT_TIMEDIFF_T " ms", peertype, ehost->dispname,
   3353           curlx_timediff(curlx_now(), data->progress.t_startsingle));
   3354     return CURLE_OPERATION_TIMEDOUT;
   3355   }
   3356   else if(result) {
   3357     failf(data, "Could not resolve %s: %s", peertype, ehost->dispname);
   3358     return result;
   3359   }
   3360   DEBUGASSERT(*pdns);
   3361   return CURLE_OK;
   3362 }
   3363 
   3364 /*
   3365  * Cleanup the connection `temp`, just allocated for `data`, before using the
   3366  * previously `existing` one for `data`. All relevant info is copied over
   3367  * and `temp` is freed.
   3368  */
   3369 static void reuse_conn(struct Curl_easy *data,
   3370                        struct connectdata *temp,
   3371                        struct connectdata *existing)
   3372 {
   3373   /* get the user+password information from the temp struct since it may
   3374    * be new for this request even when we reuse an existing connection */
   3375   if(temp->user) {
   3376     /* use the new username and password though */
   3377     free(existing->user);
   3378     free(existing->passwd);
   3379     existing->user = temp->user;
   3380     existing->passwd = temp->passwd;
   3381     temp->user = NULL;
   3382     temp->passwd = NULL;
   3383   }
   3384 
   3385 #ifndef CURL_DISABLE_PROXY
   3386   existing->bits.proxy_user_passwd = temp->bits.proxy_user_passwd;
   3387   if(existing->bits.proxy_user_passwd) {
   3388     /* use the new proxy username and proxy password though */
   3389     free(existing->http_proxy.user);
   3390     free(existing->socks_proxy.user);
   3391     free(existing->http_proxy.passwd);
   3392     free(existing->socks_proxy.passwd);
   3393     existing->http_proxy.user = temp->http_proxy.user;
   3394     existing->socks_proxy.user = temp->socks_proxy.user;
   3395     existing->http_proxy.passwd = temp->http_proxy.passwd;
   3396     existing->socks_proxy.passwd = temp->socks_proxy.passwd;
   3397     temp->http_proxy.user = NULL;
   3398     temp->socks_proxy.user = NULL;
   3399     temp->http_proxy.passwd = NULL;
   3400     temp->socks_proxy.passwd = NULL;
   3401   }
   3402 #endif
   3403 
   3404   /* Finding a connection for reuse in the cpool matches, among other
   3405    * things on the "remote-relevant" hostname. This is not necessarily
   3406    * the authority of the URL, e.g. conn->host. For example:
   3407    * - we use a proxy (not tunneling). we want to send all requests
   3408    *   that use the same proxy on this connection.
   3409    * - we have a "connect-to" setting that may redirect the hostname of
   3410    *   a new request to the same remote endpoint of an existing conn.
   3411    *   We want to reuse an existing conn to the remote endpoint.
   3412    * Since connection reuse does not match on conn->host necessarily, we
   3413    * switch `existing` conn to `temp` conn's host settings.
   3414    *       Is this correct in the case of TLS connections that have
   3415    *       used the original hostname in SNI to negotiate? Do we send
   3416    *       requests for another host through the different SNI?
   3417    */
   3418   Curl_free_idnconverted_hostname(&existing->host);
   3419   Curl_free_idnconverted_hostname(&existing->conn_to_host);
   3420   Curl_safefree(existing->host.rawalloc);
   3421   Curl_safefree(existing->conn_to_host.rawalloc);
   3422   existing->host = temp->host;
   3423   temp->host.rawalloc = NULL;
   3424   temp->host.encalloc = NULL;
   3425   existing->conn_to_host = temp->conn_to_host;
   3426   temp->conn_to_host.rawalloc = NULL;
   3427   existing->conn_to_port = temp->conn_to_port;
   3428   existing->remote_port = temp->remote_port;
   3429   free(existing->hostname_resolve);
   3430   existing->hostname_resolve = temp->hostname_resolve;
   3431   temp->hostname_resolve = NULL;
   3432 
   3433   /* reuse init */
   3434   existing->bits.reuse = TRUE; /* yes, we are reusing here */
   3435 
   3436   Curl_conn_free(data, temp);
   3437 }
   3438 
   3439 static void conn_meta_freeentry(void *p)
   3440 {
   3441   (void)p;
   3442   /* Will always be FALSE. Cannot use a 0 assert here since compilers
   3443    * are not in agreement if they then want a NORETURN attribute or
   3444    * not. *sigh* */
   3445   DEBUGASSERT(p == NULL);
   3446 }
   3447 
   3448 /**
   3449  * create_conn() sets up a new connectdata struct, or reuses an already
   3450  * existing one, and resolves hostname.
   3451  *
   3452  * if this function returns CURLE_OK and *async is set to TRUE, the resolve
   3453  * response will be coming asynchronously. If *async is FALSE, the name is
   3454  * already resolved.
   3455  *
   3456  * @param data The sessionhandle pointer
   3457  * @param in_connect is set to the next connection data pointer
   3458  * @param reusedp is set to to TRUE if connection was reused
   3459  * @see Curl_setup_conn()
   3460  *
   3461  */
   3462 
   3463 static CURLcode create_conn(struct Curl_easy *data,
   3464                             struct connectdata **in_connect,
   3465                             bool *reusedp)
   3466 {
   3467   CURLcode result = CURLE_OK;
   3468   struct connectdata *conn;
   3469   struct connectdata *existing = NULL;
   3470   bool reuse;
   3471   bool connections_available = TRUE;
   3472   bool force_reuse = FALSE;
   3473   bool waitpipe = FALSE;
   3474 
   3475   *reusedp = FALSE;
   3476   *in_connect = NULL;
   3477 
   3478   /*************************************************************
   3479    * Check input data
   3480    *************************************************************/
   3481   if(!data->state.url) {
   3482     result = CURLE_URL_MALFORMAT;
   3483     goto out;
   3484   }
   3485 
   3486   /* First, split up the current URL in parts so that we can use the
   3487      parts for checking against the already present connections. In order
   3488      to not have to modify everything at once, we allocate a temporary
   3489      connection data struct and fill in for comparison purposes. */
   3490   conn = allocate_conn(data);
   3491 
   3492   if(!conn) {
   3493     result = CURLE_OUT_OF_MEMORY;
   3494     goto out;
   3495   }
   3496 
   3497   /* We must set the return variable as soon as possible, so that our
   3498      parent can cleanup any possible allocs we may have done before
   3499      any failure */
   3500   *in_connect = conn;
   3501 
   3502   /* Do the unfailable inits first, before checks that may early return */
   3503   Curl_hash_init(&conn->meta_hash, 23,
   3504                Curl_hash_str, curlx_str_key_compare, conn_meta_freeentry);
   3505 
   3506   /* GSSAPI related inits */
   3507   Curl_sec_conn_init(conn);
   3508 
   3509   result = parseurlandfillconn(data, conn);
   3510   if(result)
   3511     goto out;
   3512 
   3513   if(data->set.str[STRING_SASL_AUTHZID]) {
   3514     conn->sasl_authzid = strdup(data->set.str[STRING_SASL_AUTHZID]);
   3515     if(!conn->sasl_authzid) {
   3516       result = CURLE_OUT_OF_MEMORY;
   3517       goto out;
   3518     }
   3519   }
   3520 
   3521   if(data->set.str[STRING_BEARER]) {
   3522     conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
   3523     if(!conn->oauth_bearer) {
   3524       result = CURLE_OUT_OF_MEMORY;
   3525       goto out;
   3526     }
   3527   }
   3528 
   3529 #ifdef USE_UNIX_SOCKETS
   3530   if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
   3531     conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
   3532     if(!conn->unix_domain_socket) {
   3533       result = CURLE_OUT_OF_MEMORY;
   3534       goto out;
   3535     }
   3536     conn->bits.abstract_unix_socket = data->set.abstract_unix_socket;
   3537   }
   3538 #endif
   3539 
   3540   /* After the Unix socket init but before the proxy vars are used, parse and
   3541      initialize the proxy vars */
   3542 #ifndef CURL_DISABLE_PROXY
   3543   result = create_conn_helper_init_proxy(data, conn);
   3544   if(result)
   3545     goto out;
   3546 
   3547   /*************************************************************
   3548    * If the protocol is using SSL and HTTP proxy is used, we set
   3549    * the tunnel_proxy bit.
   3550    *************************************************************/
   3551   if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
   3552     conn->bits.tunnel_proxy = TRUE;
   3553 #endif
   3554 
   3555   /*************************************************************
   3556    * Figure out the remote port number and fix it in the URL
   3557    *************************************************************/
   3558   result = parse_remote_port(data, conn);
   3559   if(result)
   3560     goto out;
   3561 
   3562   /* Check for overridden login details and set them accordingly so that
   3563      they are known when protocol->setup_connection is called! */
   3564   result = override_login(data, conn);
   3565   if(result)
   3566     goto out;
   3567 
   3568   result = set_login(data, conn); /* default credentials */
   3569   if(result)
   3570     goto out;
   3571 
   3572   /*************************************************************
   3573    * Process the "connect to" linked list of hostname/port mappings.
   3574    * Do this after the remote port number has been fixed in the URL.
   3575    *************************************************************/
   3576   result = parse_connect_to_slist(data, conn, data->set.connect_to);
   3577   if(result)
   3578     goto out;
   3579 
   3580   /*************************************************************
   3581    * IDN-convert the proxy hostnames
   3582    *************************************************************/
   3583 #ifndef CURL_DISABLE_PROXY
   3584   if(conn->bits.httpproxy) {
   3585     result = Curl_idnconvert_hostname(&conn->http_proxy.host);
   3586     if(result)
   3587       return result;
   3588   }
   3589   if(conn->bits.socksproxy) {
   3590     result = Curl_idnconvert_hostname(&conn->socks_proxy.host);
   3591     if(result)
   3592       return result;
   3593   }
   3594 #endif
   3595   if(conn->bits.conn_to_host) {
   3596     result = Curl_idnconvert_hostname(&conn->conn_to_host);
   3597     if(result)
   3598       return result;
   3599   }
   3600 
   3601   /*************************************************************
   3602    * Check whether the host and the "connect to host" are equal.
   3603    * Do this after the hostnames have been IDN-converted.
   3604    *************************************************************/
   3605   if(conn->bits.conn_to_host &&
   3606      curl_strequal(conn->conn_to_host.name, conn->host.name)) {
   3607     conn->bits.conn_to_host = FALSE;
   3608   }
   3609 
   3610   /*************************************************************
   3611    * Check whether the port and the "connect to port" are equal.
   3612    * Do this after the remote port number has been fixed in the URL.
   3613    *************************************************************/
   3614   if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
   3615     conn->bits.conn_to_port = FALSE;
   3616   }
   3617 
   3618 #ifndef CURL_DISABLE_PROXY
   3619   /*************************************************************
   3620    * If the "connect to" feature is used with an HTTP proxy,
   3621    * we set the tunnel_proxy bit.
   3622    *************************************************************/
   3623   if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
   3624       conn->bits.httpproxy)
   3625     conn->bits.tunnel_proxy = TRUE;
   3626 #endif
   3627 
   3628   /*************************************************************
   3629    * Setup internals depending on protocol. Needs to be done after
   3630    * we figured out what/if proxy to use.
   3631    *************************************************************/
   3632   result = setup_connection_internals(data, conn);
   3633   if(result)
   3634     goto out;
   3635 
   3636   /***********************************************************************
   3637    * file: is a special case in that it does not need a network connection
   3638    ***********************************************************************/
   3639 #ifndef CURL_DISABLE_FILE
   3640   if(conn->handler->flags & PROTOPT_NONETWORK) {
   3641     bool done;
   3642     /* this is supposed to be the connect function so we better at least check
   3643        that the file is present here! */
   3644     DEBUGASSERT(conn->handler->connect_it);
   3645     data->info.conn_scheme = conn->handler->scheme;
   3646     /* conn_protocol can only provide "old" protocols */
   3647     data->info.conn_protocol = (conn->handler->protocol) & CURLPROTO_MASK;
   3648     result = conn->handler->connect_it(data, &done);
   3649     if(result)
   3650       goto out;
   3651 
   3652     /* Setup a "faked" transfer that will do nothing */
   3653     Curl_attach_connection(data, conn);
   3654     result = Curl_cpool_add(data, conn);
   3655     if(!result) {
   3656       /* Setup whatever necessary for a resumed transfer */
   3657       result = setup_range(data);
   3658       if(!result) {
   3659         Curl_xfer_setup_nop(data);
   3660         result = Curl_init_do(data, conn);
   3661       }
   3662     }
   3663 
   3664     if(result) {
   3665       DEBUGASSERT(conn->handler->done);
   3666       /* we ignore the return code for the protocol-specific DONE */
   3667       (void)conn->handler->done(data, result, FALSE);
   3668     }
   3669     goto out;
   3670   }
   3671 #endif
   3672 
   3673   /* Setup filter for network connections */
   3674   conn->recv[FIRSTSOCKET] = Curl_cf_recv;
   3675   conn->send[FIRSTSOCKET] = Curl_cf_send;
   3676   conn->recv[SECONDARYSOCKET] = Curl_cf_recv;
   3677   conn->send[SECONDARYSOCKET] = Curl_cf_send;
   3678   conn->bits.tcp_fastopen = data->set.tcp_fastopen;
   3679 
   3680   /* Complete the easy's SSL configuration for connection cache matching */
   3681   result = Curl_ssl_easy_config_complete(data);
   3682   if(result)
   3683     goto out;
   3684 
   3685   Curl_cpool_prune_dead(data);
   3686 
   3687   /*************************************************************
   3688    * Check the current list of connections to see if we can
   3689    * reuse an already existing one or if we have to create a
   3690    * new one.
   3691    *************************************************************/
   3692 
   3693   DEBUGASSERT(conn->user);
   3694   DEBUGASSERT(conn->passwd);
   3695 
   3696   /* reuse_fresh is TRUE if we are told to use a new connection by force, but
   3697      we only acknowledge this option if this is not a reused connection
   3698      already (which happens due to follow-location or during an HTTP
   3699      authentication phase). CONNECT_ONLY transfers also refuse reuse. */
   3700   if((data->set.reuse_fresh && !data->state.followlocation) ||
   3701      data->set.connect_only)
   3702     reuse = FALSE;
   3703   else
   3704     reuse = ConnectionExists(data, conn, &existing, &force_reuse, &waitpipe);
   3705 
   3706   if(reuse) {
   3707     /*
   3708      * We already have a connection for this, we got the former connection in
   3709      * `existing` and thus we need to cleanup the one we just
   3710      * allocated before we can move along and use `existing`.
   3711      */
   3712     bool tls_upgraded = (!(conn->given->flags & PROTOPT_SSL) &&
   3713                          Curl_conn_is_ssl(conn, FIRSTSOCKET));
   3714 
   3715     reuse_conn(data, conn, existing);
   3716     conn = existing;
   3717     *in_connect = conn;
   3718 
   3719 #ifndef CURL_DISABLE_PROXY
   3720     infof(data, "Re-using existing %s: connection%s with %s %s",
   3721           conn->given->scheme,
   3722           tls_upgraded ? " (upgraded to SSL)" : "",
   3723           conn->bits.proxy ? "proxy" : "host",
   3724           conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
   3725           conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
   3726           conn->host.dispname);
   3727 #else
   3728     infof(data, "Re-using existing %s: connection%s with host %s",
   3729           conn->given->scheme,
   3730           tls_upgraded ? " (upgraded to SSL)" : "",
   3731           conn->host.dispname);
   3732 #endif
   3733   }
   3734   else {
   3735     /* We have decided that we want a new connection. However, we may not
   3736        be able to do that if we have reached the limit of how many
   3737        connections we are allowed to open. */
   3738 
   3739     if(conn->handler->flags & PROTOPT_ALPN) {
   3740       /* The protocol wants it, so set the bits if enabled in the easy handle
   3741          (default) */
   3742       if(data->set.ssl_enable_alpn)
   3743         conn->bits.tls_enable_alpn = TRUE;
   3744     }
   3745 
   3746     if(waitpipe) {
   3747       /* There is a connection that *might* become usable for multiplexing
   3748          "soon", and we wait for that */
   3749       infof(data, "Waiting on connection to negotiate possible multiplexing.");
   3750       connections_available = FALSE;
   3751     }
   3752     else {
   3753       switch(Curl_cpool_check_limits(data, conn)) {
   3754       case CPOOL_LIMIT_DEST:
   3755         infof(data, "No more connections allowed to host");
   3756         connections_available = FALSE;
   3757         break;
   3758       case CPOOL_LIMIT_TOTAL:
   3759         if(data->master_mid != UINT_MAX)
   3760           CURL_TRC_M(data, "Allowing sub-requests (like DoH) to override "
   3761                      "max connection limit");
   3762         else {
   3763           infof(data, "No connections available, total of %ld reached.",
   3764                 data->multi->max_total_connections);
   3765           connections_available = FALSE;
   3766         }
   3767         break;
   3768       default:
   3769         break;
   3770       }
   3771     }
   3772 
   3773     if(!connections_available) {
   3774       Curl_conn_free(data, conn);
   3775       *in_connect = NULL;
   3776 
   3777       result = CURLE_NO_CONNECTION_AVAILABLE;
   3778       goto out;
   3779     }
   3780     else {
   3781       /*
   3782        * This is a brand new connection, so let's store it in the connection
   3783        * cache of ours!
   3784        */
   3785       result = Curl_ssl_conn_config_init(data, conn);
   3786       if(result) {
   3787         DEBUGF(fprintf(stderr, "Error: init connection ssl config\n"));
   3788         goto out;
   3789       }
   3790 
   3791       Curl_attach_connection(data, conn);
   3792       result = Curl_cpool_add(data, conn);
   3793       if(result)
   3794         goto out;
   3795     }
   3796 
   3797 #ifdef USE_NTLM
   3798     /* If NTLM is requested in a part of this connection, make sure we do not
   3799        assume the state is fine as this is a fresh connection and NTLM is
   3800        connection based. */
   3801     if((data->state.authhost.picked & CURLAUTH_NTLM) &&
   3802        data->state.authhost.done) {
   3803       infof(data, "NTLM picked AND auth done set, clear picked");
   3804       data->state.authhost.picked = CURLAUTH_NONE;
   3805       data->state.authhost.done = FALSE;
   3806     }
   3807 
   3808     if((data->state.authproxy.picked & CURLAUTH_NTLM) &&
   3809        data->state.authproxy.done) {
   3810       infof(data, "NTLM-proxy picked AND auth done set, clear picked");
   3811       data->state.authproxy.picked = CURLAUTH_NONE;
   3812       data->state.authproxy.done = FALSE;
   3813     }
   3814 #endif
   3815   }
   3816 
   3817   /* Setup and init stuff before DO starts, in preparing for the transfer. */
   3818   result = Curl_init_do(data, conn);
   3819   if(result)
   3820     goto out;
   3821 
   3822   /*
   3823    * Setup whatever necessary for a resumed transfer
   3824    */
   3825   result = setup_range(data);
   3826   if(result)
   3827     goto out;
   3828 
   3829   /* Continue connectdata initialization here. */
   3830 
   3831   if(conn->bits.reuse) {
   3832     /* We are reusing the connection - no need to resolve anything, and
   3833        idnconvert_hostname() was called already in create_conn() for the reuse
   3834        case. */
   3835     *reusedp = TRUE;
   3836   }
   3837 
   3838   /* persist the scheme and handler the transfer is using */
   3839   data->info.conn_scheme = conn->handler->scheme;
   3840   /* conn_protocol can only provide "old" protocols */
   3841   data->info.conn_protocol = (conn->handler->protocol) & CURLPROTO_MASK;
   3842   data->info.used_proxy =
   3843 #ifdef CURL_DISABLE_PROXY
   3844     0
   3845 #else
   3846     conn->bits.proxy
   3847 #endif
   3848     ;
   3849 
   3850   /* Everything general done, inform filters that they need
   3851    * to prepare for a data transfer. */
   3852   result = Curl_conn_ev_data_setup(data);
   3853 
   3854 out:
   3855   return result;
   3856 }
   3857 
   3858 /* Curl_setup_conn() is called after the name resolve initiated in
   3859  * create_conn() is all done.
   3860  *
   3861  * Curl_setup_conn() also handles reused connections
   3862  */
   3863 CURLcode Curl_setup_conn(struct Curl_easy *data,
   3864                          struct Curl_dns_entry *dns,
   3865                          bool *protocol_done)
   3866 {
   3867   CURLcode result = CURLE_OK;
   3868   struct connectdata *conn = data->conn;
   3869 
   3870   DEBUGASSERT(dns);
   3871   Curl_pgrsTime(data, TIMER_NAMELOOKUP);
   3872 
   3873   if(!conn->bits.reuse)
   3874     result = Curl_conn_setup(data, conn, FIRSTSOCKET, dns,
   3875                              CURL_CF_SSL_DEFAULT);
   3876   if(!result)
   3877     result = Curl_headers_init(data);
   3878 
   3879   /* not sure we need this flag to be passed around any more */
   3880   *protocol_done = FALSE;
   3881   return result;
   3882 }
   3883 
   3884 CURLcode Curl_connect(struct Curl_easy *data,
   3885                       bool *asyncp,
   3886                       bool *protocol_done)
   3887 {
   3888   CURLcode result;
   3889   struct connectdata *conn;
   3890   bool reused = FALSE;
   3891 
   3892   *asyncp = FALSE; /* assume synchronous resolves by default */
   3893   *protocol_done = FALSE;
   3894 
   3895   /* Set the request to virgin state based on transfer settings */
   3896   Curl_req_hard_reset(&data->req, data);
   3897 
   3898   /* call the stuff that needs to be called */
   3899   result = create_conn(data, &conn, &reused);
   3900 
   3901   if(result == CURLE_NO_CONNECTION_AVAILABLE) {
   3902     DEBUGASSERT(!conn);
   3903     return result;
   3904   }
   3905 
   3906   if(!result) {
   3907     DEBUGASSERT(conn);
   3908     if(reused) {
   3909       if(CONN_ATTACHED(conn) > 1)
   3910         /* multiplexed */
   3911         *protocol_done = TRUE;
   3912     }
   3913     else if(conn->handler->flags & PROTOPT_NONETWORK) {
   3914       *asyncp = FALSE;
   3915       Curl_pgrsTime(data, TIMER_NAMELOOKUP);
   3916       *protocol_done = TRUE;
   3917     }
   3918     else {
   3919       /*************************************************************
   3920        * Resolve the address of the server or proxy
   3921        *************************************************************/
   3922       struct Curl_dns_entry *dns;
   3923       result = resolve_server(data, conn, asyncp, &dns);
   3924       if(!result) {
   3925         *asyncp = !dns;
   3926         if(dns)
   3927           /* DNS resolution is done: that is either because this is a reused
   3928              connection, in which case DNS was unnecessary, or because DNS
   3929              really did finish already (synch resolver/fast async resolve) */
   3930           result = Curl_setup_conn(data, dns, protocol_done);
   3931       }
   3932     }
   3933   }
   3934 
   3935   if(result && conn) {
   3936     /* We are not allowed to return failure with memory left allocated in the
   3937        connectdata struct, free those here */
   3938     Curl_detach_connection(data);
   3939     Curl_conn_terminate(data, conn, TRUE);
   3940   }
   3941 
   3942   return result;
   3943 }
   3944 
   3945 /*
   3946  * Curl_init_do() inits the readwrite session. This is inited each time (in
   3947  * the DO function before the protocol-specific DO functions are invoked) for
   3948  * a transfer, sometimes multiple times on the same Curl_easy. Make sure
   3949  * nothing in here depends on stuff that are setup dynamically for the
   3950  * transfer.
   3951  *
   3952  * Allow this function to get called with 'conn' set to NULL.
   3953  */
   3954 
   3955 CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
   3956 {
   3957   /* if this is a pushed stream, we need this: */
   3958   CURLcode result;
   3959 
   3960   if(conn) {
   3961     conn->bits.do_more = FALSE; /* by default there is no curl_do_more() to
   3962                                    use */
   3963     /* if the protocol used does not support wildcards, switch it off */
   3964     if(data->state.wildcardmatch &&
   3965        !(conn->handler->flags & PROTOPT_WILDCARD))
   3966       data->state.wildcardmatch = FALSE;
   3967   }
   3968 
   3969   data->state.done = FALSE; /* *_done() is not called yet */
   3970 
   3971   if(data->req.no_body)
   3972     /* in HTTP lingo, no body means using the HEAD request... */
   3973     data->state.httpreq = HTTPREQ_HEAD;
   3974 
   3975   result = Curl_req_start(&data->req, data);
   3976   if(!result) {
   3977     Curl_speedinit(data);
   3978     Curl_pgrsSetUploadCounter(data, 0);
   3979     Curl_pgrsSetDownloadCounter(data, 0);
   3980   }
   3981   return result;
   3982 }
   3983 
   3984 #if defined(USE_HTTP2) || defined(USE_HTTP3)
   3985 
   3986 #ifdef USE_NGHTTP2
   3987 
   3988 static void priority_remove_child(struct Curl_easy *parent,
   3989                                   struct Curl_easy *child)
   3990 {
   3991   struct Curl_data_prio_node **pnext = &parent->set.priority.children;
   3992   struct Curl_data_prio_node *pnode = parent->set.priority.children;
   3993 
   3994   DEBUGASSERT(child->set.priority.parent == parent);
   3995   while(pnode && pnode->data != child) {
   3996     pnext = &pnode->next;
   3997     pnode = pnode->next;
   3998   }
   3999 
   4000   DEBUGASSERT(pnode);
   4001   if(pnode) {
   4002     *pnext = pnode->next;
   4003     free(pnode);
   4004   }
   4005 
   4006   child->set.priority.parent = 0;
   4007   child->set.priority.exclusive = FALSE;
   4008 }
   4009 
   4010 CURLcode Curl_data_priority_add_child(struct Curl_easy *parent,
   4011                                       struct Curl_easy *child,
   4012                                       bool exclusive)
   4013 {
   4014   if(child->set.priority.parent) {
   4015     priority_remove_child(child->set.priority.parent, child);
   4016   }
   4017 
   4018   if(parent) {
   4019     struct Curl_data_prio_node **tail;
   4020     struct Curl_data_prio_node *pnode;
   4021 
   4022     pnode = calloc(1, sizeof(*pnode));
   4023     if(!pnode)
   4024       return CURLE_OUT_OF_MEMORY;
   4025     pnode->data = child;
   4026 
   4027     if(parent->set.priority.children && exclusive) {
   4028       /* exclusive: move all existing children underneath the new child */
   4029       struct Curl_data_prio_node *node = parent->set.priority.children;
   4030       while(node) {
   4031         node->data->set.priority.parent = child;
   4032         node = node->next;
   4033       }
   4034 
   4035       tail = &child->set.priority.children;
   4036       while(*tail)
   4037         tail = &(*tail)->next;
   4038 
   4039       DEBUGASSERT(!*tail);
   4040       *tail = parent->set.priority.children;
   4041       parent->set.priority.children = 0;
   4042     }
   4043 
   4044     tail = &parent->set.priority.children;
   4045     while(*tail) {
   4046       (*tail)->data->set.priority.exclusive = FALSE;
   4047       tail = &(*tail)->next;
   4048     }
   4049 
   4050     DEBUGASSERT(!*tail);
   4051     *tail = pnode;
   4052   }
   4053 
   4054   child->set.priority.parent = parent;
   4055   child->set.priority.exclusive = exclusive;
   4056   return CURLE_OK;
   4057 }
   4058 
   4059 #endif /* USE_NGHTTP2 */
   4060 
   4061 #ifdef USE_NGHTTP2
   4062 static void data_priority_cleanup(struct Curl_easy *data)
   4063 {
   4064   while(data->set.priority.children) {
   4065     struct Curl_easy *tmp = data->set.priority.children->data;
   4066     priority_remove_child(data, tmp);
   4067     if(data->set.priority.parent)
   4068       Curl_data_priority_add_child(data->set.priority.parent, tmp, FALSE);
   4069   }
   4070 
   4071   if(data->set.priority.parent)
   4072     priority_remove_child(data->set.priority.parent, data);
   4073 }
   4074 #endif
   4075 
   4076 void Curl_data_priority_clear_state(struct Curl_easy *data)
   4077 {
   4078   memset(&data->state.priority, 0, sizeof(data->state.priority));
   4079 }
   4080 
   4081 #endif /* defined(USE_HTTP2) || defined(USE_HTTP3) */
   4082 
   4083 
   4084 CURLcode Curl_conn_meta_set(struct connectdata *conn, const char *key,
   4085                             void *meta_data, Curl_meta_dtor *meta_dtor)
   4086 {
   4087   if(!Curl_hash_add2(&conn->meta_hash, CURL_UNCONST(key), strlen(key) + 1,
   4088                      meta_data, meta_dtor)) {
   4089     meta_dtor(CURL_UNCONST(key), strlen(key) + 1, meta_data);
   4090     return CURLE_OUT_OF_MEMORY;
   4091   }
   4092   return CURLE_OK;
   4093 }
   4094 
   4095 void Curl_conn_meta_remove(struct connectdata *conn, const char *key)
   4096 {
   4097   Curl_hash_delete(&conn->meta_hash, CURL_UNCONST(key), strlen(key) + 1);
   4098 }
   4099 
   4100 void *Curl_conn_meta_get(struct connectdata *conn, const char *key)
   4101 {
   4102   return Curl_hash_pick(&conn->meta_hash, CURL_UNCONST(key), strlen(key) + 1);
   4103 }
   4104 
   4105 CURLcode Curl_1st_err(CURLcode r1, CURLcode r2)
   4106 {
   4107   return r1 ? r1 : r2;
   4108 }
   4109 
   4110 CURLcode Curl_1st_fatal(CURLcode r1, CURLcode r2)
   4111 {
   4112   if(r1 && (r1 != CURLE_AGAIN))
   4113     return r1;
   4114   if(r2 && (r2 != CURLE_AGAIN))
   4115     return r2;
   4116   return r1;
   4117 }