1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2017, 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.haxx.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 #include "test.h" 23 24 #include "testutil.h" 25 #include "warnless.h" 26 #include "memdebug.h" 27 28 struct transfer_status { 29 CURL *easy; 30 int halted; 31 int counter; /* count write callback invokes */ 32 int please; /* number of times xferinfo is called while halted */ 33 }; 34 35 static int please_continue(void *userp, 36 curl_off_t dltotal, 37 curl_off_t dlnow, 38 curl_off_t ultotal, 39 curl_off_t ulnow) 40 { 41 struct transfer_status *st = (struct transfer_status *)userp; 42 (void)dltotal; 43 (void)dlnow; 44 (void)ultotal; 45 (void)ulnow; 46 if(st->halted) { 47 st->please++; 48 if(st->please == 2) { 49 /* waited enough, unpause! */ 50 curl_easy_pause(st->easy, CURLPAUSE_CONT); 51 } 52 } 53 fprintf(stderr, "xferinfo: paused %d\n", st->halted); 54 return 0; /* go on */ 55 } 56 57 static size_t header_callback(void *ptr, size_t size, size_t nmemb, 58 void *userp) 59 { 60 size_t len = size * nmemb; 61 (void)userp; 62 (void)fwrite(ptr, size, nmemb, stdout); 63 return len; 64 } 65 66 static size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userp) 67 { 68 struct transfer_status *st = (struct transfer_status *)userp; 69 size_t len = size * nmemb; 70 st->counter++; 71 if(st->counter > 1) { 72 /* the first call puts us on pause, so subsequent calls are after 73 unpause */ 74 fwrite(ptr, size, nmemb, stdout); 75 return len; 76 } 77 printf("Got %d bytes but pausing!\n", (int)len); 78 st->halted = 1; 79 return CURL_WRITEFUNC_PAUSE; 80 } 81 82 #define TEST_HANG_TIMEOUT 60 * 1000 83 84 int test(char *URL) 85 { 86 CURL *curls = NULL; 87 int i = 0; 88 int res = 0; 89 struct transfer_status st; 90 91 start_test_timing(); 92 93 memset(&st, 0, sizeof(st)); 94 95 global_init(CURL_GLOBAL_ALL); 96 97 easy_init(curls); 98 st.easy = curls; /* to allow callbacks access */ 99 100 easy_setopt(curls, CURLOPT_URL, URL); 101 easy_setopt(curls, CURLOPT_WRITEFUNCTION, write_callback); 102 easy_setopt(curls, CURLOPT_WRITEDATA, &st); 103 easy_setopt(curls, CURLOPT_HEADERFUNCTION, header_callback); 104 easy_setopt(curls, CURLOPT_HEADERDATA, &st); 105 106 easy_setopt(curls, CURLOPT_XFERINFOFUNCTION, please_continue); 107 easy_setopt(curls, CURLOPT_XFERINFODATA, &st); 108 easy_setopt(curls, CURLOPT_NOPROGRESS, 0L); 109 110 res = curl_easy_perform(curls); 111 112 test_cleanup: 113 114 curl_easy_cleanup(curls); 115 curl_global_cleanup(); 116 117 if(res) 118 i = res; 119 120 return i; /* return the final return code */ 121 } 122