Annotation of embedaddon/curl/lib/url.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>