mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 15:48:49 -05:00
- Robert Iakobashvil added curl_multi_socket_action() to libcurl, which is a
function that deprecates the curl_multi_socket() function. Using the new function the application tell libcurl what action that was found in the socket that it passes in. This gives a significant performance boost as it allows libcurl to avoid a call to poll()/select() for every call to curl_multi_socket*().
This commit is contained in:
parent
827228bd69
commit
76627b322e
8
CHANGES
8
CHANGES
@ -6,6 +6,14 @@
|
||||
|
||||
Changelog
|
||||
|
||||
Daniel S (16 April 2007)
|
||||
- Robert Iakobashvil added curl_multi_socket_action() to libcurl, which is a
|
||||
function that deprecates the curl_multi_socket() function. Using the new
|
||||
function the application tell libcurl what action that was found in the
|
||||
socket that it passes in. This gives a significant performance boost as it
|
||||
allows libcurl to avoid a call to poll()/select() for every call to
|
||||
curl_multi_socket*().
|
||||
|
||||
Daniel S (14 April 2007)
|
||||
- Jay Austin added "DH PARAMETERS" to the stunnel.pem certificate for the test
|
||||
suite to make stunnel run better in some (most?) environments.
|
||||
|
@ -11,7 +11,8 @@ Curl and libcurl 7.16.3
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o
|
||||
o Added curl_multi_socket_action()
|
||||
o Deprecated curl_multi_socket()
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
@ -37,6 +38,6 @@ New curl mirrors:
|
||||
This release would not have looked like this without help, code, reports and
|
||||
advice from friends like these:
|
||||
|
||||
Song Ma, Dan Fandrich, Yang Tse, Jay Austin
|
||||
Song Ma, Dan Fandrich, Yang Tse, Jay Austin, Robert Iakobashvil
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
@ -4,29 +4,40 @@
|
||||
.SH NAME
|
||||
curl_multi_socket \- reads/writes available data
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLMcode curl_multi_socket_action(CURLM * multi_handle,
|
||||
curl_socket_t sockfd, int ev_bitmask,
|
||||
int *running_handles);
|
||||
|
||||
CURLMcode curl_multi_socket(CURLM * multi_handle, curl_socket_t sockfd,
|
||||
int *running_handles);
|
||||
|
||||
CURLMcode curl_multi_socket_all(CURLM *multi_handle,
|
||||
int *running_handles);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Alternative versions of \fIcurl_multi_perform(3)\fP that allows the
|
||||
application to pass in one of the file descriptors/sockets that have been
|
||||
detected to have \&"action" on them and let libcurl perform. This allows
|
||||
libcurl to not have to scan through all possible file descriptors to check for
|
||||
action. When the application has detected action on a socket handled by
|
||||
libcurl, it should call \fIcurl_multi_socket(3)\fP with the \fBsockfd\fP
|
||||
argument set to the socket with the action.
|
||||
application to pass in the file descriptor/socket that has been detected to
|
||||
have \&"action" on it and let libcurl perform. This allows libcurl to not have
|
||||
to scan through all possible file descriptors to check for action. When the
|
||||
application has detected action on a socket handled by libcurl, it should call
|
||||
\fIcurl_multi_socket_action(3)\fP with the \fBsockfd\fP argument set to the
|
||||
socket with the action. When the events on a socket are known, they can be
|
||||
passed as an events bitmask \fBev_bitmask\fP by first setting \fBev_bitmask\fP
|
||||
to 0, and then adding using bitwise OR (|) any combination of events to be
|
||||
choosen from CURL_CSELECT_IN, CURL_CSELECT_OUT or CURL_CSELECT_ERR. When the
|
||||
events on a socket are unknown, pass 0 instead, and libcurl will test the
|
||||
descriptor internally.
|
||||
|
||||
At return, the int \fBrunning_handles\fP points to will contain the number of
|
||||
still running easy handles within the multi handle. When this number reaches
|
||||
zero, all transfers are complete/done. Note that when you call
|
||||
\fIcurl_multi_socket(3)\fP on a specific socket and the counter decreases by
|
||||
one, it DOES NOT necessarily mean that this exact socket/transfer is the one
|
||||
that completed. Use \fIcurl_multi_info_read(3)\fP to figure out which easy
|
||||
handle that completed.
|
||||
\fIcurl_multi_socket_action(3)\fP on a specific socket and the counter
|
||||
decreases by one, it DOES NOT necessarily mean that this exact socket/transfer
|
||||
is the one that completed. Use \fIcurl_multi_info_read(3)\fP to figure out
|
||||
which easy handle that completed.
|
||||
|
||||
The curl_multi_socket functions inform the application about updates in the
|
||||
socket (file descriptor) status by doing none, one or multiple calls to the
|
||||
@ -44,6 +55,10 @@ wait for socket actions \- at most \- before doing the timeout action: call
|
||||
the \fBcurl_multi_socket(3)\fP function with the \fBsockfd\fP argument set to
|
||||
CURL_SOCKET_TIMEOUT.
|
||||
|
||||
Usage of \fIcurl_multi_socket(3)\fP is depricated, whereas the function is
|
||||
equivalent to \fIcurl_multi_socket_action(3)\fP, when \fBev_bitmask\fP is set
|
||||
to 0.
|
||||
|
||||
.SH "CALLBACK DETAILS"
|
||||
|
||||
The socket \fBcallback\fP function uses a prototype like this
|
||||
@ -115,12 +130,15 @@ callback is called.
|
||||
|
||||
7. Wait for action on any of libcurl's sockets
|
||||
|
||||
8, When action happens, call curl_multi_socket() for the socket(s) that got
|
||||
8, When action happens, call curl_multi_socket_action() for the socket(s) that got
|
||||
action.
|
||||
|
||||
9. Go back to step 6.
|
||||
.SH AVAILABILITY
|
||||
This function was added in libcurl 7.15.4, although not deemed stable yet.
|
||||
This function was added in libcurl 7.15.4, although deemed stablesince 7.16.0.
|
||||
|
||||
\fIcurl_multi_socket(3)\fP is deprecated, use
|
||||
\fIcurl_multi_socket_action(3)\fP instead!
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_multi_cleanup "(3), " curl_multi_init "(3), "
|
||||
.BR curl_multi_fdset "(3), " curl_multi_info_read "(3)"
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@ -224,6 +224,10 @@ CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
|
||||
|
||||
#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
|
||||
|
||||
#define CURL_CSELECT_IN 0x01
|
||||
#define CURL_CSELECT_OUT 0x02
|
||||
#define CURL_CSELECT_ERR 0x04
|
||||
|
||||
typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
|
||||
curl_socket_t s, /* socket */
|
||||
int what, /* see above */
|
||||
@ -249,9 +253,21 @@ typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
|
||||
CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
|
||||
int *running_handles);
|
||||
|
||||
CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
|
||||
curl_socket_t s,
|
||||
int ev_bitmask,
|
||||
int *running_handles);
|
||||
|
||||
CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
|
||||
int *running_handles);
|
||||
|
||||
#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
|
||||
/* This macro below was added in 7.16.3 to push users who recompile to use
|
||||
the new curl_multi_socket_action() instead of the old curl_multi_socket()
|
||||
*/
|
||||
#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Name: curl_multi_timeout()
|
||||
*
|
||||
|
@ -206,7 +206,7 @@ int waitconnect(curl_socket_t sockfd, /* socket */
|
||||
/* timeout, no connect today */
|
||||
return WAITCONN_TIMEOUT;
|
||||
|
||||
if(rc & CSELECT_ERR)
|
||||
if(rc & CURL_CSELECT_ERR)
|
||||
/* error condition caught */
|
||||
return WAITCONN_FDSET_ERROR;
|
||||
|
||||
|
23
lib/multi.c
23
lib/multi.c
@ -1661,6 +1661,7 @@ static void singlesocket(struct Curl_multi *multi,
|
||||
static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
bool checkall,
|
||||
curl_socket_t s,
|
||||
int ev_bitmask,
|
||||
int *running_handles)
|
||||
{
|
||||
CURLMcode result = CURLM_OK;
|
||||
@ -1698,8 +1699,14 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
/* bad bad bad bad bad bad bad */
|
||||
return CURLM_INTERNAL_ERROR;
|
||||
|
||||
if (data->set.one_easy->easy_conn) /* set socket event bitmask */
|
||||
data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
|
||||
|
||||
result = multi_runsingle(multi, data->set.one_easy);
|
||||
|
||||
if (data->set.one_easy->easy_conn)
|
||||
data->set.one_easy->easy_conn->cselect_bits = 0;
|
||||
|
||||
if(result == CURLM_OK)
|
||||
/* get the socket(s) and check if the state has been changed since
|
||||
last */
|
||||
@ -1791,12 +1798,24 @@ CURLMcode curl_multi_setopt(CURLM *multi_handle,
|
||||
return res;
|
||||
}
|
||||
|
||||
/* we define curl_multi_socket() in the public multi.h header */
|
||||
#undef curl_multi_socket
|
||||
|
||||
CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
|
||||
int *running_handles)
|
||||
{
|
||||
CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
|
||||
running_handles);
|
||||
0, running_handles);
|
||||
if (CURLM_OK == result)
|
||||
update_timer((struct Curl_multi *)multi_handle);
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
|
||||
int ev_bitmask, int *running_handles)
|
||||
{
|
||||
CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
|
||||
ev_bitmask, running_handles);
|
||||
if (CURLM_OK == result)
|
||||
update_timer((struct Curl_multi *)multi_handle);
|
||||
return result;
|
||||
@ -1806,7 +1825,7 @@ CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
|
||||
|
||||
{
|
||||
CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
|
||||
TRUE, CURL_SOCKET_BAD, running_handles);
|
||||
TRUE, CURL_SOCKET_BAD, 0, running_handles);
|
||||
if (CURLM_OK == result)
|
||||
update_timer((struct Curl_multi *)multi_handle);
|
||||
return result;
|
||||
|
18
lib/select.c
18
lib/select.c
@ -161,7 +161,7 @@ static int wait_ms(int timeout_ms)
|
||||
* Return values:
|
||||
* -1 = system call error or fd >= FD_SETSIZE
|
||||
* 0 = timeout
|
||||
* CSELECT_IN | CSELECT_OUT | CSELECT_ERR
|
||||
* CURL_CSELECT_IN | CURL_CSELECT_OUT | CURL_CSELECT_ERR
|
||||
*/
|
||||
int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
|
||||
{
|
||||
@ -223,16 +223,16 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, int timeout_m
|
||||
num = 0;
|
||||
if (readfd != CURL_SOCKET_BAD) {
|
||||
if (pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
|
||||
ret |= CSELECT_IN;
|
||||
ret |= CURL_CSELECT_IN;
|
||||
if (pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
|
||||
ret |= CSELECT_ERR;
|
||||
ret |= CURL_CSELECT_ERR;
|
||||
num++;
|
||||
}
|
||||
if (writefd != CURL_SOCKET_BAD) {
|
||||
if (pfd[num].revents & (POLLWRNORM|POLLOUT))
|
||||
ret |= CSELECT_OUT;
|
||||
ret |= CURL_CSELECT_OUT;
|
||||
if (pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
|
||||
ret |= CSELECT_ERR;
|
||||
ret |= CURL_CSELECT_ERR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -279,15 +279,15 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, int timeout_m
|
||||
ret = 0;
|
||||
if (readfd != CURL_SOCKET_BAD) {
|
||||
if (FD_ISSET(readfd, &fds_read))
|
||||
ret |= CSELECT_IN;
|
||||
ret |= CURL_CSELECT_IN;
|
||||
if (FD_ISSET(readfd, &fds_err))
|
||||
ret |= CSELECT_ERR;
|
||||
ret |= CURL_CSELECT_ERR;
|
||||
}
|
||||
if (writefd != CURL_SOCKET_BAD) {
|
||||
if (FD_ISSET(writefd, &fds_write))
|
||||
ret |= CSELECT_OUT;
|
||||
ret |= CURL_CSELECT_OUT;
|
||||
if (FD_ISSET(writefd, &fds_err))
|
||||
ret |= CSELECT_ERR;
|
||||
ret |= CURL_CSELECT_ERR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -76,11 +76,8 @@ struct pollfd
|
||||
#define POLLRDBAND POLLPRI
|
||||
#endif
|
||||
|
||||
#define CSELECT_IN 0x01
|
||||
#define CSELECT_OUT 0x02
|
||||
#define CSELECT_ERR 0x04
|
||||
|
||||
int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms);
|
||||
int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd,
|
||||
int timeout_ms);
|
||||
|
||||
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);
|
||||
|
||||
|
@ -383,7 +383,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
|
||||
if(result & CSELECT_ERR) {
|
||||
if(result & CURL_CSELECT_ERR) {
|
||||
failf(conn->data, "SOCKS5: error occured during connection");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
@ -415,7 +415,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
|
||||
if(result & CSELECT_ERR) {
|
||||
if(result & CURL_CSELECT_ERR) {
|
||||
failf(conn->data, "SOCKS5 read error occured");
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
|
@ -314,9 +314,10 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
|
||||
curl_socket_t fd_read;
|
||||
curl_socket_t fd_write;
|
||||
int select_res;
|
||||
|
||||
curl_off_t contentlength;
|
||||
int select_res = conn->cselect_bits;
|
||||
|
||||
conn->cselect_bits = 0;
|
||||
|
||||
/* only use the proper socket if the *_HOLD bit is not set simultaneously as
|
||||
then we are in rate limiting state in that transfer direction */
|
||||
@ -331,8 +332,12 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
else
|
||||
fd_write = CURL_SOCKET_BAD;
|
||||
|
||||
select_res = Curl_socket_ready(fd_read, fd_write, 0);
|
||||
if(select_res == CSELECT_ERR) {
|
||||
if (!select_res) { /* Call for select()/poll() only, if read/write/error
|
||||
status is not known. */
|
||||
select_res = Curl_socket_ready(fd_read, fd_write, 0);
|
||||
}
|
||||
|
||||
if(select_res == CURL_CSELECT_ERR) {
|
||||
failf(data, "select/poll returned error");
|
||||
return CURLE_SEND_ERROR;
|
||||
}
|
||||
@ -342,7 +347,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
the stream was rewound (in which case we have data in a
|
||||
buffer) */
|
||||
if((k->keepon & KEEP_READ) &&
|
||||
((select_res & CSELECT_IN) || conn->bits.stream_was_rewound)) {
|
||||
((select_res & CURL_CSELECT_IN) || conn->bits.stream_was_rewound)) {
|
||||
/* read */
|
||||
bool is_empty_data = FALSE;
|
||||
|
||||
@ -1350,7 +1355,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
|
||||
/* If we still have writing to do, we check if we have a writable
|
||||
socket. */
|
||||
if((k->keepon & KEEP_WRITE) && (select_res & CSELECT_OUT)) {
|
||||
if((k->keepon & KEEP_WRITE) && (select_res & CURL_CSELECT_OUT)) {
|
||||
/* write */
|
||||
|
||||
int i, si;
|
||||
|
@ -900,6 +900,8 @@ struct connectdata {
|
||||
union {
|
||||
struct ftp_conn ftpc;
|
||||
} proto;
|
||||
|
||||
int cselect_bits; /* bitmask of socket events */
|
||||
};
|
||||
|
||||
/* The end of connectdata. */
|
||||
|
Loading…
Reference in New Issue
Block a user