diff --git a/docs/examples/block_ip.c b/docs/examples/block_ip.c index 3515acfad7..3bb837f155 100644 --- a/docs/examples/block_ip.c +++ b/docs/examples/block_ip.c @@ -110,7 +110,7 @@ static struct ip *ip_list_append(struct ip *list, const char *data) struct ip *ip, *last; char *cidr; - ip = (struct ip *)calloc(1, sizeof(*ip)); + ip = calloc(1, sizeof(*ip)); if(!ip) return NULL; @@ -296,7 +296,7 @@ int main(void) CURLcode result; struct connection_filter *filter; - filter = (struct connection_filter *)calloc(1, sizeof(*filter)); + filter = calloc(1, sizeof(*filter)); if(!filter) return 1; diff --git a/docs/examples/ephiperfifo.c b/docs/examples/ephiperfifo.c index f5b5913747..b068dabf69 100644 --- a/docs/examples/ephiperfifo.c +++ b/docs/examples/ephiperfifo.c @@ -22,7 +22,7 @@ * ***************************************************************************/ /* - * multi socket API usage with epoll and timerfd + * multi socket interface with epoll and timerfd * */ /* Example application source code using the multi socket interface to @@ -140,7 +140,61 @@ static void mcode_or_die(const char *where, CURLMcode code) } } -static void timer_cb(struct GlobalInfo *g, int revents); +/* Check for completed transfers, and remove their easy handles */ +static void check_multi_info(struct GlobalInfo *g) +{ + char *eff_url; + CURLMsg *msg; + int msgs_left; + struct ConnInfo *conn; + + fprintf(MSG_OUT, "REMAINING: %d\n", g->still_running); + while((msg = curl_multi_info_read(g->multi, &msgs_left))) { + if(msg->msg == CURLMSG_DONE) { + CURL *curl = msg->easy_handle; + CURLcode result = msg->data.result; + curl_easy_getinfo(curl, CURLINFO_PRIVATE, &conn); + curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &eff_url); + fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, result, conn->error); + curl_multi_remove_handle(g->multi, curl); + free(conn->url); + curl_easy_cleanup(curl); + free(conn); + } + } +} + +/* Called by main loop when our timeout expires */ +static void timer_cb(struct GlobalInfo *g, int revents) +{ + CURLMcode mresult; + uint64_t count = 0; + ssize_t err = 0; + + (void)revents; + + err = read(g->tfd, &count, sizeof(uint64_t)); + if(err == -1) { + /* Note that we may call the timer callback even if the timerfd is not + * readable. It is possible that there are multiple events stored in the + * epoll buffer (i.e. the timer may have fired multiple times). The event + * count is cleared after the first call so future events in the epoll + * buffer fails to read from the timer. */ + if(errno == EAGAIN) { + fprintf(MSG_OUT, "EAGAIN on tfd %d\n", g->tfd); + return; + } + } + if(err != sizeof(uint64_t)) { + fprintf(stderr, "read(tfd) == %ld", err); + perror("read(tfd)"); + } + + mresult = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0, + &g->still_running); + mcode_or_die("timer_cb: curl_multi_socket_action", mresult); + check_multi_info(g); +} /* Update the timer after curl_multi library does its thing. curl informs the * application through this callback what it wants the new timeout to be, @@ -149,6 +203,8 @@ static int multi_timer_cb(CURLM *multi, long timeout_ms, struct GlobalInfo *g) { struct itimerspec its; + (void)multi; + fprintf(MSG_OUT, "multi_timer_cb: Setting timeout to %ld ms\n", timeout_ms); if(timeout_ms > 0) { @@ -174,30 +230,6 @@ static int multi_timer_cb(CURLM *multi, long timeout_ms, struct GlobalInfo *g) return 0; } -/* Check for completed transfers, and remove their easy handles */ -static void check_multi_info(struct GlobalInfo *g) -{ - char *eff_url; - CURLMsg *msg; - int msgs_left; - struct ConnInfo *conn; - - fprintf(MSG_OUT, "REMAINING: %d\n", g->still_running); - while((msg = curl_multi_info_read(g->multi, &msgs_left))) { - if(msg->msg == CURLMSG_DONE) { - CURL *curl = msg->easy_handle; - CURLcode result = msg->data.result; - curl_easy_getinfo(curl, CURLINFO_PRIVATE, &conn); - curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &eff_url); - fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, result, conn->error); - curl_multi_remove_handle(g->multi, curl); - free(conn->url); - curl_easy_cleanup(curl); - free(conn); - } - } -} - /* Called by libevent when we get action on a multi socket filedescriptor */ static void event_cb(struct GlobalInfo *g, int fd, int revents) { @@ -205,7 +237,7 @@ static void event_cb(struct GlobalInfo *g, int fd, int revents) struct itimerspec its; int action = ((revents & EPOLLIN) ? CURL_CSELECT_IN : 0) | - ((revents & EPOLLOUT) ? CURL_CSELECT_OUT : 0); + ((revents & EPOLLOUT) ? CURL_CSELECT_OUT : 0); mresult = curl_multi_socket_action(g->multi, fd, action, &g->still_running); mcode_or_die("event_cb: curl_multi_socket_action", mresult); @@ -218,36 +250,6 @@ static void event_cb(struct GlobalInfo *g, int fd, int revents) } } -/* Called by main loop when our timeout expires */ -static void timer_cb(struct GlobalInfo *g, int revents) -{ - CURLMcode mresult; - uint64_t count = 0; - ssize_t err = 0; - - err = read(g->tfd, &count, sizeof(uint64_t)); - if(err == -1) { - /* Note that we may call the timer callback even if the timerfd is not - * readable. It is possible that there are multiple events stored in the - * epoll buffer (i.e. the timer may have fired multiple times). The event - * count is cleared after the first call so future events in the epoll - * buffer fails to read from the timer. */ - if(errno == EAGAIN) { - fprintf(MSG_OUT, "EAGAIN on tfd %d\n", g->tfd); - return; - } - } - if(err != sizeof(uint64_t)) { - fprintf(stderr, "read(tfd) == %ld", err); - perror("read(tfd)"); - } - - mresult = curl_multi_socket_action(g->multi, - CURL_SOCKET_TIMEOUT, 0, &g->still_running); - mcode_or_die("timer_cb: curl_multi_socket_action", mresult); - check_multi_info(g); -} - /* Clean up the SockInfo structure */ static void remsock(struct SockInfo *f, struct GlobalInfo *g) { @@ -290,7 +292,7 @@ static void setsock(struct SockInfo *f, curl_socket_t s, CURL *e, int act, static void addsock(curl_socket_t s, CURL *curl, int action, struct GlobalInfo *g) { - struct SockInfo *fdp = (struct SockInfo *)calloc(1, sizeof(struct SockInfo)); + struct SockInfo *fdp = calloc(1, sizeof(struct SockInfo)); fdp->global = g; setsock(fdp, s, curl, action, g); @@ -349,7 +351,7 @@ static void new_conn(const char *url, struct GlobalInfo *g) struct ConnInfo *conn; CURLMcode mresult; - conn = (struct ConnInfo *)calloc(1, sizeof(*conn)); + conn = calloc(1, sizeof(*conn)); conn->error[0] = '\0'; conn->curl = curl_easy_init(); @@ -371,13 +373,14 @@ static void new_conn(const char *url, struct GlobalInfo *g) curl_easy_setopt(conn->curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(conn->curl, CURLOPT_LOW_SPEED_TIME, 3L); curl_easy_setopt(conn->curl, CURLOPT_LOW_SPEED_LIMIT, 10L); + fprintf(MSG_OUT, "Adding easy %p to multi %p (%s)\n", conn->curl, g->multi, url); mresult = curl_multi_add_handle(g->multi, conn->curl); mcode_or_die("new_conn: curl_multi_add_handle", mresult); - /* note that the add_handle() sets a timeout to trigger soon so that the - * necessary socket_action() call gets called by this app */ + /* note that add_handle() sets a timeout to trigger soon so that the + necessary socket_action() gets called */ } /* This gets called whenever data is received from the fifo */ @@ -387,6 +390,8 @@ static void fifo_cb(struct GlobalInfo *g, int revents) long int rv = 0; int n = 0; + (void)revents; + do { s[0] = '\0'; rv = fscanf(g->input, "%1023s%n", s, &n); @@ -400,10 +405,10 @@ static void fifo_cb(struct GlobalInfo *g, int revents) } /* Create a named pipe and tell libevent to monitor it */ -static const char *fifo = "hiper.fifo"; static int init_fifo(struct GlobalInfo *g) { struct stat st; + static const char *fifo = "hiper.fifo"; curl_socket_t sockfd; struct epoll_event epev; diff --git a/docs/examples/evhiperfifo.c b/docs/examples/evhiperfifo.c index aecbfe8f15..79ce6d3973 100644 --- a/docs/examples/evhiperfifo.c +++ b/docs/examples/evhiperfifo.c @@ -22,7 +22,7 @@ * ***************************************************************************/ /* - * multi socket interface together with libev + * multi socket interface with libev * */ /* Example application source code using the multi socket interface to @@ -106,23 +106,6 @@ struct SockInfo { struct GlobalInfo *global; }; -static void timer_cb(EV_P_ struct ev_timer *w, int revents); - -/* Update the event timer after curl_multi library calls */ -static int multi_timer_cb(CURLM *multi, long timeout_ms, struct GlobalInfo *g) -{ - (void)multi; - printf("%s %li\n", __PRETTY_FUNCTION__, timeout_ms); - ev_timer_stop(g->loop, &g->timer_event); - if(timeout_ms >= 0) { - /* -1 means delete, other values are timeout times in milliseconds */ - double t = timeout_ms / 1000; - ev_timer_init(&g->timer_event, timer_cb, t, 0.); - ev_timer_start(g->loop, &g->timer_event); - } - return 0; -} - /* Die if we get a bad CURLMcode somewhere */ static void mcode_or_die(const char *where, CURLMcode code) { @@ -185,18 +168,49 @@ static void check_multi_info(struct GlobalInfo *g) } } +/* Called by libevent when our timeout expires */ +static void timer_cb(EV_P_ struct ev_timer *w, int revents) +{ + CURLMcode mresult; + struct GlobalInfo *g; + + printf("%s w %p revents %i\n", __PRETTY_FUNCTION__, (void *)w, revents); + + g = (struct GlobalInfo *)w->data; + + mresult = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0, + &g->still_running); + mcode_or_die("timer_cb: curl_multi_socket_action", mresult); + check_multi_info(g); +} + +/* Update the event timer after curl_multi library calls */ +static int multi_timer_cb(CURLM *multi, long timeout_ms, struct GlobalInfo *g) +{ + (void)multi; + printf("%s %li\n", __PRETTY_FUNCTION__, timeout_ms); + ev_timer_stop(g->loop, &g->timer_event); + if(timeout_ms >= 0) { + /* -1 means delete, other values are timeout times in milliseconds */ + double t = timeout_ms / 1000; + ev_timer_init(&g->timer_event, timer_cb, t, 0.); + ev_timer_start(g->loop, &g->timer_event); + } + return 0; +} + /* Called by libevent when we get action on a multi socket */ static void event_cb(EV_P_ struct ev_io *w, int revents) { - struct GlobalInfo *g; CURLMcode mresult; - int action; + struct GlobalInfo *g; + + int action = ((revents & EV_READ) ? CURL_POLL_IN : 0) | + ((revents & EV_WRITE) ? CURL_POLL_OUT : 0); printf("%s w %p revents %i\n", __PRETTY_FUNCTION__, (void *)w, revents); g = (struct GlobalInfo *)w->data; - action = ((revents & EV_READ) ? CURL_POLL_IN : 0) | - ((revents & EV_WRITE) ? CURL_POLL_OUT : 0); mresult = curl_multi_socket_action(g->multi, w->fd, action, &g->still_running); mcode_or_die("event_cb: curl_multi_socket_action", mresult); @@ -207,22 +221,6 @@ static void event_cb(EV_P_ struct ev_io *w, int revents) } } -/* Called by libevent when our timeout expires */ -static void timer_cb(EV_P_ struct ev_timer *w, int revents) -{ - struct GlobalInfo *g; - CURLMcode mresult; - - printf("%s w %p revents %i\n", __PRETTY_FUNCTION__, (void *)w, revents); - - g = (struct GlobalInfo *)w->data; - - mresult = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0, - &g->still_running); - mcode_or_die("timer_cb: curl_multi_socket_action", mresult); - check_multi_info(g); -} - /* Clean up the SockInfo structure */ static void remsock(struct SockInfo *f, struct GlobalInfo *g) { @@ -370,7 +368,7 @@ static void fifo_cb(EV_P_ struct ev_io *w, int revents) rv = fscanf(g->input, "%1023s%n", s, &n); s[n] = '\0'; if(n && s[0]) { - new_conn(s, g); /* if we read a URL, go get it! */ + new_conn(s, g); /* if we read a URL, go get it! */ } else break; diff --git a/docs/examples/ghiper.c b/docs/examples/ghiper.c index 20a8a2de2d..2654566247 100644 --- a/docs/examples/ghiper.c +++ b/docs/examples/ghiper.c @@ -22,7 +22,7 @@ * ***************************************************************************/ /* - * multi socket API usage together with glib2 + * multi socket API usage with glib2 * */ /* Example application source code using the multi socket interface to @@ -194,9 +194,8 @@ static gboolean event_cb(GIOChannel *ch, GIOCondition condition, gpointer data) CURLMcode mresult; int fd = g_io_channel_unix_get_fd(ch); - int action = - ((condition & G_IO_IN) ? CURL_CSELECT_IN : 0) | - ((condition & G_IO_OUT) ? CURL_CSELECT_OUT : 0); + int action = ((condition & G_IO_IN) ? CURL_CSELECT_IN : 0) | + ((condition & G_IO_OUT) ? CURL_CSELECT_OUT : 0); mresult = curl_multi_socket_action(g->multi, fd, action, &g->still_running); mcode_or_die("event_cb: curl_multi_socket_action", mresult); @@ -230,9 +229,8 @@ static void remsock(struct SockInfo *f) static void setsock(struct SockInfo *f, curl_socket_t s, CURL *e, int act, struct GlobalInfo *g) { - GIOCondition kind = - ((act & CURL_POLL_IN) ? G_IO_IN : 0) | - ((act & CURL_POLL_OUT) ? G_IO_OUT : 0); + GIOCondition kind = ((act & CURL_POLL_IN) ? G_IO_IN : 0) | + ((act & CURL_POLL_OUT) ? G_IO_OUT : 0); f->sockfd = s; f->action = act; diff --git a/docs/examples/hiperfifo.c b/docs/examples/hiperfifo.c index fc4c180582..30bb8b8a6a 100644 --- a/docs/examples/hiperfifo.c +++ b/docs/examples/hiperfifo.c @@ -198,9 +198,8 @@ static void event_cb(int fd, short kind, void *userp) struct GlobalInfo *g = (struct GlobalInfo *)userp; CURLMcode mresult; - int action = - ((kind & EV_READ) ? CURL_CSELECT_IN : 0) | - ((kind & EV_WRITE) ? CURL_CSELECT_OUT : 0); + int action = ((kind & EV_READ) ? CURL_CSELECT_IN : 0) | + ((kind & EV_WRITE) ? CURL_CSELECT_OUT : 0); mresult = curl_multi_socket_action(g->multi, fd, action, &g->still_running); mcode_or_die("event_cb: curl_multi_socket_action", mresult); @@ -243,9 +242,8 @@ static void remsock(struct SockInfo *f) static void setsock(struct SockInfo *f, curl_socket_t s, CURL *e, int act, struct GlobalInfo *g) { - int kind = - ((act & CURL_POLL_IN) ? EV_READ : 0) | - ((act & CURL_POLL_OUT) ? EV_WRITE : 0) | EV_PERSIST; + int kind = ((act & CURL_POLL_IN) ? EV_READ : 0) | + ((act & CURL_POLL_OUT) ? EV_WRITE : 0) | EV_PERSIST; f->sockfd = s; f->action = act; @@ -371,7 +369,7 @@ static void fifo_cb(int fd, short event, void *arg) event_base_loopbreak(g->evbase); } else - new_conn(s, arg); /* if we read a URL, go get it! */ + new_conn(s, arg); /* if we read a URL, go get it! */ } else break; diff --git a/docs/examples/multi-event.c b/docs/examples/multi-event.c index b4e7b18083..4d30ac8c62 100644 --- a/docs/examples/multi-event.c +++ b/docs/examples/multi-event.c @@ -41,50 +41,6 @@ struct curl_context { curl_socket_t sockfd; }; -static void curl_perform(int fd, short event, void *arg); - -static struct curl_context *create_curl_context(curl_socket_t sockfd) -{ - struct curl_context *context; - - context = (struct curl_context *)malloc(sizeof(*context)); - - context->sockfd = sockfd; - - context->event = event_new(base, sockfd, 0, curl_perform, context); - - return context; -} - -static void destroy_curl_context(struct curl_context *context) -{ - event_del(context->event); - event_free(context->event); - free(context); -} - -static void add_download(const char *url, int num) -{ - char filename[50]; - FILE *file; - CURL *curl; - - snprintf(filename, sizeof(filename), "%d.download", num); - - file = fopen(filename, "wb"); - if(!file) { - fprintf(stderr, "Error opening %s\n", filename); - return; - } - - curl = curl_easy_init(); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); - curl_easy_setopt(curl, CURLOPT_PRIVATE, file); - curl_easy_setopt(curl, CURLOPT_URL, url); - curl_multi_add_handle(multi, curl); - fprintf(stderr, "Added download %s -> %s\n", url, filename); -} - static void check_multi_info(void) { char *done_url; @@ -141,6 +97,48 @@ static void curl_perform(int fd, short event, void *arg) check_multi_info(); } +static struct curl_context *create_curl_context(curl_socket_t sockfd) +{ + struct curl_context *context; + + context = (struct curl_context *)malloc(sizeof(*context)); + + context->sockfd = sockfd; + + context->event = event_new(base, sockfd, 0, curl_perform, context); + + return context; +} + +static void destroy_curl_context(struct curl_context *context) +{ + event_del(context->event); + event_free(context->event); + free(context); +} + +static void add_download(const char *url, int num) +{ + char filename[50]; + FILE *file; + CURL *curl; + + snprintf(filename, sizeof(filename), "%d.download", num); + + file = fopen(filename, "wb"); + if(!file) { + fprintf(stderr, "Error opening %s\n", filename); + return; + } + + curl = curl_easy_init(); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); + curl_easy_setopt(curl, CURLOPT_PRIVATE, file); + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_multi_add_handle(multi, curl); + fprintf(stderr, "Added download %s -> %s\n", url, filename); +} + static void on_timeout(evutil_socket_t fd, short events, void *arg) { int running_handles;