diff options
Diffstat (limited to 'lib/multi.c')
| -rw-r--r-- | lib/multi.c | 58 | 
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) | 
