1 | /*************************************************************************** |
2 | * _ _ ____ _ |
3 | * Project ___| | | | _ \| | |
4 | * / __| | | | |_) | | |
5 | * | (__| |_| | _ <| |___ |
6 | * \___|\___/|_| \_\_____| |
7 | * |
8 | * Copyright (C) 1998 - 2020, 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 https://curl.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 | * This code sets up multiple easy handles that transfer a single file from |
24 | * the same URL, in a serial manner after each other. Due to the connection |
25 | * sharing within the multi handle all transfers are performed on the same |
26 | * persistent connection. |
27 | * |
28 | * This source code is used for lib526, lib527 and lib532 with only #ifdefs |
29 | * controlling the small differences. |
30 | * |
31 | * - lib526 closes all easy handles after |
32 | * they all have transferred the file over the single connection |
33 | * - lib527 closes each easy handle after each single transfer. |
34 | * - lib532 uses only a single easy handle that is removed, reset and then |
35 | * re-added for each transfer |
36 | * |
37 | * Test case 526, 527 and 532 use FTP, while test 528 uses the lib526 tool but |
38 | * with HTTP. |
39 | */ |
40 | |
41 | #include "test.h" |
42 | |
43 | #include <fcntl.h> |
44 | |
45 | #include "testutil.h" |
46 | #include "warnless.h" |
47 | #include "memdebug.h" |
48 | |
49 | #define TEST_HANG_TIMEOUT 60 * 1000 |
50 | |
51 | #define NUM_HANDLES 4 |
52 | |
53 | int test(char *URL) |
54 | { |
55 | int res = 0; |
56 | CURL *curl[NUM_HANDLES]; |
57 | int running; |
58 | CURLM *m = NULL; |
59 | int current = 0; |
60 | int i; |
61 | |
62 | for(i = 0; i < NUM_HANDLES; i++) |
63 | curl[i] = NULL; |
64 | |
65 | start_test_timing(); |
66 | |
67 | global_init(CURL_GLOBAL_ALL); |
68 | |
69 | /* get NUM_HANDLES easy handles */ |
70 | for(i = 0; i < NUM_HANDLES; i++) { |
71 | easy_init(curl[i]); |
72 | /* specify target */ |
73 | easy_setopt(curl[i], CURLOPT_URL, URL); |
74 | /* go verbose */ |
75 | easy_setopt(curl[i], CURLOPT_VERBOSE, 1L); |
76 | } |
77 | |
78 | multi_init(m); |
79 | |
80 | multi_add_handle(m, curl[current]); |
81 | |
82 | fprintf(stderr, "Start at URL 0\n" ); |
83 | |
84 | for(;;) { |
85 | struct timeval interval; |
86 | fd_set rd, wr, exc; |
87 | int maxfd = -99; |
88 | |
89 | interval.tv_sec = 1; |
90 | interval.tv_usec = 0; |
91 | |
92 | multi_perform(m, &running); |
93 | |
94 | abort_on_test_timeout(); |
95 | |
96 | if(!running) { |
97 | #ifdef LIB527 |
98 | /* NOTE: this code does not remove the handle from the multi handle |
99 | here, which would be the nice, sane and documented way of working. |
100 | This however tests that the API survives this abuse gracefully. */ |
101 | curl_easy_cleanup(curl[current]); |
102 | curl[current] = NULL; |
103 | #endif |
104 | if(++current < NUM_HANDLES) { |
105 | fprintf(stderr, "Advancing to URL %d\n" , current); |
106 | #ifdef LIB532 |
107 | /* first remove the only handle we use */ |
108 | curl_multi_remove_handle(m, curl[0]); |
109 | |
110 | /* make us re-use the same handle all the time, and try resetting |
111 | the handle first too */ |
112 | curl_easy_reset(curl[0]); |
113 | easy_setopt(curl[0], CURLOPT_URL, URL); |
114 | /* go verbose */ |
115 | easy_setopt(curl[0], CURLOPT_VERBOSE, 1L); |
116 | |
117 | /* re-add it */ |
118 | multi_add_handle(m, curl[0]); |
119 | #else |
120 | multi_add_handle(m, curl[current]); |
121 | #endif |
122 | } |
123 | else { |
124 | break; /* done */ |
125 | } |
126 | } |
127 | |
128 | FD_ZERO(&rd); |
129 | FD_ZERO(&wr); |
130 | FD_ZERO(&exc); |
131 | |
132 | multi_fdset(m, &rd, &wr, &exc, &maxfd); |
133 | |
134 | /* At this point, maxfd is guaranteed to be greater or equal than -1. */ |
135 | |
136 | select_test(maxfd + 1, &rd, &wr, &exc, &interval); |
137 | |
138 | abort_on_test_timeout(); |
139 | } |
140 | |
141 | test_cleanup: |
142 | |
143 | #if defined(LIB526) |
144 | |
145 | /* test 526 and 528 */ |
146 | /* proper cleanup sequence - type PB */ |
147 | |
148 | for(i = 0; i < NUM_HANDLES; i++) { |
149 | curl_multi_remove_handle(m, curl[i]); |
150 | curl_easy_cleanup(curl[i]); |
151 | } |
152 | curl_multi_cleanup(m); |
153 | curl_global_cleanup(); |
154 | |
155 | #elif defined(LIB527) |
156 | |
157 | /* test 527 */ |
158 | |
159 | /* Upon non-failure test flow the easy's have already been cleanup'ed. In |
160 | case there is a failure we arrive here with easy's that have not been |
161 | cleanup'ed yet, in this case we have to cleanup them or otherwise these |
162 | will be leaked, let's use undocumented cleanup sequence - type UB */ |
163 | |
164 | if(res) |
165 | for(i = 0; i < NUM_HANDLES; i++) |
166 | curl_easy_cleanup(curl[i]); |
167 | |
168 | curl_multi_cleanup(m); |
169 | curl_global_cleanup(); |
170 | |
171 | #elif defined(LIB532) |
172 | |
173 | /* test 532 */ |
174 | /* undocumented cleanup sequence - type UB */ |
175 | |
176 | for(i = 0; i < NUM_HANDLES; i++) |
177 | curl_easy_cleanup(curl[i]); |
178 | curl_multi_cleanup(m); |
179 | curl_global_cleanup(); |
180 | |
181 | #endif |
182 | |
183 | return res; |
184 | } |
185 | |