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