diff options
Diffstat (limited to 'docs/examples/ghiper.c')
-rw-r--r-- | docs/examples/ghiper.c | 228 |
1 files changed, 100 insertions, 128 deletions
diff --git a/docs/examples/ghiper.c b/docs/examples/ghiper.c index b25f55210..f78a943b9 100644 --- a/docs/examples/ghiper.c +++ b/docs/examples/ghiper.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2016, 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 @@ -28,33 +28,32 @@ * * Written by Jeff Pohlmeyer -Requires glib-2.x and a (POSIX?) system that has mkfifo(). + Requires glib-2.x and a (POSIX?) system that has mkfifo(). -This is an adaptation of libcurl's "hipev.c" and libevent's "event-test.c" -sample programs, adapted to use glib's g_io_channel in place of libevent. + This is an adaptation of libcurl's "hipev.c" and libevent's "event-test.c" + sample programs, adapted to use glib's g_io_channel in place of libevent. -When running, the program creates the named pipe "hiper.fifo" + When running, the program creates the named pipe "hiper.fifo" -Whenever there is input into the fifo, the program reads the input as a list -of URL's and creates some new easy handles to fetch each URL via the -curl_multi "hiper" API. + Whenever there is input into the fifo, the program reads the input as a list + of URL's and creates some new easy handles to fetch each URL via the + curl_multi "hiper" API. -Thus, you can try a single URL: - % echo http://www.yahoo.com > hiper.fifo + Thus, you can try a single URL: + % echo http://www.yahoo.com > hiper.fifo -Or a whole bunch of them: - % cat my-url-list > hiper.fifo + Or a whole bunch of them: + % cat my-url-list > hiper.fifo -The fifo buffer is handled almost instantly, so you can even add more URL's -while the previous requests are still being downloaded. + The fifo buffer is handled almost instantly, so you can even add more URL's + while the previous requests are still being downloaded. -This is purely a demo app, all retrieved data is simply discarded by the write -callback. + This is purely a demo app, all retrieved data is simply discarded by the write + callback. */ - #include <glib.h> #include <sys/stat.h> #include <unistd.h> @@ -64,13 +63,10 @@ callback. #include <errno.h> #include <curl/curl.h> - #define MSG_OUT g_print /* Change to "g_error" to write to stderr */ #define SHOW_VERBOSE 0 /* Set to non-zero for libcurl messages */ #define SHOW_PROGRESS 0 /* Set to non-zero to enable progress callback */ - - /* Global information, common to all connections */ typedef struct _GlobalInfo { CURLM *multi; @@ -78,8 +74,6 @@ typedef struct _GlobalInfo { int still_running; } GlobalInfo; - - /* Information associated with a specific easy handle */ typedef struct _ConnInfo { CURL *easy; @@ -88,7 +82,6 @@ typedef struct _ConnInfo { char error[CURL_ERROR_SIZE]; } ConnInfo; - /* Information associated with a specific socket */ typedef struct _SockInfo { curl_socket_t sockfd; @@ -100,30 +93,25 @@ typedef struct _SockInfo { GlobalInfo *global; } SockInfo; - - - /* Die if we get a bad CURLMcode somewhere */ static void mcode_or_die(const char *where, CURLMcode code) { - if ( CURLM_OK != code ) { + if(CURLM_OK != code) { const char *s; switch (code) { - case CURLM_BAD_HANDLE: s="CURLM_BAD_HANDLE"; break; - case CURLM_BAD_EASY_HANDLE: s="CURLM_BAD_EASY_HANDLE"; break; - case CURLM_OUT_OF_MEMORY: s="CURLM_OUT_OF_MEMORY"; break; - case CURLM_INTERNAL_ERROR: s="CURLM_INTERNAL_ERROR"; break; - case CURLM_BAD_SOCKET: s="CURLM_BAD_SOCKET"; break; - case CURLM_UNKNOWN_OPTION: s="CURLM_UNKNOWN_OPTION"; break; - case CURLM_LAST: s="CURLM_LAST"; break; - default: s="CURLM_unknown"; + case CURLM_BAD_HANDLE: s="CURLM_BAD_HANDLE"; break; + case CURLM_BAD_EASY_HANDLE: s="CURLM_BAD_EASY_HANDLE"; break; + case CURLM_OUT_OF_MEMORY: s="CURLM_OUT_OF_MEMORY"; break; + case CURLM_INTERNAL_ERROR: s="CURLM_INTERNAL_ERROR"; break; + case CURLM_BAD_SOCKET: s="CURLM_BAD_SOCKET"; break; + case CURLM_UNKNOWN_OPTION: s="CURLM_UNKNOWN_OPTION"; break; + case CURLM_LAST: s="CURLM_LAST"; break; + default: s="CURLM_unknown"; } MSG_OUT("ERROR: %s returns %s\n", where, s); exit(code); } } - - /* Check for completed transfers, and remove their easy handles */ static void check_multi_info(GlobalInfo *g) { @@ -135,8 +123,8 @@ static void check_multi_info(GlobalInfo *g) CURLcode res; MSG_OUT("REMAINING: %d\n", g->still_running); - while ((msg = curl_multi_info_read(g->multi, &msgs_left))) { - if (msg->msg == CURLMSG_DONE) { + while((msg = curl_multi_info_read(g->multi, &msgs_left))) { + if(msg->msg == CURLMSG_DONE) { easy = msg->easy_handle; res = msg->data.result; curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn); @@ -150,8 +138,6 @@ static void check_multi_info(GlobalInfo *g) } } - - /* Called by glib when our timeout expires */ static gboolean timer_cb(gpointer data) { @@ -159,14 +145,12 @@ static gboolean timer_cb(gpointer data) CURLMcode rc; rc = curl_multi_socket_action(g->multi, - CURL_SOCKET_TIMEOUT, 0, &g->still_running); + CURL_SOCKET_TIMEOUT, 0, &g->still_running); mcode_or_die("timer_cb: curl_multi_socket_action", rc); check_multi_info(g); return FALSE; } - - /* Update the event timer after curl_multi library calls */ static int update_timeout_cb(CURLM *multi, long timeout_ms, void *userp) { @@ -176,15 +160,12 @@ static int update_timeout_cb(CURLM *multi, long timeout_ms, void *userp) timeout.tv_usec = (timeout_ms%1000)*1000; MSG_OUT("*** update_timeout_cb %ld => %ld:%ld ***\n", - timeout_ms, timeout.tv_sec, timeout.tv_usec); + timeout_ms, timeout.tv_sec, timeout.tv_usec); g->timer_event = g_timeout_add(timeout_ms, timer_cb, g); return 0; } - - - /* Called by glib when we get action on a multi socket */ static gboolean event_cb(GIOChannel *ch, GIOCondition condition, gpointer data) { @@ -202,41 +183,43 @@ static gboolean event_cb(GIOChannel *ch, GIOCondition condition, gpointer data) check_multi_info(g); if(g->still_running) { return TRUE; - } else { + } + else { MSG_OUT("last transfer done, kill timeout\n"); - if (g->timer_event) { g_source_remove(g->timer_event); } + if(g->timer_event) { + g_source_remove(g->timer_event); + } return FALSE; } } - - /* Clean up the SockInfo structure */ static void remsock(SockInfo *f) { - if (!f) { return; } - if (f->ev) { g_source_remove(f->ev); } + if(!f) { + return; + } + if(f->ev) { + g_source_remove(f->ev); + } g_free(f); } - - /* Assign information to a SockInfo structure */ static void setsock(SockInfo*f, curl_socket_t s, CURL*e, int act, GlobalInfo*g) { GIOCondition kind = - (act&CURL_POLL_IN?G_IO_IN:0)|(act&CURL_POLL_OUT?G_IO_OUT:0); + (act&CURL_POLL_IN?G_IO_IN:0)|(act&CURL_POLL_OUT?G_IO_OUT:0); f->sockfd = s; f->action = act; f->easy = e; - if (f->ev) { g_source_remove(f->ev); } - f->ev=g_io_add_watch(f->ch, kind, event_cb,g); - + if(f->ev) { + g_source_remove(f->ev); + } + f->ev=g_io_add_watch(f->ch, kind, event_cb, g); } - - /* Initialize a new SockInfo structure */ static void addsock(curl_socket_t s, CURL *easy, int action, GlobalInfo *g) { @@ -248,8 +231,6 @@ static void addsock(curl_socket_t s, CURL *easy, int action, GlobalInfo *g) curl_multi_assign(g->multi, s, fdp); } - - /* CURLMOPT_SOCKETFUNCTION */ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) { @@ -258,14 +239,15 @@ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) static const char *whatstr[]={ "none", "IN", "OUT", "INOUT", "REMOVE" }; MSG_OUT("socket callback: s=%d e=%p what=%s ", s, e, whatstr[what]); - if (what == CURL_POLL_REMOVE) { + if(what == CURL_POLL_REMOVE) { MSG_OUT("\n"); remsock(fdp); - } else { - if (!fdp) { + } + else { + if(!fdp) { MSG_OUT("Adding data: %s%s\n", - what&CURL_POLL_IN?"READ":"", - what&CURL_POLL_OUT?"WRITE":"" ); + what&CURL_POLL_IN?"READ":"", + what&CURL_POLL_OUT?"WRITE":"" ); addsock(s, e, what, g); } else { @@ -277,8 +259,6 @@ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) return 0; } - - /* CURLOPT_WRITEFUNCTION */ static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *data) { @@ -289,18 +269,15 @@ static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *data) return realsize; } - - /* CURLOPT_PROGRESSFUNCTION */ -static int prog_cb (void *p, double dltotal, double dlnow, double ult, double uln) +static int prog_cb (void *p, double dltotal, double dlnow, double ult, + double uln) { ConnInfo *conn = (ConnInfo *)p; MSG_OUT("Progress: %s (%g/%g)\n", conn->url, dlnow, dltotal); return 0; } - - /* Create a new easy handle, and add it to the global curl_multi */ static void new_conn(char *url, GlobalInfo *g ) { @@ -308,11 +285,9 @@ static void new_conn(char *url, GlobalInfo *g ) CURLMcode rc; conn = g_malloc0(sizeof(ConnInfo)); - conn->error[0]='\0'; - conn->easy = curl_easy_init(); - if (!conn->easy) { + if(!conn->easy) { MSG_OUT("curl_easy_init() failed, exiting!\n"); exit(2); } @@ -340,93 +315,90 @@ static void new_conn(char *url, GlobalInfo *g ) that the necessary socket_action() call will be called by this app */ } - /* This gets called by glib whenever data is received from the fifo */ static gboolean fifo_cb (GIOChannel *ch, GIOCondition condition, gpointer data) { - #define BUF_SIZE 1024 +#define BUF_SIZE 1024 gsize len, tp; gchar *buf, *tmp, *all=NULL; GIOStatus rv; do { GError *err=NULL; - rv = g_io_channel_read_line (ch,&buf,&len,&tp,&err); - if ( buf ) { - if (tp) { buf[tp]='\0'; } - new_conn(buf,(GlobalInfo*)data); + rv = g_io_channel_read_line(ch, &buf, &len, &tp, &err); + if(buf) { + if(tp) { + buf[tp]='\0'; + } + new_conn(buf, (GlobalInfo*)data); g_free(buf); - } else { + } + else { buf = g_malloc(BUF_SIZE+1); - while (TRUE) { + while(TRUE) { buf[BUF_SIZE]='\0'; - g_io_channel_read_chars(ch,buf,BUF_SIZE,&len,&err); - if (len) { + g_io_channel_read_chars(ch, buf, BUF_SIZE, &len, &err); + if(len) { buf[len]='\0'; - if (all) { + if(all) { tmp=all; all=g_strdup_printf("%s%s", tmp, buf); g_free(tmp); - } else { + } + else { all = g_strdup(buf); } - } else { - break; + } + else { + break; } } - if (all) { - new_conn(all,(GlobalInfo*)data); + if(all) { + new_conn(all, (GlobalInfo*)data); g_free(all); } g_free(buf); } - if ( err ) { + if(err) { g_error("fifo_cb: %s", err->message); g_free(err); break; } - } while ( (len) && (rv == G_IO_STATUS_NORMAL) ); + } while((len) && (rv == G_IO_STATUS_NORMAL)); return TRUE; } - - - int init_fifo(void) { - struct stat st; - const char *fifo = "hiper.fifo"; - int socket; - - if (lstat (fifo, &st) == 0) { - if ((st.st_mode & S_IFMT) == S_IFREG) { - errno = EEXIST; - perror("lstat"); - exit (1); + struct stat st; + const char *fifo = "hiper.fifo"; + int socket; + + if(lstat (fifo, &st) == 0) { + if((st.st_mode & S_IFMT) == S_IFREG) { + errno = EEXIST; + perror("lstat"); + exit (1); + } } - } - - unlink (fifo); - if (mkfifo (fifo, 0600) == -1) { - perror("mkfifo"); - exit (1); - } - socket = open (fifo, O_RDWR | O_NONBLOCK, 0); + unlink (fifo); + if(mkfifo (fifo, 0600) == -1) { + perror("mkfifo"); + exit (1); + } - if (socket == -1) { - perror("open"); - exit (1); - } - MSG_OUT("Now, pipe some URL's into > %s\n", fifo); + socket = open (fifo, O_RDWR | O_NONBLOCK, 0); - return socket; + if(socket == -1) { + perror("open"); + exit (1); + } + MSG_OUT("Now, pipe some URL's into > %s\n", fifo); + return socket; } - - - int main(int argc, char **argv) { GlobalInfo *g; @@ -438,8 +410,8 @@ int main(int argc, char **argv) fd=init_fifo(); ch=g_io_channel_unix_new(fd); - g_io_add_watch(ch,G_IO_IN,fifo_cb,g); - gmain=g_main_loop_new(NULL,FALSE); + g_io_add_watch(ch, G_IO_IN, fifo_cb, g); + gmain=g_main_loop_new(NULL, FALSE); g->multi = curl_multi_init(); curl_multi_setopt(g->multi, CURLMOPT_SOCKETFUNCTION, sock_cb); curl_multi_setopt(g->multi, CURLMOPT_SOCKETDATA, g); |