aboutsummaryrefslogtreecommitdiff
path: root/tests/libtest/lib1540.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2017-03-27 12:14:57 +0200
committerDaniel Stenberg <daniel@haxx.se>2017-03-28 13:27:49 +0200
commit452203341d6e97b8f52f9a886046d9fdb96346a9 (patch)
treec5aa7fa5e29da5a1799123703be46f28d0491fc1 /tests/libtest/lib1540.c
parent7975d10cf8a3fe9b35867509b9ef10d06614eb3a (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/lib1540.c')
-rw-r--r--tests/libtest/lib1540.c121
1 files changed, 121 insertions, 0 deletions
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 */
+}