/* * curl_easy_perform() is the external interface that performs a transfer * previously setup. */ CURLcode curl_easy_perform(CURL *curl) { struct SessionHandle *data = (struct SessionHandle *)curl; if(!data) return CURLE_BAD_FUNCTION_ARGUMENT; if ( ! (data->share && data->share->hostcache) ) { if (Curl_global_host_cache_use(data) && data->hostcache != Curl_global_host_cache_get()) { if (data->hostcache) Curl_hash_destroy(data->hostcache); data->hostcache = Curl_global_host_cache_get(); } if (!data->hostcache) { data->hostcache = Curl_mk_dnscache(); if(!data->hostcache) /* While we possibly could survive and do good without a host cache, the fact that creating it failed indicates that things are truly screwed up and we should bail out! */ return CURLE_OUT_OF_MEMORY; } } return Curl_perform(data); }
/* * curl_easy_perform() is the external interface that performs a transfer * previously setup. */ CURLcode curl_easy_perform(CURL *curl) { struct SessionHandle *data = (struct SessionHandle *)curl; if(!data) return CURLE_BAD_FUNCTION_ARGUMENT; if ( ! (data->share && data->share->hostcache) ) { if (Curl_global_host_cache_use(data) && (data->dns.hostcachetype != HCACHE_GLOBAL)) { if (data->dns.hostcachetype == HCACHE_PRIVATE) Curl_hash_destroy(data->dns.hostcache); data->dns.hostcache = Curl_global_host_cache_get(); data->dns.hostcachetype = HCACHE_GLOBAL; } if (!data->dns.hostcache) { data->dns.hostcachetype = HCACHE_PRIVATE; data->dns.hostcache = Curl_mk_dnscache(); if(!data->dns.hostcache) /* While we possibly could survive and do good without a host cache, the fact that creating it failed indicates that things are truly screwed up and we should bail out! */ return CURLE_OUT_OF_MEMORY; } } if(!data->state.connc) { /* oops, no connection cache, make one up */ data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE); if(!data->state.connc) return CURLE_OUT_OF_MEMORY; } return Curl_perform(data); }
CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) { struct Curl_multi *multi=(struct Curl_multi *)multi_handle; struct Curl_one_easy *easy; bool done; CURLMcode result=CURLM_OK; *running_handles = 0; /* bump this once for every living handle */ if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; easy=multi->easy.next; while(easy) { switch(easy->state) { case CURLM_STATE_INIT: /* init this transfer. */ easy->result=Curl_pretransfer(easy->easy_handle); if(CURLE_OK == easy->result) { /* after init, go CONNECT */ easy->state = CURLM_STATE_CONNECT; result = CURLM_CALL_MULTI_PERFORM; } break; case CURLM_STATE_CONNECT: if (Curl_global_host_cache_use(easy->easy_handle)) { easy->easy_handle->hostcache = Curl_global_host_cache_get(); } else { if (multi->hostcache == NULL) { multi->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo); } easy->easy_handle->hostcache = multi->hostcache; } /* Connect. We get a connection identifier filled in. */ easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn); /* after connect, go DO */ if(CURLE_OK == easy->result) { easy->state = CURLM_STATE_DO; result = CURLM_CALL_MULTI_PERFORM; } break; case CURLM_STATE_DO: /* Do the fetch or put request */ easy->result = Curl_do(&easy->easy_conn); /* after do, go PERFORM */ if(CURLE_OK == easy->result) { if(CURLE_OK == Curl_readwrite_init(easy->easy_conn)) { easy->state = CURLM_STATE_PERFORM; result = CURLM_CALL_MULTI_PERFORM; } } break; case CURLM_STATE_PERFORM: /* read/write data if it is ready to do so */ easy->result = Curl_readwrite(easy->easy_conn, &done); /* hm, when we follow redirects, we may need to go back to the CONNECT state */ /* after the transfer is done, go DONE */ if(TRUE == done) { /* call this even if the readwrite function returned error */ easy->result = Curl_posttransfer(easy->easy_handle); easy->state = CURLM_STATE_DONE; result = CURLM_CALL_MULTI_PERFORM; } break; case CURLM_STATE_DONE: /* post-transfer command */ easy->result = Curl_done(easy->easy_conn); /* after we have DONE what we're supposed to do, go COMPLETED */ if(CURLE_OK == easy->result) easy->state = CURLM_STATE_COMPLETED; break; case CURLM_STATE_COMPLETED: /* this is a completed transfer, it is likely to still be connected */ /* This node should be delinked from the list now and we should post an information message that we are complete. */ break; default: return CURLM_INTERNAL_ERROR; } if((CURLM_STATE_COMPLETED != easy->state) && (CURLE_OK != easy->result)) { /* * If an error was returned, and we aren't in completed now, * then we go to completed and consider this transfer aborted. */ easy->state = CURLM_STATE_COMPLETED; } else if(CURLM_STATE_COMPLETED != easy->state) /* this one still lives! */ (*running_handles)++; easy = easy->next; /* operate on next handle */ } return result; }