From: Stefan Eissing Date: Thu, 18 Jul 2024 09:29:37 +0000 (+0200) Subject: lib: send eos flag X-Git-Tag: curl-8_9_0~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=be93299f10ef0b2bf7fe5c82140120073831867a;p=thirdparty%2Fcurl.git lib: send eos flag Adds a `bool eos` flag to send methods to indicate that the data is the last chunk the invovled transfer wants to send to the server. This will help protocol filters like HTTP/2 and 3 to forward the stream's EOF flag and also allow to EAGAIN such calls when buffers are not yet fully flushed. Closes #14220 --- diff --git a/lib/c-hyper.c b/lib/c-hyper.c index 3008d9a14d..9ab52461de 100644 --- a/lib/c-hyper.c +++ b/lib/c-hyper.c @@ -119,7 +119,7 @@ size_t Curl_hyper_send(void *userp, hyper_context *ctx, DEBUGF(infof(data, "Curl_hyper_send(%zu)", buflen)); result = Curl_conn_send(data, io_ctx->sockindex, - (void *)buf, buflen, &nwrote); + (void *)buf, buflen, FALSE, &nwrote); if(result == CURLE_AGAIN) { DEBUGF(infof(data, "Curl_hyper_send(%zu) -> EAGAIN", buflen)); /* would block, register interest */ diff --git a/lib/cf-h1-proxy.c b/lib/cf-h1-proxy.c index 6656b4ddcd..595d2494fd 100644 --- a/lib/cf-h1-proxy.c +++ b/lib/cf-h1-proxy.c @@ -266,7 +266,7 @@ static CURLcode send_CONNECT(struct Curl_cfilter *cf, blen -= ts->nsent; buf += ts->nsent; - nwritten = cf->next->cft->do_send(cf->next, data, buf, blen, &result); + nwritten = cf->next->cft->do_send(cf->next, data, buf, blen, FALSE, &result); if(nwritten < 0) { if(result == CURLE_AGAIN) { result = CURLE_OK; diff --git a/lib/cf-h2-proxy.c b/lib/cf-h2-proxy.c index 7613b7828d..3378bdf3f1 100644 --- a/lib/cf-h2-proxy.c +++ b/lib/cf-h2-proxy.c @@ -260,7 +260,7 @@ static ssize_t proxy_h2_nw_out_writer(void *writer_ctx, if(cf) { struct Curl_easy *data = CF_DATA_CURRENT(cf); nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, - err); + FALSE, err); CURL_TRC_CF(data, cf, "[0] nw_out_writer(len=%zu) -> %zd, %d", buflen, nwritten, *err); } @@ -1393,7 +1393,8 @@ out: static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, CURLcode *err) + const void *buf, size_t len, bool eos, + CURLcode *err) { struct cf_h2_proxy_ctx *ctx = cf->ctx; struct cf_call_data save; @@ -1402,6 +1403,7 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf, CURLcode result; int blocked = 0; + (void)eos; /* TODO, maybe useful for blocks? */ if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) { *err = CURLE_SEND_ERROR; return -1; diff --git a/lib/cf-haproxy.c b/lib/cf-haproxy.c index 200c13958f..aa4fca0cf1 100644 --- a/lib/cf-haproxy.c +++ b/lib/cf-haproxy.c @@ -132,7 +132,7 @@ static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf, size_t written; result = Curl_conn_send(data, cf->sockindex, Curl_dyn_ptr(&ctx->data_out), - len, &written); + len, FALSE, &written); if(result == CURLE_AGAIN) { result = CURLE_OK; written = 0; diff --git a/lib/cf-socket.c b/lib/cf-socket.c index 2e92db29d3..5bfaed38c9 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -1449,13 +1449,15 @@ static void win_update_sndbuf_size(struct cf_socket_ctx *ctx) #endif /* USE_WINSOCK */ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, CURLcode *err) + const void *buf, size_t len, bool eos, + CURLcode *err) { struct cf_socket_ctx *ctx = cf->ctx; curl_socket_t fdsave; ssize_t nwritten; size_t orig_len = len; + (void)eos; /* unused */ *err = CURLE_OK; fdsave = cf->conn->sock[cf->sockindex]; cf->conn->sock[cf->sockindex] = ctx->sock; diff --git a/lib/cfilters.c b/lib/cfilters.c index 9a5c3578d7..50f576dd16 100644 --- a/lib/cfilters.c +++ b/lib/cfilters.c @@ -98,10 +98,11 @@ bool Curl_cf_def_data_pending(struct Curl_cfilter *cf, } ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, CURLcode *err) + const void *buf, size_t len, bool eos, + CURLcode *err) { return cf->next? - cf->next->cft->do_send(cf->next, data, buf, len, err) : + cf->next->cft->do_send(cf->next, data, buf, len, eos, err) : CURLE_RECV_ERROR; } @@ -256,7 +257,8 @@ ssize_t Curl_cf_recv(struct Curl_easy *data, int num, char *buf, } ssize_t Curl_cf_send(struct Curl_easy *data, int num, - const void *mem, size_t len, CURLcode *code) + const void *mem, size_t len, bool eos, + CURLcode *code) { struct Curl_cfilter *cf; @@ -268,7 +270,7 @@ ssize_t Curl_cf_send(struct Curl_easy *data, int num, cf = cf->next; } if(cf) { - ssize_t nwritten = cf->cft->do_send(cf, data, mem, len, code); + ssize_t nwritten = cf->cft->do_send(cf, data, mem, len, eos, code); DEBUGASSERT(nwritten >= 0 || *code); DEBUGASSERT(nwritten < 0 || !*code || !len); return nwritten; @@ -379,10 +381,11 @@ void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data) } ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, CURLcode *err) + const void *buf, size_t len, bool eos, + CURLcode *err) { if(cf) - return cf->cft->do_send(cf, data, buf, len, err); + return cf->cft->do_send(cf, data, buf, len, eos, err); *err = CURLE_SEND_ERROR; return -1; } @@ -811,9 +814,10 @@ CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex, } CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex, - const void *buf, size_t blen, + const void *buf, size_t blen, bool eos, size_t *pnwritten) { + size_t write_len = blen; ssize_t nwritten; CURLcode result = CURLE_OK; struct connectdata *conn; @@ -831,11 +835,14 @@ CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex, if(p) { size_t altsize = (size_t)strtoul(p, NULL, 10); if(altsize) - blen = CURLMIN(blen, altsize); + write_len = CURLMIN(write_len, altsize); } } #endif - nwritten = conn->send[sockindex](data, sockindex, buf, blen, &result); + if(write_len != blen) + eos = FALSE; + nwritten = conn->send[sockindex](data, sockindex, buf, write_len, eos, + &result); DEBUGASSERT((nwritten >= 0) || result); *pnwritten = (nwritten < 0)? 0 : (size_t)nwritten; return result; diff --git a/lib/cfilters.h b/lib/cfilters.h index 7d53607f87..0301366c2e 100644 --- a/lib/cfilters.h +++ b/lib/cfilters.h @@ -105,6 +105,7 @@ typedef ssize_t Curl_cft_send(struct Curl_cfilter *cf, struct Curl_easy *data, /* transfer */ const void *buf, /* data to write */ size_t len, /* amount to write */ + bool eos, /* last chunk */ CURLcode *err); /* error to return */ typedef ssize_t Curl_cft_recv(struct Curl_cfilter *cf, @@ -241,7 +242,8 @@ void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf, bool Curl_cf_def_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data); ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, CURLcode *err); + const void *buf, size_t len, bool eos, + CURLcode *err); ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data, char *buf, size_t len, CURLcode *err); CURLcode Curl_cf_def_cntrl(struct Curl_cfilter *cf, @@ -317,7 +319,8 @@ CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf, bool blocking, bool *done); void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data); ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, CURLcode *err); + const void *buf, size_t len, bool eos, + CURLcode *err); ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data, char *buf, size_t len, CURLcode *err); CURLcode Curl_conn_cf_cntrl(struct Curl_cfilter *cf, @@ -447,7 +450,7 @@ ssize_t Curl_cf_recv(struct Curl_easy *data, int sockindex, char *buf, * The error code is placed into `*code`. */ ssize_t Curl_cf_send(struct Curl_easy *data, int sockindex, - const void *buf, size_t len, CURLcode *code); + const void *buf, size_t len, bool eos, CURLcode *code); /** * The easy handle `data` is being attached to `conn`. This does @@ -557,7 +560,7 @@ CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex, * Will return CURLE_AGAIN iff blocked on sending. */ CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex, - const void *buf, size_t blen, + const void *buf, size_t blen, bool eos, size_t *pnwritten); diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c index 54d4f979f7..49f59e3a76 100644 --- a/lib/curl_rtmp.c +++ b/lib/curl_rtmp.c @@ -329,13 +329,14 @@ static ssize_t rtmp_recv(struct Curl_easy *data, int sockindex, char *buf, } static ssize_t rtmp_send(struct Curl_easy *data, int sockindex, - const void *buf, size_t len, CURLcode *err) + const void *buf, size_t len, bool eos, CURLcode *err) { struct connectdata *conn = data->conn; RTMP *r = conn->proto.rtmp; ssize_t num; (void)sockindex; /* unused */ + (void)eos; /* unused */ num = RTMP_Write(r, (char *)buf, curlx_uztosi(len)); if(num < 0) diff --git a/lib/dict.c b/lib/dict.c index 35331ce224..7d9c18dc9d 100644 --- a/lib/dict.c +++ b/lib/dict.c @@ -146,7 +146,7 @@ static CURLcode sendf(struct Curl_easy *data, const char *fmt, ...) for(;;) { /* Write the buffer to the socket */ - result = Curl_xfer_send(data, sptr, write_len, &bytes_written); + result = Curl_xfer_send(data, sptr, write_len, FALSE, &bytes_written); if(result) break; diff --git a/lib/easy.c b/lib/easy.c index 75bf091bcb..ed4bc357e0 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -1263,7 +1263,7 @@ CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer, Curl_attach_connection(data, c); sigpipe_ignore(data, &pipe_st); - result = Curl_conn_send(data, FIRSTSOCKET, buffer, buflen, n); + result = Curl_conn_send(data, FIRSTSOCKET, buffer, buflen, FALSE, n); sigpipe_restore(&pipe_st); if(result && result != CURLE_AGAIN) diff --git a/lib/gopher.c b/lib/gopher.c index ecea32633c..051e6e7ab5 100644 --- a/lib/gopher.c +++ b/lib/gopher.c @@ -187,7 +187,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done) if(strlen(sel) < 1) break; - result = Curl_xfer_send(data, sel, k, &amount); + result = Curl_xfer_send(data, sel, k, FALSE, &amount); if(!result) { /* Which may not have written it all! */ result = Curl_client_write(data, CLIENTWRITE_HEADER, sel, amount); if(result) @@ -229,7 +229,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done) free(sel_org); if(!result) - result = Curl_xfer_send(data, "\r\n", 2, &amount); + result = Curl_xfer_send(data, "\r\n", 2, FALSE, &amount); if(result) { failf(data, "Failed sending Gopher request"); return result; diff --git a/lib/http2.c b/lib/http2.c index 6a979c1364..caee91a7fb 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -382,8 +382,8 @@ static ssize_t nw_out_writer(void *writer_ctx, struct Curl_easy *data = CF_DATA_CURRENT(cf); if(data) { - ssize_t nwritten = Curl_conn_cf_send(cf->next, data, - (const char *)buf, buflen, err); + ssize_t nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, + buflen, FALSE, err); if(nwritten > 0) CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten); return nwritten; @@ -2173,7 +2173,8 @@ out: } static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, CURLcode *err) + const void *buf, size_t len, bool eos, + CURLcode *err) { struct cf_h2_ctx *ctx = cf->ctx; struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data); @@ -2186,6 +2187,7 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data, CF_DATA_SAVE(save, cf, data); + (void)eos; /* TODO: use for stream EOF */ if(stream && stream->id != -1) { if(stream->upload_blocked_len) { /* the data in `buf` has already been submitted or added to the diff --git a/lib/krb5.c b/lib/krb5.c index 45944cefc2..7bc2f00ec8 100644 --- a/lib/krb5.c +++ b/lib/krb5.c @@ -91,7 +91,7 @@ static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn, #ifdef HAVE_GSSAPI conn->data_prot = PROT_CMD; #endif - result = Curl_xfer_send(data, sptr, write_len, &bytes_written); + result = Curl_xfer_send(data, sptr, write_len, FALSE, &bytes_written); #ifdef HAVE_GSSAPI DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); conn->data_prot = data_sec; @@ -497,7 +497,7 @@ socket_write(struct Curl_easy *data, int sockindex, const void *to, size_t written; while(len > 0) { - result = Curl_conn_send(data, sockindex, to_p, len, &written); + result = Curl_conn_send(data, sockindex, to_p, len, FALSE, &written); if(!result && written > 0) { len -= written; to_p += written; @@ -686,10 +686,12 @@ static ssize_t sec_write(struct Curl_easy *data, struct connectdata *conn, /* Matches Curl_send signature */ static ssize_t sec_send(struct Curl_easy *data, int sockindex, - const void *buffer, size_t len, CURLcode *err) + const void *buffer, size_t len, bool eos, + CURLcode *err) { struct connectdata *conn = data->conn; curl_socket_t fd = conn->sock[sockindex]; + (void)eos; /* unused */ *err = CURLE_OK; return sec_write(data, conn, fd, buffer, len); } diff --git a/lib/mqtt.c b/lib/mqtt.c index 8c461e1630..22d354a5c2 100644 --- a/lib/mqtt.c +++ b/lib/mqtt.c @@ -121,7 +121,7 @@ static CURLcode mqtt_send(struct Curl_easy *data, CURLcode result = CURLE_OK; struct MQTT *mq = data->req.p.mqtt; size_t n; - result = Curl_xfer_send(data, buf, len, &n); + result = Curl_xfer_send(data, buf, len, FALSE, &n); if(result) return result; Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n); diff --git a/lib/openldap.c b/lib/openldap.c index 1b35ba0d78..f3e13ed5cd 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -1201,7 +1201,7 @@ ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) if(conn) { struct ldapconninfo *li = conn->proto.ldapc; CURLcode err = CURLE_SEND_ERROR; - ret = (li->send)(data, FIRSTSOCKET, buf, len, &err); + ret = (li->send)(data, FIRSTSOCKET, buf, len, FALSE, &err); if(ret < 0 && err == CURLE_AGAIN) { SET_SOCKERRNO(EWOULDBLOCK); } diff --git a/lib/pingpong.c b/lib/pingpong.c index 7ce81e8af7..bf4f95763b 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -199,7 +199,8 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data, #ifdef HAVE_GSSAPI conn->data_prot = PROT_CMD; #endif - result = Curl_conn_send(data, FIRSTSOCKET, s, write_len, &bytes_written); + result = Curl_conn_send(data, FIRSTSOCKET, s, write_len, FALSE, + &bytes_written); if(result == CURLE_AGAIN) { bytes_written = 0; } @@ -403,7 +404,7 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data, result = Curl_conn_send(data, FIRSTSOCKET, pp->sendthis + pp->sendsize - pp->sendleft, - pp->sendleft, &written); + pp->sendleft, FALSE, &written); if(result == CURLE_AGAIN) { result = CURLE_OK; written = 0; diff --git a/lib/request.c b/lib/request.c index 5c8d52f696..798a33a2d5 100644 --- a/lib/request.c +++ b/lib/request.c @@ -179,6 +179,7 @@ static CURLcode xfer_send(struct Curl_easy *data, size_t hds_len, size_t *pnwritten) { CURLcode result = CURLE_OK; + bool eos = FALSE; *pnwritten = 0; #ifdef DEBUGBUILD @@ -202,7 +203,13 @@ static CURLcode xfer_send(struct Curl_easy *data, blen = hds_len + (size_t)data->set.max_send_speed; } - result = Curl_xfer_send(data, buf, blen, pnwritten); + if(data->req.eos_read && + (Curl_bufq_is_empty(&data->req.sendbuf) || + Curl_bufq_len(&data->req.sendbuf) == blen)) { + DEBUGF(infof(data, "sending last upload chunk of %zu bytes", blen)); + eos = TRUE; + } + result = Curl_xfer_send(data, buf, blen, eos, pnwritten); if(!result && *pnwritten) { if(hds_len) Curl_debug(data, CURLINFO_HEADER_OUT, (char *)buf, diff --git a/lib/smb.c b/lib/smb.c index 102662ace6..2fb16de430 100644 --- a/lib/smb.c +++ b/lib/smb.c @@ -572,7 +572,7 @@ static CURLcode smb_send(struct Curl_easy *data, size_t len, size_t bytes_written; CURLcode result; - result = Curl_xfer_send(data, smbc->send_buf, len, &bytes_written); + result = Curl_xfer_send(data, smbc->send_buf, len, FALSE, &bytes_written); if(result) return result; @@ -597,7 +597,7 @@ static CURLcode smb_flush(struct Curl_easy *data) if(!smbc->send_size) return CURLE_OK; - result = Curl_xfer_send(data, smbc->send_buf + smbc->sent, len, + result = Curl_xfer_send(data, smbc->send_buf + smbc->sent, len, FALSE, &bytes_written); if(result) return result; diff --git a/lib/socks.c b/lib/socks.c index 094ff42cd7..041e98589b 100644 --- a/lib/socks.c +++ b/lib/socks.c @@ -217,7 +217,7 @@ static CURLproxycode socks_state_send(struct Curl_cfilter *cf, CURLcode result; nwritten = Curl_conn_cf_send(cf->next, data, (char *)sx->outp, - sx->outstanding, &result); + sx->outstanding, FALSE, &result); if(nwritten <= 0) { if(CURLE_AGAIN == result) { return CURLPX_OK; diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c index edcc683261..f83db977ad 100644 --- a/lib/socks_gssapi.c +++ b/lib/socks_gssapi.c @@ -204,7 +204,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, us_length = htons((unsigned short)gss_send_token.length); memcpy(socksreq + 2, &us_length, sizeof(short)); - nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, &code); + nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, + FALSE, &code); if(code || (4 != nwritten)) { failf(data, "Failed to send GSS-API authentication request."); gss_release_name(&gss_status, &server); @@ -216,7 +217,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, nwritten = Curl_conn_cf_send(cf->next, data, (char *)gss_send_token.value, - gss_send_token.length, &code); + gss_send_token.length, FALSE, &code); if(code || ((ssize_t)gss_send_token.length != nwritten)) { failf(data, "Failed to send GSS-API authentication token."); gss_release_name(&gss_status, &server); @@ -410,7 +411,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, memcpy(socksreq + 2, &us_length, sizeof(short)); } - nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, &code); + nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE, + &code); if(code || (4 != nwritten)) { failf(data, "Failed to send GSS-API encryption request."); gss_release_buffer(&gss_status, &gss_w_token); @@ -420,7 +422,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, if(data->set.socks5_gssapi_nec) { memcpy(socksreq, &gss_enc, 1); - nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, &code); + nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, FALSE, + &code); if(code || ( 1 != nwritten)) { failf(data, "Failed to send GSS-API encryption type."); gss_delete_sec_context(&gss_status, &gss_context, NULL); @@ -430,7 +433,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, else { nwritten = Curl_conn_cf_send(cf->next, data, (char *)gss_w_token.value, - gss_w_token.length, &code); + gss_w_token.length, FALSE, &code); if(code || ((ssize_t)gss_w_token.length != nwritten)) { failf(data, "Failed to send GSS-API encryption type."); gss_release_buffer(&gss_status, &gss_w_token); diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c index a83288dd00..f64656b3e9 100644 --- a/lib/socks_sspi.c +++ b/lib/socks_sspi.c @@ -207,7 +207,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, us_length = htons((unsigned short)sspi_send_token.cbBuffer); memcpy(socksreq + 2, &us_length, sizeof(short)); - written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, &code); + written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE, + &code); if(code || (4 != written)) { failf(data, "Failed to send SSPI authentication request."); free(service_name); @@ -222,7 +223,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, written = Curl_conn_cf_send(cf->next, data, (char *)sspi_send_token.pvBuffer, - sspi_send_token.cbBuffer, &code); + sspi_send_token.cbBuffer, FALSE, &code); if(code || (sspi_send_token.cbBuffer != (size_t)written)) { failf(data, "Failed to send SSPI authentication token."); free(service_name); @@ -476,7 +477,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, memcpy(socksreq + 2, &us_length, sizeof(short)); } - written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, &code); + written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE, + &code); if(code || (4 != written)) { failf(data, "Failed to send SSPI encryption request."); if(sspi_send_token.pvBuffer) @@ -487,7 +489,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, if(data->set.socks5_gssapi_nec) { memcpy(socksreq, &gss_enc, 1); - written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, &code); + written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, FALSE, + &code); if(code || (1 != written)) { failf(data, "Failed to send SSPI encryption type."); s_pSecFn->DeleteSecurityContext(&sspi_context); @@ -497,7 +500,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, else { written = Curl_conn_cf_send(cf->next, data, (char *)sspi_send_token.pvBuffer, - sspi_send_token.cbBuffer, &code); + sspi_send_token.cbBuffer, FALSE, &code); if(code || (sspi_send_token.cbBuffer != (size_t)written)) { failf(data, "Failed to send SSPI encryption type."); if(sspi_send_token.pvBuffer) diff --git a/lib/telnet.c b/lib/telnet.c index 91fa10ada6..7714f4ff3e 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -1276,7 +1276,7 @@ static CURLcode send_telnet_data(struct Curl_easy *data, default: /* write! */ bytes_written = 0; result = Curl_xfer_send(data, outbuf + total_written, - outlen - total_written, &bytes_written); + outlen - total_written, FALSE, &bytes_written); total_written += bytes_written; break; } diff --git a/lib/transfer.c b/lib/transfer.c index 476f9c002e..1297b0de76 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -1250,7 +1250,7 @@ CURLcode Curl_xfer_write_done(struct Curl_easy *data, bool premature) } CURLcode Curl_xfer_send(struct Curl_easy *data, - const void *buf, size_t blen, + const void *buf, size_t blen, bool eos, size_t *pnwritten) { CURLcode result; @@ -1267,7 +1267,7 @@ CURLcode Curl_xfer_send(struct Curl_easy *data, } */ sockindex = ((data->conn->writesockfd != CURL_SOCKET_BAD) && (data->conn->writesockfd == data->conn->sock[SECONDARYSOCKET])); - result = Curl_conn_send(data, sockindex, buf, blen, pnwritten); + result = Curl_conn_send(data, sockindex, buf, blen, eos, pnwritten); if(result == CURLE_AGAIN) { result = CURLE_OK; *pnwritten = 0; diff --git a/lib/transfer.h b/lib/transfer.h index 33d51e3b15..04fcc4a13b 100644 --- a/lib/transfer.h +++ b/lib/transfer.h @@ -120,7 +120,7 @@ CURLcode Curl_xfer_write_done(struct Curl_easy *data, bool premature); * Will return CURLE_OK on blocking with (*pnwritten == 0). */ CURLcode Curl_xfer_send(struct Curl_easy *data, - const void *buf, size_t blen, + const void *buf, size_t blen, bool eos, size_t *pnwritten); /** diff --git a/lib/urldata.h b/lib/urldata.h index 74b744c715..5ff8cec405 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -159,6 +159,7 @@ typedef ssize_t (Curl_send)(struct Curl_easy *data, /* transfer */ int sockindex, /* socketindex */ const void *buf, /* data to write */ size_t len, /* max amount to write */ + bool eos, /* last chunk */ CURLcode *err); /* error to return */ /* return the count of bytes read, or -1 on error */ diff --git a/lib/vquic/curl_msh3.c b/lib/vquic/curl_msh3.c index b707a6ebe3..c8466280a2 100644 --- a/lib/vquic/curl_msh3.c +++ b/lib/vquic/curl_msh3.c @@ -593,7 +593,8 @@ out: } static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, CURLcode *err) + const void *buf, size_t len, bool eos, + CURLcode *err) { struct cf_msh3_ctx *ctx = cf->ctx; struct stream_ctx *stream = H3_STREAM_CTX(ctx, data); @@ -603,7 +604,6 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data, size_t nheader, i; ssize_t nwritten = -1; struct cf_call_data save; - bool eos; CF_DATA_SAVE(save, cf, data); @@ -646,21 +646,6 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data, nva[i].ValueLength = e->valuelen; } - switch(data->state.httpreq) { - case HTTPREQ_POST: - case HTTPREQ_POST_FORM: - case HTTPREQ_POST_MIME: - case HTTPREQ_PUT: - /* known request body size or -1 */ - eos = FALSE; - break; - default: - /* there is not request body */ - eos = TRUE; - stream->upload_done = TRUE; - break; - } - CURL_TRC_CF(data, cf, "req: send %zu headers", nheader); stream->req = MsH3RequestOpen(ctx->qconn, &msh3_request_if, data, nva, nheader, diff --git a/lib/vquic/curl_ngtcp2.c b/lib/vquic/curl_ngtcp2.c index 1f67f2362e..5e0a3ee127 100644 --- a/lib/vquic/curl_ngtcp2.c +++ b/lib/vquic/curl_ngtcp2.c @@ -1484,7 +1484,8 @@ out: } static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, CURLcode *err) + const void *buf, size_t len, bool eos, + CURLcode *err) { struct cf_ngtcp2_ctx *ctx = cf->ctx; struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); @@ -1500,6 +1501,7 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, pktx_init(&pktx, cf, data); *err = CURLE_OK; + (void)eos; /* TODO: use for stream EOF and block handling */ result = cf_progress_ingress(cf, data, &pktx); if(result) { *err = result; diff --git a/lib/vquic/curl_osslq.c b/lib/vquic/curl_osslq.c index dafde44f26..6b3d5fb0f1 100644 --- a/lib/vquic/curl_osslq.c +++ b/lib/vquic/curl_osslq.c @@ -1899,7 +1899,8 @@ out: } static ssize_t cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, CURLcode *err) + const void *buf, size_t len, bool eos, + CURLcode *err) { struct cf_osslq_ctx *ctx = cf->ctx; struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); @@ -1907,6 +1908,7 @@ static ssize_t cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data, ssize_t nwritten; CURLcode result; + (void)eos; /* TODO: use to end stream */ CF_DATA_SAVE(save, cf, data); DEBUGASSERT(cf->connected); DEBUGASSERT(ctx->tls.ossl.ssl); diff --git a/lib/vquic/curl_quiche.c b/lib/vquic/curl_quiche.c index 6f01c19aa5..e3470f999d 100644 --- a/lib/vquic/curl_quiche.c +++ b/lib/vquic/curl_quiche.c @@ -148,7 +148,6 @@ struct stream_ctx { struct bufq recvbuf; /* h3 response */ struct h1_req_parser h1; /* h1 request parsing */ curl_uint64_t error3; /* HTTP/3 stream error code */ - curl_off_t upload_left; /* number of request bytes left to upload */ BIT(opened); /* TRUE after stream has been opened */ BIT(closed); /* TRUE on stream close */ BIT(reset); /* TRUE on stream reset */ @@ -255,7 +254,7 @@ static void drain_stream(struct Curl_cfilter *cf, (void)cf; bits = CURL_CSELECT_IN; - if(stream && !stream->send_closed && stream->upload_left) + if(stream && !stream->send_closed) bits |= CURL_CSELECT_OUT; if(data->state.select_bits != bits) { data->state.select_bits = bits; @@ -890,13 +889,64 @@ out: return nread; } +static ssize_t cf_quiche_send_body(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct stream_ctx *stream, + const void *buf, size_t len, bool eos, + CURLcode *err) +{ + struct cf_quiche_ctx *ctx = cf->ctx; + ssize_t nwritten; + + nwritten = quiche_h3_send_body(ctx->h3c, ctx->qconn, stream->id, + (uint8_t *)buf, len, eos); + if(nwritten == QUICHE_H3_ERR_DONE || (nwritten == 0 && len > 0)) { + /* TODO: we seem to be blocked on flow control and should HOLD + * sending. But when do we open again? */ + if(!quiche_conn_stream_writable(ctx->qconn, stream->id, len)) { + CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) " + "-> window exhausted", stream->id, len); + stream->quic_flow_blocked = TRUE; + } + *err = CURLE_AGAIN; + return -1; + } + else if(nwritten == QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE) { + CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) " + "-> invalid stream state", stream->id, len); + *err = CURLE_HTTP3; + return -1; + } + else if(nwritten == QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE) { + CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) " + "-> exceeds size", stream->id, len); + *err = CURLE_SEND_ERROR; + return -1; + } + else if(nwritten < 0) { + CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) " + "-> quiche err %zd", stream->id, len, nwritten); + *err = CURLE_SEND_ERROR; + return -1; + } + else { + if(eos && (len == (size_t)nwritten)) + stream->send_closed = TRUE; + CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send body(len=%zu, " + "eos=%d) -> %zd", + stream->id, len, stream->send_closed, nwritten); + *err = CURLE_OK; + return nwritten; + } +} + /* Index where :authority header field will appear in request header field list. */ #define AUTHORITY_DST_IDX 3 static ssize_t h3_open_stream(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, + const char *buf, size_t len, bool eos, CURLcode *err) { struct cf_quiche_ctx *ctx = cf->ctx; @@ -952,23 +1002,7 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf, nva[i].value_len = e->valuelen; } - switch(data->state.httpreq) { - case HTTPREQ_POST: - case HTTPREQ_POST_FORM: - case HTTPREQ_POST_MIME: - case HTTPREQ_PUT: - if(data->state.infilesize != -1) - stream->upload_left = data->state.infilesize; - else - /* data sending without specifying the data amount up front */ - stream->upload_left = -1; /* unknown */ - break; - default: - stream->upload_left = 0; /* no request body */ - break; - } - - if(stream->upload_left == 0) + if(eos && ((size_t)nwritten == len)) stream->send_closed = TRUE; stream3_id = quiche_h3_send_request(ctx->h3c, ctx->qconn, nva, nheader, @@ -1009,6 +1043,22 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf, } } + if(nwritten > 0 && ((size_t)nwritten < len)) { + /* after the headers, there was request BODY data */ + size_t hds_len = (size_t)nwritten; + ssize_t bwritten; + + bwritten = cf_quiche_send_body(cf, data, stream, + buf + hds_len, len - hds_len, eos, err); + if((bwritten < 0) && (CURLE_AGAIN != *err)) { + /* real error, fail */ + nwritten = -1; + } + else if(bwritten > 0) { + nwritten += bwritten; + } + } + out: free(nva); Curl_dynhds_free(&h2_headers); @@ -1016,7 +1066,8 @@ out: } static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, CURLcode *err) + const void *buf, size_t len, bool eos, + CURLcode *err) { struct cf_quiche_ctx *ctx = cf->ctx; struct stream_ctx *stream = H3_STREAM_CTX(ctx, data); @@ -1032,7 +1083,7 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data, } if(!stream || !stream->opened) { - nwritten = h3_open_stream(cf, data, buf, len, err); + nwritten = h3_open_stream(cf, data, buf, len, eos, err); if(nwritten < 0) goto out; stream = H3_STREAM_CTX(ctx, data); @@ -1060,57 +1111,7 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data, goto out; } else { - bool eof = (stream->upload_left >= 0 && - (curl_off_t)len >= stream->upload_left); - nwritten = quiche_h3_send_body(ctx->h3c, ctx->qconn, stream->id, - (uint8_t *)buf, len, eof); - if(nwritten == QUICHE_H3_ERR_DONE || (nwritten == 0 && len > 0)) { - /* TODO: we seem to be blocked on flow control and should HOLD - * sending. But when do we open again? */ - if(!quiche_conn_stream_writable(ctx->qconn, stream->id, len)) { - CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) " - "-> window exhausted", stream->id, len); - stream->quic_flow_blocked = TRUE; - } - *err = CURLE_AGAIN; - nwritten = -1; - goto out; - } - else if(nwritten == QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE) { - CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) " - "-> invalid stream state", stream->id, len); - *err = CURLE_HTTP3; - nwritten = -1; - goto out; - } - else if(nwritten == QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE) { - CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) " - "-> exceeds size", stream->id, len); - *err = CURLE_SEND_ERROR; - nwritten = -1; - goto out; - } - else if(nwritten < 0) { - CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) " - "-> quiche err %zd", stream->id, len, nwritten); - *err = CURLE_SEND_ERROR; - nwritten = -1; - goto out; - } - else { - /* quiche accepted all or at least a part of the buf */ - if(stream->upload_left > 0) { - stream->upload_left = (nwritten < stream->upload_left)? - (stream->upload_left - nwritten) : 0; - } - if(stream->upload_left == 0) - stream->send_closed = TRUE; - - CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send body(len=%zu, " - "left=%" CURL_FORMAT_CURL_OFF_T ") -> %zd", - stream->id, len, stream->upload_left, nwritten); - *err = CURLE_OK; - } + nwritten = cf_quiche_send_body(cf, data, stream, buf, len, eos, err); } out: @@ -1120,7 +1121,7 @@ out: nwritten = -1; } CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] cf_send(len=%zu) -> %zd, %d", - stream? stream->id : (uint64_t)~0, len, nwritten, *err); + stream? stream->id : (curl_uint64_t)~0, len, nwritten, *err); return nwritten; } @@ -1215,9 +1216,8 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf, ssize_t sent; stream->send_closed = TRUE; - stream->upload_left = 0; body[0] = 'X'; - sent = cf_quiche_send(cf, data, body, 0, &result); + sent = cf_quiche_send(cf, data, body, 0, TRUE, &result); CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] DONE_SEND -> %zd, %d", stream->id, sent, result); } diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c index 20a05636d3..120e8f8d51 100644 --- a/lib/vssh/libssh.c +++ b/lib/vssh/libssh.c @@ -2404,12 +2404,13 @@ static CURLcode scp_done(struct Curl_easy *data, CURLcode status, } static ssize_t scp_send(struct Curl_easy *data, int sockindex, - const void *mem, size_t len, CURLcode *err) + const void *mem, size_t len, bool eos, CURLcode *err) { int rc; struct connectdata *conn = data->conn; (void) sockindex; /* we only support SCP on the fixed known primary socket */ (void) err; + (void)eos; rc = ssh_scp_write(conn->proto.sshc.scp_session, mem, len); @@ -2552,11 +2553,13 @@ static CURLcode sftp_done(struct Curl_easy *data, CURLcode status, /* return number of sent bytes */ static ssize_t sftp_send(struct Curl_easy *data, int sockindex, - const void *mem, size_t len, CURLcode *err) + const void *mem, size_t len, bool eos, + CURLcode *err) { ssize_t nwrite; struct connectdata *conn = data->conn; (void)sockindex; + (void)eos; /* limit the writes to the maximum specified in Section 3 of * https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-02 diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c index 1b566d1ab2..c7bf3b7fb8 100644 --- a/lib/vssh/libssh2.c +++ b/lib/vssh/libssh2.c @@ -3229,7 +3229,7 @@ static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer, /* swap in the TLS writer function for this call only, and then swap back the SSH one again */ conn->send[0] = ssh->tls_send; - result = Curl_conn_send(data, socknum, buffer, length, &nwrite); + result = Curl_conn_send(data, socknum, buffer, length, FALSE, &nwrite); conn->send[0] = backup; if(result == CURLE_AGAIN) return -EAGAIN; /* magic return code for libssh2 */ @@ -3540,12 +3540,13 @@ static CURLcode scp_done(struct Curl_easy *data, CURLcode status, } static ssize_t scp_send(struct Curl_easy *data, int sockindex, - const void *mem, size_t len, CURLcode *err) + const void *mem, size_t len, bool eos, CURLcode *err) { ssize_t nwrite; struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; (void)sockindex; /* we only support SCP on the fixed known primary socket */ + (void)eos; /* libssh2_channel_write() returns int! */ nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len); @@ -3678,12 +3679,13 @@ static CURLcode sftp_done(struct Curl_easy *data, CURLcode status, /* return number of sent bytes */ static ssize_t sftp_send(struct Curl_easy *data, int sockindex, - const void *mem, size_t len, CURLcode *err) + const void *mem, size_t len, bool eos, CURLcode *err) { ssize_t nwrite; struct connectdata *conn = data->conn; struct ssh_conn *sshc = &conn->proto.sshc; (void)sockindex; + (void)eos; nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len); diff --git a/lib/vtls/bearssl.c b/lib/vtls/bearssl.c index 47c5528c29..c5a762d545 100644 --- a/lib/vtls/bearssl.c +++ b/lib/vtls/bearssl.c @@ -720,7 +720,8 @@ static CURLcode bearssl_run_until(struct Curl_cfilter *cf, return CURLE_OK; if(state & BR_SSL_SENDREC) { buf = br_ssl_engine_sendrec_buf(&backend->ctx.eng, &len); - ret = Curl_conn_cf_send(cf->next, data, (char *)buf, len, &result); + ret = Curl_conn_cf_send(cf->next, data, (char *)buf, len, FALSE, + &result); CURL_TRC_CF(data, cf, "ssl_send(len=%zu) -> %zd, %d", len, ret, result); if(ret <= 0) { if(result == CURLE_AGAIN) diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index 39c22c2003..3640c6f576 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -102,7 +102,7 @@ static ssize_t gtls_push(void *s, const void *buf, size_t blen) CURLcode result; DEBUGASSERT(data); - nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result); + nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &result); CURL_TRC_CF(data, cf, "gtls_push(len=%zu) -> %zd, err=%d", blen, nwritten, result); backend->gtls.io_result = result; diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 154ce5fab0..5f3653efeb 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -200,7 +200,8 @@ static int mbedtls_bio_cf_write(void *bio, if(!data) return 0; - nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, &result); + nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, FALSE, + &result); CURL_TRC_CF(data, cf, "mbedtls_bio_cf_out_write(len=%zu) -> %zd, err=%d", blen, nwritten, result); if(nwritten < 0 && CURLE_AGAIN == result) { diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index 2b60f7fba8..326146b041 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -723,7 +723,8 @@ static int ossl_bio_cf_out_write(BIO *bio, const char *buf, int blen) if(blen < 0) return 0; - nwritten = Curl_conn_cf_send(cf->next, data, buf, (size_t)blen, &result); + nwritten = Curl_conn_cf_send(cf->next, data, buf, (size_t)blen, FALSE, + &result); CURL_TRC_CF(data, cf, "ossl_bio_cf_out_write(len=%d) -> %d, err=%d", blen, (int)nwritten, result); BIO_clear_retry_flags(bio); diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index bdcd08ab99..160907ff0a 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -115,7 +115,8 @@ write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n) CURLcode result; int ret = 0; ssize_t nwritten = Curl_conn_cf_send(io_ctx->cf->next, io_ctx->data, - (const char *)buf, len, &result); + (const char *)buf, len, FALSE, + &result); if(nwritten < 0) { nwritten = 0; if(CURLE_AGAIN == result) diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c index f9bb2f8247..9808f5ecd8 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/schannel.c @@ -1287,7 +1287,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* send initial handshake data which is now stored in output buffer */ written = Curl_conn_cf_send(cf->next, data, - outbuf.pvBuffer, outbuf.cbBuffer, + outbuf.pvBuffer, outbuf.cbBuffer, FALSE, &result); s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { @@ -1477,7 +1477,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) /* send handshake token to server */ written = Curl_conn_cf_send(cf->next, data, outbuf[i].pvBuffer, outbuf[i].cbBuffer, - &result); + FALSE, &result); if((result != CURLE_OK) || (outbuf[i].cbBuffer != (size_t) written)) { failf(data, "schannel: failed to send next handshake data: " @@ -2054,7 +2054,7 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, this_write = Curl_conn_cf_send(cf->next, data, ptr + written, len - written, - &result); + FALSE, &result); if(result == CURLE_AGAIN) continue; else if(result != CURLE_OK) { @@ -2531,7 +2531,7 @@ static CURLcode schannel_shutdown(struct Curl_cfilter *cf, /* send close message which is in output buffer */ ssize_t written = Curl_conn_cf_send(cf->next, data, outbuf.pvBuffer, outbuf.cbBuffer, - &result); + FALSE, &result); s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); if(!result) { if(written < (ssize_t)outbuf.cbBuffer) { diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c index c2803e8bfc..a45e6ab6a4 100644 --- a/lib/vtls/sectransp.c +++ b/lib/vtls/sectransp.c @@ -310,7 +310,8 @@ static OSStatus sectransp_bio_cf_out_write(SSLConnectionRef connection, OSStatus rtn = noErr; DEBUGASSERT(data); - nwritten = Curl_conn_cf_send(cf->next, data, buf, *dataLength, &result); + nwritten = Curl_conn_cf_send(cf->next, data, buf, *dataLength, FALSE, + &result); CURL_TRC_CF(data, cf, "bio_send(len=%zu) -> %zd, result=%d", *dataLength, nwritten, result); if(nwritten <= 0) { diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 96e7197d45..c5f5b0abcb 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -1725,11 +1725,12 @@ static bool ssl_cf_data_pending(struct Curl_cfilter *cf, static ssize_t ssl_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data, const void *buf, size_t len, - CURLcode *err) + bool eos, CURLcode *err) { struct cf_call_data save; ssize_t nwritten; + (void)eos; /* unused */ CF_DATA_SAVE(save, cf, data); *err = CURLE_OK; nwritten = Curl_ssl->send_plain(cf, data, buf, len, err); diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c index 0ff36d99d6..1c980f040d 100644 --- a/lib/vtls/wolfssl.c +++ b/lib/vtls/wolfssl.c @@ -291,7 +291,7 @@ static int wolfssl_bio_cf_out_write(WOLFSSL_BIO *bio, CURLcode result = CURLE_OK; DEBUGASSERT(data); - nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result); + nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &result); backend->io_result = result; CURL_TRC_CF(data, cf, "bio_write(len=%d) -> %zd, %d", blen, nwritten, result); diff --git a/lib/ws.c b/lib/ws.c index 3c2d94950c..3e8a4e818e 100644 --- a/lib/ws.c +++ b/lib/ws.c @@ -1019,7 +1019,7 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws, if(data->set.connect_only) result = Curl_senddata(data, out, outlen, &n); else { - result = Curl_xfer_send(data, out, outlen, &n); + result = Curl_xfer_send(data, out, outlen, FALSE, &n); if(!result && !n && outlen) result = CURLE_AGAIN; } @@ -1088,7 +1088,7 @@ CURL_EXTERN CURLcode curl_ws_send(CURL *data, const void *buffer, /* raw mode sends exactly what was requested, and this is from within the write callback */ if(Curl_is_in_callback(data)) { - result = Curl_xfer_send(data, buffer, buflen, &nwritten); + result = Curl_xfer_send(data, buffer, buflen, FALSE, &nwritten); } else result = Curl_senddata(data, buffer, buflen, &nwritten);