1 /*****************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
11 * This code sets up multiple easy handles that transfer a single file from
12 * the same URL, in a serial manner after each other. Due to the connection
13 * sharing within the multi handle all transfers are performed on the same
14 * persistent connection.
16 * This source code is used for lib526, lib527 and lib532 with only #ifdefs
17 * controlling the small differences.
19 * - lib526 closes all easy handles after
20 * they all have transfered the file over the single connection
21 * - lib527 closes each easy handle after each single transfer.
22 * - lib532 uses only a single easy handle that is removed, reset and then
23 * re-added for each transfer
25 * Test case 526, 527 and 532 use FTP, while test 528 uses the lib526 tool but
31 #include <sys/types.h>
38 #define MAIN_LOOP_HANG_TIMEOUT 90 * 1000
39 #define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
46 CURL *curl[NUM_HANDLES];
52 struct timeval ml_start;
53 struct timeval mp_start;
54 char ml_timedout = FALSE;
55 char mp_timedout = FALSE;
57 if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
58 fprintf(stderr, "curl_global_init() failed\n");
59 return TEST_ERR_MAJOR_BAD;
62 /* get NUM_HANDLES easy handles */
63 for(i=0; i < NUM_HANDLES; i++) {
64 curl[i] = curl_easy_init();
66 fprintf(stderr, "curl_easy_init() failed "
67 "on handle #%d\n", i);
68 for (j=i-1; j >= 0; j--) {
69 curl_easy_cleanup(curl[j]);
71 curl_global_cleanup();
72 return TEST_ERR_MAJOR_BAD + i;
74 res = curl_easy_setopt(curl[i], CURLOPT_URL, URL);
76 fprintf(stderr, "curl_easy_setopt() failed "
77 "on handle #%d\n", i);
78 for (j=i; j >= 0; j--) {
79 curl_easy_cleanup(curl[j]);
81 curl_global_cleanup();
82 return TEST_ERR_MAJOR_BAD + i;
86 res = curl_easy_setopt(curl[i], CURLOPT_VERBOSE, 1L);
88 fprintf(stderr, "curl_easy_setopt() failed "
89 "on handle #%d\n", i);
90 for (j=i; j >= 0; j--) {
91 curl_easy_cleanup(curl[j]);
93 curl_global_cleanup();
94 return TEST_ERR_MAJOR_BAD + i;
98 if ((m = curl_multi_init()) == NULL) {
99 fprintf(stderr, "curl_multi_init() failed\n");
100 for(i=0; i < NUM_HANDLES; i++) {
101 curl_easy_cleanup(curl[i]);
103 curl_global_cleanup();
104 return TEST_ERR_MAJOR_BAD;
107 if ((res = (int)curl_multi_add_handle(m, curl[current])) != CURLM_OK) {
108 fprintf(stderr, "curl_multi_add_handle() failed, "
109 "with code %d\n", res);
110 curl_multi_cleanup(m);
111 for(i=0; i < NUM_HANDLES; i++) {
112 curl_easy_cleanup(curl[i]);
114 curl_global_cleanup();
115 return TEST_ERR_MAJOR_BAD;
119 ml_start = tutil_tvnow();
121 fprintf(stderr, "Start at URL 0\n");
126 struct timeval interval;
129 interval.tv_usec = 0;
131 if (tutil_tvdiff(tutil_tvnow(), ml_start) >
132 MAIN_LOOP_HANG_TIMEOUT) {
137 mp_start = tutil_tvnow();
139 while (res == CURLM_CALL_MULTI_PERFORM) {
140 res = (int)curl_multi_perform(m, &running);
141 if (tutil_tvdiff(tutil_tvnow(), mp_start) >
142 MULTI_PERFORM_HANG_TIMEOUT) {
148 /* NOTE: this code does not remove the handle from the multi handle
149 here, which would be the nice, sane and documented way of working.
150 This however tests that the API survives this abuse gracefully. */
151 curl_easy_cleanup(curl[current]);
153 if(++current < NUM_HANDLES) {
154 fprintf(stderr, "Advancing to URL %d\n", current);
156 /* first remove the only handle we use */
157 curl_multi_remove_handle(m, curl[0]);
159 /* make us re-use the same handle all the time, and try resetting
160 the handle first too */
161 curl_easy_reset(curl[0]);
162 test_setopt(curl[0], CURLOPT_URL, URL);
163 test_setopt(curl[0], CURLOPT_VERBOSE, 1L);
166 res = (int)curl_multi_add_handle(m, curl[0]);
168 res = (int)curl_multi_add_handle(m, curl[current]);
171 fprintf(stderr, "add handle failed: %d.\n", res);
177 done = TRUE; /* bail out */
181 if (mp_timedout || done)
184 if (res != CURLM_OK) {
185 fprintf(stderr, "not okay???\n");
194 if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) {
195 fprintf(stderr, "unexpected failured of fdset.\n");
200 if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) {
201 fprintf(stderr, "bad select??\n");
206 res = CURLM_CALL_MULTI_PERFORM;
209 if (ml_timedout || mp_timedout) {
210 if (ml_timedout) fprintf(stderr, "ml_timedout\n");
211 if (mp_timedout) fprintf(stderr, "mp_timedout\n");
212 fprintf(stderr, "ABORTING TEST, since it seems "
213 "that it would have run forever.\n");
214 res = TEST_ERR_RUNS_FOREVER;
222 /* get NUM_HANDLES easy handles */
223 for(i=0; i < NUM_HANDLES; i++) {
226 curl_multi_remove_handle(m, curl[i]);
228 curl_easy_cleanup(curl[i]);
232 curl_multi_cleanup(m);
234 curl_global_cleanup();