aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/multi.c143
-rw-r--r--lib/multihandle.h24
-rw-r--r--lib/urldata.h20
3 files changed, 92 insertions, 95 deletions
diff --git a/lib/multi.c b/lib/multi.c
index 3318e0d4c..e5565ef10 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -114,23 +114,23 @@ static void mstate(struct Curl_one_easy *easy, CURLMstate state
#ifdef DEBUGBUILD
long connection_id = -5000;
#endif
- CURLMstate oldstate = easy->state;
+ CURLMstate oldstate = easy->mstate;
if(oldstate == state)
/* don't bother when the new state is the same as the old state */
return;
- easy->state = state;
+ easy->mstate = state;
#ifdef DEBUGBUILD
- if(easy->state >= CURLM_STATE_CONNECT_PEND &&
- easy->state < CURLM_STATE_COMPLETED) {
+ if(easy->mstate >= CURLM_STATE_CONNECT_PEND &&
+ easy->mstate < CURLM_STATE_COMPLETED) {
if(easy->easy_conn)
connection_id = easy->easy_conn->connection_id;
infof(easy->easy_handle,
"STATE: %s => %s handle %p; line %d (connection #%ld) \n",
- statename[oldstate], statename[easy->state],
+ statename[oldstate], statename[easy->mstate],
(void *)easy, lineno, connection_id);
}
#endif
@@ -307,12 +307,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
if(!multi->msglist)
goto error;
- /* Let's make the doubly-linked list a circular list. This makes
- the linked list code simpler and allows inserting at the end
- with less work (we didn't keep a tail pointer before). */
- multi->easy.next = &multi->easy;
- multi->easy.prev = &multi->easy;
-
multi->max_pipeline_length = 5;
return (CURLM *) multi;
@@ -365,13 +359,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
if(!timeoutlist)
return CURLM_OUT_OF_MEMORY;
- /* Allocate new node for the doubly-linked circular list of
- Curl_one_easy structs that holds pointers to easy handles */
- easy = calloc(1, sizeof(struct Curl_one_easy));
- if(!easy) {
- Curl_llist_destroy(timeoutlist, NULL);
- return CURLM_OUT_OF_MEMORY;
- }
+ easy = data;
/* In case multi handle has no hostcache yet, allocate one */
if(!multi->hostcache) {
@@ -441,17 +429,21 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
list of Curl_one_easy structs to try and maintain a FIFO queue so
the pipelined requests are in order. */
- /* We add this new entry last in the list. We make our 'next' point to the
- 'first' struct and our 'prev' point to the previous 'prev' */
- easy->next = &multi->easy;
- easy->prev = multi->easy.prev;
+ /* We add this new entry last in the list. */
- /* make 'easy' the last node in the chain */
- multi->easy.prev = easy;
-
- /* if there was a prev node, make sure its 'next' pointer links to
- the new node */
- easy->prev->next = easy;
+ easy->next = NULL; /* end of the line */
+ if(multi->easyp) {
+ struct Curl_one_easy *last = multi->easylp;
+ last->next = easy;
+ easy->prev = last;
+ multi->easylp = easy; /* the new last node */
+ }
+ else {
+ /* first node, make both prev and next be NULL! */
+ easy->next = NULL;
+ easy->prev = NULL;
+ multi->easylp = multi->easyp = easy; /* both first and last */
+ }
/* make the SessionHandle refer back to this multi handle */
Curl_easy_addmulti(easy_handle, multi_handle);
@@ -524,7 +516,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
easy = data->multi_pos;
if(easy) {
- bool premature = (easy->state < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
+ bool premature = (easy->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
bool easy_owns_conn = (easy->easy_conn &&
(easy->easy_conn->data == easy->easy_handle)) ?
TRUE : FALSE;
@@ -539,8 +531,8 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
if(easy->easy_conn &&
(easy->easy_conn->send_pipe->size +
easy->easy_conn->recv_pipe->size > 1) &&
- easy->state > CURLM_STATE_WAITDO &&
- easy->state < CURLM_STATE_COMPLETED) {
+ easy->mstate > CURLM_STATE_WAITDO &&
+ easy->mstate < CURLM_STATE_COMPLETED) {
/* If the handle is in a pipeline and has started sending off its
request but not received its response yet, we need to close
connection. */
@@ -591,7 +583,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
/* change state without using multistate(), only to make singlesocket() do
what we want */
- easy->state = CURLM_STATE_COMPLETED;
+ easy->mstate = CURLM_STATE_COMPLETED;
singlesocket(multi, easy); /* to let the application know what sockets
that vanish with this handle */
@@ -623,9 +615,14 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
/* make the previous node point to our next */
if(easy->prev)
easy->prev->next = easy->next;
+ else
+ multi->easyp = easy->next; /* point to first node */
+
/* make our next point to our previous node */
if(easy->next)
easy->next->prev = easy->prev;
+ else
+ multi->easylp = easy->prev; /* point to last node */
easy->easy_handle->set.one_easy = NULL; /* detached */
@@ -634,7 +631,6 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
/* NOTE NOTE NOTE
We do not touch the easy handle here! */
- free(easy);
multi->num_easy--; /* one less to care about now */
@@ -698,13 +694,13 @@ static int multi_getsock(struct Curl_one_easy *easy,
if(easy->easy_handle->state.pipe_broke || !easy->easy_conn)
return 0;
- if(easy->state > CURLM_STATE_CONNECT &&
- easy->state < CURLM_STATE_COMPLETED) {
+ if(easy->mstate > CURLM_STATE_CONNECT &&
+ easy->mstate < CURLM_STATE_COMPLETED) {
/* Set up ownership correctly */
easy->easy_conn->data = easy->easy_handle;
}
- switch(easy->state) {
+ switch(easy->mstate) {
default:
#if 0 /* switch back on these cases to get the compiler to check for all enums
to be present */
@@ -766,8 +762,8 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
- easy=multi->easy.next;
- while(easy != &multi->easy) {
+ easy=multi->easyp;
+ while(easy) {
bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
@@ -825,8 +821,8 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
timeout_ms = (int)timeout_internal;
/* Count up how many fds we have from the multi handle */
- easy=multi->easy.next;
- while(easy != &multi->easy) {
+ easy=multi->easyp;
+ while(easy) {
bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
@@ -863,8 +859,8 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
if(curlfds) {
/* Add the curl handles to our pollfds first */
- easy=multi->easy.next;
- while(easy != &multi->easy) {
+ easy=multi->easyp;
+ while(easy) {
bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
@@ -968,7 +964,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
infof(data, "Pipe broke: handle 0x%p, url = %s\n",
(void *)easy, data->state.path);
- if(easy->state < CURLM_STATE_COMPLETED) {
+ if(easy->mstate < CURLM_STATE_COMPLETED) {
/* Head back to the CONNECT state */
multistate(easy, CURLM_STATE_CONNECT);
result = CURLM_CALL_MULTI_PERFORM;
@@ -981,36 +977,36 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
if(!easy->easy_conn &&
- easy->state > CURLM_STATE_CONNECT &&
- easy->state < CURLM_STATE_DONE) {
+ easy->mstate > CURLM_STATE_CONNECT &&
+ easy->mstate < CURLM_STATE_DONE) {
/* In all these states, the code will blindly access 'easy->easy_conn'
so this is precaution that it isn't NULL. And it silences static
analyzers. */
- failf(data, "In state %d with no easy_conn, bail out!\n", easy->state);
+ failf(data, "In state %d with no easy_conn, bail out!\n", easy->mstate);
return CURLM_INTERNAL_ERROR;
}
- if(easy->easy_conn && easy->state > CURLM_STATE_CONNECT &&
- easy->state < CURLM_STATE_COMPLETED)
+ if(easy->easy_conn && easy->mstate > CURLM_STATE_CONNECT &&
+ easy->mstate < CURLM_STATE_COMPLETED)
/* Make sure we set the connection's current owner */
easy->easy_conn->data = data;
if(easy->easy_conn &&
- (easy->state >= CURLM_STATE_CONNECT) &&
- (easy->state < CURLM_STATE_COMPLETED)) {
+ (easy->mstate >= CURLM_STATE_CONNECT) &&
+ (easy->mstate < CURLM_STATE_COMPLETED)) {
/* we need to wait for the connect state as only then is the start time
stored, but we must not check already completed handles */
timeout_ms = Curl_timeleft(data, &now,
- (easy->state <= CURLM_STATE_WAITDO)?
+ (easy->mstate <= CURLM_STATE_WAITDO)?
TRUE:FALSE);
if(timeout_ms < 0) {
/* Handle timed out */
- if(easy->state == CURLM_STATE_WAITRESOLVE)
+ if(easy->mstate == CURLM_STATE_WAITRESOLVE)
failf(data, "Resolving timed out after %ld milliseconds",
Curl_tvdiff(now, data->progress.t_startsingle));
- else if(easy->state == CURLM_STATE_WAITCONNECT)
+ else if(easy->mstate == CURLM_STATE_WAITCONNECT)
failf(data, "Connection timed out after %ld milliseconds",
Curl_tvdiff(now, data->progress.t_startsingle));
else {
@@ -1031,7 +1027,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
}
- switch(easy->state) {
+ switch(easy->mstate) {
case CURLM_STATE_INIT:
/* init this transfer. */
easy->result=Curl_pretransfer(data);
@@ -1662,7 +1658,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
return CURLM_INTERNAL_ERROR;
}
- if(easy->state < CURLM_STATE_COMPLETED) {
+ if(easy->mstate < CURLM_STATE_COMPLETED) {
if(CURLE_OK != easy->result) {
/*
* If an error was returned, and we aren't in completed state now,
@@ -1695,7 +1691,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
easy->easy_conn = NULL;
}
}
- else if(easy->state == CURLM_STATE_CONNECT) {
+ else if(easy->mstate == CURLM_STATE_CONNECT) {
/* Curl_connect() failed */
(void)Curl_posttransfer(data);
}
@@ -1709,14 +1705,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
easy->easy_conn->bits.close = TRUE;
/* if not yet in DONE state, go there, otherwise COMPLETED */
- multistate(easy, (easy->state < CURLM_STATE_DONE)?
+ multistate(easy, (easy->mstate < CURLM_STATE_DONE)?
CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
result = CURLM_CALL_MULTI_PERFORM;
}
}
} WHILE_FALSE; /* just to break out from! */
- if(CURLM_STATE_COMPLETED == easy->state) {
+ if(CURLM_STATE_COMPLETED == easy->mstate) {
/* now fill in the Curl_message with this info */
msg = &easy->msg;
@@ -1744,8 +1740,8 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
- easy=multi->easy.next;
- while(easy != &multi->easy) {
+ easy=multi->easyp;
+ while(easy) {
CURLMcode result;
struct WildcardData *wc = &easy->easy_handle->wildcard;
@@ -1845,8 +1841,8 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
multi->msglist = NULL;
/* remove all easy handles */
- easy = multi->easy.next;
- while(easy != &multi->easy) {
+ easy = multi->easyp;
+ while(easy) {
nexteasy=easy->next;
if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
/* clear out the usage of the shared DNS cache */
@@ -1860,7 +1856,6 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association */
- free(easy);
easy = nexteasy;
}
@@ -2178,16 +2173,16 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
struct timeval now = Curl_tvnow();
if(checkall) {
- struct Curl_one_easy *easyp;
+ struct Curl_one_easy *easy;
/* *perform() deals with running_handles on its own */
result = curl_multi_perform(multi, running_handles);
/* walk through each easy handle and do the socket state change magic
and callbacks */
- easyp=multi->easy.next;
- while(easyp != &multi->easy) {
- singlesocket(multi, easyp);
- easyp = easyp->next;
+ easy=multi->easyp;
+ while(easy) {
+ singlesocket(multi, easy);
+ easy = easy->next;
}
/* or should we fall-through and do the timer-based stuff? */
@@ -2714,9 +2709,9 @@ void Curl_multi_process_pending_handles(struct Curl_multi *multi)
{
struct Curl_one_easy *easy;
- easy=multi->easy.next;
- while(easy != &multi->easy) {
- if(easy->state == CURLM_STATE_CONNECT_PEND) {
+ easy=multi->easyp;
+ while(easy) {
+ if(easy->mstate == CURLM_STATE_CONNECT_PEND) {
multistate(easy, CURLM_STATE_CONNECT);
/* Make sure that the handle will be processed soonish. */
Curl_expire(easy->easy_handle, 1);
@@ -2733,12 +2728,12 @@ void Curl_multi_dump(const struct Curl_multi *multi_handle)
int i;
fprintf(stderr, "* Multi status: %d handles, %d alive\n",
multi->num_easy, multi->num_alive);
- for(easy=multi->easy.next; easy != &multi->easy; easy = easy->next) {
- if(easy->state < CURLM_STATE_COMPLETED) {
+ for(easy=multi->easyp; easy; easy = easy->next) {
+ if(easy->mstate < CURLM_STATE_COMPLETED) {
/* only display handles that are not completed */
fprintf(stderr, "handle %p, state %s, %d sockets\n",
(void *)easy->easy_handle,
- statename[easy->state], easy->numsocks);
+ statename[easy->mstate], easy->numsocks);
for(i=0; i < easy->numsocks; i++) {
curl_socket_t s = easy->sockets[i];
struct Curl_sh_entry *entry =
diff --git a/lib/multihandle.h b/lib/multihandle.h
index 3fcd9c0e6..714abf6b7 100644
--- a/lib/multihandle.h
+++ b/lib/multihandle.h
@@ -59,26 +59,7 @@ typedef enum {
#define GETSOCK_READABLE (0x00ff)
#define GETSOCK_WRITABLE (0xff00)
-struct Curl_one_easy {
- /* first, two fields for the linked list of these */
- struct Curl_one_easy *next;
- struct Curl_one_easy *prev;
-
- 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 */
-
- struct Curl_message msg; /* A single posted message. */
-
- /* Array with the plain socket numbers this handle takes care of, in no
- particular order. Note that all sockets are added to the sockhash, where
- the state etc are also kept. This array is mostly used to detect when a
- socket is to be removed from the hash. See singlesocket(). */
- curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
- int numsocks;
-};
+#define Curl_one_easy SessionHandle
/* This is the struct known as CURLM on the outside */
struct Curl_multi {
@@ -87,7 +68,8 @@ struct Curl_multi {
long type;
/* We have a doubly-linked circular list with easy handles */
- struct Curl_one_easy easy;
+ struct Curl_one_easy *easyp;
+ struct Curl_one_easy *easylp; /* last node */
int num_easy; /* amount of entries in the linked list above. */
int num_alive; /* amount of easy handles that are added but have not yet
diff --git a/lib/urldata.h b/lib/urldata.h
index e245bfb4f..520fe2ca6 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -188,6 +188,7 @@
#include "http.h"
#include "rtsp.h"
#include "wildcard.h"
+#include "multihandle.h"
#ifdef HAVE_GSSAPI
# ifdef HAVE_GSSGNU
@@ -1619,6 +1620,25 @@ struct Names {
*/
struct SessionHandle {
+ /* first, two fields for the linked list of these */
+ struct Curl_one_easy *next;
+ struct Curl_one_easy *prev;
+
+ struct SessionHandle *easy_handle; /* the easy handle for this unit */
+ struct connectdata *easy_conn; /* the "unit's" connection */
+
+ CURLMstate mstate; /* the handle's state */
+ CURLcode result; /* previous result */
+
+ struct Curl_message msg; /* A single posted message. */
+
+ /* Array with the plain socket numbers this handle takes care of, in no
+ particular order. Note that all sockets are added to the sockhash, where
+ the state etc are also kept. This array is mostly used to detect when a
+ socket is to be removed from the hash. See singlesocket(). */
+ curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
+ int numsocks;
+
struct Names dns;
struct Curl_multi *multi; /* if non-NULL, points to the multi handle
struct to which this "belongs" when used by