1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
25 #ifdef HAVE_NETINET_IN_H
26 #include <netinet/in.h>
31 #ifdef HAVE_ARPA_INET_H
32 #include <arpa/inet.h>
37 #ifdef HAVE_IPHLPAPI_H
40 #ifdef HAVE_SYS_IOCTL_H
41 #include <sys/ioctl.h>
43 #ifdef HAVE_SYS_PARAM_H
44 #include <sys/param.h>
57 #error "We can't compile without socket() support!"
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);
69 #elif defined(USE_ICU_IDNA)
70 #include <unicode/uidna.h>
71 #endif /* USE_LIBIDN2 */
78 #include "vtls/vtls.h"
89 #include "content_encoding.h"
90 #include "http_digest.h"
91 #include "http_negotiate.h"
95 #include "speedcheck.h"
97 #include "non-ascii.h"
98 #include "inet_pton.h"
100 #include "urlapi-int.h"
101 #include "system_win32.h"
103 /* And now for the protocols */
111 #include "curl_ldap.h"
112 #include "vssh/ssh.h"
116 #include "inet_ntop.h"
117 #include "http_ntlm.h"
118 #include "curl_rtmp.h"
121 #include "http_proxy.h"
122 #include "conncache.h"
123 #include "multihandle.h"
130 /* The last 3 #include files should be in this order */
131 #include "curl_printf.h"
132 #include "curl_memory.h"
133 #include "memdebug.h"
135 #if defined(USE_ICU_IDNA)
136 #define MAX_DOMAIN_NAME_LEN 256
137 #endif /* USE_ICU_IDNA */
139 static void conn_free(struct connectdata *conn);
141 /* Some parts of the code (e.g. chunked encoding) assume this buffer has at
142 * more than just a few bytes to play with. Don't let it become too small or
143 * bad things will happen.
145 #if READBUFFER_SIZE < READBUFFER_MIN
146 # error READBUFFER_SIZE is too small
150 * get_protocol_family()
152 * This is used to return the protocol family for a given protocol.
156 * 'h' [in] - struct Curl_handler pointer.
158 * Returns the family as a single bit protocol identifier.
160 static unsigned int get_protocol_family(const struct Curl_handler *h)
163 DEBUGASSERT(h->family);
169 * Protocol table. Schemes (roughly) in 2019 popularity order:
171 * HTTPS, HTTP, FTP, FTPS, SFTP, FILE, SCP, SMTP, LDAP, IMAPS, TELNET, IMAP,
172 * LDAPS, SMTPS, TFTP, SMB, POP3, GOPHER POP3S, RTSP, RTMP, SMBS, DICT
174 static const struct Curl_handler * const protocols[] = {
176 #if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
180 #ifndef CURL_DISABLE_HTTP
184 #ifndef CURL_DISABLE_FTP
188 #if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
196 #ifndef CURL_DISABLE_FILE
200 #if defined(USE_SSH) && !defined(USE_WOLFSSH)
204 #ifndef CURL_DISABLE_SMTP
211 #ifndef CURL_DISABLE_LDAP
213 #if !defined(CURL_DISABLE_LDAPS) && \
214 ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
215 (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
220 #ifndef CURL_DISABLE_IMAP
227 #ifndef CURL_DISABLE_TELNET
228 &Curl_handler_telnet,
231 #ifndef CURL_DISABLE_TFTP
235 #ifndef CURL_DISABLE_POP3
242 #if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
243 (CURL_SIZEOF_CURL_OFF_T > 4)
250 #ifndef CURL_DISABLE_RTSP
254 #ifndef CURL_DISABLE_MQTT
258 #ifndef CURL_DISABLE_GOPHER
259 &Curl_handler_gopher,
266 &Curl_handler_rtmpte,
268 &Curl_handler_rtmpts,
271 #ifndef CURL_DISABLE_DICT
275 (struct Curl_handler *) NULL
279 * Dummy handler for undefined protocol schemes.
282 static const struct Curl_handler Curl_handler_dummy = {
283 "<no protocol>", /* scheme */
284 ZERO_NULL, /* setup_connection */
285 ZERO_NULL, /* do_it */
286 ZERO_NULL, /* done */
287 ZERO_NULL, /* do_more */
288 ZERO_NULL, /* connect_it */
289 ZERO_NULL, /* connecting */
290 ZERO_NULL, /* doing */
291 ZERO_NULL, /* proto_getsock */
292 ZERO_NULL, /* doing_getsock */
293 ZERO_NULL, /* domore_getsock */
294 ZERO_NULL, /* perform_getsock */
295 ZERO_NULL, /* disconnect */
296 ZERO_NULL, /* readwrite */
297 ZERO_NULL, /* connection_check */
301 PROTOPT_NONE /* flags */
304 void Curl_freeset(struct Curl_easy *data)
306 /* Free all dynamic strings stored in the data->set substructure. */
310 for(i = (enum dupstring)0; i < STRING_LAST; i++) {
311 Curl_safefree(data->set.str[i]);
314 for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
315 Curl_safefree(data->set.blobs[j]);
318 if(data->change.referer_alloc) {
319 Curl_safefree(data->change.referer);
320 data->change.referer_alloc = FALSE;
322 data->change.referer = NULL;
323 if(data->change.url_alloc) {
324 Curl_safefree(data->change.url);
325 data->change.url_alloc = FALSE;
327 data->change.url = NULL;
329 Curl_mime_cleanpart(&data->set.mimepost);
332 /* free the URL pieces */
333 static void up_free(struct Curl_easy *data)
335 struct urlpieces *up = &data->state.up;
336 Curl_safefree(up->scheme);
337 Curl_safefree(up->hostname);
338 Curl_safefree(up->port);
339 Curl_safefree(up->user);
340 Curl_safefree(up->password);
341 Curl_safefree(up->options);
342 Curl_safefree(up->path);
343 Curl_safefree(up->query);
344 curl_url_cleanup(data->state.uh);
345 data->state.uh = NULL;
349 * This is the internal function curl_easy_cleanup() calls. This should
350 * cleanup and free all resources associated with this sessionhandle.
352 * NOTE: if we ever add something that attempts to write to a socket or
353 * similar here, we must ignore SIGPIPE first. It is currently only done
354 * when curl_easy_perform() is invoked.
357 CURLcode Curl_close(struct Curl_easy **datap)
359 struct Curl_multi *m;
360 struct Curl_easy *data;
362 if(!datap || !*datap)
368 Curl_expire_clear(data); /* shut off timers */
372 /* This handle is still part of a multi handle, take care of this first
373 and detach this handle from there. */
374 curl_multi_remove_handle(data->multi, data);
376 if(data->multi_easy) {
377 /* when curl_easy_perform() is used, it creates its own multi handle to
378 use and this is the one */
379 curl_multi_cleanup(data->multi_easy);
380 data->multi_easy = NULL;
383 /* Destroy the timeout list that is held in the easy handle. It is
384 /normally/ done by curl_multi_remove_handle() but this is "just in
386 Curl_llist_destroy(&data->state.timeoutlist, NULL);
388 data->magic = 0; /* force a clear AFTER the possibly enforced removal from
389 the multi handle, since that function uses the magic
392 if(data->state.rangestringalloc)
393 free(data->state.range);
395 /* freed here just in case DONE wasn't called */
396 Curl_free_request_state(data);
398 /* Close down all open SSL info and sessions */
399 Curl_ssl_close_all(data);
400 Curl_safefree(data->state.first_host);
401 Curl_safefree(data->state.scratch);
402 Curl_ssl_free_certinfo(data);
404 /* Cleanup possible redirect junk */
405 free(data->req.newurl);
406 data->req.newurl = NULL;
408 if(data->change.referer_alloc) {
409 Curl_safefree(data->change.referer);
410 data->change.referer_alloc = FALSE;
412 data->change.referer = NULL;
415 Curl_safefree(data->state.buffer);
416 Curl_dyn_free(&data->state.headerb);
417 Curl_safefree(data->state.ulbuf);
418 Curl_flush_cookies(data, TRUE);
419 Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]);
420 Curl_altsvc_cleanup(&data->asi);
421 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
422 Curl_http_auth_cleanup_digest(data);
424 Curl_safefree(data->info.contenttype);
425 Curl_safefree(data->info.wouldredirect);
427 /* this destroys the channel and we cannot use it anymore after this */
428 Curl_resolver_cleanup(data->state.resolver);
430 Curl_http2_cleanup_dependencies(data);
431 Curl_convert_close(data);
433 /* No longer a dirty share, if it exists */
435 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
436 data->share->dirty--;
437 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
440 Curl_safefree(data->state.aptr.proxyuserpwd);
441 Curl_safefree(data->state.aptr.uagent);
442 Curl_safefree(data->state.aptr.userpwd);
443 Curl_safefree(data->state.aptr.accept_encoding);
444 Curl_safefree(data->state.aptr.te);
445 Curl_safefree(data->state.aptr.rangeline);
446 Curl_safefree(data->state.aptr.ref);
447 Curl_safefree(data->state.aptr.host);
448 Curl_safefree(data->state.aptr.cookiehost);
449 Curl_safefree(data->state.aptr.rtsp_transport);
451 #ifndef CURL_DISABLE_DOH
452 Curl_dyn_free(&data->req.doh.probe[0].serverdoh);
453 Curl_dyn_free(&data->req.doh.probe[1].serverdoh);
454 curl_slist_free_all(data->req.doh.headers);
457 /* destruct wildcard structures if it is needed */
458 Curl_wildcard_dtor(&data->wildcard);
465 * Initialize the UserDefined fields within a Curl_easy.
466 * This may be safely called on a new or existing Curl_easy.
468 CURLcode Curl_init_userdefined(struct Curl_easy *data)
470 struct UserDefined *set = &data->set;
471 CURLcode result = CURLE_OK;
473 set->out = stdout; /* default output to stdout */
474 set->in_set = stdin; /* default input from stdin */
475 set->err = stderr; /* default stderr to stderr */
477 /* use fwrite as default function to store output */
478 set->fwrite_func = (curl_write_callback)fwrite;
480 /* use fread as default function to read input */
481 set->fread_func_set = (curl_read_callback)fread;
482 set->is_fread_set = 0;
483 set->is_fwrite_set = 0;
485 set->seek_func = ZERO_NULL;
486 set->seek_client = ZERO_NULL;
488 /* conversion callbacks for non-ASCII hosts */
489 set->convfromnetwork = ZERO_NULL;
490 set->convtonetwork = ZERO_NULL;
491 set->convfromutf8 = ZERO_NULL;
493 set->filesize = -1; /* we don't know the size */
494 set->postfieldsize = -1; /* unknown size */
495 set->maxredirs = -1; /* allow any amount by default */
497 set->method = HTTPREQ_GET; /* Default HTTP request */
498 set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
499 #ifndef CURL_DISABLE_FTP
500 set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
501 set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
502 set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */
503 set->ftp_filemethod = FTPFILE_MULTICWD;
505 set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
507 /* Set the default size of the SSL session ID cache */
508 set->general_ssl.max_ssl_sessions = 5;
511 set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
512 set->httpauth = CURLAUTH_BASIC; /* defaults to basic */
513 set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
515 /* SOCKS5 proxy auth defaults to username/password + GSS-API */
516 set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI;
518 /* make libcurl quiet by default: */
519 set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
521 Curl_mime_initpart(&set->mimepost, data);
524 * libcurl 7.10 introduced SSL verification *by default*! This needs to be
525 * switched off unless wanted.
527 set->ssl.primary.verifypeer = TRUE;
528 set->ssl.primary.verifyhost = TRUE;
530 set->ssl.authtype = CURL_TLSAUTH_NONE;
532 set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
534 set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by
536 #ifndef CURL_DISABLE_PROXY
537 set->proxy_ssl = set->ssl;
540 set->new_file_perms = 0644; /* Default permissions */
541 set->new_directory_perms = 0755; /* Default permissions */
543 /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
544 define since we internally only use the lower 16 bits for the passed
545 in bitmask to not conflict with the private bits */
546 set->allowed_protocols = CURLPROTO_ALL;
547 set->redir_protocols = CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP |
550 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
552 * disallow unprotected protection negotiation NEC reference implementation
553 * seem not to follow rfc1961 section 4.3/4.4
555 set->socks5_gssapi_nec = FALSE;
558 /* Set the default CA cert bundle/path detected/specified at build time.
560 * If Schannel is the selected SSL backend then these locations are
561 * ignored. We allow setting CA location for schannel only when explicitly
562 * specified by the user via CURLOPT_CAINFO / --cacert.
564 if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
565 #if defined(CURL_CA_BUNDLE)
566 result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
570 result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
575 #if defined(CURL_CA_PATH)
576 result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
580 result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
586 set->wildcard_enabled = FALSE;
587 set->chunk_bgn = ZERO_NULL;
588 set->chunk_end = ZERO_NULL;
589 set->tcp_keepalive = FALSE;
590 set->tcp_keepintvl = 60;
591 set->tcp_keepidle = 60;
592 set->tcp_fastopen = FALSE;
593 set->tcp_nodelay = TRUE;
594 set->ssl_enable_npn = TRUE;
595 set->ssl_enable_alpn = TRUE;
596 set->expect_100_timeout = 1000L; /* Wait for a second by default. */
597 set->sep_headers = TRUE; /* separated header lists by default */
598 set->buffer_size = READBUFFER_SIZE;
599 set->upload_buffer_size = UPLOADBUFFER_DEFAULT;
600 set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
601 set->fnmatch = ZERO_NULL;
602 set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT;
603 set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
604 set->maxage_conn = 118;
605 set->http09_allowed = FALSE;
608 CURL_HTTP_VERSION_2TLS
610 CURL_HTTP_VERSION_1_1
613 Curl_http2_init_userset(set);
620 * @param curl is a pointer to a sessionhandle pointer that gets set by this
625 CURLcode Curl_open(struct Curl_easy **curl)
628 struct Curl_easy *data;
630 /* Very simple start-up: alloc the struct, init it with zeroes and return */
631 data = calloc(1, sizeof(struct Curl_easy));
633 /* this is a very serious error */
634 DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n"));
635 return CURLE_OUT_OF_MEMORY;
638 data->magic = CURLEASY_MAGIC_NUMBER;
640 result = Curl_resolver_init(data, &data->state.resolver);
642 DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
647 result = Curl_init_userdefined(data);
649 Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
650 Curl_convert_init(data);
653 /* most recent connection is not yet defined */
654 data->state.lastconnect_id = -1;
656 data->progress.flags |= PGRS_HIDE;
657 data->state.current_speed = -1; /* init to negative == impossible */
661 Curl_resolver_cleanup(data->state.resolver);
662 Curl_dyn_free(&data->state.headerb);
673 #ifdef USE_RECV_BEFORE_SEND_WORKAROUND
674 static void conn_reset_postponed_data(struct connectdata *conn, int num)
676 struct postponed_data * const psnd = &(conn->postponed[num]);
678 DEBUGASSERT(psnd->allocated_size > 0);
679 DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
680 DEBUGASSERT(psnd->recv_size ?
681 (psnd->recv_processed < psnd->recv_size) :
682 (psnd->recv_processed == 0));
683 DEBUGASSERT(psnd->bindsock != CURL_SOCKET_BAD);
686 psnd->allocated_size = 0;
688 psnd->recv_processed = 0;
690 psnd->bindsock = CURL_SOCKET_BAD; /* used only for DEBUGASSERT */
691 #endif /* DEBUGBUILD */
694 DEBUGASSERT(psnd->allocated_size == 0);
695 DEBUGASSERT(psnd->recv_size == 0);
696 DEBUGASSERT(psnd->recv_processed == 0);
697 DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD);
701 static void conn_reset_all_postponed_data(struct connectdata *conn)
703 conn_reset_postponed_data(conn, 0);
704 conn_reset_postponed_data(conn, 1);
706 #else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
707 /* Use "do-nothing" macro instead of function when workaround not used */
708 #define conn_reset_all_postponed_data(c) do {} while(0)
709 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
712 static void conn_shutdown(struct connectdata *conn)
715 infof(conn->data, "Closing connection %ld\n", conn->connection_id);
716 DEBUGASSERT(conn->data);
718 /* possible left-overs from the async name resolvers */
719 Curl_resolver_cancel(conn);
721 /* close the SSL stuff before we close any sockets since they will/may
722 write to the sockets */
723 Curl_ssl_close(conn, FIRSTSOCKET);
724 Curl_ssl_close(conn, SECONDARYSOCKET);
726 /* close possibly still open sockets */
727 if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
728 Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
729 if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
730 Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
731 if(CURL_SOCKET_BAD != conn->tempsock[0])
732 Curl_closesocket(conn, conn->tempsock[0]);
733 if(CURL_SOCKET_BAD != conn->tempsock[1])
734 Curl_closesocket(conn, conn->tempsock[1]);
737 static void conn_free(struct connectdata *conn)
741 Curl_free_idnconverted_hostname(&conn->host);
742 Curl_free_idnconverted_hostname(&conn->conn_to_host);
743 #ifndef CURL_DISABLE_PROXY
744 Curl_free_idnconverted_hostname(&conn->http_proxy.host);
745 Curl_free_idnconverted_hostname(&conn->socks_proxy.host);
746 Curl_safefree(conn->http_proxy.user);
747 Curl_safefree(conn->socks_proxy.user);
748 Curl_safefree(conn->http_proxy.passwd);
749 Curl_safefree(conn->socks_proxy.passwd);
750 Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
751 Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
752 Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
754 Curl_safefree(conn->user);
755 Curl_safefree(conn->passwd);
756 Curl_safefree(conn->sasl_authzid);
757 Curl_safefree(conn->options);
758 Curl_dyn_free(&conn->trailer);
759 Curl_safefree(conn->host.rawalloc); /* host name buffer */
760 Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
761 Curl_safefree(conn->hostname_resolve);
762 Curl_safefree(conn->secondaryhostname);
763 Curl_safefree(conn->connect_state);
765 conn_reset_all_postponed_data(conn);
766 Curl_llist_destroy(&conn->easyq, NULL);
767 Curl_safefree(conn->localdev);
768 Curl_free_primary_ssl_config(&conn->ssl_config);
770 #ifdef USE_UNIX_SOCKETS
771 Curl_safefree(conn->unix_domain_socket);
775 Curl_safefree(conn->ssl_extra);
777 free(conn); /* free all the connection oriented data */
781 * Disconnects the given connection. Note the connection may not be the
782 * primary connection, like when freeing room in the connection cache or
783 * killing of a dead old connection.
785 * A connection needs an easy handle when closing down. We support this passed
786 * in separately since the connection to get closed here is often already
787 * disassociated from an easy handle.
789 * This function MUST NOT reset state in the Curl_easy struct if that
790 * isn't strictly bound to the life-time of *this* particular connection.
794 CURLcode Curl_disconnect(struct Curl_easy *data,
795 struct connectdata *conn, bool dead_connection)
797 /* there must be a connection to close */
800 /* it must be removed from the connection cache */
801 DEBUGASSERT(!conn->bundle);
803 /* there must be an associated transfer */
806 /* the transfer must be detached from the connection */
807 DEBUGASSERT(!data->conn);
810 * If this connection isn't marked to force-close, leave it open if there
811 * are other users of it
813 if(CONN_INUSE(conn) && !dead_connection) {
814 DEBUGF(infof(data, "Curl_disconnect when inuse: %zu\n", CONN_INUSE(conn)));
818 if(conn->dns_entry != NULL) {
819 Curl_resolv_unlock(data, conn->dns_entry);
820 conn->dns_entry = NULL;
823 /* Cleanup NTLM connection-related data */
824 Curl_http_auth_cleanup_ntlm(conn);
826 /* Cleanup NEGOTIATE connection-related data */
827 Curl_http_auth_cleanup_negotiate(conn);
829 /* the protocol specific disconnect handler and conn_shutdown need a transfer
830 for the connection! */
833 if(conn->bits.connect_only)
834 /* treat the connection as dead in CONNECT_ONLY situations */
835 dead_connection = TRUE;
837 if(conn->handler->disconnect)
838 /* This is set if protocol-specific cleanups should be made */
839 conn->handler->disconnect(conn, dead_connection);
847 * This function should return TRUE if the socket is to be assumed to
848 * be dead. Most commonly this happens when the server has closed the
849 * connection due to inactivity.
851 static bool SocketIsDead(curl_socket_t sock)
856 sval = SOCKET_READABLE(sock, 0);
865 * IsMultiplexingPossible()
867 * Return a bitmask with the available multiplexing options for the given
868 * requested connection.
870 static int IsMultiplexingPossible(const struct Curl_easy *handle,
871 const struct connectdata *conn)
875 /* If a HTTP protocol and multiplexing is enabled */
876 if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
877 (!conn->bits.protoconnstart || !conn->bits.close)) {
879 if(Curl_multiplex_wanted(handle->multi) &&
880 (handle->set.httpversion >= CURL_HTTP_VERSION_2))
882 avail |= CURLPIPE_MULTIPLEX;
887 #ifndef CURL_DISABLE_PROXY
889 proxy_info_matches(const struct proxy_info *data,
890 const struct proxy_info *needle)
892 if((data->proxytype == needle->proxytype) &&
893 (data->port == needle->port) &&
894 Curl_safe_strcasecompare(data->host.name, needle->host.name))
901 socks_proxy_info_matches(const struct proxy_info *data,
902 const struct proxy_info *needle)
904 if(!proxy_info_matches(data, needle))
907 /* the user information is case-sensitive
908 or at least it is not defined as case-insensitive
909 see https://tools.ietf.org/html/rfc3986#section-3.2.1 */
910 if((data->user == NULL) != (needle->user == NULL))
912 /* curl_strequal does a case insentive comparison, so do not use it here! */
915 strcmp(data->user, needle->user) != 0)
917 if((data->passwd == NULL) != (needle->passwd == NULL))
919 /* curl_strequal does a case insentive comparison, so do not use it here! */
922 strcmp(data->passwd, needle->passwd) != 0)
927 /* disabled, won't get called */
928 #define proxy_info_matches(x,y) FALSE
929 #define socks_proxy_info_matches(x,y) FALSE
932 /* A connection has to have been idle for a shorter time than 'maxage_conn' to
933 be subject for reuse. The success rate is just too low after this. */
935 static bool conn_maxage(struct Curl_easy *data,
936 struct connectdata *conn,
940 timediff_t idletime = Curl_timediff(now, conn->lastused);
941 idletime /= 1000; /* integer seconds is fine */
943 if(idletime > data->set.maxage_conn) {
944 infof(data, "Too old connection (%ld seconds), disconnect it\n",
953 * This function checks if the given connection is dead and extracts it from
954 * the connection cache if so.
956 * When this is called as a Curl_conncache_foreach() callback, the connection
957 * cache lock is held!
959 * Returns TRUE if the connection was dead and extracted.
961 static bool extract_if_dead(struct connectdata *conn,
962 struct Curl_easy *data)
964 if(!CONN_INUSE(conn) && !conn->data) {
965 /* The check for a dead socket makes sense only if the connection isn't in
968 struct curltime now = Curl_now();
969 if(conn_maxage(data, conn, now)) {
972 else if(conn->handler->connection_check) {
973 /* The protocol has a special method for checking the state of the
974 connection. Use it to check if the connection is dead. */
976 struct Curl_easy *olddata = conn->data;
977 conn->data = data; /* use this transfer for now */
978 state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD);
979 conn->data = olddata;
980 dead = (state & CONNRESULT_DEAD);
983 /* Use the general method for determining the death of a connection */
984 dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
988 infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
989 Curl_conncache_remove_conn(data, conn, FALSE);
997 struct Curl_easy *data;
998 struct connectdata *extracted;
1002 * Wrapper to use extract_if_dead() function in Curl_conncache_foreach()
1005 static int call_extract_if_dead(struct connectdata *conn, void *param)
1007 struct prunedead *p = (struct prunedead *)param;
1008 if(extract_if_dead(conn, p->data)) {
1009 /* stop the iteration here, pass back the connection that was extracted */
1010 p->extracted = conn;
1013 return 0; /* continue iteration */
1017 * This function scans the connection cache for half-open/dead connections,
1018 * closes and removes them.
1019 * The cleanup is done at most once per second.
1021 static void prune_dead_connections(struct Curl_easy *data)
1023 struct curltime now = Curl_now();
1026 CONNCACHE_LOCK(data);
1028 Curl_timediff(now, data->state.conn_cache->last_cleanup);
1029 CONNCACHE_UNLOCK(data);
1031 if(elapsed >= 1000L) {
1032 struct prunedead prune;
1034 prune.extracted = NULL;
1035 while(Curl_conncache_foreach(data, data->state.conn_cache, &prune,
1036 call_extract_if_dead)) {
1039 /* remove connection from cache */
1040 Curl_conncache_remove_conn(data, prune.extracted, TRUE);
1043 (void)Curl_disconnect(data, prune.extracted, TRUE);
1045 CONNCACHE_LOCK(data);
1046 data->state.conn_cache->last_cleanup = now;
1047 CONNCACHE_UNLOCK(data);
1052 * Given one filled in connection struct (named needle), this function should
1053 * detect if there already is one that has all the significant details
1054 * exactly the same and thus should be used instead.
1056 * If there is a match, this function returns TRUE - and has marked the
1057 * connection as 'in-use'. It must later be called with ConnectionDone() to
1058 * return back to 'idle' (unused) state.
1060 * The force_reuse flag is set if the connection must be used.
1063 ConnectionExists(struct Curl_easy *data,
1064 struct connectdata *needle,
1065 struct connectdata **usethis,
1069 struct connectdata *check;
1070 struct connectdata *chosen = 0;
1071 bool foundPendingCandidate = FALSE;
1072 bool canmultiplex = IsMultiplexingPossible(data, needle);
1073 struct connectbundle *bundle;
1074 const char *hostbundle;
1077 bool wantNTLMhttp = ((data->state.authhost.want &
1078 (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
1079 (needle->handler->protocol & PROTO_FAMILY_HTTP));
1080 #ifndef CURL_DISABLE_PROXY
1081 bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
1082 ((data->state.authproxy.want &
1083 (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
1084 (needle->handler->protocol & PROTO_FAMILY_HTTP)));
1086 bool wantProxyNTLMhttp = FALSE;
1090 *force_reuse = FALSE;
1093 /* Look up the bundle with all the connections to this particular host.
1094 Locks the connection cache, beware of early returns! */
1095 bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache,
1098 /* Max pipe length is zero (unlimited) for multiplexed connections */
1099 struct Curl_llist_element *curr;
1101 infof(data, "Found bundle for host %s: %p [%s]\n",
1102 hostbundle, (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
1103 "can multiplex" : "serially"));
1105 /* We can't multiplex if we don't know anything about the server */
1107 if(bundle->multiuse == BUNDLE_UNKNOWN) {
1108 if(data->set.pipewait) {
1109 infof(data, "Server doesn't support multiplex yet, wait\n");
1111 CONNCACHE_UNLOCK(data);
1112 return FALSE; /* no re-use */
1115 infof(data, "Server doesn't support multiplex (yet)\n");
1116 canmultiplex = FALSE;
1118 if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
1119 !Curl_multiplex_wanted(data->multi)) {
1120 infof(data, "Could multiplex, but not asked to!\n");
1121 canmultiplex = FALSE;
1123 if(bundle->multiuse == BUNDLE_NO_MULTIUSE) {
1124 infof(data, "Can not multiplex, even if we wanted to!\n");
1125 canmultiplex = FALSE;
1129 curr = bundle->conn_list.head;
1132 size_t multiplexed = 0;
1135 * Note that if we use a HTTP proxy in normal mode (no tunneling), we
1136 * check connections to that proxy and not to the actual remote server.
1141 if(check->bits.connect_only || check->bits.close)
1142 /* connect-only or to-be-closed connections will not be reused */
1145 if(extract_if_dead(check, data)) {
1147 (void)Curl_disconnect(data, check, TRUE);
1151 if(bundle->multiuse == BUNDLE_MULTIPLEX)
1152 multiplexed = CONN_INUSE(check);
1159 /* can only happen within multi handles, and means that another easy
1160 handle is using this connection */
1164 if(Curl_resolver_asynch()) {
1165 /* ip_addr_str[0] is NUL only if the resolving of the name hasn't
1166 completed yet and until then we don't re-use this connection */
1167 if(!check->ip_addr_str[0]) {
1169 "Connection #%ld is still name resolving, can't reuse\n",
1170 check->connection_id);
1175 if(check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) {
1176 foundPendingCandidate = TRUE;
1177 /* Don't pick a connection that hasn't connected yet */
1178 infof(data, "Connection #%ld isn't open enough, can't reuse\n",
1179 check->connection_id);
1184 #ifdef USE_UNIX_SOCKETS
1185 if(needle->unix_domain_socket) {
1186 if(!check->unix_domain_socket)
1188 if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
1190 if(needle->bits.abstract_unix_socket !=
1191 check->bits.abstract_unix_socket)
1194 else if(check->unix_domain_socket)
1198 if((needle->handler->flags&PROTOPT_SSL) !=
1199 (check->handler->flags&PROTOPT_SSL))
1200 /* don't do mixed SSL and non-SSL connections */
1201 if(get_protocol_family(check->handler) !=
1202 needle->handler->protocol || !check->bits.tls_upgraded)
1203 /* except protocols that have been upgraded via TLS */
1206 #ifndef CURL_DISABLE_PROXY
1207 if(needle->bits.httpproxy != check->bits.httpproxy ||
1208 needle->bits.socksproxy != check->bits.socksproxy)
1211 if(needle->bits.socksproxy &&
1212 !socks_proxy_info_matches(&needle->socks_proxy,
1213 &check->socks_proxy))
1216 if(needle->bits.conn_to_host != check->bits.conn_to_host)
1217 /* don't mix connections that use the "connect to host" feature and
1218 * connections that don't use this feature */
1221 if(needle->bits.conn_to_port != check->bits.conn_to_port)
1222 /* don't mix connections that use the "connect to port" feature and
1223 * connections that don't use this feature */
1226 #ifndef CURL_DISABLE_PROXY
1227 if(needle->bits.httpproxy) {
1228 if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
1231 if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
1234 if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
1235 /* use https proxy */
1236 if(needle->handler->flags&PROTOPT_SSL) {
1237 /* use double layer ssl */
1238 if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
1239 &check->proxy_ssl_config))
1241 if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
1245 if(!Curl_ssl_config_matches(&needle->ssl_config,
1246 &check->ssl_config))
1248 if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
1255 DEBUGASSERT(!check->data || GOOD_EASY_HANDLE(check->data));
1257 DEBUGASSERT(!check->data || GOOD_EASY_HANDLE(check->data));
1259 if(!canmultiplex && check->data)
1260 /* this request can't be multiplexed but the checked connection is
1261 already in use so we skip it */
1264 if(check->data && (check->data->multi != needle->data->multi))
1265 /* this could be subject for multiplex use, but only if they belong to
1266 * the same multi handle */
1269 if(needle->localdev || needle->localport) {
1270 /* If we are bound to a specific local end (IP+port), we must not
1271 re-use a random other one, although if we didn't ask for a
1272 particular one we can reuse one that was bound.
1274 This comparison is a bit rough and too strict. Since the input
1275 parameters can be specified in numerous ways and still end up the
1276 same it would take a lot of processing to make it really accurate.
1277 Instead, this matching will assume that re-uses of bound connections
1278 will most likely also re-use the exact same binding parameters and
1279 missing out a few edge cases shouldn't hurt anyone very much.
1281 if((check->localport != needle->localport) ||
1282 (check->localportrange != needle->localportrange) ||
1283 (needle->localdev &&
1284 (!check->localdev || strcmp(check->localdev, needle->localdev))))
1288 if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
1289 /* This protocol requires credentials per connection,
1290 so verify that we're using the same name and password as well */
1291 if(strcmp(needle->user, check->user) ||
1292 strcmp(needle->passwd, check->passwd)) {
1293 /* one of them was different */
1298 if((needle->handler->flags&PROTOPT_SSL)
1299 #ifndef CURL_DISABLE_PROXY
1300 || !needle->bits.httpproxy || needle->bits.tunnel_proxy
1303 /* The requested connection does not use a HTTP proxy or it uses SSL or
1304 it is a non-SSL protocol tunneled or it is a non-SSL protocol which
1305 is allowed to be upgraded via TLS */
1307 if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
1308 (get_protocol_family(check->handler) ==
1309 needle->handler->protocol && check->bits.tls_upgraded)) &&
1310 (!needle->bits.conn_to_host || strcasecompare(
1311 needle->conn_to_host.name, check->conn_to_host.name)) &&
1312 (!needle->bits.conn_to_port ||
1313 needle->conn_to_port == check->conn_to_port) &&
1314 strcasecompare(needle->host.name, check->host.name) &&
1315 needle->remote_port == check->remote_port) {
1316 /* The schemes match or the protocol family is the same and the
1317 previous connection was TLS upgraded, and the hostname and host
1319 if(needle->handler->flags & PROTOPT_SSL) {
1320 /* This is a SSL connection so verify that we're using the same
1321 SSL options as well */
1322 if(!Curl_ssl_config_matches(&needle->ssl_config,
1323 &check->ssl_config)) {
1325 "Connection #%ld has different SSL parameters, "
1327 check->connection_id));
1330 if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
1331 foundPendingCandidate = TRUE;
1333 "Connection #%ld has not started SSL connect, "
1335 check->connection_id));
1343 /* The requested connection is using the same HTTP proxy in normal
1344 mode (no tunneling) */
1349 #if defined(USE_NTLM)
1350 /* If we are looking for an HTTP+NTLM connection, check if this is
1351 already authenticating with the right credentials. If not, keep
1352 looking so that we can reuse NTLM connections if
1353 possible. (Especially we must not reuse the same connection if
1354 partway through a handshake!) */
1356 if(strcmp(needle->user, check->user) ||
1357 strcmp(needle->passwd, check->passwd)) {
1359 /* we prefer a credential match, but this is at least a connection
1360 that can be reused and "upgraded" to NTLM */
1361 if(check->http_ntlm_state == NTLMSTATE_NONE)
1366 else if(check->http_ntlm_state != NTLMSTATE_NONE) {
1367 /* Connection is using NTLM auth but we don't want NTLM */
1371 #ifndef CURL_DISABLE_PROXY
1372 /* Same for Proxy NTLM authentication */
1373 if(wantProxyNTLMhttp) {
1374 /* Both check->http_proxy.user and check->http_proxy.passwd can be
1376 if(!check->http_proxy.user || !check->http_proxy.passwd)
1379 if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
1380 strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
1383 else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
1384 /* Proxy connection is using NTLM auth but we don't want NTLM */
1388 if(wantNTLMhttp || wantProxyNTLMhttp) {
1389 /* Credentials are already checked, we can use this connection */
1393 (check->http_ntlm_state != NTLMSTATE_NONE)) ||
1394 (wantProxyNTLMhttp &&
1395 (check->proxy_ntlm_state != NTLMSTATE_NONE))) {
1396 /* We must use this connection, no other */
1397 *force_reuse = TRUE;
1401 /* Continue look up for a better connection */
1406 /* We can multiplex if we want to. Let's continue looking for
1407 the optimal connection to use. */
1410 /* We have the optimal connection. Let's stop looking. */
1416 /* If multiplexed, make sure we don't go over concurrency limit */
1417 if(check->bits.multiplex) {
1418 /* Multiplexed connections can only be HTTP/2 for now */
1419 struct http_conn *httpc = &check->proto.httpc;
1420 if(multiplexed >= httpc->settings.max_concurrent_streams) {
1421 infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n",
1425 else if(multiplexed >=
1426 Curl_multi_max_concurrent_streams(needle->data->multi)) {
1427 infof(data, "client side MAX_CONCURRENT_STREAMS reached"
1434 /* When not multiplexed, we have a match here! */
1436 infof(data, "Multiplexed connection found!\n");
1440 /* We have found a connection. Let's stop searching. */
1449 /* mark it as used before releasing the lock */
1450 chosen->data = data; /* own it! */
1451 Curl_attach_connnection(data, chosen);
1452 CONNCACHE_UNLOCK(data);
1454 return TRUE; /* yes, we found one to use! */
1456 CONNCACHE_UNLOCK(data);
1458 if(foundPendingCandidate && data->set.pipewait) {
1460 "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set\n");
1464 return FALSE; /* no matching connecting exists */
1468 * verboseconnect() displays verbose information after a connect
1470 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1471 void Curl_verboseconnect(struct connectdata *conn)
1473 if(conn->data->set.verbose)
1474 infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
1475 #ifndef CURL_DISABLE_PROXY
1476 conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
1477 conn->bits.httpproxy ? conn->http_proxy.host.dispname :
1479 conn->bits.conn_to_host ? conn->conn_to_host.dispname :
1480 conn->host.dispname,
1481 conn->ip_addr_str, conn->port, conn->connection_id);
1486 * Helpers for IDNA conversions.
1488 bool Curl_is_ASCII_name(const char *hostname)
1490 /* get an UNSIGNED local version of the pointer */
1491 const unsigned char *ch = (const unsigned char *)hostname;
1493 if(!hostname) /* bad input, consider it ASCII! */
1504 * Strip single trailing dot in the hostname,
1505 * primarily for SNI and http host header.
1507 static void strip_trailing_dot(struct hostname *host)
1510 if(!host || !host->name)
1512 len = strlen(host->name);
1513 if(len && (host->name[len-1] == '.'))
1514 host->name[len-1] = 0;
1518 * Perform any necessary IDN conversion of hostname
1520 CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
1521 struct hostname *host)
1523 struct Curl_easy *data = conn->data;
1528 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
1532 /* set the name we use to display the host name */
1533 host->dispname = host->name;
1535 /* Check name for non-ASCII and convert hostname to ACE form if we can */
1536 if(!Curl_is_ASCII_name(host->name)) {
1538 if(idn2_check_version(IDN2_VERSION)) {
1539 char *ace_hostname = NULL;
1540 #if IDN2_VERSION_NUMBER >= 0x00140000
1541 /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
1542 IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
1544 int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL;
1546 int flags = IDN2_NFC_INPUT;
1548 int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags);
1550 host->encalloc = (char *)ace_hostname;
1551 /* change the name pointer to point to the encoded hostname */
1552 host->name = host->encalloc;
1555 failf(data, "Failed to convert %s to ACE; %s\n", host->name,
1557 return CURLE_URL_MALFORMAT;
1560 #elif defined(USE_WIN32_IDN)
1561 char *ace_hostname = NULL;
1563 if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
1564 host->encalloc = ace_hostname;
1565 /* change the name pointer to point to the encoded hostname */
1566 host->name = host->encalloc;
1569 char buffer[STRERROR_LEN];
1570 failf(data, "Failed to convert %s to ACE; %s\n", host->name,
1571 Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
1572 return CURLE_URL_MALFORMAT;
1574 #elif defined(USE_ICU_IDNA)
1575 char *ace_hostname = malloc(MAX_DOMAIN_NAME_LEN * sizeof(char));
1576 UErrorCode errorCode = U_ZERO_ERROR;
1577 UIDNAInfo info = UIDNA_INFO_INITIALIZER;
1579 uidna_openUTS46(UIDNA_USE_STD3_RULES|UIDNA_NONTRANSITIONAL_TO_UNICODE,
1581 int32_t length = uidna_nameToASCII_UTF8(uts46,
1582 host->name, strlen(host->name),
1583 ace_hostname, MAX_DOMAIN_NAME_LEN, &info, &errorCode);
1586 if(errorCode != U_ZERO_ERROR || info.errors || length < 1) {
1587 infof(data, "Failed to convert %s to ACE;\n", host->name);
1588 return CURLE_URL_MALFORMAT;
1591 host->encalloc = ace_hostname;
1592 host->name = host->encalloc;
1595 infof(data, "IDN support not present, can't parse Unicode domains\n");
1602 * Frees data allocated by idnconvert_hostname()
1604 void Curl_free_idnconverted_hostname(struct hostname *host)
1606 #if defined(USE_LIBIDN2)
1607 if(host->encalloc) {
1608 idn2_free(host->encalloc); /* must be freed with idn2_free() since this was
1609 allocated by libidn */
1610 host->encalloc = NULL;
1612 #elif defined(USE_WIN32_IDN) || defined(USE_ICU_IDNA)
1613 free(host->encalloc); /* must be freed with free() since this was
1614 allocated by curl_win32_idn_to_ascii */
1615 host->encalloc = NULL;
1622 * Allocate and initialize a new connectdata object.
1624 static struct connectdata *allocate_conn(struct Curl_easy *data)
1626 struct connectdata *conn = calloc(1, sizeof(struct connectdata));
1631 /* The SSL backend-specific data (ssl_backend_data) objects are allocated as
1632 a separate array to ensure suitable alignment.
1633 Note that these backend pointers can be swapped by vtls (eg ssl backend
1634 data becomes proxy backend data). */
1636 size_t sslsize = Curl_ssl->sizeof_ssl_backend_data;
1637 char *ssl = calloc(4, sslsize);
1642 conn->ssl_extra = ssl;
1643 conn->ssl[0].backend = (void *)ssl;
1644 conn->ssl[1].backend = (void *)(ssl + sslsize);
1645 #ifndef CURL_DISABLE_PROXY
1646 conn->proxy_ssl[0].backend = (void *)(ssl + 2 * sslsize);
1647 conn->proxy_ssl[1].backend = (void *)(ssl + 3 * sslsize);
1652 conn->handler = &Curl_handler_dummy; /* Be sure we have a handler defined
1653 already from start to avoid NULL
1654 situations and checks */
1656 /* and we setup a few fields in case we end up actually using this struct */
1658 conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
1659 conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
1660 conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */
1661 conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
1662 conn->connection_id = -1; /* no ID */
1663 conn->port = -1; /* unknown at this point */
1664 conn->remote_port = -1; /* unknown at this point */
1665 #if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
1666 conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
1667 conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
1668 #endif /* USE_RECV_BEFORE_SEND_WORKAROUND && DEBUGBUILD */
1670 /* Default protocol-independent behavior doesn't support persistent
1671 connections, so we set this to force-close. Protocols that support
1672 this need to set this to FALSE in their "curl_do" functions. */
1673 connclose(conn, "Default to force-close");
1675 /* Store creation time to help future close decision making */
1676 conn->created = Curl_now();
1678 /* Store current time to give a baseline to keepalive connection times. */
1679 conn->keepalive = Curl_now();
1681 /* Store off the configured connection upkeep time. */
1682 conn->upkeep_interval_ms = data->set.upkeep_interval_ms;
1684 conn->data = data; /* Setup the association between this connection
1685 and the Curl_easy */
1687 #ifndef CURL_DISABLE_PROXY
1688 conn->http_proxy.proxytype = data->set.proxytype;
1689 conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
1691 /* note that these two proxy bits are now just on what looks to be
1692 requested, they may be altered down the road */
1693 conn->bits.proxy = (data->set.str[STRING_PROXY] &&
1694 *data->set.str[STRING_PROXY]) ? TRUE : FALSE;
1695 conn->bits.httpproxy = (conn->bits.proxy &&
1696 (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
1697 conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
1698 conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
1700 conn->bits.socksproxy = (conn->bits.proxy &&
1701 !conn->bits.httpproxy) ? TRUE : FALSE;
1703 if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) {
1704 conn->bits.proxy = TRUE;
1705 conn->bits.socksproxy = TRUE;
1708 conn->bits.proxy_user_passwd =
1709 (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE;
1710 conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
1711 #endif /* CURL_DISABLE_PROXY */
1713 conn->bits.user_passwd = (data->set.str[STRING_USERNAME]) ? TRUE : FALSE;
1714 #ifndef CURL_DISABLE_FTP
1715 conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
1716 conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
1718 conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
1719 conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
1720 conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
1721 #ifndef CURL_DISABLE_PROXY
1722 conn->proxy_ssl_config.verifystatus =
1723 data->set.proxy_ssl.primary.verifystatus;
1724 conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
1725 conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
1727 conn->ip_version = data->set.ipver;
1728 conn->bits.connect_only = data->set.connect_only;
1729 conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
1731 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
1732 defined(NTLM_WB_ENABLED)
1733 conn->ntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
1734 conn->proxyntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
1737 /* Initialize the easy handle list */
1738 Curl_llist_init(&conn->easyq, NULL);
1741 conn->data_prot = PROT_CLEAR;
1744 /* Store the local bind parameters that will be used for this connection */
1745 if(data->set.str[STRING_DEVICE]) {
1746 conn->localdev = strdup(data->set.str[STRING_DEVICE]);
1750 conn->localportrange = data->set.localportrange;
1751 conn->localport = data->set.localport;
1753 /* the close socket stuff needs to be copied to the connection struct as
1754 it may live on without (this specific) Curl_easy */
1755 conn->fclosesocket = data->set.fclosesocket;
1756 conn->closesocket_client = data->set.closesocket_client;
1757 conn->lastused = Curl_now(); /* used now */
1762 Curl_llist_destroy(&conn->easyq, NULL);
1763 free(conn->localdev);
1765 free(conn->ssl_extra);
1771 /* returns the handler if the given scheme is built-in */
1772 const struct Curl_handler *Curl_builtin_scheme(const char *scheme)
1774 const struct Curl_handler * const *pp;
1775 const struct Curl_handler *p;
1776 /* Scan protocol handler table and match against 'scheme'. The handler may
1777 be changed later when the protocol specific setup function is called. */
1778 for(pp = protocols; (p = *pp) != NULL; pp++)
1779 if(strcasecompare(p->scheme, scheme))
1780 /* Protocol found in table. Check if allowed */
1782 return NULL; /* not found */
1786 static CURLcode findprotocol(struct Curl_easy *data,
1787 struct connectdata *conn,
1788 const char *protostr)
1790 const struct Curl_handler *p = Curl_builtin_scheme(protostr);
1792 if(p && /* Protocol found in table. Check if allowed */
1793 (data->set.allowed_protocols & p->protocol)) {
1795 /* it is allowed for "normal" request, now do an extra check if this is
1796 the result of a redirect */
1797 if(data->state.this_is_a_follow &&
1798 !(data->set.redir_protocols & p->protocol))
1802 /* Perform setup complement if some. */
1803 conn->handler = conn->given = p;
1805 /* 'port' and 'remote_port' are set in setup_connection_internals() */
1810 /* The protocol was not found in the table, but we don't have to assign it
1811 to anything since it is already assigned to a dummy-struct in the
1812 create_conn() function when the connectdata struct is allocated. */
1813 failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
1816 return CURLE_UNSUPPORTED_PROTOCOL;
1820 CURLcode Curl_uc_to_curlcode(CURLUcode uc)
1824 return CURLE_URL_MALFORMAT;
1825 case CURLUE_UNSUPPORTED_SCHEME:
1826 return CURLE_UNSUPPORTED_PROTOCOL;
1827 case CURLUE_OUT_OF_MEMORY:
1828 return CURLE_OUT_OF_MEMORY;
1829 case CURLUE_USER_NOT_ALLOWED:
1830 return CURLE_LOGIN_DENIED;
1835 * If the URL was set with an IPv6 numerical address with a zone id part, set
1836 * the scope_id based on that!
1839 static void zonefrom_url(CURLU *uh, struct connectdata *conn)
1844 uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0);
1848 unsigned long scope = strtoul(zoneid, &endp, 10);
1849 if(!*endp && (scope < UINT_MAX))
1850 /* A plain number, use it directly as a scope id. */
1851 conn->scope_id = (unsigned int)scope;
1852 #if defined(HAVE_IF_NAMETOINDEX)
1854 #elif defined(WIN32)
1855 else if(Curl_if_nametoindex) {
1858 #if defined(HAVE_IF_NAMETOINDEX) || defined(WIN32)
1859 /* Zone identifier is not numeric */
1860 unsigned int scopeidx = 0;
1862 scopeidx = Curl_if_nametoindex(zoneid);
1864 scopeidx = if_nametoindex(zoneid);
1867 infof(conn->data, "Invalid zoneid: %s; %s\n", zoneid,
1870 conn->scope_id = scopeidx;
1872 #endif /* HAVE_IF_NAMETOINDEX || WIN32 */
1879 * Parse URL and fill in the relevant members of the connection struct.
1881 static CURLcode parseurlandfillconn(struct Curl_easy *data,
1882 struct connectdata *conn)
1888 bool use_set_uh = (data->set.uh && !data->state.this_is_a_follow);
1890 up_free(data); /* cleanup previous leftovers first */
1894 uh = data->state.uh = curl_url_dup(data->set.uh);
1897 uh = data->state.uh = curl_url();
1901 return CURLE_OUT_OF_MEMORY;
1903 if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
1904 !Curl_is_absolute_url(data->change.url, NULL, MAX_SCHEME_LEN)) {
1906 if(data->change.url_alloc)
1907 free(data->change.url);
1908 url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
1911 return CURLE_OUT_OF_MEMORY;
1912 data->change.url = url;
1913 data->change.url_alloc = TRUE;
1918 uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
1919 CURLU_GUESS_SCHEME |
1920 CURLU_NON_SUPPORT_SCHEME |
1921 (data->set.disallow_username_in_url ?
1922 CURLU_DISALLOW_USER : 0) |
1923 (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
1925 DEBUGF(infof(data, "curl_url_set rejected %s\n", data->change.url));
1926 return Curl_uc_to_curlcode(uc);
1929 /* after it was parsed, get the generated normalized version */
1930 uc = curl_url_get(uh, CURLUPART_URL, &newurl, 0);
1932 return Curl_uc_to_curlcode(uc);
1933 if(data->change.url_alloc)
1934 free(data->change.url);
1935 data->change.url = newurl;
1936 data->change.url_alloc = TRUE;
1939 uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
1941 return Curl_uc_to_curlcode(uc);
1943 result = findprotocol(data, conn, data->state.up.scheme);
1947 /* we don't use the URL API's URL decoder option here since it rejects
1948 control codes and we want to allow them for some schemes in the user and
1950 uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0);
1953 result = Curl_urldecode(NULL, data->state.up.user, 0, &decoded, NULL,
1954 conn->handler->flags&PROTOPT_USERPWDCTRL ?
1955 REJECT_ZERO : REJECT_CTRL);
1958 conn->user = decoded;
1959 conn->bits.user_passwd = TRUE;
1961 else if(uc != CURLUE_NO_USER)
1962 return Curl_uc_to_curlcode(uc);
1964 uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
1967 result = Curl_urldecode(NULL, data->state.up.password, 0, &decoded, NULL,
1968 conn->handler->flags&PROTOPT_USERPWDCTRL ?
1969 REJECT_ZERO : REJECT_CTRL);
1972 conn->passwd = decoded;
1973 conn->bits.user_passwd = TRUE;
1975 else if(uc != CURLUE_NO_PASSWORD)
1976 return Curl_uc_to_curlcode(uc);
1978 uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options,
1981 conn->options = strdup(data->state.up.options);
1983 return CURLE_OUT_OF_MEMORY;
1985 else if(uc != CURLUE_NO_OPTIONS)
1986 return Curl_uc_to_curlcode(uc);
1988 uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
1990 if(!strcasecompare("file", data->state.up.scheme))
1991 return CURLE_OUT_OF_MEMORY;
1994 uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, 0);
1996 return Curl_uc_to_curlcode(uc);
1998 uc = curl_url_get(uh, CURLUPART_PORT, &data->state.up.port,
1999 CURLU_DEFAULT_PORT);
2001 if(!strcasecompare("file", data->state.up.scheme))
2002 return CURLE_OUT_OF_MEMORY;
2005 unsigned long port = strtoul(data->state.up.port, NULL, 10);
2006 conn->port = conn->remote_port = curlx_ultous(port);
2009 (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
2011 hostname = data->state.up.hostname;
2012 if(hostname && hostname[0] == '[') {
2013 /* This looks like an IPv6 address literal. See if there is an address
2016 conn->bits.ipv6_ip = TRUE;
2017 /* cut off the brackets! */
2019 hlen = strlen(hostname);
2020 hostname[hlen - 1] = 0;
2022 zonefrom_url(uh, conn);
2025 /* make sure the connect struct gets its own copy of the host name */
2026 conn->host.rawalloc = strdup(hostname ? hostname : "");
2027 if(!conn->host.rawalloc)
2028 return CURLE_OUT_OF_MEMORY;
2029 conn->host.name = conn->host.rawalloc;
2031 if(data->set.scope_id)
2032 /* Override any scope that was set above. */
2033 conn->scope_id = data->set.scope_id;
2040 * If we're doing a resumed transfer, we need to setup our stuff
2043 static CURLcode setup_range(struct Curl_easy *data)
2045 struct UrlState *s = &data->state;
2046 s->resume_from = data->set.set_resume_from;
2047 if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
2048 if(s->rangestringalloc)
2052 s->range = aprintf("%" CURL_FORMAT_CURL_OFF_T "-", s->resume_from);
2054 s->range = strdup(data->set.str[STRING_SET_RANGE]);
2056 s->rangestringalloc = (s->range) ? TRUE : FALSE;
2059 return CURLE_OUT_OF_MEMORY;
2061 /* tell ourselves to fetch this range */
2062 s->use_range = TRUE; /* enable range download */
2065 s->use_range = FALSE; /* disable range download */
2072 * setup_connection_internals() -
2074 * Setup connection internals specific to the requested protocol in the
2075 * Curl_easy. This is inited and setup before the connection is made but
2076 * is about the particular protocol that is to be used.
2078 * This MUST get called after proxy magic has been figured out.
2080 static CURLcode setup_connection_internals(struct connectdata *conn)
2082 const struct Curl_handler *p;
2085 /* Perform setup complement if some. */
2088 if(p->setup_connection) {
2089 result = (*p->setup_connection)(conn);
2094 p = conn->handler; /* May have changed. */
2098 /* we check for -1 here since if proxy was detected already, this
2099 was very likely already set to the proxy port */
2100 conn->port = p->defport;
2106 * Curl_free_request_state() should free temp data that was allocated in the
2107 * Curl_easy for this single request.
2110 void Curl_free_request_state(struct Curl_easy *data)
2112 Curl_safefree(data->req.protop);
2113 Curl_safefree(data->req.newurl);
2115 #ifndef CURL_DISABLE_DOH
2116 Curl_close(&data->req.doh.probe[0].easy);
2117 Curl_close(&data->req.doh.probe[1].easy);
2122 #ifndef CURL_DISABLE_PROXY
2123 /****************************************************************
2124 * Checks if the host is in the noproxy list. returns true if it matches
2125 * and therefore the proxy should NOT be used.
2126 ****************************************************************/
2127 static bool check_noproxy(const char *name, const char *no_proxy)
2129 /* no_proxy=domain1.dom,host.domain2.dom
2130 * (a comma-separated list of hosts which should
2131 * not be proxied, or an asterisk to override
2132 * all proxy variables)
2134 if(no_proxy && no_proxy[0]) {
2137 const char *separator = ", ";
2138 size_t no_proxy_len;
2141 if(strcasecompare("*", no_proxy)) {
2145 /* NO_PROXY was specified and it wasn't just an asterisk */
2147 no_proxy_len = strlen(no_proxy);
2148 if(name[0] == '[') {
2149 /* IPv6 numerical address */
2150 endptr = strchr(name, ']');
2154 namelen = endptr - name;
2157 namelen = strlen(name);
2159 for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
2160 while(tok_start < no_proxy_len &&
2161 strchr(separator, no_proxy[tok_start]) != NULL) {
2162 /* Look for the beginning of the token. */
2166 if(tok_start == no_proxy_len)
2167 break; /* It was all trailing separator chars, no more tokens. */
2169 for(tok_end = tok_start; tok_end < no_proxy_len &&
2170 strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
2171 /* Look for the end of the token. */
2174 /* To match previous behaviour, where it was necessary to specify
2175 * ".local.com" to prevent matching "notlocal.com", we will leave
2178 if(no_proxy[tok_start] == '.')
2181 if((tok_end - tok_start) <= namelen) {
2182 /* Match the last part of the name to the domain we are checking. */
2183 const char *checkn = name + namelen - (tok_end - tok_start);
2184 if(strncasecompare(no_proxy + tok_start, checkn,
2185 tok_end - tok_start)) {
2186 if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
2187 /* We either have an exact match, or the previous character is a .
2188 * so it is within the same domain, so no proxy for this host.
2193 } /* if((tok_end - tok_start) <= namelen) */
2194 } /* for(tok_start = 0; tok_start < no_proxy_len;
2195 tok_start = tok_end + 1) */
2196 } /* NO_PROXY was specified and it wasn't just an asterisk */
2201 #ifndef CURL_DISABLE_HTTP
2202 /****************************************************************
2203 * Detect what (if any) proxy to use. Remember that this selects a host
2204 * name and is not limited to HTTP proxies only.
2205 * The returned pointer must be freed by the caller (unless NULL)
2206 ****************************************************************/
2207 static char *detect_proxy(struct connectdata *conn)
2211 /* If proxy was not specified, we check for default proxy environment
2212 * variables, to enable i.e Lynx compliance:
2214 * http_proxy=http://some.server.dom:port/
2215 * https_proxy=http://some.server.dom:port/
2216 * ftp_proxy=http://some.server.dom:port/
2217 * no_proxy=domain1.dom,host.domain2.dom
2218 * (a comma-separated list of hosts which should
2219 * not be proxied, or an asterisk to override
2220 * all proxy variables)
2221 * all_proxy=http://some.server.dom:port/
2222 * (seems to exist for the CERN www lib. Probably
2223 * the first to check for.)
2225 * For compatibility, the all-uppercase versions of these variables are
2226 * checked if the lowercase versions don't exist.
2228 char proxy_env[128];
2229 const char *protop = conn->handler->scheme;
2230 char *envp = proxy_env;
2233 /* Now, build <protocol>_proxy and check for such a one to use */
2235 *envp++ = (char)tolower((int)*protop++);
2238 strcpy(envp, "_proxy");
2240 /* read the protocol proxy: */
2241 prox = curl_getenv(proxy_env);
2244 * We don't try the uppercase version of HTTP_PROXY because of
2247 * When curl is used in a webserver application
2248 * environment (cgi or php), this environment variable can
2249 * be controlled by the web server user by setting the
2250 * http header 'Proxy:' to some value.
2252 * This can cause 'internal' http/ftp requests to be
2253 * arbitrarily redirected by any external attacker.
2255 if(!prox && !strcasecompare("http_proxy", proxy_env)) {
2256 /* There was no lowercase variable, try the uppercase version: */
2257 Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
2258 prox = curl_getenv(proxy_env);
2263 proxy = prox; /* use this */
2266 envp = (char *)"all_proxy";
2267 proxy = curl_getenv(envp); /* default proxy to use */
2269 envp = (char *)"ALL_PROXY";
2270 proxy = curl_getenv(envp);
2274 infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy);
2278 #endif /* CURL_DISABLE_HTTP */
2281 * If this is supposed to use a proxy, we need to figure out the proxy
2282 * host name, so that we can re-use an existing connection
2283 * that may exist registered to the same proxy host.
2285 static CURLcode parse_proxy(struct Curl_easy *data,
2286 struct connectdata *conn, char *proxy,
2287 curl_proxytype proxytype)
2289 char *portptr = NULL;
2291 char *proxyuser = NULL;
2292 char *proxypasswd = NULL;
2296 struct proxy_info *proxyinfo;
2297 CURLU *uhp = curl_url();
2298 CURLcode result = CURLE_OK;
2299 char *scheme = NULL;
2301 /* When parsing the proxy, allowing non-supported schemes since we have
2302 these made up ones for proxies. Guess scheme for URLs without it. */
2303 uc = curl_url_set(uhp, CURLUPART_URL, proxy,
2304 CURLU_NON_SUPPORT_SCHEME|CURLU_GUESS_SCHEME);
2306 /* parsed okay as a URL */
2307 uc = curl_url_get(uhp, CURLUPART_SCHEME, &scheme, 0);
2309 result = CURLE_OUT_OF_MEMORY;
2313 if(strcasecompare("https", scheme))
2314 proxytype = CURLPROXY_HTTPS;
2315 else if(strcasecompare("socks5h", scheme))
2316 proxytype = CURLPROXY_SOCKS5_HOSTNAME;
2317 else if(strcasecompare("socks5", scheme))
2318 proxytype = CURLPROXY_SOCKS5;
2319 else if(strcasecompare("socks4a", scheme))
2320 proxytype = CURLPROXY_SOCKS4A;
2321 else if(strcasecompare("socks4", scheme) ||
2322 strcasecompare("socks", scheme))
2323 proxytype = CURLPROXY_SOCKS4;
2324 else if(strcasecompare("http", scheme))
2325 ; /* leave it as HTTP or HTTP/1.0 */
2327 /* Any other xxx:// reject! */
2328 failf(data, "Unsupported proxy scheme for \'%s\'", proxy);
2329 result = CURLE_COULDNT_CONNECT;
2334 failf(data, "Unsupported proxy syntax in \'%s\'", proxy);
2335 result = CURLE_COULDNT_RESOLVE_PROXY;
2340 if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
2342 if(proxytype == CURLPROXY_HTTPS) {
2343 failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
2344 "HTTPS-proxy support.", proxy);
2345 result = CURLE_NOT_BUILT_IN;
2350 proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
2351 proxytype == CURLPROXY_SOCKS5 ||
2352 proxytype == CURLPROXY_SOCKS4A ||
2353 proxytype == CURLPROXY_SOCKS4;
2355 proxyinfo = sockstype ? &conn->socks_proxy : &conn->http_proxy;
2356 proxyinfo->proxytype = proxytype;
2358 /* Is there a username and password given in this proxy url? */
2359 curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE);
2360 curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE);
2361 if(proxyuser || proxypasswd) {
2362 Curl_safefree(proxyinfo->user);
2363 proxyinfo->user = proxyuser;
2364 Curl_safefree(proxyinfo->passwd);
2366 proxypasswd = strdup("");
2368 result = CURLE_OUT_OF_MEMORY;
2372 proxyinfo->passwd = proxypasswd;
2373 conn->bits.proxy_user_passwd = TRUE; /* enable it */
2376 curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
2379 port = strtol(portptr, NULL, 10);
2383 if(data->set.proxyport)
2384 /* None given in the proxy string, then get the default one if it is
2386 port = data->set.proxyport;
2388 if(proxytype == CURLPROXY_HTTPS)
2389 port = CURL_DEFAULT_HTTPS_PROXY_PORT;
2391 port = CURL_DEFAULT_PROXY_PORT;
2395 proxyinfo->port = port;
2396 if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
2400 /* now, clone the proxy host name */
2401 uc = curl_url_get(uhp, CURLUPART_HOST, &host, CURLU_URLDECODE);
2403 result = CURLE_OUT_OF_MEMORY;
2406 Curl_safefree(proxyinfo->host.rawalloc);
2407 proxyinfo->host.rawalloc = host;
2408 if(host[0] == '[') {
2409 /* this is a numerical IPv6, strip off the brackets */
2410 size_t len = strlen(host);
2411 host[len-1] = 0; /* clear the trailing bracket */
2413 zonefrom_url(uhp, conn);
2415 proxyinfo->host.name = host;
2419 curl_url_cleanup(uhp);
2424 * Extract the user and password from the authentication string
2426 static CURLcode parse_proxy_auth(struct Curl_easy *data,
2427 struct connectdata *conn)
2429 const char *proxyuser = data->set.str[STRING_PROXYUSERNAME] ?
2430 data->set.str[STRING_PROXYUSERNAME] : "";
2431 const char *proxypasswd = data->set.str[STRING_PROXYPASSWORD] ?
2432 data->set.str[STRING_PROXYPASSWORD] : "";
2433 CURLcode result = CURLE_OK;
2436 result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
2438 if(!result && proxypasswd)
2439 result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
2444 /* create_conn helper to parse and init proxy values. to be called after unix
2445 socket init but before any proxy vars are evaluated. */
2446 static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
2449 char *socksproxy = NULL;
2450 char *no_proxy = NULL;
2451 CURLcode result = CURLE_OK;
2452 struct Curl_easy *data = conn->data;
2454 /*************************************************************
2455 * Extract the user and password from the authentication string
2456 *************************************************************/
2457 if(conn->bits.proxy_user_passwd) {
2458 result = parse_proxy_auth(data, conn);
2463 /*************************************************************
2464 * Detect what (if any) proxy to use
2465 *************************************************************/
2466 if(data->set.str[STRING_PROXY]) {
2467 proxy = strdup(data->set.str[STRING_PROXY]);
2468 /* if global proxy is set, this is it */
2470 failf(data, "memory shortage");
2471 result = CURLE_OUT_OF_MEMORY;
2476 if(data->set.str[STRING_PRE_PROXY]) {
2477 socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
2478 /* if global socks proxy is set, this is it */
2479 if(NULL == socksproxy) {
2480 failf(data, "memory shortage");
2481 result = CURLE_OUT_OF_MEMORY;
2486 if(!data->set.str[STRING_NOPROXY]) {
2487 const char *p = "no_proxy";
2488 no_proxy = curl_getenv(p);
2491 no_proxy = curl_getenv(p);
2494 infof(conn->data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
2498 if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
2499 data->set.str[STRING_NOPROXY] : no_proxy)) {
2500 Curl_safefree(proxy);
2501 Curl_safefree(socksproxy);
2503 #ifndef CURL_DISABLE_HTTP
2504 else if(!proxy && !socksproxy)
2505 /* if the host is not in the noproxy list, detect proxy. */
2506 proxy = detect_proxy(conn);
2507 #endif /* CURL_DISABLE_HTTP */
2509 Curl_safefree(no_proxy);
2511 #ifdef USE_UNIX_SOCKETS
2512 /* For the time being do not mix proxy and unix domain sockets. See #1274 */
2513 if(proxy && conn->unix_domain_socket) {
2519 if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
2520 free(proxy); /* Don't bother with an empty proxy string or if the
2521 protocol doesn't work with network */
2524 if(socksproxy && (!*socksproxy ||
2525 (conn->handler->flags & PROTOPT_NONETWORK))) {
2526 free(socksproxy); /* Don't bother with an empty socks proxy string or if
2527 the protocol doesn't work with network */
2531 /***********************************************************************
2532 * If this is supposed to use a proxy, we need to figure out the proxy host
2533 * name, proxy type and port number, so that we can re-use an existing
2534 * connection that may exist registered to the same proxy host.
2535 ***********************************************************************/
2536 if(proxy || socksproxy) {
2538 result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
2539 Curl_safefree(proxy); /* parse_proxy copies the proxy string */
2545 result = parse_proxy(data, conn, socksproxy,
2546 conn->socks_proxy.proxytype);
2547 /* parse_proxy copies the socks proxy string */
2548 Curl_safefree(socksproxy);
2553 if(conn->http_proxy.host.rawalloc) {
2554 #ifdef CURL_DISABLE_HTTP
2555 /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
2556 result = CURLE_UNSUPPORTED_PROTOCOL;
2559 /* force this connection's protocol to become HTTP if compatible */
2560 if(!(conn->handler->protocol & PROTO_FAMILY_HTTP)) {
2561 if((conn->handler->flags & PROTOPT_PROXY_AS_HTTP) &&
2562 !conn->bits.tunnel_proxy)
2563 conn->handler = &Curl_handler_http;
2565 /* if not converting to HTTP over the proxy, enforce tunneling */
2566 conn->bits.tunnel_proxy = TRUE;
2568 conn->bits.httpproxy = TRUE;
2572 conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
2573 conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
2576 if(conn->socks_proxy.host.rawalloc) {
2577 if(!conn->http_proxy.host.rawalloc) {
2578 /* once a socks proxy */
2579 if(!conn->socks_proxy.user) {
2580 conn->socks_proxy.user = conn->http_proxy.user;
2581 conn->http_proxy.user = NULL;
2582 Curl_safefree(conn->socks_proxy.passwd);
2583 conn->socks_proxy.passwd = conn->http_proxy.passwd;
2584 conn->http_proxy.passwd = NULL;
2587 conn->bits.socksproxy = TRUE;
2590 conn->bits.socksproxy = FALSE; /* not a socks proxy */
2593 conn->bits.socksproxy = FALSE;
2594 conn->bits.httpproxy = FALSE;
2596 conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
2598 if(!conn->bits.proxy) {
2599 /* we aren't using the proxy after all... */
2600 conn->bits.proxy = FALSE;
2601 conn->bits.httpproxy = FALSE;
2602 conn->bits.socksproxy = FALSE;
2603 conn->bits.proxy_user_passwd = FALSE;
2604 conn->bits.tunnel_proxy = FALSE;
2605 /* CURLPROXY_HTTPS does not have its own flag in conn->bits, yet we need
2606 to signal that CURLPROXY_HTTPS is not used for this connection */
2607 conn->http_proxy.proxytype = CURLPROXY_HTTP;
2616 #endif /* CURL_DISABLE_PROXY */
2619 * Curl_parse_login_details()
2621 * This is used to parse a login string for user name, password and options in
2622 * the following formats:
2626 * user:password;options
2628 * user;options:password
2636 * login [in] - The login string.
2637 * len [in] - The length of the login string.
2638 * userp [in/out] - The address where a pointer to newly allocated memory
2639 * holding the user will be stored upon completion.
2640 * passwdp [in/out] - The address where a pointer to newly allocated memory
2641 * holding the password will be stored upon completion.
2642 * optionsp [in/out] - The address where a pointer to newly allocated memory
2643 * holding the options will be stored upon completion.
2645 * Returns CURLE_OK on success.
2647 CURLcode Curl_parse_login_details(const char *login, const size_t len,
2648 char **userp, char **passwdp,
2651 CURLcode result = CURLE_OK;
2655 const char *psep = NULL;
2656 const char *osep = NULL;
2661 /* the input length check is because this is called directcly from setopt
2662 and isn't going through the regular string length check */
2663 size_t llen = strlen(login);
2664 if(llen > CURL_MAX_INPUT_LENGTH)
2665 return CURLE_BAD_FUNCTION_ARGUMENT;
2667 /* Attempt to find the password separator */
2669 psep = strchr(login, ':');
2671 /* Within the constraint of the login string */
2672 if(psep >= login + len)
2676 /* Attempt to find the options separator */
2678 osep = strchr(login, ';');
2680 /* Within the constraint of the login string */
2681 if(osep >= login + len)
2685 /* Calculate the portion lengths */
2687 (size_t)(osep && psep > osep ? osep - login : psep - login) :
2688 (osep ? (size_t)(osep - login) : len));
2690 (osep && osep > psep ? (size_t)(osep - psep) :
2691 (size_t)(login + len - psep)) - 1 : 0);
2693 (psep && psep > osep ? (size_t)(psep - osep) :
2694 (size_t)(login + len - osep)) - 1 : 0);
2696 /* Allocate the user portion buffer */
2698 ubuf = malloc(ulen + 1);
2700 result = CURLE_OUT_OF_MEMORY;
2703 /* Allocate the password portion buffer */
2704 if(!result && passwdp && plen) {
2705 pbuf = malloc(plen + 1);
2708 result = CURLE_OUT_OF_MEMORY;
2712 /* Allocate the options portion buffer */
2713 if(!result && optionsp && olen) {
2714 obuf = malloc(olen + 1);
2718 result = CURLE_OUT_OF_MEMORY;
2723 /* Store the user portion if necessary */
2725 memcpy(ubuf, login, ulen);
2727 Curl_safefree(*userp);
2731 /* Store the password portion if necessary */
2733 memcpy(pbuf, psep + 1, plen);
2735 Curl_safefree(*passwdp);
2739 /* Store the options portion if necessary */
2741 memcpy(obuf, osep + 1, olen);
2743 Curl_safefree(*optionsp);
2751 /*************************************************************
2752 * Figure out the remote port number and fix it in the URL
2754 * No matter if we use a proxy or not, we have to figure out the remote
2755 * port number of various reasons.
2757 * The port number embedded in the URL is replaced, if necessary.
2758 *************************************************************/
2759 static CURLcode parse_remote_port(struct Curl_easy *data,
2760 struct connectdata *conn)
2763 if(data->set.use_port && data->state.allow_port) {
2764 /* if set, we use this instead of the port possibly given in the URL */
2767 conn->remote_port = (unsigned short)data->set.use_port;
2768 msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port);
2769 uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
2771 return CURLE_OUT_OF_MEMORY;
2778 * Override the login details from the URL with that in the CURLOPT_USERPWD
2779 * option or a .netrc file, if applicable.
2781 static CURLcode override_login(struct Curl_easy *data,
2782 struct connectdata *conn,
2783 char **userp, char **passwdp, char **optionsp)
2785 bool user_changed = FALSE;
2786 bool passwd_changed = FALSE;
2789 if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) {
2790 /* ignore user+password in the URL */
2792 Curl_safefree(*userp);
2793 user_changed = TRUE;
2796 Curl_safefree(*passwdp);
2797 passwd_changed = TRUE;
2799 conn->bits.user_passwd = FALSE; /* disable user+password */
2802 if(data->set.str[STRING_USERNAME]) {
2804 *userp = strdup(data->set.str[STRING_USERNAME]);
2806 return CURLE_OUT_OF_MEMORY;
2807 conn->bits.user_passwd = TRUE; /* enable user+password */
2808 user_changed = TRUE;
2811 if(data->set.str[STRING_PASSWORD]) {
2813 *passwdp = strdup(data->set.str[STRING_PASSWORD]);
2815 return CURLE_OUT_OF_MEMORY;
2816 conn->bits.user_passwd = TRUE; /* enable user+password */
2817 passwd_changed = TRUE;
2820 if(data->set.str[STRING_OPTIONS]) {
2822 *optionsp = strdup(data->set.str[STRING_OPTIONS]);
2824 return CURLE_OUT_OF_MEMORY;
2827 conn->bits.netrc = FALSE;
2828 if(data->set.use_netrc != CURL_NETRC_IGNORED &&
2829 (!*userp || !**userp || !*passwdp || !**passwdp)) {
2830 bool netrc_user_changed = FALSE;
2831 bool netrc_passwd_changed = FALSE;
2834 ret = Curl_parsenetrc(conn->host.name,
2836 &netrc_user_changed, &netrc_passwd_changed,
2837 data->set.str[STRING_NETRC_FILE]);
2839 infof(data, "Couldn't find host %s in the .netrc file; using defaults\n",
2843 return CURLE_OUT_OF_MEMORY;
2846 /* set bits.netrc TRUE to remember that we got the name from a .netrc
2847 file, so that it is safe to use even if we followed a Location: to a
2848 different host or similar. */
2849 conn->bits.netrc = TRUE;
2850 conn->bits.user_passwd = TRUE; /* enable user+password */
2852 if(netrc_user_changed) {
2853 user_changed = TRUE;
2855 if(netrc_passwd_changed) {
2856 passwd_changed = TRUE;
2861 /* for updated strings, we update them in the URL */
2863 uc = curl_url_set(data->state.uh, CURLUPART_USER, *userp,
2866 return Curl_uc_to_curlcode(uc);
2868 if(passwd_changed) {
2869 uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, *passwdp,
2872 return Curl_uc_to_curlcode(uc);
2878 * Set the login details so they're available in the connection
2880 static CURLcode set_login(struct connectdata *conn)
2882 CURLcode result = CURLE_OK;
2883 const char *setuser = CURL_DEFAULT_USER;
2884 const char *setpasswd = CURL_DEFAULT_PASSWORD;
2886 /* If our protocol needs a password and we have none, use the defaults */
2887 if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd)
2893 /* Store the default user */
2895 conn->user = strdup(setuser);
2897 return CURLE_OUT_OF_MEMORY;
2900 /* Store the default password */
2902 conn->passwd = strdup(setpasswd);
2904 result = CURLE_OUT_OF_MEMORY;
2911 * Parses a "host:port" string to connect to.
2912 * The hostname and the port may be empty; in this case, NULL is returned for
2913 * the hostname and -1 for the port.
2915 static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
2917 char **hostname_result,
2926 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
2930 *hostname_result = NULL;
2936 host_dup = strdup(host);
2938 return CURLE_OUT_OF_MEMORY;
2942 /* start scanning for port number at this point */
2945 /* detect and extract RFC6874-style IPv6-addresses */
2946 if(*hostptr == '[') {
2948 char *ptr = ++hostptr; /* advance beyond the initial bracket */
2949 while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
2952 /* There might be a zone identifier */
2953 if(strncmp("%25", ptr, 3))
2954 infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
2956 /* Allow unreserved characters as defined in RFC 3986 */
2957 while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
2958 (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
2962 /* yeps, it ended nicely with a bracket as well */
2965 infof(data, "Invalid IPv6 address format\n");
2967 /* Note that if this didn't end with a bracket, we still advanced the
2968 * hostptr first, but I can't see anything wrong with that as no host
2969 * name nor a numeric can legally start with a bracket.
2972 failf(data, "Use of IPv6 in *_CONNECT_TO without IPv6 support built-in!");
2974 return CURLE_NOT_BUILT_IN;
2978 /* Get port number off server.com:1080 */
2979 host_portno = strchr(portptr, ':');
2982 *host_portno = '\0'; /* cut off number from host name */
2985 long portparse = strtol(host_portno, &endp, 10);
2986 if((endp && *endp) || (portparse < 0) || (portparse > 65535)) {
2987 infof(data, "No valid port number in connect to host string (%s)\n",
2993 port = (int)portparse; /* we know it will fit */
2997 /* now, clone the cleaned host name */
2999 *hostname_result = strdup(hostptr);
3000 if(!*hostname_result) {
3002 return CURLE_OUT_OF_MEMORY;
3006 *port_result = port;
3013 * Parses one "connect to" string in the form:
3014 * "HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT".
3016 static CURLcode parse_connect_to_string(struct Curl_easy *data,
3017 struct connectdata *conn,
3018 const char *conn_to_host,
3022 CURLcode result = CURLE_OK;
3023 const char *ptr = conn_to_host;
3024 int host_match = FALSE;
3025 int port_match = FALSE;
3027 *host_result = NULL;
3031 /* an empty hostname always matches */
3036 /* check whether the URL's hostname matches */
3037 size_t hostname_to_match_len;
3038 char *hostname_to_match = aprintf("%s%s%s",
3039 conn->bits.ipv6_ip ? "[" : "",
3041 conn->bits.ipv6_ip ? "]" : "");
3042 if(!hostname_to_match)
3043 return CURLE_OUT_OF_MEMORY;
3044 hostname_to_match_len = strlen(hostname_to_match);
3045 host_match = strncasecompare(ptr, hostname_to_match,
3046 hostname_to_match_len);
3047 free(hostname_to_match);
3048 ptr += hostname_to_match_len;
3050 host_match = host_match && *ptr == ':';
3056 /* an empty port always matches */
3061 /* check whether the URL's port matches */
3062 char *ptr_next = strchr(ptr, ':');
3065 long port_to_match = strtol(ptr, &endp, 10);
3066 if((endp == ptr_next) && (port_to_match == conn->remote_port)) {
3074 if(host_match && port_match) {
3075 /* parse the hostname and port to connect to */
3076 result = parse_connect_to_host_port(data, ptr, host_result, port_result);
3083 * Processes all strings in the "connect to" slist, and uses the "connect
3084 * to host" and "connect to port" of the first string that matches.
3086 static CURLcode parse_connect_to_slist(struct Curl_easy *data,
3087 struct connectdata *conn,
3088 struct curl_slist *conn_to_host)
3090 CURLcode result = CURLE_OK;
3094 while(conn_to_host && !host && port == -1) {
3095 result = parse_connect_to_string(data, conn, conn_to_host->data,
3101 conn->conn_to_host.rawalloc = host;
3102 conn->conn_to_host.name = host;
3103 conn->bits.conn_to_host = TRUE;
3105 infof(data, "Connecting to hostname: %s\n", host);
3108 /* no "connect to host" */
3109 conn->bits.conn_to_host = FALSE;
3110 Curl_safefree(host);
3114 conn->conn_to_port = port;
3115 conn->bits.conn_to_port = TRUE;
3116 infof(data, "Connecting to port: %d\n", port);
3119 /* no "connect to port" */
3120 conn->bits.conn_to_port = FALSE;
3124 conn_to_host = conn_to_host->next;
3128 if(data->asi && !host && (port == -1) &&
3129 ((conn->handler->protocol == CURLPROTO_HTTPS) ||
3131 /* allow debug builds to circumvent the HTTPS restriction */
3132 getenv("CURL_ALTSVC_HTTP")
3137 /* no connect_to match, try alt-svc! */
3138 enum alpnid srcalpnid;
3141 const int allowed_versions = ( ALPN_h1
3148 ) & data->asi->flags;
3150 host = conn->host.rawalloc;
3152 /* with h2 support, check that first */
3153 srcalpnid = ALPN_h2;
3154 hit = Curl_altsvc_lookup(data->asi,
3155 srcalpnid, host, conn->remote_port, /* from */
3161 srcalpnid = ALPN_h1;
3162 hit = Curl_altsvc_lookup(data->asi,
3163 srcalpnid, host, conn->remote_port, /* from */
3168 char *hostd = strdup((char *)as->dst.host);
3170 return CURLE_OUT_OF_MEMORY;
3171 conn->conn_to_host.rawalloc = hostd;
3172 conn->conn_to_host.name = hostd;
3173 conn->bits.conn_to_host = TRUE;
3174 conn->conn_to_port = as->dst.port;
3175 conn->bits.conn_to_port = TRUE;
3176 conn->bits.altused = TRUE;
3177 infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d\n",
3178 Curl_alpnid2str(srcalpnid), host, conn->remote_port,
3179 Curl_alpnid2str(as->dst.alpnid), hostd, as->dst.port);
3180 if(srcalpnid != as->dst.alpnid) {
3181 /* protocol version switch */
3182 switch(as->dst.alpnid) {
3184 conn->httpversion = 11;
3187 conn->httpversion = 20;
3190 conn->transport = TRNSPRT_QUIC;
3191 conn->httpversion = 30;
3193 default: /* shouldn't be possible */
3204 /*************************************************************
3205 * Resolve the address of the server or proxy
3206 *************************************************************/
3207 static CURLcode resolve_server(struct Curl_easy *data,
3208 struct connectdata *conn,
3211 CURLcode result = CURLE_OK;
3212 timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
3216 /*************************************************************
3217 * Resolve the name of the server or proxy
3218 *************************************************************/
3219 if(conn->bits.reuse)
3220 /* We're reusing the connection - no need to resolve anything, and
3221 idnconvert_hostname() was called already in create_conn() for the re-use
3226 /* this is a fresh connect */
3228 struct Curl_dns_entry *hostaddr = NULL;
3230 #ifdef USE_UNIX_SOCKETS
3231 if(conn->unix_domain_socket) {
3232 /* Unix domain sockets are local. The host gets ignored, just use the
3233 * specified domain socket address. Do not cache "DNS entries". There is
3234 * no DNS involved and we already have the filesystem path available */
3235 const char *path = conn->unix_domain_socket;
3237 hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
3239 result = CURLE_OUT_OF_MEMORY;
3241 bool longpath = FALSE;
3242 hostaddr->addr = Curl_unix2addr(path, &longpath,
3243 conn->bits.abstract_unix_socket);
3247 /* Long paths are not supported for now */
3249 failf(data, "Unix socket path too long: '%s'", path);
3250 result = CURLE_COULDNT_RESOLVE_HOST;
3253 result = CURLE_OUT_OF_MEMORY;
3262 if(!conn->bits.proxy) {
3263 struct hostname *connhost;
3264 if(conn->bits.conn_to_host)
3265 connhost = &conn->conn_to_host;
3267 connhost = &conn->host;
3269 /* If not connecting via a proxy, extract the port from the URL, if it is
3270 * there, thus overriding any defaults that might have been set above. */
3271 if(conn->bits.conn_to_port)
3272 conn->port = conn->conn_to_port;
3274 conn->port = conn->remote_port;
3276 /* Resolve target host right on */
3277 conn->hostname_resolve = strdup(connhost->name);
3278 if(!conn->hostname_resolve)
3279 return CURLE_OUT_OF_MEMORY;
3280 rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
3281 &hostaddr, timeout_ms);
3282 if(rc == CURLRESOLV_PENDING)
3285 else if(rc == CURLRESOLV_TIMEDOUT)
3286 result = CURLE_OPERATION_TIMEDOUT;
3288 else if(!hostaddr) {
3289 failf(data, "Couldn't resolve host '%s'", connhost->dispname);
3290 result = CURLE_COULDNT_RESOLVE_HOST;
3291 /* don't return yet, we need to clean up the timeout first */
3294 #ifndef CURL_DISABLE_PROXY
3296 /* This is a proxy that hasn't been resolved yet. */
3298 struct hostname * const host = conn->bits.socksproxy ?
3299 &conn->socks_proxy.host : &conn->http_proxy.host;
3302 conn->hostname_resolve = strdup(host->name);
3303 if(!conn->hostname_resolve)
3304 return CURLE_OUT_OF_MEMORY;
3305 rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
3306 &hostaddr, timeout_ms);
3308 if(rc == CURLRESOLV_PENDING)
3311 else if(rc == CURLRESOLV_TIMEDOUT)
3312 result = CURLE_OPERATION_TIMEDOUT;
3314 else if(!hostaddr) {
3315 failf(data, "Couldn't resolve proxy '%s'", host->dispname);
3316 result = CURLE_COULDNT_RESOLVE_PROXY;
3317 /* don't return yet, we need to clean up the timeout first */
3321 DEBUGASSERT(conn->dns_entry == NULL);
3322 conn->dns_entry = hostaddr;
3329 * Cleanup the connection just allocated before we can move along and use the
3330 * previously existing one. All relevant data is copied over and old_conn is
3331 * ready for freeing once this function returns.
3333 static void reuse_conn(struct connectdata *old_conn,
3334 struct connectdata *conn)
3336 #ifndef CURL_DISABLE_PROXY
3337 Curl_free_idnconverted_hostname(&old_conn->http_proxy.host);
3338 Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host);
3340 free(old_conn->http_proxy.host.rawalloc);
3341 free(old_conn->socks_proxy.host.rawalloc);
3342 Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
3344 /* free the SSL config struct from this connection struct as this was
3345 allocated in vain and is targeted for destruction */
3346 Curl_free_primary_ssl_config(&old_conn->ssl_config);
3348 conn->data = old_conn->data;
3350 /* get the user+password information from the old_conn struct since it may
3351 * be new for this request even when we re-use an existing connection */
3352 conn->bits.user_passwd = old_conn->bits.user_passwd;
3353 if(conn->bits.user_passwd) {
3354 /* use the new user name and password though */
3355 Curl_safefree(conn->user);
3356 Curl_safefree(conn->passwd);
3357 conn->user = old_conn->user;
3358 conn->passwd = old_conn->passwd;
3359 old_conn->user = NULL;
3360 old_conn->passwd = NULL;
3363 #ifndef CURL_DISABLE_PROXY
3364 conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
3365 if(conn->bits.proxy_user_passwd) {
3366 /* use the new proxy user name and proxy password though */
3367 Curl_safefree(conn->http_proxy.user);
3368 Curl_safefree(conn->socks_proxy.user);
3369 Curl_safefree(conn->http_proxy.passwd);
3370 Curl_safefree(conn->socks_proxy.passwd);
3371 conn->http_proxy.user = old_conn->http_proxy.user;
3372 conn->socks_proxy.user = old_conn->socks_proxy.user;
3373 conn->http_proxy.passwd = old_conn->http_proxy.passwd;
3374 conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
3375 old_conn->http_proxy.user = NULL;
3376 old_conn->socks_proxy.user = NULL;
3377 old_conn->http_proxy.passwd = NULL;
3378 old_conn->socks_proxy.passwd = NULL;
3380 Curl_safefree(old_conn->http_proxy.user);
3381 Curl_safefree(old_conn->socks_proxy.user);
3382 Curl_safefree(old_conn->http_proxy.passwd);
3383 Curl_safefree(old_conn->socks_proxy.passwd);
3386 /* host can change, when doing keepalive with a proxy or if the case is
3387 different this time etc */
3388 Curl_free_idnconverted_hostname(&conn->host);
3389 Curl_free_idnconverted_hostname(&conn->conn_to_host);
3390 Curl_safefree(conn->host.rawalloc);
3391 Curl_safefree(conn->conn_to_host.rawalloc);
3392 conn->host = old_conn->host;
3393 conn->conn_to_host = old_conn->conn_to_host;
3394 conn->conn_to_port = old_conn->conn_to_port;
3395 conn->remote_port = old_conn->remote_port;
3396 Curl_safefree(conn->hostname_resolve);
3398 conn->hostname_resolve = old_conn->hostname_resolve;
3399 old_conn->hostname_resolve = NULL;
3401 /* persist connection info in session handle */
3402 Curl_persistconninfo(conn);
3404 conn_reset_all_postponed_data(old_conn); /* free buffers */
3407 conn->bits.reuse = TRUE; /* yes, we're re-using here */
3409 Curl_safefree(old_conn->user);
3410 Curl_safefree(old_conn->passwd);
3411 Curl_safefree(old_conn->options);
3412 Curl_safefree(old_conn->localdev);
3413 Curl_llist_destroy(&old_conn->easyq, NULL);
3415 #ifdef USE_UNIX_SOCKETS
3416 Curl_safefree(old_conn->unix_domain_socket);
3421 * create_conn() sets up a new connectdata struct, or re-uses an already
3422 * existing one, and resolves host name.
3424 * if this function returns CURLE_OK and *async is set to TRUE, the resolve
3425 * response will be coming asynchronously. If *async is FALSE, the name is
3428 * @param data The sessionhandle pointer
3429 * @param in_connect is set to the next connection data pointer
3430 * @param async is set TRUE when an async DNS resolution is pending
3431 * @see Curl_setup_conn()
3433 * *NOTE* this function assigns the conn->data pointer!
3436 static CURLcode create_conn(struct Curl_easy *data,
3437 struct connectdata **in_connect,
3440 CURLcode result = CURLE_OK;
3441 struct connectdata *conn;
3442 struct connectdata *conn_temp = NULL;
3444 bool connections_available = TRUE;
3445 bool force_reuse = FALSE;
3446 bool waitpipe = FALSE;
3447 size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
3448 size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
3453 /*************************************************************
3455 *************************************************************/
3456 if(!data->change.url) {
3457 result = CURLE_URL_MALFORMAT;
3461 /* First, split up the current URL in parts so that we can use the
3462 parts for checking against the already present connections. In order
3463 to not have to modify everything at once, we allocate a temporary
3464 connection data struct and fill in for comparison purposes. */
3465 conn = allocate_conn(data);
3468 result = CURLE_OUT_OF_MEMORY;
3472 /* We must set the return variable as soon as possible, so that our
3473 parent can cleanup any possible allocs we may have done before
3477 result = parseurlandfillconn(data, conn);
3481 if(data->set.str[STRING_SASL_AUTHZID]) {
3482 conn->sasl_authzid = strdup(data->set.str[STRING_SASL_AUTHZID]);
3483 if(!conn->sasl_authzid) {
3484 result = CURLE_OUT_OF_MEMORY;
3489 #ifdef USE_UNIX_SOCKETS
3490 if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
3491 conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
3492 if(conn->unix_domain_socket == NULL) {
3493 result = CURLE_OUT_OF_MEMORY;
3496 conn->bits.abstract_unix_socket = data->set.abstract_unix_socket;
3500 /* After the unix socket init but before the proxy vars are used, parse and
3501 initialize the proxy vars */
3502 #ifndef CURL_DISABLE_PROXY
3503 result = create_conn_helper_init_proxy(conn);
3507 /*************************************************************
3508 * If the protocol is using SSL and HTTP proxy is used, we set
3509 * the tunnel_proxy bit.
3510 *************************************************************/
3511 if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
3512 conn->bits.tunnel_proxy = TRUE;
3515 /*************************************************************
3516 * Figure out the remote port number and fix it in the URL
3517 *************************************************************/
3518 result = parse_remote_port(data, conn);
3522 /* Check for overridden login details and set them accordingly so they
3523 they are known when protocol->setup_connection is called! */
3524 result = override_login(data, conn, &conn->user, &conn->passwd,
3529 result = set_login(conn); /* default credentials */
3533 /*************************************************************
3534 * Process the "connect to" linked list of hostname/port mappings.
3535 * Do this after the remote port number has been fixed in the URL.
3536 *************************************************************/
3537 result = parse_connect_to_slist(data, conn, data->set.connect_to);
3541 /*************************************************************
3542 * IDN-convert the hostnames
3543 *************************************************************/
3544 result = Curl_idnconvert_hostname(conn, &conn->host);
3547 if(conn->bits.conn_to_host) {
3548 result = Curl_idnconvert_hostname(conn, &conn->conn_to_host);
3552 #ifndef CURL_DISABLE_PROXY
3553 if(conn->bits.httpproxy) {
3554 result = Curl_idnconvert_hostname(conn, &conn->http_proxy.host);
3558 if(conn->bits.socksproxy) {
3559 result = Curl_idnconvert_hostname(conn, &conn->socks_proxy.host);
3565 /*************************************************************
3566 * Check whether the host and the "connect to host" are equal.
3567 * Do this after the hostnames have been IDN-converted.
3568 *************************************************************/
3569 if(conn->bits.conn_to_host &&
3570 strcasecompare(conn->conn_to_host.name, conn->host.name)) {
3571 conn->bits.conn_to_host = FALSE;
3574 /*************************************************************
3575 * Check whether the port and the "connect to port" are equal.
3576 * Do this after the remote port number has been fixed in the URL.
3577 *************************************************************/
3578 if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
3579 conn->bits.conn_to_port = FALSE;
3582 #ifndef CURL_DISABLE_PROXY
3583 /*************************************************************
3584 * If the "connect to" feature is used with an HTTP proxy,
3585 * we set the tunnel_proxy bit.
3586 *************************************************************/
3587 if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
3588 conn->bits.httpproxy)
3589 conn->bits.tunnel_proxy = TRUE;
3592 /*************************************************************
3593 * Setup internals depending on protocol. Needs to be done after
3594 * we figured out what/if proxy to use.
3595 *************************************************************/
3596 result = setup_connection_internals(conn);
3600 conn->recv[FIRSTSOCKET] = Curl_recv_plain;
3601 conn->send[FIRSTSOCKET] = Curl_send_plain;
3602 conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
3603 conn->send[SECONDARYSOCKET] = Curl_send_plain;
3605 conn->bits.tcp_fastopen = data->set.tcp_fastopen;
3607 /***********************************************************************
3608 * file: is a special case in that it doesn't need a network connection
3609 ***********************************************************************/
3610 #ifndef CURL_DISABLE_FILE
3611 if(conn->handler->flags & PROTOPT_NONETWORK) {
3613 /* this is supposed to be the connect function so we better at least check
3614 that the file is present here! */
3615 DEBUGASSERT(conn->handler->connect_it);
3616 Curl_persistconninfo(conn);
3617 result = conn->handler->connect_it(conn, &done);
3619 /* Setup a "faked" transfer that'll do nothing */
3621 conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
3623 Curl_attach_connnection(data, conn);
3624 result = Curl_conncache_add_conn(data->state.conn_cache, conn);
3629 * Setup whatever necessary for a resumed transfer
3631 result = setup_range(data);
3633 DEBUGASSERT(conn->handler->done);
3634 /* we ignore the return code for the protocol-specific DONE */
3635 (void)conn->handler->done(conn, result, FALSE);
3638 Curl_setup_transfer(data, -1, -1, FALSE, -1);
3641 /* since we skip do_init() */
3642 Curl_init_do(data, conn);
3648 /* Get a cloned copy of the SSL config situation stored in the
3649 connection struct. But to get this going nicely, we must first make
3650 sure that the strings in the master copy are pointing to the correct
3651 strings in the session handle strings array!
3653 Keep in mind that the pointers in the master copy are pointing to strings
3654 that will be freed as part of the Curl_easy struct, but all cloned
3655 copies will be separately allocated.
3657 data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
3658 data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
3659 data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
3660 data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
3661 data->set.ssl.primary.cipher_list =
3662 data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
3663 data->set.ssl.primary.cipher_list13 =
3664 data->set.str[STRING_SSL_CIPHER13_LIST_ORIG];
3665 data->set.ssl.primary.pinned_key =
3666 data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
3667 data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_ORIG];
3668 data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
3670 #ifndef CURL_DISABLE_PROXY
3671 data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
3672 data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
3673 data->set.proxy_ssl.primary.random_file =
3674 data->set.str[STRING_SSL_RANDOM_FILE];
3675 data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
3676 data->set.proxy_ssl.primary.cipher_list =
3677 data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
3678 data->set.proxy_ssl.primary.cipher_list13 =
3679 data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
3680 data->set.proxy_ssl.primary.pinned_key =
3681 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
3682 data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
3683 data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
3684 data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
3685 data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
3686 data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
3687 data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
3688 data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
3689 data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
3690 data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
3692 data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
3693 data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
3694 data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
3695 data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
3696 data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
3697 data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
3698 data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
3700 data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
3701 data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
3702 #ifndef CURL_DISABLE_PROXY
3703 data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
3704 data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
3708 data->set.ssl.key_blob = data->set.blobs[BLOB_KEY_ORIG];
3709 data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG];
3711 if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
3712 &conn->ssl_config)) {
3713 result = CURLE_OUT_OF_MEMORY;
3717 #ifndef CURL_DISABLE_PROXY
3718 if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
3719 &conn->proxy_ssl_config)) {
3720 result = CURLE_OUT_OF_MEMORY;
3725 prune_dead_connections(data);
3727 /*************************************************************
3728 * Check the current list of connections to see if we can
3729 * re-use an already existing one or if we have to create a
3731 *************************************************************/
3733 DEBUGASSERT(conn->user);
3734 DEBUGASSERT(conn->passwd);
3736 /* reuse_fresh is TRUE if we are told to use a new connection by force, but
3737 we only acknowledge this option if this is not a re-used connection
3738 already (which happens due to follow-location or during a HTTP
3739 authentication phase). CONNECT_ONLY transfers also refuse reuse. */
3740 if((data->set.reuse_fresh && !data->state.this_is_a_follow) ||
3741 data->set.connect_only)
3744 reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
3748 * We already have a connection for this, we got the former connection
3749 * in the conn_temp variable and thus we need to cleanup the one we
3750 * just allocated before we can move along and use the previously
3753 reuse_conn(conn, conn_temp);
3755 free(conn->ssl_extra);
3757 free(conn); /* we don't need this anymore */
3761 #ifndef CURL_DISABLE_PROXY
3762 infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
3763 conn->connection_id,
3764 conn->bits.proxy?"proxy":"host",
3765 conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
3766 conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
3767 conn->host.dispname);
3769 infof(data, "Re-using existing connection! (#%ld) with host %s\n",
3770 conn->connection_id, conn->host.dispname);
3774 /* We have decided that we want a new connection. However, we may not
3775 be able to do that if we have reached the limit of how many
3776 connections we are allowed to open. */
3778 if(conn->handler->flags & PROTOPT_ALPN_NPN) {
3779 /* The protocol wants it, so set the bits if enabled in the easy handle
3781 if(data->set.ssl_enable_alpn)
3782 conn->bits.tls_enable_alpn = TRUE;
3783 if(data->set.ssl_enable_npn)
3784 conn->bits.tls_enable_npn = TRUE;
3788 /* There is a connection that *might* become usable for multiplexing
3789 "soon", and we wait for that */
3790 connections_available = FALSE;
3792 /* this gets a lock on the conncache */
3793 const char *bundlehost;
3794 struct connectbundle *bundle =
3795 Curl_conncache_find_bundle(conn, data->state.conn_cache, &bundlehost);
3797 if(max_host_connections > 0 && bundle &&
3798 (bundle->num_connections >= max_host_connections)) {
3799 struct connectdata *conn_candidate;
3801 /* The bundle is full. Extract the oldest connection. */
3802 conn_candidate = Curl_conncache_extract_bundle(data, bundle);
3803 CONNCACHE_UNLOCK(data);
3806 (void)Curl_disconnect(data, conn_candidate, FALSE);
3808 infof(data, "No more connections allowed to host %s: %zu\n",
3809 bundlehost, max_host_connections);
3810 connections_available = FALSE;
3814 CONNCACHE_UNLOCK(data);
3818 if(connections_available &&
3819 (max_total_connections > 0) &&
3820 (Curl_conncache_size(data) >= max_total_connections)) {
3821 struct connectdata *conn_candidate;
3823 /* The cache is full. Let's see if we can kill a connection. */
3824 conn_candidate = Curl_conncache_extract_oldest(data);
3826 (void)Curl_disconnect(data, conn_candidate, FALSE);
3828 infof(data, "No connections available in cache\n");
3829 connections_available = FALSE;
3833 if(!connections_available) {
3834 infof(data, "No connections available.\n");
3839 result = CURLE_NO_CONNECTION_AVAILABLE;
3844 * This is a brand new connection, so let's store it in the connection
3847 Curl_attach_connnection(data, conn);
3849 result = Curl_conncache_add_conn(data->state.conn_cache, conn);
3854 #if defined(USE_NTLM)
3855 /* If NTLM is requested in a part of this connection, make sure we don't
3856 assume the state is fine as this is a fresh connection and NTLM is
3857 connection based. */
3858 if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
3859 data->state.authhost.done) {
3860 infof(data, "NTLM picked AND auth done set, clear picked!\n");
3861 data->state.authhost.picked = CURLAUTH_NONE;
3862 data->state.authhost.done = FALSE;
3865 if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
3866 data->state.authproxy.done) {
3867 infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n");
3868 data->state.authproxy.picked = CURLAUTH_NONE;
3869 data->state.authproxy.done = FALSE;
3874 /* Setup and init stuff before DO starts, in preparing for the transfer. */
3875 Curl_init_do(data, conn);
3878 * Setup whatever necessary for a resumed transfer
3880 result = setup_range(data);
3884 /* Continue connectdata initialization here. */
3887 * Inherit the proper values from the urldata struct AFTER we have arranged
3888 * the persistent connection stuff
3890 conn->seek_func = data->set.seek_func;
3891 conn->seek_client = data->set.seek_client;
3893 /*************************************************************
3894 * Resolve the address of the server or proxy
3895 *************************************************************/
3896 result = resolve_server(data, conn, async);
3898 /* Strip trailing dots. resolve_server copied the name. */
3899 strip_trailing_dot(&conn->host);
3900 #ifndef CURL_DISABLE_PROXY
3901 if(conn->bits.httpproxy)
3902 strip_trailing_dot(&conn->http_proxy.host);
3903 if(conn->bits.socksproxy)
3904 strip_trailing_dot(&conn->socks_proxy.host);
3906 if(conn->bits.conn_to_host)
3907 strip_trailing_dot(&conn->conn_to_host);
3913 /* Curl_setup_conn() is called after the name resolve initiated in
3914 * create_conn() is all done.
3916 * Curl_setup_conn() also handles reused connections
3918 * conn->data MUST already have been setup fine (in create_conn)
3921 CURLcode Curl_setup_conn(struct connectdata *conn,
3922 bool *protocol_done)
3924 CURLcode result = CURLE_OK;
3925 struct Curl_easy *data = conn->data;
3927 Curl_pgrsTime(data, TIMER_NAMELOOKUP);
3929 if(conn->handler->flags & PROTOPT_NONETWORK) {
3930 /* nothing to setup when not using a network */
3931 *protocol_done = TRUE;
3934 *protocol_done = FALSE; /* default to not done */
3936 #ifndef CURL_DISABLE_PROXY
3937 /* set proxy_connect_closed to false unconditionally already here since it
3938 is used strictly to provide extra information to a parent function in the
3939 case of proxy CONNECT failures and we must make sure we don't have it
3940 lingering set from a previous invoke */
3941 conn->bits.proxy_connect_closed = FALSE;
3944 * Set user-agent. Used for HTTP, but since we can attempt to tunnel
3945 * basically anything through a http proxy we can't limit this based on
3948 if(data->set.str[STRING_USERAGENT]) {
3949 Curl_safefree(data->state.aptr.uagent);
3950 data->state.aptr.uagent =
3951 aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
3952 if(!data->state.aptr.uagent)
3953 return CURLE_OUT_OF_MEMORY;
3956 data->req.headerbytecount = 0;
3958 #ifdef CURL_DO_LINEEND_CONV
3959 data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
3960 #endif /* CURL_DO_LINEEND_CONV */
3962 /* set start time here for timeout purposes in the connect procedure, it
3963 is later set again for the progress meter purpose */
3964 conn->now = Curl_now();
3966 if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
3967 conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
3968 result = Curl_connecthost(conn, conn->dns_entry);
3973 Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
3974 if(conn->ssl[FIRSTSOCKET].use ||
3975 (conn->handler->protocol & PROTO_FAMILY_SSH))
3976 Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
3977 conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
3978 *protocol_done = TRUE;
3979 Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
3980 Curl_verboseconnect(conn);
3983 conn->now = Curl_now(); /* time this *after* the connect is done, we set
3984 this here perhaps a second time */
3988 CURLcode Curl_connect(struct Curl_easy *data,
3990 bool *protocol_done)
3993 struct connectdata *conn;
3995 *asyncp = FALSE; /* assume synchronous resolves by default */
3997 /* init the single-transfer specific data */
3998 Curl_free_request_state(data);
3999 memset(&data->req, 0, sizeof(struct SingleRequest));
4000 data->req.maxdownload = -1;
4002 /* call the stuff that needs to be called */
4003 result = create_conn(data, &conn, asyncp);
4006 if(CONN_INUSE(conn) > 1)
4008 *protocol_done = TRUE;
4010 /* DNS resolution is done: that's either because this is a reused
4011 connection, in which case DNS was unnecessary, or because DNS
4012 really did finish already (synch resolver/fast async resolve) */
4013 result = Curl_setup_conn(conn, protocol_done);
4017 if(result == CURLE_NO_CONNECTION_AVAILABLE) {
4020 else if(result && conn) {
4021 /* We're not allowed to return failure with memory left allocated in the
4022 connectdata struct, free those here */
4023 Curl_detach_connnection(data);
4024 Curl_conncache_remove_conn(data, conn, TRUE);
4025 Curl_disconnect(data, conn, TRUE);
4032 * Curl_init_do() inits the readwrite session. This is inited each time (in
4033 * the DO function before the protocol-specific DO functions are invoked) for
4034 * a transfer, sometimes multiple times on the same Curl_easy. Make sure
4035 * nothing in here depends on stuff that are setup dynamically for the
4038 * Allow this function to get called with 'conn' set to NULL.
4041 CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
4043 struct SingleRequest *k = &data->req;
4045 /* if this is a pushed stream, we need this: */
4046 CURLcode result = Curl_preconnect(data);
4051 conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
4053 /* if the protocol used doesn't support wildcards, switch it off */
4054 if(data->state.wildcardmatch &&
4055 !(conn->handler->flags & PROTOPT_WILDCARD))
4056 data->state.wildcardmatch = FALSE;
4059 data->state.done = FALSE; /* *_done() is not called yet */
4060 data->state.expect100header = FALSE;
4062 if(data->set.opt_no_body)
4063 /* in HTTP lingo, no body means using the HEAD request... */
4064 data->state.httpreq = HTTPREQ_HEAD;
4066 k->start = Curl_now(); /* start time */
4067 k->now = k->start; /* current time is now */
4068 k->header = TRUE; /* assume header */
4070 k->ignorebody = FALSE;
4072 Curl_speedinit(data);
4073 Curl_pgrsSetUploadCounter(data, 0);
4074 Curl_pgrsSetDownloadCounter(data, 0);