size_t request_len = curlx_dyn_len(&ts->request_data);
size_t blen = request_len;
CURLcode result = CURLE_OK;
- ssize_t nwritten;
+ size_t nwritten;
if(blen <= ts->nsent)
goto out; /* we are done */
blen -= ts->nsent;
buf += ts->nsent;
- nwritten = cf->next->cft->do_send(cf->next, data, buf, blen, FALSE, &result);
- if(nwritten < 0) {
- if(result == CURLE_AGAIN) {
+ result = cf->next->cft->do_send(cf->next, data, buf, blen, FALSE, &nwritten);
+ if(result) {
+ if(result == CURLE_AGAIN)
result = CURLE_OK;
- }
goto out;
}
- DEBUGASSERT(blen >= (size_t)nwritten);
- ts->nsent += (size_t)nwritten;
+ DEBUGASSERT(blen >= nwritten);
+ ts->nsent += nwritten;
Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)nwritten);
out:
return CURLE_OK;
while(ts->keepon) {
- ssize_t nread;
+ size_t nread;
char byte;
/* Read one byte at a time to avoid a race condition. Wait at most one
break;
}
- if(nread <= 0) {
+ if(!nread) {
if(data->set.proxyauth && data->state.authproxy.avail &&
data->state.aptr.proxyuserpwd) {
/* proxy auth was requested and there was proxy auth available,
CURLcode *err)
{
struct Curl_cfilter *cf = reader_ctx;
- ssize_t nread;
if(cf) {
struct Curl_easy *data = CF_DATA_CURRENT(cf);
- nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, buflen, err);
- CURL_TRC_CF(data, cf, "[0] nw_in_reader(len=%zu) -> %zd, %d",
- buflen, nread, *err);
- }
- else {
- nread = 0;
- }
- return nread;
+ size_t nread;
+ *err = Curl_conn_cf_recv(cf->next, data, (char *)buf, buflen, &nread);
+ CURL_TRC_CF(data, cf, "[0] nw_in_reader(len=%zu) -> %d, %zu",
+ buflen, *err, nread);
+ return *err ? -1 : (ssize_t)nread;
+ }
+ *err = CURLE_FAILED_INIT;
+ return -1;
}
static ssize_t proxy_h2_nw_out_writer(void *writer_ctx,
CURLcode *err)
{
struct Curl_cfilter *cf = writer_ctx;
- ssize_t nwritten;
if(cf) {
struct Curl_easy *data = CF_DATA_CURRENT(cf);
- nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen,
- FALSE, err);
+ size_t nwritten;
+ *err = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen,
+ FALSE, &nwritten);
CURL_TRC_CF(data, cf, "[0] nw_out_writer(len=%zu) -> %zd, %d",
buflen, nwritten, *err);
+ return *err ? -1 : (ssize_t)nwritten;
}
- else {
- nwritten = 0;
- }
- return nwritten;
+ *err = CURLE_FAILED_INIT;
+ return -1;
}
static int proxy_h2_client_new(struct Curl_cfilter *cf,
}
}
-static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- CURLcode *err)
+static CURLcode h2_handle_tunnel_close(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ size_t *pnread)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
- ssize_t rv = 0;
+ *pnread = 0;
if(ctx->tunnel.error == NGHTTP2_REFUSED_STREAM) {
CURL_TRC_CF(data, cf, "[%d] REFUSED_STREAM, try again on a new "
"connection", ctx->tunnel.stream_id);
connclose(cf->conn, "REFUSED_STREAM"); /* do not use this anymore */
- *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
- return -1;
+ return CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
}
else if(ctx->tunnel.error != NGHTTP2_NO_ERROR) {
failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %u)",
ctx->tunnel.stream_id, nghttp2_http2_strerror(ctx->tunnel.error),
ctx->tunnel.error);
- *err = CURLE_HTTP2_STREAM;
- return -1;
+ return CURLE_HTTP2_STREAM;
}
else if(ctx->tunnel.reset) {
failf(data, "HTTP/2 stream %u was reset", ctx->tunnel.stream_id);
- *err = CURLE_RECV_ERROR;
- return -1;
+ return CURLE_RECV_ERROR;
}
- *err = CURLE_OK;
- rv = 0;
- CURL_TRC_CF(data, cf, "[%d] handle_tunnel_close -> %zd, %d",
- ctx->tunnel.stream_id, rv, *err);
- return rv;
+ CURL_TRC_CF(data, cf, "[%d] handle_tunnel_close -> 0",
+ ctx->tunnel.stream_id);
+ return CURLE_OK;
}
-static ssize_t tunnel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
- char *buf, size_t len, CURLcode *err)
+static CURLcode tunnel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, size_t *pnread)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
- ssize_t nread = -1;
+ CURLcode result = CURLE_AGAIN;
- *err = CURLE_AGAIN;
+ *pnread = 0;
if(!Curl_bufq_is_empty(&ctx->tunnel.recvbuf)) {
- nread = Curl_bufq_read(&ctx->tunnel.recvbuf,
- (unsigned char *)buf, len, err);
+ ssize_t nread = Curl_bufq_read(&ctx->tunnel.recvbuf,
+ (unsigned char *)buf, len, &result);
if(nread < 0)
goto out;
DEBUGASSERT(nread > 0);
+ *pnread = (size_t)nread;
}
- if(nread < 0) {
+ if(!*pnread) {
if(ctx->tunnel.closed) {
- nread = h2_handle_tunnel_close(cf, data, err);
+ result = h2_handle_tunnel_close(cf, data, pnread);
}
else if(ctx->tunnel.reset ||
(ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) ||
(ctx->rcvd_goaway &&
ctx->last_stream_id < ctx->tunnel.stream_id)) {
- *err = CURLE_RECV_ERROR;
- nread = -1;
+ result = CURLE_RECV_ERROR;
}
- }
- else if(nread == 0) {
- *err = CURLE_AGAIN;
- nread = -1;
+ else
+ result = CURLE_AGAIN;
}
out:
- CURL_TRC_CF(data, cf, "[%d] tunnel_recv(len=%zu) -> %zd, %d",
- ctx->tunnel.stream_id, len, nread, *err);
- return nread;
+ CURL_TRC_CF(data, cf, "[%d] tunnel_recv(len=%zu) -> %d, %zu",
+ ctx->tunnel.stream_id, len, result, *pnread);
+ return result;
}
-static ssize_t cf_h2_proxy_recv(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- char *buf, size_t len, CURLcode *err)
+static CURLcode cf_h2_proxy_recv(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ char *buf, size_t len,
+ size_t *pnread)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
- ssize_t nread = -1;
struct cf_call_data save;
- CURLcode result;
+ CURLcode result, r2;
+
+ *pnread = 0;
+ CF_DATA_SAVE(save, cf, data);
if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) {
- *err = CURLE_RECV_ERROR;
- return -1;
+ result = CURLE_RECV_ERROR;
+ goto out;
}
- CF_DATA_SAVE(save, cf, data);
if(Curl_bufq_is_empty(&ctx->tunnel.recvbuf)) {
- *err = proxy_h2_progress_ingress(cf, data);
- if(*err)
+ result = proxy_h2_progress_ingress(cf, data);
+ if(result)
goto out;
}
- nread = tunnel_recv(cf, data, buf, len, err);
+ result = tunnel_recv(cf, data, buf, len, pnread);
- if(nread > 0) {
- CURL_TRC_CF(data, cf, "[%d] increase window by %zd",
- ctx->tunnel.stream_id, nread);
- nghttp2_session_consume(ctx->h2, ctx->tunnel.stream_id, (size_t)nread);
+ if(!result) {
+ CURL_TRC_CF(data, cf, "[%d] increase window by %zu",
+ ctx->tunnel.stream_id, *pnread);
+ nghttp2_session_consume(ctx->h2, ctx->tunnel.stream_id, *pnread);
}
- result = proxy_h2_progress_egress(cf, data);
- if(result && (result != CURLE_AGAIN)) {
- *err = result;
- nread = -1;
- }
+ r2 = proxy_h2_progress_egress(cf, data);
+ if(r2 && (r2 != CURLE_AGAIN))
+ result = r2;
out:
if(!Curl_bufq_is_empty(&ctx->tunnel.recvbuf) &&
- (nread >= 0 || *err == CURLE_AGAIN)) {
+ (!result || (result == CURLE_AGAIN))) {
/* data pending and no fatal error to report. Need to trigger
* draining to avoid stalling when no socket events happen. */
drain_tunnel(cf, data, &ctx->tunnel);
}
- CURL_TRC_CF(data, cf, "[%d] cf_recv(len=%zu) -> %zd %d",
- ctx->tunnel.stream_id, len, nread, *err);
+ CURL_TRC_CF(data, cf, "[%d] cf_recv(len=%zu) -> %d, %zu",
+ ctx->tunnel.stream_id, len, result, *pnread);
CF_DATA_RESTORE(cf, save);
- return nread;
+ return result;
}
-static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const void *buf, size_t len, bool eos,
- CURLcode *err)
+static CURLcode cf_h2_proxy_send(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const void *buf, size_t len, bool eos,
+ size_t *pnwritten)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
struct cf_call_data save;
int rv;
- ssize_t nwritten;
- CURLcode result;
+ ssize_t nwritten = 0;
+ CURLcode result, r2;
(void)eos;
+ *pnwritten = 0;
+ CF_DATA_SAVE(save, cf, data);
+
if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) {
- *err = CURLE_SEND_ERROR;
- return -1;
+ result = CURLE_SEND_ERROR;
+ goto out;
}
- CF_DATA_SAVE(save, cf, data);
if(ctx->tunnel.closed) {
- nwritten = -1;
- *err = CURLE_SEND_ERROR;
+ result = CURLE_SEND_ERROR;
goto out;
}
- else {
- nwritten = Curl_bufq_write(&ctx->tunnel.sendbuf, buf, len, err);
- if(nwritten < 0 && (*err != CURLE_AGAIN))
- goto out;
- }
+
+ nwritten = Curl_bufq_write(&ctx->tunnel.sendbuf, buf, len, &result);
+ CURL_TRC_CF(data, cf, "cf_send(), bufq_write %d, %zd", result, nwritten);
+ if(nwritten >= 0)
+ *pnwritten = (size_t)nwritten;
+ else if(result && (result != CURLE_AGAIN))
+ goto out;
if(!Curl_bufq_is_empty(&ctx->tunnel.sendbuf)) {
/* req body data is buffered, resume the potentially suspended stream */
rv = nghttp2_session_resume_data(ctx->h2, ctx->tunnel.stream_id);
if(nghttp2_is_fatal(rv)) {
- *err = CURLE_SEND_ERROR;
- nwritten = -1;
+ result = CURLE_SEND_ERROR;
goto out;
}
}
- result = proxy_h2_progress_ingress(cf, data);
- if(result) {
- *err = result;
- nwritten = -1;
+ r2 = proxy_h2_progress_ingress(cf, data);
+ if(r2 && (r2 != CURLE_AGAIN)) {
+ result = r2;
goto out;
}
/* Call the nghttp2 send loop and flush to write ALL buffered data,
* headers and/or request body completely out to the network */
- result = proxy_h2_progress_egress(cf, data);
- if(result && (result != CURLE_AGAIN)) {
- *err = result;
- nwritten = -1;
+ r2 = proxy_h2_progress_egress(cf, data);
+ if(r2 && (r2 != CURLE_AGAIN)) {
+ result = r2;
goto out;
}
- if(proxy_h2_should_close_session(ctx)) {
+ if(!result && proxy_h2_should_close_session(ctx)) {
/* nghttp2 thinks this session is done. If the stream has not been
* closed, this is an error state for out transfer */
if(ctx->tunnel.closed) {
- *err = CURLE_SEND_ERROR;
- nwritten = -1;
+ result = CURLE_SEND_ERROR;
}
else {
CURL_TRC_CF(data, cf, "[0] send: nothing to do in this session");
- *err = CURLE_HTTP2;
- nwritten = -1;
+ result = CURLE_HTTP2;
}
}
out:
if(!Curl_bufq_is_empty(&ctx->tunnel.recvbuf) &&
- (nwritten >= 0 || *err == CURLE_AGAIN)) {
+ (!result || (result == CURLE_AGAIN))) {
/* data pending and no fatal error to report. Need to trigger
* draining to avoid stalling when no socket events happen. */
drain_tunnel(cf, data, &ctx->tunnel);
}
- CURL_TRC_CF(data, cf, "[%d] cf_send(len=%zu) -> %zd, %d, "
+ CURL_TRC_CF(data, cf, "[%d] cf_send(len=%zu) -> %d, %zu, "
"h2 windows %d-%d (stream-conn), buffers %zu-%zu (stream-conn)",
- ctx->tunnel.stream_id, len, nwritten, *err,
+ ctx->tunnel.stream_id, len, result, *pnwritten,
nghttp2_session_get_stream_remote_window_size(
ctx->h2, ctx->tunnel.stream_id),
nghttp2_session_get_remote_window_size(ctx->h2),
Curl_bufq_len(&ctx->tunnel.sendbuf),
Curl_bufq_len(&ctx->outbufq));
CF_DATA_RESTORE(cf, save);
- return nwritten;
+ return result;
}
static CURLcode cf_h2_proxy_flush(struct Curl_cfilter *cf,
case HAPROXY_SEND:
len = curlx_dyn_len(&ctx->data_out);
if(len > 0) {
- ssize_t nwritten;
- nwritten = Curl_conn_cf_send(cf->next, data,
- curlx_dyn_ptr(&ctx->data_out), len, FALSE,
- &result);
- if(nwritten < 0) {
+ size_t nwritten;
+ result = Curl_conn_cf_send(cf->next, data,
+ curlx_dyn_ptr(&ctx->data_out), len, FALSE,
+ &nwritten);
+ if(result) {
if(result != CURLE_AGAIN)
goto out;
result = CURLE_OK;
nwritten = 0;
}
- curlx_dyn_tail(&ctx->data_out, len - (size_t)nwritten);
+ curlx_dyn_tail(&ctx->data_out, len - nwritten);
if(curlx_dyn_len(&ctx->data_out) > 0) {
result = CURLE_OK;
goto out;
#endif /* USE_WINSOCK */
-static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
- const void *buf, size_t len, bool eos,
- CURLcode *err)
+static CURLcode cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, bool eos,
+ size_t *pnwritten)
{
struct cf_socket_ctx *ctx = cf->ctx;
curl_socket_t fdsave;
ssize_t nwritten;
size_t orig_len = len;
+ CURLcode result = CURLE_OK;
(void)eos; /* unused */
- *err = CURLE_OK;
+ *pnwritten = 0;
fdsave = cf->conn->sock[cf->sockindex];
cf->conn->sock[cf->sockindex] = ctx->sock;
Curl_rand_bytes(data, FALSE, &c, 1);
if(c >= ((100-ctx->wblock_percent)*256/100)) {
CURL_TRC_CF(data, cf, "send(len=%zu) SIMULATE EWOULDBLOCK", orig_len);
- *err = CURLE_AGAIN;
- nwritten = -1;
cf->conn->sock[cf->sockindex] = fdsave;
- return nwritten;
+ return CURLE_AGAIN;
}
}
if(cf->cft != &Curl_cft_udp && ctx->wpartial_percent > 0 && len > 8) {
#endif
nwritten = swrite(ctx->sock, buf, len);
- if(-1 == nwritten) {
+ if(nwritten < 0) {
int sockerr = SOCKERRNO;
if(
#endif
) {
/* this is just a case of EWOULDBLOCK */
- *err = CURLE_AGAIN;
+ result = CURLE_AGAIN;
}
else {
char buffer[STRERROR_LEN];
failf(data, "Send failure: %s",
Curl_strerror(sockerr, buffer, sizeof(buffer)));
data->state.os_errno = sockerr;
- *err = CURLE_SEND_ERROR;
+ result = CURLE_SEND_ERROR;
}
}
+ else
+ *pnwritten = (size_t)nwritten;
#if defined(USE_WINSOCK)
- if(!*err)
+ if(!result)
win_update_sndbuf_size(ctx);
#endif
- CURL_TRC_CF(data, cf, "send(len=%zu) -> %d, err=%d",
- orig_len, (int)nwritten, *err);
+ CURL_TRC_CF(data, cf, "send(len=%zu) -> %d, %zu",
+ orig_len, result, *pnwritten);
cf->conn->sock[cf->sockindex] = fdsave;
- return nwritten;
+ return result;
}
-static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
- char *buf, size_t len, CURLcode *err)
+static CURLcode cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, size_t *pnread)
{
struct cf_socket_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
ssize_t nread;
- *err = CURLE_OK;
-
+ *pnread = 0;
#ifdef DEBUGBUILD
/* simulate network blocking/partial reads */
if(cf->cft != &Curl_cft_udp && ctx->rblock_percent > 0) {
Curl_rand(data, &c, 1);
if(c >= ((100-ctx->rblock_percent)*256/100)) {
CURL_TRC_CF(data, cf, "recv(len=%zu) SIMULATE EWOULDBLOCK", len);
- *err = CURLE_AGAIN;
- return -1;
+ return CURLE_AGAIN;
}
}
if(cf->cft != &Curl_cft_udp && ctx->recv_max && ctx->recv_max < len) {
}
#endif
- *err = CURLE_OK;
nread = sread(ctx->sock, buf, len);
- if(-1 == nread) {
+ if(nread < 0) {
int sockerr = SOCKERRNO;
if(
#endif
) {
/* this is just a case of EWOULDBLOCK */
- *err = CURLE_AGAIN;
+ result = CURLE_AGAIN;
}
else {
char buffer[STRERROR_LEN];
-
failf(data, "Recv failure: %s",
Curl_strerror(sockerr, buffer, sizeof(buffer)));
data->state.os_errno = sockerr;
- *err = CURLE_RECV_ERROR;
+ result = CURLE_RECV_ERROR;
}
}
+ else
+ *pnread = (size_t)nread;
- CURL_TRC_CF(data, cf, "recv(len=%zu) -> %d, err=%d", len, (int)nread,
- *err);
- if(nread > 0 && !ctx->got_first_byte) {
+ CURL_TRC_CF(data, cf, "recv(len=%zu) -> %d, %zu", len, result, *pnread);
+ if(!result && !ctx->got_first_byte) {
ctx->first_byte_at = curlx_now();
ctx->got_first_byte = TRUE;
}
- return nread;
+ return result;
}
static void cf_socket_update_data(struct Curl_cfilter *cf,
cf->next->cft->has_data_pending(cf->next, data) : FALSE;
}
-ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+CURLcode Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, bool eos,
- CURLcode *err)
+ size_t *pnwritten)
{
- return cf->next ?
- cf->next->cft->do_send(cf->next, data, buf, len, eos, err) :
- CURLE_RECV_ERROR;
+ if(cf->next)
+ return cf->next->cft->do_send(cf->next, data, buf, len, eos, pnwritten);
+ *pnwritten = 0;
+ return CURLE_RECV_ERROR;
}
-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_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, size_t *pnread)
{
- return cf->next ?
- cf->next->cft->do_recv(cf->next, data, buf, len, err) :
- CURLE_SEND_ERROR;
+ if(cf->next)
+ return cf->next->cft->do_recv(cf->next, data, buf, len, pnread);
+ *pnread = 0;
+ return CURLE_SEND_ERROR;
}
bool Curl_cf_def_conn_is_alive(struct Curl_cfilter *cf,
return result;
}
-ssize_t Curl_cf_recv(struct Curl_easy *data, int num, char *buf,
- size_t len, CURLcode *code)
+CURLcode Curl_cf_recv(struct Curl_easy *data, int num, char *buf,
+ size_t len, size_t *pnread)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
- *code = CURLE_OK;
cf = data->conn->cfilter[num];
- while(cf && !cf->connected) {
+ while(cf && !cf->connected)
cf = cf->next;
- }
- if(cf) {
- ssize_t nread = cf->cft->do_recv(cf, data, buf, len, code);
- DEBUGASSERT(nread >= 0 || *code);
- DEBUGASSERT(nread < 0 || !*code);
- return nread;
- }
+ if(cf)
+ return cf->cft->do_recv(cf, data, buf, len, pnread);
failf(data, "recv: no filter connected");
- *code = CURLE_FAILED_INIT;
- return -1;
+ DEBUGASSERT(0);
+ *pnread = 0;
+ return CURLE_FAILED_INIT;
}
-ssize_t Curl_cf_send(struct Curl_easy *data, int num,
- const void *mem, size_t len, bool eos,
- CURLcode *code)
+CURLcode Curl_cf_send(struct Curl_easy *data, int num,
+ const void *mem, size_t len, bool eos,
+ size_t *pnwritten)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
- *code = CURLE_OK;
cf = data->conn->cfilter[num];
- while(cf && !cf->connected) {
+ while(cf && !cf->connected)
cf = cf->next;
- }
if(cf) {
- ssize_t nwritten = cf->cft->do_send(cf, data, mem, len, eos, code);
- DEBUGASSERT(nwritten >= 0 || *code);
- DEBUGASSERT(nwritten < 0 || !*code || !len);
- return nwritten;
+ return cf->cft->do_send(cf, data, mem, len, eos, pnwritten);
}
failf(data, "send: no filter connected");
DEBUGASSERT(0);
- *code = CURLE_FAILED_INIT;
- return -1;
+ *pnwritten = 0;
+ return CURLE_FAILED_INIT;
}
CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
cf->cft->do_close(cf, data);
}
-ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
- const void *buf, size_t len, bool eos,
- CURLcode *err)
+CURLcode Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, bool eos,
+ size_t *pnwritten)
{
if(cf)
- return cf->cft->do_send(cf, data, buf, len, eos, err);
- *err = CURLE_SEND_ERROR;
- return -1;
+ return cf->cft->do_send(cf, data, buf, len, eos, pnwritten);
+ *pnwritten = 0;
+ return CURLE_SEND_ERROR;
}
-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_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, size_t *pnread)
{
if(cf)
- return cf->cft->do_recv(cf, data, buf, len, err);
- *err = CURLE_RECV_ERROR;
- return -1;
+ return cf->cft->do_recv(cf, data, buf, len, pnread);
+ *pnread = 0;
+ return CURLE_RECV_ERROR;
}
CURLcode Curl_conn_connect(struct Curl_easy *data,
}
CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
- char *buf, size_t blen, ssize_t *n)
+ char *buf, size_t blen, size_t *pnread)
{
- CURLcode result = CURLE_OK;
- ssize_t nread;
-
+ DEBUGASSERT(data);
DEBUGASSERT(data->conn);
- nread = data->conn->recv[sockindex](data, sockindex, buf, blen, &result);
- DEBUGASSERT(nread >= 0 || result);
- DEBUGASSERT(nread < 0 || !result);
- *n = (nread >= 0) ? (size_t)nread : 0;
- return result;
+ if(data && data->conn && data->conn->recv[sockindex])
+ return data->conn->recv[sockindex](data, sockindex, buf, blen, pnread);
+ *pnread = 0;
+ return CURLE_FAILED_INIT;
}
CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
size_t *pnwritten)
{
size_t write_len = blen;
- ssize_t nwritten;
- CURLcode result = CURLE_OK;
- struct connectdata *conn;
- DEBUGASSERT(sockindex >= 0 && sockindex < 2);
- DEBUGASSERT(pnwritten);
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
- conn = data->conn;
+ DEBUGASSERT(sockindex >= 0 && sockindex < 2);
#ifdef DEBUGBUILD
if(write_len) {
/* Allow debug builds to override this logic to force short sends
#endif
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;
+ if(data && data->conn && data->conn->send[sockindex])
+ return data->conn->send[sockindex](data, sockindex, buf, write_len, eos,
+ pnwritten);
+ *pnwritten = 0;
+ return CURLE_FAILED_INIT;
}
void Curl_pollset_reset(struct Curl_easy *data,
typedef bool Curl_cft_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
-typedef ssize_t Curl_cft_send(struct Curl_cfilter *cf,
+typedef CURLcode 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 */
+ size_t *pnwritten); /* how much sent */
-typedef ssize_t Curl_cft_recv(struct Curl_cfilter *cf,
+typedef CURLcode Curl_cft_recv(struct Curl_cfilter *cf,
struct Curl_easy *data, /* transfer */
char *buf, /* store data here */
size_t len, /* amount to read */
- CURLcode *err); /* error to return */
+ size_t *pnread); /* how much received */
typedef bool Curl_cft_conn_is_alive(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps);
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,
+CURLcode Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
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);
+ size_t *pnwritten);
+CURLcode Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, size_t *pnread);
CURLcode Curl_cf_def_cntrl(struct Curl_cfilter *cf,
struct Curl_easy *data,
int event, int arg1, void *arg2);
struct Curl_easy *data,
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, 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_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, bool eos,
+ size_t *pnwritten);
+CURLcode Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, size_t *pnread);
CURLcode Curl_conn_cf_cntrl(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool ignore_result,
/**
* Receive data through the filter chain at `sockindex` for connection
* `data->conn`. Copy at most `len` bytes into `buf`. Return the
- * actual number of bytes copied or a negative value on error.
- * The error code is placed into `*code`.
+ * actual number of bytes copied in `*pnread`or an error.
*/
-ssize_t Curl_cf_recv(struct Curl_easy *data, int sockindex, char *buf,
- size_t len, CURLcode *code);
+CURLcode Curl_cf_recv(struct Curl_easy *data, int sockindex, char *buf,
+ size_t len, size_t *pnread);
/**
* Send `len` bytes of data from `buf` through the filter chain `sockindex`
* at connection `data->conn`. Return the actual number of bytes written
- * or a negative value on error.
- * The error code is placed into `*code`.
+ * in `*pnwritten` or on error.
*/
-ssize_t Curl_cf_send(struct Curl_easy *data, int sockindex,
- const void *buf, size_t len, bool eos, CURLcode *code);
+CURLcode Curl_cf_send(struct Curl_easy *data, int sockindex,
+ const void *buf, size_t len, bool eos,
+ size_t *pnwritten);
/**
* Notify connection filters that they need to setup data for
*/
CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
char *buf, size_t buffersize,
- ssize_t *pnread);
+ size_t *pnread);
/*
* Send data on the connection, using FIRSTSOCKET/SECONDARYSOCKET.
return CURLE_OK;
}
-static ssize_t rtmp_recv(struct Curl_easy *data, int sockindex, char *buf,
- size_t len, CURLcode *err)
+static CURLcode rtmp_recv(struct Curl_easy *data, int sockindex, char *buf,
+ size_t len, size_t *pnread)
{
struct connectdata *conn = data->conn;
RTMP *r = Curl_conn_meta_get(conn, CURL_META_RTMP_CONN);
+ CURLcode result = CURLE_OK;
ssize_t nread;
(void)sockindex; /* unused */
- if(!r) {
- *err = CURLE_FAILED_INIT;
- return -1;
- }
+ *pnread = 0;
+ if(!r)
+ return CURLE_FAILED_INIT;
nread = RTMP_Read(r, buf, curlx_uztosi(len));
if(nread < 0) {
if(r->m_read.status == RTMP_READ_COMPLETE ||
r->m_read.status == RTMP_READ_EOF) {
data->req.size = data->req.bytecount;
- nread = 0;
}
else
- *err = CURLE_RECV_ERROR;
+ result = CURLE_RECV_ERROR;
}
- return nread;
+ else
+ *pnread = (size_t)nread;
+
+ return result;
}
-static ssize_t rtmp_send(struct Curl_easy *data, int sockindex,
- const void *buf, size_t len, bool eos, CURLcode *err)
+static CURLcode rtmp_send(struct Curl_easy *data, int sockindex,
+ const void *buf, size_t len, bool eos,
+ size_t *pnwritten)
{
struct connectdata *conn = data->conn;
RTMP *r = Curl_conn_meta_get(conn, CURL_META_RTMP_CONN);
- ssize_t num;
+ ssize_t nwritten;
(void)sockindex; /* unused */
(void)eos; /* unused */
- if(!r) {
- *err = CURLE_FAILED_INIT;
- return -1;
- }
+ *pnwritten = 0;
+ if(!r)
+ return CURLE_FAILED_INIT;
- num = RTMP_Write(r, (const char *)buf, curlx_uztosi(len));
- if(num < 0)
- *err = CURLE_SEND_ERROR;
+ nwritten = RTMP_Write(r, (const char *)buf, curlx_uztosi(len));
+ if(nwritten < 0)
+ return CURLE_SEND_ERROR;
- return num;
+ *pnwritten = (size_t)nwritten;
+ return CURLE_OK;
}
void Curl_rtmp_version(char *version, size_t len)
CURLcode curl_easy_recv(CURL *d, void *buffer, size_t buflen, size_t *n)
{
CURLcode result;
- ssize_t n1;
struct connectdata *c;
struct Curl_easy *data = d;
Curl_attach_connection(data, c);
*n = 0;
- result = Curl_conn_recv(data, FIRSTSOCKET, buffer, buflen, &n1);
-
- if(result)
- return result;
-
- *n = (size_t)n1;
- return CURLE_OK;
+ return Curl_conn_recv(data, FIRSTSOCKET, buffer, buflen, n);
}
#ifndef CURL_DISABLE_WEBSOCKETS
{
struct Curl_cfilter *cf = reader_ctx;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ size_t nread;
- return Curl_conn_cf_recv(cf->next, data, (char *)buf, buflen, err);
+ *err = Curl_conn_cf_recv(cf->next, data, (char *)buf, buflen, &nread);
+ return *err ? -1 : (ssize_t)nread;
}
static ssize_t nw_out_writer(void *writer_ctx,
{
struct Curl_cfilter *cf = writer_ctx;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ size_t nwritten;
- if(data) {
- 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;
+ if(!data) {
+ *err = CURLE_OK;
+ return 0;
}
- return 0;
+
+ *err = Curl_conn_cf_send(cf->next, data, (const char *)buf,
+ buflen, FALSE, &nwritten);
+ CURL_TRC_CF(data, cf, "[0] egress write -> %d, %zu", *err, nwritten);
+ return *err ? -1 : (ssize_t)nwritten;
}
static ssize_t send_callback(nghttp2_session *h2,
return result;
}
-static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct h2_stream_ctx *stream,
- CURLcode *err)
+static CURLcode http2_handle_stream_close(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct h2_stream_ctx *stream,
+ size_t *pnlen)
{
- ssize_t rv = 0;
+ CURLcode result;
+ *pnlen = 0;
if(stream->error == NGHTTP2_REFUSED_STREAM) {
CURL_TRC_CF(data, cf, "[%d] REFUSED_STREAM, try again on a new "
"connection", stream->id);
connclose(cf->conn, "REFUSED_STREAM"); /* do not use this anymore */
data->state.refused_stream = TRUE;
- *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
- return -1;
+ return CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
}
else if(stream->error != NGHTTP2_NO_ERROR) {
if(stream->resp_hds_complete && data->req.no_body) {
stream->id, nghttp2_http2_strerror(stream->error),
stream->error);
stream->close_handled = TRUE;
- *err = CURLE_OK;
- goto out;
+ return CURLE_OK;
}
failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %u)",
stream->id, nghttp2_http2_strerror(stream->error),
stream->error);
- *err = CURLE_HTTP2_STREAM;
- return -1;
+ return CURLE_HTTP2_STREAM;
}
else if(stream->reset) {
failf(data, "HTTP/2 stream %u was reset", stream->id);
- *err = data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP2;
- return -1;
+ return data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP2;
}
if(!stream->bodystarted) {
failf(data, "HTTP/2 stream %u was closed cleanly, but before getting "
" all response header fields, treated as error",
stream->id);
- *err = CURLE_HTTP2_STREAM;
- return -1;
+ return CURLE_HTTP2_STREAM;
}
if(Curl_dynhds_count(&stream->resp_trailers)) {
struct dynbuf dbuf;
size_t i;
- *err = CURLE_OK;
+ result = CURLE_OK;
curlx_dyn_init(&dbuf, DYN_TRAILERS);
for(i = 0; i < Curl_dynhds_count(&stream->resp_trailers); ++i) {
e = Curl_dynhds_getn(&stream->resp_trailers, i);
if(!e)
break;
curlx_dyn_reset(&dbuf);
- *err = curlx_dyn_addf(&dbuf, "%.*s: %.*s\x0d\x0a",
+ result = curlx_dyn_addf(&dbuf, "%.*s: %.*s\x0d\x0a",
(int)e->namelen, e->name,
(int)e->valuelen, e->value);
- if(*err)
+ if(result)
break;
Curl_debug(data, CURLINFO_HEADER_IN, curlx_dyn_ptr(&dbuf),
curlx_dyn_len(&dbuf));
- *err = Curl_client_write(data, CLIENTWRITE_HEADER|CLIENTWRITE_TRAILER,
- curlx_dyn_ptr(&dbuf), curlx_dyn_len(&dbuf));
- if(*err)
+ result = Curl_client_write(data, CLIENTWRITE_HEADER|CLIENTWRITE_TRAILER,
+ curlx_dyn_ptr(&dbuf), curlx_dyn_len(&dbuf));
+ if(result)
break;
}
curlx_dyn_free(&dbuf);
- if(*err)
+ if(result)
goto out;
}
stream->close_handled = TRUE;
- *err = CURLE_OK;
- rv = 0;
+ result = CURLE_OK;
out:
- CURL_TRC_CF(data, cf, "handle_stream_close -> %zd, %d", rv, *err);
- return rv;
+ CURL_TRC_CF(data, cf, "handle_stream_close -> %d, %zu", result, *pnlen);
+ return result;
}
static int sweight_wanted(const struct Curl_easy *data)
return nw_out_flush(cf, data);
}
-static ssize_t stream_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
- struct h2_stream_ctx *stream,
- char *buf, size_t len, CURLcode *err)
+static CURLcode stream_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct h2_stream_ctx *stream,
+ char *buf, size_t len, size_t *pnread)
{
struct cf_h2_ctx *ctx = cf->ctx;
- ssize_t nread = -1;
+ CURLcode result = CURLE_AGAIN;
(void)buf;
- *err = CURLE_AGAIN;
+ (void)len;
+ *pnread = 0;
+
if(stream->xfer_result) {
CURL_TRC_CF(data, cf, "[%d] xfer write failed", stream->id);
- *err = stream->xfer_result;
- nread = -1;
+ result = stream->xfer_result;
}
else if(stream->closed) {
CURL_TRC_CF(data, cf, "[%d] returning CLOSE", stream->id);
- nread = http2_handle_stream_close(cf, data, stream, err);
+ result = http2_handle_stream_close(cf, data, stream, pnread);
}
else if(stream->reset ||
(ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) ||
(ctx->rcvd_goaway && ctx->remote_max_sid < stream->id)) {
CURL_TRC_CF(data, cf, "[%d] returning ERR", stream->id);
- *err = data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP2;
- nread = -1;
+ result = data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP2;
}
- if(nread < 0 && *err != CURLE_AGAIN)
- CURL_TRC_CF(data, cf, "[%d] stream_recv(len=%zu) -> %zd, %d",
- stream->id, len, nread, *err);
- return nread;
+ if(result && (result != CURLE_AGAIN))
+ CURL_TRC_CF(data, cf, "[%d] stream_recv(len=%zu) -> %d, %zu",
+ stream->id, len, result, *pnread);
+ return result;
}
static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
return CURLE_OK;
}
-static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
- char *buf, size_t len, CURLcode *err)
+static CURLcode cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, size_t *pnread)
{
struct cf_h2_ctx *ctx = cf->ctx;
struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
- ssize_t nread = -1;
- CURLcode result;
+ CURLcode result, r2;
struct cf_call_data save;
+ *pnread = 0;
if(!stream) {
/* Abnormal call sequence: either this transfer has never opened a stream
* (unlikely) or the transfer has been done, cleaned up its resources, but
* is for such a case. */
failf(data, "http/2 recv on a transfer never opened "
"or already cleared, mid=%u", data->mid);
- *err = CURLE_HTTP2;
- return -1;
+ return CURLE_HTTP2;
}
CF_DATA_SAVE(save, cf, data);
- nread = stream_recv(cf, data, stream, buf, len, err);
- if(nread < 0 && *err != CURLE_AGAIN)
+ result = stream_recv(cf, data, stream, buf, len, pnread);
+ if(result && (result != CURLE_AGAIN))
goto out;
- if(nread < 0) {
- *err = h2_progress_ingress(cf, data, len);
- if(*err)
+ if(result) {
+ result = h2_progress_ingress(cf, data, len);
+ if(result)
goto out;
- nread = stream_recv(cf, data, stream, buf, len, err);
+ result = stream_recv(cf, data, stream, buf, len, pnread);
}
- if(nread > 0) {
+ if(*pnread > 0) {
/* Now that we transferred this to the upper layer, we report
* the actual amount of DATA consumed to the H2 session, so
* that it adjusts stream flow control */
- nghttp2_session_consume(ctx->h2, stream->id, (size_t)nread);
+ nghttp2_session_consume(ctx->h2, stream->id, *pnread);
if(stream->closed) {
CURL_TRC_CF(data, cf, "[%d] DRAIN closed stream", stream->id);
drain_stream(cf, data, stream);
}
out:
- result = h2_progress_egress(cf, data);
- if(result == CURLE_AGAIN) {
+ r2 = h2_progress_egress(cf, data);
+ if(r2 == CURLE_AGAIN) {
/* pending data to send, need to be called again. Ideally, we
* monitor the socket for POLLOUT, but when not SENDING
* any more, we force processing of the transfer. */
if(!CURL_WANT_SEND(data))
drain_stream(cf, data, stream);
}
- else if(result) {
- *err = result;
- nread = -1;
+ else if(r2) {
+ result = r2;
}
- CURL_TRC_CF(data, cf, "[%d] cf_recv(len=%zu) -> %zd %d, "
+ CURL_TRC_CF(data, cf, "[%d] cf_recv(len=%zu) -> %d, %zu, "
"window=%d/%d, connection %d/%d",
- stream->id, len, nread, *err,
+ stream->id, len, result, *pnread,
nghttp2_session_get_stream_effective_recv_data_length(
ctx->h2, stream->id),
nghttp2_session_get_stream_effective_local_window_size(
HTTP2_HUGE_WINDOW_SIZE);
CF_DATA_RESTORE(cf, save);
- return nread;
+ return result;
}
static ssize_t cf_h2_body_send(struct Curl_cfilter *cf,
return nwritten;
}
-static ssize_t h2_submit(struct h2_stream_ctx **pstream,
- struct Curl_cfilter *cf, struct Curl_easy *data,
- const void *buf, size_t len,
- bool eos, CURLcode *err)
+static CURLcode h2_submit(struct h2_stream_ctx **pstream,
+ struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len,
+ bool eos, size_t *pnwritten)
{
struct cf_h2_ctx *ctx = cf->ctx;
struct h2_stream_ctx *stream = NULL;
int32_t stream_id;
nghttp2_priority_spec pri_spec;
ssize_t nwritten;
+ CURLcode result = CURLE_OK;
+ *pnwritten = 0;
Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
- *err = http2_data_setup(cf, data, &stream);
- if(*err) {
- nwritten = -1;
+ result = http2_data_setup(cf, data, &stream);
+ if(result)
goto out;
- }
- nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
+ nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, &result);
if(nwritten < 0)
goto out;
+ *pnwritten = (size_t)nwritten;
if(!stream->h1.done) {
/* need more data */
goto out;
}
DEBUGASSERT(stream->h1.req);
- *err = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
- if(*err) {
- nwritten = -1;
+ result = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
+ if(result)
goto out;
- }
/* no longer needed */
Curl_h1_req_parse_free(&stream->h1);
nva = Curl_dynhds_to_nva(&h2_headers, &nheader);
if(!nva) {
- *err = CURLE_OUT_OF_MEMORY;
- nwritten = -1;
+ result = CURLE_OUT_OF_MEMORY;
goto out;
}
if(stream_id < 0) {
CURL_TRC_CF(data, cf, "send: nghttp2_submit_request error (%s)%u",
nghttp2_strerror(stream_id), stream_id);
- *err = CURLE_SEND_ERROR;
- nwritten = -1;
+ result = CURLE_SEND_ERROR;
goto out;
}
stream->id = stream_id;
- body = (const char *)buf + nwritten;
- bodylen = len - nwritten;
+ body = (const char *)buf + *pnwritten;
+ bodylen = len - *pnwritten;
if(bodylen || eos) {
- ssize_t n = cf_h2_body_send(cf, data, stream, body, bodylen, eos, err);
+ ssize_t n = cf_h2_body_send(cf, data, stream, body, bodylen, eos, &result);
if(n >= 0)
- nwritten += n;
- else if(*err == CURLE_AGAIN)
- *err = CURLE_OK;
- else if(*err != CURLE_AGAIN) {
- *err = CURLE_SEND_ERROR;
- nwritten = -1;
- goto out;
+ *pnwritten += n;
+ else if(result == CURLE_AGAIN)
+ result = CURLE_OK;
+ else {
+ result = CURLE_SEND_ERROR;
}
}
out:
- CURL_TRC_CF(data, cf, "[%d] submit -> %zd, %d",
- stream ? stream->id : -1, nwritten, *err);
+ CURL_TRC_CF(data, cf, "[%d] submit -> %d, %zu",
+ stream ? stream->id : -1, result, *pnwritten);
Curl_safefree(nva);
*pstream = stream;
Curl_dynhds_free(&h2_headers);
- return nwritten;
+ return result;
}
-static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
- const void *buf, size_t len, bool eos,
- CURLcode *err)
+static CURLcode cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, bool eos,
+ size_t *pnwritten)
{
struct cf_h2_ctx *ctx = cf->ctx;
struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
struct cf_call_data save;
ssize_t nwritten;
- CURLcode result;
+ CURLcode result = CURLE_OK, r2;
CF_DATA_SAVE(save, cf, data);
+ *pnwritten = 0;
if(!stream || stream->id == -1) {
- nwritten = h2_submit(&stream, cf, data, buf, len, eos, err);
- if(nwritten < 0) {
+ result = h2_submit(&stream, cf, data, buf, len, eos, pnwritten);
+ if(result)
goto out;
- }
DEBUGASSERT(stream);
}
else if(stream->body_eos) {
* to trigger flushing again.
* If this works, we report to have written `len` bytes. */
DEBUGASSERT(eos);
- nwritten = cf_h2_body_send(cf, data, stream, buf, 0, eos, err);
+ nwritten = cf_h2_body_send(cf, data, stream, buf, 0, eos, &result);
CURL_TRC_CF(data, cf, "[%d] cf_body_send last CHUNK -> %zd, %d, eos=%d",
- stream->id, nwritten, *err, eos);
+ stream->id, nwritten, result, eos);
if(nwritten < 0) {
goto out;
}
- nwritten = len;
+ *pnwritten = len;
}
else {
- nwritten = cf_h2_body_send(cf, data, stream, buf, len, eos, err);
+ nwritten = cf_h2_body_send(cf, data, stream, buf, len, eos, &result);
CURL_TRC_CF(data, cf, "[%d] cf_body_send(len=%zu) -> %zd, %d, eos=%d",
- stream->id, len, nwritten, *err, eos);
+ stream->id, len, nwritten, result, eos);
+ if(nwritten >= 0)
+ *pnwritten = (size_t)nwritten;
}
/* Call the nghttp2 send loop and flush to write ALL buffered data,
* headers and/or request body completely out to the network */
- result = h2_progress_egress(cf, data);
+ r2 = h2_progress_egress(cf, data);
/* if the stream has been closed in egress handling (nghttp2 does that
* when it does not like the headers, for example */
if(stream && stream->closed) {
infof(data, "stream %u closed", stream->id);
- *err = CURLE_SEND_ERROR;
- nwritten = -1;
+ result = CURLE_SEND_ERROR;
goto out;
}
- else if(result && (result != CURLE_AGAIN)) {
- *err = result;
- nwritten = -1;
+ else if(r2 && (r2 != CURLE_AGAIN)) {
+ result = r2;
goto out;
}
/* nghttp2 thinks this session is done. If the stream has not been
* closed, this is an error state for out transfer */
if(stream && stream->closed) {
- nwritten = http2_handle_stream_close(cf, data, stream, err);
+ result = http2_handle_stream_close(cf, data, stream, pnwritten);
}
else {
CURL_TRC_CF(data, cf, "send: nothing to do in this session");
- *err = CURLE_HTTP2;
- nwritten = -1;
+ result = CURLE_HTTP2;
}
}
out:
if(stream) {
- CURL_TRC_CF(data, cf, "[%d] cf_send(len=%zu) -> %zd, %d, "
+ CURL_TRC_CF(data, cf, "[%d] cf_send(len=%zu) -> %d, %zu, "
"eos=%d, h2 windows %d-%d (stream-conn), "
"buffers %zu-%zu (stream-conn)",
- stream->id, len, nwritten, *err,
+ stream->id, len, result, *pnwritten,
stream->body_eos,
nghttp2_session_get_stream_remote_window_size(
ctx->h2, stream->id),
Curl_bufq_len(&ctx->outbufq));
}
else {
- CURL_TRC_CF(data, cf, "cf_send(len=%zu) -> %zd, %d, "
+ CURL_TRC_CF(data, cf, "cf_send(len=%zu) -> %d, %zu, "
"connection-window=%d, nw_send_buffer(%zu)",
- len, nwritten, *err,
+ len, result, *pnwritten,
nghttp2_session_get_remote_window_size(ctx->h2),
Curl_bufq_len(&ctx->outbufq));
}
CF_DATA_RESTORE(cf, save);
- return nwritten;
+ return result;
}
static CURLcode cf_h2_flush(struct Curl_cfilter *cf,
{
char *to_p = to;
CURLcode result;
- ssize_t nread = 0;
+ size_t nread = 0;
while(len > 0) {
result = Curl_conn_recv(data, sockindex, to_p, len, &nread);
- if(nread > 0) {
- len -= nread;
- to_p += nread;
- }
- else {
- if(result == CURLE_AGAIN)
- continue;
+ if(result == CURLE_AGAIN)
+ continue;
+ if(result)
return result;
- }
+ if(nread > len)
+ return CURLE_RECV_ERROR;
+ len -= nread;
+ to_p += nread;
}
return CURLE_OK;
}
return CURLE_OK;
}
-static CURLcode read_data(struct Curl_easy *data, int sockindex,
- struct krb5buffer *buf)
+static CURLcode krb5_read_data(struct Curl_easy *data, int sockindex,
+ struct krb5buffer *buf)
{
struct connectdata *conn = data->conn;
int len;
}
/* Matches Curl_recv signature */
-static ssize_t sec_recv(struct Curl_easy *data, int sockindex,
- char *buffer, size_t len, CURLcode *err)
+static CURLcode sec_recv(struct Curl_easy *data, int sockindex,
+ char *buffer, size_t len, size_t *pnread)
{
- size_t bytes_read;
- size_t total_read = 0;
struct connectdata *conn = data->conn;
-
- *err = CURLE_OK;
+ CURLcode result = CURLE_OK;
+ size_t bytes_read;
/* Handle clear text response. */
- if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR) {
- ssize_t nread;
- *err = Curl_conn_recv(data, sockindex, buffer, len, &nread);
- return nread;
- }
+ if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR)
+ return Curl_conn_recv(data, sockindex, buffer, len, pnread);
if(conn->in_buffer.eof_flag) {
conn->in_buffer.eof_flag = 0;
- return 0;
+ *pnread = 0;
+ return CURLE_OK;
}
bytes_read = buffer_read(&conn->in_buffer, buffer, len);
- len -= bytes_read;
- total_read += bytes_read;
buffer += bytes_read;
+ len -= bytes_read;
+ *pnread += bytes_read;
while(len > 0) {
- if(read_data(data, sockindex, &conn->in_buffer))
- return -1;
+ result = krb5_read_data(data, sockindex, &conn->in_buffer);
+ if(result)
+ return result;
if(curlx_dyn_len(&conn->in_buffer.buf) == 0) {
- if(bytes_read > 0)
+ if(*pnread > 0)
conn->in_buffer.eof_flag = 1;
- return bytes_read;
+ return result;
}
bytes_read = buffer_read(&conn->in_buffer, buffer, len);
- len -= bytes_read;
- total_read += bytes_read;
buffer += bytes_read;
+ len -= bytes_read;
+ *pnread += bytes_read;
}
- return total_read;
+ return result;
}
/* Send |length| bytes from |from| to the |sockindex| socket taking care of
encoding and negotiating with the server. |from| can be NULL. */
static void do_sec_send(struct Curl_easy *data, struct connectdata *conn,
- int sockindex, const char *from, int length)
+ int sockindex, const char *from, size_t length)
{
int bytes, htonl_bytes; /* 32-bit integers for htonl */
char *buffer = NULL;
else
prot_level = conn->command_prot;
}
- bytes = conn->mech->encode(conn->app_data, from, length, (int)prot_level,
- (void **)&buffer);
+ bytes = conn->mech->encode(conn->app_data, from, (int)length,
+ (int)prot_level, (void **)&buffer);
if(!buffer || bytes <= 0)
return; /* error */
free(buffer);
}
-static ssize_t sec_write(struct Curl_easy *data, struct connectdata *conn,
- int sockindex, const char *buffer, size_t length)
+static CURLcode sec_write(struct Curl_easy *data, int sockindex,
+ const char *buffer, size_t length,
+ size_t *pnwritten)
{
- ssize_t tx = 0, len = conn->buffer_size;
+ struct connectdata *conn = data->conn;
+ size_t len = conn->buffer_size;
+ *pnwritten = 0;
if(len <= 0)
len = length;
while(length) {
- if(length < (size_t)len)
+ if(length < len)
len = length;
- do_sec_send(data, conn, sockindex, buffer, curlx_sztosi(len));
+ /* WTF: this ignores all errors writing to the socket */
+ do_sec_send(data, conn, sockindex, buffer, len);
length -= len;
buffer += len;
- tx += len;
+ *pnwritten += len;
}
- return tx;
+ return CURLE_OK;
}
/* Matches Curl_send signature */
-static ssize_t sec_send(struct Curl_easy *data, int sockindex,
- const void *buffer, size_t len, bool eos,
- CURLcode *err)
+static CURLcode sec_send(struct Curl_easy *data, int sockindex,
+ const void *buffer, size_t len, bool eos,
+ size_t *pnwritten)
{
- struct connectdata *conn = data->conn;
(void)eos; /* unused */
- *err = CURLE_OK;
- return sec_write(data, conn, sockindex, buffer, len);
+ return sec_write(data, sockindex, buffer, len, pnwritten);
}
int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn,
if(rlen < nbytes) {
unsigned char readbuf[1024];
- ssize_t nread;
+ size_t nread;
DEBUGASSERT(nbytes - rlen < sizeof(readbuf));
result = Curl_xfer_recv(data, (char *)readbuf, nbytes - rlen, &nread);
if(result)
return result;
- DEBUGASSERT(nread >= 0);
- if(curlx_dyn_addn(&mq->recvbuf, readbuf, (size_t)nread))
+ if(curlx_dyn_addn(&mq->recvbuf, readbuf, nread))
return CURLE_OUT_OF_MEMORY;
rlen = curlx_dyn_len(&mq->recvbuf);
}
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- ssize_t nread;
+ size_t nread;
size_t remlen;
struct mqtt_conn *mqtt = Curl_conn_meta_get(conn, CURL_META_MQTT_CONN);
struct MQTT *mq = Curl_meta_get(data, CURL_META_MQTT_EASY);
{
struct MQTT *mq = Curl_meta_get(data, CURL_META_MQTT_EASY);
CURLcode result = CURLE_OK;
- ssize_t nread;
+ size_t nread;
unsigned char recvbyte;
struct mqtt_conn *mqtt = Curl_conn_meta_get(data->conn, CURL_META_MQTT_CONN);
struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
struct curl_pollfds cpfds;
unsigned int curl_nfds = 0; /* how many pfds are for curl transfers */
+ struct Curl_easy *data = NULL;
CURLMcode result = CURLM_OK;
unsigned int mid;
/* Add the curl handles to our pollfds first */
if(Curl_uint_bset_first(&multi->process, &mid)) {
do {
- struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
struct easy_pollset ps;
+ data = Curl_multi_get_easy(multi, mid);
if(!data) {
DEBUGASSERT(0);
Curl_uint_bset_remove(&multi->process, mid);
if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
timeout_ms = (int)timeout_internal;
+ if(data)
+ CURL_TRC_M(data, "multi_wait(fds=%d, timeout=%d) tinternal=%ld",
+ cpfds.n, timeout_ms, timeout_internal);
#if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
if(cpfds.n || use_wakeup) {
#else
/* This avoids CURLM_CALL_MULTI_PERFORM so that a very fast transfer does
not get stuck on this transfer at the expense of other concurrent
transfers */
+ CURL_TRC_M(data, "EXPIRE_RUN_NOW unblocked, select_bits=%x",
+ data->state.select_bits);
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
free(newurl);
*timeout_ms = (long)diff;
}
else {
+ if(multi->timetree) {
+ struct Curl_easy *data = Curl_splayget(multi->timetree);
+ CURL_TRC_M(data, "multi_timeout() says this has expired");
+ }
/* 0 means immediately */
*timeout_ms = 0;
}
Curl_splayset(&data->state.timenode, data);
multi->timetree = Curl_splayinsert(*curr_expire, multi->timetree,
&data->state.timenode);
+ if(data->id >= 0)
+ CURL_TRC_M(data, "set expire[%d] in %" FMT_TIMEDIFF_T "ns",
+ id, curlx_timediff_us(set, *nowp));
}
/*
return result;
}
-static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
- size_t len, CURLcode *err)
+static CURLcode oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
+ size_t len, size_t *pnread)
{
struct connectdata *conn = data->conn;
struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
(void)len;
(void)buf;
(void)sockindex;
- if(!li || !lr) {
- *err = CURLE_FAILED_INIT;
- return -1;
- }
+ *pnread = 0;
+ if(!li || !lr)
+ return CURLE_FAILED_INIT;
rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_ONE, &tv, &msg);
if(rc < 0) {
result = CURLE_RECV_ERROR;
}
- *err = result;
-
/* error or timed out */
if(!msg)
- return -1;
+ return result;
result = CURLE_OK;
}
ldap_msgfree(msg);
- *err = result;
- return result ? -1 : 0;
+ return result;
}
#ifdef USE_SSL
if(conn) {
struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
CURLcode err = CURLE_RECV_ERROR;
+ size_t nread;
if(!li) {
SET_SOCKERRNO(SOCKEINVAL);
return -1;
}
- ret = (li->recv)(data, FIRSTSOCKET, buf, len, &err);
- if(ret < 0 && err == CURLE_AGAIN) {
+ err = (li->recv)(data, FIRSTSOCKET, buf, len, &nread);
+ if(err == CURLE_AGAIN) {
SET_SOCKERRNO(SOCKEWOULDBLOCK);
}
+ ret = err ? -1 : (ber_slen_t)nread;
}
}
return ret;
if(conn) {
struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
CURLcode err = CURLE_SEND_ERROR;
+ size_t nwritten;
if(!li) {
SET_SOCKERRNO(SOCKEINVAL);
return -1;
}
- ret = (li->send)(data, FIRSTSOCKET, buf, len, FALSE, &err);
- if(ret < 0 && err == CURLE_AGAIN) {
+ err = (li->send)(data, FIRSTSOCKET, buf, len, FALSE, &nwritten);
+ if(err == CURLE_AGAIN) {
SET_SOCKERRNO(SOCKEWOULDBLOCK);
}
+ ret = err ? -1 : (ber_slen_t)nwritten;
}
}
return ret;
int sockindex,
char *buffer,
size_t buflen,
- ssize_t *nread)
+ size_t *nread)
{
CURLcode result;
#ifdef HAVE_GSSAPI
{
struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
- ssize_t gotbytes;
+ size_t gotbytes;
char buffer[900];
*code = 0; /* 0 for errors or not done */
if(result)
return result;
- if(gotbytes <= 0) {
+ if(!gotbytes) {
failf(data, "response reading failed (errno: %d)", SOCKERRNO);
return CURLE_RECV_ERROR;
}
void **msg)
{
char *buf = smbc->recv_buf;
- ssize_t bytes_read;
+ size_t bytes_read;
size_t nbt_size;
size_t msg_size;
size_t len = MAX_MESSAGE_SIZE - smbc->got;
struct socks_state {
enum connect_t state;
- ssize_t outstanding; /* send this many bytes more */
+ size_t outstanding; /* send this many bytes more */
unsigned char buffer[CURL_SOCKS_BUF_SIZE];
unsigned char *outp; /* send from this pointer */
int Curl_blockread_all(struct Curl_cfilter *cf,
struct Curl_easy *data, /* transfer */
char *buf, /* store read data here */
- ssize_t buffersize, /* max amount to read */
- ssize_t *n) /* amount bytes read */
+ size_t blen, /* space in buf */
+ size_t *pnread) /* amount bytes read */
{
- ssize_t nread = 0;
- ssize_t allread = 0;
- int result;
- CURLcode err = CURLE_OK;
+ size_t nread = 0;
+ CURLcode err;
- *n = 0;
+ *pnread = 0;
for(;;) {
timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* we already got the timeout */
- result = CURLE_OPERATION_TIMEDOUT;
- break;
+ return CURLE_OPERATION_TIMEDOUT;
}
if(!timeout_ms)
timeout_ms = TIMEDIFF_T_MAX;
if(SOCKET_READABLE(cf->conn->sock[cf->sockindex], timeout_ms) <= 0) {
- result = ~CURLE_OK;
- break;
- }
- nread = Curl_conn_cf_recv(cf->next, data, buf, buffersize, &err);
- if(nread <= 0) {
- result = (int)err;
- if(CURLE_AGAIN == err)
- continue;
- if(err) {
- break;
- }
+ return ~CURLE_OK;
}
-
- if(buffersize == nread) {
- allread += nread;
- *n = allread;
- result = CURLE_OK;
- break;
- }
- if(!nread) {
- result = ~CURLE_OK;
- break;
+ err = Curl_conn_cf_recv(cf->next, data, buf, blen, &nread);
+ if(CURLE_AGAIN == err)
+ continue;
+ else if(err)
+ return (int)err;
+
+ if(blen == nread) {
+ *pnread += nread;
+ return CURLE_OK;
}
+ if(!nread) /* EOF */
+ return ~CURLE_OK;
- buffersize -= nread;
buf += nread;
- allread += nread;
+ blen -= nread;
+ *pnread += nread;
}
- return result;
}
#endif
CURLproxycode failcode,
const char *description)
{
- ssize_t nwritten;
+ size_t nwritten;
CURLcode result;
- nwritten = Curl_conn_cf_send(cf->next, data, (char *)sx->outp,
- sx->outstanding, FALSE, &result);
- if(nwritten <= 0) {
- if(CURLE_AGAIN == result) {
+ result = Curl_conn_cf_send(cf->next, data, (char *)sx->outp,
+ sx->outstanding, FALSE, &nwritten);
+ if(result) {
+ if(CURLE_AGAIN == result)
return CURLPX_OK;
- }
- else if(CURLE_OK == result) {
- /* connection closed */
- failf(data, "connection to proxy closed");
- return CURLPX_CLOSED;
- }
+
failf(data, "Failed to send %s: %s", description,
curl_easy_strerror(result));
return failcode;
}
+ else if(!nwritten) {
+ /* connection closed */
+ failf(data, "connection to proxy closed");
+ return CURLPX_CLOSED;
+ }
+
DEBUGASSERT(sx->outstanding >= nwritten);
/* not done, remain in state */
sx->outstanding -= nwritten;
CURLproxycode failcode,
const char *description)
{
- ssize_t nread;
+ size_t nread;
CURLcode result;
- nread = Curl_conn_cf_recv(cf->next, data, (char *)sx->outp,
- sx->outstanding, &result);
- if(nread <= 0) {
- if(CURLE_AGAIN == result) {
+ result = Curl_conn_cf_recv(cf->next, data, (char *)sx->outp,
+ sx->outstanding, &nread);
+ if(result) {
+ if(CURLE_AGAIN == result)
return CURLPX_OK;
- }
- else if(CURLE_OK == result) {
- /* connection closed */
- failf(data, "connection to proxy closed");
- return CURLPX_CLOSED;
- }
+
failf(data, "SOCKS: Failed receiving %s: %s", description,
curl_easy_strerror(result));
return failcode;
}
+ else if(!nread) {
+ /* connection closed */
+ failf(data, "connection to proxy closed");
+ return CURLPX_CLOSED;
+ }
/* remain in reading state */
DEBUGASSERT(sx->outstanding >= nread);
sx->outstanding -= nread;
int Curl_blockread_all(struct Curl_cfilter *cf,
struct Curl_easy *data,
char *buf,
- ssize_t buffersize,
- ssize_t *n);
+ size_t blen,
+ size_t *pnread);
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
/*
struct connectdata *conn = cf->conn;
curl_socket_t sock = conn->sock[cf->sockindex];
CURLcode code;
- ssize_t actualread;
- ssize_t nwritten;
+ size_t actualread;
+ size_t nwritten;
int result;
OM_uint32 gss_major_status, gss_minor_status, gss_status;
OM_uint32 gss_ret_flags;
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,
- FALSE, &code);
+ code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4,
+ FALSE, &nwritten);
if(code || (4 != nwritten)) {
failf(data, "Failed to send GSS-API authentication request.");
gss_release_name(&gss_status, &server);
return CURLE_COULDNT_CONNECT;
}
- nwritten = Curl_conn_cf_send(cf->next, data,
- (char *)gss_send_token.value,
- gss_send_token.length, FALSE, &code);
- if(code || ((ssize_t)gss_send_token.length != nwritten)) {
+ code = Curl_conn_cf_send(cf->next, data,
+ (char *)gss_send_token.value,
+ gss_send_token.length, FALSE, &nwritten);
+ if(code || (gss_send_token.length != nwritten)) {
failf(data, "Failed to send GSS-API authentication token.");
gss_release_name(&gss_status, &server);
gss_release_buffer(&gss_status, &gss_recv_token);
memcpy(socksreq + 2, &us_length, sizeof(short));
}
- nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE,
- &code);
+ code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE,
+ &nwritten);
if(code || (4 != nwritten)) {
failf(data, "Failed to send GSS-API encryption request.");
gss_release_buffer(&gss_status, &gss_w_token);
if(data->set.socks5_gssapi_nec) {
memcpy(socksreq, &gss_enc, 1);
- nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, FALSE,
- &code);
+ code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, FALSE,
+ &nwritten);
if(code || ( 1 != nwritten)) {
failf(data, "Failed to send GSS-API encryption type.");
gss_delete_sec_context(&gss_status, &gss_context, NULL);
}
}
else {
- nwritten = Curl_conn_cf_send(cf->next, data,
- (char *)gss_w_token.value,
- gss_w_token.length, FALSE, &code);
- if(code || ((ssize_t)gss_w_token.length != nwritten)) {
+ code = Curl_conn_cf_send(cf->next, data, (char *)gss_w_token.value,
+ gss_w_token.length, FALSE, &nwritten);
+ if(code || (gss_w_token.length != nwritten)) {
failf(data, "Failed to send GSS-API encryption type.");
gss_release_buffer(&gss_status, &gss_w_token);
gss_delete_sec_context(&gss_status, &gss_context, NULL);
struct connectdata *conn = cf->conn;
curl_socket_t sock = conn->sock[cf->sockindex];
CURLcode code;
- ssize_t actualread;
- ssize_t written;
+ size_t actualread;
+ size_t written;
int result;
/* Needs GSS-API authentication */
SECURITY_STATUS status;
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, FALSE,
- &code);
+ code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE,
+ &written);
if(code || (4 != written)) {
failf(data, "Failed to send SSPI authentication request.");
free(service_name);
return CURLE_COULDNT_CONNECT;
}
- written = Curl_conn_cf_send(cf->next, data,
- (char *)sspi_send_token.pvBuffer,
- sspi_send_token.cbBuffer, FALSE, &code);
- if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
+ code = Curl_conn_cf_send(cf->next, data,
+ (char *)sspi_send_token.pvBuffer,
+ sspi_send_token.cbBuffer, FALSE, &written);
+ if(code || (sspi_send_token.cbBuffer != written)) {
failf(data, "Failed to send SSPI authentication token.");
free(service_name);
if(sspi_send_token.pvBuffer)
memcpy(socksreq + 2, &us_length, sizeof(short));
}
- written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE,
- &code);
+ code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE,
+ &written);
if(code || (4 != written)) {
failf(data, "Failed to send SSPI encryption request.");
if(sspi_send_token.pvBuffer)
if(data->set.socks5_gssapi_nec) {
memcpy(socksreq, &gss_enc, 1);
- written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, FALSE,
- &code);
+ code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, FALSE,
+ &written);
if(code || (1 != written)) {
failf(data, "Failed to send SSPI encryption type.");
Curl_pSecFn->DeleteSecurityContext(&sspi_context);
}
}
else {
- written = Curl_conn_cf_send(cf->next, data,
- (char *)sspi_send_token.pvBuffer,
- sspi_send_token.cbBuffer, FALSE, &code);
+ code = Curl_conn_cf_send(cf->next, data,
+ (char *)sspi_send_token.pvBuffer,
+ sspi_send_token.cbBuffer, FALSE, &written);
if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
failf(data, "Failed to send SSPI encryption type.");
if(sspi_send_token.pvBuffer)
int poll_cnt;
curl_off_t total_dl = 0;
curl_off_t total_ul = 0;
+ ssize_t snread;
#endif
- ssize_t nread;
struct curltime now;
bool keepon = TRUE;
char buffer[4*1024];
}
if(events.lNetworkEvents & FD_READ) {
/* read data from network */
+ size_t nread;
result = Curl_xfer_recv(data, buffer, sizeof(buffer), &nread);
/* read would have blocked. Loop again */
if(result == CURLE_AGAIN)
}
/* returned zero but actually received 0 or less here,
the server closed the connection and we bail out */
- else if(nread <= 0) {
+ else if(!nread) {
keepon = FALSE;
break;
}
default: /* read! */
if(pfd[0].revents & POLLIN) {
/* read data from network */
+ size_t nread;
result = Curl_xfer_recv(data, buffer, sizeof(buffer), &nread);
/* read would have blocked. Loop again */
if(result == CURLE_AGAIN)
}
/* returned zero but actually received 0 or less here,
the server closed the connection and we bail out */
- else if(nread <= 0) {
+ else if(!nread) {
keepon = FALSE;
break;
}
}
}
- nread = 0;
+ snread = 0;
if(poll_cnt == 2) {
if(pfd[1].revents & POLLIN) { /* read from in file */
- nread = read(pfd[1].fd, buffer, sizeof(buffer));
+ snread = read(pfd[1].fd, buffer, sizeof(buffer));
}
}
else {
/* read from user-supplied method */
- nread = (int)data->state.fread_func(buffer, 1, sizeof(buffer),
+ snread = (int)data->state.fread_func(buffer, 1, sizeof(buffer),
data->state.in);
- if(nread == CURL_READFUNC_ABORT) {
+ if(snread == CURL_READFUNC_ABORT) {
keepon = FALSE;
break;
}
- if(nread == CURL_READFUNC_PAUSE)
+ if(snread == CURL_READFUNC_PAUSE)
break;
}
- if(nread > 0) {
- result = send_telnet_data(data, tn, buffer, nread);
+ if(snread > 0) {
+ result = send_telnet_data(data, tn, buffer, snread);
if(result) {
keepon = FALSE;
break;
}
- total_ul += nread;
+ total_ul += snread;
Curl_pgrsSetUploadCounter(data, total_ul);
}
- else if(nread < 0)
+ else if(snread < 0)
keepon = FALSE;
break;
bool eos_reliable,
CURLcode *err)
{
- ssize_t nread;
+ size_t nread;
DEBUGASSERT(blen > 0);
/* If we are reading BODY data and the connection does NOT handle EOF
}
DEBUGF(infof(data, "sendrecv_dl: we are done"));
}
- DEBUGASSERT(nread >= 0);
- return nread;
+ return (ssize_t)nread;
}
/*
CURLcode Curl_xfer_recv(struct Curl_easy *data,
char *buf, size_t blen,
- ssize_t *pnrcvd)
+ size_t *pnrcvd)
{
int sockindex;
*/
CURLcode Curl_xfer_recv(struct Curl_easy *data,
char *buf, size_t blen,
- ssize_t *pnrcvd);
+ size_t *pnrcvd);
CURLcode Curl_xfer_send_close(struct Curl_easy *data);
CURLcode Curl_xfer_send_shutdown(struct Curl_easy *data, bool *done);
#include "request.h"
#include "netrc.h"
-/* return the count of bytes sent, or -1 on error */
-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 */
-typedef ssize_t (Curl_recv)(struct Curl_easy *data, /* transfer */
- int sockindex, /* socketindex */
- char *buf, /* store data here */
- size_t len, /* max amount to read */
- CURLcode *err); /* error to return */
+/* On error return, the value of `pnwritten` has no meaning */
+typedef CURLcode (Curl_send)(struct Curl_easy *data, /* transfer */
+ int sockindex, /* socketindex */
+ const void *buf, /* data to write */
+ size_t len, /* amount to send */
+ bool eos, /* last chunk */
+ size_t *pnwritten); /* how much sent */
+
+/* On error return, the value of `pnread` has no meaning */
+typedef CURLcode (Curl_recv)(struct Curl_easy *data, /* transfer */
+ int sockindex, /* socketindex */
+ char *buf, /* store data here */
+ size_t len, /* max amount to read */
+ size_t *pnread); /* how much received */
#include "mime.h"
#include "imap.h"
(void)SendContext;
}
-static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- CURLcode *err)
+static CURLcode recv_closed_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ size_t *pnread)
{
struct cf_msh3_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
- ssize_t nread = -1;
- if(!stream) {
- *err = CURLE_RECV_ERROR;
- return -1;
- }
(void)cf;
+ *pnread = 0;
+ if(!stream)
+ return CURLE_RECV_ERROR;
+
if(stream->reset) {
failf(data, "HTTP/3 stream reset by server");
- *err = CURLE_PARTIAL_FILE;
- CURL_TRC_CF(data, cf, "cf_recv, was reset -> %d", *err);
- goto out;
+ CURL_TRC_CF(data, cf, "cf_recv, was reset");
+ return CURLE_PARTIAL_FILE;
}
else if(stream->error3) {
failf(data, "HTTP/3 stream was not closed cleanly: (error %zd)",
(ssize_t)stream->error3);
- *err = CURLE_HTTP3;
- CURL_TRC_CF(data, cf, "cf_recv, closed uncleanly -> %d", *err);
- goto out;
+ CURL_TRC_CF(data, cf, "cf_recv, closed uncleanly");
+ return CURLE_HTTP3;
}
else {
- CURL_TRC_CF(data, cf, "cf_recv, closed ok -> %d", *err);
+ CURL_TRC_CF(data, cf, "cf_recv, closed ok");
}
- *err = CURLE_OK;
- nread = 0;
-
-out:
- return nread;
+ return CURLE_OK;
}
static void set_quic_expire(struct Curl_cfilter *cf, struct Curl_easy *data)
}
}
-static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
- char *buf, size_t len, CURLcode *err)
+static CURLcode cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, size_t *pnread)
{
struct cf_msh3_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
ssize_t nread = -1;
struct cf_call_data save;
+ CURLcode result = CURLE_OK;
+ *pnread = 0;
CURL_TRC_CF(data, cf, "cf_recv(len=%zu), stream=%d", len, !!stream);
- if(!stream) {
- *err = CURLE_RECV_ERROR;
- return -1;
- }
+ if(!stream)
+ return CURLE_RECV_ERROR;
CF_DATA_SAVE(save, cf, data);
msh3_lock_acquire(&stream->recv_lock);
if(stream->recv_error) {
failf(data, "request aborted");
- *err = stream->recv_error;
+ result = stream->recv_error;
goto out;
}
- *err = CURLE_OK;
-
if(!Curl_bufq_is_empty(&stream->recvbuf)) {
nread = Curl_bufq_read(&stream->recvbuf,
- (unsigned char *)buf, len, err);
+ (unsigned char *)buf, len, &result);
CURL_TRC_CF(data, cf, "read recvbuf(len=%zu) -> %zd, %d",
- len, nread, *err);
+ len, nread, result);
if(nread < 0)
goto out;
+ *pnread = (size_t)nread;
if(stream->closed)
h3_drain_stream(cf, data);
}
else if(stream->closed) {
- nread = recv_closed_stream(cf, data, err);
+ result = recv_closed_stream(cf, data, pnread);
goto out;
}
else {
CURL_TRC_CF(data, cf, "req: nothing here, call again");
- *err = CURLE_AGAIN;
+ result = CURLE_AGAIN;
}
out:
msh3_lock_release(&stream->recv_lock);
set_quic_expire(cf, data);
CF_DATA_RESTORE(cf, save);
- return nread;
+ return result;
}
-static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
- const void *buf, size_t len, bool eos,
- CURLcode *err)
+static CURLcode cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, bool eos,
+ size_t *pnwritten)
{
struct cf_msh3_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
size_t nheader, i;
ssize_t nwritten = -1;
struct cf_call_data save;
+ CURLcode result = CURLE_OK;
+ *pnwritten = 0;
CF_DATA_SAVE(save, cf, data);
Curl_h1_req_parse_init(&h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
/* The first send on the request contains the headers and possibly some
data. Parse out the headers and create the request, then if there is
any data left over go ahead and send it too. */
- nwritten = Curl_h1_req_parse_read(&h1, buf, len, NULL, 0, err);
+ nwritten = Curl_h1_req_parse_read(&h1, buf, len, NULL, 0, &result);
if(nwritten < 0)
goto out;
DEBUGASSERT(h1.done);
DEBUGASSERT(h1.req);
+ *pnwritten = (size_t)nwritten;
- *err = Curl_http_req_to_h2(&h2_headers, h1.req, data);
- if(*err) {
- nwritten = -1;
+ result = Curl_http_req_to_h2(&h2_headers, h1.req, data);
+ if(result)
goto out;
- }
nheader = Curl_dynhds_count(&h2_headers);
nva = malloc(sizeof(MSH3_HEADER) * nheader);
if(!nva) {
- *err = CURLE_OUT_OF_MEMORY;
- nwritten = -1;
+ result = CURLE_OUT_OF_MEMORY;
goto out;
}
MSH3_REQUEST_FLAG_NONE);
if(!stream->req) {
failf(data, "request open failed");
- *err = CURLE_SEND_ERROR;
- goto out;
+ result = CURLE_SEND_ERROR;
}
- *err = CURLE_OK;
- nwritten = len;
+ result = CURLE_OK;
+ *pnwritten = len;
goto out;
}
else {
if(!MsH3RequestSend(stream->req, MSH3_REQUEST_FLAG_NONE, buf,
(uint32_t)len, stream)) {
- *err = CURLE_SEND_ERROR;
+ result = CURLE_SEND_ERROR;
goto out;
}
/* msh3/msquic will hold onto this memory until the send complete event.
How do we make sure curl does not free it until then? */
- *err = CURLE_OK;
- nwritten = len;
+ result = CURLE_OK;
+ *pnwritten = len;
}
out:
Curl_h1_req_parse_free(&h1);
Curl_dynhds_free(&h2_headers);
CF_DATA_RESTORE(cf, save);
- return nwritten;
+ return result;
}
static void cf_msh3_adjust_pollset(struct Curl_cfilter *cf,
}
/* incoming data frames on the h3 stream */
-static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
- char *buf, size_t blen, CURLcode *err)
+static CURLcode cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t blen, size_t *pnread)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
- ssize_t nread = -1;
struct cf_call_data save;
struct pkt_io_ctx pktx;
+ CURLcode result = CURLE_OK;
(void)ctx;
(void)buf;
DEBUGASSERT(ctx);
DEBUGASSERT(ctx->qconn);
DEBUGASSERT(ctx->h3conn);
- *err = CURLE_OK;
+ *pnread = 0;
/* handshake verification failed in callback, do not recv anything */
if(ctx->tls_vrfy_result)
pktx_init(&pktx, cf, data);
if(!stream || ctx->shutdown_started) {
- *err = CURLE_RECV_ERROR;
+ result = CURLE_RECV_ERROR;
goto out;
}
if(cf_progress_ingress(cf, data, &pktx)) {
- *err = CURLE_RECV_ERROR;
- nread = -1;
+ result = CURLE_RECV_ERROR;
goto out;
}
if(stream->xfer_result) {
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] xfer write failed", stream->id);
cf_ngtcp2_stream_close(cf, data, stream);
- *err = stream->xfer_result;
- nread = -1;
+ result = stream->xfer_result;
goto out;
}
else if(stream->closed) {
- nread = recv_closed_stream(cf, data, stream, err);
+ ssize_t nread = recv_closed_stream(cf, data, stream, &result);
+ if(nread > 0)
+ *pnread = (size_t)nread;
goto out;
}
- *err = CURLE_AGAIN;
- nread = -1;
+ result = CURLE_AGAIN;
out:
if(cf_progress_egress(cf, data, &pktx)) {
- *err = CURLE_SEND_ERROR;
- nread = -1;
+ result = CURLE_SEND_ERROR;
}
else {
- CURLcode result2 = check_and_set_expiry(cf, data, &pktx);
- if(result2) {
- *err = result2;
- nread = -1;
- }
+ CURLcode r2 = check_and_set_expiry(cf, data, &pktx);
+ if(r2)
+ result = r2;
}
- CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_recv(blen=%zu) -> %zd, %d",
- stream ? stream->id : -1, blen, nread, *err);
+ CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_recv(blen=%zu) -> %dm, %zu",
+ stream ? stream->id : -1, blen, result, *pnread);
CF_DATA_RESTORE(cf, save);
- return nread;
+ return result;
}
static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
field list. */
#define AUTHORITY_DST_IDX 3
-static ssize_t h3_stream_open(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const void *buf, size_t len,
- CURLcode *err)
+static CURLcode h3_stream_open(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const void *buf, size_t len,
+ size_t *pnwritten)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = NULL;
ssize_t nwritten = -1;
nghttp3_data_reader reader;
nghttp3_data_reader *preader = NULL;
+ CURLcode result;
+ *pnwritten = 0;
Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
- *err = h3_data_setup(cf, data);
- if(*err)
+ result = h3_data_setup(cf, data);
+ if(result)
goto out;
stream = H3_STREAM_CTX(ctx, data);
DEBUGASSERT(stream);
if(!stream) {
- *err = CURLE_FAILED_INIT;
+ result = CURLE_FAILED_INIT;
goto out;
}
- nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
+ nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, &result);
if(nwritten < 0)
goto out;
+ *pnwritten = (size_t)nwritten;
+
if(!stream->h1.done) {
/* need more data */
goto out;
}
DEBUGASSERT(stream->h1.req);
- *err = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
- if(*err) {
- nwritten = -1;
+ result = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
+ if(result)
goto out;
- }
+
/* no longer needed */
Curl_h1_req_parse_free(&stream->h1);
nheader = Curl_dynhds_count(&h2_headers);
nva = malloc(sizeof(nghttp3_nv) * nheader);
if(!nva) {
- *err = CURLE_OUT_OF_MEMORY;
- nwritten = -1;
+ result = CURLE_OUT_OF_MEMORY;
goto out;
}
rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &sid, data);
if(rc) {
failf(data, "can get bidi streams");
- *err = CURLE_SEND_ERROR;
- nwritten = -1;
+ result = CURLE_SEND_ERROR;
goto out;
}
stream->id = (curl_int64_t)sid;
"%d (%s)", stream->id, rc, nghttp3_strerror(rc));
break;
}
- *err = CURLE_SEND_ERROR;
- nwritten = -1;
+ result = CURLE_SEND_ERROR;
goto out;
}
out:
free(nva);
Curl_dynhds_free(&h2_headers);
- return nwritten;
+ return result;
}
-static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
- const void *buf, size_t len, bool eos,
- CURLcode *err)
+static CURLcode cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, bool eos,
+ size_t *pnwritten)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
- ssize_t sent = -1;
struct cf_call_data save;
struct pkt_io_ctx pktx;
- CURLcode result;
+ CURLcode result = CURLE_OK, r2;
CF_DATA_SAVE(save, cf, data);
DEBUGASSERT(cf->connected);
DEBUGASSERT(ctx->qconn);
DEBUGASSERT(ctx->h3conn);
pktx_init(&pktx, cf, data);
- *err = CURLE_OK;
+ *pnwritten = 0;
/* handshake verification failed in callback, do not send anything */
if(ctx->tls_vrfy_result)
return ctx->tls_vrfy_result;
(void)eos; /* use for stream EOF and block handling */
- result = cf_progress_ingress(cf, data, &pktx);
- if(result) {
- *err = result;
+ r2 = cf_progress_ingress(cf, data, &pktx);
+ if(r2) {
+ result = r2;
}
if(!stream || stream->id < 0) {
if(ctx->shutdown_started) {
CURL_TRC_CF(data, cf, "cannot open stream on closed connection");
- *err = CURLE_SEND_ERROR;
+ result = CURLE_SEND_ERROR;
goto out;
}
- sent = h3_stream_open(cf, data, buf, len, err);
- if(sent < 0) {
- CURL_TRC_CF(data, cf, "failed to open stream -> %d", *err);
+ result = h3_stream_open(cf, data, buf, len, pnwritten);
+ if(result) {
+ CURL_TRC_CF(data, cf, "failed to open stream -> %d", result);
goto out;
}
stream = H3_STREAM_CTX(ctx, data);
else if(stream->xfer_result) {
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] xfer write failed", stream->id);
cf_ngtcp2_stream_close(cf, data, stream);
- *err = stream->xfer_result;
+ result = stream->xfer_result;
goto out;
}
else if(stream->closed) {
* error situation. */
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] discarding data"
"on closed stream with response", stream->id);
- *err = CURLE_OK;
- sent = (ssize_t)len;
+ result = CURLE_OK;
+ *pnwritten = len;
goto out;
}
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] send_body(len=%zu) "
"-> stream closed", stream->id, len);
- *err = CURLE_HTTP3;
- sent = -1;
+ result = CURLE_HTTP3;
goto out;
}
else if(ctx->shutdown_started) {
CURL_TRC_CF(data, cf, "cannot send on closed connection");
- *err = CURLE_SEND_ERROR;
+ result = CURLE_SEND_ERROR;
goto out;
}
else {
- sent = Curl_bufq_write(&stream->sendbuf, buf, len, err);
+ ssize_t sent;
+ sent = Curl_bufq_write(&stream->sendbuf, buf, len, &result);
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_send, add to "
"sendbuf(len=%zu) -> %zd, %d",
- stream->id, len, sent, *err);
- if(sent < 0) {
+ stream->id, len, sent, result);
+ if(sent < 0)
goto out;
- }
-
+ *pnwritten = (size_t)sent;
(void)nghttp3_conn_resume_stream(ctx->h3conn, stream->id);
}
- if(sent > 0 && !ctx->tls_handshake_complete && ctx->use_earlydata)
- ctx->earlydata_skip += sent;
+ if(*pnwritten > 0 && !ctx->tls_handshake_complete && ctx->use_earlydata)
+ ctx->earlydata_skip += *pnwritten;
- result = cf_progress_egress(cf, data, &pktx);
- if(result) {
- *err = result;
- sent = -1;
- }
+ r2 = cf_progress_egress(cf, data, &pktx);
+ if(r2)
+ result = r2;
out:
- result = check_and_set_expiry(cf, data, &pktx);
- if(result) {
- *err = result;
- sent = -1;
- }
- CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_send(len=%zu) -> %zd, %d",
- stream ? stream->id : -1, len, sent, *err);
+ r2 = check_and_set_expiry(cf, data, &pktx);
+ if(r2)
+ result = r2;
+
+ CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_send(len=%zu) -> %d, %zu",
+ stream ? stream->id : -1, len, result, *pnwritten);
CF_DATA_RESTORE(cf, save);
- return sent;
+ return result;
}
static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
return nwritten;
}
-static ssize_t cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data,
- const void *buf, size_t len, bool eos,
- CURLcode *err)
+static CURLcode cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, bool eos,
+ size_t *pnwritten)
{
struct cf_osslq_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
struct cf_call_data save;
ssize_t nwritten;
- CURLcode result;
+ CURLcode result = CURLE_OK, r2;
(void)eos; /* use to end stream */
CF_DATA_SAVE(save, cf, data);
DEBUGASSERT(cf->connected);
DEBUGASSERT(ctx->tls.ossl.ssl);
DEBUGASSERT(ctx->h3.conn);
- *err = CURLE_OK;
+ *pnwritten = 0;
result = cf_progress_ingress(cf, data);
- if(result) {
- *err = result;
- nwritten = -1;
+ if(result)
goto out;
- }
result = cf_progress_egress(cf, data);
- if(result) {
- *err = result;
- nwritten = -1;
+ if(result)
goto out;
- }
if(!stream || stream->s.id < 0) {
- nwritten = h3_stream_open(cf, data, buf, len, err);
+ nwritten = h3_stream_open(cf, data, buf, len, &result);
if(nwritten < 0) {
- CURL_TRC_CF(data, cf, "failed to open stream -> %d", *err);
+ CURL_TRC_CF(data, cf, "failed to open stream -> %d", result);
goto out;
}
stream = H3_STREAM_CTX(ctx, data);
+ *pnwritten = (size_t)nwritten;
}
else if(stream->closed) {
if(stream->resp_hds_complete) {
* error situation. */
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] discarding data"
"on closed stream with response", stream->s.id);
- *err = CURLE_OK;
- nwritten = (ssize_t)len;
+ result = CURLE_OK;
+ *pnwritten = len;
goto out;
}
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] send_body(len=%zu) "
"-> stream closed", stream->s.id, len);
- *err = CURLE_HTTP3;
- nwritten = -1;
+ result = CURLE_HTTP3;
goto out;
}
else {
- nwritten = Curl_bufq_write(&stream->sendbuf, buf, len, err);
+ nwritten = Curl_bufq_write(&stream->sendbuf, buf, len, &result);
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_send, add to "
"sendbuf(len=%zu) -> %zd, %d",
- stream->s.id, len, nwritten, *err);
+ stream->s.id, len, nwritten, result);
if(nwritten < 0) {
goto out;
}
-
+ *pnwritten = (size_t)nwritten;
(void)nghttp3_conn_resume_stream(ctx->h3.conn, stream->s.id);
}
- result = cf_progress_egress(cf, data);
- if(result) {
- *err = result;
- nwritten = -1;
- }
+ r2 = cf_progress_egress(cf, data);
+ if(r2)
+ result = r2;
out:
- result = check_and_set_expiry(cf, data);
- CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_send(len=%zu) -> %zd, %d",
- stream ? stream->s.id : -1, len, nwritten, *err);
+ r2 = check_and_set_expiry(cf, data);
+ if(r2)
+ result = r2;
+ CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_send(len=%zu) -> %d, %zu",
+ stream ? stream->s.id : -1, len, result, *pnwritten);
CF_DATA_RESTORE(cf, save);
- return nwritten;
+ return result;
}
-static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct h3_stream_ctx *stream,
- CURLcode *err)
+static CURLcode recv_closed_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct h3_stream_ctx *stream,
+ size_t *pnread)
{
- ssize_t nread = -1;
-
(void)cf;
+ *pnread = 0;
if(stream->reset) {
failf(data,
"HTTP/3 stream %" FMT_PRId64 " reset by server",
stream->s.id);
- *err = data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP3;
- goto out;
+ return data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP3;
}
else if(!stream->resp_hds_complete) {
failf(data,
" was closed cleanly, but before getting"
" all response header fields, treated as error",
stream->s.id);
- *err = CURLE_HTTP3;
- goto out;
+ return CURLE_HTTP3;
}
- *err = CURLE_OK;
- nread = 0;
-
-out:
- return nread;
+ return CURLE_OK;
}
-static ssize_t cf_osslq_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
- char *buf, size_t len, CURLcode *err)
+static CURLcode cf_osslq_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, size_t *pnread)
{
struct cf_osslq_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
ssize_t nread = -1;
struct cf_call_data save;
- CURLcode result;
+ CURLcode result = CURLE_OK, r2;
(void)ctx;
CF_DATA_SAVE(save, cf, data);
DEBUGASSERT(ctx);
DEBUGASSERT(ctx->tls.ossl.ssl);
DEBUGASSERT(ctx->h3.conn);
- *err = CURLE_OK;
+ *pnread = 0;
if(!stream) {
- *err = CURLE_RECV_ERROR;
+ result = CURLE_RECV_ERROR;
goto out;
}
if(!Curl_bufq_is_empty(&stream->recvbuf)) {
nread = Curl_bufq_read(&stream->recvbuf,
- (unsigned char *)buf, len, err);
+ (unsigned char *)buf, len, &result);
if(nread < 0) {
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] read recvbuf(len=%zu) "
- "-> %zd, %d", stream->s.id, len, nread, *err);
+ "-> %zd, %d", stream->s.id, len, nread, result);
goto out;
}
+ *pnread = (size_t)nread;
}
- result = cf_progress_ingress(cf, data);
- if(result) {
- *err = result;
- nread = -1;
+ r2 = cf_progress_ingress(cf, data);
+ if(r2) {
+ result = r2;
goto out;
}
/* recvbuf had nothing before, maybe after progressing ingress? */
- if(nread < 0 && !Curl_bufq_is_empty(&stream->recvbuf)) {
+ if(!*pnread && !Curl_bufq_is_empty(&stream->recvbuf)) {
nread = Curl_bufq_read(&stream->recvbuf,
- (unsigned char *)buf, len, err);
+ (unsigned char *)buf, len, &result);
if(nread < 0) {
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] read recvbuf(len=%zu) "
- "-> %zd, %d", stream->s.id, len, nread, *err);
+ "-> %zd, %d", stream->s.id, len, nread, result);
goto out;
}
+ *pnread = (size_t)nread;
}
- if(nread > 0) {
+ if(*pnread) {
h3_drain_stream(cf, data);
}
else {
if(stream->closed) {
- nread = recv_closed_stream(cf, data, stream, err);
+ result = recv_closed_stream(cf, data, stream, pnread);
goto out;
}
- *err = CURLE_AGAIN;
- nread = -1;
+ result = CURLE_AGAIN;
}
out:
if(cf_progress_egress(cf, data)) {
- *err = CURLE_SEND_ERROR;
- nread = -1;
+ result = CURLE_SEND_ERROR;
}
else {
- CURLcode result2 = check_and_set_expiry(cf, data);
- if(result2) {
- *err = result2;
- nread = -1;
- }
+ r2 = check_and_set_expiry(cf, data);
+ if(r2)
+ result = r2;
}
- CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_recv(len=%zu) -> %zd, %d",
- stream ? stream->s.id : -1, len, nread, *err);
+ CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_recv(len=%zu) -> %d, %zu",
+ stream ? stream->s.id : -1, len, result, *pnread);
CF_DATA_RESTORE(cf, save);
- return nread;
+ return result;
}
/*
return nread;
}
-static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
- char *buf, size_t len, CURLcode *err)
+static CURLcode cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, size_t *pnread)
{
struct cf_quiche_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
ssize_t nread = -1;
- CURLcode result;
+ CURLcode result = CURLE_OK, r2;
+ *pnread = 0;
vquic_ctx_update_time(&ctx->q);
- if(!stream) {
- *err = CURLE_RECV_ERROR;
- return -1;
- }
+ if(!stream)
+ return CURLE_RECV_ERROR;
+
if(!Curl_bufq_is_empty(&stream->recvbuf)) {
nread = Curl_bufq_read(&stream->recvbuf,
- (unsigned char *)buf, len, err);
+ (unsigned char *)buf, len, &result);
CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] read recvbuf(len=%zu) "
- "-> %zd, %d", stream->id, len, nread, *err);
+ "-> %zd, %d", stream->id, len, nread, result);
if(nread < 0)
goto out;
+ *pnread = (size_t)nread;
}
if(cf_process_ingress(cf, data)) {
CURL_TRC_CF(data, cf, "cf_recv, error on ingress");
- *err = CURLE_RECV_ERROR;
- nread = -1;
+ result = CURLE_RECV_ERROR;
goto out;
}
/* recvbuf had nothing before, maybe after progressing ingress? */
if(nread < 0 && !Curl_bufq_is_empty(&stream->recvbuf)) {
nread = Curl_bufq_read(&stream->recvbuf,
- (unsigned char *)buf, len, err);
+ (unsigned char *)buf, len, &result);
CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] read recvbuf(len=%zu) "
- "-> %zd, %d", stream->id, len, nread, *err);
+ "-> %zd, %d", stream->id, len, nread, result);
if(nread < 0)
goto out;
+ *pnread = (size_t)nread;
}
- if(nread > 0) {
+ if(*pnread) {
if(stream->closed)
h3_drain_stream(cf, data);
}
else {
if(stream->closed) {
- nread = recv_closed_stream(cf, data, err);
+ nread = recv_closed_stream(cf, data, &result);
goto out;
}
else if(quiche_conn_is_draining(ctx->qconn)) {
failf(data, "QUIC connection is draining");
- *err = CURLE_HTTP3;
- nread = -1;
+ result = CURLE_HTTP3;
goto out;
}
- *err = CURLE_AGAIN;
- nread = -1;
+ result = CURLE_AGAIN;
}
out:
- result = cf_flush_egress(cf, data);
- if(result) {
+ r2 = cf_flush_egress(cf, data);
+ if(r2) {
CURL_TRC_CF(data, cf, "cf_recv, flush egress failed");
- *err = result;
- nread = -1;
+ result = r2;
}
- if(nread > 0)
+ if(*pnread > 0)
ctx->data_recvd += nread;
CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] cf_recv(total=%"
- FMT_OFF_T ") -> %zd, %d",
- stream->id, ctx->data_recvd, nread, *err);
- return nread;
+ FMT_OFF_T ") -> %d, %zu",
+ stream->id, ctx->data_recvd, result, *pnread);
+ return result;
}
-static ssize_t cf_quiche_send_body(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct h3_stream_ctx *stream,
- const void *buf, size_t len, bool eos,
- CURLcode *err)
+static CURLcode cf_quiche_send_body(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct h3_stream_ctx *stream,
+ const void *buf, size_t len, bool eos,
+ size_t *pnwritten)
{
struct cf_quiche_ctx *ctx = cf->ctx;
ssize_t nwritten;
+ *pnwritten = 0;
nwritten = quiche_h3_send_body(ctx->h3c, ctx->qconn, stream->id,
(uint8_t *)CURL_UNCONST(buf), len, eos);
if(nwritten == QUICHE_H3_ERR_DONE || (nwritten == 0 && len > 0)) {
"-> window exhausted", stream->id, len);
stream->quic_flow_blocked = TRUE;
}
- *err = CURLE_AGAIN;
- return -1;
+ return CURLE_AGAIN;
}
else if(nwritten == QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE) {
CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] send_body(len=%zu) "
"-> invalid stream state", stream->id, len);
- *err = CURLE_HTTP3;
- return -1;
+ return CURLE_HTTP3;
}
else if(nwritten == QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE) {
CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] send_body(len=%zu) "
"-> exceeds size", stream->id, len);
- *err = CURLE_SEND_ERROR;
- return -1;
+ return CURLE_SEND_ERROR;
}
else if(nwritten < 0) {
CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] send_body(len=%zu) "
"-> quiche err %zd", stream->id, len, nwritten);
- *err = CURLE_SEND_ERROR;
- return -1;
+ return CURLE_SEND_ERROR;
}
else {
if(eos && (len == (size_t)nwritten))
CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] send body(len=%zu, "
"eos=%d) -> %zd",
stream->id, len, stream->send_closed, nwritten);
- *err = CURLE_OK;
- return nwritten;
+ *pnwritten = (size_t)nwritten;
+ return CURLE_OK;
}
}
field list. */
#define AUTHORITY_DST_IDX 3
-static ssize_t h3_open_stream(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const char *buf, size_t len, bool eos,
- CURLcode *err)
+static CURLcode h3_open_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *buf, size_t blen, bool eos,
+ size_t *pnwritten)
{
struct cf_quiche_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
curl_int64_t stream3_id;
struct dynhds h2_headers;
quiche_h3_header *nva = NULL;
+ CURLcode result = CURLE_OK;
ssize_t nwritten;
+ *pnwritten = 0;
if(!stream) {
- *err = h3_data_setup(cf, data);
- if(*err) {
- return -1;
- }
+ result = h3_data_setup(cf, data);
+ if(result)
+ return result;
stream = H3_STREAM_CTX(ctx, data);
DEBUGASSERT(stream);
}
Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
DEBUGASSERT(stream);
- nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
+ nwritten = Curl_h1_req_parse_read(&stream->h1, buf, blen, NULL, 0, &result);
if(nwritten < 0)
goto out;
if(!stream->h1.done) {
}
DEBUGASSERT(stream->h1.req);
- *err = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
- if(*err) {
- nwritten = -1;
+ result = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
+ if(result)
goto out;
- }
+
/* no longer needed */
Curl_h1_req_parse_free(&stream->h1);
nheader = Curl_dynhds_count(&h2_headers);
nva = malloc(sizeof(quiche_h3_header) * nheader);
if(!nva) {
- *err = CURLE_OUT_OF_MEMORY;
- nwritten = -1;
+ result = CURLE_OUT_OF_MEMORY;
goto out;
}
nva[i].value_len = e->valuelen;
}
- if(eos && ((size_t)nwritten == len))
+ *pnwritten = (size_t)nwritten;
+ buf += *pnwritten;
+ blen -= *pnwritten;
+
+ if(eos && !blen)
stream->send_closed = TRUE;
stream3_id = quiche_h3_send_request(ctx->h3c, ctx->qconn, nva, nheader,
* exhausted. Which happens frequently and intermittent. */
CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] blocked", stream->id);
stream->quic_flow_blocked = TRUE;
- *err = CURLE_AGAIN;
- nwritten = -1;
+ result = CURLE_AGAIN;
goto out;
}
else {
CURL_TRC_CF(data, cf, "send_request(%s) -> %" FMT_PRIu64,
data->state.url, stream3_id);
}
- *err = CURLE_SEND_ERROR;
- nwritten = -1;
+ result = CURLE_SEND_ERROR;
goto out;
}
DEBUGASSERT(!stream->opened);
- *err = CURLE_OK;
stream->id = stream3_id;
stream->opened = TRUE;
stream->closed = FALSE;
}
}
- 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;
+ if(blen) { /* after the headers, there was request BODY data */
+ size_t bwritten;
+ CURLcode r2 = CURLE_OK;
- 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;
+ r2 = cf_quiche_send_body(cf, data, stream, buf, blen, eos, &bwritten);
+ if(r2 && (CURLE_AGAIN != r2)) { /* real error, fail */
+ result = r2;
}
else if(bwritten > 0) {
- nwritten += bwritten;
+ *pnwritten += (size_t)bwritten;
}
}
out:
free(nva);
Curl_dynhds_free(&h2_headers);
- return nwritten;
+ return result;
}
-static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
- const void *buf, size_t len, bool eos,
- CURLcode *err)
+static CURLcode cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, bool eos,
+ size_t *pnwritten)
{
struct cf_quiche_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
- CURLcode result;
- ssize_t nwritten;
+ CURLcode result, r2;
+ *pnwritten = 0;
vquic_ctx_update_time(&ctx->q);
- *err = cf_process_ingress(cf, data);
- if(*err) {
- nwritten = -1;
+ result = cf_process_ingress(cf, data);
+ if(result)
goto out;
- }
if(!stream || !stream->opened) {
- nwritten = h3_open_stream(cf, data, buf, len, eos, err);
- if(nwritten < 0)
+ result = h3_open_stream(cf, data, buf, len, eos, pnwritten);
+ if(result)
goto out;
stream = H3_STREAM_CTX(ctx, data);
}
* it would see the response and stop/discard sending on its own- */
CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] discarding data"
"on closed stream with response", stream->id);
- *err = CURLE_OK;
- nwritten = (ssize_t)len;
+ result = CURLE_OK;
+ *pnwritten = len;
goto out;
}
CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] send_body(len=%zu) "
"-> stream closed", stream->id, len);
- *err = CURLE_HTTP3;
- nwritten = -1;
+ result = CURLE_HTTP3;
goto out;
}
else {
- nwritten = cf_quiche_send_body(cf, data, stream, buf, len, eos, err);
+ result = cf_quiche_send_body(cf, data, stream, buf, len, eos, pnwritten);
}
out:
- result = cf_flush_egress(cf, data);
- if(result) {
- *err = result;
- nwritten = -1;
- }
- CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] cf_send(len=%zu) -> %zd, %d",
- stream ? stream->id : (curl_uint64_t)~0, len, nwritten, *err);
- return nwritten;
+ r2 = cf_flush_egress(cf, data);
+ if(r2)
+ result = r2;
+
+ CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] cf_send(len=%zu) -> %d, %zu",
+ stream ? stream->id : (curl_uint64_t)~0, len,
+ result, *pnwritten);
+ return result;
}
static bool stream_is_writeable(struct Curl_cfilter *cf,
struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
if(stream && !stream->send_closed) {
unsigned char body[1];
- ssize_t sent;
+ size_t sent;
stream->send_closed = TRUE;
body[0] = 'X';
- sent = cf_quiche_send(cf, data, body, 0, TRUE, &result);
- CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] DONE_SEND -> %zd, %d",
- stream->id, sent, result);
+ result = cf_quiche_send(cf, data, body, 0, TRUE, &sent);
+ CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] DONE_SEND -> %d, %zu",
+ stream->id, result, sent);
}
break;
}
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);
* 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);
+ 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);
* 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;
}
/*
}
/* 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
*/
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);
}
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
}
* 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:
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;
}
}
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];
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,
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);
+ 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;
}
/*
}
/* 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);
+ 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)
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);
(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;
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;
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;
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)
struct gtls_ssl_backend_data *backend =
(struct gtls_ssl_backend_data *)connssl->backend;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
- ssize_t nwritten;
+ size_t nwritten;
CURLcode result;
DEBUGASSERT(data);
- 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);
+ result = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &nwritten);
+ CURL_TRC_CF(data, cf, "gtls_push(len=%zu) -> %d, %zu",
+ blen, result, nwritten);
backend->gtls.io_result = result;
- if(nwritten < 0) {
+ if(result) {
/* !checksrc! disable ERRNOVAR 1 */
gnutls_transport_set_errno(backend->gtls.session,
(CURLE_AGAIN == result) ? EAGAIN : EINVAL);
- nwritten = -1;
+ return -1;
}
- return nwritten;
+ return (ssize_t)nwritten;
}
static ssize_t gtls_pull(void *s, void *buf, size_t blen)
struct gtls_ssl_backend_data *backend =
(struct gtls_ssl_backend_data *)connssl->backend;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
- ssize_t nread;
+ size_t nread;
CURLcode result;
DEBUGASSERT(data);
}
}
- nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
- CURL_TRC_CF(data, cf, "glts_pull(len=%zu) -> %zd, err=%d",
- blen, nread, result);
+ result = Curl_conn_cf_recv(cf->next, data, buf, blen, &nread);
+ CURL_TRC_CF(data, cf, "glts_pull(len=%zu) -> %d, %zd",
+ blen, result, nread);
backend->gtls.io_result = result;
- if(nread < 0) {
+ if(result) {
/* !checksrc! disable ERRNOVAR 1 */
gnutls_transport_set_errno(backend->gtls.session,
(CURLE_AGAIN == result) ? EAGAIN : EINVAL);
- nread = -1;
+ return -1;
}
else if(nread == 0)
connssl->peer_closed = TRUE;
- return nread;
+ return (ssize_t)nread;
}
/* gtls_init()
{
struct Curl_cfilter *cf = bio;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
- ssize_t nwritten;
+ size_t nwritten;
CURLcode result;
DEBUGASSERT(data);
if(!data)
return 0;
- nwritten = Curl_conn_cf_send(cf->next, data, (const 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) {
- nwritten = MBEDTLS_ERR_SSL_WANT_WRITE;
- }
- return (int)nwritten;
+ result = Curl_conn_cf_send(cf->next, data, (const char *)buf, blen, FALSE,
+ &nwritten);
+ CURL_TRC_CF(data, cf, "mbedtls_bio_cf_out_write(len=%zu) -> %d, %zu",
+ blen, result, nwritten);
+ if(CURLE_AGAIN == result)
+ return MBEDTLS_ERR_SSL_WANT_WRITE;
+ return result ? -1 : (int)nwritten;
}
static int mbedtls_bio_cf_read(void *bio, unsigned char *buf, size_t blen)
{
struct Curl_cfilter *cf = bio;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
- ssize_t nread;
+ size_t nread;
CURLcode result;
DEBUGASSERT(data);
if(!buf)
return 0;
- nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &result);
- CURL_TRC_CF(data, cf, "mbedtls_bio_cf_in_read(len=%zu) -> %zd, err=%d",
- blen, nread, result);
- if(nread < 0 && CURLE_AGAIN == result) {
- nread = MBEDTLS_ERR_SSL_WANT_READ;
- }
- return (int)nread;
+ result = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &nread);
+ CURL_TRC_CF(data, cf, "mbedtls_bio_cf_in_read(len=%zu) -> %d, %zu",
+ blen, result, nread);
+ if(CURLE_AGAIN == result)
+ return MBEDTLS_ERR_SSL_WANT_READ;
+ return result ? -1 : (int)nread;
}
/*
struct ssl_connect_data *connssl = cf->ctx;
struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
- ssize_t nwritten;
- CURLcode result = CURLE_SEND_ERROR;
+ size_t nwritten;
+ CURLcode result;
DEBUGASSERT(data);
if(blen < 0)
return 0;
- 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);
+ result = Curl_conn_cf_send(cf->next, data, buf, (size_t)blen, FALSE,
+ &nwritten);
+ CURL_TRC_CF(data, cf, "ossl_bio_cf_out_write(len=%d) -> %d, %zu",
+ blen, result, nwritten);
BIO_clear_retry_flags(bio);
octx->io_result = result;
- if(nwritten < 0) {
+ if(result) {
if(CURLE_AGAIN == result)
BIO_set_retry_write(bio);
+ return -1;
}
return (int)nwritten;
}
struct ssl_connect_data *connssl = cf->ctx;
struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
- ssize_t nread;
- CURLcode result = CURLE_RECV_ERROR;
+ size_t nread;
+ CURLcode result, r2;
DEBUGASSERT(data);
/* OpenSSL catches this case, so should we. */
if(blen < 0)
return 0;
- nread = Curl_conn_cf_recv(cf->next, data, buf, (size_t)blen, &result);
- CURL_TRC_CF(data, cf, "ossl_bio_cf_in_read(len=%d) -> %d, err=%d",
- blen, (int)nread, result);
+ result = Curl_conn_cf_recv(cf->next, data, buf, (size_t)blen, &nread);
+ CURL_TRC_CF(data, cf, "ossl_bio_cf_in_read(len=%d) -> %d, %zu",
+ blen, result, nread);
BIO_clear_retry_flags(bio);
octx->io_result = result;
- if(nread < 0) {
+ if(result) {
if(CURLE_AGAIN == result)
BIO_set_retry_read(bio);
}
/* Before returning server replies to the SSL instance, we need
* to have setup the x509 store or verification will fail. */
if(!octx->x509_store_setup) {
- result = Curl_ssl_setup_x509_store(cf, data, octx->ssl_ctx);
- if(result) {
- octx->io_result = result;
+ r2 = Curl_ssl_setup_x509_store(cf, data, octx->ssl_ctx);
+ if(r2) {
+ octx->io_result = r2;
return -1;
}
octx->x509_store_setup = TRUE;
}
-
- return (int)nread;
+ return result ? -1 : (int)nread;
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L
struct ssl_connect_data *const connssl = io_ctx->cf->ctx;
CURLcode result;
int ret = 0;
- ssize_t nread = Curl_conn_cf_recv(io_ctx->cf->next, io_ctx->data,
- (char *)buf, len, &result);
- if(nread < 0) {
+ size_t nread;
+
+ result = Curl_conn_cf_recv(io_ctx->cf->next, io_ctx->data,
+ (char *)buf, len, &nread);
+ if(result) {
nread = 0;
/* !checksrc! disable ERRNOVAR 4 */
if(CURLE_AGAIN == result)
else if(nread == 0)
connssl->peer_closed = TRUE;
*out_n = (uintptr_t)nread;
- CURL_TRC_CF(io_ctx->data, io_ctx->cf, "cf->next recv(len=%zu) -> %zd, %d",
- len, nread, result);
+ CURL_TRC_CF(io_ctx->data, io_ctx->cf, "cf->next recv(len=%zu) -> %d, %zu",
+ len, result, nread);
return ret;
}
const struct io_ctx *io_ctx = userdata;
CURLcode result;
int ret = 0;
- ssize_t nwritten = Curl_conn_cf_send(io_ctx->cf->next, io_ctx->data,
- (const char *)buf, len, FALSE,
- &result);
- if(nwritten < 0) {
+ size_t nwritten;
+
+ result = Curl_conn_cf_send(io_ctx->cf->next, io_ctx->data,
+ (const char *)buf, len, FALSE, &nwritten);
+ if(result) {
nwritten = 0;
if(CURLE_AGAIN == result)
ret = EAGAIN;
ret = EINVAL;
}
*out_n = (uintptr_t)nwritten;
- CURL_TRC_CF(io_ctx->data, io_ctx->cf, "cf->next send(len=%zu) -> %zd, %d",
- len, nwritten, result);
+ CURL_TRC_CF(io_ctx->data, io_ctx->cf, "cf->next send(len=%zu) -> %d, %zu",
+ len, result, nwritten);
return ret;
}
static CURLcode
schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- ssize_t written = -1;
+ size_t written = 0;
struct ssl_connect_data *connssl = cf->ctx;
struct schannel_ssl_backend_data *backend =
(struct schannel_ssl_backend_data *)connssl->backend;
"sending %lu bytes.", outbuf.cbBuffer));
/* send initial handshake data which is now stored in output buffer */
- written = Curl_conn_cf_send(cf->next, data,
- outbuf.pvBuffer, outbuf.cbBuffer, FALSE,
- &result);
+ result = Curl_conn_cf_send(cf->next, data,
+ outbuf.pvBuffer, outbuf.cbBuffer, FALSE,
+ &written);
Curl_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
- if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) {
+ if((result != CURLE_OK) || (outbuf.cbBuffer != written)) {
failf(data, "schannel: failed to send initial handshake data: "
- "sent %zd of %lu bytes", written, outbuf.cbBuffer);
+ "sent %zu of %lu bytes", written, outbuf.cbBuffer);
return CURLE_SSL_CONNECT_ERROR;
}
DEBUGF(infof(data, "schannel: sent initial handshake data: "
- "sent %zd bytes", written));
+ "sent %zu bytes", written));
backend->recv_unrecoverable_err = CURLE_OK;
backend->recv_sspi_close_notify = FALSE;
(struct schannel_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
int i;
- ssize_t nread = -1, written = -1;
+ size_t nread = 0, written = 0;
unsigned char *reallocated_buffer;
SecBuffer outbuf[3];
SecBufferDesc outbuf_desc;
for(;;) {
if(doread) {
/* read encrypted handshake data from socket */
- nread = Curl_conn_cf_recv(cf->next, data,
- (char *) (backend->encdata_buffer +
- backend->encdata_offset),
- backend->encdata_length -
- backend->encdata_offset,
- &result);
+ result = Curl_conn_cf_recv(cf->next, data,
+ (char *) (backend->encdata_buffer +
+ backend->encdata_offset),
+ backend->encdata_length -
+ backend->encdata_offset,
+ &nread);
if(result == CURLE_AGAIN) {
connssl->io_need = CURL_SSL_IO_NEED_RECV;
DEBUGF(infof(data, "schannel: failed to receive handshake, "
/* increase encrypted data buffer offset */
backend->encdata_offset += nread;
backend->encdata_is_incomplete = FALSE;
- SCH_DEV(infof(data, "schannel: encrypted data got %zd", nread));
+ SCH_DEV(infof(data, "schannel: encrypted data got %zu", nread));
}
SCH_DEV(infof(data,
"sending %lu bytes.", outbuf[i].cbBuffer));
/* send handshake token to server */
- written = Curl_conn_cf_send(cf->next, data,
- outbuf[i].pvBuffer, outbuf[i].cbBuffer,
- FALSE, &result);
+ result = Curl_conn_cf_send(cf->next, data,
+ outbuf[i].pvBuffer, outbuf[i].cbBuffer,
+ FALSE, &written);
if((result != CURLE_OK) ||
- (outbuf[i].cbBuffer != (size_t) written)) {
+ (outbuf[i].cbBuffer != written)) {
failf(data, "schannel: failed to send next handshake data: "
- "sent %zd of %lu bytes", written, outbuf[i].cbBuffer);
+ "sent %zu of %lu bytes", written, outbuf[i].cbBuffer);
return CURLE_SSL_CONNECT_ERROR;
}
}
/* send entire message or fail */
while(len > (size_t)written) {
- ssize_t this_write = 0;
+ size_t this_write = 0;
int what;
timediff_t timeout_ms = Curl_timeleft(data, NULL, FALSE);
if(timeout_ms < 0) {
}
/* socket is writable */
- this_write = Curl_conn_cf_send(cf->next, data,
- ptr + written, len - written,
- FALSE, &result);
+ result = Curl_conn_cf_send(cf->next, data,
+ ptr + written, len - written,
+ FALSE, &this_write);
if(result == CURLE_AGAIN)
continue;
else if(result != CURLE_OK) {
break;
}
- written += this_write;
+ written += (ssize_t)this_write;
}
}
else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) {
char *buf, size_t len, CURLcode *err)
{
size_t size = 0;
- ssize_t nread = -1;
+ size_t nread = 0;
struct ssl_connect_data *connssl = cf->ctx;
unsigned char *reallocated_buffer;
size_t reallocated_length;
backend->encdata_offset, backend->encdata_length));
/* read encrypted data from socket */
- nread = Curl_conn_cf_recv(cf->next, data,
- (char *)(backend->encdata_buffer +
- backend->encdata_offset),
- size, err);
+ *err = Curl_conn_cf_recv(cf->next, data,
+ (char *)(backend->encdata_buffer +
+ backend->encdata_offset),
+ size, &nread);
if(*err) {
if(*err == CURLE_AGAIN)
SCH_DEV(infof(data, "schannel: recv returned CURLE_AGAIN"));
backend->recv_connection_closed = TRUE;
DEBUGF(infof(data, "schannel: server closed the connection"));
}
- else if(nread > 0) {
- backend->encdata_offset += (size_t)nread;
+ else {
+ backend->encdata_offset += nread;
backend->encdata_is_incomplete = FALSE;
- SCH_DEV(infof(data, "schannel: encrypted data got %zd", nread));
+ SCH_DEV(infof(data, "schannel: encrypted data got %zu", nread));
}
}
if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
/* send close message which is in output buffer */
- ssize_t written = Curl_conn_cf_send(cf->next, data,
- outbuf.pvBuffer, outbuf.cbBuffer,
- FALSE, &result);
+ size_t written;
+
+ result = Curl_conn_cf_send(cf->next, data,
+ outbuf.pvBuffer, outbuf.cbBuffer,
+ FALSE, &written);
Curl_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
if(!result) {
- if(written < (ssize_t)outbuf.cbBuffer) {
+ if(written < outbuf.cbBuffer) {
failf(data, "schannel: failed to send close msg: %s"
- " (bytes written: %zd)", curl_easy_strerror(result), written);
+ " (bytes written: %zu)", curl_easy_strerror(result), written);
result = CURLE_SEND_ERROR;
goto out;
}
return result;
}
-static ssize_t ssl_cf_send(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const void *buf, size_t blen,
- bool eos, CURLcode *err)
+static CURLcode ssl_cf_send(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const void *buf, size_t blen,
+ bool eos, size_t *pnwritten)
{
struct ssl_connect_data *connssl = cf->ctx;
struct cf_call_data save;
- ssize_t nwritten = 0, early_written = 0;
+ CURLcode result = CURLE_OK;
(void)eos;
- *err = CURLE_OK;
+ *pnwritten = 0;
CF_DATA_SAVE(save, cf, data);
if(connssl->state == ssl_connection_deferred) {
bool done = FALSE;
- *err = ssl_cf_connect_deferred(cf, data, buf, blen, &done);
- if(*err) {
- nwritten = -1;
+ result = ssl_cf_connect_deferred(cf, data, buf, blen, &done);
+ if(result)
goto out;
- }
else if(!done) {
- *err = CURLE_AGAIN;
- nwritten = -1;
+ result = CURLE_AGAIN;
goto out;
}
DEBUGASSERT(connssl->state == ssl_connection_complete);
if(connssl->earlydata_skip) {
if(connssl->earlydata_skip >= blen) {
connssl->earlydata_skip -= blen;
- *err = CURLE_OK;
- nwritten = (ssize_t)blen;
+ result = CURLE_OK;
+ *pnwritten = blen;
goto out;
}
else {
- early_written = connssl->earlydata_skip;
+ *pnwritten = connssl->earlydata_skip;
buf = ((const char *)buf) + connssl->earlydata_skip;
blen -= connssl->earlydata_skip;
connssl->earlydata_skip = 0;
}
/* OpenSSL and maybe other TLS libs do not like 0-length writes. Skip. */
- if(blen > 0)
- nwritten = connssl->ssl_impl->send_plain(cf, data, buf, blen, err);
-
- if(nwritten >= 0)
- nwritten += early_written;
+ if(blen > 0) {
+ ssize_t nwritten;
+ nwritten = connssl->ssl_impl->send_plain(cf, data, buf, blen, &result);
+ if(nwritten > 0)
+ *pnwritten += (size_t)nwritten;
+ }
out:
CF_DATA_RESTORE(cf, save);
- return nwritten;
+ return result;
}
-static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
- struct Curl_easy *data, char *buf, size_t len,
- CURLcode *err)
+static CURLcode ssl_cf_recv(struct Curl_cfilter *cf,
+ struct Curl_easy *data, char *buf, size_t len,
+ size_t *pnread)
{
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);
- *err = CURLE_OK;
+ *pnread = 0;
if(connssl->state == ssl_connection_deferred) {
bool done = FALSE;
- *err = ssl_cf_connect_deferred(cf, data, NULL, 0, &done);
- if(*err) {
- nread = -1;
+ result = ssl_cf_connect_deferred(cf, data, NULL, 0, &done);
+ if(result)
goto out;
- }
else if(!done) {
- *err = CURLE_AGAIN;
- nread = -1;
+ result = CURLE_AGAIN;
goto out;
}
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
- nread = connssl->ssl_impl->recv_plain(cf, data, buf, len, err);
+ 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 */
- *err = CURLE_OK;
+ result = CURLE_OK;
}
out:
- CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len,
- nread, *err);
+ CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %d, %zd", len,
+ result, *pnread);
CF_DATA_RESTORE(cf, save);
- return nread;
+ return result;
}
static CURLcode ssl_cf_shutdown(struct Curl_cfilter *cf,
struct ssl_connect_data *connssl = cf->ctx;
struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
- ssize_t nwritten, skiplen = 0;
+ size_t nwritten, skiplen = 0;
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
skiplen = (ssize_t)(blen - wssl->io_send_blocked_len);
blen = wssl->io_send_blocked_len;
}
- nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &result);
+ result = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &nwritten);
wssl->io_result = result;
- CURL_TRC_CF(data, cf, "bio_write(len=%d) -> %zd, %d",
- blen, nwritten, result);
+ CURL_TRC_CF(data, cf, "bio_write(len=%d) -> %d, %zu",
+ blen, result, nwritten);
#ifdef USE_FULL_BIO
wolfSSL_BIO_clear_retry_flags(bio);
#endif
- if(nwritten < 0 && CURLE_AGAIN == result) {
+ if(CURLE_AGAIN == result) {
wolfSSL_BIO_set_retry_write(bio);
if(wssl->shutting_down && !wssl->io_send_blocked_len)
wssl->io_send_blocked_len = blen;
}
else if(!result && skiplen)
nwritten += skiplen;
- return (int)nwritten;
+ return result ? -1 : (int)nwritten;
}
static int wssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
struct ssl_connect_data *connssl = cf->ctx;
struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
- ssize_t nread;
+ size_t nread;
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
}
}
- nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
+ result = Curl_conn_cf_recv(cf->next, data, buf, blen, &nread);
wssl->io_result = result;
- CURL_TRC_CF(data, cf, "bio_read(len=%d) -> %zd, %d", blen, nread, result);
+ CURL_TRC_CF(data, cf, "bio_read(len=%d) -> %d, %zu", blen, result, nread);
#ifdef USE_FULL_BIO
wolfSSL_BIO_clear_retry_flags(bio);
#endif
- if(nread < 0 && CURLE_AGAIN == result)
+ if(CURLE_AGAIN == result)
wolfSSL_BIO_set_retry_read(bio);
else if(nread == 0)
connssl->peer_closed = TRUE;
- return (int)nread;
+ return result ? -1 : (int)nread;
}
static WOLFSSL_BIO_METHOD *wssl_bio_cf_method = NULL;