113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci 2513498266Sopenharmony_ci#if !defined(LIB670) && !defined(LIB671) 2613498266Sopenharmony_ci#define CURL_DISABLE_DEPRECATION /* Using and testing the form api */ 2713498266Sopenharmony_ci#endif 2813498266Sopenharmony_ci 2913498266Sopenharmony_ci#include "test.h" 3013498266Sopenharmony_ci 3113498266Sopenharmony_ci#include <time.h> 3213498266Sopenharmony_ci 3313498266Sopenharmony_ci#include "memdebug.h" 3413498266Sopenharmony_ci 3513498266Sopenharmony_ci#define PAUSE_TIME 5 3613498266Sopenharmony_ci 3713498266Sopenharmony_ci 3813498266Sopenharmony_cistatic const char name[] = "field"; 3913498266Sopenharmony_ci 4013498266Sopenharmony_cistruct ReadThis { 4113498266Sopenharmony_ci CURL *easy; 4213498266Sopenharmony_ci time_t origin; 4313498266Sopenharmony_ci int count; 4413498266Sopenharmony_ci}; 4513498266Sopenharmony_ci 4613498266Sopenharmony_ci 4713498266Sopenharmony_cistatic size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp) 4813498266Sopenharmony_ci{ 4913498266Sopenharmony_ci struct ReadThis *pooh = (struct ReadThis *) userp; 5013498266Sopenharmony_ci time_t delta; 5113498266Sopenharmony_ci 5213498266Sopenharmony_ci if(size * nmemb < 1) 5313498266Sopenharmony_ci return 0; 5413498266Sopenharmony_ci 5513498266Sopenharmony_ci switch(pooh->count++) { 5613498266Sopenharmony_ci case 0: 5713498266Sopenharmony_ci *ptr = '\x41'; /* ASCII A. */ 5813498266Sopenharmony_ci return 1; 5913498266Sopenharmony_ci case 1: 6013498266Sopenharmony_ci pooh->origin = time(NULL); 6113498266Sopenharmony_ci return CURL_READFUNC_PAUSE; 6213498266Sopenharmony_ci case 2: 6313498266Sopenharmony_ci delta = time(NULL) - pooh->origin; 6413498266Sopenharmony_ci *ptr = delta >= PAUSE_TIME? '\x42': '\x41'; /* ASCII A or B. */ 6513498266Sopenharmony_ci return 1; 6613498266Sopenharmony_ci case 3: 6713498266Sopenharmony_ci return 0; 6813498266Sopenharmony_ci } 6913498266Sopenharmony_ci fprintf(stderr, "Read callback called after EOF\n"); 7013498266Sopenharmony_ci exit(1); 7113498266Sopenharmony_ci} 7213498266Sopenharmony_ci 7313498266Sopenharmony_ci#if !defined(LIB670) && !defined(LIB672) 7413498266Sopenharmony_cistatic int xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow, 7513498266Sopenharmony_ci curl_off_t ultotal, curl_off_t ulnow) 7613498266Sopenharmony_ci{ 7713498266Sopenharmony_ci struct ReadThis *pooh = (struct ReadThis *) clientp; 7813498266Sopenharmony_ci 7913498266Sopenharmony_ci (void) dltotal; 8013498266Sopenharmony_ci (void) dlnow; 8113498266Sopenharmony_ci (void) ultotal; 8213498266Sopenharmony_ci (void) ulnow; 8313498266Sopenharmony_ci 8413498266Sopenharmony_ci if(pooh->origin) { 8513498266Sopenharmony_ci time_t delta = time(NULL) - pooh->origin; 8613498266Sopenharmony_ci 8713498266Sopenharmony_ci if(delta >= 4 * PAUSE_TIME) { 8813498266Sopenharmony_ci fprintf(stderr, "unpausing failed: drain problem?\n"); 8913498266Sopenharmony_ci return CURLE_ABORTED_BY_CALLBACK; 9013498266Sopenharmony_ci } 9113498266Sopenharmony_ci 9213498266Sopenharmony_ci if(delta >= PAUSE_TIME) 9313498266Sopenharmony_ci curl_easy_pause(pooh->easy, CURLPAUSE_CONT); 9413498266Sopenharmony_ci } 9513498266Sopenharmony_ci 9613498266Sopenharmony_ci return 0; 9713498266Sopenharmony_ci} 9813498266Sopenharmony_ci#endif 9913498266Sopenharmony_ci 10013498266Sopenharmony_ciint test(char *URL) 10113498266Sopenharmony_ci{ 10213498266Sopenharmony_ci#if defined(LIB670) || defined(LIB671) 10313498266Sopenharmony_ci curl_mime *mime = NULL; 10413498266Sopenharmony_ci curl_mimepart *part; 10513498266Sopenharmony_ci#else 10613498266Sopenharmony_ci CURLFORMcode formrc; 10713498266Sopenharmony_ci struct curl_httppost *formpost = NULL; 10813498266Sopenharmony_ci struct curl_httppost *lastptr = NULL; 10913498266Sopenharmony_ci#endif 11013498266Sopenharmony_ci#if defined(LIB670) || defined(LIB672) 11113498266Sopenharmony_ci CURLM *multi = NULL; 11213498266Sopenharmony_ci CURLMcode mres; 11313498266Sopenharmony_ci CURLMsg *msg; 11413498266Sopenharmony_ci int msgs_left; 11513498266Sopenharmony_ci int still_running = 0; 11613498266Sopenharmony_ci#endif 11713498266Sopenharmony_ci 11813498266Sopenharmony_ci struct ReadThis pooh; 11913498266Sopenharmony_ci CURLcode result; 12013498266Sopenharmony_ci int res = TEST_ERR_FAILURE; 12113498266Sopenharmony_ci 12213498266Sopenharmony_ci /* 12313498266Sopenharmony_ci * Check proper pausing/unpausing from a mime or form read callback. 12413498266Sopenharmony_ci */ 12513498266Sopenharmony_ci 12613498266Sopenharmony_ci if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { 12713498266Sopenharmony_ci fprintf(stderr, "curl_global_init() failed\n"); 12813498266Sopenharmony_ci return TEST_ERR_MAJOR_BAD; 12913498266Sopenharmony_ci } 13013498266Sopenharmony_ci 13113498266Sopenharmony_ci pooh.origin = (time_t) 0; 13213498266Sopenharmony_ci pooh.count = 0; 13313498266Sopenharmony_ci pooh.easy = curl_easy_init(); 13413498266Sopenharmony_ci 13513498266Sopenharmony_ci /* First set the URL that is about to receive our POST. */ 13613498266Sopenharmony_ci test_setopt(pooh.easy, CURLOPT_URL, URL); 13713498266Sopenharmony_ci 13813498266Sopenharmony_ci /* get verbose debug output please */ 13913498266Sopenharmony_ci test_setopt(pooh.easy, CURLOPT_VERBOSE, 1L); 14013498266Sopenharmony_ci 14113498266Sopenharmony_ci /* include headers in the output */ 14213498266Sopenharmony_ci test_setopt(pooh.easy, CURLOPT_HEADER, 1L); 14313498266Sopenharmony_ci 14413498266Sopenharmony_ci#if defined(LIB670) || defined(LIB671) 14513498266Sopenharmony_ci /* Build the mime tree. */ 14613498266Sopenharmony_ci mime = curl_mime_init(pooh.easy); 14713498266Sopenharmony_ci part = curl_mime_addpart(mime); 14813498266Sopenharmony_ci result = curl_mime_name(part, name); 14913498266Sopenharmony_ci if(result) { 15013498266Sopenharmony_ci fprintf(stderr, 15113498266Sopenharmony_ci "Something went wrong when building the mime structure: %d\n", 15213498266Sopenharmony_ci (int) result); 15313498266Sopenharmony_ci goto test_cleanup; 15413498266Sopenharmony_ci } 15513498266Sopenharmony_ci 15613498266Sopenharmony_ci res = curl_mime_data_cb(part, (curl_off_t) 2, read_callback, 15713498266Sopenharmony_ci NULL, NULL, &pooh); 15813498266Sopenharmony_ci 15913498266Sopenharmony_ci /* Bind mime data to its easy handle. */ 16013498266Sopenharmony_ci if(!res) 16113498266Sopenharmony_ci test_setopt(pooh.easy, CURLOPT_MIMEPOST, mime); 16213498266Sopenharmony_ci#else 16313498266Sopenharmony_ci /* Build the form. */ 16413498266Sopenharmony_ci formrc = curl_formadd(&formpost, &lastptr, 16513498266Sopenharmony_ci CURLFORM_COPYNAME, name, 16613498266Sopenharmony_ci CURLFORM_STREAM, &pooh, 16713498266Sopenharmony_ci CURLFORM_CONTENTLEN, (curl_off_t) 2, 16813498266Sopenharmony_ci CURLFORM_END); 16913498266Sopenharmony_ci if(formrc) { 17013498266Sopenharmony_ci fprintf(stderr, "curl_formadd() = %d\n", (int) formrc); 17113498266Sopenharmony_ci goto test_cleanup; 17213498266Sopenharmony_ci } 17313498266Sopenharmony_ci 17413498266Sopenharmony_ci /* We want to use our own read function. */ 17513498266Sopenharmony_ci test_setopt(pooh.easy, CURLOPT_READFUNCTION, read_callback); 17613498266Sopenharmony_ci 17713498266Sopenharmony_ci /* Send a multi-part formpost. */ 17813498266Sopenharmony_ci test_setopt(pooh.easy, CURLOPT_HTTPPOST, formpost); 17913498266Sopenharmony_ci#endif 18013498266Sopenharmony_ci 18113498266Sopenharmony_ci#if defined(LIB670) || defined(LIB672) 18213498266Sopenharmony_ci /* Use the multi interface. */ 18313498266Sopenharmony_ci multi = curl_multi_init(); 18413498266Sopenharmony_ci mres = curl_multi_add_handle(multi, pooh.easy); 18513498266Sopenharmony_ci while(!mres) { 18613498266Sopenharmony_ci struct timeval timeout; 18713498266Sopenharmony_ci int rc = 0; 18813498266Sopenharmony_ci fd_set fdread; 18913498266Sopenharmony_ci fd_set fdwrite; 19013498266Sopenharmony_ci fd_set fdexcept; 19113498266Sopenharmony_ci int maxfd = -1; 19213498266Sopenharmony_ci 19313498266Sopenharmony_ci mres = curl_multi_perform(multi, &still_running); 19413498266Sopenharmony_ci if(!still_running || mres != CURLM_OK) 19513498266Sopenharmony_ci break; 19613498266Sopenharmony_ci 19713498266Sopenharmony_ci if(pooh.origin) { 19813498266Sopenharmony_ci time_t delta = time(NULL) - pooh.origin; 19913498266Sopenharmony_ci 20013498266Sopenharmony_ci if(delta >= 4 * PAUSE_TIME) { 20113498266Sopenharmony_ci fprintf(stderr, "unpausing failed: drain problem?\n"); 20213498266Sopenharmony_ci res = CURLE_OPERATION_TIMEDOUT; 20313498266Sopenharmony_ci break; 20413498266Sopenharmony_ci } 20513498266Sopenharmony_ci 20613498266Sopenharmony_ci if(delta >= PAUSE_TIME) 20713498266Sopenharmony_ci curl_easy_pause(pooh.easy, CURLPAUSE_CONT); 20813498266Sopenharmony_ci } 20913498266Sopenharmony_ci 21013498266Sopenharmony_ci FD_ZERO(&fdread); 21113498266Sopenharmony_ci FD_ZERO(&fdwrite); 21213498266Sopenharmony_ci FD_ZERO(&fdexcept); 21313498266Sopenharmony_ci timeout.tv_sec = 0; 21413498266Sopenharmony_ci timeout.tv_usec = 1000000 * PAUSE_TIME / 10; 21513498266Sopenharmony_ci mres = curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcept, &maxfd); 21613498266Sopenharmony_ci if(mres) 21713498266Sopenharmony_ci break; 21813498266Sopenharmony_ci#if defined(_WIN32) 21913498266Sopenharmony_ci if(maxfd == -1) 22013498266Sopenharmony_ci Sleep(100); 22113498266Sopenharmony_ci else 22213498266Sopenharmony_ci#endif 22313498266Sopenharmony_ci rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcept, &timeout); 22413498266Sopenharmony_ci if(rc == -1) { 22513498266Sopenharmony_ci fprintf(stderr, "Select error\n"); 22613498266Sopenharmony_ci break; 22713498266Sopenharmony_ci } 22813498266Sopenharmony_ci } 22913498266Sopenharmony_ci 23013498266Sopenharmony_ci if(mres != CURLM_OK) 23113498266Sopenharmony_ci for(;;) { 23213498266Sopenharmony_ci msg = curl_multi_info_read(multi, &msgs_left); 23313498266Sopenharmony_ci if(!msg) 23413498266Sopenharmony_ci break; 23513498266Sopenharmony_ci if(msg->msg == CURLMSG_DONE) { 23613498266Sopenharmony_ci result = msg->data.result; 23713498266Sopenharmony_ci res = (int) result; 23813498266Sopenharmony_ci } 23913498266Sopenharmony_ci } 24013498266Sopenharmony_ci 24113498266Sopenharmony_ci curl_multi_remove_handle(multi, pooh.easy); 24213498266Sopenharmony_ci curl_multi_cleanup(multi); 24313498266Sopenharmony_ci 24413498266Sopenharmony_ci#else 24513498266Sopenharmony_ci /* Use the easy interface. */ 24613498266Sopenharmony_ci test_setopt(pooh.easy, CURLOPT_XFERINFODATA, &pooh); 24713498266Sopenharmony_ci test_setopt(pooh.easy, CURLOPT_XFERINFOFUNCTION, xferinfo); 24813498266Sopenharmony_ci test_setopt(pooh.easy, CURLOPT_NOPROGRESS, 0L); 24913498266Sopenharmony_ci result = curl_easy_perform(pooh.easy); 25013498266Sopenharmony_ci res = (int) result; 25113498266Sopenharmony_ci#endif 25213498266Sopenharmony_ci 25313498266Sopenharmony_ci 25413498266Sopenharmony_citest_cleanup: 25513498266Sopenharmony_ci curl_easy_cleanup(pooh.easy); 25613498266Sopenharmony_ci#if defined(LIB670) || defined(LIB671) 25713498266Sopenharmony_ci curl_mime_free(mime); 25813498266Sopenharmony_ci#else 25913498266Sopenharmony_ci curl_formfree(formpost); 26013498266Sopenharmony_ci#endif 26113498266Sopenharmony_ci 26213498266Sopenharmony_ci curl_global_cleanup(); 26313498266Sopenharmony_ci return res; 26413498266Sopenharmony_ci} 265