summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2006-07-26 22:19:42 +0000
committerDaniel Stenberg <daniel@haxx.se>2006-07-26 22:19:42 +0000
commit6f6b93da02019141812b81bfdbb6bcda430c3b4d (patch)
treeb7c63e529d88edfbfebd5aaeb4570bd26f2b1cef
parent45b1843dc9d5b283e5fd892dd74415e0e2a426a7 (diff)
downloadcurl-6f6b93da02019141812b81bfdbb6bcda430c3b4d.tar.gz
[Hiper-related work] Added a function called curl_multi_assign() that will
set a private pointer added to the internal libcurl hash table for the particular socket passed in to this function.
-rw-r--r--CHANGES16
-rw-r--r--docs/libcurl/Makefile.am10
-rw-r--r--docs/libcurl/curl_global_init.334
-rw-r--r--docs/libcurl/curl_multi_assign.344
-rw-r--r--docs/libcurl/curl_multi_setopt.35
-rw-r--r--docs/libcurl/curl_multi_socket.348
-rw-r--r--hiper/STATUS22
-rw-r--r--hiper/hipev.c53
-rw-r--r--include/curl/multi.h29
-rw-r--r--lib/multi.c24
10 files changed, 204 insertions, 81 deletions
diff --git a/CHANGES b/CHANGES
index 29c2aa263..2478c1766 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,22 @@
Changelog
+Daniel (27 July 2006)
+- [Hiper-related work] Added a function called curl_multi_assign() that will
+ set a private pointer added to the internal libcurl hash table for the
+ particular socket passed in to this function:
+
+ CURLMcode curl_multi_assign(CURLM *multi_handle,
+ curl_socket_t sockfd,
+ void *sockp);
+
+ 'sockp' being a custom pointer set by the application to be associated with
+ this socket. The socket has to be already existing and in-use by libcurl,
+ like having already called the callback telling about its existance.
+
+ 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).
+
Daniel (26 July 2006)
- Dan Nelson added the CURLOPT_FTP_ALTERNATIVE_TO_USER libcurl option and curl
tool option named --ftp-alternative-to-user. It provides a mean to send a
diff --git a/docs/libcurl/Makefile.am b/docs/libcurl/Makefile.am
index e43a0b67c..ea96cea1d 100644
--- a/docs/libcurl/Makefile.am
+++ b/docs/libcurl/Makefile.am
@@ -18,7 +18,7 @@ man_MANS = curl_easy_cleanup.3 curl_easy_getinfo.3 curl_easy_init.3 \
curl_multi_strerror.3 curl_share_strerror.3 curl_global_init_mem.3 \
libcurl-tutorial.3 curl_easy_reset.3 curl_easy_escape.3 \
curl_easy_unescape.3 curl_multi_setopt.3 curl_multi_socket.3 \
- curl_multi_timeout.3 curl_formget.3
+ curl_multi_timeout.3 curl_formget.3 curl_multi_assign.3
HTMLPAGES = curl_easy_cleanup.html curl_easy_getinfo.html \
curl_easy_init.html curl_easy_perform.html curl_easy_setopt.html \
@@ -35,8 +35,8 @@ HTMLPAGES = curl_easy_cleanup.html curl_easy_getinfo.html \
libcurl-errors.html curl_easy_strerror.html curl_multi_strerror.html \
curl_share_strerror.html curl_global_init_mem.html libcurl-tutorial.html \
curl_easy_reset.html curl_easy_escape.html curl_easy_unescape.html \
- curl_multi_setopt.html curl_multi_socket.html curl_multi_timeout.html \
- curl_formget.html
+ curl_multi_setopt.html curl_multi_socket.html curl_multi_timeout.html \
+ curl_formget.html curl_multi_assign.html
PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf curl_easy_init.pdf \
curl_easy_perform.pdf curl_easy_setopt.pdf curl_easy_duphandle.pdf \
@@ -52,8 +52,8 @@ PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf curl_easy_init.pdf \
libcurl-errors.pdf curl_easy_strerror.pdf curl_multi_strerror.pdf \
curl_share_strerror.pdf curl_global_init_mem.pdf libcurl-tutorial.pdf \
curl_easy_reset.pdf curl_easy_escape.pdf curl_easy_unescape.pdf \
- curl_multi_setopt.pdf curl_multi_socket.pdf curl_multi_timeout.pdf \
- curl_formget.pdf
+ curl_multi_setopt.pdf curl_multi_socket.pdf curl_multi_timeout.pdf \
+ curl_formget.pdf curl_multi_assign.pdf
CLEANFILES = $(HTMLPAGES) $(PDFPAGES)
diff --git a/docs/libcurl/curl_global_init.3 b/docs/libcurl/curl_global_init.3
index 0729ef787..ba15ad4e0 100644
--- a/docs/libcurl/curl_global_init.3
+++ b/docs/libcurl/curl_global_init.3
@@ -11,30 +11,30 @@ curl_global_init - Global libcurl initialisation
.BI "CURLcode curl_global_init(long " flags ");"
.ad
.SH DESCRIPTION
-This function sets up the program environment that libcurl needs. Think
-of it as an extension of the library loader.
+This function sets up the program environment that libcurl needs. Think of it
+as an extension of the library loader.
-This function must be called at least once within a program (a program is
-all the code that shares a memory space) before the program calls any other
-function in libcurl. The environment it sets up is constant for the life
-of the program and is the same for every program, so multiple calls have
-the same effect as one call.
+This function must be called at least once within a program (a program is all
+the code that shares a memory space) before the program calls any other
+function in libcurl. The environment it sets up is constant for the life of
+the program and is the same for every program, so multiple calls have the same
+effect as one call.
The flags option is a bit pattern that tells libcurl exactly what features to
init, as described below. Set the desired bits by ORing the values together.
In normal operation, you must specify CURL_GLOBAL_ALL. Don't use any other
-value unless you are familiar with and mean to control internal operations
-of libcurl.
+value unless you are familiar with and mean to control internal operations of
+libcurl.
-\fBThis function is not thread safe.\fP You must not call it when any
-other thread in the program (i.e. a thread sharing the same memory) is
-running. This doesn't just mean no other thread that is using
-libcurl. Because \fIcurl_global_init()\fP calls functions of other
-libraries that are similarly thread unsafe, it could conflict with any
-other thread that uses these other libraries.
+\fBThis function is not thread safe.\fP You must not call it when any other
+thread in the program (i.e. a thread sharing the same memory) is running.
+This doesn't just mean no other thread that is using libcurl. Because
+\fIcurl_global_init()\fP calls functions of other libraries that are similarly
+thread unsafe, it could conflict with any other thread that uses these other
+libraries.
-See the description in \fBlibcurl\fP(3) of global environment
-requirements for details of how to use this function.
+See the description in \fBlibcurl\fP(3) of global environment requirements for
+details of how to use this function.
.SH FLAGS
.TP 5
diff --git a/docs/libcurl/curl_multi_assign.3 b/docs/libcurl/curl_multi_assign.3
new file mode 100644
index 000000000..cb47a5e25
--- /dev/null
+++ b/docs/libcurl/curl_multi_assign.3
@@ -0,0 +1,44 @@
+.\" $Id$
+.\"
+.TH curl_multi_assign 3 "9 Jul 2006" "libcurl 7.16.0" "libcurl Manual"
+.SH NAME
+curl_multi_assign \- set data to associated with an internal socket
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLMcode curl_multi_assign(CURLM *multi_handle, curl_socket_t sockfd,
+ void *sockptr);
+.SH DESCRIPTION
+This function assigns an association in the multi handle between the given
+socket and a private pointer of the application. This is (only) useful for
+\fIcurl_multi_socket(3)\fP uses.
+
+When set, the \fIsockptr\fP pointer will be passed to all future socket
+callbacks for the specific \fIsockfd\fP socket.
+
+If the given \fIsockfd\fP isn't already in use by libcurl, this function will
+return an error.
+
+libcurl only keeps one single pointer associated with a socket, so calling
+this function several times for the same socket will make the last set pointer
+get used.
+
+The idea here being that this association (socket to private pointer) is
+something that just about every application that uses this API will need and
+then libcurl can just as well do it since it already has an internal hash
+table lookup for this.
+.SH "RETURN VALUE"
+The standard CURLMcode for multi interface error codes.
+.SH "TYPICAL USAGE"
+In a typical application you allocate a struct or at least use some kind of
+semi-dynamic data for each socket that we must wait for action on when using
+the \fIcurl_multi_socket(3)\fP approach.
+
+When our socket-callback get called by libcurl and we get to know about yet
+another socket to wait for, we can use \fIcurl_multi_assign(3)\fP to point out
+the particular data so that when we get updates about this same socket again,
+we don't have to find the struct associated with this socket by ourselves.
+.SH AVAILABILITY
+This function was added in libcurl 7.15.5, although not deemed stable yet.
+.SH "SEE ALSO"
+.BR curl_multi_setopt "(3), " curl_multi_socket "(3) "
diff --git a/docs/libcurl/curl_multi_setopt.3 b/docs/libcurl/curl_multi_setopt.3
index 623daa53f..0228e3d64 100644
--- a/docs/libcurl/curl_multi_setopt.3
+++ b/docs/libcurl/curl_multi_setopt.3
@@ -25,8 +25,9 @@ the socket (file descriptor) status by doing none, one or multiple calls to
the curl_socket_callback given in the \fBparam\fP argument. They update the
status with changes since the previous time a \fIcurl_multi_socket(3)\fP
function was called. If the given callback pointer is NULL, no callback will
-be called. Set the callback's fourth argument with \fICURLMOPT_SOCKETDATA\fP.
-See \fIcurl_multi_socket(3)\fP for more callback details.
+be called. Set the callback's \fBuserp\fP argument with
+\fICURLMOPT_SOCKETDATA\fP. See \fIcurl_multi_socket(3)\fP for more callback
+details.
.IP CURLMOPT_SOCKETDATA
Pass a pointer to whatever you want passed to the curl_socket_callback's forth
argument, the userp pointer. This is not used by libcurl but only passed-thru
diff --git a/docs/libcurl/curl_multi_socket.3 b/docs/libcurl/curl_multi_socket.3
index e5312c840..0c5ba7345 100644
--- a/docs/libcurl/curl_multi_socket.3
+++ b/docs/libcurl/curl_multi_socket.3
@@ -1,6 +1,6 @@
.\" $Id$
.\"
-.TH curl_multi_socket 3 "21 Dec 2005" "libcurl 7.16.0" "libcurl Manual"
+.TH curl_multi_socket 3 "9 Jul 2006" "libcurl 7.16.0" "libcurl Manual"
.SH NAME
curl_multi_socket \- reads/writes available data
.SH SYNOPSIS
@@ -19,32 +19,41 @@ application has detected action on a socket handled by libcurl, it should call
with the action.
These functions inform the application about updates in the socket (file
-descriptor) status by doing none, one or multiple calls to the
-curl_socket_callback given with the CURLMOPT_SOCKETFUNCTION option to
+descriptor) status by doing none, one or multiple calls to the callback
+function set with the CURLMOPT_SOCKETFUNCTION option to
\fIcurl_multi_setopt(3)\fP. They update the status with changes since the
previous time this function was called.
-If you want to force libcurl to (re-)check all its internal sockets and
-transfers instead of just a single one, you call
-\fBcurl_multi_socket_all(3)\fP instead.
+To force libcurl to (re-)check all its internal sockets and transfers instead
+of just a single one, you call \fBcurl_multi_socket_all(3)\fP.
-An application should call \fBcurl_multi_timeout(3)\fP to figure out how long
-it should 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.
+Applications should call \fBcurl_multi_timeout(3)\fP to figure out how long to
+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.
+
+.SH "CALLBACK DETAILS"
The socket \fBcallback\fP function uses a prototype like this
.nf
- int curl_socket_callback(CURL *easy, /* easy handle */
- curl_socket_t s, /* socket */
- int action, /* see values below */
- void *userp); /* "private" pointer */
+ int curl_socket_callback(CURL *easy, /* easy handle */
+ curl_socket_t s, /* socket */
+ int action, /* see values below */
+ void *userp, /* private callback pointer */
+ void *socketp); /* private socket pointer */
.fi
The callback MUST return 0.
-The \fIaction\fP (third) argument to the callback has one of five values:
+The \fIeasy\fP argument is a pointer to the easy handle that deals with this
+particular socket. Note that a single handle may work with several sockets
+simultaneously.
+
+The \fIs\fP argument is the actual socket value as you use it within your
+system.
+
+The \fIaction\fP argument to the callback has one of five values:
.RS
.IP "CURL_POLL_NONE (0)"
register, not interested in readiness (yet)
@@ -57,6 +66,15 @@ register, interested in both read and write readiness
.IP "CURL_POLL_REMOVE (4)"
deregister
.RE
+
+The \fIsocketp\fP argument is a private pointer you have previously set with
+\fIcurl_multi_assign(3)\fP to be associated with the \fIs\fP socket. If no
+pointer has been set, socketp will be NULL. This argument is of course a
+service to applications that want to keep certain data or structs that are
+strictly associated to the given socket.
+
+The \fIuserp\fP argument is a private pointer you have previously set with
+\fIcurl_multi_setopt(3)\fP and the CURLMOPT_SOCKETDATA option.
.SH "RETURN VALUE"
CURLMcode type, general libcurl multi interface error code.
diff --git a/hiper/STATUS b/hiper/STATUS
index df8f4515c..6b3e511f4 100644
--- a/hiper/STATUS
+++ b/hiper/STATUS
@@ -267,3 +267,25 @@ April 20, 2006
using the same socket. I've cleaned up and simplified code now to adjust to
this.
+---------------------------------------------------------------------------
+
+July 9, 2006
+
+ TODO: We need to alter how we use c-ares for getting info about its sockets,
+ as c-ares now provides a callback approach very similar to how libcurl is
+ about to work.
+
+ I'm adding a function called curl_multi_assign() that will set a private
+ pointer added to the internal libcurl hash table for the particular socket
+ passed in to this function:
+
+ CURLMcode curl_multi_assign(CURLM *multi_handle,
+ curl_socket_t sockfd,
+ void *sockp);
+
+ 'sockp' being a custom pointer set by the application to be associated with
+ this socket. The socket has to be already existing and in-use by libcurl,
+ like having already called the callback telling about its existance.
+
+ 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).
diff --git a/hiper/hipev.c b/hiper/hipev.c
index d82d7349f..b5a015918 100644
--- a/hiper/hipev.c
+++ b/hiper/hipev.c
@@ -88,36 +88,16 @@ struct fdinfo {
static struct fdinfo *allsocks;
-static struct fdinfo *findsock(curl_socket_t s)
+static void remsock(struct fdinfo *f)
{
- /* return the struct for the given socket */
- struct fdinfo *fdp = allsocks;
-
- while(fdp) {
- if(fdp->sockfd == s)
- break;
- fdp = fdp->next;
- }
- return fdp; /* a struct pointer or NULL */
-}
-
-static void remsock(curl_socket_t s)
-{
- struct fdinfo *fdp = allsocks;
-
- while(fdp) {
- if(fdp->sockfd == s)
- break;
- fdp = fdp->next;
- }
- if(!fdp)
+ if(!f)
/* did not find socket to remove! */
return;
- if(fdp->prev)
- fdp->prev->next = fdp->next;
- if(fdp->next)
- fdp->next->prev = fdp->prev;
+ if(f->prev)
+ f->prev->next = f->next;
+ if(f->next)
+ f->next->prev = f->prev;
else
/* this was the last entry */
allsocks = NULL;
@@ -131,7 +111,7 @@ static void setsock(struct fdinfo *fdp, curl_socket_t s, CURL *easy,
fdp->easy = easy;
}
-static void addsock(curl_socket_t s, CURL *easy, int action)
+static void addsock(curl_socket_t s, CURL *easy, int action, CURLM *multi)
{
struct fdinfo *fdp = calloc(sizeof(struct fdinfo), 1);
@@ -146,6 +126,9 @@ static void addsock(curl_socket_t s, CURL *easy, int action)
}
else
allsocks = fdp;
+
+ /* Set this association in libcurl */
+ curl_multi_assign(multi, s, fdp);
}
static void fdinfo2fdset(fd2_set *fdread, fd2_set *fdwrite, int *maxfd)
@@ -201,18 +184,20 @@ static void fdinfo2fdset(fd2_set *fdread, fd2_set *fdwrite, int *maxfd)
static int socket_callback(CURL *easy, /* easy handle */
curl_socket_t s, /* socket */
int what, /* see above */
- void *userp) /* "private" pointer */
+ void *cbp, /* callback pointer */
+ void *socketp) /* socket pointer */
{
- struct fdinfo *fdp;
+ struct fdinfo *fdp = (struct fdinfo *)socketp;
+
printf("socket %d easy %p what %d\n", s, easy, what);
if(what == CURL_POLL_REMOVE)
- remsock(s);
+ remsock(fdp);
else {
- fdp = findsock(s);
-
if(!fdp) {
- addsock(s, easy, what);
+ /* not previously known, add it and set association */
+ printf("Add info for socket %d (%d)\n", s, what);
+ addsock(s, easy, what, cbp);
}
else {
/* we already know about it, just change action/timeout */
@@ -443,7 +428,7 @@ int main(int argc, char **argv)
}
curl_multi_setopt(multi_handle, CURLMOPT_SOCKETFUNCTION, socket_callback);
- curl_multi_setopt(multi_handle, CURLMOPT_SOCKETDATA, NULL);
+ 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));
diff --git a/include/curl/multi.h b/include/curl/multi.h
index 4fc70640a..eb62446df 100644
--- a/include/curl/multi.h
+++ b/include/curl/multi.h
@@ -261,11 +261,14 @@ CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
curl_socket_t s, /* socket */
int what, /* see above */
- void *userp); /* "private" pointer */
+ void *userp, /* private callback
+ pointer */
+ void *socketp); /* private socket
+ pointer */
-CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s);
+CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s);
-CURLMcode curl_multi_socket_all(CURLM *multi_handle);
+CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle);
/*
* Name: curl_multi_timeout()
@@ -276,7 +279,8 @@ CURLMcode curl_multi_socket_all(CURLM *multi_handle);
*
* Returns: CURLM error code.
*/
-CURLMcode curl_multi_timeout(CURLM *multi_handle, long *milliseconds);
+CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
+ long *milliseconds);
#undef CINIT /* re-using the same name as in curl.h */
@@ -309,8 +313,21 @@ typedef enum {
*
* Returns: CURLM error code.
*/
-CURLMcode curl_multi_setopt(CURLM *multi_handle,
- CURLMoption option, ...);
+CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
+ CURLMoption option, ...);
+
+
+/*
+ * Name: curl_multi_assign()
+ *
+ * Desc: This function sets an association in the multi handle between the
+ * given socket and a private pointer of the application. This is
+ * (only) useful for curl_multi_socket uses.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
+ curl_socket_t sockfd, void *sockp);
#ifdef __cplusplus
} /* end of extern "C" */
diff --git a/lib/multi.c b/lib/multi.c
index 44c742476..3296f09e5 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -182,7 +182,7 @@ struct Curl_sh_entry {
time_t timestamp;
long inuse;
int action; /* what action READ/WRITE this socket waits for */
- void *userp; /* settable by users (not yet decided exactly how) */
+ void *socketp; /* settable by users with curl_multi_assign() */
};
/* bits for 'action' having no bits means this socket is not expecting any
action */
@@ -1125,10 +1125,14 @@ static void singlesocket(struct Curl_multi *multi,
/* call the callback with this new info */
if(multi->socket_cb) {
+ struct Curl_sh_entry *entry =
+ Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
+
multi->socket_cb(easy->easy_handle,
s,
action,
- multi->socket_userp);
+ multi->socket_userp,
+ entry->socketp);
}
/* Update the sockhash accordingly */
@@ -1385,3 +1389,19 @@ void Curl_expire(struct SessionHandle *data, long milli)
#endif
}
+CURLMcode curl_multi_assign(CURLM *multi_handle,
+ curl_socket_t s, void *hashp)
+{
+ struct Curl_sh_entry *there = NULL;
+ struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
+
+ if(s != CURL_SOCKET_BAD)
+ there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
+
+ if(!there)
+ return CURLM_BAD_SOCKET;
+
+ there->socketp = hashp;
+
+ return CURLM_OK;
+}