aboutsummaryrefslogtreecommitdiff
path: root/lib/sendf.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2008-01-08 14:52:05 +0000
committerDaniel Stenberg <daniel@haxx.se>2008-01-08 14:52:05 +0000
commitde23b98522991dbc1f2c184216d9f73bead83895 (patch)
treea0fe7c7ee352274f5d1adbc299a806575142c2a6 /lib/sendf.c
parent5e1c9e90d9a12033b1f1a4d09f2864580a662471 (diff)
Introducing curl_easy_pause() and new magic return codes for both the read
and the write callbacks that now can make a connection's reading and/or writing get paused.
Diffstat (limited to 'lib/sendf.c')
-rw-r--r--lib/sendf.c74
1 files changed, 71 insertions, 3 deletions
diff --git a/lib/sendf.c b/lib/sendf.c
index b33277ac3..32a8655b2 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -376,6 +376,36 @@ CURLcode Curl_write(struct connectdata *conn,
return retcode;
}
+static CURLcode pausewrite(struct SessionHandle *data,
+ int type, /* what type of data */
+ char *ptr,
+ size_t len)
+{
+ /* signalled to pause sending on this connection, but since we have data
+ we want to send we need to dup it to save a copy for when the sending
+ is again enabled */
+ struct SingleRequest *k = &data->req;
+ char *dupl = malloc(len);
+ if(!dupl)
+ return CURLE_OUT_OF_MEMORY;
+
+ memcpy(dupl, ptr, len);
+
+ /* store this information in the state struct for later use */
+ data->state.tempwrite = dupl;
+ data->state.tempwritesize = len;
+ data->state.tempwritetype = type;
+
+ /* mark the connection as RECV paused */
+ k->keepon |= KEEP_READ_PAUSE;
+
+ DEBUGF(infof(data, "Pausing with %d bytes in buffer for type %02x\n",
+ (int)len, type));
+
+ return CURLE_OK;
+}
+
+
/* client_write() sends data to the write callback(s)
The bit pattern defines to what "streams" to write to. Body and/or header.
@@ -390,8 +420,37 @@ CURLcode Curl_client_write(struct connectdata *conn,
size_t wrote;
if(data->state.cancelled) {
- /* We just suck everything into a black hole */
- return CURLE_OK;
+ /* We just suck everything into a black hole */
+ return CURLE_OK;
+ }
+
+ /* If reading is actually paused, we're forced to append this chunk of data
+ to the already held data, but only if it is the same type as otherwise it
+ can't work and it'll return error instead. */
+ if(data->req.keepon & KEEP_READ_PAUSE) {
+ size_t newlen;
+ char *newptr;
+ if(type != data->state.tempwritetype)
+ /* major internal confusion */
+ return CURLE_RECV_ERROR;
+
+ /* figure out the new size of the data to save */
+ newlen = len + data->state.tempwritesize;
+ /* allocate the new memory area */
+ newptr = malloc(newlen);
+ if(!newptr)
+ return CURLE_OUT_OF_MEMORY;
+ /* copy the previously held data to the new area */
+ memcpy(newptr, data->state.tempwrite, data->state.tempwritesize);
+ /* copy the new data to the end of the new area */
+ memcpy(newptr + data->state.tempwritesize, ptr, len);
+ /* free the old data */
+ free(data->state.tempwrite);
+ /* update the pointer and the size */
+ data->state.tempwrite = newptr;
+ data->state.tempwritesize = newlen;
+
+ return CURLE_OK;
}
if(0 == len)
@@ -422,8 +481,11 @@ CURLcode Curl_client_write(struct connectdata *conn,
wrote = len;
}
+ if(CURL_WRITEFUNC_PAUSE == wrote)
+ return pausewrite(data, type, ptr, len);
+
if(wrote != len) {
- failf (data, "Failed writing body");
+ failf(data, "Failed writing body (%d != %d)", (int)wrote, (int)len);
return CURLE_WRITE_ERROR;
}
}
@@ -441,6 +503,12 @@ CURLcode Curl_client_write(struct connectdata *conn,
regardless of the ftp transfer mode (ASCII/Image) */
wrote = writeit(ptr, 1, len, data->set.writeheader);
+ if(CURL_WRITEFUNC_PAUSE == wrote)
+ /* here we pass in the HEADER bit only since if this was body as well
+ then it was passed already and clearly that didn't trigger the pause,
+ so this is saved for later with the HEADER bit only */
+ return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
+
if(wrote != len) {
failf (data, "Failed writing header");
return CURLE_WRITE_ERROR;