cw-out: handle error codes for 0len writes
No binary (build failed)
—
(log yok)
| @@ -195,6 +195,50 @@ static void cw_get_writefunc(struct Curl_easy *data, cw_out_type otype, | |
| } | |
| } | |
| + | static CURLcode cw_out_cb_write(struct cw_out_ctx *ctx, |
| + | struct Curl_easy *data, |
| + | curl_write_callback wcb, |
| + | void *wcb_data, |
| + | cw_out_type otype, |
| + | const char *buf, size_t blen, |
| + | size_t *pnwritten) |
| + | { |
| + | size_t nwritten; |
| + | CURLcode result; |
| + | |
| + | *pnwritten = 0; |
| + | Curl_set_in_callback(data, TRUE); |
| + | nwritten = wcb((char *)CURL_UNCONST(buf), 1, blen, wcb_data); |
| + | Curl_set_in_callback(data, FALSE); |
| + | CURL_TRC_WRITE(data, "[OUT] wrote %zu %s bytes -> %zu", |
| + | blen, (otype == CW_OUT_HDS) ? "header" : "body", |
| + | nwritten); |
| + | if(CURL_WRITEFUNC_PAUSE == nwritten) { |
| + | if(data->conn && data->conn->handler->flags & PROTOPT_NONETWORK) { |
| + | /* Protocols that work without network cannot be paused. This is |
| + | actually only FILE:// just now, and it cannot pause since the |
| + | transfer is not done using the "normal" procedure. */ |
| + | failf(data, "Write callback asked for PAUSE when not supported"); |
| + | return CURLE_WRITE_ERROR; |
| + | } |
| + | ctx->paused = TRUE; |
| + | CURL_TRC_WRITE(data, "[OUT] PAUSE requested by client"); |
| + | result = Curl_xfer_pause_recv(data, TRUE); |
| + | return result ? result : CURLE_AGAIN; |
| + | } |
| + | else if(CURL_WRITEFUNC_ERROR == nwritten) { |
| + | failf(data, "client returned ERROR on write of %zu bytes", blen); |
| + | return CURLE_WRITE_ERROR; |
| + | } |
| + | else if(nwritten != blen) { |
| + | failf(data, "Failure writing output to destination, " |
| + | "passed %zu returned %zd", blen, nwritten); |
| + | return CURLE_WRITE_ERROR; |
| + | } |
| + | *pnwritten = nwritten; |
| + | return CURLE_OK; |
| + | } |
| + | |
| static CURLcode cw_out_ptr_flush(struct cw_out_ctx *ctx, | |
| struct Curl_easy *data, | |
| cw_out_type otype, | |
| @@ -206,6 +250,7 @@ static CURLcode cw_out_ptr_flush(struct cw_out_ctx *ctx, | |
| void *wcb_data; | |
| size_t max_write, min_write; | |
| size_t wlen, nwritten; | |
| + | CURLcode result; |
| /* If we errored once, we do not invoke the client callback again */ | |
| if(ctx->errored) | |
| @@ -221,44 +266,18 @@ static CURLcode cw_out_ptr_flush(struct cw_out_ctx *ctx, | |
| *pconsumed = 0; | |
| if(otype == CW_OUT_BODY_0LEN) { | |
| DEBUGASSERT(!blen); | |
| - | Curl_set_in_callback(data, TRUE); |
| - | nwritten = wcb((char *)CURL_UNCONST(buf), 1, blen, wcb_data); |
| - | Curl_set_in_callback(data, FALSE); |
| - | CURL_TRC_WRITE(data, "[OUT] wrote %zu BODY bytes -> %zu", |
| - | blen, nwritten); |
| + | return cw_out_cb_write(ctx, data, wcb, wcb_data, otype, |
| + | buf, blen, &nwritten); |
| } | |
| else { | |
| while(blen && !ctx->paused) { | |
| if(!flush_all && blen < min_write) | |
| break; | |
| wlen = max_write ? CURLMIN(blen, max_write) : blen; | |
| - | Curl_set_in_callback(data, TRUE); |
| - | nwritten = wcb((char *)CURL_UNCONST(buf), 1, wlen, wcb_data); |
| - | Curl_set_in_callback(data, FALSE); |
| - | CURL_TRC_WRITE(data, "[OUT] wrote %zu %s bytes -> %zu", |
| - | wlen, (otype == CW_OUT_BODY) ? "body" : "header", |
| - | nwritten); |
| - | if(CURL_WRITEFUNC_PAUSE == nwritten) { |
| - | if(data->conn && data->conn->handler->flags & PROTOPT_NONETWORK) { |
| - | /* Protocols that work without network cannot be paused. This is |
| - | actually only FILE:// just now, and it cannot pause since the |
| - | transfer is not done using the "normal" procedure. */ |
| - | failf(data, "Write callback asked for PAUSE when not supported"); |
| - | return CURLE_WRITE_ERROR; |
| - | } |
| - | ctx->paused = TRUE; |
| - | CURL_TRC_WRITE(data, "[OUT] PAUSE requested by client"); |
| - | return Curl_xfer_pause_recv(data, TRUE); |
| - | } |
| - | else if(CURL_WRITEFUNC_ERROR == nwritten) { |
| - | failf(data, "client returned ERROR on write of %zu bytes", wlen); |
| - | return CURLE_WRITE_ERROR; |
| - | } |
| - | else if(nwritten != wlen) { |
| - | failf(data, "Failure writing output to destination, " |
| - | "passed %zu returned %zd", wlen, nwritten); |
| - | return CURLE_WRITE_ERROR; |
| - | } |
| + | result = cw_out_cb_write(ctx, data, wcb, wcb_data, otype, |
| + | buf, wlen, &nwritten); |
| + | if(result) |
| + | return result; |
| *pconsumed += nwritten; | |
| blen -= nwritten; | |
| buf += nwritten; | |
| @@ -274,14 +293,14 @@ static CURLcode cw_out_buf_flush(struct cw_out_ctx *ctx, | |
| { | |
| CURLcode result = CURLE_OK; | |
| - | if(curlx_dyn_len(&cwbuf->b)) { |
| + | if(curlx_dyn_len(&cwbuf->b) || (cwbuf->type == CW_OUT_BODY_0LEN)) { |
| size_t consumed; | |
| result = cw_out_ptr_flush(ctx, data, cwbuf->type, flush_all, | |
| curlx_dyn_ptr(&cwbuf->b), | |
| curlx_dyn_len(&cwbuf->b), | |
| &consumed); | |
| - | if(result) |
| + | if(result && (result != CURLE_AGAIN)) |
| return result; | |
| if(consumed) { | |
| @@ -394,8 +413,9 @@ static CURLcode cw_out_do_write(struct cw_out_ctx *ctx, | |
| size_t consumed; | |
| result = cw_out_ptr_flush(ctx, data, otype, flush_all, | |
| buf, blen, &consumed); | |
| - | if(result) |
| + | if(result && (result != CURLE_AGAIN)) |
| return result; | |
| + | result = CURLE_OK; |
| if(consumed < blen) { | |
| /* did not write all, append the rest */ | |
| result = cw_out_append(ctx, data, otype, | |