aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES8
-rw-r--r--RELEASE-NOTES5
-rw-r--r--docs/libcurl/curl_multi_socket.342
-rw-r--r--include/curl/multi.h18
-rw-r--r--lib/connect.c2
-rw-r--r--lib/multi.c23
-rw-r--r--lib/select.c18
-rw-r--r--lib/select.h7
-rw-r--r--lib/socks.c4
-rw-r--r--lib/transfer.c17
-rw-r--r--lib/urldata.h2
11 files changed, 106 insertions, 40 deletions
diff --git a/CHANGES b/CHANGES
index 21d90e0bc..79863cbe9 100644
--- a/CHANGES
+++ b/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.
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index db4a21622..1a6239a15 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -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)
diff --git a/docs/libcurl/curl_multi_socket.3 b/docs/libcurl/curl_multi_socket.3
index 9ad8257f1..3cfd20b40 100644
--- a/docs/libcurl/curl_multi_socket.3
+++ b/docs/libcurl/curl_multi_socket.3
@@ -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)"
diff --git a/include/curl/multi.h b/include/curl/multi.h
index d2533728d..5eab527ae 100644
--- a/include/curl/multi.h
+++ b/include/curl/multi.h
@@ -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()
*
diff --git a/lib/connect.c b/lib/connect.c
index 95791cf5d..dd67638ff 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -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;
diff --git a/lib/multi.c b/lib/multi.c
index 530357392..76614c760 100644
--- a/lib/multi.c
+++ b/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;
diff --git a/lib/select.c b/lib/select.c
index 2af14eb36..1cc819a2a 100644
--- a/lib/select.c
+++ b/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;
diff --git a/lib/select.h b/lib/select.h
index 5a62a6fd8..77b3e915f 100644
--- a/lib/select.h
+++ b/lib/select.h
@@ -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);
diff --git a/lib/socks.c b/lib/socks.c
index 1157b960c..6b95e752d 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -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;
}
diff --git a/lib/transfer.c b/lib/transfer.c
index b70f3b509..52b4c8966 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -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;
diff --git a/lib/urldata.h b/lib/urldata.h
index 419915569..b129ca708 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -900,6 +900,8 @@ struct connectdata {
union {
struct ftp_conn ftpc;
} proto;
+
+ int cselect_bits; /* bitmask of socket events */
};
/* The end of connectdata. */