lib670.c (6698B)
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 #include "first.h" 25 26 #include "memdebug.h" 27 28 #define PAUSE_TIME 5 29 30 struct t670_ReadThis { 31 CURL *easy; 32 time_t origin; 33 int count; 34 }; 35 36 static size_t t670_read_cb(char *ptr, size_t size, size_t nmemb, void *userp) 37 { 38 struct t670_ReadThis *pooh = (struct t670_ReadThis *) userp; 39 time_t delta; 40 41 if(size * nmemb < 1) 42 return 0; 43 44 switch(pooh->count++) { 45 case 0: 46 *ptr = '\x41'; /* ASCII A. */ 47 return 1; 48 case 1: 49 pooh->origin = time(NULL); 50 return CURL_READFUNC_PAUSE; 51 case 2: 52 delta = time(NULL) - pooh->origin; 53 *ptr = delta >= PAUSE_TIME ? '\x42' : '\x41'; /* ASCII A or B. */ 54 return 1; 55 case 3: 56 return 0; 57 } 58 curl_mfprintf(stderr, "Read callback called after EOF\n"); 59 exit(1); 60 } 61 62 static int t670_xferinfo(void *clientp, 63 curl_off_t dltotal, curl_off_t dlnow, 64 curl_off_t ultotal, curl_off_t ulnow) 65 { 66 struct t670_ReadThis *pooh = (struct t670_ReadThis *) clientp; 67 68 (void) dltotal; 69 (void) dlnow; 70 (void) ultotal; 71 (void) ulnow; 72 73 if(pooh->origin) { 74 time_t delta = time(NULL) - pooh->origin; 75 76 if(delta >= 4 * PAUSE_TIME) { 77 curl_mfprintf(stderr, "unpausing failed: drain problem?\n"); 78 return CURLE_ABORTED_BY_CALLBACK; 79 } 80 81 if(delta >= PAUSE_TIME) 82 curl_easy_pause(pooh->easy, CURLPAUSE_CONT); 83 } 84 85 return 0; 86 } 87 88 static CURLcode test_lib670(char *URL) 89 { 90 static const char testname[] = "field"; 91 92 curl_mime *mime = NULL; 93 struct curl_httppost *formpost = NULL; 94 95 struct t670_ReadThis pooh; 96 CURLcode res = TEST_ERR_FAILURE; 97 98 /* 99 * Check proper pausing/unpausing from a mime or form read callback. 100 */ 101 102 if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { 103 curl_mfprintf(stderr, "curl_global_init() failed\n"); 104 return TEST_ERR_MAJOR_BAD; 105 } 106 107 pooh.origin = (time_t) 0; 108 pooh.count = 0; 109 pooh.easy = curl_easy_init(); 110 111 /* First set the URL that is about to receive our POST. */ 112 test_setopt(pooh.easy, CURLOPT_URL, URL); 113 114 /* get verbose debug output please */ 115 test_setopt(pooh.easy, CURLOPT_VERBOSE, 1L); 116 117 /* include headers in the output */ 118 test_setopt(pooh.easy, CURLOPT_HEADER, 1L); 119 120 if(testnum == 670 || testnum == 671) { 121 curl_mimepart *part; 122 /* Build the mime tree. */ 123 mime = curl_mime_init(pooh.easy); 124 part = curl_mime_addpart(mime); 125 res = curl_mime_name(part, testname); 126 if(res != CURLE_OK) { 127 curl_mfprintf(stderr, 128 "Something went wrong when building the mime structure: %d\n", 129 res); 130 goto test_cleanup; 131 } 132 133 res = curl_mime_data_cb(part, (curl_off_t) 2, t670_read_cb, 134 NULL, NULL, &pooh); 135 136 /* Bind mime data to its easy handle. */ 137 if(res == CURLE_OK) 138 test_setopt(pooh.easy, CURLOPT_MIMEPOST, mime); 139 } 140 else { 141 struct curl_httppost *lastptr = NULL; 142 CURLFORMcode formrc; 143 /* Build the form. */ 144 formrc = curl_formadd(&formpost, &lastptr, 145 CURLFORM_COPYNAME, testname, 146 CURLFORM_STREAM, &pooh, 147 CURLFORM_CONTENTLEN, (curl_off_t) 2, 148 CURLFORM_END); 149 if(formrc) { 150 curl_mfprintf(stderr, "curl_formadd() = %d\n", (int) formrc); 151 goto test_cleanup; 152 } 153 154 /* We want to use our own read function. */ 155 test_setopt(pooh.easy, CURLOPT_READFUNCTION, t670_read_cb); 156 157 /* Send a multi-part formpost. */ 158 test_setopt(pooh.easy, CURLOPT_HTTPPOST, formpost); 159 } 160 161 if(testnum == 670 || testnum == 672) { 162 CURLMcode mres; 163 CURLM *multi; 164 /* Use the multi interface. */ 165 multi = curl_multi_init(); 166 mres = curl_multi_add_handle(multi, pooh.easy); 167 while(!mres) { 168 struct timeval timeout; 169 int rc = 0; 170 fd_set fdread; 171 fd_set fdwrite; 172 fd_set fdexcept; 173 int maxfd = -1; 174 int still_running = 0; 175 176 mres = curl_multi_perform(multi, &still_running); 177 if(!still_running || mres != CURLM_OK) 178 break; 179 180 if(pooh.origin) { 181 time_t delta = time(NULL) - pooh.origin; 182 183 if(delta >= 4 * PAUSE_TIME) { 184 curl_mfprintf(stderr, "unpausing failed: drain problem?\n"); 185 res = CURLE_OPERATION_TIMEDOUT; 186 break; 187 } 188 189 if(delta >= PAUSE_TIME) 190 curl_easy_pause(pooh.easy, CURLPAUSE_CONT); 191 } 192 193 FD_ZERO(&fdread); 194 FD_ZERO(&fdwrite); 195 FD_ZERO(&fdexcept); 196 timeout.tv_sec = 0; 197 timeout.tv_usec = 1000000 * PAUSE_TIME / 10; 198 mres = curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcept, &maxfd); 199 if(mres) 200 break; 201 #ifdef _WIN32 202 if(maxfd == -1) 203 curlx_wait_ms(100); 204 else 205 #endif 206 rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcept, &timeout); 207 if(rc == -1) { 208 curl_mfprintf(stderr, "Select error\n"); 209 break; 210 } 211 } 212 213 if(mres != CURLM_OK) 214 for(;;) { 215 int msgs_left; 216 CURLMsg *msg; 217 msg = curl_multi_info_read(multi, &msgs_left); 218 if(!msg) 219 break; 220 if(msg->msg == CURLMSG_DONE) { 221 res = msg->data.result; 222 } 223 } 224 225 curl_multi_remove_handle(multi, pooh.easy); 226 curl_multi_cleanup(multi); 227 } 228 else { 229 /* Use the easy interface. */ 230 test_setopt(pooh.easy, CURLOPT_XFERINFODATA, &pooh); 231 test_setopt(pooh.easy, CURLOPT_XFERINFOFUNCTION, t670_xferinfo); 232 test_setopt(pooh.easy, CURLOPT_NOPROGRESS, 0L); 233 res = curl_easy_perform(pooh.easy); 234 } 235 236 test_cleanup: 237 curl_easy_cleanup(pooh.easy); 238 239 if(testnum == 670 || testnum == 671) { 240 curl_mime_free(mime); 241 } 242 else { 243 curl_formfree(formpost); 244 } 245 246 curl_global_cleanup(); 247 return res; 248 }