mirror of
https://github.com/curl/curl.git
synced 2025-09-13 23:52:42 +03:00
lib: send rework
Curl_read/Curl_write clarifications - replace `Curl_read()`, `Curl_write()` and `Curl_nwrite()` to 1clarify when and at what level they operate - send/recv of transfer related data is now done via `Curl_xfer_send()/Curl_xfer_recv()` which no longer has socket/socketindex as parameter. It decides on the transfer setup of `conn->sockfd` and `conn->writesockfd` on which connection filter chain to operate. - send/recv on a specific connection filter chain is done via `Curl_conn_send()/Curl_conn_recv()` which get the socket index as parameter. - rename `Curl_setup_transfer()` to `Curl_xfer_setup()` for naming consistency - clarify that the special CURLE_AGAIN handling to return `CURLE_OK` with length 0 only applies to `Curl_xfer_send()` and CURLE_AGAIN is returned by all other send() variants. SingleRequest reshuffling - move functions into request.[ch] - differentiate between reset and free - add Curl_req_done() to perform last actions - add a send `bufq` to SingleRequest for future use in keeping upload data Closes #12963
This commit is contained in:
parent
b8ed0f8259
commit
5929822114
|
@ -201,6 +201,7 @@ LIB_CFILES = \
|
|||
psl.c \
|
||||
rand.c \
|
||||
rename.c \
|
||||
request.c \
|
||||
rtsp.c \
|
||||
select.c \
|
||||
sendf.c \
|
||||
|
@ -337,6 +338,7 @@ LIB_HFILES = \
|
|||
psl.h \
|
||||
rand.h \
|
||||
rename.h \
|
||||
request.h \
|
||||
rtsp.h \
|
||||
select.h \
|
||||
sendf.h \
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
|
||||
#include <hyper.h>
|
||||
#include "urldata.h"
|
||||
#include "cfilters.h"
|
||||
#include "sendf.h"
|
||||
#include "headers.h"
|
||||
#include "transfer.h"
|
||||
|
@ -74,7 +75,8 @@ typedef enum {
|
|||
size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
|
||||
uint8_t *buf, size_t buflen)
|
||||
{
|
||||
struct Curl_easy *data = userp;
|
||||
struct hyp_io_ctx *io_ctx = userp;
|
||||
struct Curl_easy *data = io_ctx->data;
|
||||
struct connectdata *conn = data->conn;
|
||||
CURLcode result;
|
||||
ssize_t nread;
|
||||
|
@ -82,7 +84,8 @@ size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
|
|||
(void)ctx;
|
||||
|
||||
DEBUGF(infof(data, "Curl_hyper_recv(%zu)", buflen));
|
||||
result = Curl_read(data, conn->sockfd, (char *)buf, buflen, &nread);
|
||||
result = Curl_conn_recv(data, io_ctx->sockindex,
|
||||
(char *)buf, buflen, &nread);
|
||||
if(result == CURLE_AGAIN) {
|
||||
/* would block, register interest */
|
||||
DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> EAGAIN", buflen));
|
||||
|
@ -106,15 +109,14 @@ size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
|
|||
size_t Curl_hyper_send(void *userp, hyper_context *ctx,
|
||||
const uint8_t *buf, size_t buflen)
|
||||
{
|
||||
struct Curl_easy *data = userp;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct hyp_io_ctx *io_ctx = userp;
|
||||
struct Curl_easy *data = io_ctx->data;
|
||||
CURLcode result;
|
||||
ssize_t nwrote;
|
||||
|
||||
DEBUGF(infof(data, "Curl_hyper_send(%zu)", buflen));
|
||||
result = Curl_write(data, conn->sockfd, (void *)buf, buflen, &nwrote);
|
||||
if(!result && !nwrote)
|
||||
result = CURLE_AGAIN;
|
||||
result = Curl_conn_send(data, io_ctx->sockindex,
|
||||
(void *)buf, buflen, &nwrote);
|
||||
if(result == CURLE_AGAIN) {
|
||||
DEBUGF(infof(data, "Curl_hyper_send(%zu) -> EAGAIN", buflen));
|
||||
/* would block, register interest */
|
||||
|
@ -885,7 +887,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
|||
may be parts of the request that is not yet sent, since we can deal with
|
||||
the rest of the request in the PERFORM phase. */
|
||||
*done = TRUE;
|
||||
Curl_client_cleanup(data);
|
||||
Curl_cw_reset(data);
|
||||
|
||||
/* Add collecting of headers written to client. For a new connection,
|
||||
* we might have done that already, but reuse
|
||||
|
@ -939,7 +941,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
|||
goto error;
|
||||
}
|
||||
/* tell Hyper how to read/write network data */
|
||||
hyper_io_set_userdata(io, data);
|
||||
h->io_ctx.data = data;
|
||||
h->io_ctx.sockindex = FIRSTSOCKET;
|
||||
hyper_io_set_userdata(io, &h->io_ctx);
|
||||
hyper_io_set_read(io, Curl_hyper_recv);
|
||||
hyper_io_set_write(io, Curl_hyper_send);
|
||||
|
||||
|
@ -1200,7 +1204,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
|||
if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
|
||||
/* HTTP GET/HEAD download */
|
||||
Curl_pgrsSetUploadSize(data, 0); /* nothing */
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, TRUE, -1);
|
||||
}
|
||||
conn->datastream = Curl_hyper_stream;
|
||||
if(data->state.expect100header)
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
|
||||
#include <hyper.h>
|
||||
|
||||
struct hyp_io_ctx {
|
||||
struct Curl_easy *data;
|
||||
int sockindex;
|
||||
};
|
||||
|
||||
/* per-transfer data for the Hyper backend */
|
||||
struct hyptransfer {
|
||||
hyper_waker *write_waker;
|
||||
|
@ -36,6 +41,7 @@ struct hyptransfer {
|
|||
const hyper_executor *exec;
|
||||
hyper_waker *exp100_waker;
|
||||
hyper_waker *send_body_waker;
|
||||
struct hyp_io_ctx io_ctx;
|
||||
};
|
||||
|
||||
size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
|
||||
|
|
|
@ -366,7 +366,6 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
|
|||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SingleRequest *k = &data->req;
|
||||
curl_socket_t tunnelsocket = Curl_conn_cf_get_socket(cf, data);
|
||||
char *linep;
|
||||
size_t line_len;
|
||||
int error, writetype;
|
||||
|
@ -386,7 +385,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
|
|||
|
||||
/* Read one byte at a time to avoid a race condition. Wait at most one
|
||||
second before looping to ensure continuous pgrsUpdates. */
|
||||
result = Curl_read(data, tunnelsocket, &byte, 1, &nread);
|
||||
result = Curl_conn_recv(data, cf->sockindex, &byte, 1, &nread);
|
||||
if(result == CURLE_AGAIN)
|
||||
/* socket buffer drained, return */
|
||||
return CURLE_OK;
|
||||
|
@ -593,7 +592,9 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
|
|||
goto error;
|
||||
}
|
||||
/* tell Hyper how to read/write network data */
|
||||
hyper_io_set_userdata(io, data);
|
||||
h->io_ctx.data = data;
|
||||
h->io_ctx.sockindex = cf->sockindex;
|
||||
hyper_io_set_userdata(io, &h->io_ctx);
|
||||
hyper_io_set_read(io, Curl_hyper_recv);
|
||||
hyper_io_set_write(io, Curl_hyper_send);
|
||||
conn->sockfd = tunnelsocket;
|
||||
|
@ -1007,7 +1008,7 @@ out:
|
|||
data->req.header = TRUE; /* assume header */
|
||||
data->req.bytecount = 0;
|
||||
data->req.ignorebody = FALSE;
|
||||
Curl_client_cleanup(data);
|
||||
Curl_cw_reset(data);
|
||||
Curl_pgrsSetUploadCounter(data, 0);
|
||||
Curl_pgrsSetDownloadCounter(data, 0);
|
||||
|
||||
|
|
|
@ -129,11 +129,17 @@ static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
|
|||
case HAPROXY_SEND:
|
||||
len = Curl_dyn_len(&ctx->data_out);
|
||||
if(len > 0) {
|
||||
ssize_t written = Curl_conn_send(data, cf->sockindex,
|
||||
ssize_t written;
|
||||
result = Curl_conn_send(data, cf->sockindex,
|
||||
Curl_dyn_ptr(&ctx->data_out),
|
||||
len, &result);
|
||||
if(written < 0)
|
||||
len, &written);
|
||||
if(result == CURLE_AGAIN) {
|
||||
result = CURLE_OK;
|
||||
written = 0;
|
||||
}
|
||||
else if(result)
|
||||
goto out;
|
||||
DEBUGASSERT(written >= 0);
|
||||
Curl_dyn_tail(&ctx->data_out, len - (size_t)written);
|
||||
if(Curl_dyn_len(&ctx->data_out) > 0) {
|
||||
result = CURLE_OK;
|
||||
|
|
|
@ -168,38 +168,46 @@ void Curl_conn_close(struct Curl_easy *data, int index)
|
|||
}
|
||||
}
|
||||
|
||||
ssize_t Curl_conn_recv(struct Curl_easy *data, int num, char *buf,
|
||||
ssize_t Curl_cf_recv(struct Curl_easy *data, int num, char *buf,
|
||||
size_t len, CURLcode *code)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(data->conn);
|
||||
*code = CURLE_OK;
|
||||
cf = data->conn->cfilter[num];
|
||||
while(cf && !cf->connected) {
|
||||
cf = cf->next;
|
||||
}
|
||||
if(cf) {
|
||||
return cf->cft->do_recv(cf, data, buf, len, code);
|
||||
ssize_t nread = cf->cft->do_recv(cf, data, buf, len, code);
|
||||
DEBUGASSERT(nread >= 0 || *code);
|
||||
DEBUGASSERT(nread < 0 || !*code);
|
||||
return nread;
|
||||
}
|
||||
failf(data, "recv: no filter connected");
|
||||
*code = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t Curl_conn_send(struct Curl_easy *data, int num,
|
||||
ssize_t Curl_cf_send(struct Curl_easy *data, int num,
|
||||
const void *mem, size_t len, CURLcode *code)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(data->conn);
|
||||
*code = CURLE_OK;
|
||||
cf = data->conn->cfilter[num];
|
||||
while(cf && !cf->connected) {
|
||||
cf = cf->next;
|
||||
}
|
||||
if(cf) {
|
||||
return cf->cft->do_send(cf, data, mem, len, code);
|
||||
ssize_t nwritten = cf->cft->do_send(cf, data, mem, len, code);
|
||||
DEBUGASSERT(nwritten >= 0 || *code);
|
||||
DEBUGASSERT(nwritten < 0 || !*code || !len);
|
||||
return nwritten;
|
||||
}
|
||||
failf(data, "send: no filter connected");
|
||||
DEBUGASSERT(0);
|
||||
|
@ -662,6 +670,58 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
|
|||
return (result || n <= 0)? 1 : (size_t)n;
|
||||
}
|
||||
|
||||
int Curl_conn_sockindex(struct Curl_easy *data, curl_socket_t sockfd)
|
||||
{
|
||||
if(data && data->conn &&
|
||||
sockfd != CURL_SOCKET_BAD && sockfd == data->conn->sock[SECONDARYSOCKET])
|
||||
return SECONDARYSOCKET;
|
||||
return FIRSTSOCKET;
|
||||
}
|
||||
|
||||
CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
|
||||
char *buf, size_t blen, ssize_t *n)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
ssize_t nread;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
|
||||
const void *buf, size_t blen,
|
||||
ssize_t *pnwritten)
|
||||
{
|
||||
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;
|
||||
#ifdef CURLDEBUG
|
||||
{
|
||||
/* Allow debug builds to override this logic to force short sends
|
||||
*/
|
||||
char *p = getenv("CURL_SMALLSENDS");
|
||||
if(p) {
|
||||
size_t altsize = (size_t)strtoul(p, NULL, 10);
|
||||
if(altsize)
|
||||
blen = CURLMIN(blen, altsize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nwritten = conn->send[sockindex](data, sockindex, buf, blen, &result);
|
||||
DEBUGASSERT((nwritten >= 0) || result);
|
||||
*pnwritten = nwritten;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Curl_pollset_reset(struct Curl_easy *data,
|
||||
struct easy_pollset *ps)
|
||||
|
|
|
@ -405,7 +405,7 @@ void Curl_conn_adjust_pollset(struct Curl_easy *data,
|
|||
* actuel number of bytes copied or a negative value on error.
|
||||
* The error code is placed into `*code`.
|
||||
*/
|
||||
ssize_t Curl_conn_recv(struct Curl_easy *data, int sockindex, char *buf,
|
||||
ssize_t Curl_cf_recv(struct Curl_easy *data, int sockindex, char *buf,
|
||||
size_t len, CURLcode *code);
|
||||
|
||||
/**
|
||||
|
@ -414,7 +414,7 @@ ssize_t Curl_conn_recv(struct Curl_easy *data, int sockindex, char *buf,
|
|||
* or a negative value on error.
|
||||
* The error code is placed into `*code`.
|
||||
*/
|
||||
ssize_t Curl_conn_send(struct Curl_easy *data, int sockindex,
|
||||
ssize_t Curl_cf_send(struct Curl_easy *data, int sockindex,
|
||||
const void *buf, size_t len, CURLcode *code);
|
||||
|
||||
/**
|
||||
|
@ -497,6 +497,30 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
|
|||
int sockindex);
|
||||
|
||||
|
||||
/**
|
||||
* Get the index of the given socket in the connection's sockets.
|
||||
* Useful in calling `Curl_conn_send()/Curl_conn_recv()` with the
|
||||
* correct socket index.
|
||||
*/
|
||||
int Curl_conn_sockindex(struct Curl_easy *data, curl_socket_t sockfd);
|
||||
|
||||
/*
|
||||
* Receive data on the connection, using FIRSTSOCKET/SECONDARYSOCKET.
|
||||
* Will return CURLE_AGAIN iff blocked on receiving.
|
||||
*/
|
||||
CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
|
||||
char *buf, size_t buffersize,
|
||||
ssize_t *pnread);
|
||||
|
||||
/*
|
||||
* Send data on the connection, using FIRSTSOCKET/SECONDARYSOCKET.
|
||||
* Will return CURLE_AGAIN iff blocked on sending.
|
||||
*/
|
||||
CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
|
||||
const void *buf, size_t blen,
|
||||
ssize_t *pnwritten);
|
||||
|
||||
|
||||
void Curl_pollset_reset(struct Curl_easy *data,
|
||||
struct easy_pollset *ps);
|
||||
|
||||
|
|
|
@ -265,10 +265,10 @@ static CURLcode rtmp_do(struct Curl_easy *data, bool *done)
|
|||
|
||||
if(data->state.upload) {
|
||||
Curl_pgrsSetUploadSize(data, data->state.infilesize);
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
}
|
||||
else
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1);
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
|
23
lib/dict.c
23
lib/dict.c
|
@ -122,11 +122,10 @@ static char *unescape_word(const char *input)
|
|||
}
|
||||
|
||||
/* sendf() sends formatted data to the server */
|
||||
static CURLcode sendf(curl_socket_t sockfd, struct Curl_easy *data,
|
||||
const char *fmt, ...) CURL_PRINTF(3, 4);
|
||||
static CURLcode sendf(struct Curl_easy *data,
|
||||
const char *fmt, ...) CURL_PRINTF(2, 3);
|
||||
|
||||
static CURLcode sendf(curl_socket_t sockfd, struct Curl_easy *data,
|
||||
const char *fmt, ...)
|
||||
static CURLcode sendf(struct Curl_easy *data, const char *fmt, ...)
|
||||
{
|
||||
ssize_t bytes_written;
|
||||
size_t write_len;
|
||||
|
@ -146,7 +145,7 @@ static CURLcode sendf(curl_socket_t sockfd, struct Curl_easy *data,
|
|||
|
||||
for(;;) {
|
||||
/* Write the buffer to the socket */
|
||||
result = Curl_write(data, sockfd, sptr, write_len, &bytes_written);
|
||||
result = Curl_xfer_send(data, sptr, write_len, &bytes_written);
|
||||
|
||||
if(result)
|
||||
break;
|
||||
|
@ -178,8 +177,6 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
|
|||
char *nthdef = NULL; /* This is not part of the protocol, but required
|
||||
by RFC 2229 */
|
||||
CURLcode result;
|
||||
struct connectdata *conn = data->conn;
|
||||
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
|
||||
|
||||
char *path;
|
||||
|
||||
|
@ -228,7 +225,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
|
|||
goto error;
|
||||
}
|
||||
|
||||
result = sendf(sockfd, data,
|
||||
result = sendf(data,
|
||||
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
|
||||
"MATCH "
|
||||
"%s " /* database */
|
||||
|
@ -243,7 +240,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
|
|||
failf(data, "Failed sending DICT request");
|
||||
goto error;
|
||||
}
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); /* no upload */
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1); /* no upload */
|
||||
}
|
||||
else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
|
||||
strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
|
||||
|
@ -276,7 +273,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
|
|||
goto error;
|
||||
}
|
||||
|
||||
result = sendf(sockfd, data,
|
||||
result = sendf(data,
|
||||
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
|
||||
"DEFINE "
|
||||
"%s " /* database */
|
||||
|
@ -289,7 +286,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
|
|||
failf(data, "Failed sending DICT request");
|
||||
goto error;
|
||||
}
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1);
|
||||
}
|
||||
else {
|
||||
|
||||
|
@ -302,7 +299,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
|
|||
if(ppath[i] == ':')
|
||||
ppath[i] = ' ';
|
||||
}
|
||||
result = sendf(sockfd, data,
|
||||
result = sendf(data,
|
||||
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
|
||||
"%s\r\n"
|
||||
"QUIT\r\n", ppath);
|
||||
|
@ -311,7 +308,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
|
|||
goto error;
|
||||
}
|
||||
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
35
lib/easy.c
35
lib/easy.c
|
@ -1038,7 +1038,7 @@ fail:
|
|||
*/
|
||||
void curl_easy_reset(struct Curl_easy *data)
|
||||
{
|
||||
Curl_free_request_state(data);
|
||||
Curl_req_reset(&data->req, data);
|
||||
|
||||
/* zero out UserDefined data: */
|
||||
Curl_freeset(data);
|
||||
|
@ -1166,9 +1166,11 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
|||
}
|
||||
|
||||
|
||||
static CURLcode easy_connection(struct Curl_easy *data, curl_socket_t *sfd,
|
||||
static CURLcode easy_connection(struct Curl_easy *data,
|
||||
struct connectdata **connp)
|
||||
{
|
||||
curl_socket_t sfd;
|
||||
|
||||
if(!data)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
|
@ -1178,9 +1180,9 @@ static CURLcode easy_connection(struct Curl_easy *data, curl_socket_t *sfd,
|
|||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
}
|
||||
|
||||
*sfd = Curl_getconnectinfo(data, connp);
|
||||
sfd = Curl_getconnectinfo(data, connp);
|
||||
|
||||
if(*sfd == CURL_SOCKET_BAD) {
|
||||
if(sfd == CURL_SOCKET_BAD) {
|
||||
failf(data, "Failed to get recent socket");
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
}
|
||||
|
@ -1196,7 +1198,6 @@ static CURLcode easy_connection(struct Curl_easy *data, curl_socket_t *sfd,
|
|||
CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
|
||||
size_t *n)
|
||||
{
|
||||
curl_socket_t sfd;
|
||||
CURLcode result;
|
||||
ssize_t n1;
|
||||
struct connectdata *c;
|
||||
|
@ -1204,7 +1205,7 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
|
|||
if(Curl_is_in_callback(data))
|
||||
return CURLE_RECURSIVE_API_CALL;
|
||||
|
||||
result = easy_connection(data, &sfd, &c);
|
||||
result = easy_connection(data, &c);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -1214,7 +1215,7 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
|
|||
Curl_attach_connection(data, c);
|
||||
|
||||
*n = 0;
|
||||
result = Curl_read(data, sfd, buffer, buflen, &n1);
|
||||
result = Curl_conn_recv(data, FIRSTSOCKET, buffer, buflen, &n1);
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
@ -1226,11 +1227,10 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
|
|||
#ifdef USE_WEBSOCKETS
|
||||
CURLcode Curl_connect_only_attach(struct Curl_easy *data)
|
||||
{
|
||||
curl_socket_t sfd;
|
||||
CURLcode result;
|
||||
struct connectdata *c = NULL;
|
||||
|
||||
result = easy_connection(data, &sfd, &c);
|
||||
result = easy_connection(data, &c);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -1251,13 +1251,12 @@ CURLcode Curl_connect_only_attach(struct Curl_easy *data)
|
|||
CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
|
||||
size_t buflen, ssize_t *n)
|
||||
{
|
||||
curl_socket_t sfd;
|
||||
CURLcode result;
|
||||
ssize_t n1;
|
||||
struct connectdata *c = NULL;
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
result = easy_connection(data, &sfd, &c);
|
||||
*n = 0;
|
||||
result = easy_connection(data, &c);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -1266,20 +1265,12 @@ CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
|
|||
needs to be reattached */
|
||||
Curl_attach_connection(data, c);
|
||||
|
||||
*n = 0;
|
||||
sigpipe_ignore(data, &pipe_st);
|
||||
result = Curl_write(data, sfd, buffer, buflen, &n1);
|
||||
result = Curl_conn_send(data, FIRSTSOCKET, buffer, buflen, n);
|
||||
sigpipe_restore(&pipe_st);
|
||||
|
||||
if(n1 == -1)
|
||||
if(result && result != CURLE_AGAIN)
|
||||
return CURLE_SEND_ERROR;
|
||||
|
||||
/* detect EAGAIN */
|
||||
if(!result && !n1)
|
||||
return CURLE_AGAIN;
|
||||
|
||||
*n = n1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
23
lib/ftp.c
23
lib/ftp.c
|
@ -151,7 +151,7 @@ static CURLcode wc_statemach(struct Curl_easy *data);
|
|||
static void wc_data_dtor(void *ptr);
|
||||
static CURLcode ftp_state_retr(struct Curl_easy *data, curl_off_t filesize);
|
||||
static CURLcode ftp_readresp(struct Curl_easy *data,
|
||||
curl_socket_t sockfd,
|
||||
int sockindex,
|
||||
struct pingpong *pp,
|
||||
int *ftpcode,
|
||||
size_t *size);
|
||||
|
@ -581,11 +581,11 @@ static CURLcode InitiateTransfer(struct Curl_easy *data)
|
|||
/* set the SO_SNDBUF for the secondary socket for those who need it */
|
||||
Curl_sndbufset(conn->sock[SECONDARYSOCKET]);
|
||||
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, SECONDARYSOCKET);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, SECONDARYSOCKET);
|
||||
}
|
||||
else {
|
||||
/* FTP download: */
|
||||
Curl_setup_transfer(data, SECONDARYSOCKET,
|
||||
Curl_xfer_setup(data, SECONDARYSOCKET,
|
||||
conn->proto.ftpc.retr_size_saved, FALSE, -1);
|
||||
}
|
||||
|
||||
|
@ -664,13 +664,13 @@ static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
|
|||
}
|
||||
|
||||
static CURLcode ftp_readresp(struct Curl_easy *data,
|
||||
curl_socket_t sockfd,
|
||||
int sockindex,
|
||||
struct pingpong *pp,
|
||||
int *ftpcode, /* return the ftp-code if done */
|
||||
size_t *size) /* size of the response */
|
||||
{
|
||||
int code;
|
||||
CURLcode result = Curl_pp_readresp(data, sockfd, pp, &code, size);
|
||||
CURLcode result = Curl_pp_readresp(data, sockindex, pp, &code, size);
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
{
|
||||
|
@ -805,7 +805,7 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
|
|||
break;
|
||||
}
|
||||
}
|
||||
result = ftp_readresp(data, sockfd, pp, ftpcode, &nread);
|
||||
result = ftp_readresp(data, FIRSTSOCKET, pp, ftpcode, &nread);
|
||||
if(result)
|
||||
break;
|
||||
|
||||
|
@ -1725,7 +1725,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
|
|||
infof(data, "File already completely uploaded");
|
||||
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
|
||||
/* Set ->transfer so that we won't get any error in
|
||||
* ftp_done() because we didn't transfer anything! */
|
||||
|
@ -2396,7 +2396,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
|
|||
|
||||
if(ftp->downloadsize == 0) {
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
infof(data, "File already completely downloaded");
|
||||
|
||||
/* Set ->transfer so that we won't get any error in ftp_done()
|
||||
|
@ -2803,7 +2803,6 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
|
|||
struct connectdata *conn)
|
||||
{
|
||||
CURLcode result;
|
||||
curl_socket_t sock = conn->sock[FIRSTSOCKET];
|
||||
int ftpcode;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
struct pingpong *pp = &ftpc->pp;
|
||||
|
@ -2813,7 +2812,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
|
|||
if(pp->sendleft)
|
||||
return Curl_pp_flushsend(data, pp);
|
||||
|
||||
result = ftp_readresp(data, sock, pp, &ftpcode, &nread);
|
||||
result = ftp_readresp(data, FIRSTSOCKET, pp, &ftpcode, &nread);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -3813,7 +3812,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
|
|||
}
|
||||
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
|
||||
if(!ftpc->wait_data_conn) {
|
||||
/* no waiting for the data connection so this is now complete */
|
||||
|
@ -4415,7 +4414,7 @@ static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)
|
|||
|
||||
if(ftp->transfer != PPTRANSFER_BODY)
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
else if(!connected)
|
||||
/* since we didn't connect now, we want do_more to get called */
|
||||
conn->bits.do_more = TRUE;
|
||||
|
|
|
@ -185,7 +185,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
|
|||
if(strlen(sel) < 1)
|
||||
break;
|
||||
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, sel, k, &amount);
|
||||
result = Curl_xfer_send(data, sel, k, &amount);
|
||||
if(!result) { /* Which may not have written it all! */
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER, sel, amount);
|
||||
if(result)
|
||||
|
@ -227,7 +227,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
|
|||
free(sel_org);
|
||||
|
||||
if(!result)
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, "\r\n", 2, &amount);
|
||||
result = Curl_xfer_send(data, "\r\n", 2, &amount);
|
||||
if(result) {
|
||||
failf(data, "Failed sending Gopher request");
|
||||
return result;
|
||||
|
@ -236,7 +236,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
|
|||
if(result)
|
||||
return result;
|
||||
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1);
|
||||
return CURLE_OK;
|
||||
}
|
||||
#endif /* CURL_DISABLE_GOPHER */
|
||||
|
|
18
lib/http.c
18
lib/http.c
|
@ -1356,7 +1356,11 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
|
|||
sendsize = (size_t)data->set.upload_buffer_size;
|
||||
}
|
||||
|
||||
result = Curl_nwrite(data, sockindex, ptr, sendsize, &amount);
|
||||
result = Curl_conn_send(data, sockindex, ptr, sendsize, &amount);
|
||||
if(result == CURLE_AGAIN) {
|
||||
result = CURLE_OK;
|
||||
amount = 0;
|
||||
}
|
||||
|
||||
if(!result) {
|
||||
/*
|
||||
|
@ -2511,7 +2515,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
|
|||
failf(data, "Failed sending PUT request");
|
||||
else
|
||||
/* prepare for transfer */
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, TRUE,
|
||||
http->postsize?FIRSTSOCKET:-1);
|
||||
if(result)
|
||||
return result;
|
||||
|
@ -2534,7 +2538,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
|
|||
failf(data, "Failed sending POST request");
|
||||
else
|
||||
/* setup variables for the upcoming transfer */
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, TRUE, -1);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2592,7 +2596,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
|
|||
failf(data, "Failed sending POST request");
|
||||
else
|
||||
/* prepare for transfer */
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, TRUE,
|
||||
http->postsize?FIRSTSOCKET:-1);
|
||||
if(result)
|
||||
return result;
|
||||
|
@ -2735,7 +2739,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
|
|||
if(result)
|
||||
failf(data, "Failed sending HTTP POST request");
|
||||
else
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, TRUE,
|
||||
http->postdata?FIRSTSOCKET:-1);
|
||||
break;
|
||||
|
||||
|
@ -2755,11 +2759,11 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
|
|||
!(data->set.connect_only))
|
||||
/* Set up the transfer for two-way since without CONNECT_ONLY set, this
|
||||
request probably wants to send data too post upgrade */
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, FIRSTSOCKET);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, TRUE, FIRSTSOCKET);
|
||||
#endif
|
||||
else
|
||||
/* HTTP GET/HEAD download: */
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, TRUE, -1);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
11
lib/imap.c
11
lib/imap.c
|
@ -1213,14 +1213,14 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
|
|||
|
||||
if(data->req.bytecount == size)
|
||||
/* The entire data is already transferred! */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
else {
|
||||
/* IMAP download */
|
||||
data->req.maxdownload = size;
|
||||
/* force a recv/send check of this connection, as the data might've been
|
||||
read off the socket already */
|
||||
data->state.select_bits = CURL_CSELECT_IN;
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, size, FALSE, -1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1268,7 +1268,7 @@ static CURLcode imap_state_append_resp(struct Curl_easy *data, int imapcode,
|
|||
Curl_pgrsSetUploadSize(data, data->state.infilesize);
|
||||
|
||||
/* IMAP upload */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
|
||||
/* End of DO phase */
|
||||
imap_state(data, IMAP_STOP);
|
||||
|
@ -1299,7 +1299,6 @@ static CURLcode imap_statemachine(struct Curl_easy *data,
|
|||
struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
curl_socket_t sock = conn->sock[FIRSTSOCKET];
|
||||
int imapcode;
|
||||
struct imap_conn *imapc = &conn->proto.imapc;
|
||||
struct pingpong *pp = &imapc->pp;
|
||||
|
@ -1316,7 +1315,7 @@ static CURLcode imap_statemachine(struct Curl_easy *data,
|
|||
|
||||
do {
|
||||
/* Read the response from the server */
|
||||
result = Curl_pp_readresp(data, sock, pp, &imapcode, &nread);
|
||||
result = Curl_pp_readresp(data, FIRSTSOCKET, pp, &imapcode, &nread);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -1694,7 +1693,7 @@ static CURLcode imap_dophase_done(struct Curl_easy *data, bool connected)
|
|||
|
||||
if(imap->transfer != PPTRANSFER_BODY)
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
|
17
lib/krb5.c
17
lib/krb5.c
|
@ -52,6 +52,7 @@
|
|||
#include "ftp.h"
|
||||
#include "curl_gssapi.h"
|
||||
#include "sendf.h"
|
||||
#include "transfer.h"
|
||||
#include "curl_krb5.h"
|
||||
#include "warnless.h"
|
||||
#include "strcase.h"
|
||||
|
@ -90,8 +91,7 @@ static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
|
|||
#ifdef HAVE_GSSAPI
|
||||
conn->data_prot = PROT_CMD;
|
||||
#endif
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, sptr, write_len,
|
||||
&bytes_written);
|
||||
result = Curl_xfer_send(data, sptr, write_len, &bytes_written);
|
||||
#ifdef HAVE_GSSAPI
|
||||
DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
|
||||
conn->data_prot = data_sec;
|
||||
|
@ -470,7 +470,7 @@ socket_read(struct Curl_easy *data, int sockindex, void *to, size_t len)
|
|||
ssize_t nread = 0;
|
||||
|
||||
while(len > 0) {
|
||||
nread = Curl_conn_recv(data, sockindex, to_p, len, &result);
|
||||
result = Curl_conn_recv(data, sockindex, to_p, len, &nread);
|
||||
if(nread > 0) {
|
||||
len -= nread;
|
||||
to_p += nread;
|
||||
|
@ -497,8 +497,8 @@ socket_write(struct Curl_easy *data, int sockindex, const void *to,
|
|||
ssize_t written;
|
||||
|
||||
while(len > 0) {
|
||||
written = Curl_conn_send(data, sockindex, to_p, len, &result);
|
||||
if(written > 0) {
|
||||
result = Curl_conn_send(data, sockindex, to_p, len, &written);
|
||||
if(!result && written > 0) {
|
||||
len -= written;
|
||||
to_p += written;
|
||||
}
|
||||
|
@ -567,8 +567,11 @@ static ssize_t sec_recv(struct Curl_easy *data, int sockindex,
|
|||
*err = CURLE_OK;
|
||||
|
||||
/* Handle clear text response. */
|
||||
if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR)
|
||||
return Curl_conn_recv(data, sockindex, buffer, len, err);
|
||||
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->in_buffer.eof_flag) {
|
||||
conn->in_buffer.eof_flag = 0;
|
||||
|
|
|
@ -749,7 +749,7 @@ quit:
|
|||
FREE_ON_WINLDAP(host);
|
||||
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
connclose(conn, "LDAP connection always disable reuse");
|
||||
|
||||
return result;
|
||||
|
|
13
lib/mqtt.c
13
lib/mqtt.c
|
@ -120,7 +120,7 @@ static CURLcode mqtt_send(struct Curl_easy *data,
|
|||
CURLcode result = CURLE_OK;
|
||||
struct MQTT *mq = data->req.p.mqtt;
|
||||
ssize_t n;
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, buf, len, &n);
|
||||
result = Curl_xfer_send(data, buf, len, &n);
|
||||
if(result)
|
||||
return result;
|
||||
Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n);
|
||||
|
@ -366,8 +366,7 @@ static CURLcode mqtt_recv_atleast(struct Curl_easy *data, size_t nbytes)
|
|||
ssize_t nread;
|
||||
|
||||
DEBUGASSERT(nbytes - rlen < sizeof(readbuf));
|
||||
result = Curl_read(data, data->conn->sock[FIRSTSOCKET],
|
||||
(char *)readbuf, nbytes - rlen, &nread);
|
||||
result = Curl_xfer_recv(data, (char *)readbuf, nbytes - rlen, &nread);
|
||||
if(result)
|
||||
return result;
|
||||
DEBUGASSERT(nread >= 0);
|
||||
|
@ -622,7 +621,6 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
|
|||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn = data->conn;
|
||||
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
|
||||
ssize_t nread;
|
||||
size_t remlen;
|
||||
struct mqtt_conn *mqtt = &conn->proto.mqtt;
|
||||
|
@ -679,7 +677,7 @@ MQTT_SUBACK_COMING:
|
|||
size_t rest = mq->npacket;
|
||||
if(rest > sizeof(buffer))
|
||||
rest = sizeof(buffer);
|
||||
result = Curl_read(data, sockfd, buffer, rest, &nread);
|
||||
result = Curl_xfer_recv(data, buffer, rest, &nread);
|
||||
if(result) {
|
||||
if(CURLE_AGAIN == result) {
|
||||
infof(data, "EEEE AAAAGAIN");
|
||||
|
@ -744,7 +742,6 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
|
|||
struct mqtt_conn *mqtt = &conn->proto.mqtt;
|
||||
struct MQTT *mq = data->req.p.mqtt;
|
||||
ssize_t nread;
|
||||
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
|
||||
unsigned char byte;
|
||||
|
||||
*done = FALSE;
|
||||
|
@ -762,7 +759,7 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
|
|||
switch(mqtt->state) {
|
||||
case MQTT_FIRST:
|
||||
/* Read the initial byte only */
|
||||
result = Curl_read(data, sockfd, (char *)&mq->firstbyte, 1, &nread);
|
||||
result = Curl_xfer_recv(data, (char *)&mq->firstbyte, 1, &nread);
|
||||
if(result)
|
||||
break;
|
||||
else if(!nread) {
|
||||
|
@ -778,7 +775,7 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
|
|||
FALLTHROUGH();
|
||||
case MQTT_REMAINING_LENGTH:
|
||||
do {
|
||||
result = Curl_read(data, sockfd, (char *)&byte, 1, &nread);
|
||||
result = Curl_xfer_recv(data, (char *)&byte, 1, &nread);
|
||||
if(!nread)
|
||||
break;
|
||||
Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1);
|
||||
|
|
|
@ -706,9 +706,10 @@ static CURLcode multi_done(struct Curl_easy *data,
|
|||
|
||||
process_pending_handles(data->multi); /* connection / multiplex */
|
||||
|
||||
Curl_safefree(data->state.ulbuf);
|
||||
if(!result)
|
||||
result = Curl_req_done(&data->req, data, premature);
|
||||
|
||||
Curl_client_cleanup(data);
|
||||
Curl_safefree(data->state.ulbuf);
|
||||
|
||||
CONNCACHE_LOCK(data);
|
||||
Curl_detach_connection(data);
|
||||
|
@ -1007,7 +1008,7 @@ static int connecting_getsock(struct Curl_easy *data, curl_socket_t *socks)
|
|||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
(void)socks;
|
||||
/* Not using `conn->sockfd` as `Curl_setup_transfer()` initializes
|
||||
/* Not using `conn->sockfd` as `Curl_xfer_setup()` initializes
|
||||
* that *after* the connect. */
|
||||
if(conn && conn->sock[FIRSTSOCKET] != CURL_SOCKET_BAD) {
|
||||
/* Default is to wait to something from the server */
|
||||
|
|
|
@ -916,7 +916,7 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done)
|
|||
else {
|
||||
lr->msgid = msgid;
|
||||
data->req.p.ldap = lr;
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1);
|
||||
*done = TRUE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -199,8 +199,11 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data,
|
|||
#ifdef HAVE_GSSAPI
|
||||
conn->data_prot = PROT_CMD;
|
||||
#endif
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, s, write_len, &bytes_written);
|
||||
if(result)
|
||||
result = Curl_conn_send(data, FIRSTSOCKET, s, write_len, &bytes_written);
|
||||
if(result == CURLE_AGAIN) {
|
||||
bytes_written = 0;
|
||||
}
|
||||
else if(result)
|
||||
return result;
|
||||
#ifdef HAVE_GSSAPI
|
||||
data_sec = conn->data_prot;
|
||||
|
@ -251,7 +254,7 @@ CURLcode Curl_pp_sendf(struct Curl_easy *data, struct pingpong *pp,
|
|||
}
|
||||
|
||||
static CURLcode pingpong_read(struct Curl_easy *data,
|
||||
curl_socket_t sockfd,
|
||||
int sockindex,
|
||||
char *buffer,
|
||||
size_t buflen,
|
||||
ssize_t *nread)
|
||||
|
@ -261,7 +264,7 @@ static CURLcode pingpong_read(struct Curl_easy *data,
|
|||
enum protection_level prot = data->conn->data_prot;
|
||||
data->conn->data_prot = PROT_CLEAR;
|
||||
#endif
|
||||
result = Curl_read(data, sockfd, buffer, buflen, nread);
|
||||
result = Curl_conn_recv(data, sockindex, buffer, buflen, nread);
|
||||
#ifdef HAVE_GSSAPI
|
||||
DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST);
|
||||
data->conn->data_prot = (unsigned char)prot;
|
||||
|
@ -275,7 +278,7 @@ static CURLcode pingpong_read(struct Curl_easy *data,
|
|||
* Reads a piece of a server response.
|
||||
*/
|
||||
CURLcode Curl_pp_readresp(struct Curl_easy *data,
|
||||
curl_socket_t sockfd,
|
||||
int sockindex,
|
||||
struct pingpong *pp,
|
||||
int *code, /* return the server code if done */
|
||||
size_t *size) /* size of the response */
|
||||
|
@ -300,7 +303,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
|
|||
ssize_t gotbytes = 0;
|
||||
char buffer[900];
|
||||
|
||||
result = pingpong_read(data, sockfd, buffer, sizeof(buffer), &gotbytes);
|
||||
result = pingpong_read(data, sockindex, buffer, sizeof(buffer), &gotbytes);
|
||||
if(result == CURLE_AGAIN)
|
||||
return CURLE_OK;
|
||||
|
||||
|
@ -396,9 +399,15 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data,
|
|||
{
|
||||
/* we have a piece of a command still left to send */
|
||||
ssize_t written;
|
||||
CURLcode result = Curl_nwrite(data, FIRSTSOCKET,
|
||||
CURLcode result;
|
||||
|
||||
result = Curl_conn_send(data, FIRSTSOCKET,
|
||||
pp->sendthis + pp->sendsize - pp->sendleft,
|
||||
pp->sendleft, &written);
|
||||
if(result == CURLE_AGAIN) {
|
||||
result = CURLE_OK;
|
||||
written = 0;
|
||||
}
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data,
|
|||
* Reads a piece of a server response.
|
||||
*/
|
||||
CURLcode Curl_pp_readresp(struct Curl_easy *data,
|
||||
curl_socket_t sockfd,
|
||||
int sockindex,
|
||||
struct pingpong *pp,
|
||||
int *code, /* return the server code if done */
|
||||
size_t *size); /* size of the response */
|
||||
|
|
|
@ -934,7 +934,7 @@ static CURLcode pop3_state_command_resp(struct Curl_easy *data,
|
|||
|
||||
if(pop3->transfer == PPTRANSFER_BODY) {
|
||||
/* POP3 download */
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1);
|
||||
|
||||
if(pp->overflow) {
|
||||
/* The recv buffer contains data that is actually body content so send
|
||||
|
@ -970,7 +970,6 @@ static CURLcode pop3_statemachine(struct Curl_easy *data,
|
|||
struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
curl_socket_t sock = conn->sock[FIRSTSOCKET];
|
||||
int pop3code;
|
||||
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||
struct pingpong *pp = &pop3c->pp;
|
||||
|
@ -987,7 +986,7 @@ static CURLcode pop3_statemachine(struct Curl_easy *data,
|
|||
|
||||
do {
|
||||
/* Read the response from the server */
|
||||
result = Curl_pp_readresp(data, sock, pp, &pop3code, &nread);
|
||||
result = Curl_pp_readresp(data, FIRSTSOCKET, pp, &pop3code, &nread);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
|
108
lib/request.c
Normal file
108
lib/request.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include "urldata.h"
|
||||
#include "dynbuf.h"
|
||||
#include "doh.h"
|
||||
#include "request.h"
|
||||
#include "sendf.h"
|
||||
#include "url.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
CURLcode Curl_req_init(struct SingleRequest *req)
|
||||
{
|
||||
memset(req, 0, sizeof(*req));
|
||||
Curl_bufq_init2(&req->sendbuf, UPLOADBUFFER_DEFAULT, 1,
|
||||
BUFQ_OPT_SOFT_LIMIT);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_req_start(struct SingleRequest *req,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
req->start = Curl_now();
|
||||
Curl_cw_reset(data);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_req_done(struct SingleRequest *req,
|
||||
struct Curl_easy *data, bool aborted)
|
||||
{
|
||||
(void)req;
|
||||
/* TODO: add flush handling for client output */
|
||||
(void)aborted;
|
||||
Curl_cw_reset(data);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
void Curl_req_reset(struct SingleRequest *req, struct Curl_easy *data)
|
||||
{
|
||||
/* This is a bit ugly. `req->p` is a union and we assume we can
|
||||
* free this safely without leaks. */
|
||||
Curl_safefree(req->p.http);
|
||||
Curl_safefree(req->newurl);
|
||||
Curl_cw_reset(data);
|
||||
|
||||
Curl_bufq_reset(&req->sendbuf);
|
||||
if(data->set.upload_buffer_size != req->sendbuf.chunk_size) {
|
||||
Curl_bufq_free(&req->sendbuf);
|
||||
Curl_bufq_init2(&req->sendbuf, data->set.upload_buffer_size, 1,
|
||||
BUFQ_OPT_SOFT_LIMIT);
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_DOH
|
||||
if(req->doh) {
|
||||
Curl_close(&req->doh->probe[0].easy);
|
||||
Curl_close(&req->doh->probe[1].easy);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Curl_req_free(struct SingleRequest *req, struct Curl_easy *data)
|
||||
{
|
||||
/* This is a bit ugly. `req->p` is a union and we assume we can
|
||||
* free this safely without leaks. */
|
||||
Curl_safefree(req->p.http);
|
||||
Curl_safefree(req->newurl);
|
||||
Curl_bufq_free(&req->sendbuf);
|
||||
Curl_cw_reset(data);
|
||||
|
||||
#ifndef CURL_DISABLE_DOH
|
||||
if(req->doh) {
|
||||
Curl_close(&req->doh->probe[0].easy);
|
||||
Curl_close(&req->doh->probe[1].easy);
|
||||
Curl_dyn_free(&req->doh->probe[0].serverdoh);
|
||||
Curl_dyn_free(&req->doh->probe[1].serverdoh);
|
||||
curl_slist_free_all(req->doh->headers);
|
||||
Curl_safefree(req->doh);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
192
lib/request.h
Normal file
192
lib/request.h
Normal file
|
@ -0,0 +1,192 @@
|
|||
#ifndef HEADER_CURL_REQUEST_H
|
||||
#define HEADER_CURL_REQUEST_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* This file is for lib internal stuff */
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include "bufq.h"
|
||||
|
||||
/* forward declarations */
|
||||
struct UserDefined;
|
||||
|
||||
enum expect100 {
|
||||
EXP100_SEND_DATA, /* enough waiting, just send the body now */
|
||||
EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */
|
||||
EXP100_SENDING_REQUEST, /* still sending the request but will wait for
|
||||
the 100 header once done with the request */
|
||||
EXP100_FAILED /* used on 417 Expectation Failed */
|
||||
};
|
||||
|
||||
enum upgrade101 {
|
||||
UPGR101_INIT, /* default state */
|
||||
UPGR101_WS, /* upgrade to WebSockets requested */
|
||||
UPGR101_H2, /* upgrade to HTTP/2 requested */
|
||||
UPGR101_RECEIVED, /* 101 response received */
|
||||
UPGR101_WORKING /* talking upgraded protocol */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Request specific data in the easy handle (Curl_easy). Previously,
|
||||
* these members were on the connectdata struct but since a conn struct may
|
||||
* now be shared between different Curl_easys, we store connection-specific
|
||||
* data here. This struct only keeps stuff that's interesting for *this*
|
||||
* request, as it will be cleared between multiple ones
|
||||
*/
|
||||
struct SingleRequest {
|
||||
curl_off_t size; /* -1 if unknown at this point */
|
||||
curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch,
|
||||
-1 means unlimited */
|
||||
curl_off_t bytecount; /* total number of bytes read */
|
||||
curl_off_t writebytecount; /* number of bytes written */
|
||||
|
||||
curl_off_t pendingheader; /* this many bytes left to send is actually
|
||||
header and not body */
|
||||
struct curltime start; /* transfer started at this time */
|
||||
unsigned int headerbytecount; /* received server headers (not CONNECT
|
||||
headers) */
|
||||
unsigned int allheadercount; /* all received headers (server + CONNECT) */
|
||||
unsigned int deductheadercount; /* this amount of bytes doesn't count when
|
||||
we check if anything has been transferred
|
||||
at the end of a connection. We use this
|
||||
counter to make only a 100 reply (without
|
||||
a following second response code) result
|
||||
in a CURLE_GOT_NOTHING error code */
|
||||
int headerline; /* counts header lines to better track the
|
||||
first one */
|
||||
curl_off_t offset; /* possible resume offset read from the
|
||||
Content-Range: header */
|
||||
int httpcode; /* error code from the 'HTTP/1.? XXX' or
|
||||
'RTSP/1.? XXX' line */
|
||||
int keepon;
|
||||
struct curltime start100; /* time stamp to wait for the 100 code from */
|
||||
enum expect100 exp100; /* expect 100 continue state */
|
||||
enum upgrade101 upgr101; /* 101 upgrade state */
|
||||
|
||||
/* Client Writer stack, handles trasnfer- and content-encodings, protocol
|
||||
* checks, pausing by client callbacks. */
|
||||
struct Curl_cwriter *writer_stack;
|
||||
struct bufq sendbuf; /* data which needs to be send to the server */
|
||||
time_t timeofdoc;
|
||||
long bodywrites;
|
||||
char *location; /* This points to an allocated version of the Location:
|
||||
header data */
|
||||
char *newurl; /* Set to the new URL to use when a redirect or a retry is
|
||||
wanted */
|
||||
|
||||
/* 'upload_present' is used to keep a byte counter of how much data there is
|
||||
still left in the buffer, aimed for upload. */
|
||||
ssize_t upload_present;
|
||||
|
||||
/* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a
|
||||
buffer, so the next read should read from where this pointer points to,
|
||||
and the 'upload_present' contains the number of bytes available at this
|
||||
position */
|
||||
char *upload_fromhere;
|
||||
|
||||
/* Allocated protocol-specific data. Each protocol handler makes sure this
|
||||
points to data it needs. */
|
||||
union {
|
||||
struct FILEPROTO *file;
|
||||
struct FTP *ftp;
|
||||
struct HTTP *http;
|
||||
struct IMAP *imap;
|
||||
struct ldapreqinfo *ldap;
|
||||
struct MQTT *mqtt;
|
||||
struct POP3 *pop3;
|
||||
struct RTSP *rtsp;
|
||||
struct smb_request *smb;
|
||||
struct SMTP *smtp;
|
||||
struct SSHPROTO *ssh;
|
||||
struct TELNET *telnet;
|
||||
} p;
|
||||
#ifndef CURL_DISABLE_DOH
|
||||
struct dohdata *doh; /* DoH specific data for this request */
|
||||
#endif
|
||||
char fread_eof[2]; /* the body read callback (index 0) returned EOF or
|
||||
the trailer read callback (index 1) returned EOF */
|
||||
#ifndef CURL_DISABLE_COOKIES
|
||||
unsigned char setcookies;
|
||||
#endif
|
||||
BIT(header); /* incoming data has HTTP header */
|
||||
BIT(content_range); /* set TRUE if Content-Range: was found */
|
||||
BIT(download_done); /* set to TRUE when download is complete */
|
||||
BIT(eos_written); /* iff EOS has been written to client */
|
||||
BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding
|
||||
upload and we're uploading the last chunk */
|
||||
BIT(ignorebody); /* we read a response-body but we ignore it! */
|
||||
BIT(http_bodyless); /* HTTP response status code is between 100 and 199,
|
||||
204 or 304 */
|
||||
BIT(chunk); /* if set, this is a chunked transfer-encoding */
|
||||
BIT(ignore_cl); /* ignore content-length */
|
||||
BIT(upload_chunky); /* set TRUE if we are doing chunked transfer-encoding
|
||||
on upload */
|
||||
BIT(getheader); /* TRUE if header parsing is wanted */
|
||||
BIT(forbidchunk); /* used only to explicitly forbid chunk-upload for
|
||||
specific upload buffers. See readmoredata() in http.c
|
||||
for details. */
|
||||
BIT(no_body); /* the response has no body */
|
||||
BIT(authneg); /* TRUE when the auth phase has started, which means
|
||||
that we are creating a request with an auth header,
|
||||
but it is not the final request in the auth
|
||||
negotiation. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the state of the request for first use.
|
||||
*/
|
||||
CURLcode Curl_req_init(struct SingleRequest *req);
|
||||
|
||||
/**
|
||||
* The request is about to start.
|
||||
*/
|
||||
CURLcode Curl_req_start(struct SingleRequest *req,
|
||||
struct Curl_easy *data);
|
||||
|
||||
/**
|
||||
* The request is done. If not aborted, make sure that buffers are
|
||||
* flushed to the client.
|
||||
* @param req the request
|
||||
* @param data the transfer
|
||||
* @param aborted TRUE iff the request was aborted/errored
|
||||
*/
|
||||
CURLcode Curl_req_done(struct SingleRequest *req,
|
||||
struct Curl_easy *data, bool aborted);
|
||||
|
||||
/**
|
||||
* Free the state of the request, not usable afterwards.
|
||||
*/
|
||||
void Curl_req_free(struct SingleRequest *req, struct Curl_easy *data);
|
||||
|
||||
/**
|
||||
* Reset the state of the request for new use, given the
|
||||
* settings.
|
||||
*/
|
||||
void Curl_req_reset(struct SingleRequest *req, struct Curl_easy *data);
|
||||
|
||||
|
||||
#endif /* HEADER_CURL_REQUEST_H */
|
|
@ -310,7 +310,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
|
|||
}
|
||||
|
||||
if(rtspreq == RTSPREQ_RECEIVE) {
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, TRUE, -1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -573,7 +573,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
|
|||
return result;
|
||||
}
|
||||
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, putsize?FIRSTSOCKET:-1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, -1, TRUE, putsize?FIRSTSOCKET:-1);
|
||||
|
||||
/* Increment the CSeq on success */
|
||||
data->state.rtsp_next_client_CSeq++;
|
||||
|
|
112
lib/sendf.c
112
lib/sendf.c
|
@ -61,79 +61,6 @@
|
|||
|
||||
static CURLcode do_init_stack(struct Curl_easy *data);
|
||||
|
||||
/*
|
||||
* Curl_nwrite() is an internal write function that sends data to the
|
||||
* server. Works with a socket index for the connection.
|
||||
*
|
||||
* If the write would block (CURLE_AGAIN), it returns CURLE_OK and
|
||||
* (*nwritten == 0). Otherwise we return regular CURLcode value.
|
||||
*/
|
||||
CURLcode Curl_nwrite(struct Curl_easy *data,
|
||||
int sockindex,
|
||||
const void *buf,
|
||||
size_t blen,
|
||||
ssize_t *pnwritten)
|
||||
{
|
||||
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;
|
||||
#ifdef CURLDEBUG
|
||||
{
|
||||
/* Allow debug builds to override this logic to force short sends
|
||||
*/
|
||||
char *p = getenv("CURL_SMALLSENDS");
|
||||
if(p) {
|
||||
size_t altsize = (size_t)strtoul(p, NULL, 10);
|
||||
if(altsize)
|
||||
blen = CURLMIN(blen, altsize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nwritten = conn->send[sockindex](data, sockindex, buf, blen, &result);
|
||||
if(result == CURLE_AGAIN) {
|
||||
nwritten = 0;
|
||||
result = CURLE_OK;
|
||||
}
|
||||
else if(result) {
|
||||
nwritten = -1; /* make sure */
|
||||
}
|
||||
else {
|
||||
DEBUGASSERT(nwritten >= 0);
|
||||
}
|
||||
|
||||
*pnwritten = nwritten;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_write() is an internal write function that sends data to the
|
||||
* server. Works with plain sockets, SCP, SSL or kerberos.
|
||||
*
|
||||
* If the write would block (CURLE_AGAIN), we return CURLE_OK and
|
||||
* (*written == 0). Otherwise we return regular CURLcode value.
|
||||
*/
|
||||
CURLcode Curl_write(struct Curl_easy *data,
|
||||
curl_socket_t sockfd,
|
||||
const void *mem,
|
||||
size_t len,
|
||||
ssize_t *written)
|
||||
{
|
||||
struct connectdata *conn;
|
||||
int num;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(data->conn);
|
||||
conn = data->conn;
|
||||
num = (sockfd != CURL_SOCKET_BAD && sockfd == conn->sock[SECONDARYSOCKET]);
|
||||
return Curl_nwrite(data, num, mem, len, written);
|
||||
}
|
||||
|
||||
/* Curl_client_write() sends data to the write callback(s)
|
||||
|
||||
The bit pattern defines to what "streams" to write to. Body and/or header.
|
||||
|
@ -163,7 +90,7 @@ CURLcode Curl_client_write(struct Curl_easy *data,
|
|||
return Curl_cwriter_write(data, data->req.writer_stack, type, buf, blen);
|
||||
}
|
||||
|
||||
void Curl_client_cleanup(struct Curl_easy *data)
|
||||
void Curl_cw_reset(struct Curl_easy *data)
|
||||
{
|
||||
struct Curl_cwriter *writer = data->req.writer_stack;
|
||||
|
||||
|
@ -499,40 +426,3 @@ void Curl_cwriter_remove_by_name(struct Curl_easy *data,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal read-from-socket function. This is meant to deal with plain
|
||||
* sockets, SSL sockets and kerberos sockets.
|
||||
*
|
||||
* Returns a regular CURLcode value.
|
||||
*/
|
||||
CURLcode Curl_read(struct Curl_easy *data, /* transfer */
|
||||
curl_socket_t sockfd, /* read from this socket */
|
||||
char *buf, /* store read data here */
|
||||
size_t sizerequested, /* max amount to read */
|
||||
ssize_t *n) /* amount bytes read */
|
||||
{
|
||||
CURLcode result = CURLE_RECV_ERROR;
|
||||
ssize_t nread = 0;
|
||||
size_t bytesfromsocket = 0;
|
||||
char *buffertofill = NULL;
|
||||
struct connectdata *conn = data->conn;
|
||||
|
||||
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
|
||||
If it is the second socket, we set num to 1. Otherwise to 0. This lets
|
||||
us use the correct ssl handle. */
|
||||
int num = (sockfd == conn->sock[SECONDARYSOCKET]);
|
||||
|
||||
*n = 0; /* reset amount to zero */
|
||||
|
||||
bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
|
||||
buffertofill = buf;
|
||||
|
||||
nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result);
|
||||
if(nread < 0)
|
||||
goto out;
|
||||
|
||||
*n += nread;
|
||||
result = CURLE_OK;
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
|
20
lib/sendf.h
20
lib/sendf.h
|
@ -61,7 +61,7 @@ CURLcode Curl_client_write(struct Curl_easy *data, int type, const char *ptr,
|
|||
/**
|
||||
* Free all resources related to client writing.
|
||||
*/
|
||||
void Curl_client_cleanup(struct Curl_easy *data);
|
||||
void Curl_cw_reset(struct Curl_easy *data);
|
||||
|
||||
/**
|
||||
* Client Writers - a chain passing transfer BODY data to the client.
|
||||
|
@ -175,22 +175,4 @@ void Curl_cwriter_def_close(struct Curl_easy *data,
|
|||
struct Curl_cwriter *writer);
|
||||
|
||||
|
||||
/* internal read-function, does plain socket, SSL and krb4 */
|
||||
CURLcode Curl_read(struct Curl_easy *data, curl_socket_t sockfd,
|
||||
char *buf, size_t buffersize,
|
||||
ssize_t *n);
|
||||
|
||||
/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */
|
||||
CURLcode Curl_write(struct Curl_easy *data,
|
||||
curl_socket_t sockfd,
|
||||
const void *mem, size_t len,
|
||||
ssize_t *written);
|
||||
|
||||
/* internal write-function, using sockindex for connection destination */
|
||||
CURLcode Curl_nwrite(struct Curl_easy *data,
|
||||
int sockindex,
|
||||
const void *buf,
|
||||
size_t blen,
|
||||
ssize_t *pnwritten);
|
||||
|
||||
#endif /* HEADER_CURL_SENDF_H */
|
||||
|
|
11
lib/smb.c
11
lib/smb.c
|
@ -485,7 +485,6 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done)
|
|||
static CURLcode smb_recv_message(struct Curl_easy *data, void **msg)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
|
||||
struct smb_conn *smbc = &conn->proto.smbc;
|
||||
char *buf = smbc->recv_buf;
|
||||
ssize_t bytes_read;
|
||||
|
@ -494,7 +493,7 @@ static CURLcode smb_recv_message(struct Curl_easy *data, void **msg)
|
|||
size_t len = MAX_MESSAGE_SIZE - smbc->got;
|
||||
CURLcode result;
|
||||
|
||||
result = Curl_read(data, sockfd, buf + smbc->got, len, &bytes_read);
|
||||
result = Curl_xfer_recv(data, buf + smbc->got, len, &bytes_read);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -568,8 +567,7 @@ static CURLcode smb_send(struct Curl_easy *data, ssize_t len,
|
|||
ssize_t bytes_written;
|
||||
CURLcode result;
|
||||
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, data->state.ulbuf,
|
||||
len, &bytes_written);
|
||||
result = Curl_xfer_send(data, data->state.ulbuf, len, &bytes_written);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -594,9 +592,8 @@ static CURLcode smb_flush(struct Curl_easy *data)
|
|||
if(!smbc->send_size)
|
||||
return CURLE_OK;
|
||||
|
||||
result = Curl_nwrite(data, FIRSTSOCKET,
|
||||
data->state.ulbuf + smbc->sent,
|
||||
len, &bytes_written);
|
||||
result = Curl_xfer_send(data, data->state.ulbuf + smbc->sent, len,
|
||||
&bytes_written);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
|
|
@ -1164,7 +1164,7 @@ static CURLcode smtp_state_data_resp(struct Curl_easy *data, int smtpcode,
|
|||
Curl_pgrsSetUploadSize(data, data->state.infilesize);
|
||||
|
||||
/* SMTP upload */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
|
||||
/* End of DO phase */
|
||||
smtp_state(data, SMTP_STOP);
|
||||
|
@ -1196,7 +1196,6 @@ static CURLcode smtp_statemachine(struct Curl_easy *data,
|
|||
struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
curl_socket_t sock = conn->sock[FIRSTSOCKET];
|
||||
int smtpcode;
|
||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||
struct pingpong *pp = &smtpc->pp;
|
||||
|
@ -1212,7 +1211,7 @@ static CURLcode smtp_statemachine(struct Curl_easy *data,
|
|||
|
||||
do {
|
||||
/* Read the response from the server */
|
||||
result = Curl_pp_readresp(data, sock, pp, &smtpcode, &nread);
|
||||
result = Curl_pp_readresp(data, FIRSTSOCKET, pp, &smtpcode, &nread);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -1434,7 +1433,7 @@ static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
|
|||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Send the end of block data */
|
||||
result = Curl_write(data, conn->writesockfd, eob, len, &bytes_written);
|
||||
result = Curl_xfer_send(data, eob, len, &bytes_written);
|
||||
if(result) {
|
||||
free(eob);
|
||||
return result;
|
||||
|
@ -1595,7 +1594,7 @@ static CURLcode smtp_dophase_done(struct Curl_easy *data, bool connected)
|
|||
|
||||
if(smtp->transfer != PPTRANSFER_BODY)
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
|
|
@ -1270,7 +1270,7 @@ static CURLcode send_telnet_data(struct Curl_easy *data,
|
|||
break;
|
||||
default: /* write! */
|
||||
bytes_written = 0;
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, outbuf + total_written,
|
||||
result = Curl_xfer_send(data, outbuf + total_written,
|
||||
outlen - total_written, &bytes_written);
|
||||
total_written += bytes_written;
|
||||
break;
|
||||
|
@ -1464,7 +1464,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
|
|||
}
|
||||
if(events.lNetworkEvents & FD_READ) {
|
||||
/* read data from network */
|
||||
result = Curl_read(data, sockfd, buffer, sizeof(buffer), &nread);
|
||||
result = Curl_xfer_recv(data, buffer, sizeof(buffer), &nread);
|
||||
/* read would've blocked. Loop again */
|
||||
if(result == CURLE_AGAIN)
|
||||
break;
|
||||
|
@ -1545,7 +1545,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
|
|||
default: /* read! */
|
||||
if(pfd[0].revents & POLLIN) {
|
||||
/* read data from network */
|
||||
result = Curl_read(data, sockfd, buffer, sizeof(buffer), &nread);
|
||||
result = Curl_xfer_recv(data, buffer, sizeof(buffer), &nread);
|
||||
/* read would've blocked. Loop again */
|
||||
if(result == CURLE_AGAIN)
|
||||
break;
|
||||
|
@ -1635,7 +1635,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
|
|||
}
|
||||
#endif
|
||||
/* mark this as "no further transfer wanted" */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1240,7 +1240,7 @@ static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
|
|||
*done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
|
||||
if(*done)
|
||||
/* Tell curl we're done */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
}
|
||||
else {
|
||||
/* no timeouts to handle, check our socket */
|
||||
|
@ -1263,7 +1263,7 @@ static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
|
|||
*done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
|
||||
if(*done)
|
||||
/* Tell curl we're done */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
}
|
||||
/* if rc == 0, then select() timed out */
|
||||
}
|
||||
|
|
|
@ -448,7 +448,7 @@ static ssize_t Curl_xfer_recv_resp(struct Curl_easy *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
*err = Curl_read(data, data->conn->sockfd, buf, blen, &nread);
|
||||
*err = Curl_xfer_recv(data, buf, blen, &nread);
|
||||
if(*err)
|
||||
return -1;
|
||||
DEBUGASSERT(nread >= 0);
|
||||
|
@ -770,9 +770,11 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
|||
that instead of reading more data */
|
||||
}
|
||||
|
||||
if(!Curl_bufq_is_empty(&k->sendbuf)) {
|
||||
DEBUGASSERT(0);
|
||||
}
|
||||
/* write to socket (send away data) */
|
||||
result = Curl_write(data,
|
||||
conn->writesockfd, /* socket to send to */
|
||||
result = Curl_xfer_send(data,
|
||||
k->upload_fromhere, /* buffer pointer */
|
||||
k->upload_present, /* buffer size */
|
||||
&bytes_written); /* actually sent */
|
||||
|
@ -1590,11 +1592,10 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
|
|||
}
|
||||
|
||||
/*
|
||||
* Curl_setup_transfer() is called to setup some basic properties for the
|
||||
* Curl_xfer_setup() is called to setup some basic properties for the
|
||||
* upcoming transfer.
|
||||
*/
|
||||
void
|
||||
Curl_setup_transfer(
|
||||
void Curl_xfer_setup(
|
||||
struct Curl_easy *data, /* transfer */
|
||||
int sockindex, /* socket index to read from or -1 */
|
||||
curl_off_t size, /* -1 if unknown at this point */
|
||||
|
@ -1610,6 +1611,7 @@ Curl_setup_transfer(
|
|||
|
||||
DEBUGASSERT(conn != NULL);
|
||||
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
|
||||
DEBUGASSERT((writesockindex <= 1) && (writesockindex >= -1));
|
||||
|
||||
httpsending = ((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
|
||||
(http->sending == HTTPSEND_REQUEST));
|
||||
|
@ -1727,3 +1729,51 @@ CURLcode Curl_xfer_write_done(struct Curl_easy *data, bool premature)
|
|||
(void)premature;
|
||||
return Curl_cw_out_done(data);
|
||||
}
|
||||
|
||||
CURLcode Curl_xfer_send(struct Curl_easy *data,
|
||||
const void *buf, size_t blen,
|
||||
ssize_t *pnwritten)
|
||||
{
|
||||
CURLcode result;
|
||||
int sockindex;
|
||||
|
||||
if(!data || !data->conn)
|
||||
return CURLE_FAILED_INIT;
|
||||
/* FIXME: would like to enable this, but some protocols (MQTT) do not
|
||||
* setup the transfer correctly, it seems
|
||||
if(data->conn->writesockfd == CURL_SOCKET_BAD) {
|
||||
failf(data, "transfer not setup for sending");
|
||||
DEBUGASSERT(0);
|
||||
return CURLE_SEND_ERROR;
|
||||
} */
|
||||
sockindex = ((data->conn->writesockfd != CURL_SOCKET_BAD) &&
|
||||
(data->conn->writesockfd == data->conn->sock[SECONDARYSOCKET]));
|
||||
result = Curl_conn_send(data, sockindex, buf, blen, pnwritten);
|
||||
if(result == CURLE_AGAIN) {
|
||||
result = CURLE_OK;
|
||||
*pnwritten = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_xfer_recv(struct Curl_easy *data,
|
||||
char *buf, size_t blen,
|
||||
ssize_t *pnrcvd)
|
||||
{
|
||||
int sockindex;
|
||||
|
||||
if(!data || !data->conn)
|
||||
return CURLE_FAILED_INIT;
|
||||
/* FIXME: would like to enable this, but some protocols (MQTT) do not
|
||||
* setup the transfer correctly, it seems
|
||||
if(data->conn->sockfd == CURL_SOCKET_BAD) {
|
||||
failf(data, "transfer not setup for receiving");
|
||||
DEBUGASSERT(0);
|
||||
return CURLE_RECV_ERROR;
|
||||
} */
|
||||
sockindex = ((data->conn->sockfd != CURL_SOCKET_BAD) &&
|
||||
(data->conn->sockfd == data->conn->sock[SECONDARYSOCKET]));
|
||||
if(data->set.buffer_size > 0 && (size_t)data->set.buffer_size < blen)
|
||||
blen = (size_t)data->set.buffer_size;
|
||||
return Curl_conn_recv(data, sockindex, buf, blen, pnrcvd);
|
||||
}
|
||||
|
|
|
@ -75,8 +75,7 @@ CURLcode Curl_xfer_write_resp(struct Curl_easy *data,
|
|||
bool is_eos, bool *done);
|
||||
|
||||
/* This sets up a forthcoming transfer */
|
||||
void
|
||||
Curl_setup_transfer (struct Curl_easy *data,
|
||||
void Curl_xfer_setup(struct Curl_easy *data,
|
||||
int sockindex, /* socket index to read from or -1 */
|
||||
curl_off_t size, /* -1 if unknown at this point */
|
||||
bool getheader, /* TRUE if header parsing is wanted */
|
||||
|
@ -91,4 +90,22 @@ Curl_setup_transfer (struct Curl_easy *data,
|
|||
*/
|
||||
CURLcode Curl_xfer_write_done(struct Curl_easy *data, bool premature);
|
||||
|
||||
/**
|
||||
* Send data on the socket/connection filter designated
|
||||
* for transfer's outgoing data.
|
||||
* Will return CURLE_OK on blocking with (*pnwritten == 0).
|
||||
*/
|
||||
CURLcode Curl_xfer_send(struct Curl_easy *data,
|
||||
const void *buf, size_t blen,
|
||||
ssize_t *pnwritten);
|
||||
|
||||
/**
|
||||
* Receive data on the socket/connection filter designated
|
||||
* for transfer's incoming data.
|
||||
* Will return CURLE_AGAIN on blocking with (*pnrcvd == 0).
|
||||
*/
|
||||
CURLcode Curl_xfer_recv(struct Curl_easy *data,
|
||||
char *buf, size_t blen,
|
||||
ssize_t *pnrcvd);
|
||||
|
||||
#endif /* HEADER_CURL_TRANSFER_H */
|
||||
|
|
60
lib/url.c
60
lib/url.c
|
@ -261,7 +261,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
|
|||
free(data->state.range);
|
||||
|
||||
/* freed here just in case DONE wasn't called */
|
||||
Curl_free_request_state(data);
|
||||
Curl_req_free(&data->req, data);
|
||||
|
||||
/* Close down all open SSL info and sessions */
|
||||
Curl_ssl_close_all(data);
|
||||
|
@ -269,10 +269,6 @@ CURLcode Curl_close(struct Curl_easy **datap)
|
|||
Curl_safefree(data->state.scratch);
|
||||
Curl_ssl_free_certinfo(data);
|
||||
|
||||
/* Cleanup possible redirect junk */
|
||||
free(data->req.newurl);
|
||||
data->req.newurl = NULL;
|
||||
|
||||
if(data->state.referer_alloc) {
|
||||
Curl_safefree(data->state.referer);
|
||||
data->state.referer_alloc = FALSE;
|
||||
|
@ -325,15 +321,6 @@ CURLcode Curl_close(struct Curl_easy **datap)
|
|||
Curl_safefree(data->state.aptr.proxyuser);
|
||||
Curl_safefree(data->state.aptr.proxypasswd);
|
||||
|
||||
#ifndef CURL_DISABLE_DOH
|
||||
if(data->req.doh) {
|
||||
Curl_dyn_free(&data->req.doh->probe[0].serverdoh);
|
||||
Curl_dyn_free(&data->req.doh->probe[1].serverdoh);
|
||||
curl_slist_free_all(data->req.doh->headers);
|
||||
Curl_safefree(data->req.doh);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_FORM_API)
|
||||
Curl_mime_cleanpart(data->state.formp);
|
||||
Curl_safefree(data->state.formp);
|
||||
|
@ -519,9 +506,17 @@ CURLcode Curl_open(struct Curl_easy **curl)
|
|||
|
||||
data->magic = CURLEASY_MAGIC_NUMBER;
|
||||
|
||||
result = Curl_req_init(&data->req);
|
||||
if(result) {
|
||||
DEBUGF(fprintf(stderr, "Error: request init failed\n"));
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = Curl_resolver_init(data, &data->state.async.resolver);
|
||||
if(result) {
|
||||
DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
|
||||
Curl_req_free(&data->req, data);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
@ -545,6 +540,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
|
|||
Curl_resolver_cleanup(data->state.async.resolver);
|
||||
Curl_dyn_free(&data->state.headerb);
|
||||
Curl_freeset(data);
|
||||
Curl_req_free(&data->req, data);
|
||||
free(data);
|
||||
data = NULL;
|
||||
}
|
||||
|
@ -2054,24 +2050,6 @@ static CURLcode setup_connection_internals(struct Curl_easy *data,
|
|||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_free_request_state() should free temp data that was allocated in the
|
||||
* Curl_easy for this single request.
|
||||
*/
|
||||
|
||||
void Curl_free_request_state(struct Curl_easy *data)
|
||||
{
|
||||
Curl_safefree(data->req.p.http);
|
||||
Curl_safefree(data->req.newurl);
|
||||
#ifndef CURL_DISABLE_DOH
|
||||
if(data->req.doh) {
|
||||
Curl_close(&data->req.doh->probe[0].easy);
|
||||
Curl_close(&data->req.doh->probe[1].easy);
|
||||
}
|
||||
#endif
|
||||
Curl_client_cleanup(data);
|
||||
}
|
||||
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
|
||||
|
@ -3609,7 +3587,7 @@ static CURLcode create_conn(struct Curl_easy *data,
|
|||
(void)conn->handler->done(data, result, FALSE);
|
||||
goto out;
|
||||
}
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
}
|
||||
|
||||
/* since we skip do_init() */
|
||||
|
@ -3620,10 +3598,10 @@ static CURLcode create_conn(struct Curl_easy *data,
|
|||
#endif
|
||||
|
||||
/* Setup filter for network connections */
|
||||
conn->recv[FIRSTSOCKET] = Curl_conn_recv;
|
||||
conn->send[FIRSTSOCKET] = Curl_conn_send;
|
||||
conn->recv[SECONDARYSOCKET] = Curl_conn_recv;
|
||||
conn->send[SECONDARYSOCKET] = Curl_conn_send;
|
||||
conn->recv[FIRSTSOCKET] = Curl_cf_recv;
|
||||
conn->send[FIRSTSOCKET] = Curl_cf_send;
|
||||
conn->recv[SECONDARYSOCKET] = Curl_cf_recv;
|
||||
conn->send[SECONDARYSOCKET] = Curl_cf_send;
|
||||
conn->bits.tcp_fastopen = data->set.tcp_fastopen;
|
||||
|
||||
/* Complete the easy's SSL configuration for connection cache matching */
|
||||
|
@ -3866,7 +3844,7 @@ CURLcode Curl_connect(struct Curl_easy *data,
|
|||
*asyncp = FALSE; /* assume synchronous resolves by default */
|
||||
|
||||
/* init the single-transfer specific data */
|
||||
Curl_free_request_state(data);
|
||||
Curl_req_reset(&data->req, data);
|
||||
memset(&data->req, 0, sizeof(struct SingleRequest));
|
||||
data->req.size = data->req.maxdownload = -1;
|
||||
data->req.no_body = data->set.opt_no_body;
|
||||
|
@ -3935,12 +3913,14 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
|
|||
/* in HTTP lingo, no body means using the HEAD request... */
|
||||
data->state.httpreq = HTTPREQ_HEAD;
|
||||
|
||||
k->start = Curl_now(); /* start time */
|
||||
result = Curl_req_start(&data->req, data);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
k->header = TRUE; /* assume header */
|
||||
k->bytecount = 0;
|
||||
k->ignorebody = FALSE;
|
||||
|
||||
Curl_client_cleanup(data);
|
||||
Curl_speedinit(data);
|
||||
Curl_pgrsSetUploadCounter(data, 0);
|
||||
Curl_pgrsSetDownloadCounter(data, 0);
|
||||
|
|
|
@ -41,7 +41,6 @@ void Curl_disconnect(struct Curl_easy *data,
|
|||
struct connectdata *, bool dead_connection);
|
||||
CURLcode Curl_setup_conn(struct Curl_easy *data,
|
||||
bool *protocol_done);
|
||||
void Curl_free_request_state(struct Curl_easy *data);
|
||||
CURLcode Curl_parse_login_details(const char *login, const size_t len,
|
||||
char **userptr, char **passwdptr,
|
||||
char **optionsptr);
|
||||
|
|
122
lib/urldata.h
122
lib/urldata.h
|
@ -143,6 +143,7 @@ typedef unsigned int curl_prot_t;
|
|||
#include "splay.h"
|
||||
#include "dynbuf.h"
|
||||
#include "dynhds.h"
|
||||
#include "request.h"
|
||||
|
||||
/* return the count of bytes sent, or -1 on error */
|
||||
typedef ssize_t (Curl_send)(struct Curl_easy *data, /* transfer */
|
||||
|
@ -616,22 +617,6 @@ struct easy_pollset {
|
|||
unsigned char actions[MAX_SOCKSPEREASYHANDLE];
|
||||
};
|
||||
|
||||
enum expect100 {
|
||||
EXP100_SEND_DATA, /* enough waiting, just send the body now */
|
||||
EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */
|
||||
EXP100_SENDING_REQUEST, /* still sending the request but will wait for
|
||||
the 100 header once done with the request */
|
||||
EXP100_FAILED /* used on 417 Expectation Failed */
|
||||
};
|
||||
|
||||
enum upgrade101 {
|
||||
UPGR101_INIT, /* default state */
|
||||
UPGR101_WS, /* upgrade to WebSockets requested */
|
||||
UPGR101_H2, /* upgrade to HTTP/2 requested */
|
||||
UPGR101_RECEIVED, /* 101 response received */
|
||||
UPGR101_WORKING /* talking upgraded protocol */
|
||||
};
|
||||
|
||||
enum doh_slots {
|
||||
/* Explicit values for first two symbols so as to match hard-coded
|
||||
* constants in existing code
|
||||
|
@ -650,111 +635,6 @@ enum doh_slots {
|
|||
DOH_PROBE_SLOTS
|
||||
};
|
||||
|
||||
/*
|
||||
* Request specific data in the easy handle (Curl_easy). Previously,
|
||||
* these members were on the connectdata struct but since a conn struct may
|
||||
* now be shared between different Curl_easys, we store connection-specific
|
||||
* data here. This struct only keeps stuff that's interesting for *this*
|
||||
* request, as it will be cleared between multiple ones
|
||||
*/
|
||||
struct SingleRequest {
|
||||
curl_off_t size; /* -1 if unknown at this point */
|
||||
curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch,
|
||||
-1 means unlimited */
|
||||
curl_off_t bytecount; /* total number of bytes read */
|
||||
curl_off_t writebytecount; /* number of bytes written */
|
||||
|
||||
curl_off_t pendingheader; /* this many bytes left to send is actually
|
||||
header and not body */
|
||||
struct curltime start; /* transfer started at this time */
|
||||
unsigned int headerbytecount; /* received server headers (not CONNECT
|
||||
headers) */
|
||||
unsigned int allheadercount; /* all received headers (server + CONNECT) */
|
||||
unsigned int deductheadercount; /* this amount of bytes doesn't count when
|
||||
we check if anything has been transferred
|
||||
at the end of a connection. We use this
|
||||
counter to make only a 100 reply (without
|
||||
a following second response code) result
|
||||
in a CURLE_GOT_NOTHING error code */
|
||||
int headerline; /* counts header lines to better track the
|
||||
first one */
|
||||
curl_off_t offset; /* possible resume offset read from the
|
||||
Content-Range: header */
|
||||
int httpcode; /* error code from the 'HTTP/1.? XXX' or
|
||||
'RTSP/1.? XXX' line */
|
||||
int keepon;
|
||||
struct curltime start100; /* time stamp to wait for the 100 code from */
|
||||
enum expect100 exp100; /* expect 100 continue state */
|
||||
enum upgrade101 upgr101; /* 101 upgrade state */
|
||||
|
||||
/* Client Writer stack, handles trasnfer- and content-encodings, protocol
|
||||
* checks, pausing by client callbacks. */
|
||||
struct Curl_cwriter *writer_stack;
|
||||
time_t timeofdoc;
|
||||
long bodywrites;
|
||||
char *location; /* This points to an allocated version of the Location:
|
||||
header data */
|
||||
char *newurl; /* Set to the new URL to use when a redirect or a retry is
|
||||
wanted */
|
||||
|
||||
/* 'upload_present' is used to keep a byte counter of how much data there is
|
||||
still left in the buffer, aimed for upload. */
|
||||
ssize_t upload_present;
|
||||
|
||||
/* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a
|
||||
buffer, so the next read should read from where this pointer points to,
|
||||
and the 'upload_present' contains the number of bytes available at this
|
||||
position */
|
||||
char *upload_fromhere;
|
||||
|
||||
/* Allocated protocol-specific data. Each protocol handler makes sure this
|
||||
points to data it needs. */
|
||||
union {
|
||||
struct FILEPROTO *file;
|
||||
struct FTP *ftp;
|
||||
struct HTTP *http;
|
||||
struct IMAP *imap;
|
||||
struct ldapreqinfo *ldap;
|
||||
struct MQTT *mqtt;
|
||||
struct POP3 *pop3;
|
||||
struct RTSP *rtsp;
|
||||
struct smb_request *smb;
|
||||
struct SMTP *smtp;
|
||||
struct SSHPROTO *ssh;
|
||||
struct TELNET *telnet;
|
||||
} p;
|
||||
#ifndef CURL_DISABLE_DOH
|
||||
struct dohdata *doh; /* DoH specific data for this request */
|
||||
#endif
|
||||
char fread_eof[2]; /* the body read callback (index 0) returned EOF or
|
||||
the trailer read callback (index 1) returned EOF */
|
||||
#ifndef CURL_DISABLE_COOKIES
|
||||
unsigned char setcookies;
|
||||
#endif
|
||||
BIT(header); /* incoming data has HTTP header */
|
||||
BIT(content_range); /* set TRUE if Content-Range: was found */
|
||||
BIT(download_done); /* set to TRUE when download is complete */
|
||||
BIT(eos_written); /* iff EOS has been written to client */
|
||||
BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding
|
||||
upload and we're uploading the last chunk */
|
||||
BIT(ignorebody); /* we read a response-body but we ignore it! */
|
||||
BIT(http_bodyless); /* HTTP response status code is between 100 and 199,
|
||||
204 or 304 */
|
||||
BIT(chunk); /* if set, this is a chunked transfer-encoding */
|
||||
BIT(ignore_cl); /* ignore content-length */
|
||||
BIT(upload_chunky); /* set TRUE if we are doing chunked transfer-encoding
|
||||
on upload */
|
||||
BIT(getheader); /* TRUE if header parsing is wanted */
|
||||
BIT(forbidchunk); /* used only to explicitly forbid chunk-upload for
|
||||
specific upload buffers. See readmoredata() in http.c
|
||||
for details. */
|
||||
BIT(no_body); /* the response has no body */
|
||||
BIT(authneg); /* TRUE when the auth phase has started, which means
|
||||
that we are creating a request with an auth header,
|
||||
but it is not the final request in the auth
|
||||
negotiation. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Specific protocol handler.
|
||||
*/
|
||||
|
|
|
@ -1349,9 +1349,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
|
|||
Curl_pgrsSetUploadSize(data, data->state.infilesize);
|
||||
}
|
||||
/* upload data */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
|
||||
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
conn->sockfd = conn->writesockfd;
|
||||
|
||||
/* store this original bitmask setup to use later on if we can't
|
||||
|
@ -1575,7 +1575,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
|
|||
sshc->sftp_dir = NULL;
|
||||
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
state(data, SSH_STOP);
|
||||
break;
|
||||
|
||||
|
@ -1720,14 +1720,14 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
|
|||
/* Setup the actual download */
|
||||
if(data->req.size == 0) {
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
infof(data, "File already completely downloaded");
|
||||
state(data, SSH_STOP);
|
||||
break;
|
||||
}
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, data->req.size, FALSE, -1);
|
||||
|
||||
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
conn->writesockfd = conn->sockfd;
|
||||
|
||||
/* we want to use the _receiving_ function even when the socket turns
|
||||
|
@ -1849,9 +1849,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
|
|||
}
|
||||
|
||||
/* upload data */
|
||||
Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET);
|
||||
Curl_xfer_setup(data, -1, data->req.size, FALSE, FIRSTSOCKET);
|
||||
|
||||
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
conn->sockfd = conn->writesockfd;
|
||||
|
||||
/* store this original bitmask setup to use later on if we can't
|
||||
|
@ -1893,9 +1893,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
|
|||
/* download data */
|
||||
bytecount = ssh_scp_request_get_size(sshc->scp_session);
|
||||
data->req.maxdownload = (curl_off_t) bytecount;
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, bytecount, FALSE, -1);
|
||||
|
||||
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
conn->writesockfd = conn->sockfd;
|
||||
|
||||
/* we want to use the _receiving_ function even when the socket turns
|
||||
|
|
|
@ -2195,9 +2195,9 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
|
|||
Curl_pgrsSetUploadSize(data, data->state.infilesize);
|
||||
}
|
||||
/* upload data */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
|
||||
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
conn->sockfd = conn->writesockfd;
|
||||
|
||||
if(result) {
|
||||
|
@ -2448,7 +2448,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
|
|||
Curl_safefree(sshp->readdir_longentry);
|
||||
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
state(data, SSH_STOP);
|
||||
break;
|
||||
|
||||
|
@ -2590,14 +2590,14 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
|
|||
/* Setup the actual download */
|
||||
if(data->req.size == 0) {
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
infof(data, "File already completely downloaded");
|
||||
state(data, SSH_STOP);
|
||||
break;
|
||||
}
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, data->req.size, FALSE, -1);
|
||||
|
||||
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
conn->writesockfd = conn->sockfd;
|
||||
|
||||
/* we want to use the _receiving_ function even when the socket turns
|
||||
|
@ -2741,9 +2741,9 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
|
|||
/* upload data */
|
||||
data->req.size = data->state.infilesize;
|
||||
Curl_pgrsSetUploadSize(data, data->state.infilesize);
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
|
||||
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
conn->sockfd = conn->writesockfd;
|
||||
|
||||
if(result) {
|
||||
|
@ -2812,9 +2812,9 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
|
|||
/* download data */
|
||||
bytecount = (curl_off_t)sb.st_size;
|
||||
data->req.maxdownload = (curl_off_t)sb.st_size;
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, bytecount, FALSE, -1);
|
||||
|
||||
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
conn->writesockfd = conn->sockfd;
|
||||
|
||||
/* we want to use the _receiving_ function even when the socket turns
|
||||
|
@ -3193,12 +3193,13 @@ static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
|
|||
struct connectdata *conn = data->conn;
|
||||
Curl_recv *backup = conn->recv[0];
|
||||
struct ssh_conn *ssh = &conn->proto.sshc;
|
||||
int socknum = Curl_conn_sockindex(data, sock);
|
||||
(void)flags;
|
||||
|
||||
/* swap in the TLS reader function for this call only, and then swap back
|
||||
the SSH one again */
|
||||
conn->recv[0] = ssh->tls_recv;
|
||||
result = Curl_read(data, sock, buffer, length, &nread);
|
||||
result = Curl_conn_recv(data, socknum, buffer, length, &nread);
|
||||
conn->recv[0] = backup;
|
||||
if(result == CURLE_AGAIN)
|
||||
return -EAGAIN; /* magic return code for libssh2 */
|
||||
|
@ -3217,12 +3218,13 @@ static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
|
|||
struct connectdata *conn = data->conn;
|
||||
Curl_send *backup = conn->send[0];
|
||||
struct ssh_conn *ssh = &conn->proto.sshc;
|
||||
int socknum = Curl_conn_sockindex(data, sock);
|
||||
(void)flags;
|
||||
|
||||
/* swap in the TLS writer function for this call only, and then swap back
|
||||
the SSH one again */
|
||||
conn->send[0] = ssh->tls_send;
|
||||
result = Curl_write(data, sock, buffer, length, &nwrite);
|
||||
result = Curl_conn_send(data, socknum, buffer, length, &nwrite);
|
||||
conn->send[0] = backup;
|
||||
if(result == CURLE_AGAIN)
|
||||
return -EAGAIN; /* magic return code for libssh2 */
|
||||
|
|
|
@ -678,9 +678,9 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
|
|||
Curl_pgrsSetUploadSize(data, data->state.infilesize);
|
||||
}
|
||||
/* upload data */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
|
||||
|
||||
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
conn->sockfd = conn->writesockfd;
|
||||
|
||||
if(result) {
|
||||
|
@ -778,14 +778,14 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
|
|||
/* Setup the actual download */
|
||||
if(data->req.size == 0) {
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
Curl_xfer_setup(data, -1, -1, FALSE, -1);
|
||||
infof(data, "File already completely downloaded");
|
||||
state(data, SSH_STOP);
|
||||
break;
|
||||
}
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
|
||||
Curl_xfer_setup(data, FIRSTSOCKET, data->req.size, FALSE, -1);
|
||||
|
||||
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
conn->writesockfd = conn->sockfd;
|
||||
|
||||
/* we want to use the _receiving_ function even when the socket turns
|
||||
|
|
13
lib/ws.c
13
lib/ws.c
|
@ -1020,8 +1020,12 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws,
|
|||
while(Curl_bufq_peek(&ws->sendbuf, &out, &outlen)) {
|
||||
if(data->set.connect_only)
|
||||
result = Curl_senddata(data, out, outlen, &n);
|
||||
else
|
||||
result = Curl_write(data, data->conn->writesockfd, out, outlen, &n);
|
||||
else {
|
||||
result = Curl_xfer_send(data, out, outlen, &n);
|
||||
if(!result && !n && outlen)
|
||||
result = CURLE_AGAIN;
|
||||
}
|
||||
|
||||
if(result) {
|
||||
if(result == CURLE_AGAIN) {
|
||||
if(!complete) {
|
||||
|
@ -1086,8 +1090,7 @@ CURL_EXTERN CURLcode curl_ws_send(CURL *data, const void *buffer,
|
|||
/* raw mode sends exactly what was requested, and this is from within
|
||||
the write callback */
|
||||
if(Curl_is_in_callback(data)) {
|
||||
result = Curl_write(data, data->conn->writesockfd, buffer, buflen,
|
||||
&nwritten);
|
||||
result = Curl_xfer_send(data, buffer, buflen, &nwritten);
|
||||
}
|
||||
else
|
||||
result = Curl_senddata(data, buffer, buflen, &nwritten);
|
||||
|
@ -1104,7 +1107,7 @@ CURL_EXTERN CURLcode curl_ws_send(CURL *data, const void *buffer,
|
|||
return result;
|
||||
|
||||
/* TODO: the current design does not allow partial writes, afaict.
|
||||
* It is not clear who the application is supposed to react. */
|
||||
* It is not clear how the application is supposed to react. */
|
||||
space = Curl_bufq_space(&ws->sendbuf);
|
||||
DEBUGF(infof(data, "curl_ws_send(len=%zu), sendbuf len=%zu space %zu",
|
||||
buflen, Curl_bufq_len(&ws->sendbuf), space));
|
||||
|
|
|
@ -84,8 +84,6 @@ UNITTEST_START
|
|||
"Curl_free() did not set to NULL");
|
||||
}
|
||||
|
||||
Curl_free_request_state(empty);
|
||||
|
||||
rc = Curl_close(&empty);
|
||||
fail_unless(rc == CURLE_OK, "Curl_close() failed");
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user