1e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/***************************************************************************
29bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                                  _   _ ____  _
39bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *  Project                     ___| | | |  _ \| |
49bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                             / __| | | | |_) | |
59bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                            | (__| |_| |  _ <| |___
69bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                             \___|\___/|_| \_\_____|
79bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
8e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
99bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
10e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is licensed as described in the file COPYING, which
11e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * you should have received as part of this distribution. The terms
12e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * are also available at http://curl.haxx.se/docs/copyright.html.
13e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *
14e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * copies of the Software, and permit persons to whom the Software is
16e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * furnished to do so, under the terms of the COPYING file.
17e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *
18e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * KIND, either express or implied.
20e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *
21e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ***************************************************************************/
22e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* Example application source code using the multi socket interface to
239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * download many files at once.
249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This example features the same basic functionality as hiperfifo.c does,
269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * but this uses libev instead of libevent.
279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Written by Jeff Pohlmeyer, converted to use libev by Markus Koetter
299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas EckelsRequires libev and a (POSIX?) system that has mkfifo().
319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas EckelsThis is an adaptation of libcurl's "hipev.c" and libevent's "event-test.c"
339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelssample programs.
349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas EckelsWhen running, the program creates the named pipe "hiper.fifo"
369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas EckelsWhenever there is input into the fifo, the program reads the input as a list
389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsof URL's and creates some new easy handles to fetch each URL via the
399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelscurl_multi "hiper" API.
409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas EckelsThus, you can try a single URL:
439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  % echo http://www.yahoo.com > hiper.fifo
449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas EckelsOr a whole bunch of them:
469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  % cat my-url-list > hiper.fifo
479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas EckelsThe fifo buffer is handled almost instantly, so you can even add more URL's
499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelswhile the previous requests are still being downloaded.
509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas EckelsNote:
529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  For the sake of simplicity, URL length is limited to 1023 char's !
539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas EckelsThis is purely a demo app, all retrieved data is simply discarded by the write
559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelscallback.
569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels*/
589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <stdio.h>
609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <string.h>
619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <stdlib.h>
629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <sys/time.h>
639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <time.h>
649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <unistd.h>
659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <sys/poll.h>
669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <curl/curl.h>
679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <ev.h>
689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <fcntl.h>
699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <sys/stat.h>
709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <errno.h>
719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define DPRINT(x...) printf(x)
739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define MSG_OUT stdout /* Send info to stdout, change to stderr if you want */
759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Global information, common to all connections */
789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelstypedef struct _GlobalInfo
799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  struct ev_loop *loop;
819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  struct ev_io fifo_event;
829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  struct ev_timer timer_event;
839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  CURLM *multi;
849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  int still_running;
859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  FILE* input;
869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} GlobalInfo;
879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Information associated with a specific easy handle */
909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelstypedef struct _ConnInfo
919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  CURL *easy;
939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  char *url;
949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  GlobalInfo *global;
959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  char error[CURL_ERROR_SIZE];
969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} ConnInfo;
979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Information associated with a specific socket */
1009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelstypedef struct _SockInfo
1019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
1029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_socket_t sockfd;
1039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  CURL *easy;
1049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  int action;
1059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  long timeout;
1069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  struct ev_io ev;
1079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  int evset;
1089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  GlobalInfo *global;
1099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} SockInfo;
1109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void timer_cb(EV_P_ struct ev_timer *w, int revents);
1129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Update the event timer after curl_multi library calls */
1149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int multi_timer_cb(CURLM *multi, long timeout_ms, GlobalInfo *g)
1159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
1169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  DPRINT("%s %li\n", __PRETTY_FUNCTION__,  timeout_ms);
1179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ev_timer_stop(g->loop, &g->timer_event);
1189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if (timeout_ms > 0)
1199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  {
1209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    double  t = timeout_ms / 1000;
1219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    ev_timer_init(&g->timer_event, timer_cb, t, 0.);
1229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    ev_timer_start(g->loop, &g->timer_event);
1239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }else
1249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    timer_cb(g->loop, &g->timer_event, 0);
1259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return 0;
1269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
1279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Die if we get a bad CURLMcode somewhere */
1299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void mcode_or_die(const char *where, CURLMcode code)
1309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
1319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if ( CURLM_OK != code )
1329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  {
1339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    const char *s;
1349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    switch ( code )
1359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    {
1369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    case CURLM_BAD_HANDLE:         s="CURLM_BAD_HANDLE";         break;
1379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    case CURLM_BAD_EASY_HANDLE:    s="CURLM_BAD_EASY_HANDLE";    break;
1389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    case CURLM_OUT_OF_MEMORY:      s="CURLM_OUT_OF_MEMORY";      break;
1399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    case CURLM_INTERNAL_ERROR:     s="CURLM_INTERNAL_ERROR";     break;
1409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    case CURLM_UNKNOWN_OPTION:     s="CURLM_UNKNOWN_OPTION";     break;
1419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    case CURLM_LAST:               s="CURLM_LAST";               break;
1429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    default: s="CURLM_unknown";
1439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      break;
1449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    case     CURLM_BAD_SOCKET:         s="CURLM_BAD_SOCKET";
1459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      fprintf(MSG_OUT, "ERROR: %s returns %s\n", where, s);
1469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      /* ignore this error */
1479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      return;
1489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    }
1499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    fprintf(MSG_OUT, "ERROR: %s returns %s\n", where, s);
1509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    exit(code);
1519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
1529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
1539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Check for completed transfers, and remove their easy handles */
1579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void check_multi_info(GlobalInfo *g)
1589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
1599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  char *eff_url;
1609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  CURLMsg *msg;
1619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  int msgs_left;
1629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ConnInfo *conn;
1639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  CURL *easy;
1649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  CURLcode res;
1659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  fprintf(MSG_OUT, "REMAINING: %d\n", g->still_running);
1679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  while ((msg = curl_multi_info_read(g->multi, &msgs_left))) {
1689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if (msg->msg == CURLMSG_DONE) {
1699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      easy = msg->easy_handle;
1709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      res = msg->data.result;
1719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn);
1729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url);
1739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, res, conn->error);
1749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      curl_multi_remove_handle(g->multi, easy);
1759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      free(conn->url);
1769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      curl_easy_cleanup(easy);
1779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      free(conn);
1789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    }
1799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
1809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
1819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Called by libevent when we get action on a multi socket */
1859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void event_cb(EV_P_ struct ev_io *w, int revents)
1869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
1879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  DPRINT("%s  w %p revents %i\n", __PRETTY_FUNCTION__, w, revents);
1889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  GlobalInfo *g = (GlobalInfo*) w->data;
1899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  CURLMcode rc;
1909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  int action = (revents&EV_READ?CURL_POLL_IN:0)|
1929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    (revents&EV_WRITE?CURL_POLL_OUT:0);
1939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rc = curl_multi_socket_action(g->multi, w->fd, action, &g->still_running);
1949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  mcode_or_die("event_cb: curl_multi_socket_action", rc);
1959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  check_multi_info(g);
1969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if ( g->still_running <= 0 )
1979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  {
1989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    fprintf(MSG_OUT, "last transfer done, kill timeout\n");
1999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    ev_timer_stop(g->loop, &g->timer_event);
2009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
2019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
2029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Called by libevent when our timeout expires */
2049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void timer_cb(EV_P_ struct ev_timer *w, int revents)
2059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
2069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  DPRINT("%s  w %p revents %i\n", __PRETTY_FUNCTION__, w, revents);
2079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  GlobalInfo *g = (GlobalInfo *)w->data;
2099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  CURLMcode rc;
2109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rc = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0, &g->still_running);
2129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  mcode_or_die("timer_cb: curl_multi_socket_action", rc);
2139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  check_multi_info(g);
2149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
2159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Clean up the SockInfo structure */
2179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void remsock(SockInfo *f, GlobalInfo *g)
2189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
2199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  printf("%s  \n", __PRETTY_FUNCTION__);
2209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if ( f )
2219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  {
2229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if ( f->evset )
2239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      ev_io_stop(g->loop, &f->ev);
2249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    free(f);
2259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
2269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
2279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Assign information to a SockInfo structure */
2319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void setsock(SockInfo*f, curl_socket_t s, CURL*e, int act, GlobalInfo*g)
2329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
2339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  printf("%s  \n", __PRETTY_FUNCTION__);
2349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  int kind = (act&CURL_POLL_IN?EV_READ:0)|(act&CURL_POLL_OUT?EV_WRITE:0);
2369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  f->sockfd = s;
2389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  f->action = act;
2399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  f->easy = e;
2409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if ( f->evset )
2419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    ev_io_stop(g->loop, &f->ev);
2429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ev_io_init(&f->ev, event_cb, f->sockfd, kind);
2439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  f->ev.data = g;
2449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  f->evset=1;
2459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ev_io_start(g->loop, &f->ev);
2469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
2479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Initialize a new SockInfo structure */
2519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void addsock(curl_socket_t s, CURL *easy, int action, GlobalInfo *g)
2529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
2539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  SockInfo *fdp = calloc(sizeof(SockInfo), 1);
2549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  fdp->global = g;
2569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  setsock(fdp, s, easy, action, g);
2579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_multi_assign(g->multi, s, fdp);
2589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
2599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* CURLMOPT_SOCKETFUNCTION */
2619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
2629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
2639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  DPRINT("%s e %p s %i what %i cbp %p sockp %p\n",
2649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels         __PRETTY_FUNCTION__, e, s, what, cbp, sockp);
2659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  GlobalInfo *g = (GlobalInfo*) cbp;
2679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  SockInfo *fdp = (SockInfo*) sockp;
2689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  const char *whatstr[]={ "none", "IN", "OUT", "INOUT", "REMOVE"};
2699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  fprintf(MSG_OUT,
2719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          "socket callback: s=%d e=%p what=%s ", s, e, whatstr[what]);
2729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if ( what == CURL_POLL_REMOVE )
2739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  {
2749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    fprintf(MSG_OUT, "\n");
2759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    remsock(fdp, g);
2769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  } else
2779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  {
2789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if ( !fdp )
2799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    {
2809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      fprintf(MSG_OUT, "Adding data: %s\n", whatstr[what]);
2819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      addsock(s, e, what, g);
2829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    } else
2839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    {
2849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      fprintf(MSG_OUT,
2859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels              "Changing action from %s to %s\n",
2869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels              whatstr[fdp->action], whatstr[what]);
2879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      setsock(fdp, s, e, what, g);
2889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    }
2899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
2909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return 0;
2919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
2929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* CURLOPT_WRITEFUNCTION */
2959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic size_t write_cb(void *ptr, size_t size, size_t nmemb, void *data)
2969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
2979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  size_t realsize = size * nmemb;
2989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ConnInfo *conn = (ConnInfo*) data;
2999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  (void)ptr;
3009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  (void)conn;
3019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return realsize;
3029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
3039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* CURLOPT_PROGRESSFUNCTION */
3069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int prog_cb (void *p, double dltotal, double dlnow, double ult,
3079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels                    double uln)
3089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
3099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ConnInfo *conn = (ConnInfo *)p;
3109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  (void)ult;
3119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  (void)uln;
3129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  fprintf(MSG_OUT, "Progress: %s (%g/%g)\n", conn->url, dlnow, dltotal);
3149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return 0;
3159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
3169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Create a new easy handle, and add it to the global curl_multi */
3199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void new_conn(char *url, GlobalInfo *g )
3209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
3219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ConnInfo *conn;
3229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  CURLMcode rc;
3239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  conn = calloc(1, sizeof(ConnInfo));
3259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  memset(conn, 0, sizeof(ConnInfo));
3269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  conn->error[0]='\0';
3279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  conn->easy = curl_easy_init();
3299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if ( !conn->easy )
3309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  {
3319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    fprintf(MSG_OUT, "curl_easy_init() failed, exiting!\n");
3329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    exit(2);
3339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
3349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  conn->global = g;
3359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  conn->url = strdup(url);
3369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_easy_setopt(conn->easy, CURLOPT_URL, conn->url);
3379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_easy_setopt(conn->easy, CURLOPT_WRITEFUNCTION, write_cb);
338e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  curl_easy_setopt(conn->easy, CURLOPT_WRITEDATA, conn);
3399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_easy_setopt(conn->easy, CURLOPT_VERBOSE, 1L);
3409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_easy_setopt(conn->easy, CURLOPT_ERRORBUFFER, conn->error);
3419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_easy_setopt(conn->easy, CURLOPT_PRIVATE, conn);
3429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_easy_setopt(conn->easy, CURLOPT_NOPROGRESS, 0L);
3439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_easy_setopt(conn->easy, CURLOPT_PROGRESSFUNCTION, prog_cb);
3449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_easy_setopt(conn->easy, CURLOPT_PROGRESSDATA, conn);
3459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_easy_setopt(conn->easy, CURLOPT_LOW_SPEED_TIME, 3L);
3469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_easy_setopt(conn->easy, CURLOPT_LOW_SPEED_LIMIT, 10L);
3479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  fprintf(MSG_OUT,
3499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          "Adding easy %p to multi %p (%s)\n", conn->easy, g->multi, url);
3509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rc = curl_multi_add_handle(g->multi, conn->easy);
3519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  mcode_or_die("new_conn: curl_multi_add_handle", rc);
3529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  /* note that the add_handle() will set a time-out to trigger very soon so
3549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels     that the necessary socket_action() call will be called by this app */
3559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
3569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* This gets called whenever data is received from the fifo */
3589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void fifo_cb(EV_P_ struct ev_io *w, int revents)
3599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
3609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  char s[1024];
3619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  long int rv=0;
3629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  int n=0;
3639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  GlobalInfo *g = (GlobalInfo *)w->data;
3649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  do
3669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  {
3679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    s[0]='\0';
3689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    rv=fscanf(g->input, "%1023s%n", s, &n);
3699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    s[n]='\0';
3709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if ( n && s[0] )
3719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    {
3729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      new_conn(s,g);  /* if we read a URL, go get it! */
3739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    } else break;
3749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  } while ( rv != EOF );
3759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
3769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Create a named pipe and tell libevent to monitor it */
3789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int init_fifo (GlobalInfo *g)
3799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
3809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  struct stat st;
3819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  static const char *fifo = "hiper.fifo";
382e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  curl_socket_t sockfd;
3839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo);
3859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if ( lstat (fifo, &st) == 0 )
3869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  {
3879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if ( (st.st_mode & S_IFMT) == S_IFREG )
3889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    {
3899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      errno = EEXIST;
3909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      perror("lstat");
3919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      exit (1);
3929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    }
3939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
3949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  unlink(fifo);
3959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if ( mkfifo (fifo, 0600) == -1 )
3969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  {
3979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    perror("mkfifo");
3989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    exit (1);
3999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
4009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0);
4019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if ( sockfd == -1 )
4029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  {
4039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    perror("open");
4049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    exit (1);
4059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
4069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  g->input = fdopen(sockfd, "r");
4079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
4089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  fprintf(MSG_OUT, "Now, pipe some URL's into > %s\n", fifo);
4099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ev_io_init(&g->fifo_event, fifo_cb, sockfd, EV_READ);
4109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ev_io_start(g->loop, &g->fifo_event);
4119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return(0);
4129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
4139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
4149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsint main(int argc, char **argv)
4159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
4169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  GlobalInfo g;
4179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  CURLMcode rc;
4189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  (void)argc;
4199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  (void)argv;
4209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
4219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  memset(&g, 0, sizeof(GlobalInfo));
4229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  g.loop = ev_default_loop(0);
4239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
4249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  init_fifo(&g);
4259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  g.multi = curl_multi_init();
4269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
4279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ev_timer_init(&g.timer_event, timer_cb, 0., 0.);
4289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  g.timer_event.data = &g;
4299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  g.fifo_event.data = &g;
4309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_multi_setopt(g.multi, CURLMOPT_SOCKETFUNCTION, sock_cb);
4319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_multi_setopt(g.multi, CURLMOPT_SOCKETDATA, &g);
4329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_multi_setopt(g.multi, CURLMOPT_TIMERFUNCTION, multi_timer_cb);
4339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_multi_setopt(g.multi, CURLMOPT_TIMERDATA, &g);
4349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
4359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  /* we don't call any curl_multi_socket*() function yet as we have no handles
4369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels     added! */
4379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
4389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ev_loop(g.loop, 0);
4399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_multi_cleanup(g.multi);
4409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return 0;
4419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
442