aboutsummaryrefslogtreecommitdiff
path: root/lib/multi.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/multi.c')
-rw-r--r--lib/multi.c58
1 files changed, 43 insertions, 15 deletions
diff --git a/lib/multi.c b/lib/multi.c
index ff9e91fea..b7ab209f5 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -22,10 +22,16 @@
*****************************************************************************/
#include "setup.h"
+#include <stdlib.h>
+#include <string.h>
#include <curl/curl.h>
#include "multi.h" /* will become <curl/multi.h> soon */
+#include "urldata.h"
+#include "transfer.h"
+#include "url.h"
+
struct Curl_message {
/* the 'CURLMsg' is the part that is visible to the external user */
struct CURLMsg extmsg;
@@ -48,7 +54,9 @@ struct Curl_one_easy {
struct Curl_one_easy *next;
struct Curl_one_easy *prev;
- CURL *easy_handle; /* this is the easy handle for this unit */
+ struct SessionHandle *easy_handle; /* the easy handle for this unit */
+ struct connectdata *easy_conn; /* the "unit's" connection */
+
CURLMstate state; /* the handle's state */
CURLcode result; /* previous result */
};
@@ -134,7 +142,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
/* increase the node-counter */
multi->num_easy++;
- return CURLM_OK;
+ return CURLM_CALL_MULTI_PERFORM;
}
CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
@@ -190,23 +198,30 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
and then we must make sure that is done. */
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
struct Curl_one_easy *easy;
+ int this_max_fd=-1;
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ *max_fd = -1; /* so far none! */
+
easy=multi->easy.next;
while(easy) {
switch(easy->state) {
- case CURLM_STATE_INIT:
- case CURLM_STATE_CONNECT:
- case CURLM_STATE_DO:
- case CURLM_STATE_DONE:
- /* we want curl_multi_perform() to get called, but we don't have any
- file descriptors to set */
+ default:
break;
case CURLM_STATE_PERFORM:
/* This should have a set of file descriptors for us to set. */
/* after the transfer is done, go DONE */
+
+ Curl_single_fdset(easy->easy_conn,
+ read_fd_set, write_fd_set,
+ exc_fd_set, &this_max_fd);
+
+ /* remember the maximum file descriptor */
+ if(this_max_fd > *max_fd)
+ *max_fd = this_max_fd;
+
break;
}
easy = easy->next; /* check next handle */
@@ -222,6 +237,8 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
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;
@@ -239,8 +256,9 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
}
break;
case CURLM_STATE_CONNECT:
- /* connect */
- easy->result = Curl_connect(easy->easy_handle);
+ /* 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;
@@ -249,15 +267,18 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
break;
case CURLM_STATE_DO:
/* Do the fetch or put request */
- easy->result = Curl_do(easy->easy_handle);
+ easy->result = Curl_do(&easy->easy_conn);
/* after do, go PERFORM */
if(CURLE_OK == easy->result) {
- easy->state = CURLM_STATE_PERFORM;
+ 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_handle, &done);
+ 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 */
@@ -265,11 +286,12 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
/* 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_handle);
+ 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;
@@ -280,7 +302,10 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
/* 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)) {
/*
@@ -289,10 +314,13 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
*/
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 CURLM_OK;
+ return result;
}
CURLMcode curl_multi_cleanup(CURLM *multi_handle)