]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
lib: send eos flag
authorStefan Eissing <stefan@eissing.org>
Thu, 18 Jul 2024 09:29:37 +0000 (11:29 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 18 Jul 2024 21:27:35 +0000 (23:27 +0200)
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

41 files changed:
lib/c-hyper.c
lib/cf-h1-proxy.c
lib/cf-h2-proxy.c
lib/cf-haproxy.c
lib/cf-socket.c
lib/cfilters.c
lib/cfilters.h
lib/curl_rtmp.c
lib/dict.c
lib/easy.c
lib/gopher.c
lib/http2.c
lib/krb5.c
lib/mqtt.c
lib/openldap.c
lib/pingpong.c
lib/request.c
lib/smb.c
lib/socks.c
lib/socks_gssapi.c
lib/socks_sspi.c
lib/telnet.c
lib/transfer.c
lib/transfer.h
lib/urldata.h
lib/vquic/curl_msh3.c
lib/vquic/curl_ngtcp2.c
lib/vquic/curl_osslq.c
lib/vquic/curl_quiche.c
lib/vssh/libssh.c
lib/vssh/libssh2.c
lib/vtls/bearssl.c
lib/vtls/gtls.c
lib/vtls/mbedtls.c
lib/vtls/openssl.c
lib/vtls/rustls.c
lib/vtls/schannel.c
lib/vtls/sectransp.c
lib/vtls/vtls.c
lib/vtls/wolfssl.c
lib/ws.c

index 3008d9a14dbca6dfa38cc70dd78edb970e55840a..9ab52461de917335c43c72785009921049e261f8 100644 (file)
@@ -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 */
index 6656b4ddcdbdd2240298ccc7580078573706f3f2..595d2494fdf94fd2df9f38ef9cde5a5e9c7c91b1 100644 (file)
@@ -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;
index 7613b7828d12803668e28bf043c1f5f7bbfd0bfe..3378bdf3f121a3f9bd8c206f1c2ee1c5aaa4acf1 100644 (file)
@@ -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;
index 200c13958fe0f663d666de22778f9f9ec4b9d91a..aa4fca0cf17f6d5b8769dd4f66c08edc48027b7d 100644 (file)
@@ -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;
index 2e92db29d30211f0310fe005c325dc77c15a7571..5bfaed38c965ba8d7ff24df1a7149b4b31c4d683 100644 (file)
@@ -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;
index 9a5c3578d77e84e61d58e3a44347a8b335107b4f..50f576dd16f2872db84dff80abaa9408d34f0d69 100644 (file)
@@ -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;
index 7d53607f877a86134ea07f6bd00dd5cd66750c3d..0301366c2e29ba07dd6afa10821ab7beb4b59472 100644 (file)
@@ -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);
 
 
index 54d4f979f74b6dd0dc6da2d59914a97dad6d4fc6..49f59e3a7638f934de9e0bc943566dcb245d1dfd 100644 (file)
@@ -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)
index 35331ce224a8001e4765fa6079e0c115b0e841ed..7d9c18dc9db0ae642c4a8447573da3a346505e29 100644 (file)
@@ -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;
index 75bf091bcb72422715850cea7a8d841af7ee1d8a..ed4bc357e01253f9dc3d042b9b02493c7fe2ff20 100644 (file)
@@ -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)
index ecea32633c76e0cfeb3084ff4b779ea6bd0425a8..051e6e7ab5bd61f6a19a4a185796cfe03a7c34ab 100644 (file)
@@ -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;
index 6a979c13640018de3aa774b8ee646736271fdfd6..caee91a7fb560133b0fe9ffd7d572baa500c1c12 100644 (file)
@@ -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
index 45944cefc262ed7178d0b1d3e9ac30c8dcf16987..7bc2f00ec80ae112e859bd678ccea619d8b7aafa 100644 (file)
@@ -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);
 }
index 8c461e16304635b85f975fe74fe16d3a151f807c..22d354a5c26a567f98c829a054441433cdd1250f 100644 (file)
@@ -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);
index 1b35ba0d78063df3707ad3711dbb5a9b65c91efc..f3e13ed5cd54f678199971c2a024778ecbeab28a 100644 (file)
@@ -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);
       }
index 7ce81e8af7c24a2ddb4b705d26043236fcea5adb..bf4f95763b424964eee9f27f4aa6b4fd395b9465 100644 (file)
@@ -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;
index 5c8d52f696be9985a2958aab04a39a8a04c93231..798a33a2d5cb429a25c821c4a82ebeb34d03d17e 100644 (file)
@@ -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,
index 102662ace6401a8c8c5811c926f5d0de6b81fc5f..2fb16de4303fc458eac9fa1f870b30bfa15585bf 100644 (file)
--- 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;
index 094ff42cd7242172cfc0e733c1ea281c704a7b7a..041e98589be9c03cffd67d5b0aebda1739310f99 100644 (file)
@@ -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;
index edcc683261e3c51601b1d7fa90c8b8fa0a3e6af4..f83db977adf1078c3668a6e4ee1b6991ea7e92ea 100644 (file)
@@ -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);
index a83288dd00a1c33244ff2b0f819e551ada13007d..f64656b3e9d2a35a591caab1d8501d6394c13b06 100644 (file)
@@ -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)
index 91fa10ada66d799137d011f137245fb530a49470..7714f4ff3e1894f44405735aac7fe757e83e1b2e 100644 (file)
@@ -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;
     }
index 476f9c002e190e9bfbf22a972e5c3e190344f2ed..1297b0de76219bf323d11fa9fff3e77fd4315a48 100644 (file)
@@ -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;
index 33d51e3b15b903bf77407193372504270c7215cc..04fcc4a13b19e036f5681b06312effe7912ea5d3 100644 (file)
@@ -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);
 
 /**
index 74b744c7157e97ab2f0c118d1162d3fbeadd8329..5ff8cec405ce9e052ec7210569620e16349fa1c2 100644 (file)
@@ -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 */
index b707a6ebe36d874cb5e05e6ae21f2e9970fa8ccc..c8466280a20303f457cc4e11d95d0b1efed0e5d5 100644 (file)
@@ -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,
index 1f67f2362e77588c60322cc8d97878d42debeae5..5e0a3ee1271ac61949fb15f111d43d38bfe065b6 100644 (file)
@@ -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;
index dafde44f26bcac2f5553fd2a7a74ab72c58bde50..6b3d5fb0f12635c3fd6c1f592c66192d87520f4d 100644 (file)
@@ -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);
index 6f01c19aa5c31886641865f160879b9be4d86d14..e3470f999d6316a0b43266faef050f7f58088661 100644 (file)
@@ -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);
     }
index 20a05636d384180c58a02c39883c0bef007b2904..120e8f8d51ae85d573f885ba96bbdfad0421257a 100644 (file)
@@ -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
index 1b566d1ab21d9da10f31fdd0c7c153c663165d0e..c7bf3b7fb861222ec592e41b107b3c08f08e6289 100644 (file)
@@ -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);
 
index 47c5528c29c90d1bd271be09cf5caad3262b7e27..c5a762d545f69f51cd034125eaca969c11725ed0 100644 (file)
@@ -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)
index 39c22c2003f9d986517c2d47213be2a42ff50bfb..3640c6f57686b9bee361d70f2eb33823bd27c454 100644 (file)
@@ -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;
index 154ce5fab0744aaea8f7a32933370ef4bc3600db..5f3653efeba9763799f116ef90a2fb6e556d1fb9 100644 (file)
@@ -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) {
index 2b60f7fba876ab5cf0ff546d2ccc3b91ed4ca819..326146b041b31b1654363532acc2e986ca4f4396 100644 (file)
@@ -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);
index bdcd08ab991740978e24123af70b6449357adc23..160907ff0ac8c4c6cd4136632cef79ea1d4a76a5 100644 (file)
@@ -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)
index f9bb2f824715ce7510c5619e2515cc9a27eeba1a..9808f5ecd89dd9f43a8bc7604fa806875e084938 100644 (file)
@@ -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) {
index c2803e8bfc751662ced6509000df012b5ffe34be..a45e6ab6a4a1fad0a79f33c77903e86b037de371 100644 (file)
@@ -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) {
index 96e7197d4530260909c4bec1a74b098c50ec8036..c5f5b0abcb1f2538a2765c5cb5d1dc3632d08d05 100644 (file)
@@ -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);
index 0ff36d99d6ba5e452d86d2194f776e63e879d5a4..1c980f040d3d7ff90e985ed4ebd40ac5a8d85dce 100644 (file)
@@ -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);
index 3c2d94950c2d9b7a90d6c8073c6fadb6ff7f1ff1..3e8a4e818e50307b308fba08cf096c37054758fd 100644 (file)
--- 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);