mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
curl_multi_socket() and curl_multi_socket_all() got modified prototypes: they
both now provide the number of running handles back to the calling function.
This commit is contained in:
parent
c033c4c71c
commit
01b2cf82ec
11
CHANGES
11
CHANGES
@ -6,6 +6,17 @@
|
||||
|
||||
Changelog
|
||||
|
||||
Daniel (31 July 2006)
|
||||
- *ARLERT* curl_multi_socket() and curl_multi_socket_all() got modified
|
||||
prototypes: they both now provide the number of running handles back to the
|
||||
calling function. It makes the functions resemble the good old
|
||||
curl_multi_perform() more and provides a nice way to know when the multi
|
||||
handle goes empty.
|
||||
|
||||
ALERT2: don't use the curl_multi_socket*() functionality in anything
|
||||
production-like until I say it's somewhat settled, as I suspect there might
|
||||
be some further API changes before I'm done...
|
||||
|
||||
Daniel (28 July 2006)
|
||||
- Yves Lejeune fixed so that replacing Content-Type: when doing multipart
|
||||
formposts work exactly the way you want it (and the way you'd assume it
|
||||
|
@ -289,3 +289,12 @@ July 9, 2006
|
||||
|
||||
The set hashp pointer will then be passed on to the callback in upcoming
|
||||
calls when this same socket is used (in the brand new 'socketp' argument).
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
July 30, 2006
|
||||
|
||||
Shockingly stupid (of me not having realized this before), but we really need
|
||||
to add a 'running_handles' argument to the curl_multi_socket() and
|
||||
curl_multi_socket_all() prototypes so that the caller can get to know when
|
||||
all the transfers are actually done!
|
||||
|
129
hiper/hipev.c
129
hiper/hipev.c
@ -71,9 +71,6 @@ struct connection {
|
||||
size_t dlcounter;
|
||||
struct globalinfo *global;
|
||||
char error[CURL_ERROR_SIZE];
|
||||
struct event ev[3]; /* maximum 3 events per handle NOTE: should this rather
|
||||
be a define in a public curl header file or possibly
|
||||
just documented somewhere or... ? */
|
||||
};
|
||||
|
||||
struct fdinfo {
|
||||
@ -84,10 +81,27 @@ struct fdinfo {
|
||||
CURL *easy;
|
||||
int action; /* as set by libcurl */
|
||||
long timeout; /* as set by libcurl */
|
||||
struct event ev; /* */
|
||||
int evset; /* true if the 'ev' struct has been used in a event_set() call */
|
||||
CURLMcode *multi; /* pointer to the multi handle */
|
||||
int *running_handles; /* pointer to the running_handles counter */
|
||||
};
|
||||
|
||||
static struct fdinfo *allsocks;
|
||||
|
||||
static int running_handles;
|
||||
|
||||
/* called from libevent on action on a particular socket ("event") */
|
||||
static void eventcallback(int fd, short type, void *userp)
|
||||
{
|
||||
struct fdinfo *fdp = (struct fdinfo *)userp;
|
||||
|
||||
fprintf(stderr, "EVENT callback\n");
|
||||
|
||||
/* tell libcurl to deal with the transfer associated with this socket */
|
||||
curl_multi_socket(fdp->multi, fd, fdp->running_handles);
|
||||
}
|
||||
|
||||
static void remsock(struct fdinfo *f)
|
||||
{
|
||||
if(!f)
|
||||
@ -109,12 +123,29 @@ static void setsock(struct fdinfo *fdp, curl_socket_t s, CURL *easy,
|
||||
fdp->sockfd = s;
|
||||
fdp->action = action;
|
||||
fdp->easy = easy;
|
||||
|
||||
if(fdp->evset)
|
||||
/* first remove the existing event if the old setup was used */
|
||||
event_del(&fdp->ev);
|
||||
|
||||
/* now use and add the current socket setup */
|
||||
event_set(&fdp->ev, fdp->sockfd,
|
||||
(action&CURL_POLL_IN?EV_READ:0)|
|
||||
(action&CURL_POLL_OUT?EV_WRITE:0),
|
||||
eventcallback, fdp);
|
||||
|
||||
fdp->evset=1;
|
||||
|
||||
fprintf(stderr, "event_add() for fd %d\n", s);
|
||||
event_add(&fdp->ev, NULL); /* no timeout */
|
||||
}
|
||||
|
||||
static void addsock(curl_socket_t s, CURL *easy, int action, CURLM *multi)
|
||||
{
|
||||
struct fdinfo *fdp = calloc(sizeof(struct fdinfo), 1);
|
||||
|
||||
fdp->multi = multi;
|
||||
fdp->running_handles = &running_handles;
|
||||
setsock(fdp, s, easy, action);
|
||||
|
||||
if(allsocks) {
|
||||
@ -189,7 +220,7 @@ static int socket_callback(CURL *easy, /* easy handle */
|
||||
{
|
||||
struct fdinfo *fdp = (struct fdinfo *)socketp;
|
||||
|
||||
printf("socket %d easy %p what %d\n", s, easy, what);
|
||||
fprintf(stderr, "socket %d easy %p what %d\n", s, easy, what);
|
||||
|
||||
if(what == CURL_POLL_REMOVE)
|
||||
remsock(fdp);
|
||||
@ -219,7 +250,7 @@ writecallback(void *ptr, size_t size, size_t nmemb, void *data)
|
||||
c->dlcounter += realsize;
|
||||
c->global->dlcounter += realsize;
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
printf("%02d: %d, total %d\n",
|
||||
c->id, c->dlcounter, c->global->dlcounter);
|
||||
#endif
|
||||
@ -360,6 +391,7 @@ int main(int argc, char **argv)
|
||||
int selectmaxamount;
|
||||
struct fdinfo *fdp;
|
||||
char act;
|
||||
long timeout_ms;
|
||||
|
||||
memset(&info, 0, sizeof(struct globalinfo));
|
||||
|
||||
@ -431,81 +463,40 @@ int main(int argc, char **argv)
|
||||
curl_multi_setopt(multi_handle, CURLMOPT_SOCKETDATA, multi_handle);
|
||||
|
||||
/* we start the action by calling *socket() right away */
|
||||
while(CURLM_CALL_MULTI_PERFORM == curl_multi_socket_all(multi_handle));
|
||||
while(CURLM_CALL_MULTI_PERFORM == curl_multi_socket_all(multi_handle,
|
||||
&running_handles));
|
||||
|
||||
printf("Starting timer, expects to run for %ldus\n", RUN_FOR_THIS_LONG);
|
||||
timer_start();
|
||||
timer_pause();
|
||||
/* event_dispatch() isn't good enough for us, since we need a global timeout
|
||||
to occur after a given time of inactivity
|
||||
*/
|
||||
|
||||
while(1) {
|
||||
/* get the timeout value from libcurl */
|
||||
curl_multi_timeout(multi_handle, &timeout_ms);
|
||||
|
||||
while(running_handles) {
|
||||
struct timeval timeout;
|
||||
int rc; /* select() return code */
|
||||
long timeout_ms;
|
||||
|
||||
fd2_set fdread;
|
||||
fd2_set fdwrite;
|
||||
int maxfd;
|
||||
|
||||
curl_multi_timeout(multi_handle, &timeout_ms);
|
||||
|
||||
/* set timeout to wait */
|
||||
/* convert ms to timeval */
|
||||
timeout.tv_sec = timeout_ms/1000;
|
||||
timeout.tv_usec = (timeout_ms%1000)*1000;
|
||||
|
||||
/* convert file descriptors from the transfers to fd_sets */
|
||||
fdinfo2fdset(&fdread, &fdwrite, &maxfd);
|
||||
event_loopexit(&timeout);
|
||||
|
||||
selects++;
|
||||
rc = select(maxfd+1,
|
||||
(fd_set *)&fdread,
|
||||
(fd_set *)&fdwrite,
|
||||
NULL, &timeout);
|
||||
switch(rc) {
|
||||
case -1:
|
||||
/* select error */
|
||||
break;
|
||||
case 0:
|
||||
timeouts++;
|
||||
curl_multi_socket(multi_handle, CURL_SOCKET_TIMEOUT);
|
||||
break;
|
||||
/* The event_loopexit() function may have taken a while and it may or may
|
||||
not have invoked libcurl calls during that time. During those calls,
|
||||
the timeout situation might very well have changed, so we check the
|
||||
timeout time again to see if we really need to call curl_multi_socket()
|
||||
at this point! */
|
||||
|
||||
default:
|
||||
/* timeout or readable/writable sockets */
|
||||
/* get the timeout value from libcurl */
|
||||
curl_multi_timeout(multi_handle, &timeout_ms);
|
||||
|
||||
for(i=0, fdp = allsocks; fdp; fdp = fdp->next) {
|
||||
act = 0;
|
||||
if((fdp->action & CURL_POLL_IN) &&
|
||||
FD_ISSET(fdp->sockfd, &fdread)) {
|
||||
act |= CURL_POLL_IN;
|
||||
i++;
|
||||
}
|
||||
if((fdp->action & CURL_POLL_OUT) &&
|
||||
FD_ISSET(fdp->sockfd, &fdwrite)) {
|
||||
act |= CURL_POLL_OUT;
|
||||
i++;
|
||||
}
|
||||
if(timeout_ms <= 0) {
|
||||
/* no time left */
|
||||
curl_multi_socket(multi_handle, CURL_SOCKET_TIMEOUT, &running_handles);
|
||||
|
||||
if(act) {
|
||||
multi_socket++;
|
||||
timer_continue();
|
||||
if(act & CURL_POLL_OUT)
|
||||
act--;
|
||||
curl_multi_socket(multi_handle, fdp->sockfd);
|
||||
timer_pause();
|
||||
}
|
||||
}
|
||||
|
||||
performselect += rc;
|
||||
if(rc > topselect)
|
||||
topselect = rc;
|
||||
break;
|
||||
}
|
||||
|
||||
timer_total(); /* calculate the total time spent so far */
|
||||
|
||||
if(total > RUN_FOR_THIS_LONG) {
|
||||
printf("Stopped after %ldus\n", total);
|
||||
break;
|
||||
/* and get the new timeout value again */
|
||||
curl_multi_timeout(multi_handle, &timeout_ms);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,9 +266,11 @@ typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
|
||||
void *socketp); /* private socket
|
||||
pointer */
|
||||
|
||||
CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s);
|
||||
CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
|
||||
int *running_handles);
|
||||
|
||||
CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle);
|
||||
CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
|
||||
int *running_handles);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_timeout()
|
||||
|
40
lib/multi.c
40
lib/multi.c
@ -1123,6 +1123,15 @@ static void singlesocket(struct Curl_multi *multi,
|
||||
action |= CURL_POLL_OUT;
|
||||
}
|
||||
|
||||
/* Update the sockhash accordingly BEFORE the callback of not a removal,
|
||||
in case the callback wants to use curl_multi_assign(), but do the
|
||||
removal AFTER the callback for the very same reason (but then to be
|
||||
able to pass the correct entry->socketp) */
|
||||
|
||||
if(action != CURL_POLL_REMOVE)
|
||||
/* make sure this socket is present in the hash for this handle */
|
||||
sh_addentry(multi->sockhash, s, easy->easy_handle);
|
||||
|
||||
/* call the callback with this new info */
|
||||
if(multi->socket_cb) {
|
||||
struct Curl_sh_entry *entry =
|
||||
@ -1132,16 +1141,13 @@ static void singlesocket(struct Curl_multi *multi,
|
||||
s,
|
||||
action,
|
||||
multi->socket_userp,
|
||||
entry->socketp);
|
||||
entry ? entry->socketp : NULL);
|
||||
}
|
||||
|
||||
/* Update the sockhash accordingly */
|
||||
if(action == CURL_POLL_REMOVE)
|
||||
/* remove from hash for this easy handle */
|
||||
sh_delentry(multi->sockhash, s);
|
||||
else
|
||||
/* make sure this socket is present in the hash for this handle */
|
||||
sh_addentry(multi->sockhash, s, easy->easy_handle);
|
||||
|
||||
}
|
||||
/* copy the current state to the storage area */
|
||||
memcpy(&easy->sockstate, ¤t, sizeof(struct socketstate));
|
||||
@ -1154,16 +1160,16 @@ static void singlesocket(struct Curl_multi *multi,
|
||||
|
||||
static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
bool checkall,
|
||||
curl_socket_t s)
|
||||
curl_socket_t s,
|
||||
int *running_handles)
|
||||
{
|
||||
CURLMcode result = CURLM_OK;
|
||||
int running_handles;
|
||||
struct SessionHandle *data = NULL;
|
||||
struct Curl_tree *t;
|
||||
|
||||
if(checkall) {
|
||||
struct Curl_one_easy *easyp;
|
||||
result = curl_multi_perform(multi, &running_handles);
|
||||
result = curl_multi_perform(multi, running_handles);
|
||||
|
||||
/* walk through each easy handle and do the socket state change magic
|
||||
and callbacks */
|
||||
@ -1190,7 +1196,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
|
||||
data = entry->easy;
|
||||
|
||||
result = multi_runsingle(multi, data->set.one_easy, &running_handles);
|
||||
result = multi_runsingle(multi, data->set.one_easy, running_handles);
|
||||
|
||||
if(result == CURLM_OK)
|
||||
/* get the socket(s) and check if the state has been changed since
|
||||
@ -1212,7 +1218,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
|
||||
/* the first loop lap 'data' can be NULL */
|
||||
if(data) {
|
||||
result = multi_runsingle(multi, data->set.one_easy, &running_handles);
|
||||
result = multi_runsingle(multi, data->set.one_easy, running_handles);
|
||||
|
||||
if(result == CURLM_OK)
|
||||
/* get the socket(s) and check if the state has been changed since
|
||||
@ -1269,20 +1275,18 @@ CURLMcode curl_multi_setopt(CURLM *multi_handle,
|
||||
}
|
||||
|
||||
|
||||
CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s)
|
||||
CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
|
||||
int *running_handles)
|
||||
{
|
||||
#if 0
|
||||
printf("multi_socket(%d)\n", (int)s);
|
||||
#endif
|
||||
|
||||
return multi_socket((struct Curl_multi *)multi_handle, FALSE, s);
|
||||
return multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
|
||||
running_handles);
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_socket_all(CURLM *multi_handle)
|
||||
CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
|
||||
|
||||
{
|
||||
return multi_socket((struct Curl_multi *)multi_handle,
|
||||
TRUE, CURL_SOCKET_BAD);
|
||||
TRUE, CURL_SOCKET_BAD, running_handles);
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_timeout(CURLM *multi_handle,
|
||||
|
Loading…
Reference in New Issue
Block a user