summaryrefslogtreecommitdiff
path: root/lib/transfer.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2022-11-22 08:25:50 +0100
committerDaniel Stenberg <daniel@haxx.se>2022-11-25 08:30:26 +0100
commit1b3973180b6b7f1023240a67d3acdb11b534bf03 (patch)
tree17be952a0a29f34d8fbcc4217aa67d1a868c66ef /lib/transfer.c
parent9ecebb5d008305265f37b289ea928c7802df7f31 (diff)
downloadcurl-1b3973180b6b7f1023240a67d3acdb11b534bf03.tar.gz
lib: rewind BEFORE request instead of AFTER previous
This makes a big difference for cases when the rewind is not actually necessary to perofm (for example HTTP response code 301 converts to GET) and therefore the rewind can be avoided. In particular for situations when that rewind fails, for example when reading from a pipe or similar. Reported-by: Ali Utku Selen Fixes #9735 Closes #9958
Diffstat (limited to 'lib/transfer.c')
-rw-r--r--lib/transfer.c100
1 files changed, 4 insertions, 96 deletions
diff --git a/lib/transfer.c b/lib/transfer.c
index c10f7e38d..ba0410fc5 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -363,88 +363,6 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
return CURLE_OK;
}
-
-/*
- * Curl_readrewind() rewinds the read stream. This is typically used for HTTP
- * POST/PUT with multi-pass authentication when a sending was denied and a
- * resend is necessary.
- */
-CURLcode Curl_readrewind(struct Curl_easy *data)
-{
- struct connectdata *conn = data->conn;
- curl_mimepart *mimepart = &data->set.mimepost;
-
- conn->bits.rewindaftersend = FALSE; /* we rewind now */
-
- /* explicitly switch off sending data on this connection now since we are
- about to restart a new transfer and thus we want to avoid inadvertently
- sending more data on the existing connection until the next transfer
- starts */
- data->req.keepon &= ~KEEP_SEND;
-
- /* We have sent away data. If not using CURLOPT_POSTFIELDS or
- CURLOPT_HTTPPOST, call app to rewind
- */
- if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
- struct HTTP *http = data->req.p.http;
-
- if(http->sendit)
- mimepart = http->sendit;
- }
- if(data->set.postfields)
- ; /* do nothing */
- else if(data->state.httpreq == HTTPREQ_POST_MIME ||
- data->state.httpreq == HTTPREQ_POST_FORM) {
- CURLcode result = Curl_mime_rewind(mimepart);
- if(result) {
- failf(data, "Cannot rewind mime/post data");
- return result;
- }
- }
- else {
- if(data->set.seek_func) {
- int err;
-
- Curl_set_in_callback(data, true);
- err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
- Curl_set_in_callback(data, false);
- if(err) {
- failf(data, "seek callback returned error %d", (int)err);
- return CURLE_SEND_FAIL_REWIND;
- }
- }
- else if(data->set.ioctl_func) {
- curlioerr err;
-
- Curl_set_in_callback(data, true);
- err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
- data->set.ioctl_client);
- Curl_set_in_callback(data, false);
- infof(data, "the ioctl callback returned %d", (int)err);
-
- if(err) {
- failf(data, "ioctl callback returned error %d", (int)err);
- return CURLE_SEND_FAIL_REWIND;
- }
- }
- else {
- /* If no CURLOPT_READFUNCTION is used, we know that we operate on a
- given FILE * stream and we can actually attempt to rewind that
- ourselves with fseek() */
- if(data->state.fread_func == (curl_read_callback)fread) {
- if(-1 != fseek(data->state.in, 0, SEEK_SET))
- /* successful rewind */
- return CURLE_OK;
- }
-
- /* no callback set or failure above, makes us fail at once */
- failf(data, "necessary data rewind wasn't possible");
- return CURLE_SEND_FAIL_REWIND;
- }
- }
- return CURLE_OK;
-}
-
static int data_pending(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
@@ -895,11 +813,6 @@ CURLcode Curl_done_sending(struct Curl_easy *data,
Curl_http2_done_sending(data, conn);
Curl_quic_done_sending(data);
- if(conn->bits.rewindaftersend) {
- CURLcode result = Curl_readrewind(data);
- if(result)
- return result;
- }
return CURLE_OK;
}
@@ -1383,7 +1296,6 @@ int Curl_single_getsock(struct Curl_easy *data,
/* don't include HOLD and PAUSE connections */
if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) {
-
if((conn->sockfd != conn->writesockfd) ||
bitmap == GETSOCK_BLANK) {
/* only if they are not the same socket and we have a readable
@@ -1925,14 +1837,10 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
transferred! */
- if(conn->handler->protocol&PROTO_FAMILY_HTTP) {
- if(data->req.writebytecount) {
- CURLcode result = Curl_readrewind(data);
- if(result) {
- Curl_safefree(*url);
- return result;
- }
- }
+ if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
+ data->req.writebytecount) {
+ data->state.rewindbeforesend = TRUE;
+ infof(data, "state.rewindbeforesend = TRUE");
}
}
return CURLE_OK;