diff options
author | Daniel Stenberg <daniel@haxx.se> | 2017-03-27 12:14:57 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2017-03-28 13:27:49 +0200 |
commit | 452203341d6e97b8f52f9a886046d9fdb96346a9 (patch) | |
tree | c5aa7fa5e29da5a1799123703be46f28d0491fc1 /tests/libtest | |
parent | 7975d10cf8a3fe9b35867509b9ef10d06614eb3a (diff) |
pause: handle mixed types of data when paused
When receiving chunked encoded data with trailers, and the write
callback returns PAUSE, there might be both body and header to store to
resend on unpause. Previously libcurl returned error for that case.
Added test case 1540 to verify.
Reported-by: Stephen Toub
Fixes #1354
Closes #1357
Diffstat (limited to 'tests/libtest')
-rw-r--r-- | tests/libtest/Makefile.inc | 5 | ||||
-rw-r--r-- | tests/libtest/lib1540.c | 121 |
2 files changed, 126 insertions, 0 deletions
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc index 66628aae1..d85956d8b 100644 --- a/tests/libtest/Makefile.inc +++ b/tests/libtest/Makefile.inc @@ -25,6 +25,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \ lib1520 \ lib1525 lib1526 lib1527 lib1528 lib1529 lib1530 lib1531 lib1532 lib1533 \ lib1534 lib1535 lib1536 \ + lib1540 \ lib1900 \ lib2033 @@ -412,6 +413,10 @@ lib1536_SOURCES = lib1536.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) lib1536_LDADD = $(TESTUTIL_LIBS) lib1536_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1536 +lib1540_SOURCES = lib1540.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) +lib1540_LDADD = $(TESTUTIL_LIBS) +lib1540_CPPFLAGS = $(AM_CPPFLAGS) + lib1900_SOURCES = lib1900.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) lib1900_LDADD = $(TESTUTIL_LIBS) lib1900_CPPFLAGS = $(AM_CPPFLAGS) diff --git a/tests/libtest/lib1540.c b/tests/libtest/lib1540.c new file mode 100644 index 000000000..86ba085ca --- /dev/null +++ b/tests/libtest/lib1540.c @@ -0,0 +1,121 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "test.h" + +#include "testutil.h" +#include "warnless.h" +#include "memdebug.h" + +struct transfer_status { + CURL *easy; + int halted; + int counter; /* count write callback invokes */ + int please; /* number of times xferinfo is called while halted */ +}; + +static int please_continue(void *userp, + curl_off_t dltotal, + curl_off_t dlnow, + curl_off_t ultotal, + curl_off_t ulnow) +{ + struct transfer_status *st = (struct transfer_status *)userp; + (void)dltotal; + (void)dlnow; + (void)ultotal; + (void)ulnow; + if(st->halted) { + st->please++; + if(st->please == 2) { + /* waited enough, unpause! */ + curl_easy_pause(st->easy, CURLPAUSE_CONT); + } + } + fprintf(stderr, "xferinfo: paused %d\n", st->halted); + return 0; /* go on */ +} + +static size_t header_callback(void *ptr, size_t size, size_t nmemb, + void *userp) +{ + size_t len = size * nmemb; + (void)userp; + (void)fwrite(ptr, size, nmemb, stdout); + return len; +} + +static size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userp) +{ + struct transfer_status *st = (struct transfer_status *)userp; + size_t len = size * nmemb; + st->counter++; + if(st->counter > 1) { + /* the first call puts us on pause, so subsequent calls are after + unpause */ + fwrite(ptr, size, nmemb, stdout); + return len; + } + printf("Got %d bytes but pausing!\n", (int)len); + st->halted = 1; + return CURL_WRITEFUNC_PAUSE; +} + +#define TEST_HANG_TIMEOUT 60 * 1000 + +int test(char *URL) +{ + CURL *curls = NULL; + int i = 0; + int res = 0; + struct transfer_status st; + + start_test_timing(); + + memset(&st, 0, sizeof(st)); + + global_init(CURL_GLOBAL_ALL); + + easy_init(curls); + st.easy = curls; /* to allow callbacks access */ + + easy_setopt(curls, CURLOPT_URL, URL); + easy_setopt(curls, CURLOPT_WRITEFUNCTION, write_callback); + easy_setopt(curls, CURLOPT_WRITEDATA, &st); + easy_setopt(curls, CURLOPT_HEADERFUNCTION, header_callback); + easy_setopt(curls, CURLOPT_HEADERDATA, &st); + + easy_setopt(curls, CURLOPT_XFERINFOFUNCTION, please_continue); + easy_setopt(curls, CURLOPT_XFERINFODATA, &st); + easy_setopt(curls, CURLOPT_NOPROGRESS, 0L); + + res = curl_easy_perform(curls); + +test_cleanup: + + curl_easy_cleanup(curls); + curl_global_cleanup(); + + if(res) + i = res; + + return i; /* return the final return code */ +} |