1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23#include "test.h"
24
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <fcntl.h>
28
29#include "testutil.h"
30#include "warnless.h"
31#include "memdebug.h"
32
33#define MAIN_LOOP_HANG_TIMEOUT     90 * 1000
34#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
35
36int test(char *URL)
37{
38  int res = 0;
39  CURL *curl;
40  int running;
41  char done=FALSE;
42  CURLM *m = NULL;
43  struct timeval ml_start;
44  struct timeval mp_start;
45  char ml_timedout = FALSE;
46  char mp_timedout = FALSE;
47
48  if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
49    fprintf(stderr, "curl_global_init() failed\n");
50    return TEST_ERR_MAJOR_BAD;
51  }
52
53  if ((curl = curl_easy_init()) == NULL) {
54    fprintf(stderr, "curl_easy_init() failed\n");
55    curl_global_cleanup();
56    return TEST_ERR_MAJOR_BAD;
57  }
58
59  test_setopt(curl, CURLOPT_URL, URL);
60  test_setopt(curl, CURLOPT_VERBOSE, 1);
61  test_setopt(curl, CURLOPT_PROXY, libtest_arg2);
62  test_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
63
64  if ((m = curl_multi_init()) == NULL) {
65    fprintf(stderr, "curl_multi_init() failed\n");
66    curl_easy_cleanup(curl);
67    curl_global_cleanup();
68    return TEST_ERR_MAJOR_BAD;
69  }
70
71  if ((res = (int)curl_multi_add_handle(m, curl)) != CURLM_OK) {
72    fprintf(stderr, "curl_multi_add_handle() failed, "
73            "with code %d\n", res);
74    curl_multi_cleanup(m);
75    curl_easy_cleanup(curl);
76    curl_global_cleanup();
77    return TEST_ERR_MAJOR_BAD;
78  }
79
80  ml_timedout = FALSE;
81  ml_start = tutil_tvnow();
82
83  fprintf(stderr, "Start at URL 0\n");
84
85  while (!done) {
86    fd_set rd, wr, exc;
87    int max_fd;
88    struct timeval interval;
89
90    interval.tv_sec = 1;
91    interval.tv_usec = 0;
92
93    if (tutil_tvdiff(tutil_tvnow(), ml_start) >
94        MAIN_LOOP_HANG_TIMEOUT) {
95      ml_timedout = TRUE;
96      break;
97    }
98    mp_timedout = FALSE;
99    mp_start = tutil_tvnow();
100
101    while (res == CURLM_CALL_MULTI_PERFORM) {
102      res = (int)curl_multi_perform(m, &running);
103      if (tutil_tvdiff(tutil_tvnow(), mp_start) >
104          MULTI_PERFORM_HANG_TIMEOUT) {
105        mp_timedout = TRUE;
106        break;
107      }
108      if (running <= 0) {
109        done = TRUE; /* bail out */
110        break;
111      }
112    }
113    if (mp_timedout || done)
114      break;
115
116    if (res != CURLM_OK) {
117      fprintf(stderr, "not okay???\n");
118      break;
119    }
120
121    FD_ZERO(&rd);
122    FD_ZERO(&wr);
123    FD_ZERO(&exc);
124    max_fd = 0;
125
126    if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) {
127      fprintf(stderr, "unexpected failured of fdset.\n");
128      res = 189;
129      break;
130    }
131
132    if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) {
133      fprintf(stderr, "bad select??\n");
134      res = 195;
135      break;
136    }
137
138    res = CURLM_CALL_MULTI_PERFORM;
139  }
140
141  if (ml_timedout || mp_timedout) {
142    if (ml_timedout) fprintf(stderr, "ml_timedout\n");
143    if (mp_timedout) fprintf(stderr, "mp_timedout\n");
144    fprintf(stderr, "ABORTING TEST, since it seems "
145            "that it would have run forever.\n");
146    res = TEST_ERR_RUNS_FOREVER;
147  }
148
149test_cleanup:
150
151  curl_easy_cleanup(curl);
152  if(m)
153    curl_multi_cleanup(m);
154  curl_global_cleanup();
155
156  return res;
157}
158