aboutsummaryrefslogtreecommitdiff
path: root/lib/easy.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 /lib/easy.c
parent7975d10cf8a3fe9b35867509b9ef10d06614eb3a (diff)
downloadgnurl-452203341d6e97b8f52f9a886046d9fdb96346a9.tar.gz
gnurl-452203341d6e97b8f52f9a886046d9fdb96346a9.tar.bz2
gnurl-452203341d6e97b8f52f9a886046d9fdb96346a9.zip
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 'lib/easy.c')
-rw-r--r--lib/easy.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/lib/easy.c b/lib/easy.c
index cf65af911..b3159d1a2 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * 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
@@ -1011,19 +1011,32 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
/* put it back in the keepon */
k->keepon = newstate;
- if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) {
- /* we have a buffer for sending that we now seem to be able to deliver
- since the receive pausing is lifted! */
-
- /* get the pointer in local copy since the function may return PAUSE
- again and then we'll get a new copy allocted and stored in
- the tempwrite variables */
- char *tempwrite = data->state.tempwrite;
-
- data->state.tempwrite = NULL;
- result = Curl_client_chop_write(data->easy_conn, data->state.tempwritetype,
- tempwrite, data->state.tempwritesize);
- free(tempwrite);
+ if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempcount) {
+ /* there are buffers for sending that can be delivered as the receive
+ pausing is lifted! */
+ unsigned int i;
+ unsigned int count = data->state.tempcount;
+ struct tempbuf writebuf[3]; /* there can only be three */
+
+ /* copy the structs to allow for immediate re-pausing */
+ for(i=0; i < data->state.tempcount; i++) {
+ writebuf[i] = data->state.tempwrite[i];
+ data->state.tempwrite[i].buf = NULL;
+ }
+ data->state.tempcount = 0;
+
+ for(i=0; i < count; i++) {
+ /* even if one function returns error, this loops through and frees all
+ buffers */
+ if(!result)
+ result = Curl_client_chop_write(data->easy_conn,
+ writebuf[i].type,
+ writebuf[i].buf,
+ writebuf[i].len);
+ free(writebuf[i].buf);
+ }
+ if(result)
+ return result;
}
/* if there's no error and we're not pausing both directions, we want