]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
vtls: change send/recv signatures of tls backends
authorStefan Eissing <stefan@eissing.org>
Wed, 11 Jun 2025 12:50:15 +0000 (14:50 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 21 Jun 2025 08:34:02 +0000 (10:34 +0200)
Similar to connection filter changes, return a CURLcode and the
read/written amount as size_t *.

Closes #17593

lib/vtls/gtls.c
lib/vtls/mbedtls.c
lib/vtls/openssl.c
lib/vtls/rustls.c
lib/vtls/schannel.c
lib/vtls/vtls.c
lib/vtls/vtls_int.h
lib/vtls/wolfssl.c

index 9fe09ac0ceb94f75c4a7dd6ce8ed3ea95ba2afa0..9ca0108c2f26d1e8494c0e49296368dad3945c10 100644 (file)
@@ -1948,48 +1948,49 @@ static bool gtls_data_pending(struct Curl_cfilter *cf,
   return FALSE;
 }
 
-static ssize_t gtls_send(struct Curl_cfilter *cf,
-                         struct Curl_easy *data,
-                         const void *buf,
-                         size_t blen,
-                         CURLcode *curlcode)
+static CURLcode gtls_send(struct Curl_cfilter *cf,
+                          struct Curl_easy *data,
+                          const void *buf,
+                          size_t blen,
+                          size_t *pnwritten)
 {
   struct ssl_connect_data *connssl = cf->ctx;
   struct gtls_ssl_backend_data *backend =
     (struct gtls_ssl_backend_data *)connssl->backend;
-  ssize_t rc;
-  size_t nwritten, total_written = 0;
+  CURLcode result = CURLE_OK;
+  ssize_t nwritten;
+  size_t remain = blen;
 
   (void)data;
   DEBUGASSERT(backend);
+  *pnwritten = 0;
 
-  while(blen) {
+  while(remain) {
     backend->gtls.io_result = CURLE_OK;
-    rc = gnutls_record_send(backend->gtls.session, buf, blen);
+    nwritten = gnutls_record_send(backend->gtls.session, buf, remain);
 
-    if(rc < 0) {
-      if(total_written && (rc == GNUTLS_E_AGAIN)) {
-        *curlcode = CURLE_OK;
-        rc = (ssize_t)total_written;
+    if(nwritten >= 0) {
+      *pnwritten += (size_t)nwritten;
+      DEBUGASSERT((size_t)nwritten <= remain);
+      buf = (char *)CURL_UNCONST(buf) + (size_t)nwritten;
+      remain -= (size_t)nwritten;
+    }
+    else {
+      if(*pnwritten && (nwritten == GNUTLS_E_AGAIN)) {
+        result = CURLE_OK;
         goto out;
       }
-      *curlcode = (rc == GNUTLS_E_AGAIN) ?
+      result = (nwritten == GNUTLS_E_AGAIN) ?
         CURLE_AGAIN :
         (backend->gtls.io_result ? backend->gtls.io_result : CURLE_SEND_ERROR);
-
-      rc = -1;
       goto out;
     }
-    nwritten = (size_t)rc;
-    total_written += nwritten;
-    DEBUGASSERT(nwritten <= blen);
-    buf = (char *)CURL_UNCONST(buf) + nwritten;
-    blen -= nwritten;
   }
-  rc = total_written;
 
 out:
-  return rc;
+  CURL_TRC_CF(data, cf, "gtls_send(len=%zu) -> %d, %zu",
+              blen, result, *pnwritten);
+  return result;
 }
 
 /*
@@ -2095,50 +2096,49 @@ static void gtls_close(struct Curl_cfilter *cf,
 #endif
 }
 
-static ssize_t gtls_recv(struct Curl_cfilter *cf,
-                         struct Curl_easy *data,
-                         char *buf,
-                         size_t buffersize,
-                         CURLcode *curlcode)
+static CURLcode gtls_recv(struct Curl_cfilter *cf,
+                          struct Curl_easy *data,
+                          char *buf, size_t blen,
+                          size_t *pnread)
 {
   struct ssl_connect_data *connssl = cf->ctx;
   struct gtls_ssl_backend_data *backend =
     (struct gtls_ssl_backend_data *)connssl->backend;
-  ssize_t ret;
+  CURLcode result = CURLE_OK;
+  ssize_t nread;
 
   (void)data;
   DEBUGASSERT(backend);
 
-  ret = gnutls_record_recv(backend->gtls.session, buf, buffersize);
-  if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
-    *curlcode = CURLE_AGAIN;
-    ret = -1;
-    goto out;
-  }
+  nread = gnutls_record_recv(backend->gtls.session, buf, blen);
 
-  if(ret == GNUTLS_E_REHANDSHAKE) {
-    /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
-       proper way" takes a whole lot of work. */
-    CURLcode result = handshake(cf, data);
-    if(result)
-      *curlcode = result;
-    else
-      *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
-    ret = -1;
-    goto out;
-  }
-
-  if(ret < 0) {
-    failf(data, "GnuTLS recv error (%d): %s",
-          (int)ret, gnutls_strerror((int)ret));
-    *curlcode = backend->gtls.io_result ?
-      backend->gtls.io_result : CURLE_RECV_ERROR;
-    ret = -1;
-    goto out;
+  if(nread >= 0)
+    *pnread = (size_t)nread;
+  else {
+    if((nread == GNUTLS_E_AGAIN) || (nread == GNUTLS_E_INTERRUPTED)) {
+      result = CURLE_AGAIN;
+      goto out;
+    }
+    else if(nread == GNUTLS_E_REHANDSHAKE) {
+      /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
+         proper way" takes a whole lot of work. */
+      result = handshake(cf, data);
+      if(!result)
+        result = CURLE_AGAIN; /* then return as if this was a wouldblock */
+      goto out;
+    }
+    else {
+      failf(data, "GnuTLS recv error (%d): %s",
+            (int)nread, gnutls_strerror((int)nread));
+      result = backend->gtls.io_result ?
+        backend->gtls.io_result : CURLE_RECV_ERROR;
+      goto out;
+    }
   }
 
 out:
-  return ret;
+  CURL_TRC_CF(data, cf, "gtls_recv(len=%zu) -> 0, %zu", blen, *pnread);
+  return result;
 }
 
 size_t Curl_gtls_version(char *buffer, size_t size)
index 3e94fdff0896925e236957c14b7626e93a81738e..80d43aec860ae6af8a391347dbef2314338604ef 100644 (file)
@@ -1203,16 +1203,18 @@ out:
   return result;
 }
 
-static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data,
-                         const void *mem, size_t len,
-                         CURLcode *curlcode)
+static CURLcode mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+                          const void *mem, size_t len,
+                          size_t *pnwritten)
 {
   struct ssl_connect_data *connssl = cf->ctx;
   struct mbed_ssl_backend_data *backend =
     (struct mbed_ssl_backend_data *)connssl->backend;
-  int ret = -1;
+  CURLcode result = CURLE_OK;
+  int nwritten;
 
   (void)data;
+  *pnwritten = 0;
   DEBUGASSERT(backend);
   /* mbedtls is picky when a mbedtls_ssl_write) was previously blocked.
    * It requires to be called with the same amount of bytes again, or it
@@ -1225,28 +1227,29 @@ static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data,
     len = backend->send_blocked_len;
   }
 
-  ret = mbedtls_ssl_write(&backend->ssl, (const unsigned char *)mem, len);
+  nwritten = mbedtls_ssl_write(&backend->ssl, (const unsigned char *)mem, len);
 
-  if(ret < 0) {
+  if(nwritten >= 0) {
+    *pnwritten = (size_t)nwritten;
+    backend->send_blocked = FALSE;
+  }
+  else {
     CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> -0x%04X",
-                len, -ret);
-    *curlcode = ((ret == MBEDTLS_ERR_SSL_WANT_WRITE)
+                len, -nwritten);
+    result = ((nwritten == MBEDTLS_ERR_SSL_WANT_WRITE)
 #ifdef HAS_TLS13_SUPPORT
-      || (ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
+      || (nwritten == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
 #endif
       ) ? CURLE_AGAIN : CURLE_SEND_ERROR;
-    ret = -1;
-    if((*curlcode == CURLE_AGAIN) && !backend->send_blocked) {
+    if((result == CURLE_AGAIN) && !backend->send_blocked) {
       backend->send_blocked = TRUE;
       backend->send_blocked_len = len;
     }
   }
-  else {
-    CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> %d", len, ret);
-    backend->send_blocked = FALSE;
-  }
 
-  return ret;
+  CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> %d, %zu",
+              len, result, *pnwritten);
+  return result;
 }
 
 static CURLcode mbedtls_shutdown(struct Curl_cfilter *cf,
@@ -1365,48 +1368,48 @@ static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data)
   }
 }
 
-static ssize_t mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
-                         char *buf, size_t buffersize,
-                         CURLcode *curlcode)
+static CURLcode mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+                          char *buf, size_t buffersize,
+                          size_t *pnread)
 {
   struct ssl_connect_data *connssl = cf->ctx;
   struct mbed_ssl_backend_data *backend =
     (struct mbed_ssl_backend_data *)connssl->backend;
-  int ret = -1;
+  CURLcode result = CURLE_OK;
+  int nread;
 
   (void)data;
   DEBUGASSERT(backend);
+  *pnread = 0;
 
-  ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf,
-                         buffersize);
-  if(ret <= 0) {
+  nread = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, buffersize);
+  if(nread > 0)
+    *pnread = (size_t)nread;
+  else {
     CURL_TRC_CF(data, cf, "mbedtls_ssl_read(len=%zu) -> -0x%04X",
-                buffersize, -ret);
-    switch(ret) {
+                buffersize, -nread);
+    switch(nread) {
 #ifdef HAS_SESSION_TICKETS
     case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET:
       mbed_new_session(cf, data);
       FALLTHROUGH();
 #endif
     case MBEDTLS_ERR_SSL_WANT_READ:
-      *curlcode = CURLE_AGAIN;
-      ret = -1;
+      result = CURLE_AGAIN;
       break;
     case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
-      *curlcode = CURLE_OK;
-      ret = 0;
+      result = CURLE_OK;
       break;
     default: {
       char errorbuf[128];
-      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-      failf(data, "ssl_read returned: (-0x%04X) %s", -ret, errorbuf);
-      *curlcode = CURLE_RECV_ERROR;
-      ret = -1;
+      mbedtls_strerror(nread, errorbuf, sizeof(errorbuf));
+      failf(data, "ssl_read returned: (-0x%04X) %s", -nread, errorbuf);
+      result = CURLE_RECV_ERROR;
       break;
     }
     }
   }
-  return (ssize_t)ret;
+  return result;
 }
 
 static size_t mbedtls_version(char *buffer, size_t size)
index e7a82fffd58b9362dc96e8e7281165a9378ef97b..d5f98eff27a87dda480cea496068ba62e1cd09a9 100644 (file)
@@ -2177,6 +2177,8 @@ static CURLcode ossl_shutdown(struct Curl_cfilter *cf,
 
 out:
   cf->shutdown = (result || *done);
+  if(cf->shutdown || (connssl->io_need != CURL_SSL_IO_NEED_NONE))
+    connssl->input_pending = FALSE;
   return result;
 }
 
@@ -2188,6 +2190,7 @@ static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
   (void)data;
   DEBUGASSERT(octx);
 
+  connssl->input_pending = FALSE;
   if(octx->ssl) {
     SSL_free(octx->ssl);
     octx->ssl = NULL;
@@ -5227,11 +5230,11 @@ static bool ossl_data_pending(struct Curl_cfilter *cf,
   return connssl->input_pending;
 }
 
-static ssize_t ossl_send(struct Curl_cfilter *cf,
-                         struct Curl_easy *data,
-                         const void *mem,
-                         size_t len,
-                         CURLcode *curlcode)
+static CURLcode ossl_send(struct Curl_cfilter *cf,
+                          struct Curl_easy *data,
+                          const void *mem,
+                          size_t len,
+                          size_t *pnwritten)
 {
   /* SSL_write() is said to return 'int' while write() and send() returns
      'size_t' */
@@ -5239,39 +5242,39 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
   char error_buffer[256];
   sslerr_t sslerror;
   int memlen;
-  int rc;
   struct ssl_connect_data *connssl = cf->ctx;
   struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
+  CURLcode result = CURLE_OK;
+  int nwritten;
 
   (void)data;
   DEBUGASSERT(octx);
-
+  *pnwritten = 0;
   ERR_clear_error();
 
   connssl->io_need = CURL_SSL_IO_NEED_NONE;
   memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
-  rc = SSL_write(octx->ssl, mem, memlen);
+  nwritten = SSL_write(octx->ssl, mem, memlen);
 
-  if(rc <= 0) {
-    err = SSL_get_error(octx->ssl, rc);
+  if(nwritten > 0)
+    *pnwritten = (size_t)nwritten;
+  else {
+    err = SSL_get_error(octx->ssl, nwritten);
 
     switch(err) {
     case SSL_ERROR_WANT_READ:
       connssl->io_need = CURL_SSL_IO_NEED_RECV;
-      *curlcode = CURLE_AGAIN;
-      rc = -1;
+      result = CURLE_AGAIN;
       goto out;
     case SSL_ERROR_WANT_WRITE:
-      *curlcode = CURLE_AGAIN;
-      rc = -1;
+      result = CURLE_AGAIN;
       goto out;
     case SSL_ERROR_SYSCALL:
     {
       int sockerr = SOCKERRNO;
 
       if(octx->io_result == CURLE_AGAIN) {
-        *curlcode = CURLE_AGAIN;
-        rc = -1;
+        result = CURLE_AGAIN;
         goto out;
       }
       sslerror = ERR_get_error();
@@ -5285,8 +5288,7 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
 
       failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
             error_buffer, sockerr);
-      *curlcode = CURLE_SEND_ERROR;
-      rc = -1;
+      result = CURLE_SEND_ERROR;
       goto out;
     }
     case SSL_ERROR_SSL: {
@@ -5295,49 +5297,50 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
       sslerror = ERR_get_error();
       failf(data, "SSL_write() error: %s",
             ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
-      *curlcode = CURLE_SEND_ERROR;
-      rc = -1;
+      result = CURLE_SEND_ERROR;
       goto out;
     }
     default:
       /* a true error */
       failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
             SSL_ERROR_to_str(err), SOCKERRNO);
-      *curlcode = CURLE_SEND_ERROR;
-      rc = -1;
+      result = CURLE_SEND_ERROR;
       goto out;
     }
   }
-  *curlcode = CURLE_OK;
 
 out:
-  return (ssize_t)rc; /* number of bytes */
+  return result;
 }
 
-static ssize_t ossl_recv(struct Curl_cfilter *cf,
-                         struct Curl_easy *data,   /* transfer */
-                         char *buf,                /* store read data here */
-                         size_t buffersize,        /* max amount to read */
-                         CURLcode *curlcode)
+static CURLcode ossl_recv(struct Curl_cfilter *cf,
+                          struct Curl_easy *data,   /* transfer */
+                          char *buf,                /* store read data here */
+                          size_t buffersize,        /* max amount to read */
+                          size_t *pnread)
 {
   char error_buffer[256];
   unsigned long sslerror;
-  ssize_t nread;
   int buffsize;
   struct connectdata *conn = cf->conn;
   struct ssl_connect_data *connssl = cf->ctx;
   struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
+  CURLcode result = CURLE_OK;
+  int nread;
 
   (void)data;
   DEBUGASSERT(octx);
 
+  *pnread = 0;
   ERR_clear_error();
 
   connssl->io_need = CURL_SSL_IO_NEED_NONE;
   buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
-  nread = (ssize_t)SSL_read(octx->ssl, buf, buffsize);
+  nread = SSL_read(octx->ssl, buf, buffsize);
 
-  if(nread <= 0) {
+  if(nread > 0)
+    *pnread = (size_t)nread;
+  else {
     /* failed SSL_read */
     int err = SSL_get_error(octx->ssl, (int)nread);
 
@@ -5352,21 +5355,18 @@ static ssize_t ossl_recv(struct Curl_cfilter *cf,
         connclose(conn, "TLS close_notify");
       break;
     case SSL_ERROR_WANT_READ:
-      *curlcode = CURLE_AGAIN;
-      nread = -1;
+      result = CURLE_AGAIN;
       goto out;
     case SSL_ERROR_WANT_WRITE:
       connssl->io_need = CURL_SSL_IO_NEED_SEND;
-      *curlcode = CURLE_AGAIN;
-      nread = -1;
+      result = CURLE_AGAIN;
       goto out;
     default:
       /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return
          value/errno" */
       /* https://docs.openssl.org/master/man3/ERR_get_error/ */
       if(octx->io_result == CURLE_AGAIN) {
-        *curlcode = CURLE_AGAIN;
-        nread = -1;
+        result = CURLE_AGAIN;
         goto out;
       }
       sslerror = ERR_get_error();
@@ -5383,18 +5383,17 @@ static ssize_t ossl_recv(struct Curl_cfilter *cf,
                     SSL_ERROR_to_str(err));
         failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d",
               error_buffer, sockerr);
-        *curlcode = CURLE_RECV_ERROR;
-        nread = -1;
+        result = CURLE_RECV_ERROR;
         goto out;
       }
       else if(err == SSL_ERROR_SYSCALL) {
         if(octx->io_result) {
           /* logging handling in underlying filter already */
-          *curlcode = octx->io_result;
+          result = octx->io_result;
         }
         else if(connssl->peer_closed) {
           failf(data, "Connection closed abruptly");
-          *curlcode = CURLE_RECV_ERROR;
+          result = CURLE_RECV_ERROR;
         }
         else {
           /* We should no longer get here nowadays. But handle
@@ -5408,16 +5407,15 @@ static ssize_t ossl_recv(struct Curl_cfilter *cf,
           }
           failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d",
                 error_buffer, sockerr);
-          *curlcode = CURLE_RECV_ERROR;
+          result = CURLE_RECV_ERROR;
         }
-        nread = -1;
         goto out;
       }
     }
   }
 
 out:
-  if(!nread || ((nread < 0) && (*curlcode == CURLE_AGAIN))) {
+  if((!result && !*pnread) || (result == CURLE_AGAIN)) {
     /* This happens when:
      * - we read an EOF
      * - OpenSSLs buffers are empty, there is no more data
@@ -5426,7 +5424,9 @@ out:
      *   until more data arrives */
     connssl->input_pending = FALSE;
   }
-  return nread;
+  CURL_TRC_CF(data, cf, "ossl_recv(len=%zu) -> %d, %zu (in_pending=%d)",
+              buffersize, result, *pnread, connssl->input_pending);
+  return result;
 }
 
 static CURLcode ossl_get_channel_binding(struct Curl_easy *data, int sockindex,
index 391dede4c9c23d09d794d3ce7a414767e3eb971f..24f646078d8f6308cc6559f7a3467f4d8579ba14 100644 (file)
@@ -195,37 +195,37 @@ static ssize_t tls_recv_more(struct Curl_cfilter *cf,
  * buffer, and process packets, but will not consume bytes from Rustls'
  * plaintext output buffer.
  */
-static ssize_t
+static CURLcode
 cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
-            char *plainbuf, size_t plainlen, CURLcode *err)
+            char *plainbuf, size_t plainlen, size_t *pnread)
 {
   const struct ssl_connect_data *const connssl = cf->ctx;
   struct rustls_ssl_backend_data *const backend =
     (struct rustls_ssl_backend_data *)connssl->backend;
   struct rustls_connection *rconn = NULL;
+  CURLcode result = CURLE_OK;
   size_t n = 0;
-  size_t plain_bytes_copied = 0;
   rustls_result rresult = 0;
-  ssize_t nread;
   bool eof = FALSE;
 
   DEBUGASSERT(backend);
+  *pnread = 0;
   rconn = backend->conn;
 
-  while(plain_bytes_copied < plainlen) {
+  while(*pnread < plainlen) {
     if(!backend->data_in_pending) {
-      if(tls_recv_more(cf, data, err) < 0) {
-        if(*err != CURLE_AGAIN) {
-          nread = -1;
+      if(tls_recv_more(cf, data, &result) < 0) {
+        if(result != CURLE_AGAIN) {
           goto out;
         }
+        result = CURLE_OK;
         break;
       }
     }
 
     rresult = rustls_connection_read(rconn,
-                                     (uint8_t *)plainbuf + plain_bytes_copied,
-                                     plainlen - plain_bytes_copied,
+                                     (uint8_t *)plainbuf + *pnread,
+                                     plainlen - *pnread,
                                      &n);
     if(rresult == RUSTLS_RESULT_PLAINTEXT_EMPTY) {
       backend->data_in_pending = FALSE;
@@ -233,15 +233,13 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
     else if(rresult == RUSTLS_RESULT_UNEXPECTED_EOF) {
       failf(data, "rustls: peer closed TCP connection "
             "without first closing TLS connection");
-      *err = CURLE_RECV_ERROR;
-      nread = -1;
+      result = CURLE_RECV_ERROR;
       goto out;
     }
     else if(rresult != RUSTLS_RESULT_OK) {
       /* n always equals 0 in this case, do not need to check it */
       rustls_failf(data, rresult, "rustls_connection_read");
-      *err = CURLE_RECV_ERROR;
-      nread = -1;
+      result = CURLE_RECV_ERROR;
       goto out;
     }
     else if(n == 0) {
@@ -252,27 +250,18 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
       break;
     }
     else {
-      plain_bytes_copied += n;
+      *pnread += n;
     }
   }
 
-  if(plain_bytes_copied) {
-    *err = CURLE_OK;
-    nread = (ssize_t)plain_bytes_copied;
-  }
-  else if(eof) {
-    *err = CURLE_OK;
-    nread = 0;
-  }
-  else {
-    *err = CURLE_AGAIN;
-    nread = -1;
+  if(!eof && !*pnread) {
+    result = CURLE_AGAIN;
   }
 
 out:
-  CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d",
-              plainlen, nread, *err);
-  return nread;
+  CURL_TRC_CF(data, cf, "rustls_recv(len=%zu) -> %d, %zu",
+              plainlen, result, *pnread);
+  return result;
 }
 
 static CURLcode cr_flush_out(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -320,9 +309,9 @@ static CURLcode cr_flush_out(struct Curl_cfilter *cf, struct Curl_easy *data,
  * In that case, it will not read anything into Rustls' plaintext input buffer.
  * It will only drain Rustls' plaintext output buffer into the socket.
  */
-static ssize_t
+static CURLcode
 cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
-        const void *plainbuf, size_t plainlen, CURLcode *err)
+        const void *plainbuf, size_t plainlen, size_t *pnwritten)
 {
   const struct ssl_connect_data *const connssl = cf->ctx;
   struct rustls_ssl_backend_data *const backend =
@@ -330,10 +319,11 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
   struct rustls_connection *rconn = NULL;
   size_t plainwritten = 0;
   const unsigned char *buf = plainbuf;
+  CURLcode result = CURLE_OK;
   size_t blen = plainlen;
-  ssize_t nwritten = 0;
 
   DEBUGASSERT(backend);
+  *pnwritten = 0;
   rconn = backend->conn;
   DEBUGASSERT(rconn);
 
@@ -344,18 +334,18 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
    * if successful, deduct the previous plain bytes from the current
    * send. */
   if(backend->plain_out_buffered) {
-    *err = cr_flush_out(cf, data, rconn);
+    result = cr_flush_out(cf, data, rconn);
     CURL_TRC_CF(data, cf, "cf_send: flushing %zu previously added bytes -> %d",
-                backend->plain_out_buffered, *err);
-    if(*err)
-      return -1;
+                backend->plain_out_buffered, result);
+    if(result)
+      return result;
     if(blen > backend->plain_out_buffered) {
       blen -= backend->plain_out_buffered;
       buf += backend->plain_out_buffered;
     }
     else
       blen = 0;
-    nwritten += (ssize_t)backend->plain_out_buffered;
+    *pnwritten += (ssize_t)backend->plain_out_buffered;
     backend->plain_out_buffered = 0;
   }
 
@@ -365,37 +355,35 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
     rresult = rustls_connection_write(rconn, buf, blen, &plainwritten);
     if(rresult != RUSTLS_RESULT_OK) {
       rustls_failf(data, rresult, "rustls_connection_write");
-      *err = CURLE_WRITE_ERROR;
-      return -1;
+      result = CURLE_WRITE_ERROR;
+      goto out;
     }
     else if(plainwritten == 0) {
       failf(data, "rustls_connection_write: EOF");
-      *err = CURLE_WRITE_ERROR;
-      return -1;
+      result = CURLE_WRITE_ERROR;
+      goto out;
     }
   }
 
-  *err = cr_flush_out(cf, data, rconn);
-  if(*err) {
-    if(CURLE_AGAIN == *err) {
+  result = cr_flush_out(cf, data, rconn);
+  if(result) {
+    if(CURLE_AGAIN == result) {
       /* The TLS bytes may have been partially written, but we fail the
        * complete send() and remember how much we already added to Rustls. */
-      CURL_TRC_CF(data, cf, "cf_send: EAGAIN, remember we added %zu plain"
-                  " bytes already to Rustls", blen);
       backend->plain_out_buffered = plainwritten;
-      if(nwritten) {
-        *err = CURLE_OK;
-        return (ssize_t)nwritten;
+      if(*pnwritten) {
+        result = CURLE_OK;
       }
     }
-    return -1;
+    goto out;
   }
   else
-    nwritten += (ssize_t)plainwritten;
+    *pnwritten += (ssize_t)plainwritten;
 
-  CURL_TRC_CF(data, cf, "cf_send(len=%zu) -> %d, %zd",
-              plainlen, *err, nwritten);
-  return nwritten;
+out:
+  CURL_TRC_CF(data, cf, "rustls_send(len=%zu) -> %d, %zd",
+              plainlen, result, *pnwritten);
+  return result;
 }
 
 /* A server certificate verify callback for Rustls that always returns
@@ -1184,8 +1172,9 @@ cr_connect(struct Curl_cfilter *cf,
        * send its FINISHED message off. We attempt to let it write
        * one more time. Oh my.
        */
+      size_t nwritten;
       cr_set_negotiated_alpn(cf, data, rconn);
-      cr_send(cf, data, NULL, 0, &tmperr);
+      tmperr = cr_send(cf, data, NULL, 0, &nwritten);
       if(tmperr == CURLE_AGAIN) {
         connssl->io_need = CURL_SSL_IO_NEED_SEND;
         return CURLE_OK;
@@ -1258,8 +1247,9 @@ cr_connect(struct Curl_cfilter *cf,
     DEBUGASSERT(wants_read || wants_write);
 
     if(wants_write) {
+      size_t nwritten;
       CURL_TRC_CF(data, cf, "rustls_connection wants us to write_tls.");
-      cr_send(cf, data, NULL, 0, &tmperr);
+      tmperr = cr_send(cf, data, NULL, 0, &nwritten);
       if(tmperr == CURLE_AGAIN) {
         CURL_TRC_CF(data, cf, "writing would block");
         connssl->io_need = CURL_SSL_IO_NEED_SEND;
@@ -1312,8 +1302,7 @@ cr_shutdown(struct Curl_cfilter *cf,
   struct rustls_ssl_backend_data *backend =
     (struct rustls_ssl_backend_data *)connssl->backend;
   CURLcode result = CURLE_OK;
-  ssize_t nwritten, nread;
-  size_t i;
+  size_t i, nread, nwritten;
 
   DEBUGASSERT(backend);
   if(!backend->conn || cf->shutdown) {
@@ -1332,8 +1321,8 @@ cr_shutdown(struct Curl_cfilter *cf,
     }
   }
 
-  nwritten = cr_send(cf, data, NULL, 0, &result);
-  if(nwritten < 0) {
+  result = cr_send(cf, data, NULL, 0, &nwritten);
+  if(result) {
     if(result == CURLE_AGAIN) {
       connssl->io_need = CURL_SSL_IO_NEED_SEND;
       result = CURLE_OK;
@@ -1346,26 +1335,23 @@ cr_shutdown(struct Curl_cfilter *cf,
 
   for(i = 0; i < 10; ++i) {
     char buf[1024];
-    nread = cr_recv(cf, data, buf, (int)sizeof(buf), &result);
-    if(nread <= 0)
+    result = cr_recv(cf, data, buf, (int)sizeof(buf), &nread);
+    if(result)
       break;
   }
 
-  if(nread > 0) {
-    /* still data coming in? */
-  }
-  else if(nread == 0) {
-    /* We got the close notify alert and are done. */
-    *done = TRUE;
-  }
-  else if(result == CURLE_AGAIN) {
+  if(result == CURLE_AGAIN) {
     connssl->io_need = CURL_SSL_IO_NEED_RECV;
     result = CURLE_OK;
   }
-  else {
+  else if(result) {
     DEBUGASSERT(result);
     CURL_TRC_CF(data, cf, "shutdown, error: %d", result);
   }
+  else if(nread == 0) {
+    /* We got the close notify alert and are done. */
+    *done = TRUE;
+  }
 
 out:
   cf->shutdown = (result || *done);
index 0dfca379621b7d75ea5e9c97cd235093c503f619..6afb4fe19cc3736258c2cc5f540cb1f927327265 100644 (file)
@@ -1714,22 +1714,22 @@ static CURLcode schannel_connect(struct Curl_cfilter *cf,
   return CURLE_OK;
 }
 
-static ssize_t
+static CURLcode
 schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data,
-              const void *buf, size_t len, CURLcode *err)
+              const void *buf, size_t len, size_t *pnwritten)
 {
-  ssize_t written = -1;
   size_t data_len = 0;
   unsigned char *ptr = NULL;
   struct ssl_connect_data *connssl = cf->ctx;
   SecBuffer outbuf[4];
   SecBufferDesc outbuf_desc;
   SECURITY_STATUS sspi_status = SEC_E_OK;
-  CURLcode result;
+  CURLcode result = CURLE_OK;
   struct schannel_ssl_backend_data *backend =
     (struct schannel_ssl_backend_data *)connssl->backend;
 
   DEBUGASSERT(backend);
+  *pnwritten = 0;
 
   /* check if the maximum stream sizes were queried */
   if(backend->stream_sizes.cbMaximumMessage == 0) {
@@ -1738,8 +1738,7 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data,
       SECPKG_ATTR_STREAM_SIZES,
       &backend->stream_sizes);
     if(sspi_status != SEC_E_OK) {
-      *err = CURLE_SEND_ERROR;
-      return -1;
+      return CURLE_SEND_ERROR;
     }
   }
 
@@ -1753,8 +1752,7 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data,
     backend->stream_sizes.cbTrailer;
   ptr = (unsigned char *) malloc(data_len);
   if(!ptr) {
-    *err = CURLE_OUT_OF_MEMORY;
-    return -1;
+    return CURLE_OUT_OF_MEMORY;
   }
 
   /* setup output buffers (header, data, trailer, empty) */
@@ -1777,7 +1775,6 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data,
 
   /* check if the message was encrypted */
   if(sspi_status == SEC_E_OK) {
-    written = 0;
 
     /* send the encrypted message including header, data and trailer */
     len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
@@ -1799,16 +1796,15 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data,
     */
 
     /* send entire message or fail */
-    while(len > (size_t)written) {
+    while(len > *pnwritten) {
       size_t this_write = 0;
       int what;
       timediff_t timeout_ms = Curl_timeleft(data, NULL, FALSE);
       if(timeout_ms < 0) {
         /* we already got the timeout */
         failf(data, "schannel: timed out sending data "
-              "(bytes sent: %zd)", written);
-        *err = CURLE_OPERATION_TIMEDOUT;
-        written = -1;
+              "(bytes sent: %zu)", *pnwritten);
+        result = CURLE_OPERATION_TIMEDOUT;
         break;
       }
       else if(!timeout_ms)
@@ -1817,53 +1813,49 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data,
       if(what < 0) {
         /* fatal error */
         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
-        *err = CURLE_SEND_ERROR;
-        written = -1;
+        result = CURLE_SEND_ERROR;
         break;
       }
       else if(0 == what) {
         failf(data, "schannel: timed out sending data "
-              "(bytes sent: %zd)", written);
-        *err = CURLE_OPERATION_TIMEDOUT;
-        written = -1;
+              "(bytes sent: %zu)", *pnwritten);
+        result = CURLE_OPERATION_TIMEDOUT;
         break;
       }
       /* socket is writable */
 
        result = Curl_conn_cf_send(cf->next, data,
-                                  ptr + written, len - written,
+                                  ptr + *pnwritten, len - *pnwritten,
                                   FALSE, &this_write);
       if(result == CURLE_AGAIN)
         continue;
       else if(result != CURLE_OK) {
-        *err = result;
-        written = -1;
         break;
       }
 
-      written += (ssize_t)this_write;
+      *pnwritten += this_write;
     }
   }
   else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) {
-    *err = CURLE_OUT_OF_MEMORY;
+    result = CURLE_OUT_OF_MEMORY;
   }
   else{
-    *err = CURLE_SEND_ERROR;
+    result = CURLE_SEND_ERROR;
   }
 
   Curl_safefree(ptr);
 
-  if(len == (size_t)written)
+  if(len == *pnwritten)
     /* Encrypted message including header, data and trailer entirely sent.
        The return value is the number of unencrypted bytes that were sent. */
-    written = outbuf[1].cbBuffer;
+    *pnwritten = outbuf[1].cbBuffer;
 
-  return written;
+  return result;
 }
 
-static ssize_t
+static CURLcode
 schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
-              char *buf, size_t len, CURLcode *err)
+              char *buf, size_t len, size_t *pnread)
 {
   size_t size = 0;
   size_t nread = 0;
@@ -1879,8 +1871,10 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE;
   struct schannel_ssl_backend_data *backend =
     (struct schannel_ssl_backend_data *)connssl->backend;
+  CURLcode result = CURLE_OK;
 
   DEBUGASSERT(backend);
+  *pnread = 0;
 
   /****************************************************************************
    * Do not return or set backend->recv_unrecoverable_err unless in the
@@ -1899,7 +1893,6 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
    */
 
   SCH_DEV(infof(data, "schannel: client wants to read %zu bytes", len));
-  *err = CURLE_OK;
 
   if(len && len <= backend->decdata_offset) {
     SCH_DEV(infof(data,
@@ -1907,7 +1900,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
     goto cleanup;
   }
   else if(backend->recv_unrecoverable_err) {
-    *err = backend->recv_unrecoverable_err;
+    result = backend->recv_unrecoverable_err;
     infof(data, "schannel: an unrecoverable error occurred in a prior call");
     goto cleanup;
   }
@@ -1933,7 +1926,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
       reallocated_buffer = realloc(backend->encdata_buffer,
                                    reallocated_length);
       if(!reallocated_buffer) {
-        *err = CURLE_OUT_OF_MEMORY;
+        result = CURLE_OUT_OF_MEMORY;
         failf(data, "schannel: unable to re-allocate memory");
         goto cleanup;
       }
@@ -1950,17 +1943,17 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
                   backend->encdata_offset, backend->encdata_length));
 
     /* read encrypted data from socket */
-    *err = Curl_conn_cf_recv(cf->next, data,
+    result = Curl_conn_cf_recv(cf->next, data,
                              (char *)(backend->encdata_buffer +
                                       backend->encdata_offset),
                              size, &nread);
-    if(*err) {
-      if(*err == CURLE_AGAIN)
+    if(result) {
+      if(result == CURLE_AGAIN)
         SCH_DEV(infof(data, "schannel: recv returned CURLE_AGAIN"));
-      else if(*err == CURLE_RECV_ERROR)
+      else if(result == CURLE_RECV_ERROR)
         infof(data, "schannel: recv returned CURLE_RECV_ERROR");
       else
-        infof(data, "schannel: recv returned error %d", *err);
+        infof(data, "schannel: recv returned error %d", result);
     }
     else if(nread == 0) {
       backend->recv_connection_closed = TRUE;
@@ -2019,7 +2012,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
           reallocated_buffer = realloc(backend->decdata_buffer,
                                        reallocated_length);
           if(!reallocated_buffer) {
-            *err = CURLE_OUT_OF_MEMORY;
+            result = CURLE_OUT_OF_MEMORY;
             failf(data, "schannel: unable to re-allocate memory");
             goto cleanup;
           }
@@ -2070,7 +2063,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
       /* check if server wants to renegotiate the connection context */
       if(sspi_status == SEC_I_RENEGOTIATE) {
         infof(data, "schannel: remote party requests renegotiation");
-        if(*err && *err != CURLE_AGAIN) {
+        if(result && result != CURLE_AGAIN) {
           infof(data, "schannel: cannot renegotiate, an error is pending");
           goto cleanup;
         }
@@ -2081,9 +2074,9 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
         connssl->connecting_state = ssl_connect_2;
         connssl->io_need = CURL_SSL_IO_NEED_SEND;
         backend->recv_renegotiating = TRUE;
-        *err = schannel_connect(cf, data, &done);
+        result = schannel_connect(cf, data, &done);
         backend->recv_renegotiating = FALSE;
-        if(*err) {
+        if(result) {
           infof(data, "schannel: renegotiation failed");
           goto cleanup;
         }
@@ -2102,8 +2095,8 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
         /* We received the close notify just fine, any error we got
          * from the lower filters afterwards (e.g. the socket), is not
          * an error on the TLS data stream. That one ended here. */
-        if(*err == CURLE_RECV_ERROR)
-          *err = CURLE_OK;
+        if(result == CURLE_RECV_ERROR)
+          result = CURLE_OK;
         infof(data,
               "schannel: server close notification received (close_notify)");
         goto cleanup;
@@ -2111,8 +2104,8 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
     }
     else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
       backend->encdata_is_incomplete = TRUE;
-      if(!*err)
-        *err = CURLE_AGAIN;
+      if(!result)
+        result = CURLE_AGAIN;
       SCH_DEV(infof(data, "schannel: failed to decrypt data, need more data"));
       goto cleanup;
     }
@@ -2122,7 +2115,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
       failf(data, "schannel: failed to read data from server: %s",
             Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
 #endif
-      *err = CURLE_RECV_ERROR;
+      result = CURLE_RECV_ERROR;
       goto cleanup;
     }
   }
@@ -2145,13 +2138,13 @@ cleanup:
   */
   if(len && !backend->decdata_offset && backend->recv_connection_closed &&
      !backend->recv_sspi_close_notify) {
-    *err = CURLE_RECV_ERROR;
+    result = CURLE_RECV_ERROR;
     failf(data, "schannel: server closed abruptly (missing close_notify)");
   }
 
   /* Any error other than CURLE_AGAIN is an unrecoverable error. */
-  if(*err && *err != CURLE_AGAIN)
-    backend->recv_unrecoverable_err = *err;
+  if(result && result != CURLE_AGAIN)
+    backend->recv_unrecoverable_err = result;
 
   size = len < backend->decdata_offset ? len : backend->decdata_offset;
   if(size) {
@@ -2163,21 +2156,21 @@ cleanup:
     SCH_DEV(infof(data,
                   "schannel: decrypted data buffer: offset %zu length %zu",
                   backend->decdata_offset, backend->decdata_length));
-    *err = CURLE_OK;
-    return (ssize_t)size;
+    *pnread = size;
+    return CURLE_OK;
   }
 
-  if(!*err && !backend->recv_connection_closed)
-    *err = CURLE_AGAIN;
+  if(!result && !backend->recv_connection_closed)
+    result = CURLE_AGAIN;
 
   /* it is debatable what to return when !len. We could return whatever error
      we got from decryption but instead we override here so the return is
      consistent.
   */
   if(!len)
-    *err = CURLE_OK;
+    return CURLE_OK;
 
-  return *err ? -1 : 0;
+  return result;
 }
 
 static bool schannel_data_pending(struct Curl_cfilter *cf,
@@ -2319,23 +2312,23 @@ static CURLcode schannel_shutdown(struct Curl_cfilter *cf,
   if(backend->cred && backend->ctxt &&
      !backend->recv_sspi_close_notify && !backend->recv_connection_closed) {
     char buffer[1024];
-    ssize_t nread;
+    size_t nread;
 
-    nread = schannel_recv(cf, data, buffer, sizeof(buffer), &result);
-    if(nread > 0) {
-      /* still data coming in? */
+    result = schannel_recv(cf, data, buffer, sizeof(buffer), &nread);
+    if(result == CURLE_AGAIN) {
+      connssl->io_need = CURL_SSL_IO_NEED_RECV;
+    }
+    else if(result) {
+      CURL_TRC_CF(data, cf, "SSL shutdown, error %d", result);
+      result = CURLE_RECV_ERROR;
     }
     else if(nread == 0) {
       /* We got the close notify alert and are done. */
       backend->recv_connection_closed = TRUE;
       *done = TRUE;
     }
-    else if(nread < 0 && result == CURLE_AGAIN) {
-      connssl->io_need = CURL_SSL_IO_NEED_RECV;
-    }
     else {
-      CURL_TRC_CF(data, cf, "SSL shutdown, error %d", result);
-      result = CURLE_RECV_ERROR;
+      /* still data coming in? */
     }
   }
 
index 13431e1e1b3fda76c75b8f9935e689f9b49fc04a..16b291cb45adde3a19ebfbdad128530fd615a617 100644 (file)
@@ -917,23 +917,23 @@ static void multissl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
   Curl_ssl->close(cf, data);
 }
 
-static ssize_t multissl_recv_plain(struct Curl_cfilter *cf,
-                                   struct Curl_easy *data,
-                                   char *buf, size_t len, CURLcode *code)
+static CURLcode multissl_recv_plain(struct Curl_cfilter *cf,
+                                    struct Curl_easy *data,
+                                    char *buf, size_t len, size_t *pnread)
 {
   if(multissl_setup(NULL))
     return CURLE_FAILED_INIT;
-  return Curl_ssl->recv_plain(cf, data, buf, len, code);
+  return Curl_ssl->recv_plain(cf, data, buf, len, pnread);
 }
 
-static ssize_t multissl_send_plain(struct Curl_cfilter *cf,
-                                   struct Curl_easy *data,
-                                   const void *mem, size_t len,
-                                   CURLcode *code)
+static CURLcode multissl_send_plain(struct Curl_cfilter *cf,
+                                    struct Curl_easy *data,
+                                    const void *mem, size_t len,
+                                    size_t *pnwritten)
 {
   if(multissl_setup(NULL))
     return CURLE_FAILED_INIT;
-  return Curl_ssl->send_plain(cf, data, mem, len, code);
+  return Curl_ssl->send_plain(cf, data, mem, len, pnwritten);
 }
 
 static const struct Curl_ssl Curl_ssl_multi = {
@@ -1474,10 +1474,10 @@ static CURLcode ssl_cf_send(struct Curl_cfilter *cf,
 
   /* OpenSSL and maybe other TLS libs do not like 0-length writes. Skip. */
   if(blen > 0) {
-    ssize_t nwritten;
-    nwritten = connssl->ssl_impl->send_plain(cf, data, buf, blen, &result);
-    if(nwritten > 0)
-      *pnwritten += (size_t)nwritten;
+    size_t nwritten;
+    result = connssl->ssl_impl->send_plain(cf, data, buf, blen, &nwritten);
+    if(!result)
+      *pnwritten += nwritten;
   }
 
 out:
@@ -1492,7 +1492,6 @@ static CURLcode ssl_cf_recv(struct Curl_cfilter *cf,
   struct ssl_connect_data *connssl = cf->ctx;
   struct cf_call_data save;
   CURLcode result = CURLE_OK;
-  ssize_t nread;
 
   CF_DATA_SAVE(save, cf, data);
   *pnread = 0;
@@ -1508,19 +1507,9 @@ static CURLcode ssl_cf_recv(struct Curl_cfilter *cf,
     DEBUGASSERT(connssl->state == ssl_connection_complete);
   }
 
-  nread = connssl->ssl_impl->recv_plain(cf, data, buf, len, &result);
-  if(nread > 0) {
-    DEBUGASSERT((size_t)nread <= len);
-    *pnread = (size_t)nread;
-  }
-  else if(nread == 0) {
-    /* eof */
-    result = CURLE_OK;
-  }
+  result = connssl->ssl_impl->recv_plain(cf, data, buf, len, pnread);
 
 out:
-  CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %d, %zd", len,
-              result, *pnread);
   CF_DATA_RESTORE(cf, save);
   return result;
 }
index 6cd2ae4d26c0706fa2b71df15c1d2dd8c87ed4c5..11987c382a3ce1b8e08f900b99a31bed3110c59d 100644 (file)
@@ -178,10 +178,10 @@ struct Curl_ssl {
 
   CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
                     unsigned char *sha256sum, size_t sha256sumlen);
-  ssize_t (*recv_plain)(struct Curl_cfilter *cf, struct Curl_easy *data,
-                        char *buf, size_t len, CURLcode *code);
-  ssize_t (*send_plain)(struct Curl_cfilter *cf, struct Curl_easy *data,
-                        const void *mem, size_t len, CURLcode *code);
+  CURLcode (*recv_plain)(struct Curl_cfilter *cf, struct Curl_easy *data,
+                         char *buf, size_t len, size_t *pnread);
+  CURLcode (*send_plain)(struct Curl_cfilter *cf, struct Curl_easy *data,
+                         const void *mem, size_t len, size_t *pnwritten);
 
   CURLcode (*get_channel_binding)(struct Curl_easy *data, int sockindex,
                                   struct dynbuf *binding);
index d842d88c26a944d15cd3b28a1d59b80b9ee01a45..610cc4d7e5c18e2c44025e11799608bcd3677d66 100644 (file)
@@ -1789,49 +1789,48 @@ static CURLcode wssl_handshake(struct Curl_cfilter *cf,
   }
 }
 
-static ssize_t wssl_send(struct Curl_cfilter *cf,
-                         struct Curl_easy *data,
-                         const void *buf, size_t blen,
-                         CURLcode *curlcode)
+static CURLcode wssl_send(struct Curl_cfilter *cf,
+                          struct Curl_easy *data,
+                          const void *buf, size_t blen,
+                          size_t *pnwritten)
 {
   struct ssl_connect_data *connssl = cf->ctx;
   struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend;
-  size_t total_written = 0;
-  ssize_t nwritten = -1;
-  DEBUGASSERT(wssl);
+  CURLcode result = CURLE_OK;
+  int nwritten;
 
+  DEBUGASSERT(wssl);
+  *pnwritten = 0;
   wolfSSL_ERR_clear_error();
 
   if(blen) {
     int memlen = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen;
-    int rc;
 
-    rc = wolfSSL_write(wssl->ssl, buf, memlen);
-    if(rc <= 0) {
-      int err = wolfSSL_get_error(wssl->ssl, rc);
+    nwritten = wolfSSL_write(wssl->ssl, buf, memlen);
+
+    if(nwritten > 0)
+      *pnwritten += (size_t)nwritten;
+    else {
+      int err = wolfSSL_get_error(wssl->ssl, nwritten);
 
       switch(err) {
       case WOLFSSL_ERROR_WANT_READ:
       case WOLFSSL_ERROR_WANT_WRITE:
         /* there is data pending, re-invoke wolfSSL_write() */
-        if(total_written) {
-          *curlcode = CURLE_OK;
-          nwritten = total_written;
+        if(*pnwritten) {
+          result = CURLE_OK;
           goto out;
         }
-        *curlcode = CURLE_AGAIN;
-        nwritten = -1;
+        result = CURLE_AGAIN;
         goto out;
 
       default:
         if(wssl->io_result == CURLE_AGAIN) {
-          if(total_written) {
-            *curlcode = CURLE_OK;
-            nwritten = total_written;
+          if(*pnwritten) {
+            result = CURLE_OK;
             goto out;
           }
-          *curlcode = CURLE_AGAIN;
-          nwritten = -1;
+          result = CURLE_AGAIN;
           goto out;
         }
         {
@@ -1841,21 +1840,16 @@ static ssize_t wssl_send(struct Curl_cfilter *cf,
                               sizeof(error_buffer)),
                 SOCKERRNO);
         }
-        *curlcode = CURLE_SEND_ERROR;
-        nwritten = -1;
+        result = CURLE_SEND_ERROR;
         goto out;
       }
     }
-    else
-      total_written += rc;
   }
 
-  *curlcode = CURLE_OK;
-  nwritten = total_written;
 out:
-  CURL_TRC_CF(data, cf, "wssl_send(len=%zu) -> %" FMT_OFF_T ", %d",
-              blen, nwritten, *curlcode);
-  return nwritten;
+  CURL_TRC_CF(data, cf, "wssl_send(len=%zu) -> %d, %zu",
+              blen, result, *pnwritten);
+  return result;
 }
 
 static CURLcode wssl_shutdown(struct Curl_cfilter *cf,
@@ -1982,10 +1976,10 @@ static void wssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
   }
 }
 
-static ssize_t wssl_recv(struct Curl_cfilter *cf,
-                         struct Curl_easy *data,
-                         char *buf, size_t blen,
-                         CURLcode *curlcode)
+static CURLcode wssl_recv(struct Curl_cfilter *cf,
+                          struct Curl_easy *data,
+                          char *buf, size_t blen,
+                          size_t *pnread)
 {
   struct ssl_connect_data *connssl = cf->ctx;
   struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend;
@@ -1994,36 +1988,34 @@ static ssize_t wssl_recv(struct Curl_cfilter *cf,
 
   DEBUGASSERT(wssl);
 
+  *pnread = 0;
   wolfSSL_ERR_clear_error();
-  *curlcode = CURLE_OK;
 
   nread = wolfSSL_read(wssl->ssl, buf, buffsize);
 
-  if(nread <= 0) {
+  if(nread > 0)
+    *pnread = (size_t)nread;
+  else {
     int err = wolfSSL_get_error(wssl->ssl, nread);
 
     switch(err) {
     case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */
       CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> CLOSED", blen);
-      *curlcode = CURLE_OK;
-      return 0;
+      return CURLE_OK;
     case WOLFSSL_ERROR_NONE:
     case WOLFSSL_ERROR_WANT_READ:
     case WOLFSSL_ERROR_WANT_WRITE:
       if(!wssl->io_result && connssl->peer_closed) {
         CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> CLOSED", blen);
-        *curlcode = CURLE_OK;
-        return 0;
+        return CURLE_OK;
       }
       /* there is data pending, re-invoke wolfSSL_read() */
       CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> AGAIN", blen);
-      *curlcode = CURLE_AGAIN;
-      return -1;
+      return CURLE_AGAIN;
     default:
       if(wssl->io_result == CURLE_AGAIN) {
         CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> AGAIN", blen);
-        *curlcode = CURLE_AGAIN;
-        return -1;
+        return CURLE_AGAIN;
       }
       else if(!wssl->io_result && connssl->peer_closed) {
         CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> CLOSED", blen);
@@ -2036,13 +2028,12 @@ static ssize_t wssl_recv(struct Curl_cfilter *cf,
                             sizeof(error_buffer)),
               SOCKERRNO);
       }
-      *curlcode = CURLE_RECV_ERROR;
-      return -1;
+      return CURLE_RECV_ERROR;
     }
   }
 
-  CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> %d", blen, nread);
-  return nread;
+  CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> 0, %zu", blen, *pnread);
+  return CURLE_OK;
 }
 
 size_t Curl_wssl_version(char *buffer, size_t size)