Lines Matching +full:- +full:- +full:no +full:- +full:transfer +full:- +full:progress
21 * SPDX-License-Identifier: curl
30 #include "transfer.h"
34 #include "progress.h"
76 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
77 CURL handle takes 45-50 K memory, therefore this 3K are not significant.
94 ((x) && (x)->magic == CURL_MULTI_HANDLE)
133 data->req.chunk = FALSE; in before_perform()
139 /* this is a completed transfer */ in init_completed()
154 CURLMstate oldstate = data->mstate; in mstate()
183 data->mstate = state; in mstate()
186 if(data->mstate >= MSTATE_PENDING && in mstate()
187 data->mstate < MSTATE_COMPLETED) { in mstate()
188 long connection_id = -5000; in mstate()
190 if(data->conn) in mstate()
191 connection_id = data->conn->connection_id; in mstate()
195 statename[oldstate], statename[data->mstate], in mstate()
202 DEBUGASSERT(data->multi->num_alive > 0); in mstate()
203 data->multi->num_alive--; in mstate()
206 /* if this state has an init-function, run it */ in mstate()
230 /* bits for 'action' having no bits means this socket is not expecting any
281 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)he->ptr; in sockhash_destroy()
282 Curl_hash_destroy(&sh->transfers); in sockhash_destroy()
306 Curl_hash_init(&check->transfers, TRHASH_SIZE, trhash, trhash_compare, in sh_addentry()
311 Curl_hash_destroy(&check->transfers); in sh_addentry()
324 Curl_hash_destroy(&entry->transfers); in sh_delentry()
363 * limiting. It simply has a fixed-size array, and on each entry in the array
383 * Called when a transfer is completed. Adds the given msg pointer to
389 Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg, in multi_addmsg()
390 &msg->list); in multi_addmsg()
403 multi->magic = CURL_MULTI_HANDLE; in Curl_multi_handle()
405 Curl_init_dnscache(&multi->hostcache, dnssize); in Curl_multi_handle()
407 sh_init(&multi->sockhash, hashsize); in Curl_multi_handle()
409 if(Curl_conncache_init(&multi->conn_cache, chashsize)) in Curl_multi_handle()
412 Curl_llist_init(&multi->msglist, NULL); in Curl_multi_handle()
413 Curl_llist_init(&multi->pending, NULL); in Curl_multi_handle()
415 multi->multiplexing = TRUE; in Curl_multi_handle()
417 /* -1 means it not set by user, use the default value */ in Curl_multi_handle()
418 multi->maxconnects = -1; in Curl_multi_handle()
419 multi->max_concurrent_streams = 100; in Curl_multi_handle()
422 multi->wsa_event = WSACreateEvent(); in Curl_multi_handle()
423 if(multi->wsa_event == WSA_INVALID_EVENT) in Curl_multi_handle()
427 if(wakeup_create(multi->wakeup_pair) < 0) { in Curl_multi_handle()
428 multi->wakeup_pair[0] = CURL_SOCKET_BAD; in Curl_multi_handle()
429 multi->wakeup_pair[1] = CURL_SOCKET_BAD; in Curl_multi_handle()
431 else if(curlx_nonblock(multi->wakeup_pair[0], TRUE) < 0 || in Curl_multi_handle()
432 curlx_nonblock(multi->wakeup_pair[1], TRUE) < 0) { in Curl_multi_handle()
433 wakeup_close(multi->wakeup_pair[0]); in Curl_multi_handle()
434 wakeup_close(multi->wakeup_pair[1]); in Curl_multi_handle()
435 multi->wakeup_pair[0] = CURL_SOCKET_BAD; in Curl_multi_handle()
436 multi->wakeup_pair[1] = CURL_SOCKET_BAD; in Curl_multi_handle()
445 sockhash_destroy(&multi->sockhash); in Curl_multi_handle()
446 Curl_hash_destroy(&multi->hostcache); in Curl_multi_handle()
447 Curl_conncache_destroy(&multi->conn_cache); in Curl_multi_handle()
463 data->next = NULL; /* end of the line */ in link_easy()
464 if(multi->easyp) { in link_easy()
465 struct Curl_easy *last = multi->easylp; in link_easy()
466 last->next = data; in link_easy()
467 data->prev = last; in link_easy()
468 multi->easylp = data; /* the new last node */ in link_easy()
472 data->prev = NULL; in link_easy()
473 multi->easylp = multi->easyp = data; /* both first and last */ in link_easy()
482 if(data->prev) in unlink_easy()
483 data->prev->next = data->next; in unlink_easy()
485 multi->easyp = data->next; /* point to first node */ in unlink_easy()
488 if(data->next) in unlink_easy()
489 data->next->prev = data->prev; in unlink_easy()
491 multi->easylp = data->prev; /* point to last node */ in unlink_easy()
509 if(data->multi) in curl_multi_add_handle()
512 if(multi->in_callback) in curl_multi_add_handle()
515 if(multi->dead) { in curl_multi_add_handle()
517 handles are still alive - but if there are none alive anymore, it is in curl_multi_add_handle()
519 if(multi->num_alive) in curl_multi_add_handle()
521 multi->dead = FALSE; in curl_multi_add_handle()
525 Curl_llist_init(&data->state.timeoutlist, NULL); in curl_multi_add_handle()
528 * No failure allowed in this function beyond this point. And no in curl_multi_add_handle()
531 * function no matter what. in curl_multi_add_handle()
533 if(data->set.errorbuffer) in curl_multi_add_handle()
534 data->set.errorbuffer[0] = 0; in curl_multi_add_handle()
536 /* make the Curl_easy refer back to this multi handle - before Curl_expire() in curl_multi_add_handle()
538 data->multi = multi; in curl_multi_add_handle()
543 sockets that time-out or have actions will be dealt with. Since this in curl_multi_add_handle()
544 handle has no action yet, we make sure it times out to get things to in curl_multi_add_handle()
548 /* A somewhat crude work-around for a little glitch in Curl_update_timer() in curl_multi_add_handle()
555 The work-around is thus simply to clear the 'lastcall' variable to force in curl_multi_add_handle()
558 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall)); in curl_multi_add_handle()
569 if(!data->dns.hostcache || in curl_multi_add_handle()
570 (data->dns.hostcachetype == HCACHE_NONE)) { in curl_multi_add_handle()
571 data->dns.hostcache = &multi->hostcache; in curl_multi_add_handle()
572 data->dns.hostcachetype = HCACHE_MULTI; in curl_multi_add_handle()
576 if(data->share && (data->share->specifier & (1<< CURL_LOCK_DATA_CONNECT))) in curl_multi_add_handle()
577 data->state.conn_cache = &data->share->conn_cache; in curl_multi_add_handle()
579 data->state.conn_cache = &multi->conn_cache; in curl_multi_add_handle()
580 data->state.lastconnect_id = -1; in curl_multi_add_handle()
584 if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL))) in curl_multi_add_handle()
585 data->psl = &data->share->psl; in curl_multi_add_handle()
587 data->psl = &multi->psl; in curl_multi_add_handle()
592 /* increase the node-counter */ in curl_multi_add_handle()
593 multi->num_easy++; in curl_multi_add_handle()
595 /* increase the alive-counter */ in curl_multi_add_handle()
596 multi->num_alive++; in curl_multi_add_handle()
603 data->state.conn_cache->closure_handle->set.timeout = data->set.timeout; in curl_multi_add_handle()
604 data->state.conn_cache->closure_handle->set.server_response_timeout = in curl_multi_add_handle()
605 data->set.server_response_timeout; in curl_multi_add_handle()
606 data->state.conn_cache->closure_handle->set.no_signal = in curl_multi_add_handle()
607 data->set.no_signal; in curl_multi_add_handle()
614 /* Debug-function, used like this:
616 * Curl_hash_print(&multi->sockhash, debug_print_sock_hash);
625 sh->readers, sh->writers);
635 struct connectdata *conn = data->conn; in multi_done()
639 (int)status, (int)premature, data->state.done)); in multi_done()
641 if(data->state.done) in multi_done()
649 Curl_safefree(data->req.newurl); in multi_done()
650 Curl_safefree(data->req.location); in multi_done()
659 this more fine-grained in the future. */ in multi_done()
665 /* this calls the protocol-specific function pointer previously set */ in multi_done()
666 if(conn->handler->done) in multi_done()
667 result = conn->handler->done(data, status, premature); in multi_done()
679 /* Inform connection filters that this transfer is done */ in multi_done()
682 process_pending_handles(data->multi); /* connection / multiplex */ in multi_done()
690 "no more multi_done now!", in multi_done()
691 conn->easyq.size)); in multi_done()
695 data->state.done = TRUE; /* called just now! */ in multi_done()
697 if(conn->dns_entry) { in multi_done()
698 Curl_resolv_unlock(data, conn->dns_entry); /* done with this */ in multi_done()
699 conn->dns_entry = NULL; in multi_done()
702 Curl_safefree(data->state.ulbuf); in multi_done()
704 /* if the transfer was completed in a paused state there can be buffered in multi_done()
706 for(i = 0; i < data->state.tempcount; i++) { in multi_done()
707 Curl_dyn_free(&data->state.tempwrite[i].b); in multi_done()
709 data->state.tempcount = 0; in multi_done()
711 /* if data->set.reuse_forbid is TRUE, it means the libcurl client has in multi_done()
715 if conn->bits.close is TRUE, it means that the connection should be in multi_done()
721 state it is for re-using, so we're forced to close it. In a perfect world in multi_done()
723 but currently we have no such detail knowledge. in multi_done()
726 if((data->set.reuse_forbid in multi_done()
728 && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 || in multi_done()
729 conn->proxy_ntlm_state == NTLMSTATE_TYPE2) in multi_done()
732 && !(conn->http_negotiate_state == GSS_AUTHRECV || in multi_done()
733 conn->proxy_negotiate_state == GSS_AUTHRECV) in multi_done()
735 ) || conn->bits.close in multi_done()
737 DEBUGF(infof(data, "multi_done, not re-using connection=%ld, forbid=%d" in multi_done()
739 conn->connection_id, in multi_done()
740 data->set.reuse_forbid, conn->bits.close, premature, in multi_done()
751 conn->bits.socksproxy ? in multi_done()
752 conn->socks_proxy.host.dispname : in multi_done()
753 conn->bits.httpproxy ? conn->http_proxy.host.dispname : in multi_done()
755 conn->bits.conn_to_host ? conn->conn_to_host.dispname : in multi_done()
756 conn->host.dispname; in multi_done()
758 long connection_id = conn->connection_id; in multi_done()
762 /* the connection is no longer in use by this transfer */ in multi_done()
766 data->state.lastconnect_id = connection_id; in multi_done()
770 data->state.lastconnect_id = -1; in multi_done()
773 Curl_safefree(data->state.buffer); in multi_done()
781 if(data->state.lastconnect_id != conn->connection_id) in close_connect_only()
784 if(!conn->connect_only) in close_connect_only()
787 connclose(conn, "Removing connect-only easy handle"); in close_connect_only()
809 if(!data->multi) in curl_multi_remove_handle()
813 if(data->multi != multi) in curl_multi_remove_handle()
816 if(multi->in_callback) in curl_multi_remove_handle()
819 premature = (data->mstate < MSTATE_COMPLETED) ? TRUE : FALSE; in curl_multi_remove_handle()
826 multi->num_alive--; in curl_multi_remove_handle()
829 if(data->conn && in curl_multi_remove_handle()
830 data->mstate > MSTATE_DO && in curl_multi_remove_handle()
831 data->mstate < MSTATE_COMPLETED) { in curl_multi_remove_handle()
834 streamclose(data->conn, "Removed with partial response"); in curl_multi_remove_handle()
837 if(data->conn) { in curl_multi_remove_handle()
843 (void)multi_done(data, data->result, premature); in curl_multi_remove_handle()
846 /* The timer must be shut down before data->multi is set to NULL, else the in curl_multi_remove_handle()
851 if(data->connect_queue.ptr) in curl_multi_remove_handle()
854 Curl_llist_remove(&multi->pending, &data->connect_queue, NULL); in curl_multi_remove_handle()
856 if(data->dns.hostcachetype == HCACHE_MULTI) { in curl_multi_remove_handle()
859 data->dns.hostcache = NULL; in curl_multi_remove_handle()
860 data->dns.hostcachetype = HCACHE_NONE; in curl_multi_remove_handle()
863 Curl_wildcard_dtor(&data->wildcard); in curl_multi_remove_handle()
867 data->mstate = MSTATE_COMPLETED; in curl_multi_remove_handle()
877 if(data->set.connect_only && !data->multi_easy) { in curl_multi_remove_handle()
880 has bits.close set nothing can use that transfer anymore and it is in curl_multi_remove_handle()
895 if(data->state.lastconnect_id != -1) { in curl_multi_remove_handle()
896 /* Mark any connect-only connection for closure */ in curl_multi_remove_handle()
897 Curl_conncache_foreach(data, data->state.conn_cache, in curl_multi_remove_handle()
903 if(data->psl == &multi->psl) in curl_multi_remove_handle()
904 data->psl = NULL; in curl_multi_remove_handle()
909 data->state.conn_cache = NULL; in curl_multi_remove_handle()
911 data->multi = NULL; /* clear the association to this multi handle */ in curl_multi_remove_handle()
913 /* make sure there's no pending message in the queue sent from this easy in curl_multi_remove_handle()
916 for(e = multi->msglist.head; e; e = e->next) { in curl_multi_remove_handle()
917 struct Curl_message *msg = e->ptr; in curl_multi_remove_handle()
919 if(msg->extmsg.easy_handle == easy) { in curl_multi_remove_handle()
920 Curl_llist_remove(&multi->msglist, e, NULL); in curl_multi_remove_handle()
928 for(e = multi->pending.head; e; e = e->next) { in curl_multi_remove_handle()
929 struct Curl_easy *curr_data = e->ptr; in curl_multi_remove_handle()
932 Curl_llist_remove(&multi->pending, e, NULL); in curl_multi_remove_handle()
941 multi->num_easy--; /* one less to care about now */ in curl_multi_remove_handle()
954 return (multi && (multi->multiplexing)); in Curl_multiplex_wanted()
958 * Curl_detach_connection() removes the given transfer from the connection.
960 * This is the only function that should clear data->conn. This will
961 * occasionally be called with the data->conn pointer already cleared.
965 struct connectdata *conn = data->conn; in Curl_detach_connection()
968 Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL); in Curl_detach_connection()
970 data->conn = NULL; in Curl_detach_connection()
974 * Curl_attach_connection() attaches this transfer to this connection.
976 * This is the only function that should assign data->conn
981 DEBUGASSERT(!data->conn); in Curl_attach_connection()
983 data->conn = conn; in Curl_attach_connection()
984 Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data, in Curl_attach_connection()
985 &data->conn_queue); in Curl_attach_connection()
986 if(conn->handler && conn->handler->attach) in Curl_attach_connection()
987 conn->handler->attach(data, conn); in Curl_attach_connection()
995 if(conn && conn->handler->domore_getsock) in domore_getsock()
996 return conn->handler->domore_getsock(data, conn, socks); in domore_getsock()
1004 if(conn && conn->handler->doing_getsock) in doing_getsock()
1005 return conn->handler->doing_getsock(data, conn, socks); in doing_getsock()
1013 if(conn->handler->proto_getsock) in protocol_getsock()
1014 return conn->handler->proto_getsock(data, conn, socks); in protocol_getsock()
1023 struct connectdata *conn = data->conn; in multi_getsock()
1024 /* The no connection case can happen when this is called from in multi_getsock()
1030 switch(data->mstate) { in multi_getsock()
1068 int this_max_fd = -1; in curl_multi_fdset()
1076 if(multi->in_callback) in curl_multi_fdset()
1079 data = multi->easyp; in curl_multi_fdset()
1112 data = data->next; /* check next handle */ in curl_multi_fdset()
1143 bool extrawait, /* when no socket, wait */
1159 DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
1168 if(multi->in_callback)
1175 data = multi->easyp;
1195 data = data->next; /* check next handle */
1200 is actually larger than -1! */
1212 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1235 data = multi->easyp;
1269 if(WSAEventSelect(s, multi->wsa_event, mask) != 0) {
1277 data = data->next; /* check next handle */
1281 /* Add external file descriptions from poll-like struct curl_waitfd */
1293 if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) {
1312 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1313 ufds[nfds].fd = multi->wakeup_pair[0];
1328 pollrc = Curl_poll(ufds, nfds, 0); /* just pre-check with WinSock */
1341 else { /* now wait... if not ready during the pre-check (pollrc == 0) */
1342 WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
1367 WSAEventSelect(s, multi->wsa_event, 0);
1386 data = multi->easyp;
1397 WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
1405 data = data->next;
1409 WSAResetEvent(multi->wsa_event);
1412 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1417 /* the reading socket is non-blocking, try to read
1420 when there is no more data, breaking the loop. */
1421 nread = wakeup_read(multi->wakeup_pair[0], buf, sizeof(buf));
1429 retcode--;
1448 /* Avoid busy-looping when there's nothing particular to wait for */
1452 /* when there are no easy handles in the multi, this holds a -1
1495 if(WSASetEvent(multi->wsa_event))
1501 if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
1505 /* swrite() is not thread-safe in general, because concurrent calls
1509 The write socket is set to non-blocking, this way this function
1514 if(wakeup_write(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
1545 bool retval = multi->recheckstate;
1547 multi->recheckstate = FALSE;
1557 if(multi->in_callback)
1562 struct SingleRequest *k = &data->req;
1565 connection, only this transfer */
1571 k->keepon |= KEEP_RECV; /* setup to receive! */
1579 struct connectdata *conn = data->conn;
1582 DEBUGASSERT(conn->handler);
1584 if(conn->handler->do_it)
1585 /* generic protocol-specific function pointer set in curl_connect() */
1586 result = conn->handler->do_it(data, done);
1596 * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
1603 struct connectdata *conn = data->conn;
1607 if(conn->handler->do_more)
1608 result = conn->handler->do_more(data, complete);
1627 if(data->mstate == MSTATE_RESOLVING)
1630 Curl_timediff(*now, data->progress.t_startsingle));
1631 else if(data->mstate == MSTATE_CONNECTING)
1634 Curl_timediff(*now, data->progress.t_startsingle));
1636 struct SingleRequest *k = &data->req;
1637 if(k->size != -1) {
1641 Curl_timediff(*now, data->progress.t_startsingle),
1642 k->bytecount, k->size);
1648 Curl_timediff(*now, data->progress.t_startsingle),
1649 k->bytecount);
1654 if(data->mstate > MSTATE_DO) {
1655 streamclose(data->conn, "Disconnected with pending data");
1666 * We are doing protocol-specific connecting and this is being called over and
1674 struct connectdata *conn = data->conn;
1676 if(conn && conn->handler->connecting) {
1678 result = conn->handler->connecting(data, done);
1694 struct connectdata *conn = data->conn;
1696 if(conn && conn->handler->doing) {
1698 result = conn->handler->doing(data, done);
1715 struct connectdata *conn = data->conn;
1722 && conn->bits.protoconnstart) {
1727 Unless this protocol doesn't have any protocol-connect callback, as
1729 if(!conn->handler->connecting)
1735 if(!conn->bits.protoconnstart) {
1736 if(conn->handler->connect_it) {
1737 /* is there a protocol-specific connect() procedure? */
1739 /* Call the protocol-specific connect function */
1740 result = conn->handler->connect_it(data, protocol_done);
1748 conn->bits.protoconnstart = TRUE;
1756 * POST/PUT with multi-pass authentication when a sending was denied and a
1761 struct connectdata *conn = data->conn;
1762 curl_mimepart *mimepart = &data->set.mimepost;
1765 data->state.rewindbeforesend = FALSE; /* we rewind now */
1768 about to restart a new transfer and thus we want to avoid inadvertently
1769 sending more data on the existing connection until the next transfer
1771 data->req.keepon &= ~KEEP_SEND;
1776 if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
1777 struct HTTP *http = data->req.p.http;
1779 if(http->sendit)
1780 mimepart = http->sendit;
1782 if(data->set.postfields ||
1783 (data->state.httpreq == HTTPREQ_GET) ||
1784 (data->state.httpreq == HTTPREQ_HEAD))
1785 ; /* no need to rewind */
1786 else if(data->state.httpreq == HTTPREQ_POST_MIME ||
1787 data->state.httpreq == HTTPREQ_POST_FORM) {
1795 if(data->set.seek_func) {
1799 err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
1806 else if(data->set.ioctl_func) {
1810 err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
1811 data->set.ioctl_client);
1821 /* If no CURLOPT_READFUNCTION is used, we know that we operate on a
1824 if(data->state.fread_func == (curl_read_callback)fread) {
1825 if(-1 != fseek(data->state.in, 0, SEEK_SET))
1830 /* no callback set or failure above, makes us fail at once */
1841 * transfer.
1845 if(!data->state.buffer) {
1846 data->state.buffer = malloc(data->set.buffer_size + 1);
1847 if(!data->state.buffer)
1856 multi->in_callback = value;
1878 if(multi->dead) {
1879 /* a multi-level callback returned error before, meaning every individual
1880 transfer now has failed */
1888 if(!multi->warned) {
1892 multi->warned = true;
1907 if(data->mstate > MSTATE_CONNECT &&
1908 data->mstate < MSTATE_COMPLETED) {
1910 DEBUGASSERT(data->conn);
1911 if(!data->conn)
1915 if(data->conn &&
1916 (data->mstate >= MSTATE_CONNECT) &&
1917 (data->mstate < MSTATE_COMPLETED)) {
1933 switch(data->mstate) {
1935 /* init this transfer. */
1953 /* init this transfer. */
1959 if(data->set.timeout)
1960 Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
1962 if(data->set.connecttimeout)
1963 Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
1967 /* There was no connection available. We will go to the pending
1971 /* add this handle to the list of connect-pending handles */
1972 Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
1973 &data->connect_queue);
1977 else if(data->state.previouslypending) {
1978 /* this transfer comes from the pending queue so try move another */
1979 infof(data, "Transfer was pending, now try another");
1980 process_pending_handles(data->multi);
2006 struct connectdata *conn = data->conn;
2011 if(conn->bits.httpproxy)
2012 hostname = conn->http_proxy.host.name;
2015 if(conn->bits.conn_to_host)
2016 hostname = conn->conn_to_host.name;
2018 hostname = conn->host.name;
2021 dns = Curl_fetch_addr(data, hostname, (int)conn->port);
2025 data->state.async.dns = dns;
2026 data->state.async.done = TRUE;
2053 data->conn = NULL; /* no more connection */
2075 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
2076 DEBUGASSERT(data->conn);
2079 if(data->conn->bits.proxy_connect_closed) {
2100 DEBUGASSERT(data->conn);
2116 if(data->state.rewindbeforesend)
2119 if(!result && data->conn->bits.reuse) {
2146 /* protocol-specific connect phase */
2162 if(data->set.fprereq) {
2167 prereq_rc = data->set.fprereq(data->set.prereq_userp,
2168 data->info.conn_primary_ip,
2169 data->info.conn_local_ip,
2170 data->info.conn_primary_port,
2171 data->info.conn_local_port);
2174 failf(data, "operation aborted by pre-request callback");
2175 /* failure in pre-request callback - don't do any other processing */
2184 if(data->set.connect_only == 1) {
2186 connkeep(data->conn, "CONNECT_ONLY");
2195 /* When multi_do() returns failure, data->conn might be NULL! */
2201 if(data->state.wildcardmatch) {
2202 struct WildcardData *wc = data->wildcard;
2203 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
2207 /* if there's no connection left, skip the DONE state */
2208 multistate(data, data->conn ?
2222 else if(data->conn->bits.do_more) {
2235 data->conn->bits.reuse) {
2285 if(data->conn)
2294 DEBUGASSERT(data->conn);
2299 multistate(data, data->conn->bits.do_more?
2316 DEBUGASSERT(data->conn);
2340 DEBUGASSERT(data->conn);
2341 if(data->conn->bits.multiplex)
2345 /* Only perform the transfer if there's a good socket to work with.
2347 if((data->conn->sockfd != CURL_SOCKET_BAD) ||
2348 (data->conn->writesockfd != CURL_SOCKET_BAD))
2352 if(data->state.wildcardmatch &&
2353 ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
2354 data->wildcard->state = CURLWC_DONE;
2362 case MSTATE_RATELIMITING: /* limit-rate exceeded in either direction */
2363 DEBUGASSERT(data->conn);
2364 /* if both rates are within spec, resume transfer */
2371 if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2373 streamclose(data->conn, "Transfer returned error");
2380 if(data->set.max_send_speed)
2382 Curl_pgrsLimitWaitTime(data->progress.uploaded,
2383 data->progress.ul_limit_size,
2384 data->set.max_send_speed,
2385 data->progress.ul_limit_start,
2389 if(data->set.max_recv_speed)
2391 Curl_pgrsLimitWaitTime(data->progress.downloaded,
2392 data->progress.dl_limit_size,
2393 data->set.max_recv_speed,
2394 data->progress.dl_limit_start,
2413 DEBUGASSERT(data->state.buffer);
2416 if(data->set.max_send_speed)
2417 send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
2418 data->progress.ul_limit_size,
2419 data->set.max_send_speed,
2420 data->progress.ul_limit_start,
2425 if(data->set.max_recv_speed)
2426 recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
2427 data->progress.dl_limit_size,
2428 data->set.max_recv_speed,
2429 data->progress.dl_limit_start,
2443 result = Curl_readwrite(data->conn, data, &done, &comeback);
2447 * condition and the server closed the re-used connection exactly when
2469 streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1");
2470 data->state.httpwant = CURL_HTTP_VERSION_1_1;
2472 data->state.errorbuf = FALSE;
2475 newurl = strdup(data->state.url);
2488 * The transfer phase returned error, we mark the connection to get
2489 * closed to prevent being re-used. This is because we can't possibly
2495 if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2497 streamclose(data->conn, "Transfer returned error");
2509 if(data->req.newurl || retry) {
2512 /* if the URL is a follow-location and not just a retried request
2515 newurl = data->req.newurl;
2516 data->req.newurl = NULL;
2531 /* after the transfer is done, go DONE */
2535 if(data->req.location) {
2537 newurl = data->req.location;
2538 data->req.location = NULL;
2554 /* This avoids CURLM_CALL_MULTI_PERFORM so that a very fast transfer
2555 won't get stuck on this transfer at the expense of other concurrent
2567 if(data->conn) {
2570 if(data->conn->bits.multiplex)
2574 /* post-transfer command */
2583 if(data->state.wildcardmatch) {
2584 if(data->wildcard->state != CURLWC_DONE) {
2585 /* if a wildcard is set and we are not ending -> lets start again
2601 data->result = result;
2608 if(data->conn &&
2609 data->mstate >= MSTATE_CONNECT &&
2610 data->mstate < MSTATE_DO &&
2624 if(data->mstate < MSTATE_COMPLETED) {
2628 * then we go to completed and consider this transfer aborted.
2631 /* NOTE: no attempt to disconnect connections must be made
2632 in the case blocks above - cleanup happens only here */
2637 if(data->conn) {
2641 struct connectdata *conn = data->conn;
2655 else if(data->mstate == MSTATE_CONNECT) {
2663 /* if there's still a connection to use, call the progress function */
2664 else if(data->conn && Curl_pgrsUpdate(data)) {
2665 /* aborted due to progress callback return code must close the
2668 streamclose(data->conn, "Aborted by callback");
2671 multistate(data, (data->mstate < MSTATE_DONE)?
2677 if(MSTATE_COMPLETED == data->mstate) {
2678 if(data->set.fmultidone) {
2680 data->set.fmultidone(data, result);
2684 msg = &data->msg;
2686 msg->extmsg.msg = CURLMSG_DONE;
2687 msg->extmsg.easy_handle = data;
2688 msg->extmsg.data.result = result;
2691 DEBUGASSERT(!data->conn);
2697 data->result = result;
2712 if(multi->in_callback)
2715 data = multi->easyp;
2718 bool nosig = data->set.no_signal;
2724 if(data->set.no_signal != nosig) {
2727 nosig = data->set.no_signal;
2732 data = data->next; /* operate on next handle */
2748 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2751 (void)add_next_timeout(now, multi, t->payload);
2755 *running_handles = multi->num_alive;
2769 if(multi->in_callback)
2772 multi->magic = 0; /* not good anymore */
2775 data = multi->easyp;
2777 nextdata = data->next;
2778 if(!data->state.done && data->conn)
2781 if(data->dns.hostcachetype == HCACHE_MULTI) {
2783 Curl_hostcache_clean(data, data->dns.hostcache);
2784 data->dns.hostcache = NULL;
2785 data->dns.hostcachetype = HCACHE_NONE;
2789 data->state.conn_cache = NULL;
2790 data->multi = NULL; /* clear the association */
2793 if(data->psl == &multi->psl)
2794 data->psl = NULL;
2801 Curl_conncache_close_all_connections(&multi->conn_cache);
2803 sockhash_destroy(&multi->sockhash);
2804 Curl_conncache_destroy(&multi->conn_cache);
2805 Curl_hash_destroy(&multi->hostcache);
2806 Curl_psl_destroy(&multi->psl);
2809 WSACloseEvent(multi->wsa_event);
2812 wakeup_close(multi->wakeup_pair[0]);
2813 wakeup_close(multi->wakeup_pair[1]);
2818 Curl_free_multi_ssl_backend_data(multi->ssl_backend_data);
2832 * figure out if a transfer has ended. We MUST make this function as fast as
2845 !multi->in_callback &&
2846 Curl_llist_count(&multi->msglist)) {
2851 e = multi->msglist.head;
2853 msg = e->ptr;
2856 Curl_llist_remove(&multi->msglist, e, NULL);
2858 *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist));
2860 return &msg->extmsg;
2890 sockets we should have from now on. Detect the differences, remove no
2905 entry = sh_getentry(&multi->sockhash, s);
2914 /* check if new for this transfer */
2916 for(j = 0; j< data->numsocks; j++) {
2917 if(s == data->sockets[j]) {
2918 prevaction = data->actions[j];
2926 entry = sh_addentry(&multi->sockhash, s);
2934 entry->readers--;
2936 entry->writers--;
2938 entry->readers++;
2940 entry->writers++;
2944 entry->users++;
2946 entry->readers++;
2948 entry->writers++;
2950 /* add 'data' to the transfer hash on this socket! */
2951 if(!Curl_hash_add(&entry->transfers, (char *)&data, /* hash key */
2953 Curl_hash_destroy(&entry->transfers);
2958 comboaction = (entry->writers? CURL_POLL_OUT : 0) |
2959 (entry->readers ? CURL_POLL_IN : 0);
2962 if(sincebefore && ((int)entry->action == comboaction))
2966 if(multi->socket_cb) {
2968 rc = multi->socket_cb(data, s, comboaction, multi->socket_userp,
2969 entry->socketp);
2971 if(rc == -1) {
2972 multi->dead = TRUE;
2977 entry->action = comboaction; /* store the current action state */
2984 for(i = 0; i< data->numsocks; i++) {
2987 s = data->sockets[i];
2998 entry = sh_getentry(&multi->sockhash, s);
3002 unsigned char oldactions = data->actions[i];
3004 entry->users--;
3006 entry->writers--;
3008 entry->readers--;
3009 if(!entry->users) {
3010 if(multi->socket_cb) {
3012 rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
3013 multi->socket_userp, entry->socketp);
3015 if(rc == -1) {
3016 multi->dead = TRUE;
3020 sh_delentry(entry, &multi->sockhash, s);
3024 if(Curl_hash_delete(&entry->transfers, (char *)&data,
3032 memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
3033 memcpy(data->actions, actions, num*sizeof(char));
3034 data->numsocks = num;
3040 if(singlesocket(data->multi, data))
3060 struct Curl_multi *multi = data->multi;
3064 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3068 if(multi->socket_cb) {
3070 rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
3071 multi->socket_userp, entry->socketp);
3076 sh_delentry(entry, &multi->sockhash, s);
3077 if(rc == -1)
3081 multi->dead = TRUE;
3103 struct curltime *tv = &d->state.expiretime;
3104 struct Curl_llist *list = &d->state.timeoutlist;
3111 for(e = list->head; e;) {
3112 struct Curl_llist_element *n = e->next;
3114 node = (struct time_node *)e->ptr;
3115 diff = Curl_timediff(node->time, now);
3124 e = list->head;
3128 tv->tv_sec = 0;
3129 tv->tv_usec = 0;
3133 memcpy(tv, &node->time, sizeof(*tv));
3137 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
3138 &d->state.timenode);
3161 data = multi->easyp;
3164 data = data->next;
3168 /* or should we fall-through and do the timer-based stuff? */
3172 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3176 real-world tests it has been proved that libevent can in fact give
3186 Curl_hash_start_iterate(&entry->transfers, &iter);
3189 data = (struct Curl_easy *)he->ptr;
3191 DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
3193 if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
3195 data->conn->cselect_bits = ev_bitmask;
3200 /* Now we fall-through and do the timer-based stuff, since we don't want
3205 multi_runsingle() in case there's no need to */
3211 /* Asked to run due to time-out. Clear the 'lastcall' variable to force
3216 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
3220 * The loop following here will go on as long as there are expire-times left
3221 * to process in the splay and 'data' will be re-assigned for every expired
3245 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
3247 data = t->payload; /* assign this for next loop */
3248 (void)add_next_timeout(now, multi, t->payload);
3253 *running_handles = multi->num_alive;
3267 if(multi->in_callback)
3274 multi->socket_cb = va_arg(param, curl_socket_callback);
3277 multi->socket_userp = va_arg(param, void *);
3280 multi->push_cb = va_arg(param, curl_push_callback);
3283 multi->push_userp = va_arg(param, void *);
3286 multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX ? 1 : 0;
3289 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
3292 multi->timer_userp = va_arg(param, void *);
3295 multi->maxconnects = va_arg(param, long);
3298 multi->max_host_connections = va_arg(param, long);
3301 multi->max_total_connections = va_arg(param, long);
3319 multi->max_concurrent_streams = curlx_sltoui(streams);
3337 if(multi->in_callback)
3349 if(multi->in_callback)
3360 if(multi->in_callback)
3373 if(multi->dead) {
3378 if(multi->timetree) {
3383 multi->timetree = Curl_splay(tv_zero, multi->timetree);
3385 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
3387 timediff_t diff = Curl_timediff(multi->timetree->key, now);
3407 *timeout_ms = -1;
3419 if(multi->in_callback)
3434 if(!multi->timer_cb || multi->dead)
3441 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
3442 multi->timer_lastcall = none;
3443 /* there's no timeout now but there was one previously, tell the app to
3446 rc = multi->timer_cb(multi, -1, multi->timer_userp);
3448 if(rc == -1) {
3449 multi->dead = TRUE;
3457 /* When multi_timeout() is done, multi->timetree points to the node with the
3458 * timeout we got the (relative) time-out time for. We can thus easily check
3461 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
3464 multi->timer_lastcall = multi->timetree->key;
3467 rc = multi->timer_cb(multi, timeout_ms, multi->timer_userp);
3469 if(rc == -1) {
3470 multi->dead = TRUE;
3485 struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3487 for(e = timeoutlist->head; e; e = e->next) {
3488 struct time_node *n = (struct time_node *)e->ptr;
3489 if(n->eid == eid) {
3512 struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3514 node = &data->state.expires[eid];
3517 memcpy(&node->time, stamp, sizeof(*stamp));
3518 node->eid = eid; /* also marks it as in use */
3523 for(e = timeoutlist->head; e; e = e->next) {
3524 struct time_node *check = (struct time_node *)e->ptr;
3525 timediff_t diff = Curl_timediff(check->time, node->time);
3535 Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
3543 * this'-time for the transfer, to be extracted by curl_multi_timeout()
3552 struct Curl_multi *multi = data->multi;
3553 struct curltime *nowp = &data->state.expiretime;
3569 set.tv_usec -= 1000000;
3579 if(nowp->tv_sec || nowp->tv_usec) {
3581 Compare if the new time is earlier, and only remove-old/add-new if it
3593 the splay tree first and then re-add the new value */
3594 rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3595 &multi->timetree);
3603 data->state.timenode.payload = data;
3604 multi->timetree = Curl_splayinsert(*nowp, multi->timetree,
3605 &data->state.timenode);
3627 struct Curl_multi *multi = data->multi;
3628 struct curltime *nowp = &data->state.expiretime;
3635 if(nowp->tv_sec || nowp->tv_usec) {
3638 struct Curl_llist *list = &data->state.timeoutlist;
3641 rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3642 &multi->timetree);
3647 while(list->size > 0) {
3648 Curl_llist_remove(list, list->tail, NULL);
3652 infof(data, "Expire cleared (transfer %p)", data);
3654 nowp->tv_sec = 0;
3655 nowp->tv_usec = 0;
3667 there = sh_getentry(&multi->sockhash, s);
3672 there->socketp = hashp;
3679 return multi ? multi->max_host_connections : 0;
3684 return multi ? multi->max_total_connections : 0;
3696 DEBUGASSERT(data->multi);
3697 conn = data->conn;
3699 DEBUGASSERT(conn->bundle);
3701 conn->bundle->multiuse = bundlestate;
3702 process_pending_handles(data->multi);
3707 struct Curl_llist_element *e = multi->pending.head;
3709 struct Curl_easy *data = e->ptr;
3711 DEBUGASSERT(data->mstate == MSTATE_PENDING);
3716 Curl_llist_remove(&multi->pending, e, NULL);
3722 data->state.previouslypending = TRUE;
3728 /* might get called when there is no data pointer! */
3730 if(data->multi_easy)
3731 data->multi_easy->in_callback = value;
3732 else if(data->multi)
3733 data->multi->in_callback = value;
3739 return ((easy->multi && easy->multi->in_callback) ||
3740 (easy->multi_easy && easy->multi_easy->in_callback));
3749 multi->num_easy, multi->num_alive);
3750 for(data = multi->easyp; data; data = data->next) {
3751 if(data->mstate < MSTATE_COMPLETED) {
3755 statename[data->mstate], data->numsocks);
3756 for(i = 0; i < data->numsocks; i++) {
3757 curl_socket_t s = data->sockets[i];
3758 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3766 (entry->action&CURL_POLL_IN)?"RECVING":"",
3767 (entry->action&CURL_POLL_OUT)?"SENDING":"");
3769 if(data->numsocks)
3779 return multi->max_concurrent_streams;