lib: unify recv/send function signatures

cfilter/conn: change send/recv function signatures. Unify the
calling/return conventions in our send/receive handling.

Curl_conn_recv(), adjust pnread type

Parameter `pnread` was a `ssize_t *`, but `size_t *` is better since the
function returns any error in its `CURLcode` return value.

Closes #17546
This commit is contained in:
Stefan Eissing 2025-06-11 10:18:15 +02:00 committed by Daniel Stenberg
parent 3934431421
commit 20c90ba298
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
37 changed files with 1114 additions and 1219 deletions

View file

@ -2875,19 +2875,20 @@ static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
return myssh_done(data, sshc, status);
}
static ssize_t scp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, bool eos, CURLcode *err)
static CURLcode scp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, bool eos,
size_t *pnwritten)
{
int rc;
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
(void) sockindex; /* we only support SCP on the fixed known primary socket */
(void)eos;
*pnwritten = 0;
if(!sshc) {
*err = CURLE_FAILED_INIT;
return -1;
}
if(!sshc)
return CURLE_FAILED_INIT;
rc = ssh_scp_write(sshc->scp_session, mem, len);
@ -2897,32 +2898,30 @@ static ssize_t scp_send(struct Curl_easy *data, int sockindex,
* Currently rc can only be number of bytes read or SSH_ERROR. */
myssh_block2waitfor(conn, sshc, (rc == SSH_AGAIN));
if(rc == SSH_AGAIN) {
*err = CURLE_AGAIN;
return 0;
}
if(rc == SSH_AGAIN)
return CURLE_AGAIN;
else
#endif
if(rc != SSH_OK) {
*err = CURLE_SSH;
return -1;
}
if(rc != SSH_OK)
return CURLE_SSH;
return len;
*pnwritten = len;
return CURLE_OK;
}
static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
static CURLcode scp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, size_t *pnread)
{
ssize_t nread;
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
(void) sockindex; /* we only support SCP on the fixed known primary socket */
ssize_t nread;
(void) sockindex; /* we only support SCP on the fixed known primary socket */
*pnread = 0;
if(!sshc)
return CURLE_FAILED_INIT;
if(!sshc) {
*err = CURLE_FAILED_INIT;
return -1;
}
/* libssh returns int */
nread = ssh_scp_read(sshc->scp_session, mem, len);
@ -2932,13 +2931,11 @@ static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
* Currently rc can only be SSH_OK or SSH_ERROR. */
myssh_block2waitfor(conn, sshc, (nread == SSH_AGAIN));
if(nread == SSH_AGAIN) {
*err = CURLE_AGAIN;
nread = -1;
}
if(nread == SSH_AGAIN)
return CURLE_AGAIN;
#endif
return nread;
*pnread = (size_t)nread;
return CURLE_OK;
}
/*
@ -3038,20 +3035,21 @@ 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, bool eos,
CURLcode *err)
static CURLcode sftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, bool eos,
size_t *pnwritten)
{
ssize_t nwrite;
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
ssize_t nwrite;
(void)sockindex;
(void)eos;
*pnwritten = 0;
if(!sshc)
return CURLE_FAILED_INIT;
if(!sshc) {
*err = CURLE_FAILED_INIT;
return -1;
}
/* limit the writes to the maximum specified in Section 3 of
* https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-02
*/
@ -3063,31 +3061,27 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
sftp_file_set_nonblocking(sshc->sftp_file);
if(sftp_aio_begin_write(sshc->sftp_file, mem, len,
&sshc->sftp_aio) == SSH_ERROR) {
*err = CURLE_SEND_ERROR;
return -1;
return CURLE_SEND_ERROR;
}
sshc->sftp_send_state = 1;
FALLTHROUGH();
case 1:
nwrite = sftp_aio_wait_write(&sshc->sftp_aio);
myssh_block2waitfor(conn, sshc, (nwrite == SSH_AGAIN) ? TRUE : FALSE);
if(nwrite == SSH_AGAIN) {
*err = CURLE_AGAIN;
return 0;
}
else if(nwrite < 0) {
*err = CURLE_SEND_ERROR;
return -1;
}
if(nwrite == SSH_AGAIN)
return CURLE_AGAIN;
else if(nwrite < 0)
return CURLE_SEND_ERROR;
if(sshc->sftp_aio) {
sftp_aio_free(sshc->sftp_aio);
sshc->sftp_aio = NULL;
}
sshc->sftp_send_state = 0;
return nwrite;
*pnwritten = (size_t)nwrite;
return CURLE_OK;
default:
/* we never reach here */
return -1;
return CURLE_SEND_ERROR;
}
#else
nwrite = sftp_write(sshc->sftp_file, mem, len);
@ -3101,12 +3095,11 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
}
else
#endif
if(nwrite < 0) {
*err = CURLE_SSH;
nwrite = -1;
}
if(nwrite < 0)
return CURLE_SSH;
return nwrite;
*pnwritten = (size_t)nwrite;
return CURLE_OK;
#endif
}
@ -3114,28 +3107,26 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
* Return number of received (decrypted) bytes
* or <0 on error
*/
static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
static CURLcode sftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, size_t *pnread)
{
ssize_t nread;
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
ssize_t nread;
(void)sockindex;
*pnread = 0;
DEBUGASSERT(len < CURL_MAX_READ_SIZE);
if(!sshc) {
*err = CURLE_FAILED_INIT;
return -1;
}
if(!sshc)
return CURLE_FAILED_INIT;
switch(sshc->sftp_recv_state) {
case 0:
sshc->sftp_file_index =
sftp_async_read_begin(sshc->sftp_file, (uint32_t)len);
if(sshc->sftp_file_index < 0) {
*err = CURLE_RECV_ERROR;
return -1;
}
if(sshc->sftp_file_index < 0)
return CURLE_RECV_ERROR;
FALLTHROUGH();
case 1:
@ -3145,21 +3136,18 @@ static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
myssh_block2waitfor(conn, sshc, (nread == SSH_AGAIN));
if(nread == SSH_AGAIN) {
*err = CURLE_AGAIN;
return -1;
}
else if(nread < 0) {
*err = CURLE_RECV_ERROR;
return -1;
}
if(nread == SSH_AGAIN)
return CURLE_AGAIN;
else if(nread < 0)
return CURLE_RECV_ERROR;
sshc->sftp_recv_state = 0;
return nread;
*pnread = (size_t)nread;
return CURLE_OK;
default:
/* we never reach here */
return -1;
return CURLE_RECV_ERROR;
}
}

View file

@ -3290,7 +3290,7 @@ static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
size_t length, int flags, void **abstract)
{
struct Curl_easy *data = (struct Curl_easy *)*abstract;
ssize_t nread;
size_t nread;
CURLcode result;
struct connectdata *conn = data->conn;
Curl_recv *backup = conn->recv[0];
@ -3311,7 +3311,7 @@ static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
else if(result)
return -1; /* generic error */
Curl_debug(data, CURLINFO_DATA_IN, (const char *)buffer, (size_t)nread);
return nread;
return (ssize_t)nread;
}
static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
@ -3769,58 +3769,63 @@ static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
return ssh_done(data, status);
}
static ssize_t scp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, bool eos, CURLcode *err)
static CURLcode scp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, bool eos,
size_t *pnwritten)
{
ssize_t nwrite;
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
CURLcode result = CURLE_OK;
ssize_t nwritten;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
(void)eos;
*pnwritten = 0;
if(!sshc)
return CURLE_FAILED_INIT;
if(!sshc) {
*err = CURLE_FAILED_INIT;
return -1;
}
/* libssh2_channel_write() returns int! */
nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len);
nwritten = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len);
ssh_block2waitfor(data, sshc, (nwrite == LIBSSH2_ERROR_EAGAIN));
ssh_block2waitfor(data, sshc, (nwritten == LIBSSH2_ERROR_EAGAIN));
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nwrite = 0;
}
else if(nwrite < LIBSSH2_ERROR_NONE) {
*err = libssh2_session_error_to_CURLE((int)nwrite);
nwrite = -1;
}
if(nwritten == LIBSSH2_ERROR_EAGAIN)
result = CURLE_AGAIN;
else if(nwritten < LIBSSH2_ERROR_NONE)
result = libssh2_session_error_to_CURLE((int)nwritten);
else
*pnwritten = (size_t)nwritten;
return nwrite;
return result;
}
static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
static CURLcode scp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, size_t *pnread)
{
ssize_t nread;
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
(void)sockindex; /* we only support SCP on the fixed known primary socket */
CURLcode result = CURLE_OK;
ssize_t nread;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
*pnread = 0;
if(!sshc)
return CURLE_FAILED_INIT;
if(!sshc) {
*err = CURLE_FAILED_INIT;
return -1;
}
/* libssh2_channel_read() returns int */
nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len);
ssh_block2waitfor(data, sshc, (nread == LIBSSH2_ERROR_EAGAIN));
if(nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nread = -1;
}
if(nread == LIBSSH2_ERROR_EAGAIN)
return CURLE_AGAIN;
else if(nread < LIBSSH2_ERROR_NONE)
result = libssh2_session_error_to_CURLE((int)nread);
else
*pnread = (size_t)nread;
return nread;
return result;
}
/*
@ -3925,64 +3930,61 @@ 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, bool eos, CURLcode *err)
static CURLcode sftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, bool eos,
size_t *pnwritten)
{
ssize_t nwrite;
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
ssize_t nwrite;
(void)sockindex;
(void)eos;
*pnwritten = 0;
if(!sshc)
return CURLE_FAILED_INIT;
if(!sshc) {
*err = CURLE_FAILED_INIT;
return -1;
}
nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len);
ssh_block2waitfor(data, sshc, (nwrite == LIBSSH2_ERROR_EAGAIN));
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nwrite = 0;
}
else if(nwrite < LIBSSH2_ERROR_NONE) {
*err = libssh2_session_error_to_CURLE((int)nwrite);
nwrite = -1;
}
return nwrite;
if(nwrite == LIBSSH2_ERROR_EAGAIN)
return CURLE_AGAIN;
else if(nwrite < LIBSSH2_ERROR_NONE)
return libssh2_session_error_to_CURLE((int)nwrite);
*pnwritten = (size_t)nwrite;
return CURLE_OK;
}
/*
* Return number of received (decrypted) bytes
* or <0 on error
*/
static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
static CURLcode sftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, size_t *pnread)
{
ssize_t nread;
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
(void)sockindex;
ssize_t nread;
(void)sockindex;
*pnread = 0;
if(!sshc)
return CURLE_FAILED_INIT;
if(!sshc) {
*err = CURLE_FAILED_INIT;
return -1;
}
nread = libssh2_sftp_read(sshc->sftp_handle, mem, len);
ssh_block2waitfor(data, sshc, (nread == LIBSSH2_ERROR_EAGAIN));
if(nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nread = -1;
if(nread == LIBSSH2_ERROR_EAGAIN)
return CURLE_AGAIN;
else if(nread < 0)
return libssh2_session_error_to_CURLE((int)nread);
}
else if(nread < 0) {
*err = libssh2_session_error_to_CURLE((int)nread);
}
return nread;
*pnread = (size_t)nread;
return CURLE_OK;
}
static const char *sftp_libssh2_strerror(unsigned long err)

View file

@ -220,37 +220,35 @@ static void wssh_state(struct Curl_easy *data,
sshc->state = nowstate;
}
static ssize_t wscp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, bool eos,
CURLcode *err)
static CURLcode wscp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, bool eos,
size_t *pnwritten)
{
ssize_t nwrite = 0;
(void)data;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
(void)mem;
(void)len;
(void)eos;
(void)err;
return nwrite;
*pnwritten = 0;
return CURLE_OK;
}
static ssize_t wscp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
static CURLcode wscp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, size_t *pnread)
{
ssize_t nread = 0;
(void)data;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
(void)mem;
(void)len;
(void)err;
*pnread = 0;
return nread;
return CURLE_OK;
}
/* return number of sent bytes */
static ssize_t wsftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, bool eos, CURLcode *err)
static CURLcode wsftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, bool eos,
size_t *pnwritten)
{
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
@ -259,10 +257,10 @@ static ssize_t wsftp_send(struct Curl_easy *data, int sockindex,
(void)sockindex;
(void)eos;
if(!sshc) {
*err = CURLE_FAILED_INIT;
return -1;
}
*pnwritten = 0;
if(!sshc)
return CURLE_FAILED_INIT;
offset[0] = (word32)sshc->offset & 0xFFFFFFFF;
offset[1] = (word32)(sshc->offset >> 32) & 0xFFFFFFFF;
@ -275,31 +273,30 @@ static ssize_t wsftp_send(struct Curl_easy *data, int sockindex,
rc = wolfSSH_get_error(sshc->ssh_session);
if(rc == WS_WANT_READ) {
conn->waitfor = KEEP_RECV;
*err = CURLE_AGAIN;
return -1;
return CURLE_AGAIN;
}
else if(rc == WS_WANT_WRITE) {
conn->waitfor = KEEP_SEND;
*err = CURLE_AGAIN;
return -1;
return CURLE_AGAIN;
}
if(rc < 0) {
failf(data, "wolfSSH_SFTP_SendWritePacket returned %d", rc);
return -1;
return CURLE_SEND_ERROR;
}
DEBUGASSERT(rc == (int)len);
*pnwritten = (size_t)rc;
sshc->offset += *pnwritten;
infof(data, "sent %zu bytes SFTP from offset %" FMT_OFF_T,
len, sshc->offset);
sshc->offset += len;
return (ssize_t)rc;
*pnwritten, sshc->offset);
return CURLE_OK;
}
/*
* Return number of received (decrypted) bytes
* or <0 on error
*/
static ssize_t wsftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
static CURLcode wsftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, size_t *pnread)
{
int rc;
struct connectdata *conn = data->conn;
@ -307,10 +304,10 @@ static ssize_t wsftp_recv(struct Curl_easy *data, int sockindex,
word32 offset[2];
(void)sockindex;
if(!sshc) {
*err = CURLE_FAILED_INIT;
return -1;
}
*pnread = 0;
if(!sshc)
return CURLE_FAILED_INIT;
offset[0] = (word32)sshc->offset & 0xFFFFFFFF;
offset[1] = (word32)(sshc->offset >> 32) & 0xFFFFFFFF;
@ -322,24 +319,22 @@ static ssize_t wsftp_recv(struct Curl_easy *data, int sockindex,
rc = wolfSSH_get_error(sshc->ssh_session);
if(rc == WS_WANT_READ) {
conn->waitfor = KEEP_RECV;
*err = CURLE_AGAIN;
return -1;
return CURLE_AGAIN;
}
else if(rc == WS_WANT_WRITE) {
conn->waitfor = KEEP_SEND;
*err = CURLE_AGAIN;
return -1;
return CURLE_AGAIN;
}
DEBUGASSERT(rc <= (int)len);
if(rc < 0) {
failf(data, "wolfSSH_SFTP_SendReadPacket returned %d", rc);
return -1;
return CURLE_RECV_ERROR;
}
sshc->offset += len;
return (ssize_t)rc;
*pnread = (size_t)rc;
sshc->offset += *pnread;
return CURLE_OK;
}
static void wssh_easy_dtor(void *key, size_t klen, void *entry)