Lines Matching +full:remote +full:- +full:build +full:- +full:cache +full:- +full:proxy +full:- +full:enabled
21 * SPDX-License-Identifier: curl
89 #include "urlapi-int.h"
160 * 'h' [in] - struct Curl_handler pointer.
167 DEBUGASSERT(h->family); in get_protocol_family()
168 return h->family; in get_protocol_family()
173 /* Free all dynamic strings stored in the data->set substructure. */ in Curl_freeset()
178 Curl_safefree(data->set.str[i]); in Curl_freeset()
182 Curl_safefree(data->set.blobs[j]); in Curl_freeset()
185 if(data->state.referer_alloc) { in Curl_freeset()
186 Curl_safefree(data->state.referer); in Curl_freeset()
187 data->state.referer_alloc = FALSE; in Curl_freeset()
189 data->state.referer = NULL; in Curl_freeset()
190 if(data->state.url_alloc) { in Curl_freeset()
191 Curl_safefree(data->state.url); in Curl_freeset()
192 data->state.url_alloc = FALSE; in Curl_freeset()
194 data->state.url = NULL; in Curl_freeset()
196 Curl_mime_cleanpart(&data->set.mimepost); in Curl_freeset()
199 curl_slist_free_all(data->state.cookielist); in Curl_freeset()
200 data->state.cookielist = NULL; in Curl_freeset()
207 struct urlpieces *up = &data->state.up; in up_free()
208 Curl_safefree(up->scheme); in up_free()
209 Curl_safefree(up->hostname); in up_free()
210 Curl_safefree(up->port); in up_free()
211 Curl_safefree(up->user); in up_free()
212 Curl_safefree(up->password); in up_free()
213 Curl_safefree(up->options); in up_free()
214 Curl_safefree(up->path); in up_free()
215 Curl_safefree(up->query); in up_free()
216 curl_url_cleanup(data->state.uh); in up_free()
217 data->state.uh = NULL; in up_free()
242 if(!data->state.internal) { in Curl_close()
243 if(data->multi) in Curl_close()
246 curl_multi_remove_handle(data->multi, data); in Curl_close()
248 if(data->multi_easy) { in Curl_close()
251 curl_multi_cleanup(data->multi_easy); in Curl_close()
252 data->multi_easy = NULL; in Curl_close()
256 data->magic = 0; /* force a clear AFTER the possibly enforced removal from in Curl_close()
260 if(data->state.rangestringalloc) in Curl_close()
261 free(data->state.range); in Curl_close()
264 Curl_req_free(&data->req, data); in Curl_close()
268 Curl_safefree(data->state.first_host); in Curl_close()
269 Curl_safefree(data->state.scratch); in Curl_close()
272 if(data->state.referer_alloc) { in Curl_close()
273 Curl_safefree(data->state.referer); in Curl_close()
274 data->state.referer_alloc = FALSE; in Curl_close()
276 data->state.referer = NULL; in Curl_close()
279 Curl_dyn_free(&data->state.headerb); in Curl_close()
282 Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]); in Curl_close()
283 Curl_altsvc_cleanup(&data->asi); in Curl_close()
286 Curl_hsts_save(data, data->hsts, data->set.str[STRING_HSTS]); in Curl_close()
287 if(!data->share || !data->share->hsts) in Curl_close()
288 Curl_hsts_cleanup(&data->hsts); in Curl_close()
289 curl_slist_free_all(data->state.hstslist); /* clean up list */ in Curl_close()
294 Curl_safefree(data->info.contenttype); in Curl_close()
295 Curl_safefree(data->info.wouldredirect); in Curl_close()
299 Curl_resolver_cleanup(data->state.async.resolver); in Curl_close()
304 if(data->share) { in Curl_close()
306 data->share->dirty--; in Curl_close()
311 Curl_safefree(data->state.aptr.proxyuserpwd); in Curl_close()
313 Curl_safefree(data->state.aptr.uagent); in Curl_close()
314 Curl_safefree(data->state.aptr.userpwd); in Curl_close()
315 Curl_safefree(data->state.aptr.accept_encoding); in Curl_close()
316 Curl_safefree(data->state.aptr.te); in Curl_close()
317 Curl_safefree(data->state.aptr.rangeline); in Curl_close()
318 Curl_safefree(data->state.aptr.ref); in Curl_close()
319 Curl_safefree(data->state.aptr.host); in Curl_close()
321 Curl_safefree(data->state.aptr.cookiehost); in Curl_close()
324 Curl_safefree(data->state.aptr.rtsp_transport); in Curl_close()
326 Curl_safefree(data->state.aptr.user); in Curl_close()
327 Curl_safefree(data->state.aptr.passwd); in Curl_close()
329 Curl_safefree(data->state.aptr.proxyuser); in Curl_close()
330 Curl_safefree(data->state.aptr.proxypasswd); in Curl_close()
334 Curl_mime_cleanpart(data->state.formp); in Curl_close()
335 Curl_safefree(data->state.formp); in Curl_close()
339 Curl_wildcard_dtor(&data->wildcard); in Curl_close()
352 struct UserDefined *set = &data->set; in Curl_init_userdefined()
355 set->out = stdout; /* default output to stdout */ in Curl_init_userdefined()
356 set->in_set = stdin; /* default input from stdin */ in Curl_init_userdefined()
357 set->err = stderr; /* default stderr to stderr */ in Curl_init_userdefined()
360 set->fwrite_func = (curl_write_callback)fwrite; in Curl_init_userdefined()
363 set->fread_func_set = (curl_read_callback)fread; in Curl_init_userdefined()
364 set->is_fread_set = 0; in Curl_init_userdefined()
366 set->seek_client = ZERO_NULL; in Curl_init_userdefined()
368 set->filesize = -1; /* we don't know the size */ in Curl_init_userdefined()
369 set->postfieldsize = -1; /* unknown size */ in Curl_init_userdefined()
370 set->maxredirs = 30; /* sensible default */ in Curl_init_userdefined()
372 set->method = HTTPREQ_GET; /* Default HTTP request */ in Curl_init_userdefined()
374 set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */ in Curl_init_userdefined()
377 set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */ in Curl_init_userdefined()
378 set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */ in Curl_init_userdefined()
379 set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */ in Curl_init_userdefined()
380 set->ftp_filemethod = FTPFILE_MULTICWD; in Curl_init_userdefined()
381 set->ftp_skip_ip = TRUE; /* skip PASV IP by default */ in Curl_init_userdefined()
383 set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */ in Curl_init_userdefined()
385 /* Set the default size of the SSL session ID cache */ in Curl_init_userdefined()
386 set->general_ssl.max_ssl_sessions = 5; in Curl_init_userdefined()
388 set->general_ssl.ca_cache_timeout = 24 * 60 * 60; in Curl_init_userdefined()
390 set->httpauth = CURLAUTH_BASIC; /* defaults to basic */ in Curl_init_userdefined()
393 set->proxyport = 0; in Curl_init_userdefined()
394 set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */ in Curl_init_userdefined()
395 set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */ in Curl_init_userdefined()
396 /* SOCKS5 proxy auth defaults to username/password + GSS-API */ in Curl_init_userdefined()
397 set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI; in Curl_init_userdefined()
401 set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */ in Curl_init_userdefined()
403 Curl_mime_initpart(&set->mimepost); in Curl_init_userdefined()
407 set->doh_verifyhost = TRUE; in Curl_init_userdefined()
408 set->doh_verifypeer = TRUE; in Curl_init_userdefined()
412 set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; in Curl_init_userdefined()
413 set->new_directory_perms = 0755; /* Default permissions */ in Curl_init_userdefined()
416 set->new_file_perms = 0644; /* Default permissions */ in Curl_init_userdefined()
417 set->allowed_protocols = (curl_prot_t) CURLPROTO_ALL; in Curl_init_userdefined()
418 set->redir_protocols = CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP | in Curl_init_userdefined()
426 set->socks5_gssapi_nec = FALSE; in Curl_init_userdefined()
429 /* Set the default CA cert bundle/path detected/specified at build time. in Curl_init_userdefined()
434 * CURLOPT_CAINFO / --cacert. in Curl_init_userdefined()
439 result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE); in Curl_init_userdefined()
443 result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY], in Curl_init_userdefined()
450 result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH); in Curl_init_userdefined()
454 result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH); in Curl_init_userdefined()
462 set->wildcard_enabled = FALSE; in Curl_init_userdefined()
463 set->chunk_bgn = ZERO_NULL; in Curl_init_userdefined()
464 set->chunk_end = ZERO_NULL; in Curl_init_userdefined()
465 set->fnmatch = ZERO_NULL; in Curl_init_userdefined()
467 set->tcp_keepalive = FALSE; in Curl_init_userdefined()
468 set->tcp_keepintvl = 60; in Curl_init_userdefined()
469 set->tcp_keepidle = 60; in Curl_init_userdefined()
470 set->tcp_fastopen = FALSE; in Curl_init_userdefined()
471 set->tcp_nodelay = TRUE; in Curl_init_userdefined()
472 set->ssl_enable_alpn = TRUE; in Curl_init_userdefined()
473 set->expect_100_timeout = 1000L; /* Wait for a second by default. */ in Curl_init_userdefined()
474 set->sep_headers = TRUE; /* separated header lists by default */ in Curl_init_userdefined()
475 set->buffer_size = READBUFFER_SIZE; in Curl_init_userdefined()
476 set->upload_buffer_size = UPLOADBUFFER_DEFAULT; in Curl_init_userdefined()
477 set->happy_eyeballs_timeout = CURL_HET_DEFAULT; in Curl_init_userdefined()
478 set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT; in Curl_init_userdefined()
479 set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */ in Curl_init_userdefined()
480 set->maxage_conn = 118; in Curl_init_userdefined()
481 set->maxlifetime_conn = 0; in Curl_init_userdefined()
482 set->http09_allowed = FALSE; in Curl_init_userdefined()
484 set->httpwant = CURL_HTTP_VERSION_2TLS in Curl_init_userdefined()
486 set->httpwant = CURL_HTTP_VERSION_1_1 in Curl_init_userdefined()
490 memset(&set->priority, 0, sizeof(set->priority)); in Curl_init_userdefined()
492 set->quick_exit = 0L; in Curl_init_userdefined()
509 /* Very simple start-up: alloc the struct, init it with zeroes and return */ in Curl_open()
517 data->magic = CURLEASY_MAGIC_NUMBER; in Curl_open()
519 Curl_req_init(&data->req); in Curl_open()
521 result = Curl_resolver_init(data, &data->state.async.resolver); in Curl_open()
524 Curl_req_free(&data->req, data); in Curl_open()
531 Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER); in Curl_open()
535 data->state.lastconnect_id = -1; in Curl_open()
536 data->state.recent_conn_id = -1; in Curl_open()
538 data->id = -1; in Curl_open()
540 data->progress.flags |= PGRS_HIDE; in Curl_open()
541 data->state.current_speed = -1; /* init to negative == impossible */ in Curl_open()
545 Curl_resolver_cleanup(data->state.async.resolver); in Curl_open()
546 Curl_dyn_free(&data->state.headerb); in Curl_open()
548 Curl_req_free(&data->req, data); in Curl_open()
563 /* possible left-overs from the async name resolvers */ in conn_shutdown()
576 for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) { in conn_free()
580 Curl_free_idnconverted_hostname(&conn->host); in conn_free()
581 Curl_free_idnconverted_hostname(&conn->conn_to_host); in conn_free()
583 Curl_free_idnconverted_hostname(&conn->http_proxy.host); in conn_free()
584 Curl_free_idnconverted_hostname(&conn->socks_proxy.host); in conn_free()
585 Curl_safefree(conn->http_proxy.user); in conn_free()
586 Curl_safefree(conn->socks_proxy.user); in conn_free()
587 Curl_safefree(conn->http_proxy.passwd); in conn_free()
588 Curl_safefree(conn->socks_proxy.passwd); in conn_free()
589 Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */ in conn_free()
590 Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */ in conn_free()
592 Curl_safefree(conn->user); in conn_free()
593 Curl_safefree(conn->passwd); in conn_free()
594 Curl_safefree(conn->sasl_authzid); in conn_free()
595 Curl_safefree(conn->options); in conn_free()
596 Curl_safefree(conn->oauth_bearer); in conn_free()
597 Curl_safefree(conn->host.rawalloc); /* host name buffer */ in conn_free()
598 Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */ in conn_free()
599 Curl_safefree(conn->hostname_resolve); in conn_free()
600 Curl_safefree(conn->secondaryhostname); in conn_free()
601 Curl_safefree(conn->localdev); in conn_free()
605 Curl_safefree(conn->unix_domain_socket); in conn_free()
613 * primary connection, like when freeing room in the connection cache or
621 * isn't strictly bound to the life-time of *this* particular connection.
631 /* it must be removed from the connection cache */ in Curl_disconnect()
632 DEBUGASSERT(!conn->bundle); in Curl_disconnect()
638 DEBUGASSERT(!data->conn); in Curl_disconnect()
642 conn->connection_id, dead_connection)); in Curl_disconnect()
644 * If this connection isn't marked to force-close, leave it open if there in Curl_disconnect()
652 if(conn->dns_entry) { in Curl_disconnect()
653 Curl_resolv_unlock(data, conn->dns_entry); in Curl_disconnect()
654 conn->dns_entry = NULL; in Curl_disconnect()
657 /* Cleanup NTLM connection-related data */ in Curl_disconnect()
660 /* Cleanup NEGOTIATE connection-related data */ in Curl_disconnect()
663 if(conn->connect_only) in Curl_disconnect()
671 if(conn->handler && conn->handler->disconnect) in Curl_disconnect()
672 /* This is set if protocol-specific cleanups should be made */ in Curl_disconnect()
673 conn->handler->disconnect(data, conn, dead_connection); in Curl_disconnect()
694 /* If an HTTP protocol and multiplexing is enabled */ in IsMultiplexingPossible()
695 if((conn->handler->protocol & PROTO_FAMILY_HTTP) && in IsMultiplexingPossible()
696 (!conn->bits.protoconnstart || !conn->bits.close)) { in IsMultiplexingPossible()
698 if(Curl_multiplex_wanted(handle->multi) && in IsMultiplexingPossible()
699 (handle->state.httpwant >= CURL_HTTP_VERSION_2)) in IsMultiplexingPossible()
711 if((data->proxytype == needle->proxytype) && in proxy_info_matches()
712 (data->port == needle->port) && in proxy_info_matches()
713 strcasecompare(data->host.name, needle->host.name)) in proxy_info_matches()
726 /* the user information is case-sensitive in socks_proxy_info_matches()
727 or at least it is not defined as case-insensitive in socks_proxy_info_matches()
728 see https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1 */ in socks_proxy_info_matches()
732 if(Curl_timestrcmp(data->user, needle->user) || in socks_proxy_info_matches()
733 Curl_timestrcmp(data->passwd, needle->passwd)) in socks_proxy_info_matches()
753 idletime = Curl_timediff(now, conn->lastused); in conn_maxage()
756 if(idletime > data->set.maxage_conn) { in conn_maxage()
762 lifetime = Curl_timediff(now, conn->created); in conn_maxage()
765 if(data->set.maxlifetime_conn && lifetime > data->set.maxlifetime_conn) { in conn_maxage()
778 * the connection cache if so.
781 * cache lock is held!
797 else if(conn->handler->connection_check) { in prune_if_dead()
806 state = conn->handler->connection_check(data, conn, CONNCHECK_ISDEAD); in prune_if_dead()
819 * that we expect - in general - no waiting input data. Input in prune_if_dead()
832 /* remove connection from cache */ in prune_if_dead()
834 conn->connection_id); in prune_if_dead()
859 * This function scans the connection cache for half-open/dead connections,
869 DEBUGASSERT(!data->conn); /* no connection */ in prune_dead_connections()
872 Curl_timediff(now, data->state.conn_cache->last_cleanup); in prune_dead_connections()
877 while(Curl_conncache_foreach(data, data->state.conn_cache, &pruned, in prune_dead_connections()
881 /* connection previously removed from cache in prune_if_dead() */ in prune_dead_connections()
887 data->state.conn_cache->last_cleanup = now; in prune_dead_connections()
896 return (Curl_safecmp(one->proto.sshc.rsa, two->proto.sshc.rsa) && in ssh_config_matches()
897 Curl_safecmp(one->proto.sshc.rsa_pub, two->proto.sshc.rsa_pub)); in ssh_config_matches()
908 * If there is a match, this function returns TRUE - and has marked the
909 * connection as 'in-use'. It must later be called with ConnectionDone() to
928 bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) && in ConnectionExists()
929 (needle->handler->protocol & PROTO_FAMILY_HTTP)); in ConnectionExists()
931 bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd && in ConnectionExists()
932 ((data->state.authproxy.want & in ConnectionExists()
934 (needle->handler->protocol & PROTO_FAMILY_HTTP))); in ConnectionExists()
940 bool h2upgrade = (data->state.httpwant == CURL_HTTP_VERSION_2_0) && in ConnectionExists()
941 (needle->handler->protocol & CURLPROTO_HTTP); in ConnectionExists()
948 Locks the connection cache, beware of early returns! */ in ConnectionExists()
949 bundle = Curl_conncache_find_bundle(data, needle, data->state.conn_cache); in ConnectionExists()
955 (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ? in ConnectionExists()
962 if(bundle->multiuse == BUNDLE_UNKNOWN) { in ConnectionExists()
963 if(data->set.pipewait) { in ConnectionExists()
971 else if(bundle->multiuse == BUNDLE_MULTIPLEX) { in ConnectionExists()
972 if(Curl_multiplex_wanted(data->multi)) in ConnectionExists()
977 else if(bundle->multiuse == BUNDLE_NO_MULTIUSE) { in ConnectionExists()
982 curr = bundle->conn_list.head; in ConnectionExists()
984 struct connectdata *check = curr->ptr; in ConnectionExists()
987 curr = curr->next; in ConnectionExists()
989 /* Note that if we use an HTTP proxy in normal mode (no tunneling), we in ConnectionExists()
990 * check connections to that proxy and not to the actual remote server. in ConnectionExists()
992 if(check->connect_only || check->bits.close) in ConnectionExists()
993 /* connect-only or to-be-closed connections will not be reused */ in ConnectionExists()
996 if(data->set.ipver != CURL_IPRESOLVE_WHATEVER in ConnectionExists()
997 && data->set.ipver != check->ip_version) { in ConnectionExists()
1006 !check->primary.remote_ip[0]) in ConnectionExists()
1017 struct Curl_llist_element *e = check->easyq.head; in ConnectionExists()
1018 struct Curl_easy *entry = e->ptr; in ConnectionExists()
1019 if(entry->multi != data->multi) in ConnectionExists()
1028 " isn't open enough, can't reuse", check->connection_id); in ConnectionExists()
1034 if(!check->bits.multiplex && CONN_INUSE(check)) in ConnectionExists()
1038 if(needle->unix_domain_socket) { in ConnectionExists()
1039 if(!check->unix_domain_socket) in ConnectionExists()
1041 if(strcmp(needle->unix_domain_socket, check->unix_domain_socket)) in ConnectionExists()
1043 if(needle->bits.abstract_unix_socket != in ConnectionExists()
1044 check->bits.abstract_unix_socket) in ConnectionExists()
1047 else if(check->unix_domain_socket) in ConnectionExists()
1051 if((needle->handler->flags&PROTOPT_SSL) != in ConnectionExists()
1052 (check->handler->flags&PROTOPT_SSL)) in ConnectionExists()
1053 /* don't do mixed SSL and non-SSL connections */ in ConnectionExists()
1054 if(get_protocol_family(check->handler) != in ConnectionExists()
1055 needle->handler->protocol || !check->bits.tls_upgraded) in ConnectionExists()
1059 if(needle->bits.conn_to_host != check->bits.conn_to_host) in ConnectionExists()
1064 if(needle->bits.conn_to_port != check->bits.conn_to_port) in ConnectionExists()
1070 if(needle->bits.httpproxy != check->bits.httpproxy || in ConnectionExists()
1071 needle->bits.socksproxy != check->bits.socksproxy) in ConnectionExists()
1074 if(needle->bits.socksproxy && in ConnectionExists()
1075 !socks_proxy_info_matches(&needle->socks_proxy, in ConnectionExists()
1076 &check->socks_proxy)) in ConnectionExists()
1079 if(needle->bits.httpproxy) { in ConnectionExists()
1080 if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy) in ConnectionExists()
1083 if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy)) in ConnectionExists()
1086 if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) { in ConnectionExists()
1088 if(needle->http_proxy.proxytype != check->http_proxy.proxytype) in ConnectionExists()
1090 /* match SSL config to proxy */ in ConnectionExists()
1094 " has different SSL proxy parameters, can't reuse", in ConnectionExists()
1095 check->connection_id)); in ConnectionExists()
1104 if(h2upgrade && !check->httpversion && canmultiplex) { in ConnectionExists()
1105 if(data->set.pipewait) { in ConnectionExists()
1115 if(needle->localdev || needle->localport) { in ConnectionExists()
1127 if((check->localport != needle->localport) || in ConnectionExists()
1128 (check->localportrange != needle->localportrange) || in ConnectionExists()
1129 (needle->localdev && in ConnectionExists()
1130 (!check->localdev || strcmp(check->localdev, needle->localdev)))) in ConnectionExists()
1134 if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { in ConnectionExists()
1137 if(Curl_timestrcmp(needle->user, check->user) || in ConnectionExists()
1138 Curl_timestrcmp(needle->passwd, check->passwd) || in ConnectionExists()
1139 Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) || in ConnectionExists()
1140 Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) { in ConnectionExists()
1148 if(needle->gssapi_delegation != check->gssapi_delegation) in ConnectionExists()
1153 if((needle->handler->protocol & PROTO_FAMILY_HTTP) && in ConnectionExists()
1154 (((check->httpversion >= 20) && in ConnectionExists()
1155 (data->state.httpwant < CURL_HTTP_VERSION_2_0)) in ConnectionExists()
1156 || ((check->httpversion >= 30) && in ConnectionExists()
1157 (data->state.httpwant < CURL_HTTP_VERSION_3)))) in ConnectionExists()
1160 else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) { in ConnectionExists()
1166 else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) { in ConnectionExists()
1167 /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */ in ConnectionExists()
1168 if(Curl_timestrcmp(needle->proto.ftpc.account, in ConnectionExists()
1169 check->proto.ftpc.account) || in ConnectionExists()
1170 Curl_timestrcmp(needle->proto.ftpc.alternative_to_user, in ConnectionExists()
1171 check->proto.ftpc.alternative_to_user) || in ConnectionExists()
1172 (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) || in ConnectionExists()
1173 (needle->proto.ftpc.ccc != check->proto.ftpc.ccc)) in ConnectionExists()
1179 * not talking to a HTTP proxy OR using a tunnel through a proxy */ in ConnectionExists()
1180 if((needle->handler->flags&PROTOPT_SSL) in ConnectionExists()
1182 || !needle->bits.httpproxy || needle->bits.tunnel_proxy in ConnectionExists()
1187 if(!strcasecompare(needle->handler->scheme, check->handler->scheme) && in ConnectionExists()
1188 (get_protocol_family(check->handler) != in ConnectionExists()
1189 needle->handler->protocol || !check->bits.tls_upgraded)) in ConnectionExists()
1193 if((needle->bits.conn_to_host && !strcasecompare( in ConnectionExists()
1194 needle->conn_to_host.name, check->conn_to_host.name)) || in ConnectionExists()
1195 (needle->bits.conn_to_port && in ConnectionExists()
1196 needle->conn_to_port != check->conn_to_port)) in ConnectionExists()
1200 if(!strcasecompare(needle->host.name, check->host.name) || in ConnectionExists()
1201 needle->remote_port != check->remote_port) in ConnectionExists()
1205 if((needle->handler->flags & PROTOPT_SSL) && in ConnectionExists()
1210 check->connection_id)); in ConnectionExists()
1222 if(Curl_timestrcmp(needle->user, check->user) || in ConnectionExists()
1223 Curl_timestrcmp(needle->passwd, check->passwd)) { in ConnectionExists()
1227 if(check->http_ntlm_state == NTLMSTATE_NONE) in ConnectionExists()
1232 else if(check->http_ntlm_state != NTLMSTATE_NONE) { in ConnectionExists()
1238 /* Same for Proxy NTLM authentication */ in ConnectionExists()
1240 /* Both check->http_proxy.user and check->http_proxy.passwd can be in ConnectionExists()
1242 if(!check->http_proxy.user || !check->http_proxy.passwd) in ConnectionExists()
1245 if(Curl_timestrcmp(needle->http_proxy.user, in ConnectionExists()
1246 check->http_proxy.user) || in ConnectionExists()
1247 Curl_timestrcmp(needle->http_proxy.passwd, in ConnectionExists()
1248 check->http_proxy.passwd)) in ConnectionExists()
1251 else if(check->proxy_ntlm_state != NTLMSTATE_NONE) { in ConnectionExists()
1252 /* Proxy connection is using NTLM auth but we don't want NTLM */ in ConnectionExists()
1264 (check->http_ntlm_state != NTLMSTATE_NONE)) || in ConnectionExists()
1266 (check->proxy_ntlm_state != NTLMSTATE_NONE))) { in ConnectionExists()
1278 DEBUGASSERT(check->bits.multiplex); in ConnectionExists()
1281 Curl_multi_max_concurrent_streams(data->multi)) { in ConnectionExists()
1315 if(foundPendingCandidate && data->set.pipewait) { in ConnectionExists()
1331 if(data->set.verbose && sockindex == SECONDARYSOCKET) in Curl_verboseconnect()
1333 conn->secondary.remote_ip, conn->secondary.remote_port); in Curl_verboseconnect()
1336 CURL_CONN_HOST_DISPNAME(conn), conn->primary.remote_ip, in Curl_verboseconnect()
1337 conn->primary.remote_port); in Curl_verboseconnect()
1352 conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */ in allocate_conn()
1353 conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */ in allocate_conn()
1354 conn->sockfd = CURL_SOCKET_BAD; in allocate_conn()
1355 conn->writesockfd = CURL_SOCKET_BAD; in allocate_conn()
1356 conn->connection_id = -1; /* no ID */ in allocate_conn()
1357 conn->primary.remote_port = -1; /* unknown at this point */ in allocate_conn()
1358 conn->remote_port = -1; /* unknown at this point */ in allocate_conn()
1360 /* Default protocol-independent behavior doesn't support persistent in allocate_conn()
1361 connections, so we set this to force-close. Protocols that support in allocate_conn()
1363 connclose(conn, "Default to force-close"); in allocate_conn()
1366 conn->created = Curl_now(); in allocate_conn()
1369 conn->keepalive = conn->created; in allocate_conn()
1372 conn->http_proxy.proxytype = data->set.proxytype; in allocate_conn()
1373 conn->socks_proxy.proxytype = CURLPROXY_SOCKS4; in allocate_conn()
1375 /* note that these two proxy bits are now just on what looks to be in allocate_conn()
1377 conn->bits.proxy = (data->set.str[STRING_PROXY] && in allocate_conn()
1378 *data->set.str[STRING_PROXY]) ? TRUE : FALSE; in allocate_conn()
1379 conn->bits.httpproxy = (conn->bits.proxy && in allocate_conn()
1380 (conn->http_proxy.proxytype == CURLPROXY_HTTP || in allocate_conn()
1381 conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 || in allocate_conn()
1382 IS_HTTPS_PROXY(conn->http_proxy.proxytype))) ? in allocate_conn()
1384 conn->bits.socksproxy = (conn->bits.proxy && in allocate_conn()
1385 !conn->bits.httpproxy) ? TRUE : FALSE; in allocate_conn()
1387 if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) { in allocate_conn()
1388 conn->bits.proxy = TRUE; in allocate_conn()
1389 conn->bits.socksproxy = TRUE; in allocate_conn()
1392 conn->bits.proxy_user_passwd = in allocate_conn()
1393 (data->state.aptr.proxyuser) ? TRUE : FALSE; in allocate_conn()
1394 conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy; in allocate_conn()
1398 conn->bits.ftp_use_epsv = data->set.ftp_use_epsv; in allocate_conn()
1399 conn->bits.ftp_use_eprt = data->set.ftp_use_eprt; in allocate_conn()
1401 conn->ip_version = data->set.ipver; in allocate_conn()
1402 conn->connect_only = data->set.connect_only; in allocate_conn()
1403 conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */ in allocate_conn()
1406 Curl_llist_init(&conn->easyq, NULL); in allocate_conn()
1409 conn->data_prot = PROT_CLEAR; in allocate_conn()
1413 if(data->set.str[STRING_DEVICE]) { in allocate_conn()
1414 conn->localdev = strdup(data->set.str[STRING_DEVICE]); in allocate_conn()
1415 if(!conn->localdev) in allocate_conn()
1419 conn->localportrange = data->set.localportrange; in allocate_conn()
1420 conn->localport = data->set.localport; in allocate_conn()
1425 conn->fclosesocket = data->set.fclosesocket; in allocate_conn()
1426 conn->closesocket_client = data->set.closesocket_client; in allocate_conn()
1427 conn->lastused = conn->created; in allocate_conn()
1428 conn->gssapi_delegation = data->set.gssapi_delegation; in allocate_conn()
1433 free(conn->localdev); in allocate_conn()
1443 /* returns the handler if the given scheme is built-in */
1648 l--; in Curl_getn_scheme_handler()
1652 if(h && strncasecompare(scheme, h->scheme, len) && !h->scheme[len]) in Curl_getn_scheme_handler()
1665 (data->set.allowed_protocols & p->protocol)) { in findprotocol()
1669 if(data->state.this_is_a_follow && in findprotocol()
1670 !(data->set.redir_protocols & p->protocol)) in findprotocol()
1675 conn->handler = conn->given = p; in findprotocol()
1682 to anything since it is already assigned to a dummy-struct in the in findprotocol()
1686 data->state.this_is_a_follow ? " (in redirect)":""); in findprotocol()
1726 conn->scope_id = (unsigned int)scope;
1749 conn->scope_id = scopeidx;
1770 bool use_set_uh = (data->set.uh && !data->state.this_is_a_follow);
1776 uh = data->state.uh = curl_url_dup(data->set.uh);
1779 uh = data->state.uh = curl_url();
1785 if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
1786 !Curl_is_absolute_url(data->state.url, NULL, 0, TRUE)) {
1787 char *url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
1788 data->state.url);
1791 if(data->state.url_alloc)
1792 free(data->state.url);
1793 data->state.url = url;
1794 data->state.url_alloc = TRUE;
1799 uc = curl_url_set(uh, CURLUPART_URL, data->state.url,
1802 (data->set.disallow_username_in_url ?
1804 (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
1814 if(data->state.url_alloc)
1815 free(data->state.url);
1816 data->state.url = newurl;
1817 data->state.url_alloc = TRUE;
1820 uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
1824 uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
1826 if(!strcasecompare("file", data->state.up.scheme))
1829 else if(strlen(data->state.up.hostname) > MAX_URL_LEN) {
1833 hostname = data->state.up.hostname;
1839 conn->bits.ipv6_ip = TRUE;
1843 hostname[hlen - 1] = 0;
1849 conn->host.rawalloc = strdup(hostname ? hostname : "");
1850 if(!conn->host.rawalloc)
1852 conn->host.name = conn->host.rawalloc;
1855 * IDN-convert the hostnames
1857 result = Curl_idnconvert_hostname(&conn->host);
1863 if(data->hsts && strcasecompare("http", data->state.up.scheme)) {
1865 if(Curl_hsts(data->hsts, conn->host.name, TRUE)) {
1867 Curl_safefree(data->state.up.scheme);
1871 if(data->state.url_alloc)
1872 Curl_safefree(data->state.url);
1877 uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
1882 data->state.url = url;
1883 data->state.url_alloc = TRUE;
1885 data->state.url);
1890 result = findprotocol(data, conn, data->state.up.scheme);
1898 if(!data->set.str[STRING_PASSWORD]) {
1899 uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
1902 result = Curl_urldecode(data->state.up.password, 0, &decoded, NULL,
1903 conn->handler->flags&PROTOPT_USERPWDCTRL ?
1907 conn->passwd = decoded;
1908 result = Curl_setstropt(&data->state.aptr.passwd, decoded);
1916 if(!data->set.str[STRING_USERNAME]) {
1920 uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0);
1923 result = Curl_urldecode(data->state.up.user, 0, &decoded, NULL,
1924 conn->handler->flags&PROTOPT_USERPWDCTRL ?
1928 conn->user = decoded;
1929 result = Curl_setstropt(&data->state.aptr.user, decoded);
1933 else if(data->state.aptr.passwd) {
1935 result = Curl_setstropt(&data->state.aptr.user, "");
1941 uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options,
1944 conn->options = strdup(data->state.up.options);
1945 if(!conn->options)
1951 uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path,
1956 uc = curl_url_get(uh, CURLUPART_PORT, &data->state.up.port,
1959 if(!strcasecompare("file", data->state.up.scheme))
1963 unsigned long port = strtoul(data->state.up.port, NULL, 10);
1964 conn->primary.remote_port = conn->remote_port =
1965 (data->set.use_port && data->state.allow_port) ?
1966 data->set.use_port : curlx_ultous(port);
1969 (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
1972 if(data->set.scope_id)
1974 conn->scope_id = data->set.scope_id;
1987 struct UrlState *s = &data->state;
1988 s->resume_from = data->set.set_resume_from;
1989 if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
1990 if(s->rangestringalloc)
1991 free(s->range);
1993 if(s->resume_from)
1994 s->range = aprintf("%" CURL_FORMAT_CURL_OFF_T "-", s->resume_from);
1996 s->range = strdup(data->set.str[STRING_SET_RANGE]);
1998 s->rangestringalloc = (s->range) ? TRUE : FALSE;
2000 if(!s->range)
2004 s->use_range = TRUE; /* enable range download */
2007 s->use_range = FALSE; /* disable range download */
2014 * setup_connection_internals() -
2020 * This MUST get called after proxy magic has been figured out.
2029 p = conn->handler;
2031 if(p->setup_connection) {
2032 result = (*p->setup_connection)(data, conn);
2037 p = conn->handler; /* May have changed. */
2040 if(conn->primary.remote_port < 0)
2041 /* we check for -1 here since if proxy was detected already, this
2042 was very likely already set to the proxy port */
2043 conn->primary.remote_port = p->defport;
2053 * Detect what (if any) proxy to use. Remember that this selects a host
2060 char *proxy = NULL; local
2062 /* If proxy was not specified, we check for default proxy environment
2069 * (a comma-separated list of hosts which should
2071 * all proxy variables)
2076 * For compatibility, the all-uppercase versions of these variables are
2085 msnprintf(proxy_env, sizeof(proxy_env), "%s_proxy", conn->handler->scheme);
2087 /* read the protocol proxy: */
2088 proxy = curl_getenv(proxy_env);
2097 * http header 'Proxy:' to some value.
2102 if(!proxy && !strcasecompare("http_proxy", proxy_env)) {
2105 proxy = curl_getenv(proxy_env);
2108 if(!proxy) {
2110 /* websocket proxy fallbacks */
2112 proxy = curl_getenv("http_proxy");
2115 proxy = curl_getenv("https_proxy");
2116 if(!proxy)
2117 proxy = curl_getenv("HTTPS_PROXY");
2119 if(!proxy) {
2122 proxy = curl_getenv(envp); /* default proxy to use */
2123 if(!proxy) {
2125 proxy = curl_getenv(envp);
2131 if(proxy)
2132 infof(data, "Uses proxy env variable %s == '%s'", envp, proxy);
2134 return proxy;
2139 * If this is supposed to use a proxy, we need to figure out the proxy
2141 * that may exist registered to the same proxy host.
2144 struct connectdata *conn, char *proxy, argument
2148 int port = -1;
2169 /* When parsing the proxy, allowing non-supported schemes since we have
2171 uc = curl_url_set(uhp, CURLUPART_URL, proxy,
2200 failf(data, "Unsupported proxy scheme for \'%s\'", proxy);
2206 failf(data, "Unsupported proxy syntax in \'%s\': %s", proxy,
2216 failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
2217 "HTTPS-proxy support.", proxy);
2228 proxyinfo = sockstype ? &conn->socks_proxy : &conn->http_proxy;
2229 proxyinfo->proxytype = (unsigned char)proxytype;
2231 /* Is there a username and password given in this proxy url? */
2240 Curl_safefree(proxyinfo->user);
2241 proxyinfo->user = proxyuser;
2242 result = Curl_setstropt(&data->state.aptr.proxyuser, proxyuser);
2246 Curl_safefree(proxyinfo->passwd);
2254 proxyinfo->passwd = proxypasswd;
2255 result = Curl_setstropt(&data->state.aptr.proxypasswd, proxypasswd);
2259 conn->bits.proxy_user_passwd = TRUE; /* enable it */
2269 if(data->set.proxyport)
2270 /* None given in the proxy string, then get the default one if it is
2272 port = (int)data->set.proxyport;
2281 proxyinfo->port = port;
2282 if(conn->primary.remote_port < 0 || sockstype ||
2283 !conn->socks_proxy.host.rawalloc)
2284 conn->primary.remote_port = port;
2287 /* now, clone the proxy host name */
2309 Curl_safefree(proxyinfo->host.rawalloc);
2310 proxyinfo->host.rawalloc = host;
2311 proxyinfo->host.name = host;
2318 Curl_safefree(proxyinfo->host.rawalloc);
2319 proxyinfo->host.rawalloc = host;
2323 host[len-1] = 0; /* clear the trailing bracket */
2327 proxyinfo->host.name = host;
2351 const char *proxyuser = data->state.aptr.proxyuser ?
2352 data->state.aptr.proxyuser : "";
2353 const char *proxypasswd = data->state.aptr.proxypasswd ?
2354 data->state.aptr.proxypasswd : "";
2357 conn->http_proxy.user = strdup(proxyuser);
2358 if(conn->http_proxy.user) {
2359 conn->http_proxy.passwd = strdup(proxypasswd);
2360 if(conn->http_proxy.passwd)
2363 Curl_safefree(conn->http_proxy.user);
2368 /* create_conn helper to parse and init proxy values. to be called after unix
2369 socket init but before any proxy vars are evaluated. */
2373 char *proxy = NULL; local
2382 if(conn->bits.proxy_user_passwd) {
2389 * Detect what (if any) proxy to use
2391 if(data->set.str[STRING_PROXY]) {
2392 proxy = strdup(data->set.str[STRING_PROXY]);
2393 /* if global proxy is set, this is it */
2394 if(!proxy) {
2401 if(data->set.str[STRING_PRE_PROXY]) {
2402 socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
2403 /* if global socks proxy is set, this is it */
2411 if(!data->set.str[STRING_NOPROXY]) {
2419 infof(data, "Uses proxy env variable %s == '%s'", p, no_proxy);
2423 if(Curl_check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
2424 data->set.str[STRING_NOPROXY] : no_proxy,
2426 Curl_safefree(proxy);
2430 else if(!proxy && !socksproxy)
2431 /* if the host is not in the noproxy list, detect proxy. */
2432 proxy = detect_proxy(data, conn);
2435 infof(data, "space-separated NOPROXY patterns are deprecated");
2440 /* For the time being do not mix proxy and unix domain sockets. See #1274 */
2441 if(proxy && conn->unix_domain_socket) {
2442 free(proxy);
2443 proxy = NULL;
2447 if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
2448 free(proxy); /* Don't bother with an empty proxy string or if the
2450 proxy = NULL;
2453 (conn->handler->flags & PROTOPT_NONETWORK))) {
2454 free(socksproxy); /* Don't bother with an empty socks proxy string or if
2460 * If this is supposed to use a proxy, we need to figure out the proxy host
2461 * name, proxy type and port number, so that we can reuse an existing
2462 * connection that may exist registered to the same proxy host.
2464 if(proxy || socksproxy) {
2465 curl_proxytype ptype = (curl_proxytype)conn->http_proxy.proxytype;
2466 if(proxy) {
2467 result = parse_proxy(data, conn, proxy, ptype);
2468 Curl_safefree(proxy); /* parse_proxy copies the proxy string */
2475 /* parse_proxy copies the socks proxy string */
2481 if(conn->http_proxy.host.rawalloc) {
2483 /* asking for an HTTP proxy is a bit funny when HTTP is disabled... */
2488 if(!(conn->handler->protocol & PROTO_FAMILY_HTTP)) {
2489 if((conn->handler->flags & PROTOPT_PROXY_AS_HTTP) &&
2490 !conn->bits.tunnel_proxy)
2491 conn->handler = &Curl_handler_http;
2493 /* if not converting to HTTP over the proxy, enforce tunneling */
2494 conn->bits.tunnel_proxy = TRUE;
2496 conn->bits.httpproxy = TRUE;
2500 conn->bits.httpproxy = FALSE; /* not an HTTP proxy */
2501 conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
2504 if(conn->socks_proxy.host.rawalloc) {
2505 if(!conn->http_proxy.host.rawalloc) {
2506 /* once a socks proxy */
2507 if(!conn->socks_proxy.user) {
2508 conn->socks_proxy.user = conn->http_proxy.user;
2509 conn->http_proxy.user = NULL;
2510 Curl_safefree(conn->socks_proxy.passwd);
2511 conn->socks_proxy.passwd = conn->http_proxy.passwd;
2512 conn->http_proxy.passwd = NULL;
2515 conn->bits.socksproxy = TRUE;
2518 conn->bits.socksproxy = FALSE; /* not a socks proxy */
2521 conn->bits.socksproxy = FALSE;
2522 conn->bits.httpproxy = FALSE;
2524 conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
2526 if(!conn->bits.proxy) {
2527 /* we aren't using the proxy after all... */
2528 conn->bits.proxy = FALSE;
2529 conn->bits.httpproxy = FALSE;
2530 conn->bits.socksproxy = FALSE;
2531 conn->bits.proxy_user_passwd = FALSE;
2532 conn->bits.tunnel_proxy = FALSE;
2533 /* CURLPROXY_HTTPS does not have its own flag in conn->bits, yet we need
2535 conn->http_proxy.proxytype = CURLPROXY_HTTP;
2541 free(proxy);
2564 * login [in] - login string.
2565 * len [in] - length of the login string.
2566 * userp [in/out] - address where a pointer to newly allocated memory
2568 * passwdp [in/out] - address where a pointer to newly allocated memory
2570 * optionsp [in/out] - OPTIONAL address where a pointer to newly allocated
2600 (size_t)(osep && psep > osep ? osep - login : psep - login) :
2601 (osep ? (size_t)(osep - login) : len));
2603 (osep && osep > psep ? (size_t)(osep - psep) :
2604 (size_t)(login + len - psep)) - 1 : 0);
2606 (psep && psep > osep ? (size_t)(psep - osep) :
2607 (size_t)(login + len - osep)) - 1 : 0);
2641 * Figure out the remote port number and fix it in the URL
2643 * No matter if we use a proxy or not, we have to figure out the remote
2652 if(data->set.use_port && data->state.allow_port) {
2656 conn->remote_port = data->set.use_port;
2657 msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port);
2658 uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
2674 char **userp = &conn->user;
2675 char **passwdp = &conn->passwd;
2676 char **optionsp = &conn->options;
2678 if(data->set.str[STRING_OPTIONS]) {
2680 *optionsp = strdup(data->set.str[STRING_OPTIONS]);
2686 if(data->set.use_netrc == CURL_NETRC_REQUIRED) {
2690 conn->bits.netrc = FALSE;
2691 if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) {
2695 if(data->state.aptr.user) {
2697 userp = &data->state.aptr.user;
2701 ret = Curl_parsenetrc(conn->host.name,
2703 data->set.str[STRING_NETRC_FILE]);
2706 conn->host.name,
2707 (data->set.str[STRING_NETRC_FILE] ?
2708 data->set.str[STRING_NETRC_FILE] : ".netrc"));
2718 conn->bits.netrc = TRUE;
2721 Curl_safefree(conn->user);
2722 conn->user = strdup(*userp);
2723 if(!conn->user)
2738 if(data->state.aptr.user != *userp) {
2740 result = Curl_setstropt(&data->state.aptr.user, *userp);
2745 if(data->state.aptr.user) {
2746 uc = curl_url_set(data->state.uh, CURLUPART_USER, data->state.aptr.user,
2751 *userp = strdup(data->state.aptr.user);
2757 CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp);
2761 if(data->state.aptr.passwd) {
2762 uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD,
2763 data->state.aptr.passwd, CURLU_URLENCODE);
2767 *passwdp = strdup(data->state.aptr.passwd);
2787 if((conn->handler->flags & PROTOPT_NEEDSPWD) && !data->state.aptr.user)
2794 if(!conn->user) {
2795 conn->user = strdup(setuser);
2796 if(!conn->user)
2801 if(!conn->passwd) {
2802 conn->passwd = strdup(setpasswd);
2803 if(!conn->passwd)
2813 * the hostname and -1 for the port.
2824 int port = -1;
2832 *port_result = -1;
2846 /* detect and extract RFC6874-style IPv6-addresses */
2858 while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
2873 failf(data, "Use of IPv6 in *_CONNECT_TO without IPv6 support built-in");
2915 * "HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT".
2929 *port_result = -1;
2940 conn->bits.ipv6_ip ? "[" : "",
2941 conn->host.name,
2942 conn->bits.ipv6_ip ? "]" : "");
2967 if((endp == ptr_next) && (port_to_match == conn->remote_port)) {
2993 int port = -1;
2995 while(conn_to_host && !host && port == -1) {
2996 result = parse_connect_to_string(data, conn, conn_to_host->data,
3002 conn->conn_to_host.rawalloc = host;
3003 conn->conn_to_host.name = host;
3004 conn->bits.conn_to_host = TRUE;
3010 conn->bits.conn_to_host = FALSE;
3015 conn->conn_to_port = port;
3016 conn->bits.conn_to_port = TRUE;
3021 conn->bits.conn_to_port = FALSE;
3022 port = -1;
3025 conn_to_host = conn_to_host->next;
3029 if(data->asi && !host && (port == -1) &&
3030 ((conn->handler->protocol == CURLPROTO_HTTPS) ||
3038 /* no connect_to match, try alt-svc! */
3049 ) & data->asi->flags;
3051 host = conn->host.rawalloc;
3055 hit = Curl_altsvc_lookup(data->asi,
3056 srcalpnid, host, conn->remote_port, /* from */
3063 hit = Curl_altsvc_lookup(data->asi,
3064 srcalpnid, host, conn->remote_port, /* from */
3069 char *hostd = strdup((char *)as->dst.host);
3072 conn->conn_to_host.rawalloc = hostd;
3073 conn->conn_to_host.name = hostd;
3074 conn->bits.conn_to_host = TRUE;
3075 conn->conn_to_port = as->dst.port;
3076 conn->bits.conn_to_port = TRUE;
3077 conn->bits.altused = TRUE;
3078 infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d",
3079 Curl_alpnid2str(srcalpnid), host, conn->remote_port,
3080 Curl_alpnid2str(as->dst.alpnid), hostd, as->dst.port);
3081 if(srcalpnid != as->dst.alpnid) {
3083 switch(as->dst.alpnid) {
3085 conn->httpversion = 11;
3088 conn->httpversion = 20;
3091 conn->transport = TRNSPRT_QUIC;
3092 conn->httpversion = 30;
3114 DEBUGASSERT(conn->dns_entry == NULL);
3117 * specified domain socket address. Do not cache "DNS entries". There is
3123 hostaddr->addr = Curl_unix2addr(unix_path, &longpath,
3124 conn->bits.abstract_unix_socket);
3125 if(!hostaddr->addr) {
3133 hostaddr->inuse++;
3134 conn->dns_entry = hostaddr;
3149 DEBUGASSERT(conn->dns_entry == NULL);
3151 host = conn->bits.socksproxy ? &conn->socks_proxy.host :
3152 &conn->http_proxy.host;
3154 conn->hostname_resolve = strdup(host->name);
3155 if(!conn->hostname_resolve)
3158 rc = Curl_resolv_timeout(data, conn->hostname_resolve,
3159 conn->primary.remote_port, &hostaddr, timeout_ms);
3160 conn->dns_entry = hostaddr;
3166 failf(data, "Couldn't resolve proxy '%s'", host->dispname);
3183 DEBUGASSERT(conn->dns_entry == NULL);
3185 connhost = conn->bits.conn_to_host ? &conn->conn_to_host : &conn->host;
3187 /* If not connecting via a proxy, extract the port from the URL, if it is
3189 conn->primary.remote_port = conn->bits.conn_to_port ? conn->conn_to_port :
3190 conn->remote_port;
3193 conn->hostname_resolve = strdup(connhost->name);
3194 if(!conn->hostname_resolve)
3197 rc = Curl_resolv_timeout(data, conn->hostname_resolve,
3198 conn->primary.remote_port, &hostaddr, timeout_ms);
3199 conn->dns_entry = hostaddr;
3204 CURL_FORMAT_TIMEDIFF_T " ms", connhost->dispname,
3205 Curl_timediff(Curl_now(), data->progress.t_startsingle));
3209 failf(data, "Could not resolve host: %s", connhost->dispname);
3222 char *unix_path = conn->unix_domain_socket;
3225 if(!unix_path && conn->socks_proxy.host.name &&
3227 conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX)))
3228 unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1;
3232 conn->transport = TRNSPRT_UNIX;
3246 * Resolve the address of the server or proxy
3255 /* Resolve the name of the server or proxy */
3256 if(conn->bits.reuse) {
3257 /* We're reusing the connection - no need to resolve anything, and
3278 if(temp->user) {
3280 Curl_safefree(existing->user);
3281 Curl_safefree(existing->passwd);
3282 existing->user = temp->user;
3283 existing->passwd = temp->passwd;
3284 temp->user = NULL;
3285 temp->passwd = NULL;
3289 existing->bits.proxy_user_passwd = temp->bits.proxy_user_passwd;
3290 if(existing->bits.proxy_user_passwd) {
3291 /* use the new proxy user name and proxy password though */
3292 Curl_safefree(existing->http_proxy.user);
3293 Curl_safefree(existing->socks_proxy.user);
3294 Curl_safefree(existing->http_proxy.passwd);
3295 Curl_safefree(existing->socks_proxy.passwd);
3296 existing->http_proxy.user = temp->http_proxy.user;
3297 existing->socks_proxy.user = temp->socks_proxy.user;
3298 existing->http_proxy.passwd = temp->http_proxy.passwd;
3299 existing->socks_proxy.passwd = temp->socks_proxy.passwd;
3300 temp->http_proxy.user = NULL;
3301 temp->socks_proxy.user = NULL;
3302 temp->http_proxy.passwd = NULL;
3303 temp->socks_proxy.passwd = NULL;
3307 /* Finding a connection for reuse in the cache matches, among other
3308 * things on the "remote-relevant" hostname. This is not necessarily
3309 * the authority of the URL, e.g. conn->host. For example:
3310 * - we use a proxy (not tunneling). we want to send all requests
3311 * that use the same proxy on this connection.
3312 * - we have a "connect-to" setting that may redirect the hostname of
3313 * a new request to the same remote endpoint of an existing conn.
3314 * We want to reuse an existing conn to the remote endpoint.
3315 * Since connection reuse does not match on conn->host necessarily, we
3321 Curl_free_idnconverted_hostname(&existing->host);
3322 Curl_free_idnconverted_hostname(&existing->conn_to_host);
3323 Curl_safefree(existing->host.rawalloc);
3324 Curl_safefree(existing->conn_to_host.rawalloc);
3325 existing->host = temp->host;
3326 temp->host.rawalloc = NULL;
3327 temp->host.encalloc = NULL;
3328 existing->conn_to_host = temp->conn_to_host;
3329 temp->conn_to_host.rawalloc = NULL;
3330 existing->conn_to_port = temp->conn_to_port;
3331 existing->remote_port = temp->remote_port;
3332 Curl_safefree(existing->hostname_resolve);
3334 existing->hostname_resolve = temp->hostname_resolve;
3335 temp->hostname_resolve = NULL;
3338 existing->bits.reuse = TRUE; /* yes, we're reusing here */
3369 size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
3370 size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
3378 if(!data->state.url) {
3403 if(data->set.str[STRING_SASL_AUTHZID]) {
3404 conn->sasl_authzid = strdup(data->set.str[STRING_SASL_AUTHZID]);
3405 if(!conn->sasl_authzid) {
3411 if(data->set.str[STRING_BEARER]) {
3412 conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
3413 if(!conn->oauth_bearer) {
3420 if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
3421 conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
3422 if(!conn->unix_domain_socket) {
3426 conn->bits.abstract_unix_socket = data->set.abstract_unix_socket;
3430 /* After the unix socket init but before the proxy vars are used, parse and
3431 initialize the proxy vars */
3438 * If the protocol is using SSL and HTTP proxy is used, we set
3441 if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
3442 conn->bits.tunnel_proxy = TRUE;
3446 * Figure out the remote port number and fix it in the URL
3453 they are known when protocol->setup_connection is called! */
3464 * Do this after the remote port number has been fixed in the URL.
3466 result = parse_connect_to_slist(data, conn, data->set.connect_to);
3471 * IDN-convert the proxy hostnames
3474 if(conn->bits.httpproxy) {
3475 result = Curl_idnconvert_hostname(&conn->http_proxy.host);
3479 if(conn->bits.socksproxy) {
3480 result = Curl_idnconvert_hostname(&conn->socks_proxy.host);
3485 if(conn->bits.conn_to_host) {
3486 result = Curl_idnconvert_hostname(&conn->conn_to_host);
3493 * Do this after the hostnames have been IDN-converted.
3495 if(conn->bits.conn_to_host &&
3496 strcasecompare(conn->conn_to_host.name, conn->host.name)) {
3497 conn->bits.conn_to_host = FALSE;
3502 * Do this after the remote port number has been fixed in the URL.
3504 if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
3505 conn->bits.conn_to_port = FALSE;
3510 * If the "connect to" feature is used with an HTTP proxy,
3513 if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
3514 conn->bits.httpproxy)
3515 conn->bits.tunnel_proxy = TRUE;
3520 * we figured out what/if proxy to use.
3530 if(conn->handler->flags & PROTOPT_NONETWORK) {
3534 DEBUGASSERT(conn->handler->connect_it);
3536 result = conn->handler->connect_it(data, &done);
3550 DEBUGASSERT(conn->handler->done);
3551 /* we ignore the return code for the protocol-specific DONE */
3552 (void)conn->handler->done(data, result, FALSE);
3555 Curl_xfer_setup(data, -1, -1, FALSE, -1);
3566 conn->recv[FIRSTSOCKET] = Curl_cf_recv;
3567 conn->send[FIRSTSOCKET] = Curl_cf_send;
3568 conn->recv[SECONDARYSOCKET] = Curl_cf_recv;
3569 conn->send[SECONDARYSOCKET] = Curl_cf_send;
3570 conn->bits.tcp_fastopen = data->set.tcp_fastopen;
3572 /* Complete the easy's SSL configuration for connection cache matching */
3585 DEBUGASSERT(conn->user);
3586 DEBUGASSERT(conn->passwd);
3590 already (which happens due to follow-location or during an HTTP
3592 if((data->set.reuse_fresh && !data->state.followlocation) ||
3593 data->set.connect_only)
3609 infof(data, "Re-using existing connection with %s %s",
3610 conn->bits.proxy?"proxy":"host",
3611 conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
3612 conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
3613 conn->host.dispname);
3615 infof(data, "Re-using existing connection with host %s",
3616 conn->host.dispname);
3624 if(conn->handler->flags & PROTOPT_ALPN) {
3625 /* The protocol wants it, so set the bits if enabled in the easy handle
3627 if(data->set.ssl_enable_alpn)
3628 conn->bits.tls_enable_alpn = TRUE;
3638 Curl_conncache_find_bundle(data, conn, data->state.conn_cache);
3641 (bundle->num_connections >= max_host_connections)) {
3666 /* The cache is full. Let's see if we can kill a connection. */
3671 infof(data, "No connections available in cache");
3688 * cache of ours!
3706 if((data->state.authhost.picked & CURLAUTH_NTLM) &&
3707 data->state.authhost.done) {
3709 data->state.authhost.picked = CURLAUTH_NONE;
3710 data->state.authhost.done = FALSE;
3713 if((data->state.authproxy.picked & CURLAUTH_NTLM) &&
3714 data->state.authproxy.done) {
3715 infof(data, "NTLM-proxy picked AND auth done set, clear picked");
3716 data->state.authproxy.picked = CURLAUTH_NONE;
3717 data->state.authproxy.done = FALSE;
3735 * Resolve the address of the server or proxy
3759 struct connectdata *conn = data->conn;
3763 if(conn->handler->flags & PROTOPT_NONETWORK) {
3772 case of proxy CONNECT failures and we must make sure we don't have it
3774 conn->bits.proxy_connect_closed = FALSE;
3778 data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
3783 conn->now = Curl_now();
3784 if(!conn->bits.reuse)
3785 result = Curl_conn_setup(data, conn, FIRSTSOCKET, conn->dns_entry,
3805 Curl_req_hard_reset(&data->req, data);
3838 * the DO function before the protocol-specific DO functions are invoked) for
3852 conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
3855 if(data->state.wildcardmatch &&
3856 !(conn->handler->flags & PROTOPT_WILDCARD))
3857 data->state.wildcardmatch = FALSE;
3860 data->state.done = FALSE; /* *_done() is not called yet */
3862 if(data->req.no_body)
3864 data->state.httpreq = HTTPREQ_HEAD;
3866 result = Curl_req_start(&data->req, data);
3882 struct Curl_data_prio_node **pnext = &parent->set.priority.children;
3883 struct Curl_data_prio_node *pnode = parent->set.priority.children;
3885 DEBUGASSERT(child->set.priority.parent == parent);
3886 while(pnode && pnode->data != child) {
3887 pnext = &pnode->next;
3888 pnode = pnode->next;
3893 *pnext = pnode->next;
3897 child->set.priority.parent = 0;
3898 child->set.priority.exclusive = FALSE;
3905 if(child->set.priority.parent) {
3906 priority_remove_child(child->set.priority.parent, child);
3916 pnode->data = child;
3918 if(parent->set.priority.children && exclusive) {
3920 struct Curl_data_prio_node *node = parent->set.priority.children;
3922 node->data->set.priority.parent = child;
3923 node = node->next;
3926 tail = &child->set.priority.children;
3928 tail = &(*tail)->next;
3931 *tail = parent->set.priority.children;
3932 parent->set.priority.children = 0;
3935 tail = &parent->set.priority.children;
3937 (*tail)->data->set.priority.exclusive = FALSE;
3938 tail = &(*tail)->next;
3945 child->set.priority.parent = parent;
3946 child->set.priority.exclusive = exclusive;
3955 while(data->set.priority.children) {
3956 struct Curl_easy *tmp = data->set.priority.children->data;
3958 if(data->set.priority.parent)
3959 Curl_data_priority_add_child(data->set.priority.parent, tmp, FALSE);
3962 if(data->set.priority.parent)
3963 priority_remove_child(data->set.priority.parent, data);
3969 memset(&data->state.priority, 0, sizeof(data->state.priority));