diff --git a/include/curl/multi.h b/include/curl/multi.h index f96566669c6771..26bbeac8fdc388 100644 --- a/include/curl/multi.h +++ b/include/curl/multi.h @@ -67,6 +67,21 @@ typedef enum { CURLM_LAST } CURLMcode; +#define CURLMINFO_STRING CURLINFO_STRING +#define CURLMINFO_LONG CURLINFO_LONG +#define CURLMINFO_DOUBLE CURLINFO_DOUBLE +#define CURLMINFO_SLIST CURLINFO_SLIST +#define CURLMINFO_MASK CURLINFO_MASK +#define CURLMINFO_TYPEMASK CURLINFO_TYPEMASK + +typedef enum { + CURLMINFO_NONE, + CURLMINFO_NUM_READ_FDS = CURLMINFO_LONG + 1, + CURLMINFO_NUM_WRITE_FDS = CURLMINFO_LONG + 2, + CURLMINFO_NUM_EX_FDS = CURLMINFO_LONG + 3, + CURLMINFO_NUM_FDS = CURLMINFO_LONG + 4 +} CURLMINFO; + /* just to make code nicer when using curl_multi_socket() you can now check for CURLM_CALL_MULTI_SOCKET too in the same style it works for curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ @@ -133,6 +148,18 @@ CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, fd_set *exc_fd_set, int *max_fd); +/* + * Name: curl_multi_fdvec() + * + * Desc: Retreive a vector of fds contained in the multi handle + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_fdvec(CURLM *multi_handle, + int *read_fds, + int *write_fds, + int *ex_fds); + /* * Name: curl_multi_perform() * @@ -325,6 +352,15 @@ typedef enum { CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, CURLMoption option, ...); +/* + * Name: curl_multi_getinfo() + * + * Desc: Retreives info from a multi handle. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_getinfo(CURLM *multi_handle, + CURLMINFO info, ...); /* * Name: curl_multi_assign() diff --git a/lib/multi.c b/lib/multi.c index ff43378f561dfa..7bb71a8ccbf57f 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -941,6 +941,38 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle, return CURLM_OK; } +CURLMcode curl_multi_fdvec(CURLM *multi_handle, + int *read_fds, + int *write_fds, + int *ex_fds) +{ + struct Curl_multi *multi=(struct Curl_multi *)multi_handle; + struct Curl_one_easy *easy; + int rfds = 0, wfds = 0, xfds = 0; + (void)ex_fds; /* not used */ + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + for(easy = multi->easy.next; + easy != &multi->easy; + easy = easy->next) { + curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; + int i, bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE); + + for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) { + if (read_fds && (bitmap & GETSOCK_READSOCK(i))) { + read_fds[rfds++] = sockbunch[i]; + } + if (write_fds && (bitmap & GETSOCK_WRITESOCK(i))) { + write_fds[wfds++] = sockbunch[i]; + } + } + } + + return CURLM_OK; +} + static CURLMcode multi_runsingle(struct Curl_multi *multi, struct timeval now, struct Curl_one_easy *easy) @@ -2269,6 +2301,71 @@ CURLMcode curl_multi_setopt(CURLM *multi_handle, return res; } +static unsigned long curl_multi_count_fds(struct Curl_multi *multi, + char readH, char writeH, char exH) +{ + struct Curl_one_easy *easy; + int nfds = 0; + (void)exH; /* not used */ + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + for(easy = multi->easy.next; + easy != &multi->easy; + easy = easy->next) { + curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; + int i, bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE); + + for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) { + if ((readH && (bitmap & GETSOCK_READSOCK(i))) || + (writeH && (bitmap & GETSOCK_WRITESOCK(i)))) { + nfds++; + } + } + } + + return nfds; +} + +#undef curl_multi_getinfo +CURLMcode curl_multi_getinfo(CURLM *multi_handle, + CURLMINFO info, ...) +{ + struct Curl_multi *multi=(struct Curl_multi *)multi_handle; + CURLMcode res = CURLM_OK; + va_list param; + void *voidp; + long *longp; + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + va_start(param, info); + voidp = va_arg(param, void *); + longp = (long*)voidp; + + switch(info) { + case CURLMINFO_NUM_READ_FDS: + *longp = curl_multi_count_fds(multi, 1, 0, 0); + break; + case CURLMINFO_NUM_WRITE_FDS: + *longp = curl_multi_count_fds(multi, 0, 1, 0); + break; + case CURLMINFO_NUM_EX_FDS: + *longp = curl_multi_count_fds(multi, 0, 0, 1); + break; + case CURLMINFO_NUM_FDS: + *longp = curl_multi_count_fds(multi, 1, 1, 1); + break; + default: + res = CURLM_UNKNOWN_OPTION; + } + + va_end(param); + return res; +} + /* we define curl_multi_socket() in the public multi.h header */ #undef curl_multi_socket