On Fri, 5 Jun 2015, Frank Meier wrote:
The Problem is, curl believes that the server replied too early, that it replied before all request bytes have been transferred, but this isn't true. The last bytes have been sent to the server after the 2nd last call to the readfunction, but curl only "knows" that this is the case after calling the readfunction another time, which signals the EOF by returning 0. But this happens after curl already tries to read the response.
Aha. Thanks for clarifying and sorry for being slow.As for your first suggestion I agree completely. I do however suggest a slightly different fix, see attachment. It runs all the tests for me.
If I understand your problem correctly, this will fix the problem as long as the post size is known right?
So what I would like to do is signal from the readfunction that the returned bytes are the final ones, but since there is no EOF flag in the API, the only way I see is to call the readfunction twice in line to assure curls "knows" about the EOF before it tries to read the response.
That feels like a bit too much. In all except the last call, that will return new data and there's another point that needs to handle pausing and I fear that'll open the gates for lots of problems.
I would rather consider a way to introduce an EOF flag so that a callback can actually say "here are the final N bytes of data". Like for example allowing a callback to OR the return value with 0x20000000 and treat that bit as EOF. Of course that'd break all older libcurls but would be made to work with a libcurl supporting this! What would you think about that?
-- / daniel.haxx.se
From ea06bd1d912d99c89228905fb68eb5ba60891cac Mon Sep 17 00:00:00 2001 From: Daniel Stenberg <[email protected]> Date: Sun, 7 Jun 2015 23:52:34 +0200 Subject: [PATCH] urldata: store POST size in state.infilesize too ... to simplify checking when PUT _or_ POST have completed. Reported-by: Frank Meier Bug: http://curl.haxx.se/mail/lib-2015-06/0019.html --- lib/http.c | 10 +++++----- lib/multi.c | 5 ++++- lib/rtsp.c | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/http.c b/lib/http.c index 8e422f0..7a5137e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -422,12 +422,12 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) } else { /* figure out how much data we are expected to send */ switch(data->set.httpreq) { case HTTPREQ_POST: - if(data->set.postfieldsize != -1) - expectsend = data->set.postfieldsize; + if(data->state.infilesize != -1) + expectsend = data->state.infilesize; else if(data->set.postfields) expectsend = (curl_off_t)strlen(data->set.postfields); break; case HTTPREQ_PUT: if(data->state.infilesize != -1) @@ -2570,12 +2570,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(conn->bits.authneg) postsize = 0; else { /* figure out the size of the postfields */ - postsize = (data->set.postfieldsize != -1)? - data->set.postfieldsize: + postsize = (data->state.infilesize != -1)? + data->state.infilesize: (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1); } /* We only set Content-Length and allow a custom Content-Length if we don't upload data chunked, as RFC2616 forbids us to set both @@ -2694,11 +2694,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* 0 CR LF CR LF */ if(result) return result; } - else if(data->set.postfieldsize) { + else if(data->state.infilesize) { /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, postsize?postsize:-1); /* set the pointer to mark that we will send the post body using the read callback, but only if we're not in authenticate diff --git a/lib/multi.c b/lib/multi.c index fcef2e1..bfc4d54 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -400,11 +400,14 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle, } /* Point to the multi's connection cache */ data->state.conn_cache = &multi->conn_cache; - data->state.infilesize = data->set.filesize; + if(data->set.httpreq == HTTPREQ_PUT) + data->state.infilesize = data->set.filesize; + else + data->state.infilesize = data->set.postfieldsize; /* This adds the new entry at the 'end' of the doubly-linked circular list of SessionHandle structs to try and maintain a FIFO queue so the pipelined requests are in order. */ diff --git a/lib/rtsp.c b/lib/rtsp.c index c5ca757..5d61c6f 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -493,12 +493,12 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) putsize = data->state.infilesize; data->set.httpreq = HTTPREQ_PUT; } else { - postsize = (data->set.postfieldsize != -1)? - data->set.postfieldsize: + postsize = (data->state.infilesize != -1)? + data->state.infilesize: (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); data->set.httpreq = HTTPREQ_POST; } if(putsize > 0 || postsize > 0) { -- 2.1.4
------------------------------------------------------------------- List admin: http://cool.haxx.se/list/listinfo/curl-library Etiquette: http://curl.haxx.se/mail/etiquette.html
