struct hyp_io_ctx *io_ctx = userp;
struct Curl_easy *data = io_ctx->data;
CURLcode result;
- ssize_t nwrote;
+ size_t nwrote;
DEBUGF(infof(data, "Curl_hyper_send(%zu)", buflen));
result = Curl_conn_send(data, io_ctx->sockindex,
(void *)buf, buflen, &nwrote);
+ if(!result && !nwrote)
+ result = CURLE_AGAIN;
if(result == CURLE_AGAIN) {
DEBUGF(infof(data, "Curl_hyper_send(%zu) -> EAGAIN", buflen));
/* would block, register interest */
*/
static CURLcode bodysend(struct Curl_easy *data,
- struct connectdata *conn,
hyper_headers *headers,
hyper_request *hyperreq,
Curl_HttpReq httpreq)
else {
hyper_body *body;
Curl_dyn_init(&req, DYN_HTTP_REQUEST);
- result = Curl_http_bodysend(data, conn, &req, httpreq);
+ result = Curl_http_req_send(data, &req, httpreq);
if(!result)
result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
if(result)
goto error;
- result = bodysend(data, conn, headers, req, httpreq);
+ result = bodysend(data, headers, req, httpreq);
if(result)
goto error;
}
}
+static bool tunnel_want_send(struct h1_tunnel_state *ts)
+{
+ return (ts->tunnel_state == H1_TUNNEL_CONNECT);
+}
+
#ifndef USE_HYPER
static CURLcode start_CONNECT(struct Curl_cfilter *cf,
struct Curl_easy *data,
wait for the socket to become readable to be able to get the
response headers or if we're still sending the request, wait
for write. */
- if(ts->CONNECT.sending == HTTPSEND_REQUEST)
+ if(tunnel_want_send(ts))
Curl_pollset_set_out_only(data, ps, sock);
else
Curl_pollset_set_in_only(data, ps, sock);
case HAPROXY_SEND:
len = Curl_dyn_len(&ctx->data_out);
if(len > 0) {
- ssize_t written;
+ size_t written;
result = Curl_conn_send(data, cf->sockindex,
Curl_dyn_ptr(&ctx->data_out),
len, &written);
}
else if(result)
goto out;
- DEBUGASSERT(written >= 0);
- Curl_dyn_tail(&ctx->data_out, len - (size_t)written);
+ Curl_dyn_tail(&ctx->data_out, len - written);
if(Curl_dyn_len(&ctx->data_out) > 0) {
result = CURLE_OK;
goto out;
CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t blen,
- ssize_t *pnwritten)
+ size_t *pnwritten)
{
ssize_t nwritten;
CURLcode result = CURLE_OK;
#endif
nwritten = conn->send[sockindex](data, sockindex, buf, blen, &result);
DEBUGASSERT((nwritten >= 0) || result);
- *pnwritten = nwritten;
+ *pnwritten = (nwritten < 0)? 0 : (size_t)nwritten;
return result;
}
*/
CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t blen,
- ssize_t *pnwritten);
+ size_t *pnwritten);
void Curl_pollset_reset(struct Curl_easy *data,
static CURLcode sendf(struct Curl_easy *data, const char *fmt, ...)
{
- ssize_t bytes_written;
+ size_t bytes_written;
size_t write_len;
CURLcode result = CURLE_OK;
char *s;
* This is the private internal version of curl_easy_send()
*/
CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
- size_t buflen, ssize_t *n)
+ size_t buflen, size_t *n)
{
CURLcode result;
struct connectdata *c = NULL;
CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
size_t buflen, size_t *n)
{
- ssize_t written = 0;
+ size_t written = 0;
CURLcode result;
if(Curl_is_in_callback(data))
return CURLE_RECURSIVE_API_CALL;
result = Curl_senddata(data, buffer, buflen, &written);
- *n = (size_t)written;
+ *n = written;
return result;
}
* Prototypes for library-wide functions provided by easy.c
*/
CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
- size_t buflen, ssize_t *n);
+ size_t buflen, size_t *n);
#ifdef USE_WEBSOCKETS
CURLcode Curl_connect_only_attach(struct Curl_easy *data);
char *sel = NULL;
char *sel_org = NULL;
timediff_t timeout_ms;
- ssize_t amount, k;
- size_t len;
+ ssize_t k;
+ size_t amount, len;
int what;
*done = TRUE; /* unconditionally */
return data->state.authproblem;
}
+#ifndef USE_HYPER
/*
* readmoredata() is a "fread() emulation" to provide POST and/or request
* data. It is used when a huge POST is to be made and the entire chunk wasn't
*
* Returns CURLcode
*/
-CURLcode Curl_buffer_send(struct dynbuf *in,
- struct Curl_easy *data,
- struct HTTP *http,
- /* add the number of sent bytes to this
- counter */
- curl_off_t *bytes_written,
- /* how much of the buffer contains body data */
- curl_off_t included_body_bytes,
- int sockindex)
+static CURLcode buffer_send(struct dynbuf *in,
+ struct Curl_easy *data,
+ struct HTTP *http,
+ /* add the number of sent bytes to this
+ counter */
+ curl_off_t *bytes_written,
+ /* how much of the buffer contains body data */
+ curl_off_t included_body_bytes)
{
- ssize_t amount;
+ size_t amount;
CURLcode result;
char *ptr;
size_t size;
size_t sendsize;
size_t headersize;
- DEBUGASSERT(sockindex <= SECONDARYSOCKET && sockindex >= 0);
-
/* The looping below is required since we use non-blocking sockets, but due
to the circumstances we will just loop and try again and again etc */
sendsize = (size_t)data->set.upload_buffer_size;
}
- result = Curl_conn_send(data, sockindex, ptr, sendsize, &amount);
- if(result == CURLE_AGAIN) {
- result = CURLE_OK;
- amount = 0;
- }
+ result = Curl_xfer_send(data, ptr, sendsize, &amount);
if(!result) {
/*
/* end of the add_buffer functions */
/* ------------------------------------------------------------------------- */
+#else /* !USE_HYPER */
+ /* In hyper, this is an ugly NOP */
+#define buffer_send(a,b,c,d,e) CURLE_OK
+
+#endif /* !USE_HYPER(else) */
#endif
/* check and possibly add an Expect: header */
-static CURLcode expect100(struct Curl_easy *data,
- struct connectdata *conn,
- struct dynbuf *req)
+static CURLcode expect100(struct Curl_easy *data, struct dynbuf *req)
{
CURLcode result = CURLE_OK;
- if(!data->state.disableexpect && Curl_use_http_1_1plus(data, conn) &&
- (conn->httpversion < 20)) {
+ if(!data->state.disableexpect &&
+ Curl_use_http_1_1plus(data, data->conn) &&
+ (data->conn->httpversion < 20)) {
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
Expect: 100-continue to the headers which actually speeds up post
operations (as there is one packet coming back from the web server) */
return result;
}
-static CURLcode addexpect(struct Curl_easy *data, struct connectdata *conn,
- struct dynbuf *r)
+static CURLcode addexpect(struct Curl_easy *data, struct dynbuf *r)
{
data->state.expect100header = FALSE;
/* Avoid Expect: 100-continue if Upgrade: is used */
STRCONST("100-continue"));
}
else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0)
- return expect100(data, conn, r);
+ return expect100(data, r);
}
return CURLE_OK;
}
-CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
+CURLcode Curl_http_req_send(struct Curl_easy *data,
struct dynbuf *r, Curl_HttpReq httpreq)
{
#ifndef USE_HYPER
/* Hyper always handles the body separately */
curl_off_t included_body = 0;
-#else
- /* from this point down, this function should not be used */
-#define Curl_buffer_send(a,b,c,d,e,f) CURLE_OK
#endif
CURLcode result = CURLE_OK;
struct HTTP *http = data->req.p.http;
+ DEBUGASSERT(data->conn);
switch(httpreq) {
case HTTPREQ_PUT: /* Let's PUT the data to the server! */
return result;
}
- result = addexpect(data, conn, r);
+ result = addexpect(data, r);
if(result)
return result;
Curl_pgrsSetUploadSize(data, http->postsize);
/* this sends the buffer and frees all the buffer resources */
- result = Curl_buffer_send(r, data, data->req.p.http,
- &data->info.request_size, 0,
- FIRSTSOCKET);
+ result = buffer_send(r, data, data->req.p.http,
+ &data->info.request_size, 0);
if(result)
failf(data, "Failed sending PUT request");
else
if(result)
return result;
- result = Curl_buffer_send(r, data, data->req.p.http,
- &data->info.request_size, 0,
- FIRSTSOCKET);
+ result = buffer_send(r, data, data->req.p.http,
+ &data->info.request_size, 0);
if(result)
failf(data, "Failed sending POST request");
else
}
#endif
- result = addexpect(data, conn, r);
+ result = addexpect(data, r);
if(result)
return result;
http->sending = HTTPSEND_BODY;
/* this sends the buffer and frees all the buffer resources */
- result = Curl_buffer_send(r, data, data->req.p.http,
- &data->info.request_size, 0,
- FIRSTSOCKET);
+ result = buffer_send(r, data, data->req.p.http,
+ &data->info.request_size, 0);
if(result)
failf(data, "Failed sending POST request");
else
return result;
}
- result = addexpect(data, conn, r);
+ result = addexpect(data, r);
if(result)
return result;
}
}
/* issue the request */
- result = Curl_buffer_send(r, data, data->req.p.http,
- &data->info.request_size, included_body,
- FIRSTSOCKET);
+ result = buffer_send(r, data, data->req.p.http,
+ &data->info.request_size, included_body);
if(result)
failf(data, "Failed sending HTTP POST request");
return result;
/* issue the request */
- result = Curl_buffer_send(r, data, data->req.p.http,
- &data->info.request_size, 0,
- FIRSTSOCKET);
+ result = Curl_req_send_hds(data, Curl_dyn_ptr(r), Curl_dyn_len(r));
+ Curl_dyn_free(r);
if(result)
failf(data, "Failed sending HTTP request");
#ifdef USE_WEBSOCKETS
- else if((conn->handler->protocol & (CURLPROTO_WS|CURLPROTO_WSS)) &&
+ else if((data->conn->handler->protocol & (CURLPROTO_WS|CURLPROTO_WSS)) &&
!(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 */
(httpreq == HTTPREQ_HEAD))
Curl_pgrsSetUploadSize(data, 0); /* nothing */
- /* bodysend takes ownership of the 'req' memory on success */
- result = Curl_http_bodysend(data, conn, &req, httpreq);
+ /* req_send takes ownership of the 'req' memory on success */
+ result = Curl_http_req_send(data, &req, httpreq);
}
if(result) {
Curl_dyn_free(&req);
const char *thisheader,
const size_t thislen);
struct HTTP; /* see below */
-CURLcode Curl_buffer_send(struct dynbuf *in,
- struct Curl_easy *data,
- struct HTTP *http,
- curl_off_t *bytes_written,
- curl_off_t included_body_bytes,
- int socketindex);
CURLcode Curl_add_timecondition(struct Curl_easy *data,
#ifndef USE_HYPER
CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
Curl_HttpReq httpreq,
const char **teep);
-CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
+CURLcode Curl_http_req_send(struct Curl_easy *data,
struct dynbuf *r, Curl_HttpReq httpreq);
bool Curl_use_http_1_1plus(const struct Curl_easy *data,
const struct connectdata *conn);
static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
const char *cmd)
{
- ssize_t bytes_written;
+ size_t bytes_written;
#define SBUF_SIZE 1024
char s[SBUF_SIZE];
size_t write_len;
if(result)
break;
- Curl_debug(data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written);
+ Curl_debug(data, CURLINFO_HEADER_OUT, sptr, bytes_written);
- if(bytes_written != (ssize_t)write_len) {
+ if(bytes_written != write_len) {
write_len -= bytes_written;
sptr += bytes_written;
}
{
const char *to_p = to;
CURLcode result;
- ssize_t written;
+ size_t written;
while(len > 0) {
result = Curl_conn_send(data, sockindex, to_p, len, &written);
{
CURLcode result = CURLE_OK;
struct MQTT *mq = data->req.p.mqtt;
- ssize_t n;
+ size_t n;
result = Curl_xfer_send(data, buf, len, &n);
if(result)
return result;
Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n);
- if(len != (size_t)n) {
+ if(len != n) {
size_t nsend = len - n;
char *sendleftovers = Curl_memdup(&buf[n], nsend);
if(!sendleftovers)
const char *fmt,
va_list args)
{
- ssize_t bytes_written = 0;
+ size_t bytes_written = 0;
size_t write_len;
char *s;
CURLcode result;
conn->data_prot = (unsigned char)data_sec;
#endif
- Curl_debug(data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written);
+ Curl_debug(data, CURLINFO_HEADER_OUT, s, bytes_written);
- if(bytes_written != (ssize_t)write_len) {
+ if(bytes_written != write_len) {
/* the whole chunk was not sent, keep it around and adjust sizes */
pp->sendthis = s;
pp->sendsize = write_len;
struct pingpong *pp)
{
/* we have a piece of a command still left to send */
- ssize_t written;
+ size_t written;
CURLcode result;
result = Curl_conn_send(data, FIRSTSOCKET,
if(result)
return result;
- if(written != (ssize_t)pp->sendleft) {
+ if(written != pp->sendleft) {
/* only a fraction was sent */
pp->sendleft -= written;
}
#include "urldata.h"
#include "dynbuf.h"
#include "doh.h"
+#include "progress.h"
#include "request.h"
#include "sendf.h"
+#include "transfer.h"
#include "url.h"
/* The last 3 #include files should be in this order */
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;
}
{
req->start = Curl_now();
Curl_cw_reset(data);
+ if(!req->sendbuf_init) {
+ Curl_bufq_init2(&req->sendbuf, data->set.upload_buffer_size, 1,
+ BUFQ_OPT_SOFT_LIMIT);
+ req->sendbuf_init = TRUE;
+ }
+ else {
+ 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);
+ }
+ }
+
return CURLE_OK;
}
struct Curl_easy *data, bool aborted)
{
(void)req;
- /* TODO: add flush handling for client output */
- (void)aborted;
+ if(!aborted)
+ (void)Curl_req_flush(data);
Curl_cw_reset(data);
return CURLE_OK;
}
void Curl_req_reset(struct SingleRequest *req, struct Curl_easy *data)
{
+ struct bufq savebuf;
+ bool save_init;
+
/* 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
+
+ savebuf = req->sendbuf;
+ save_init = req->sendbuf_init;
+
+ memset(req, 0, sizeof(*req));
+ data->req.size = data->req.maxdownload = -1;
+ data->req.no_body = data->set.opt_no_body;
+ if(save_init) {
+ req->sendbuf = savebuf;
+ req->sendbuf_init = save_init;
+ }
}
void Curl_req_free(struct SingleRequest *req, struct Curl_easy *data)
* free this safely without leaks. */
Curl_safefree(req->p.http);
Curl_safefree(req->newurl);
- Curl_bufq_free(&req->sendbuf);
+ if(req->sendbuf_init)
+ Curl_bufq_free(&req->sendbuf);
Curl_cw_reset(data);
#ifndef CURL_DISABLE_DOH
#endif
}
+static CURLcode req_send(struct Curl_easy *data,
+ const char *buf, size_t blen,
+ size_t hds_len, size_t *pnwritten)
+{
+ CURLcode result = CURLE_OK;
+
+ *pnwritten = 0;
+#ifdef CURLDEBUG
+ {
+ /* Allow debug builds to override this logic to force short initial
+ sends
+ */
+ char *p = getenv("CURL_SMALLREQSEND");
+ if(p) {
+ size_t altsize = (size_t)strtoul(p, NULL, 10);
+ if(altsize && altsize < blen)
+ blen = altsize;
+ }
+ }
+#endif
+ /* Make sure this doesn't send more body bytes than what the max send
+ speed says. The headers do not count to the max speed. */
+ if(data->set.max_send_speed) {
+ size_t body_bytes = blen - hds_len;
+ if((curl_off_t)body_bytes > data->set.max_send_speed)
+ blen = hds_len + (size_t)data->set.max_send_speed;
+ }
+
+ result = Curl_xfer_send(data, buf, blen, pnwritten);
+ if(!result && *pnwritten) {
+ if(hds_len)
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)buf,
+ CURLMIN(hds_len, *pnwritten));
+ if(*pnwritten > hds_len) {
+ size_t body_len = *pnwritten - hds_len;
+ Curl_debug(data, CURLINFO_DATA_OUT, (char *)buf + hds_len, body_len);
+ data->req.writebytecount += body_len;
+ Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
+ }
+ }
+ return result;
+}
+
+static CURLcode req_send_buffer_add(struct Curl_easy *data,
+ const char *buf, size_t blen,
+ size_t hds_len)
+{
+ CURLcode result = CURLE_OK;
+ ssize_t n;
+ n = Curl_bufq_write(&data->req.sendbuf,
+ (const unsigned char *)buf, blen, &result);
+ if(n < 0)
+ return result;
+ /* We rely on a SOFTLIMIT on sendbuf, so it can take all data in */
+ DEBUGASSERT((size_t)n == blen);
+ data->req.sendbuf_hds_len += hds_len;
+ return CURLE_OK;
+}
+
+static CURLcode req_send_buffer_flush(struct Curl_easy *data)
+{
+ CURLcode result = CURLE_OK;
+ const unsigned char *buf;
+ size_t blen;
+
+ while(Curl_bufq_peek(&data->req.sendbuf, &buf, &blen)) {
+ size_t nwritten, hds_len = CURLMIN(data->req.sendbuf_hds_len, blen);
+ result = req_send(data, (const char *)buf, blen, hds_len, &nwritten);
+ if(result)
+ break;
+
+ Curl_bufq_skip(&data->req.sendbuf, nwritten);
+ if(hds_len)
+ data->req.sendbuf_hds_len -= CURLMIN(hds_len, nwritten);
+ /* leave if we could not send all. Maybe network blocking or
+ * speed limits on transfer */
+ if(nwritten < blen)
+ break;
+ }
+ return result;
+}
+
+CURLcode Curl_req_flush(struct Curl_easy *data)
+{
+ CURLcode result;
+
+ if(!data || !data->conn)
+ return CURLE_FAILED_INIT;
+
+ if(!Curl_bufq_is_empty(&data->req.sendbuf)) {
+ result = req_send_buffer_flush(data);
+ if(result)
+ return result;
+ if(!Curl_bufq_is_empty(&data->req.sendbuf)) {
+ return CURLE_AGAIN;
+ }
+ }
+ return CURLE_OK;
+}
+
+CURLcode Curl_req_send(struct Curl_easy *data,
+ const char *buf, size_t blen,
+ size_t hds_len)
+{
+ CURLcode result;
+
+ if(!data || !data->conn)
+ return CURLE_FAILED_INIT;
+
+ /* We always buffer and send from there. The reason is that on
+ * blocking, we can retry using the same memory address. This is
+ * important for TLS libraries that expect this.
+ * We *could* optimized for non-TLS transfers, but that would mean
+ * separate code paths and seems not worth it. */
+ result = req_send_buffer_add(data, buf, blen, hds_len);
+ if(result)
+ return result;
+ result = req_send_buffer_flush(data);
+ if(result == CURLE_AGAIN)
+ result = CURLE_OK;
+ return result;
+}
+
+bool Curl_req_want_send(struct Curl_easy *data)
+{
+ return data->req.sendbuf_init && !Curl_bufq_is_empty(&data->req.sendbuf);
+}
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
+ size_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
* checks, pausing by client callbacks. */
struct Curl_cwriter *writer_stack;
struct bufq sendbuf; /* data which needs to be send to the server */
+ size_t sendbuf_hds_len; /* amount of header bytes in sendbuf */
time_t timeofdoc;
long bodywrites;
char *location; /* This points to an allocated version of the Location:
/* '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;
+ size_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,
that we are creating a request with an auth header,
but it is not the final request in the auth
negotiation. */
+ BIT(sendbuf_init); /* sendbuf is initialized */
};
/**
void Curl_req_reset(struct SingleRequest *req, struct Curl_easy *data);
+/**
+ * Send request bytes for transfer. If not all could be sent
+ * they will be buffered. Use `Curl_req_flush()` to make sure
+ * bytes are really send.
+ * @param data the transfer making the request
+ * @param buf the bytes to send
+ * @param blen the number of bytes to send
+ * @param hds_len the number of bytes from the start that are headers
+ * @return CURLE_OK (on blocking with *pnwritten == 0) or error.
+ */
+CURLcode Curl_req_send(struct Curl_easy *data,
+ const char *buf, size_t blen,
+ size_t hds_len);
+
+/* Convenience for sending only header bytes */
+#define Curl_req_send_hds(data, buf, blen) \
+ Curl_req_send((data), (buf), (blen), (blen))
+
+/**
+ * Flush all buffered request bytes.
+ * @return CURLE_OK on success, CURLE_AGAIN if sending was blocked,
+ * or the error on the sending.
+ */
+CURLcode Curl_req_flush(struct Curl_easy *data);
+
+/**
+ * TRUE iff the request wants to send, e.g. has buffered bytes.
+ */
+bool Curl_req_want_send(struct Curl_easy *data);
+
#endif /* HEADER_CURL_REQUEST_H */
}
/* issue the request */
- result = Curl_buffer_send(&req_buffer, data, data->req.p.http,
- &data->info.request_size, 0, FIRSTSOCKET);
+ result = Curl_req_send_hds(data, Curl_dyn_ptr(&req_buffer),
+ Curl_dyn_len(&req_buffer));
+ Curl_dyn_free(&req_buffer);
if(result) {
failf(data, "Failed sending RTSP request");
return result;
h->pid = smb_swap16((unsigned short) pid);
}
-static CURLcode smb_send(struct Curl_easy *data, ssize_t len,
+static CURLcode smb_send(struct Curl_easy *data, size_t len,
size_t upload_size)
{
struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
- ssize_t bytes_written;
+ size_t bytes_written;
CURLcode result;
result = Curl_xfer_send(data, data->state.ulbuf, len, &bytes_written);
{
struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
- ssize_t bytes_written;
- ssize_t len = smbc->send_size - smbc->sent;
+ size_t bytes_written;
+ size_t len = smbc->send_size - smbc->sent;
CURLcode result;
if(!smbc->send_size)
struct SMTP *smtp = data->req.p.smtp;
struct pingpong *pp = &conn->proto.smtpc.pp;
char *eob;
- ssize_t len;
- ssize_t bytes_written;
+ size_t len, bytes_written;
(void)premature;
static CURLcode send_telnet_data(struct Curl_easy *data,
char *buffer, ssize_t nread)
{
- ssize_t i, outlen;
+ size_t i, outlen;
unsigned char *outbuf;
CURLcode result = CURLE_OK;
- ssize_t bytes_written, total_written = 0;
+ size_t bytes_written;
+ size_t total_written = 0;
struct connectdata *conn = data->conn;
struct TELNET *tn = data->req.p.telnet;
DEBUGASSERT(tn);
+ DEBUGASSERT(nread > 0);
+ if(nread < 0)
+ return CURLE_TOO_LARGE;
if(memchr(buffer, CURL_IAC, nread)) {
/* only use the escape buffer when necessary */
Curl_dyn_reset(&tn->out);
- for(i = 0; i < nread && !result; i++) {
+ for(i = 0; i < (size_t)nread && !result; i++) {
result = Curl_dyn_addn(&tn->out, &buffer[i], 1);
if(!result && ((unsigned char)buffer[i] == CURL_IAC))
/* IAC is FF in hex */
outbuf = Curl_dyn_uptr(&tn->out);
}
else {
- outlen = nread;
+ outlen = (size_t)nread;
outbuf = (unsigned char *)buffer;
}
while(!result && total_written < outlen) {
#endif
#define curl_upload_refill_watermark(data) \
- ((ssize_t)((data)->set.upload_buffer_size >> 5))
+ ((size_t)((data)->set.upload_buffer_size >> 5))
/*
* Send data to upload to the server, when the socket is writable.
int *didwhat)
{
ssize_t i, si;
- ssize_t bytes_written;
+ size_t bytes_written;
CURLcode result;
ssize_t nread; /* number of bytes read */
bool sending_http_headers = FALSE;
*didwhat |= KEEP_SEND;
+ if(!(k->keepon & KEEP_SEND_PAUSE)) {
+ result = Curl_req_flush(data);
+ if(result == CURLE_AGAIN) /* unable to send all we have */
+ return CURLE_OK;
+ else if(result)
+ return result;
+ }
+
do {
curl_off_t nbody;
ssize_t offset = 0;
k->upload_present < curl_upload_refill_watermark(data) &&
!k->upload_chunky &&/*(variable sized chunked header; append not safe)*/
!k->upload_done && /*!(k->upload_done once k->upload_present sent)*/
- !(k->writebytecount + k->upload_present - k->pendingheader ==
- data->state.infilesize)) {
+ !(k->writebytecount + (curl_off_t)k->upload_present -
+ (curl_off_t)k->pendingheader == data->state.infilesize)) {
offset = k->upload_present;
}
that instead of reading more data */
}
- if(!Curl_bufq_is_empty(&k->sendbuf)) {
- DEBUGASSERT(0);
- }
/* write to socket (send away data) */
result = Curl_xfer_send(data,
k->upload_fromhere, /* buffer pointer */
if(k->pendingheader) {
/* parts of what was sent was header */
- curl_off_t n = CURLMIN(k->pendingheader, bytes_written);
+ size_t n = CURLMIN(k->pendingheader, bytes_written);
/* show the data before we change the pointer upload_fromhere */
- Curl_debug(data, CURLINFO_HEADER_OUT, k->upload_fromhere, (size_t)n);
+ Curl_debug(data, CURLINFO_HEADER_OUT, k->upload_fromhere, n);
k->pendingheader -= n;
nbody = bytes_written - n; /* size of the written body part */
}
struct SingleRequest *k = &data->req;
struct connectdata *conn = data->conn;
struct HTTP *http = data->req.p.http;
- bool httpsending;
+ bool want_send = Curl_req_want_send(data);
DEBUGASSERT(conn != NULL);
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
DEBUGASSERT((writesockindex <= 1) && (writesockindex >= -1));
- httpsending = ((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
- (http->sending == HTTPSEND_REQUEST));
-
- if(conn->bits.multiplex || conn->httpversion >= 20 || httpsending) {
+ if(conn->bits.multiplex || conn->httpversion >= 20 || want_send) {
/* when multiplexing, the read/write sockets need to be the same! */
conn->sockfd = sockindex == -1 ?
((writesockindex == -1 ? CURL_SOCKET_BAD : conn->sock[writesockindex])) :
conn->sock[sockindex];
conn->writesockfd = conn->sockfd;
- if(httpsending)
+ if(want_send)
/* special and very HTTP-specific */
writesockindex = FIRSTSOCKET;
}
CURLcode Curl_xfer_send(struct Curl_easy *data,
const void *buf, size_t blen,
- ssize_t *pnwritten)
+ size_t *pnwritten)
{
CURLcode result;
int sockindex;
*/
CURLcode Curl_xfer_send(struct Curl_easy *data,
const void *buf, size_t blen,
- ssize_t *pnwritten);
+ size_t *pnwritten);
/**
* Receive data on the socket/connection filter designated
/* init the single-transfer specific 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;
/* call the stuff that needs to be called */
result = create_conn(data, &conn, asyncp);
size_t length, int flags, void **abstract)
{
struct Curl_easy *data = (struct Curl_easy *)*abstract;
- ssize_t nwrite;
+ size_t nwrite;
CURLcode result;
struct connectdata *conn = data->conn;
Curl_send *backup = conn->send[0];
return -EAGAIN; /* magic return code for libssh2 */
else if(result)
return -1; /* error */
- Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, (size_t)nwrite);
- return nwrite;
+ Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, nwrite);
+ return (ssize_t)nwrite;
}
#endif
if(!Curl_bufq_is_empty(&ws->sendbuf)) {
CURLcode result;
const unsigned char *out;
- size_t outlen;
- ssize_t n;
+ size_t outlen, n;
while(Curl_bufq_peek(&ws->sendbuf, &out, &outlen)) {
if(data->set.connect_only)
}
}
else {
- infof(data, "WS: flushed %zu bytes", (size_t)n);
- Curl_bufq_skip(&ws->sendbuf, (size_t)n);
+ infof(data, "WS: flushed %zu bytes", n);
+ Curl_bufq_skip(&ws->sendbuf, n);
}
}
}
unsigned int flags)
{
struct websocket *ws;
- ssize_t nwritten, n;
- size_t space;
+ ssize_t n;
+ size_t nwritten, space;
CURLcode result;
*sent = 0;
infof(data, "WS: wanted to send %zu bytes, sent %zu bytes",
buflen, nwritten);
- *sent = (nwritten >= 0)? (size_t)nwritten : 0;
+ *sent = nwritten;
return result;
}