gnutls: send all data

Turns out `gnutls_record_send()` does really what the name says: it
sends exactly one TLS record. If more than 16k are there to send, it
needs to be called again with new buffer offset and length.

Continue sending record until the input is all sent or a EAGAIN (or
fatal error) is returned by gnutls.

Closes #14722
This commit is contained in:
Stefan Eissing 2024-08-29 12:53:57 +02:00 committed by Daniel Stenberg
parent 44d1b6c271
commit 6354b35dfe
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -1778,28 +1778,44 @@ static bool gtls_data_pending(struct Curl_cfilter *cf,
static ssize_t gtls_send(struct Curl_cfilter *cf,
struct Curl_easy *data,
const void *mem,
size_t len,
const void *buf,
size_t blen,
CURLcode *curlcode)
{
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;
(void)data;
DEBUGASSERT(backend);
backend->gtls.io_result = CURLE_OK;
rc = gnutls_record_send(backend->gtls.session, mem, len);
while(blen) {
backend->gtls.io_result = CURLE_OK;
rc = gnutls_record_send(backend->gtls.session, buf, blen);
if(rc < 0) {
*curlcode = (rc == GNUTLS_E_AGAIN)?
CURLE_AGAIN :
(backend->gtls.io_result? backend->gtls.io_result : CURLE_SEND_ERROR);
if(rc < 0) {
if(total_written && (rc == GNUTLS_E_AGAIN)) {
*curlcode = CURLE_OK;
rc = (ssize_t)total_written;
goto out;
}
*curlcode = (rc == GNUTLS_E_AGAIN)?
CURLE_AGAIN :
(backend->gtls.io_result? backend->gtls.io_result : CURLE_SEND_ERROR);
rc = -1;
rc = -1;
goto out;
}
nwritten = (size_t)rc;
total_written += nwritten;
DEBUGASSERT(nwritten <= blen);
buf = (char *)buf + nwritten;
blen -= nwritten;
}
rc = total_written;
out:
return rc;
}