mirror of
https://github.com/curl/curl.git
synced 2026-06-18 10:15:36 +03:00
lib: unify recv/send function signatures
cfilter/conn: change send/recv function signatures. Unify the calling/return conventions in our send/receive handling. Curl_conn_recv(), adjust pnread type Parameter `pnread` was a `ssize_t *`, but `size_t *` is better since the function returns any error in its `CURLcode` return value. Closes #17546
This commit is contained in:
parent
3934431421
commit
20c90ba298
37 changed files with 1114 additions and 1219 deletions
|
|
@ -252,7 +252,7 @@ static CURLcode send_CONNECT(struct Curl_cfilter *cf,
|
|||
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 */
|
||||
|
|
@ -260,16 +260,15 @@ static CURLcode send_CONNECT(struct Curl_cfilter *cf,
|
|||
blen -= ts->nsent;
|
||||
buf += ts->nsent;
|
||||
|
||||
nwritten = cf->next->cft->do_send(cf->next, data, buf, blen, 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:
|
||||
|
|
@ -379,7 +378,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
|
|||
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
|
||||
|
|
@ -397,7 +396,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -238,18 +238,17 @@ static ssize_t proxy_nw_in_reader(void *reader_ctx,
|
|||
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);
|
||||
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;
|
||||
}
|
||||
else {
|
||||
nread = 0;
|
||||
}
|
||||
return nread;
|
||||
*err = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t proxy_h2_nw_out_writer(void *writer_ctx,
|
||||
|
|
@ -257,19 +256,18 @@ 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,
|
||||
|
|
@ -1277,212 +1275,203 @@ static void cf_h2_proxy_adjust_pollset(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;
|
||||
|
||||
if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) {
|
||||
*err = CURLE_RECV_ERROR;
|
||||
return -1;
|
||||
}
|
||||
*pnread = 0;
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
|
||||
if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) {
|
||||
result = CURLE_RECV_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
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;
|
||||
if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) {
|
||||
*err = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
}
|
||||
*pnwritten = 0;
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
|
||||
if(ctx->tunnel.closed) {
|
||||
nwritten = -1;
|
||||
*err = CURLE_SEND_ERROR;
|
||||
if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) {
|
||||
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;
|
||||
|
||||
if(ctx->tunnel.closed) {
|
||||
result = CURLE_SEND_ERROR;
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -131,17 +131,17 @@ static CURLcode cf_haproxy_connect(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;
|
||||
|
|
|
|||
|
|
@ -1456,17 +1456,18 @@ static void win_update_sndbuf_size(struct cf_socket_ctx *ctx)
|
|||
|
||||
#endif /* USE_WINSOCK */
|
||||
|
||||
static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
const void *buf, size_t len, 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;
|
||||
|
||||
|
|
@ -1477,10 +1478,8 @@ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
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) {
|
||||
|
|
@ -1503,7 +1502,7 @@ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
#endif
|
||||
nwritten = swrite(ctx->sock, buf, len);
|
||||
|
||||
if(-1 == nwritten) {
|
||||
if(nwritten < 0) {
|
||||
int sockerr = SOCKERRNO;
|
||||
|
||||
if(
|
||||
|
|
@ -1520,36 +1519,38 @@ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
#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) {
|
||||
|
|
@ -1557,8 +1558,7 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
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) {
|
||||
|
|
@ -1569,10 +1569,9 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
}
|
||||
#endif
|
||||
|
||||
*err = CURLE_OK;
|
||||
nread = sread(ctx->sock, buf, len);
|
||||
|
||||
if(-1 == nread) {
|
||||
if(nread < 0) {
|
||||
int sockerr = SOCKERRNO;
|
||||
|
||||
if(
|
||||
|
|
@ -1588,25 +1587,25 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
#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,
|
||||
|
|
|
|||
116
lib/cfilters.c
116
lib/cfilters.c
|
|
@ -97,21 +97,23 @@ bool Curl_cf_def_data_pending(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,
|
||||
|
|
@ -234,52 +236,42 @@ CURLcode Curl_conn_shutdown(struct Curl_easy *data, int sockindex, bool *done)
|
|||
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,
|
||||
|
|
@ -381,23 +373,23 @@ void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
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,
|
||||
|
|
@ -912,17 +904,14 @@ int Curl_conn_sockindex(struct Curl_easy *data, curl_socket_t sockfd)
|
|||
}
|
||||
|
||||
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,
|
||||
|
|
@ -930,15 +919,10 @@ 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
|
||||
|
|
@ -953,11 +937,11 @@ CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
|
|||
#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,
|
||||
|
|
|
|||
|
|
@ -102,18 +102,18 @@ typedef void Curl_cft_adjust_pollset(struct Curl_cfilter *cf,
|
|||
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,
|
||||
|
|
@ -249,11 +249,11 @@ void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
|
|||
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);
|
||||
|
|
@ -326,11 +326,11 @@ CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
|
|||
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,
|
||||
|
|
@ -475,20 +475,19 @@ int Curl_conn_cf_poll(struct Curl_cfilter *cf,
|
|||
/**
|
||||
* 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
|
||||
|
|
@ -567,7 +566,7 @@ int Curl_conn_sockindex(struct Curl_easy *data, curl_socket_t sockfd);
|
|||
*/
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -326,51 +326,54 @@ static CURLcode rtmp_disconnect(struct Curl_easy *data,
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -1241,7 +1241,6 @@ static CURLcode easy_connection(struct Curl_easy *data,
|
|||
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;
|
||||
|
||||
|
|
@ -1258,13 +1257,7 @@ CURLcode curl_easy_recv(CURL *d, void *buffer, size_t buflen, size_t *n)
|
|||
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
|
||||
|
|
|
|||
243
lib/http2.c
243
lib/http2.c
|
|
@ -486,8 +486,10 @@ static ssize_t nw_in_reader(void *reader_ctx,
|
|||
{
|
||||
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,
|
||||
|
|
@ -496,15 +498,17 @@ 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,
|
||||
|
|
@ -1874,20 +1878,20 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
|
|||
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) {
|
||||
|
|
@ -1896,27 +1900,23 @@ static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
|
|||
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)) {
|
||||
|
|
@ -1924,37 +1924,36 @@ static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
|
|||
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)
|
||||
|
|
@ -2037,36 +2036,36 @@ out:
|
|||
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,
|
||||
|
|
@ -2140,15 +2139,15 @@ 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
|
||||
|
|
@ -2156,29 +2155,28 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
* 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);
|
||||
|
|
@ -2186,21 +2184,20 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
}
|
||||
|
||||
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(
|
||||
|
|
@ -2209,7 +2206,7 @@ out:
|
|||
HTTP2_HUGE_WINDOW_SIZE);
|
||||
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
return nread;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t cf_h2_body_send(struct Curl_cfilter *cf,
|
||||
|
|
@ -2259,10 +2256,10 @@ 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;
|
||||
|
|
@ -2274,36 +2271,34 @@ static ssize_t h2_submit(struct h2_stream_ctx **pstream,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -2329,8 +2324,7 @@ static ssize_t h2_submit(struct h2_stream_ctx **pstream,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -2357,48 +2351,46 @@ static ssize_t h2_submit(struct h2_stream_ctx **pstream,
|
|||
|
||||
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) {
|
||||
|
|
@ -2407,35 +2399,35 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
* 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;
|
||||
}
|
||||
|
||||
|
|
@ -2443,21 +2435,20 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
/* 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),
|
||||
|
|
@ -2466,14 +2457,14 @@ out:
|
|||
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,
|
||||
|
|
|
|||
94
lib/krb5.c
94
lib/krb5.c
|
|
@ -479,19 +479,18 @@ socket_read(struct Curl_easy *data, int sockindex, void *to, size_t len)
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
|
@ -523,8 +522,8 @@ socket_write(struct Curl_easy *data, int sockindex, const void *to,
|
|||
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;
|
||||
|
|
@ -579,52 +578,49 @@ buffer_read(struct krb5buffer *buf, void *data, size_t 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;
|
||||
|
|
@ -642,8 +638,8 @@ static void do_sec_send(struct Curl_easy *data, struct connectdata *conn,
|
|||
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 */
|
||||
|
||||
|
|
@ -677,34 +673,36 @@ static void do_sec_send(struct Curl_easy *data, struct connectdata *conn,
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -428,14 +428,13 @@ static CURLcode mqtt_recv_atleast(struct Curl_easy *data, size_t nbytes)
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
@ -703,7 +702,7 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
|
|||
{
|
||||
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);
|
||||
|
|
@ -868,7 +867,7 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
|
|||
{
|
||||
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);
|
||||
|
||||
|
|
|
|||
15
lib/multi.c
15
lib/multi.c
|
|
@ -1218,6 +1218,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
|
|||
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;
|
||||
|
||||
|
|
@ -1243,8 +1244,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
|
|||
/* 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);
|
||||
|
|
@ -1320,6 +1321,9 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
|
|||
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
|
||||
|
|
@ -1950,6 +1954,8 @@ static CURLMcode state_performing(struct Curl_easy *data,
|
|||
/* 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);
|
||||
|
|
@ -3197,6 +3203,10 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
|
|||
*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;
|
||||
}
|
||||
|
|
@ -3420,6 +3430,9 @@ void Curl_expire_ex(struct Curl_easy *data,
|
|||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1047,8 +1047,8 @@ static CURLcode client_write(struct Curl_easy *data,
|
|||
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);
|
||||
|
|
@ -1066,10 +1066,9 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
|
|||
(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) {
|
||||
|
|
@ -1077,11 +1076,9 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
|
|||
result = CURLE_RECV_ERROR;
|
||||
}
|
||||
|
||||
*err = result;
|
||||
|
||||
/* error or timed out */
|
||||
if(!msg)
|
||||
return -1;
|
||||
return result;
|
||||
|
||||
result = CURLE_OK;
|
||||
|
||||
|
|
@ -1209,8 +1206,7 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
|
|||
}
|
||||
|
||||
ldap_msgfree(msg);
|
||||
*err = result;
|
||||
return result ? -1 : 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef USE_SSL
|
||||
|
|
@ -1257,15 +1253,17 @@ ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
|
|||
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;
|
||||
|
|
@ -1280,15 +1278,17 @@ ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ static CURLcode pingpong_read(struct Curl_easy *data,
|
|||
int sockindex,
|
||||
char *buffer,
|
||||
size_t buflen,
|
||||
ssize_t *nread)
|
||||
size_t *nread)
|
||||
{
|
||||
CURLcode result;
|
||||
#ifdef HAVE_GSSAPI
|
||||
|
|
@ -294,7 +294,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
|
|||
{
|
||||
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 */
|
||||
|
|
@ -321,7 +321,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
|
|||
if(result)
|
||||
return result;
|
||||
|
||||
if(gotbytes <= 0) {
|
||||
if(!gotbytes) {
|
||||
failf(data, "response reading failed (errno: %d)", SOCKERRNO);
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -543,7 +543,7 @@ static CURLcode smb_recv_message(struct Curl_easy *data,
|
|||
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;
|
||||
|
|
|
|||
98
lib/socks.c
98
lib/socks.c
|
|
@ -81,7 +81,7 @@ enum connect_t {
|
|||
|
||||
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 */
|
||||
|
||||
|
|
@ -101,54 +101,41 @@ struct socks_state {
|
|||
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;
|
||||
}
|
||||
err = Curl_conn_cf_recv(cf->next, data, buf, blen, &nread);
|
||||
if(CURLE_AGAIN == err)
|
||||
continue;
|
||||
else if(err)
|
||||
return (int)err;
|
||||
|
||||
if(buffersize == nread) {
|
||||
allread += nread;
|
||||
*n = allread;
|
||||
result = CURLE_OK;
|
||||
break;
|
||||
}
|
||||
if(!nread) {
|
||||
result = ~CURLE_OK;
|
||||
break;
|
||||
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
|
||||
|
||||
|
|
@ -213,24 +200,25 @@ static CURLproxycode socks_state_send(struct Curl_cfilter *cf,
|
|||
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;
|
||||
|
|
@ -244,24 +232,24 @@ static CURLproxycode socks_state_recv(struct Curl_cfilter *cf,
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@
|
|||
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)
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -115,8 +115,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
|
|||
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;
|
||||
|
|
@ -210,8 +210,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
|
|||
us_length = htons((unsigned short)gss_send_token.length);
|
||||
memcpy(socksreq + 2, &us_length, sizeof(short));
|
||||
|
||||
nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4,
|
||||
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);
|
||||
|
|
@ -221,10 +221,10 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
|
|||
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);
|
||||
|
|
@ -418,8 +418,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
|
|||
memcpy(socksreq + 2, &us_length, sizeof(short));
|
||||
}
|
||||
|
||||
nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, 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);
|
||||
|
|
@ -429,8 +429,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
|
|||
|
||||
if(data->set.socks5_gssapi_nec) {
|
||||
memcpy(socksreq, &gss_enc, 1);
|
||||
nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, 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);
|
||||
|
|
@ -438,10 +438,9 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
|
|||
}
|
||||
}
|
||||
else {
|
||||
nwritten = Curl_conn_cf_send(cf->next, data,
|
||||
(char *)gss_w_token.value,
|
||||
gss_w_token.length, 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);
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
|
|||
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;
|
||||
|
|
@ -207,8 +207,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
|
|||
us_length = htons((unsigned short)sspi_send_token.cbBuffer);
|
||||
memcpy(socksreq + 2, &us_length, sizeof(short));
|
||||
|
||||
written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, 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);
|
||||
|
|
@ -221,10 +221,10 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
|
|||
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)
|
||||
|
|
@ -478,8 +478,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
|
|||
memcpy(socksreq + 2, &us_length, sizeof(short));
|
||||
}
|
||||
|
||||
written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, 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)
|
||||
|
|
@ -490,8 +490,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
|
|||
|
||||
if(data->set.socks5_gssapi_nec) {
|
||||
memcpy(socksreq, &gss_enc, 1);
|
||||
written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, 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);
|
||||
|
|
@ -499,9 +499,9 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
|
|||
}
|
||||
}
|
||||
else {
|
||||
written = Curl_conn_cf_send(cf->next, data,
|
||||
(char *)sspi_send_token.pvBuffer,
|
||||
sspi_send_token.cbBuffer, 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)
|
||||
|
|
|
|||
26
lib/telnet.c
26
lib/telnet.c
|
|
@ -1314,8 +1314,8 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
|
|||
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];
|
||||
|
|
@ -1464,6 +1464,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
|
|||
}
|
||||
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)
|
||||
|
|
@ -1475,7 +1476,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
|
|||
}
|
||||
/* 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;
|
||||
}
|
||||
|
|
@ -1550,6 +1551,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
|
|||
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)
|
||||
|
|
@ -1567,7 +1569,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
|
|||
}
|
||||
/* 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;
|
||||
}
|
||||
|
|
@ -1590,34 +1592,34 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ static ssize_t xfer_recv_resp(struct Curl_easy *data,
|
|||
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
|
||||
|
|
@ -252,8 +252,7 @@ static ssize_t xfer_recv_resp(struct Curl_easy *data,
|
|||
}
|
||||
DEBUGF(infof(data, "sendrecv_dl: we are done"));
|
||||
}
|
||||
DEBUGASSERT(nread >= 0);
|
||||
return nread;
|
||||
return (ssize_t)nread;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -954,7 +953,7 @@ CURLcode Curl_xfer_send(struct Curl_easy *data,
|
|||
|
||||
CURLcode Curl_xfer_recv(struct Curl_easy *data,
|
||||
char *buf, size_t blen,
|
||||
ssize_t *pnrcvd)
|
||||
size_t *pnrcvd)
|
||||
{
|
||||
int sockindex;
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ CURLcode Curl_xfer_send(struct Curl_easy *data,
|
|||
*/
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -158,20 +158,20 @@ typedef unsigned int curl_prot_t;
|
|||
#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 */
|
||||
/* 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 */
|
||||
|
||||
/* 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 `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"
|
||||
|
|
|
|||
|
|
@ -518,40 +518,33 @@ static void MSH3_CALL msh3_data_sent(MSH3_REQUEST *Request,
|
|||
(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)
|
||||
|
|
@ -571,60 +564,59 @@ 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);
|
||||
|
|
@ -634,7 +626,9 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
size_t nheader, i;
|
||||
ssize_t nwritten = -1;
|
||||
struct cf_call_data save;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
*pnwritten = 0;
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
|
||||
Curl_h1_req_parse_init(&h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
|
||||
|
|
@ -648,23 +642,21 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
/* 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;
|
||||
}
|
||||
|
||||
|
|
@ -683,11 +675,10 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
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 {
|
||||
|
|
@ -699,14 +690,14 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
|
||||
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:
|
||||
|
|
@ -715,7 +706,7 @@ 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,
|
||||
|
|
|
|||
|
|
@ -1293,14 +1293,14 @@ out:
|
|||
}
|
||||
|
||||
/* 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;
|
||||
|
|
@ -1310,7 +1310,7 @@ static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
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)
|
||||
|
|
@ -1319,46 +1319,42 @@ static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
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,
|
||||
|
|
@ -1464,10 +1460,10 @@ cb_h3_read_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;
|
||||
|
|
@ -1480,41 +1476,43 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -1530,8 +1528,7 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
|
|||
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;
|
||||
|
|
@ -1574,8 +1571,7 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
|
|||
"%d (%s)", stream->id, rc, nghttp3_strerror(rc));
|
||||
break;
|
||||
}
|
||||
*err = CURLE_SEND_ERROR;
|
||||
nwritten = -1;
|
||||
result = CURLE_SEND_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -1592,46 +1588,45 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
|
|||
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);
|
||||
|
|
@ -1639,7 +1634,7 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *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) {
|
||||
|
|
@ -1651,52 +1646,48 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
* 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,
|
||||
|
|
|
|||
|
|
@ -2009,44 +2009,39 @@ out:
|
|||
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) {
|
||||
|
|
@ -2057,56 +2052,53 @@ static ssize_t cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
* 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,
|
||||
|
|
@ -2114,24 +2106,19 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
|
|||
" 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);
|
||||
|
|
@ -2139,69 +2126,66 @@ static ssize_t cf_osslq_recv(struct Curl_cfilter *cf, struct Curl_easy *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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -873,90 +873,89 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
|
|||
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)) {
|
||||
|
|
@ -967,26 +966,22 @@ static ssize_t cf_quiche_send_body(struct Curl_cfilter *cf,
|
|||
"-> 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))
|
||||
|
|
@ -994,8 +989,8 @@ static ssize_t cf_quiche_send_body(struct Curl_cfilter *cf,
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1003,10 +998,10 @@ static ssize_t cf_quiche_send_body(struct Curl_cfilter *cf,
|
|||
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);
|
||||
|
|
@ -1014,13 +1009,14 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
|
|||
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);
|
||||
}
|
||||
|
|
@ -1028,7 +1024,7 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
|
|||
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) {
|
||||
|
|
@ -1037,19 +1033,17 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -1061,7 +1055,11 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
|
|||
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,
|
||||
|
|
@ -1072,21 +1070,18 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
|
|||
* 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;
|
||||
|
|
@ -1102,48 +1097,43 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
|
|||
}
|
||||
}
|
||||
|
||||
if(nwritten > 0 && ((size_t)nwritten < len)) {
|
||||
/* after the headers, there was request BODY data */
|
||||
size_t hds_len = (size_t)nwritten;
|
||||
ssize_t bwritten;
|
||||
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);
|
||||
}
|
||||
|
|
@ -1159,29 +1149,28 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *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,
|
||||
|
|
@ -1269,13 +1258,13 @@ static CURLcode cf_quiche_data_event(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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2875,19 +2875,20 @@ static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
|
|||
return myssh_done(data, sshc, status);
|
||||
}
|
||||
|
||||
static ssize_t scp_send(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len, bool eos, CURLcode *err)
|
||||
static CURLcode scp_send(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len, bool eos,
|
||||
size_t *pnwritten)
|
||||
{
|
||||
int rc;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
|
||||
|
||||
(void) sockindex; /* we only support SCP on the fixed known primary socket */
|
||||
(void)eos;
|
||||
*pnwritten = 0;
|
||||
|
||||
if(!sshc) {
|
||||
*err = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
if(!sshc)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
rc = ssh_scp_write(sshc->scp_session, mem, len);
|
||||
|
||||
|
|
@ -2897,32 +2898,30 @@ static ssize_t scp_send(struct Curl_easy *data, int sockindex,
|
|||
* Currently rc can only be number of bytes read or SSH_ERROR. */
|
||||
myssh_block2waitfor(conn, sshc, (rc == SSH_AGAIN));
|
||||
|
||||
if(rc == SSH_AGAIN) {
|
||||
*err = CURLE_AGAIN;
|
||||
return 0;
|
||||
}
|
||||
if(rc == SSH_AGAIN)
|
||||
return CURLE_AGAIN;
|
||||
else
|
||||
#endif
|
||||
if(rc != SSH_OK) {
|
||||
*err = CURLE_SSH;
|
||||
return -1;
|
||||
}
|
||||
if(rc != SSH_OK)
|
||||
return CURLE_SSH;
|
||||
|
||||
return len;
|
||||
*pnwritten = len;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
|
||||
char *mem, size_t len, CURLcode *err)
|
||||
static CURLcode scp_recv(struct Curl_easy *data, int sockindex,
|
||||
char *mem, size_t len, size_t *pnread)
|
||||
{
|
||||
ssize_t nread;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
|
||||
(void) sockindex; /* we only support SCP on the fixed known primary socket */
|
||||
ssize_t nread;
|
||||
|
||||
(void) sockindex; /* we only support SCP on the fixed known primary socket */
|
||||
*pnread = 0;
|
||||
|
||||
if(!sshc)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
if(!sshc) {
|
||||
*err = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
/* libssh returns int */
|
||||
nread = ssh_scp_read(sshc->scp_session, mem, len);
|
||||
|
||||
|
|
@ -2932,13 +2931,11 @@ static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
|
|||
* Currently rc can only be SSH_OK or SSH_ERROR. */
|
||||
|
||||
myssh_block2waitfor(conn, sshc, (nread == SSH_AGAIN));
|
||||
if(nread == SSH_AGAIN) {
|
||||
*err = CURLE_AGAIN;
|
||||
nread = -1;
|
||||
}
|
||||
if(nread == SSH_AGAIN)
|
||||
return CURLE_AGAIN;
|
||||
#endif
|
||||
|
||||
return nread;
|
||||
*pnread = (size_t)nread;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3038,20 +3035,21 @@ static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
|
|||
}
|
||||
|
||||
/* return number of sent bytes */
|
||||
static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len, bool eos,
|
||||
CURLcode *err)
|
||||
static CURLcode sftp_send(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len, bool eos,
|
||||
size_t *pnwritten)
|
||||
{
|
||||
ssize_t nwrite;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
|
||||
ssize_t nwrite;
|
||||
|
||||
(void)sockindex;
|
||||
(void)eos;
|
||||
*pnwritten = 0;
|
||||
|
||||
if(!sshc)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
if(!sshc) {
|
||||
*err = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
/* limit the writes to the maximum specified in Section 3 of
|
||||
* https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-02
|
||||
*/
|
||||
|
|
@ -3063,31 +3061,27 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
|
|||
sftp_file_set_nonblocking(sshc->sftp_file);
|
||||
if(sftp_aio_begin_write(sshc->sftp_file, mem, len,
|
||||
&sshc->sftp_aio) == SSH_ERROR) {
|
||||
*err = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
return CURLE_SEND_ERROR;
|
||||
}
|
||||
sshc->sftp_send_state = 1;
|
||||
FALLTHROUGH();
|
||||
case 1:
|
||||
nwrite = sftp_aio_wait_write(&sshc->sftp_aio);
|
||||
myssh_block2waitfor(conn, sshc, (nwrite == SSH_AGAIN) ? TRUE : FALSE);
|
||||
if(nwrite == SSH_AGAIN) {
|
||||
*err = CURLE_AGAIN;
|
||||
return 0;
|
||||
}
|
||||
else if(nwrite < 0) {
|
||||
*err = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
}
|
||||
if(nwrite == SSH_AGAIN)
|
||||
return CURLE_AGAIN;
|
||||
else if(nwrite < 0)
|
||||
return CURLE_SEND_ERROR;
|
||||
if(sshc->sftp_aio) {
|
||||
sftp_aio_free(sshc->sftp_aio);
|
||||
sshc->sftp_aio = NULL;
|
||||
}
|
||||
sshc->sftp_send_state = 0;
|
||||
return nwrite;
|
||||
*pnwritten = (size_t)nwrite;
|
||||
return CURLE_OK;
|
||||
default:
|
||||
/* we never reach here */
|
||||
return -1;
|
||||
return CURLE_SEND_ERROR;
|
||||
}
|
||||
#else
|
||||
nwrite = sftp_write(sshc->sftp_file, mem, len);
|
||||
|
|
@ -3101,12 +3095,11 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
|
|||
}
|
||||
else
|
||||
#endif
|
||||
if(nwrite < 0) {
|
||||
*err = CURLE_SSH;
|
||||
nwrite = -1;
|
||||
}
|
||||
if(nwrite < 0)
|
||||
return CURLE_SSH;
|
||||
|
||||
return nwrite;
|
||||
*pnwritten = (size_t)nwrite;
|
||||
return CURLE_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -3114,28 +3107,26 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
|
|||
* Return number of received (decrypted) bytes
|
||||
* or <0 on error
|
||||
*/
|
||||
static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
|
||||
char *mem, size_t len, CURLcode *err)
|
||||
static CURLcode sftp_recv(struct Curl_easy *data, int sockindex,
|
||||
char *mem, size_t len, size_t *pnread)
|
||||
{
|
||||
ssize_t nread;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
|
||||
ssize_t nread;
|
||||
|
||||
(void)sockindex;
|
||||
*pnread = 0;
|
||||
|
||||
DEBUGASSERT(len < CURL_MAX_READ_SIZE);
|
||||
if(!sshc) {
|
||||
*err = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
if(!sshc)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
switch(sshc->sftp_recv_state) {
|
||||
case 0:
|
||||
sshc->sftp_file_index =
|
||||
sftp_async_read_begin(sshc->sftp_file, (uint32_t)len);
|
||||
if(sshc->sftp_file_index < 0) {
|
||||
*err = CURLE_RECV_ERROR;
|
||||
return -1;
|
||||
}
|
||||
if(sshc->sftp_file_index < 0)
|
||||
return CURLE_RECV_ERROR;
|
||||
|
||||
FALLTHROUGH();
|
||||
case 1:
|
||||
|
|
@ -3145,21 +3136,18 @@ static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
|
|||
|
||||
myssh_block2waitfor(conn, sshc, (nread == SSH_AGAIN));
|
||||
|
||||
if(nread == SSH_AGAIN) {
|
||||
*err = CURLE_AGAIN;
|
||||
return -1;
|
||||
}
|
||||
else if(nread < 0) {
|
||||
*err = CURLE_RECV_ERROR;
|
||||
return -1;
|
||||
}
|
||||
if(nread == SSH_AGAIN)
|
||||
return CURLE_AGAIN;
|
||||
else if(nread < 0)
|
||||
return CURLE_RECV_ERROR;
|
||||
|
||||
sshc->sftp_recv_state = 0;
|
||||
return nread;
|
||||
*pnread = (size_t)nread;
|
||||
return CURLE_OK;
|
||||
|
||||
default:
|
||||
/* we never reach here */
|
||||
return -1;
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3290,7 +3290,7 @@ static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
|
|||
size_t length, int flags, void **abstract)
|
||||
{
|
||||
struct Curl_easy *data = (struct Curl_easy *)*abstract;
|
||||
ssize_t nread;
|
||||
size_t nread;
|
||||
CURLcode result;
|
||||
struct connectdata *conn = data->conn;
|
||||
Curl_recv *backup = conn->recv[0];
|
||||
|
|
@ -3311,7 +3311,7 @@ static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
|
|||
else if(result)
|
||||
return -1; /* generic error */
|
||||
Curl_debug(data, CURLINFO_DATA_IN, (const char *)buffer, (size_t)nread);
|
||||
return nread;
|
||||
return (ssize_t)nread;
|
||||
}
|
||||
|
||||
static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
|
||||
|
|
@ -3769,58 +3769,63 @@ static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
|
|||
return ssh_done(data, status);
|
||||
}
|
||||
|
||||
static ssize_t scp_send(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len, bool eos, CURLcode *err)
|
||||
static CURLcode scp_send(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len, bool eos,
|
||||
size_t *pnwritten)
|
||||
{
|
||||
ssize_t nwrite;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
|
||||
CURLcode result = CURLE_OK;
|
||||
ssize_t nwritten;
|
||||
|
||||
(void)sockindex; /* we only support SCP on the fixed known primary socket */
|
||||
(void)eos;
|
||||
*pnwritten = 0;
|
||||
|
||||
if(!sshc)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
if(!sshc) {
|
||||
*err = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
/* libssh2_channel_write() returns int! */
|
||||
nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len);
|
||||
nwritten = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len);
|
||||
|
||||
ssh_block2waitfor(data, sshc, (nwrite == LIBSSH2_ERROR_EAGAIN));
|
||||
ssh_block2waitfor(data, sshc, (nwritten == LIBSSH2_ERROR_EAGAIN));
|
||||
|
||||
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
|
||||
*err = CURLE_AGAIN;
|
||||
nwrite = 0;
|
||||
}
|
||||
else if(nwrite < LIBSSH2_ERROR_NONE) {
|
||||
*err = libssh2_session_error_to_CURLE((int)nwrite);
|
||||
nwrite = -1;
|
||||
}
|
||||
if(nwritten == LIBSSH2_ERROR_EAGAIN)
|
||||
result = CURLE_AGAIN;
|
||||
else if(nwritten < LIBSSH2_ERROR_NONE)
|
||||
result = libssh2_session_error_to_CURLE((int)nwritten);
|
||||
else
|
||||
*pnwritten = (size_t)nwritten;
|
||||
|
||||
return nwrite;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
|
||||
char *mem, size_t len, CURLcode *err)
|
||||
static CURLcode scp_recv(struct Curl_easy *data, int sockindex,
|
||||
char *mem, size_t len, size_t *pnread)
|
||||
{
|
||||
ssize_t nread;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
|
||||
(void)sockindex; /* we only support SCP on the fixed known primary socket */
|
||||
CURLcode result = CURLE_OK;
|
||||
ssize_t nread;
|
||||
|
||||
(void)sockindex; /* we only support SCP on the fixed known primary socket */
|
||||
*pnread = 0;
|
||||
|
||||
if(!sshc)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
if(!sshc) {
|
||||
*err = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
/* libssh2_channel_read() returns int */
|
||||
nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len);
|
||||
|
||||
ssh_block2waitfor(data, sshc, (nread == LIBSSH2_ERROR_EAGAIN));
|
||||
if(nread == LIBSSH2_ERROR_EAGAIN) {
|
||||
*err = CURLE_AGAIN;
|
||||
nread = -1;
|
||||
}
|
||||
if(nread == LIBSSH2_ERROR_EAGAIN)
|
||||
return CURLE_AGAIN;
|
||||
else if(nread < LIBSSH2_ERROR_NONE)
|
||||
result = libssh2_session_error_to_CURLE((int)nread);
|
||||
else
|
||||
*pnread = (size_t)nread;
|
||||
|
||||
return nread;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3925,64 +3930,61 @@ static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
|
|||
}
|
||||
|
||||
/* return number of sent bytes */
|
||||
static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len, bool eos, CURLcode *err)
|
||||
static CURLcode sftp_send(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len, bool eos,
|
||||
size_t *pnwritten)
|
||||
{
|
||||
ssize_t nwrite;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
|
||||
ssize_t nwrite;
|
||||
|
||||
(void)sockindex;
|
||||
(void)eos;
|
||||
*pnwritten = 0;
|
||||
|
||||
if(!sshc)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
if(!sshc) {
|
||||
*err = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len);
|
||||
|
||||
ssh_block2waitfor(data, sshc, (nwrite == LIBSSH2_ERROR_EAGAIN));
|
||||
|
||||
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
|
||||
*err = CURLE_AGAIN;
|
||||
nwrite = 0;
|
||||
}
|
||||
else if(nwrite < LIBSSH2_ERROR_NONE) {
|
||||
*err = libssh2_session_error_to_CURLE((int)nwrite);
|
||||
nwrite = -1;
|
||||
}
|
||||
|
||||
return nwrite;
|
||||
if(nwrite == LIBSSH2_ERROR_EAGAIN)
|
||||
return CURLE_AGAIN;
|
||||
else if(nwrite < LIBSSH2_ERROR_NONE)
|
||||
return libssh2_session_error_to_CURLE((int)nwrite);
|
||||
*pnwritten = (size_t)nwrite;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return number of received (decrypted) bytes
|
||||
* or <0 on error
|
||||
*/
|
||||
static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
|
||||
char *mem, size_t len, CURLcode *err)
|
||||
static CURLcode sftp_recv(struct Curl_easy *data, int sockindex,
|
||||
char *mem, size_t len, size_t *pnread)
|
||||
{
|
||||
ssize_t nread;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
|
||||
(void)sockindex;
|
||||
ssize_t nread;
|
||||
|
||||
(void)sockindex;
|
||||
*pnread = 0;
|
||||
|
||||
if(!sshc)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
if(!sshc) {
|
||||
*err = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
nread = libssh2_sftp_read(sshc->sftp_handle, mem, len);
|
||||
|
||||
ssh_block2waitfor(data, sshc, (nread == LIBSSH2_ERROR_EAGAIN));
|
||||
|
||||
if(nread == LIBSSH2_ERROR_EAGAIN) {
|
||||
*err = CURLE_AGAIN;
|
||||
nread = -1;
|
||||
if(nread == LIBSSH2_ERROR_EAGAIN)
|
||||
return CURLE_AGAIN;
|
||||
else if(nread < 0)
|
||||
return libssh2_session_error_to_CURLE((int)nread);
|
||||
|
||||
}
|
||||
else if(nread < 0) {
|
||||
*err = libssh2_session_error_to_CURLE((int)nread);
|
||||
}
|
||||
return nread;
|
||||
*pnread = (size_t)nread;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static const char *sftp_libssh2_strerror(unsigned long err)
|
||||
|
|
|
|||
|
|
@ -220,37 +220,35 @@ static void wssh_state(struct Curl_easy *data,
|
|||
sshc->state = nowstate;
|
||||
}
|
||||
|
||||
static ssize_t wscp_send(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len, bool eos,
|
||||
CURLcode *err)
|
||||
static CURLcode wscp_send(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len, bool eos,
|
||||
size_t *pnwritten)
|
||||
{
|
||||
ssize_t nwrite = 0;
|
||||
(void)data;
|
||||
(void)sockindex; /* we only support SCP on the fixed known primary socket */
|
||||
(void)mem;
|
||||
(void)len;
|
||||
(void)eos;
|
||||
(void)err;
|
||||
|
||||
return nwrite;
|
||||
*pnwritten = 0;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static ssize_t wscp_recv(struct Curl_easy *data, int sockindex,
|
||||
char *mem, size_t len, CURLcode *err)
|
||||
static CURLcode wscp_recv(struct Curl_easy *data, int sockindex,
|
||||
char *mem, size_t len, size_t *pnread)
|
||||
{
|
||||
ssize_t nread = 0;
|
||||
(void)data;
|
||||
(void)sockindex; /* we only support SCP on the fixed known primary socket */
|
||||
(void)mem;
|
||||
(void)len;
|
||||
(void)err;
|
||||
*pnread = 0;
|
||||
|
||||
return nread;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* return number of sent bytes */
|
||||
static ssize_t wsftp_send(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len, bool eos, CURLcode *err)
|
||||
static CURLcode wsftp_send(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len, bool eos,
|
||||
size_t *pnwritten)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
|
||||
|
|
@ -259,10 +257,10 @@ static ssize_t wsftp_send(struct Curl_easy *data, int sockindex,
|
|||
(void)sockindex;
|
||||
(void)eos;
|
||||
|
||||
if(!sshc) {
|
||||
*err = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
*pnwritten = 0;
|
||||
if(!sshc)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
offset[0] = (word32)sshc->offset & 0xFFFFFFFF;
|
||||
offset[1] = (word32)(sshc->offset >> 32) & 0xFFFFFFFF;
|
||||
|
||||
|
|
@ -275,31 +273,30 @@ static ssize_t wsftp_send(struct Curl_easy *data, int sockindex,
|
|||
rc = wolfSSH_get_error(sshc->ssh_session);
|
||||
if(rc == WS_WANT_READ) {
|
||||
conn->waitfor = KEEP_RECV;
|
||||
*err = CURLE_AGAIN;
|
||||
return -1;
|
||||
return CURLE_AGAIN;
|
||||
}
|
||||
else if(rc == WS_WANT_WRITE) {
|
||||
conn->waitfor = KEEP_SEND;
|
||||
*err = CURLE_AGAIN;
|
||||
return -1;
|
||||
return CURLE_AGAIN;
|
||||
}
|
||||
if(rc < 0) {
|
||||
failf(data, "wolfSSH_SFTP_SendWritePacket returned %d", rc);
|
||||
return -1;
|
||||
return CURLE_SEND_ERROR;
|
||||
}
|
||||
DEBUGASSERT(rc == (int)len);
|
||||
*pnwritten = (size_t)rc;
|
||||
sshc->offset += *pnwritten;
|
||||
infof(data, "sent %zu bytes SFTP from offset %" FMT_OFF_T,
|
||||
len, sshc->offset);
|
||||
sshc->offset += len;
|
||||
return (ssize_t)rc;
|
||||
*pnwritten, sshc->offset);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return number of received (decrypted) bytes
|
||||
* or <0 on error
|
||||
*/
|
||||
static ssize_t wsftp_recv(struct Curl_easy *data, int sockindex,
|
||||
char *mem, size_t len, CURLcode *err)
|
||||
static CURLcode wsftp_recv(struct Curl_easy *data, int sockindex,
|
||||
char *mem, size_t len, size_t *pnread)
|
||||
{
|
||||
int rc;
|
||||
struct connectdata *conn = data->conn;
|
||||
|
|
@ -307,10 +304,10 @@ static ssize_t wsftp_recv(struct Curl_easy *data, int sockindex,
|
|||
word32 offset[2];
|
||||
(void)sockindex;
|
||||
|
||||
if(!sshc) {
|
||||
*err = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
*pnread = 0;
|
||||
if(!sshc)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
offset[0] = (word32)sshc->offset & 0xFFFFFFFF;
|
||||
offset[1] = (word32)(sshc->offset >> 32) & 0xFFFFFFFF;
|
||||
|
||||
|
|
@ -322,24 +319,22 @@ static ssize_t wsftp_recv(struct Curl_easy *data, int sockindex,
|
|||
rc = wolfSSH_get_error(sshc->ssh_session);
|
||||
if(rc == WS_WANT_READ) {
|
||||
conn->waitfor = KEEP_RECV;
|
||||
*err = CURLE_AGAIN;
|
||||
return -1;
|
||||
return CURLE_AGAIN;
|
||||
}
|
||||
else if(rc == WS_WANT_WRITE) {
|
||||
conn->waitfor = KEEP_SEND;
|
||||
*err = CURLE_AGAIN;
|
||||
return -1;
|
||||
return CURLE_AGAIN;
|
||||
}
|
||||
|
||||
DEBUGASSERT(rc <= (int)len);
|
||||
|
||||
if(rc < 0) {
|
||||
failf(data, "wolfSSH_SFTP_SendReadPacket returned %d", rc);
|
||||
return -1;
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
sshc->offset += len;
|
||||
|
||||
return (ssize_t)rc;
|
||||
*pnread = (size_t)rc;
|
||||
sshc->offset += *pnread;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static void wssh_easy_dtor(void *key, size_t klen, void *entry)
|
||||
|
|
|
|||
|
|
@ -91,21 +91,21 @@ static ssize_t gtls_push(void *s, const 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 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)
|
||||
|
|
@ -115,7 +115,7 @@ 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);
|
||||
|
|
@ -129,19 +129,19 @@ static ssize_t gtls_pull(void *s, void *buf, size_t blen)
|
|||
}
|
||||
}
|
||||
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -191,28 +191,27 @@ static int mbedtls_bio_cf_write(void *bio,
|
|||
{
|
||||
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);
|
||||
|
|
@ -222,13 +221,12 @@ static int mbedtls_bio_cf_read(void *bio, unsigned char *buf, size_t blen)
|
|||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -717,22 +717,23 @@ static int ossl_bio_cf_out_write(BIO *bio, const char *buf, int blen)
|
|||
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;
|
||||
}
|
||||
|
|
@ -743,8 +744,8 @@ static int ossl_bio_cf_in_read(BIO *bio, char *buf, int blen)
|
|||
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. */
|
||||
|
|
@ -753,12 +754,12 @@ static int ossl_bio_cf_in_read(BIO *bio, char *buf, int blen)
|
|||
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);
|
||||
}
|
||||
|
|
@ -769,15 +770,14 @@ static int ossl_bio_cf_in_read(BIO *bio, char *buf, int blen)
|
|||
/* 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
|
||||
|
|
|
|||
|
|
@ -101,9 +101,11 @@ read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n)
|
|||
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)
|
||||
|
|
@ -114,8 +116,8 @@ read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -125,10 +127,11 @@ write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n)
|
|||
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;
|
||||
|
|
@ -136,8 +139,8 @@ write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -897,7 +897,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
|
|||
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;
|
||||
|
|
@ -1128,18 +1128,18 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
"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;
|
||||
|
|
@ -1161,7 +1161,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
(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;
|
||||
|
|
@ -1229,12 +1229,12 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
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, "
|
||||
|
|
@ -1250,7 +1250,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
/* 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,
|
||||
|
|
@ -1317,13 +1317,13 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1800,7 +1800,7 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
|
||||
/* 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) {
|
||||
|
|
@ -1830,9 +1830,9 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
}
|
||||
/* 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) {
|
||||
|
|
@ -1841,7 +1841,7 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
break;
|
||||
}
|
||||
|
||||
written += this_write;
|
||||
written += (ssize_t)this_write;
|
||||
}
|
||||
}
|
||||
else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) {
|
||||
|
|
@ -1866,7 +1866,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
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;
|
||||
|
|
@ -1950,10 +1950,10 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
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"));
|
||||
|
|
@ -1966,10 +1966,10 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2279,14 +2279,16 @@ static CURLcode schannel_shutdown(struct Curl_cfilter *cf,
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1443,29 +1443,26 @@ static bool ssl_cf_data_pending(struct Curl_cfilter *cf,
|
|||
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);
|
||||
|
|
@ -1474,12 +1471,12 @@ static ssize_t ssl_cf_send(struct Curl_cfilter *cf,
|
|||
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;
|
||||
|
|
@ -1487,56 +1484,56 @@ static ssize_t ssl_cf_send(struct Curl_cfilter *cf,
|
|||
}
|
||||
|
||||
/* 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,
|
||||
|
|
|
|||
|
|
@ -319,7 +319,7 @@ static int wssl_bio_cf_out_write(WOLFSSL_BIO *bio,
|
|||
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);
|
||||
|
|
@ -333,21 +333,21 @@ static int wssl_bio_cf_out_write(WOLFSSL_BIO *bio,
|
|||
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)
|
||||
|
|
@ -356,7 +356,7 @@ 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);
|
||||
|
|
@ -376,17 +376,17 @@ static int wssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue