1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker
25*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
26*6236dae4SAndroid Build Coastguard Worker #include "strtoofft.h"
27*6236dae4SAndroid Build Coastguard Worker
28*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
29*6236dae4SAndroid Build Coastguard Worker #include <netinet/in.h>
30*6236dae4SAndroid Build Coastguard Worker #endif
31*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETDB_H
32*6236dae4SAndroid Build Coastguard Worker #include <netdb.h>
33*6236dae4SAndroid Build Coastguard Worker #endif
34*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ARPA_INET_H
35*6236dae4SAndroid Build Coastguard Worker #include <arpa/inet.h>
36*6236dae4SAndroid Build Coastguard Worker #endif
37*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NET_IF_H
38*6236dae4SAndroid Build Coastguard Worker #include <net/if.h>
39*6236dae4SAndroid Build Coastguard Worker #endif
40*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SYS_IOCTL_H
41*6236dae4SAndroid Build Coastguard Worker #include <sys/ioctl.h>
42*6236dae4SAndroid Build Coastguard Worker #endif
43*6236dae4SAndroid Build Coastguard Worker #include <signal.h>
44*6236dae4SAndroid Build Coastguard Worker
45*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SYS_PARAM_H
46*6236dae4SAndroid Build Coastguard Worker #include <sys/param.h>
47*6236dae4SAndroid Build Coastguard Worker #endif
48*6236dae4SAndroid Build Coastguard Worker
49*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SYS_SELECT_H
50*6236dae4SAndroid Build Coastguard Worker #include <sys/select.h>
51*6236dae4SAndroid Build Coastguard Worker #elif defined(HAVE_UNISTD_H)
52*6236dae4SAndroid Build Coastguard Worker #include <unistd.h>
53*6236dae4SAndroid Build Coastguard Worker #endif
54*6236dae4SAndroid Build Coastguard Worker
55*6236dae4SAndroid Build Coastguard Worker #ifndef HAVE_SOCKET
56*6236dae4SAndroid Build Coastguard Worker #error "We cannot compile without socket() support!"
57*6236dae4SAndroid Build Coastguard Worker #endif
58*6236dae4SAndroid Build Coastguard Worker
59*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
60*6236dae4SAndroid Build Coastguard Worker #include <curl/curl.h>
61*6236dae4SAndroid Build Coastguard Worker #include "netrc.h"
62*6236dae4SAndroid Build Coastguard Worker
63*6236dae4SAndroid Build Coastguard Worker #include "content_encoding.h"
64*6236dae4SAndroid Build Coastguard Worker #include "hostip.h"
65*6236dae4SAndroid Build Coastguard Worker #include "cfilters.h"
66*6236dae4SAndroid Build Coastguard Worker #include "cw-out.h"
67*6236dae4SAndroid Build Coastguard Worker #include "transfer.h"
68*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
69*6236dae4SAndroid Build Coastguard Worker #include "speedcheck.h"
70*6236dae4SAndroid Build Coastguard Worker #include "progress.h"
71*6236dae4SAndroid Build Coastguard Worker #include "http.h"
72*6236dae4SAndroid Build Coastguard Worker #include "url.h"
73*6236dae4SAndroid Build Coastguard Worker #include "getinfo.h"
74*6236dae4SAndroid Build Coastguard Worker #include "vtls/vtls.h"
75*6236dae4SAndroid Build Coastguard Worker #include "vquic/vquic.h"
76*6236dae4SAndroid Build Coastguard Worker #include "select.h"
77*6236dae4SAndroid Build Coastguard Worker #include "multiif.h"
78*6236dae4SAndroid Build Coastguard Worker #include "connect.h"
79*6236dae4SAndroid Build Coastguard Worker #include "http2.h"
80*6236dae4SAndroid Build Coastguard Worker #include "mime.h"
81*6236dae4SAndroid Build Coastguard Worker #include "strcase.h"
82*6236dae4SAndroid Build Coastguard Worker #include "hsts.h"
83*6236dae4SAndroid Build Coastguard Worker #include "setopt.h"
84*6236dae4SAndroid Build Coastguard Worker #include "headers.h"
85*6236dae4SAndroid Build Coastguard Worker
86*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
87*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
88*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
89*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
90*6236dae4SAndroid Build Coastguard Worker
91*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
92*6236dae4SAndroid Build Coastguard Worker !defined(CURL_DISABLE_IMAP)
93*6236dae4SAndroid Build Coastguard Worker /*
94*6236dae4SAndroid Build Coastguard Worker * checkheaders() checks the linked list of custom headers for a
95*6236dae4SAndroid Build Coastguard Worker * particular header (prefix). Provide the prefix without colon!
96*6236dae4SAndroid Build Coastguard Worker *
97*6236dae4SAndroid Build Coastguard Worker * Returns a pointer to the first matching header or NULL if none matched.
98*6236dae4SAndroid Build Coastguard Worker */
Curl_checkheaders(const struct Curl_easy * data,const char * thisheader,const size_t thislen)99*6236dae4SAndroid Build Coastguard Worker char *Curl_checkheaders(const struct Curl_easy *data,
100*6236dae4SAndroid Build Coastguard Worker const char *thisheader,
101*6236dae4SAndroid Build Coastguard Worker const size_t thislen)
102*6236dae4SAndroid Build Coastguard Worker {
103*6236dae4SAndroid Build Coastguard Worker struct curl_slist *head;
104*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(thislen);
105*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(thisheader[thislen-1] != ':');
106*6236dae4SAndroid Build Coastguard Worker
107*6236dae4SAndroid Build Coastguard Worker for(head = data->set.headers; head; head = head->next) {
108*6236dae4SAndroid Build Coastguard Worker if(strncasecompare(head->data, thisheader, thislen) &&
109*6236dae4SAndroid Build Coastguard Worker Curl_headersep(head->data[thislen]) )
110*6236dae4SAndroid Build Coastguard Worker return head->data;
111*6236dae4SAndroid Build Coastguard Worker }
112*6236dae4SAndroid Build Coastguard Worker
113*6236dae4SAndroid Build Coastguard Worker return NULL;
114*6236dae4SAndroid Build Coastguard Worker }
115*6236dae4SAndroid Build Coastguard Worker #endif
116*6236dae4SAndroid Build Coastguard Worker
data_pending(struct Curl_easy * data)117*6236dae4SAndroid Build Coastguard Worker static int data_pending(struct Curl_easy *data)
118*6236dae4SAndroid Build Coastguard Worker {
119*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
120*6236dae4SAndroid Build Coastguard Worker
121*6236dae4SAndroid Build Coastguard Worker if(conn->handler->protocol&PROTO_FAMILY_FTP)
122*6236dae4SAndroid Build Coastguard Worker return Curl_conn_data_pending(data, SECONDARYSOCKET);
123*6236dae4SAndroid Build Coastguard Worker
124*6236dae4SAndroid Build Coastguard Worker /* in the case of libssh2, we can never be really sure that we have emptied
125*6236dae4SAndroid Build Coastguard Worker its internal buffers so we MUST always try until we get EAGAIN back */
126*6236dae4SAndroid Build Coastguard Worker return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) ||
127*6236dae4SAndroid Build Coastguard Worker Curl_conn_data_pending(data, FIRSTSOCKET);
128*6236dae4SAndroid Build Coastguard Worker }
129*6236dae4SAndroid Build Coastguard Worker
130*6236dae4SAndroid Build Coastguard Worker /*
131*6236dae4SAndroid Build Coastguard Worker * Check to see if CURLOPT_TIMECONDITION was met by comparing the time of the
132*6236dae4SAndroid Build Coastguard Worker * remote document with the time provided by CURLOPT_TIMEVAL
133*6236dae4SAndroid Build Coastguard Worker */
Curl_meets_timecondition(struct Curl_easy * data,time_t timeofdoc)134*6236dae4SAndroid Build Coastguard Worker bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc)
135*6236dae4SAndroid Build Coastguard Worker {
136*6236dae4SAndroid Build Coastguard Worker if((timeofdoc == 0) || (data->set.timevalue == 0))
137*6236dae4SAndroid Build Coastguard Worker return TRUE;
138*6236dae4SAndroid Build Coastguard Worker
139*6236dae4SAndroid Build Coastguard Worker switch(data->set.timecondition) {
140*6236dae4SAndroid Build Coastguard Worker case CURL_TIMECOND_IFMODSINCE:
141*6236dae4SAndroid Build Coastguard Worker default:
142*6236dae4SAndroid Build Coastguard Worker if(timeofdoc <= data->set.timevalue) {
143*6236dae4SAndroid Build Coastguard Worker infof(data,
144*6236dae4SAndroid Build Coastguard Worker "The requested document is not new enough");
145*6236dae4SAndroid Build Coastguard Worker data->info.timecond = TRUE;
146*6236dae4SAndroid Build Coastguard Worker return FALSE;
147*6236dae4SAndroid Build Coastguard Worker }
148*6236dae4SAndroid Build Coastguard Worker break;
149*6236dae4SAndroid Build Coastguard Worker case CURL_TIMECOND_IFUNMODSINCE:
150*6236dae4SAndroid Build Coastguard Worker if(timeofdoc >= data->set.timevalue) {
151*6236dae4SAndroid Build Coastguard Worker infof(data,
152*6236dae4SAndroid Build Coastguard Worker "The requested document is not old enough");
153*6236dae4SAndroid Build Coastguard Worker data->info.timecond = TRUE;
154*6236dae4SAndroid Build Coastguard Worker return FALSE;
155*6236dae4SAndroid Build Coastguard Worker }
156*6236dae4SAndroid Build Coastguard Worker break;
157*6236dae4SAndroid Build Coastguard Worker }
158*6236dae4SAndroid Build Coastguard Worker
159*6236dae4SAndroid Build Coastguard Worker return TRUE;
160*6236dae4SAndroid Build Coastguard Worker }
161*6236dae4SAndroid Build Coastguard Worker
xfer_recv_shutdown(struct Curl_easy * data,bool * done)162*6236dae4SAndroid Build Coastguard Worker static CURLcode xfer_recv_shutdown(struct Curl_easy *data, bool *done)
163*6236dae4SAndroid Build Coastguard Worker {
164*6236dae4SAndroid Build Coastguard Worker int sockindex;
165*6236dae4SAndroid Build Coastguard Worker
166*6236dae4SAndroid Build Coastguard Worker if(!data || !data->conn)
167*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
168*6236dae4SAndroid Build Coastguard Worker if(data->conn->sockfd == CURL_SOCKET_BAD)
169*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
170*6236dae4SAndroid Build Coastguard Worker sockindex = (data->conn->sockfd == data->conn->sock[SECONDARYSOCKET]);
171*6236dae4SAndroid Build Coastguard Worker return Curl_conn_shutdown(data, sockindex, done);
172*6236dae4SAndroid Build Coastguard Worker }
173*6236dae4SAndroid Build Coastguard Worker
xfer_recv_shutdown_started(struct Curl_easy * data)174*6236dae4SAndroid Build Coastguard Worker static bool xfer_recv_shutdown_started(struct Curl_easy *data)
175*6236dae4SAndroid Build Coastguard Worker {
176*6236dae4SAndroid Build Coastguard Worker int sockindex;
177*6236dae4SAndroid Build Coastguard Worker
178*6236dae4SAndroid Build Coastguard Worker if(!data || !data->conn)
179*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
180*6236dae4SAndroid Build Coastguard Worker if(data->conn->sockfd == CURL_SOCKET_BAD)
181*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
182*6236dae4SAndroid Build Coastguard Worker sockindex = (data->conn->sockfd == data->conn->sock[SECONDARYSOCKET]);
183*6236dae4SAndroid Build Coastguard Worker return Curl_shutdown_started(data, sockindex);
184*6236dae4SAndroid Build Coastguard Worker }
185*6236dae4SAndroid Build Coastguard Worker
Curl_xfer_send_shutdown(struct Curl_easy * data,bool * done)186*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_xfer_send_shutdown(struct Curl_easy *data, bool *done)
187*6236dae4SAndroid Build Coastguard Worker {
188*6236dae4SAndroid Build Coastguard Worker int sockindex;
189*6236dae4SAndroid Build Coastguard Worker
190*6236dae4SAndroid Build Coastguard Worker if(!data || !data->conn)
191*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
192*6236dae4SAndroid Build Coastguard Worker if(data->conn->writesockfd == CURL_SOCKET_BAD)
193*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
194*6236dae4SAndroid Build Coastguard Worker sockindex = (data->conn->writesockfd == data->conn->sock[SECONDARYSOCKET]);
195*6236dae4SAndroid Build Coastguard Worker return Curl_conn_shutdown(data, sockindex, done);
196*6236dae4SAndroid Build Coastguard Worker }
197*6236dae4SAndroid Build Coastguard Worker
198*6236dae4SAndroid Build Coastguard Worker /**
199*6236dae4SAndroid Build Coastguard Worker * Receive raw response data for the transfer.
200*6236dae4SAndroid Build Coastguard Worker * @param data the transfer
201*6236dae4SAndroid Build Coastguard Worker * @param buf buffer to keep response data received
202*6236dae4SAndroid Build Coastguard Worker * @param blen length of `buf`
203*6236dae4SAndroid Build Coastguard Worker * @param eos_reliable if EOS detection in underlying connection is reliable
204*6236dae4SAndroid Build Coastguard Worker * @param err error code in case of -1 return
205*6236dae4SAndroid Build Coastguard Worker * @return number of bytes read or -1 for error
206*6236dae4SAndroid Build Coastguard Worker */
xfer_recv_resp(struct Curl_easy * data,char * buf,size_t blen,bool eos_reliable,CURLcode * err)207*6236dae4SAndroid Build Coastguard Worker static ssize_t xfer_recv_resp(struct Curl_easy *data,
208*6236dae4SAndroid Build Coastguard Worker char *buf, size_t blen,
209*6236dae4SAndroid Build Coastguard Worker bool eos_reliable,
210*6236dae4SAndroid Build Coastguard Worker CURLcode *err)
211*6236dae4SAndroid Build Coastguard Worker {
212*6236dae4SAndroid Build Coastguard Worker ssize_t nread;
213*6236dae4SAndroid Build Coastguard Worker
214*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(blen > 0);
215*6236dae4SAndroid Build Coastguard Worker /* If we are reading BODY data and the connection does NOT handle EOF
216*6236dae4SAndroid Build Coastguard Worker * and we know the size of the BODY data, limit the read amount */
217*6236dae4SAndroid Build Coastguard Worker if(!eos_reliable && !data->req.header && data->req.size != -1) {
218*6236dae4SAndroid Build Coastguard Worker curl_off_t totalleft = data->req.size - data->req.bytecount;
219*6236dae4SAndroid Build Coastguard Worker if(totalleft <= 0)
220*6236dae4SAndroid Build Coastguard Worker blen = 0;
221*6236dae4SAndroid Build Coastguard Worker else if(totalleft < (curl_off_t)blen)
222*6236dae4SAndroid Build Coastguard Worker blen = (size_t)totalleft;
223*6236dae4SAndroid Build Coastguard Worker }
224*6236dae4SAndroid Build Coastguard Worker else if(xfer_recv_shutdown_started(data)) {
225*6236dae4SAndroid Build Coastguard Worker /* we already received everything. Do not try more. */
226*6236dae4SAndroid Build Coastguard Worker blen = 0;
227*6236dae4SAndroid Build Coastguard Worker }
228*6236dae4SAndroid Build Coastguard Worker
229*6236dae4SAndroid Build Coastguard Worker if(!blen) {
230*6236dae4SAndroid Build Coastguard Worker /* want nothing more */
231*6236dae4SAndroid Build Coastguard Worker *err = CURLE_OK;
232*6236dae4SAndroid Build Coastguard Worker nread = 0;
233*6236dae4SAndroid Build Coastguard Worker }
234*6236dae4SAndroid Build Coastguard Worker else {
235*6236dae4SAndroid Build Coastguard Worker *err = Curl_xfer_recv(data, buf, blen, &nread);
236*6236dae4SAndroid Build Coastguard Worker }
237*6236dae4SAndroid Build Coastguard Worker
238*6236dae4SAndroid Build Coastguard Worker if(*err)
239*6236dae4SAndroid Build Coastguard Worker return -1;
240*6236dae4SAndroid Build Coastguard Worker if(nread == 0) {
241*6236dae4SAndroid Build Coastguard Worker if(data->req.shutdown) {
242*6236dae4SAndroid Build Coastguard Worker bool done;
243*6236dae4SAndroid Build Coastguard Worker *err = xfer_recv_shutdown(data, &done);
244*6236dae4SAndroid Build Coastguard Worker if(*err)
245*6236dae4SAndroid Build Coastguard Worker return -1;
246*6236dae4SAndroid Build Coastguard Worker if(!done) {
247*6236dae4SAndroid Build Coastguard Worker *err = CURLE_AGAIN;
248*6236dae4SAndroid Build Coastguard Worker return -1;
249*6236dae4SAndroid Build Coastguard Worker }
250*6236dae4SAndroid Build Coastguard Worker }
251*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "sendrecv_dl: we are done"));
252*6236dae4SAndroid Build Coastguard Worker }
253*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(nread >= 0);
254*6236dae4SAndroid Build Coastguard Worker return nread;
255*6236dae4SAndroid Build Coastguard Worker }
256*6236dae4SAndroid Build Coastguard Worker
257*6236dae4SAndroid Build Coastguard Worker /*
258*6236dae4SAndroid Build Coastguard Worker * Go ahead and do a read if we have a readable socket or if
259*6236dae4SAndroid Build Coastguard Worker * the stream was rewound (in which case we have data in a
260*6236dae4SAndroid Build Coastguard Worker * buffer)
261*6236dae4SAndroid Build Coastguard Worker */
sendrecv_dl(struct Curl_easy * data,struct SingleRequest * k,int * didwhat)262*6236dae4SAndroid Build Coastguard Worker static CURLcode sendrecv_dl(struct Curl_easy *data,
263*6236dae4SAndroid Build Coastguard Worker struct SingleRequest *k,
264*6236dae4SAndroid Build Coastguard Worker int *didwhat)
265*6236dae4SAndroid Build Coastguard Worker {
266*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
267*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
268*6236dae4SAndroid Build Coastguard Worker char *buf, *xfer_buf;
269*6236dae4SAndroid Build Coastguard Worker size_t blen, xfer_blen;
270*6236dae4SAndroid Build Coastguard Worker int maxloops = 10;
271*6236dae4SAndroid Build Coastguard Worker curl_off_t total_received = 0;
272*6236dae4SAndroid Build Coastguard Worker bool is_multiplex = FALSE;
273*6236dae4SAndroid Build Coastguard Worker
274*6236dae4SAndroid Build Coastguard Worker result = Curl_multi_xfer_buf_borrow(data, &xfer_buf, &xfer_blen);
275*6236dae4SAndroid Build Coastguard Worker if(result)
276*6236dae4SAndroid Build Coastguard Worker goto out;
277*6236dae4SAndroid Build Coastguard Worker
278*6236dae4SAndroid Build Coastguard Worker /* This is where we loop until we have read everything there is to
279*6236dae4SAndroid Build Coastguard Worker read or we get a CURLE_AGAIN */
280*6236dae4SAndroid Build Coastguard Worker do {
281*6236dae4SAndroid Build Coastguard Worker bool is_eos = FALSE;
282*6236dae4SAndroid Build Coastguard Worker size_t bytestoread;
283*6236dae4SAndroid Build Coastguard Worker ssize_t nread;
284*6236dae4SAndroid Build Coastguard Worker
285*6236dae4SAndroid Build Coastguard Worker if(!is_multiplex) {
286*6236dae4SAndroid Build Coastguard Worker /* Multiplexed connection have inherent handling of EOF and we do not
287*6236dae4SAndroid Build Coastguard Worker * have to carefully restrict the amount we try to read.
288*6236dae4SAndroid Build Coastguard Worker * Multiplexed changes only in one direction. */
289*6236dae4SAndroid Build Coastguard Worker is_multiplex = Curl_conn_is_multiplex(conn, FIRSTSOCKET);
290*6236dae4SAndroid Build Coastguard Worker }
291*6236dae4SAndroid Build Coastguard Worker
292*6236dae4SAndroid Build Coastguard Worker buf = xfer_buf;
293*6236dae4SAndroid Build Coastguard Worker bytestoread = xfer_blen;
294*6236dae4SAndroid Build Coastguard Worker
295*6236dae4SAndroid Build Coastguard Worker if(bytestoread && data->set.max_recv_speed > 0) {
296*6236dae4SAndroid Build Coastguard Worker /* In case of speed limit on receiving: if this loop already got
297*6236dae4SAndroid Build Coastguard Worker * data, break out. If not, limit the amount of bytes to receive.
298*6236dae4SAndroid Build Coastguard Worker * The overall, timed, speed limiting is done in multi.c */
299*6236dae4SAndroid Build Coastguard Worker if(total_received)
300*6236dae4SAndroid Build Coastguard Worker break;
301*6236dae4SAndroid Build Coastguard Worker if(data->set.max_recv_speed < (curl_off_t)bytestoread)
302*6236dae4SAndroid Build Coastguard Worker bytestoread = (size_t)data->set.max_recv_speed;
303*6236dae4SAndroid Build Coastguard Worker }
304*6236dae4SAndroid Build Coastguard Worker
305*6236dae4SAndroid Build Coastguard Worker nread = xfer_recv_resp(data, buf, bytestoread, is_multiplex, &result);
306*6236dae4SAndroid Build Coastguard Worker if(nread < 0) {
307*6236dae4SAndroid Build Coastguard Worker if(CURLE_AGAIN != result)
308*6236dae4SAndroid Build Coastguard Worker goto out; /* real error */
309*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
310*6236dae4SAndroid Build Coastguard Worker if(data->req.download_done && data->req.no_body &&
311*6236dae4SAndroid Build Coastguard Worker !data->req.resp_trailer) {
312*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "EAGAIN, download done, no trailer announced, "
313*6236dae4SAndroid Build Coastguard Worker "not waiting for EOS"));
314*6236dae4SAndroid Build Coastguard Worker nread = 0;
315*6236dae4SAndroid Build Coastguard Worker /* continue as if we read the EOS */
316*6236dae4SAndroid Build Coastguard Worker }
317*6236dae4SAndroid Build Coastguard Worker else
318*6236dae4SAndroid Build Coastguard Worker break; /* get out of loop */
319*6236dae4SAndroid Build Coastguard Worker }
320*6236dae4SAndroid Build Coastguard Worker
321*6236dae4SAndroid Build Coastguard Worker /* We only get a 0-length read on EndOfStream */
322*6236dae4SAndroid Build Coastguard Worker blen = (size_t)nread;
323*6236dae4SAndroid Build Coastguard Worker is_eos = (blen == 0);
324*6236dae4SAndroid Build Coastguard Worker *didwhat |= KEEP_RECV;
325*6236dae4SAndroid Build Coastguard Worker
326*6236dae4SAndroid Build Coastguard Worker if(!blen) {
327*6236dae4SAndroid Build Coastguard Worker /* if we receive 0 or less here, either the data transfer is done or the
328*6236dae4SAndroid Build Coastguard Worker server closed the connection and we bail out from this! */
329*6236dae4SAndroid Build Coastguard Worker if(is_multiplex)
330*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "nread == 0, stream closed, bailing"));
331*6236dae4SAndroid Build Coastguard Worker else
332*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "nread <= 0, server closed connection, bailing"));
333*6236dae4SAndroid Build Coastguard Worker result = Curl_req_stop_send_recv(data);
334*6236dae4SAndroid Build Coastguard Worker if(result)
335*6236dae4SAndroid Build Coastguard Worker goto out;
336*6236dae4SAndroid Build Coastguard Worker if(k->eos_written) /* already did write this to client, leave */
337*6236dae4SAndroid Build Coastguard Worker break;
338*6236dae4SAndroid Build Coastguard Worker }
339*6236dae4SAndroid Build Coastguard Worker total_received += blen;
340*6236dae4SAndroid Build Coastguard Worker
341*6236dae4SAndroid Build Coastguard Worker result = Curl_xfer_write_resp(data, buf, blen, is_eos);
342*6236dae4SAndroid Build Coastguard Worker if(result || data->req.done)
343*6236dae4SAndroid Build Coastguard Worker goto out;
344*6236dae4SAndroid Build Coastguard Worker
345*6236dae4SAndroid Build Coastguard Worker /* if we are done, we stop receiving. On multiplexed connections,
346*6236dae4SAndroid Build Coastguard Worker * we should read the EOS. Which may arrive as meta data after
347*6236dae4SAndroid Build Coastguard Worker * the bytes. Not taking it in might lead to RST of streams. */
348*6236dae4SAndroid Build Coastguard Worker if((!is_multiplex && data->req.download_done) || is_eos) {
349*6236dae4SAndroid Build Coastguard Worker data->req.keepon &= ~KEEP_RECV;
350*6236dae4SAndroid Build Coastguard Worker }
351*6236dae4SAndroid Build Coastguard Worker /* if we are PAUSEd or stopped receiving, leave the loop */
352*6236dae4SAndroid Build Coastguard Worker if((k->keepon & KEEP_RECV_PAUSE) || !(k->keepon & KEEP_RECV))
353*6236dae4SAndroid Build Coastguard Worker break;
354*6236dae4SAndroid Build Coastguard Worker
355*6236dae4SAndroid Build Coastguard Worker } while(maxloops--);
356*6236dae4SAndroid Build Coastguard Worker
357*6236dae4SAndroid Build Coastguard Worker if((maxloops <= 0) || data_pending(data)) {
358*6236dae4SAndroid Build Coastguard Worker /* did not read until EAGAIN or there is still pending data, mark as
359*6236dae4SAndroid Build Coastguard Worker read-again-please */
360*6236dae4SAndroid Build Coastguard Worker data->state.select_bits = CURL_CSELECT_IN;
361*6236dae4SAndroid Build Coastguard Worker if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
362*6236dae4SAndroid Build Coastguard Worker data->state.select_bits |= CURL_CSELECT_OUT;
363*6236dae4SAndroid Build Coastguard Worker }
364*6236dae4SAndroid Build Coastguard Worker
365*6236dae4SAndroid Build Coastguard Worker if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
366*6236dae4SAndroid Build Coastguard Worker (conn->bits.close || is_multiplex)) {
367*6236dae4SAndroid Build Coastguard Worker /* When we have read the entire thing and the close bit is set, the server
368*6236dae4SAndroid Build Coastguard Worker may now close the connection. If there is now any kind of sending going
369*6236dae4SAndroid Build Coastguard Worker on from our side, we need to stop that immediately. */
370*6236dae4SAndroid Build Coastguard Worker infof(data, "we are done reading and this is set to close, stop send");
371*6236dae4SAndroid Build Coastguard Worker Curl_req_abort_sending(data);
372*6236dae4SAndroid Build Coastguard Worker }
373*6236dae4SAndroid Build Coastguard Worker
374*6236dae4SAndroid Build Coastguard Worker out:
375*6236dae4SAndroid Build Coastguard Worker Curl_multi_xfer_buf_release(data, xfer_buf);
376*6236dae4SAndroid Build Coastguard Worker if(result)
377*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "sendrecv_dl() -> %d", result));
378*6236dae4SAndroid Build Coastguard Worker return result;
379*6236dae4SAndroid Build Coastguard Worker }
380*6236dae4SAndroid Build Coastguard Worker
381*6236dae4SAndroid Build Coastguard Worker /*
382*6236dae4SAndroid Build Coastguard Worker * Send data to upload to the server, when the socket is writable.
383*6236dae4SAndroid Build Coastguard Worker */
sendrecv_ul(struct Curl_easy * data,int * didwhat)384*6236dae4SAndroid Build Coastguard Worker static CURLcode sendrecv_ul(struct Curl_easy *data, int *didwhat)
385*6236dae4SAndroid Build Coastguard Worker {
386*6236dae4SAndroid Build Coastguard Worker /* We should not get here when the sending is already done. It
387*6236dae4SAndroid Build Coastguard Worker * probably means that someone set `data-req.keepon |= KEEP_SEND`
388*6236dae4SAndroid Build Coastguard Worker * when it should not. */
389*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!Curl_req_done_sending(data));
390*6236dae4SAndroid Build Coastguard Worker
391*6236dae4SAndroid Build Coastguard Worker if(!Curl_req_done_sending(data)) {
392*6236dae4SAndroid Build Coastguard Worker *didwhat |= KEEP_SEND;
393*6236dae4SAndroid Build Coastguard Worker return Curl_req_send_more(data);
394*6236dae4SAndroid Build Coastguard Worker }
395*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
396*6236dae4SAndroid Build Coastguard Worker }
397*6236dae4SAndroid Build Coastguard Worker
select_bits_paused(struct Curl_easy * data,int select_bits)398*6236dae4SAndroid Build Coastguard Worker static int select_bits_paused(struct Curl_easy *data, int select_bits)
399*6236dae4SAndroid Build Coastguard Worker {
400*6236dae4SAndroid Build Coastguard Worker /* See issue #11982: we really need to be careful not to progress
401*6236dae4SAndroid Build Coastguard Worker * a transfer direction when that direction is paused. Not all parts
402*6236dae4SAndroid Build Coastguard Worker * of our state machine are handling PAUSED transfers correctly. So, we
403*6236dae4SAndroid Build Coastguard Worker * do not want to go there.
404*6236dae4SAndroid Build Coastguard Worker * NOTE: we are only interested in PAUSE, not HOLD. */
405*6236dae4SAndroid Build Coastguard Worker
406*6236dae4SAndroid Build Coastguard Worker /* if there is data in a direction not paused, return false */
407*6236dae4SAndroid Build Coastguard Worker if(((select_bits & CURL_CSELECT_IN) &&
408*6236dae4SAndroid Build Coastguard Worker !(data->req.keepon & KEEP_RECV_PAUSE)) ||
409*6236dae4SAndroid Build Coastguard Worker ((select_bits & CURL_CSELECT_OUT) &&
410*6236dae4SAndroid Build Coastguard Worker !(data->req.keepon & KEEP_SEND_PAUSE)))
411*6236dae4SAndroid Build Coastguard Worker return FALSE;
412*6236dae4SAndroid Build Coastguard Worker
413*6236dae4SAndroid Build Coastguard Worker return (data->req.keepon & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE));
414*6236dae4SAndroid Build Coastguard Worker }
415*6236dae4SAndroid Build Coastguard Worker
416*6236dae4SAndroid Build Coastguard Worker /*
417*6236dae4SAndroid Build Coastguard Worker * Curl_sendrecv() is the low-level function to be called when data is to
418*6236dae4SAndroid Build Coastguard Worker * be read and written to/from the connection.
419*6236dae4SAndroid Build Coastguard Worker */
Curl_sendrecv(struct Curl_easy * data,struct curltime * nowp)420*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_sendrecv(struct Curl_easy *data, struct curltime *nowp)
421*6236dae4SAndroid Build Coastguard Worker {
422*6236dae4SAndroid Build Coastguard Worker struct SingleRequest *k = &data->req;
423*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
424*6236dae4SAndroid Build Coastguard Worker int didwhat = 0;
425*6236dae4SAndroid Build Coastguard Worker
426*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(nowp);
427*6236dae4SAndroid Build Coastguard Worker if(data->state.select_bits) {
428*6236dae4SAndroid Build Coastguard Worker if(select_bits_paused(data, data->state.select_bits)) {
429*6236dae4SAndroid Build Coastguard Worker /* leave the bits unchanged, so they'll tell us what to do when
430*6236dae4SAndroid Build Coastguard Worker * this transfer gets unpaused. */
431*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
432*6236dae4SAndroid Build Coastguard Worker goto out;
433*6236dae4SAndroid Build Coastguard Worker }
434*6236dae4SAndroid Build Coastguard Worker data->state.select_bits = 0;
435*6236dae4SAndroid Build Coastguard Worker }
436*6236dae4SAndroid Build Coastguard Worker
437*6236dae4SAndroid Build Coastguard Worker #ifdef USE_HYPER
438*6236dae4SAndroid Build Coastguard Worker if(data->conn->datastream) {
439*6236dae4SAndroid Build Coastguard Worker result = data->conn->datastream(data, data->conn, &didwhat,
440*6236dae4SAndroid Build Coastguard Worker CURL_CSELECT_OUT|CURL_CSELECT_IN);
441*6236dae4SAndroid Build Coastguard Worker if(result || data->req.done)
442*6236dae4SAndroid Build Coastguard Worker goto out;
443*6236dae4SAndroid Build Coastguard Worker }
444*6236dae4SAndroid Build Coastguard Worker else {
445*6236dae4SAndroid Build Coastguard Worker #endif
446*6236dae4SAndroid Build Coastguard Worker /* We go ahead and do a read if we have a readable socket or if the stream
447*6236dae4SAndroid Build Coastguard Worker was rewound (in which case we have data in a buffer) */
448*6236dae4SAndroid Build Coastguard Worker if(k->keepon & KEEP_RECV) {
449*6236dae4SAndroid Build Coastguard Worker result = sendrecv_dl(data, k, &didwhat);
450*6236dae4SAndroid Build Coastguard Worker if(result || data->req.done)
451*6236dae4SAndroid Build Coastguard Worker goto out;
452*6236dae4SAndroid Build Coastguard Worker }
453*6236dae4SAndroid Build Coastguard Worker
454*6236dae4SAndroid Build Coastguard Worker /* If we still have writing to do, we check if we have a writable socket. */
455*6236dae4SAndroid Build Coastguard Worker if(Curl_req_want_send(data) || (data->req.keepon & KEEP_SEND_TIMED)) {
456*6236dae4SAndroid Build Coastguard Worker result = sendrecv_ul(data, &didwhat);
457*6236dae4SAndroid Build Coastguard Worker if(result)
458*6236dae4SAndroid Build Coastguard Worker goto out;
459*6236dae4SAndroid Build Coastguard Worker }
460*6236dae4SAndroid Build Coastguard Worker #ifdef USE_HYPER
461*6236dae4SAndroid Build Coastguard Worker }
462*6236dae4SAndroid Build Coastguard Worker #endif
463*6236dae4SAndroid Build Coastguard Worker
464*6236dae4SAndroid Build Coastguard Worker if(!didwhat) {
465*6236dae4SAndroid Build Coastguard Worker /* Transfer wanted to send/recv, but nothing was possible. */
466*6236dae4SAndroid Build Coastguard Worker result = Curl_conn_ev_data_idle(data);
467*6236dae4SAndroid Build Coastguard Worker if(result)
468*6236dae4SAndroid Build Coastguard Worker goto out;
469*6236dae4SAndroid Build Coastguard Worker }
470*6236dae4SAndroid Build Coastguard Worker
471*6236dae4SAndroid Build Coastguard Worker if(Curl_pgrsUpdate(data))
472*6236dae4SAndroid Build Coastguard Worker result = CURLE_ABORTED_BY_CALLBACK;
473*6236dae4SAndroid Build Coastguard Worker else
474*6236dae4SAndroid Build Coastguard Worker result = Curl_speedcheck(data, *nowp);
475*6236dae4SAndroid Build Coastguard Worker if(result)
476*6236dae4SAndroid Build Coastguard Worker goto out;
477*6236dae4SAndroid Build Coastguard Worker
478*6236dae4SAndroid Build Coastguard Worker if(k->keepon) {
479*6236dae4SAndroid Build Coastguard Worker if(0 > Curl_timeleft(data, nowp, FALSE)) {
480*6236dae4SAndroid Build Coastguard Worker if(k->size != -1) {
481*6236dae4SAndroid Build Coastguard Worker failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
482*6236dae4SAndroid Build Coastguard Worker " milliseconds with %" FMT_OFF_T " out of %"
483*6236dae4SAndroid Build Coastguard Worker FMT_OFF_T " bytes received",
484*6236dae4SAndroid Build Coastguard Worker Curl_timediff(*nowp, data->progress.t_startsingle),
485*6236dae4SAndroid Build Coastguard Worker k->bytecount, k->size);
486*6236dae4SAndroid Build Coastguard Worker }
487*6236dae4SAndroid Build Coastguard Worker else {
488*6236dae4SAndroid Build Coastguard Worker failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
489*6236dae4SAndroid Build Coastguard Worker " milliseconds with %" FMT_OFF_T " bytes received",
490*6236dae4SAndroid Build Coastguard Worker Curl_timediff(*nowp, data->progress.t_startsingle),
491*6236dae4SAndroid Build Coastguard Worker k->bytecount);
492*6236dae4SAndroid Build Coastguard Worker }
493*6236dae4SAndroid Build Coastguard Worker result = CURLE_OPERATION_TIMEDOUT;
494*6236dae4SAndroid Build Coastguard Worker goto out;
495*6236dae4SAndroid Build Coastguard Worker }
496*6236dae4SAndroid Build Coastguard Worker }
497*6236dae4SAndroid Build Coastguard Worker else {
498*6236dae4SAndroid Build Coastguard Worker /*
499*6236dae4SAndroid Build Coastguard Worker * The transfer has been performed. Just make some general checks before
500*6236dae4SAndroid Build Coastguard Worker * returning.
501*6236dae4SAndroid Build Coastguard Worker */
502*6236dae4SAndroid Build Coastguard Worker if(!(data->req.no_body) && (k->size != -1) &&
503*6236dae4SAndroid Build Coastguard Worker (k->bytecount != k->size) && !k->newurl) {
504*6236dae4SAndroid Build Coastguard Worker failf(data, "transfer closed with %" FMT_OFF_T
505*6236dae4SAndroid Build Coastguard Worker " bytes remaining to read", k->size - k->bytecount);
506*6236dae4SAndroid Build Coastguard Worker result = CURLE_PARTIAL_FILE;
507*6236dae4SAndroid Build Coastguard Worker goto out;
508*6236dae4SAndroid Build Coastguard Worker }
509*6236dae4SAndroid Build Coastguard Worker if(Curl_pgrsUpdate(data)) {
510*6236dae4SAndroid Build Coastguard Worker result = CURLE_ABORTED_BY_CALLBACK;
511*6236dae4SAndroid Build Coastguard Worker goto out;
512*6236dae4SAndroid Build Coastguard Worker }
513*6236dae4SAndroid Build Coastguard Worker }
514*6236dae4SAndroid Build Coastguard Worker
515*6236dae4SAndroid Build Coastguard Worker /* If there is nothing more to send/recv, the request is done */
516*6236dae4SAndroid Build Coastguard Worker if(0 == (k->keepon&(KEEP_RECVBITS|KEEP_SENDBITS)))
517*6236dae4SAndroid Build Coastguard Worker data->req.done = TRUE;
518*6236dae4SAndroid Build Coastguard Worker
519*6236dae4SAndroid Build Coastguard Worker out:
520*6236dae4SAndroid Build Coastguard Worker if(result)
521*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "Curl_sendrecv() -> %d", result));
522*6236dae4SAndroid Build Coastguard Worker return result;
523*6236dae4SAndroid Build Coastguard Worker }
524*6236dae4SAndroid Build Coastguard Worker
525*6236dae4SAndroid Build Coastguard Worker /* Curl_init_CONNECT() gets called each time the handle switches to CONNECT
526*6236dae4SAndroid Build Coastguard Worker which means this gets called once for each subsequent redirect etc */
Curl_init_CONNECT(struct Curl_easy * data)527*6236dae4SAndroid Build Coastguard Worker void Curl_init_CONNECT(struct Curl_easy *data)
528*6236dae4SAndroid Build Coastguard Worker {
529*6236dae4SAndroid Build Coastguard Worker data->state.fread_func = data->set.fread_func_set;
530*6236dae4SAndroid Build Coastguard Worker data->state.in = data->set.in_set;
531*6236dae4SAndroid Build Coastguard Worker data->state.upload = (data->state.httpreq == HTTPREQ_PUT);
532*6236dae4SAndroid Build Coastguard Worker }
533*6236dae4SAndroid Build Coastguard Worker
534*6236dae4SAndroid Build Coastguard Worker /*
535*6236dae4SAndroid Build Coastguard Worker * Curl_pretransfer() is called immediately before a transfer starts, and only
536*6236dae4SAndroid Build Coastguard Worker * once for one transfer no matter if it has redirects or do multi-pass
537*6236dae4SAndroid Build Coastguard Worker * authentication etc.
538*6236dae4SAndroid Build Coastguard Worker */
Curl_pretransfer(struct Curl_easy * data)539*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_pretransfer(struct Curl_easy *data)
540*6236dae4SAndroid Build Coastguard Worker {
541*6236dae4SAndroid Build Coastguard Worker CURLcode result;
542*6236dae4SAndroid Build Coastguard Worker
543*6236dae4SAndroid Build Coastguard Worker if(!data->state.url && !data->set.uh) {
544*6236dae4SAndroid Build Coastguard Worker /* we cannot do anything without URL */
545*6236dae4SAndroid Build Coastguard Worker failf(data, "No URL set");
546*6236dae4SAndroid Build Coastguard Worker return CURLE_URL_MALFORMAT;
547*6236dae4SAndroid Build Coastguard Worker }
548*6236dae4SAndroid Build Coastguard Worker
549*6236dae4SAndroid Build Coastguard Worker /* since the URL may have been redirected in a previous use of this handle */
550*6236dae4SAndroid Build Coastguard Worker if(data->state.url_alloc) {
551*6236dae4SAndroid Build Coastguard Worker /* the already set URL is allocated, free it first! */
552*6236dae4SAndroid Build Coastguard Worker Curl_safefree(data->state.url);
553*6236dae4SAndroid Build Coastguard Worker data->state.url_alloc = FALSE;
554*6236dae4SAndroid Build Coastguard Worker }
555*6236dae4SAndroid Build Coastguard Worker
556*6236dae4SAndroid Build Coastguard Worker if(!data->state.url && data->set.uh) {
557*6236dae4SAndroid Build Coastguard Worker CURLUcode uc;
558*6236dae4SAndroid Build Coastguard Worker free(data->set.str[STRING_SET_URL]);
559*6236dae4SAndroid Build Coastguard Worker uc = curl_url_get(data->set.uh,
560*6236dae4SAndroid Build Coastguard Worker CURLUPART_URL, &data->set.str[STRING_SET_URL], 0);
561*6236dae4SAndroid Build Coastguard Worker if(uc) {
562*6236dae4SAndroid Build Coastguard Worker failf(data, "No URL set");
563*6236dae4SAndroid Build Coastguard Worker return CURLE_URL_MALFORMAT;
564*6236dae4SAndroid Build Coastguard Worker }
565*6236dae4SAndroid Build Coastguard Worker }
566*6236dae4SAndroid Build Coastguard Worker
567*6236dae4SAndroid Build Coastguard Worker if(data->set.postfields && data->set.set_resume_from) {
568*6236dae4SAndroid Build Coastguard Worker /* we cannot */
569*6236dae4SAndroid Build Coastguard Worker failf(data, "cannot mix POSTFIELDS with RESUME_FROM");
570*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
571*6236dae4SAndroid Build Coastguard Worker }
572*6236dae4SAndroid Build Coastguard Worker
573*6236dae4SAndroid Build Coastguard Worker data->state.prefer_ascii = data->set.prefer_ascii;
574*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_LIST_ONLY_PROTOCOL
575*6236dae4SAndroid Build Coastguard Worker data->state.list_only = data->set.list_only;
576*6236dae4SAndroid Build Coastguard Worker #endif
577*6236dae4SAndroid Build Coastguard Worker data->state.httpreq = data->set.method;
578*6236dae4SAndroid Build Coastguard Worker data->state.url = data->set.str[STRING_SET_URL];
579*6236dae4SAndroid Build Coastguard Worker
580*6236dae4SAndroid Build Coastguard Worker /* Init the SSL session ID cache here. We do it here since we want to do it
581*6236dae4SAndroid Build Coastguard Worker after the *_setopt() calls (that could specify the size of the cache) but
582*6236dae4SAndroid Build Coastguard Worker before any transfer takes place. */
583*6236dae4SAndroid Build Coastguard Worker result = Curl_ssl_initsessions(data, data->set.general_ssl.max_ssl_sessions);
584*6236dae4SAndroid Build Coastguard Worker if(result)
585*6236dae4SAndroid Build Coastguard Worker return result;
586*6236dae4SAndroid Build Coastguard Worker
587*6236dae4SAndroid Build Coastguard Worker data->state.requests = 0;
588*6236dae4SAndroid Build Coastguard Worker data->state.followlocation = 0; /* reset the location-follow counter */
589*6236dae4SAndroid Build Coastguard Worker data->state.this_is_a_follow = FALSE; /* reset this */
590*6236dae4SAndroid Build Coastguard Worker data->state.errorbuf = FALSE; /* no error has occurred */
591*6236dae4SAndroid Build Coastguard Worker data->state.httpwant = data->set.httpwant;
592*6236dae4SAndroid Build Coastguard Worker data->state.httpversion = 0;
593*6236dae4SAndroid Build Coastguard Worker data->state.authproblem = FALSE;
594*6236dae4SAndroid Build Coastguard Worker data->state.authhost.want = data->set.httpauth;
595*6236dae4SAndroid Build Coastguard Worker data->state.authproxy.want = data->set.proxyauth;
596*6236dae4SAndroid Build Coastguard Worker Curl_safefree(data->info.wouldredirect);
597*6236dae4SAndroid Build Coastguard Worker Curl_data_priority_clear_state(data);
598*6236dae4SAndroid Build Coastguard Worker
599*6236dae4SAndroid Build Coastguard Worker if(data->state.httpreq == HTTPREQ_PUT)
600*6236dae4SAndroid Build Coastguard Worker data->state.infilesize = data->set.filesize;
601*6236dae4SAndroid Build Coastguard Worker else if((data->state.httpreq != HTTPREQ_GET) &&
602*6236dae4SAndroid Build Coastguard Worker (data->state.httpreq != HTTPREQ_HEAD)) {
603*6236dae4SAndroid Build Coastguard Worker data->state.infilesize = data->set.postfieldsize;
604*6236dae4SAndroid Build Coastguard Worker if(data->set.postfields && (data->state.infilesize == -1))
605*6236dae4SAndroid Build Coastguard Worker data->state.infilesize = (curl_off_t)strlen(data->set.postfields);
606*6236dae4SAndroid Build Coastguard Worker }
607*6236dae4SAndroid Build Coastguard Worker else
608*6236dae4SAndroid Build Coastguard Worker data->state.infilesize = 0;
609*6236dae4SAndroid Build Coastguard Worker
610*6236dae4SAndroid Build Coastguard Worker /* If there is a list of cookie files to read, do it now! */
611*6236dae4SAndroid Build Coastguard Worker Curl_cookie_loadfiles(data);
612*6236dae4SAndroid Build Coastguard Worker
613*6236dae4SAndroid Build Coastguard Worker /* If there is a list of host pairs to deal with */
614*6236dae4SAndroid Build Coastguard Worker if(data->state.resolve)
615*6236dae4SAndroid Build Coastguard Worker result = Curl_loadhostpairs(data);
616*6236dae4SAndroid Build Coastguard Worker
617*6236dae4SAndroid Build Coastguard Worker /* If there is a list of hsts files to read */
618*6236dae4SAndroid Build Coastguard Worker Curl_hsts_loadfiles(data);
619*6236dae4SAndroid Build Coastguard Worker
620*6236dae4SAndroid Build Coastguard Worker if(!result) {
621*6236dae4SAndroid Build Coastguard Worker /* Allow data->set.use_port to set which port to use. This needs to be
622*6236dae4SAndroid Build Coastguard Worker * disabled for example when we follow Location: headers to URLs using
623*6236dae4SAndroid Build Coastguard Worker * different ports! */
624*6236dae4SAndroid Build Coastguard Worker data->state.allow_port = TRUE;
625*6236dae4SAndroid Build Coastguard Worker
626*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
627*6236dae4SAndroid Build Coastguard Worker /*************************************************************
628*6236dae4SAndroid Build Coastguard Worker * Tell signal handler to ignore SIGPIPE
629*6236dae4SAndroid Build Coastguard Worker *************************************************************/
630*6236dae4SAndroid Build Coastguard Worker if(!data->set.no_signal)
631*6236dae4SAndroid Build Coastguard Worker data->state.prev_signal = signal(SIGPIPE, SIG_IGN);
632*6236dae4SAndroid Build Coastguard Worker #endif
633*6236dae4SAndroid Build Coastguard Worker
634*6236dae4SAndroid Build Coastguard Worker Curl_initinfo(data); /* reset session-specific information "variables" */
635*6236dae4SAndroid Build Coastguard Worker Curl_pgrsResetTransferSizes(data);
636*6236dae4SAndroid Build Coastguard Worker Curl_pgrsStartNow(data);
637*6236dae4SAndroid Build Coastguard Worker
638*6236dae4SAndroid Build Coastguard Worker /* In case the handle is reused and an authentication method was picked
639*6236dae4SAndroid Build Coastguard Worker in the session we need to make sure we only use the one(s) we now
640*6236dae4SAndroid Build Coastguard Worker consider to be fine */
641*6236dae4SAndroid Build Coastguard Worker data->state.authhost.picked &= data->state.authhost.want;
642*6236dae4SAndroid Build Coastguard Worker data->state.authproxy.picked &= data->state.authproxy.want;
643*6236dae4SAndroid Build Coastguard Worker
644*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_FTP
645*6236dae4SAndroid Build Coastguard Worker data->state.wildcardmatch = data->set.wildcard_enabled;
646*6236dae4SAndroid Build Coastguard Worker if(data->state.wildcardmatch) {
647*6236dae4SAndroid Build Coastguard Worker struct WildcardData *wc;
648*6236dae4SAndroid Build Coastguard Worker if(!data->wildcard) {
649*6236dae4SAndroid Build Coastguard Worker data->wildcard = calloc(1, sizeof(struct WildcardData));
650*6236dae4SAndroid Build Coastguard Worker if(!data->wildcard)
651*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
652*6236dae4SAndroid Build Coastguard Worker }
653*6236dae4SAndroid Build Coastguard Worker wc = data->wildcard;
654*6236dae4SAndroid Build Coastguard Worker if(wc->state < CURLWC_INIT) {
655*6236dae4SAndroid Build Coastguard Worker if(wc->ftpwc)
656*6236dae4SAndroid Build Coastguard Worker wc->dtor(wc->ftpwc);
657*6236dae4SAndroid Build Coastguard Worker Curl_safefree(wc->pattern);
658*6236dae4SAndroid Build Coastguard Worker Curl_safefree(wc->path);
659*6236dae4SAndroid Build Coastguard Worker result = Curl_wildcard_init(wc); /* init wildcard structures */
660*6236dae4SAndroid Build Coastguard Worker if(result)
661*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
662*6236dae4SAndroid Build Coastguard Worker }
663*6236dae4SAndroid Build Coastguard Worker }
664*6236dae4SAndroid Build Coastguard Worker #endif
665*6236dae4SAndroid Build Coastguard Worker result = Curl_hsts_loadcb(data, data->hsts);
666*6236dae4SAndroid Build Coastguard Worker }
667*6236dae4SAndroid Build Coastguard Worker
668*6236dae4SAndroid Build Coastguard Worker /*
669*6236dae4SAndroid Build Coastguard Worker * Set user-agent. Used for HTTP, but since we can attempt to tunnel
670*6236dae4SAndroid Build Coastguard Worker * basically anything through an HTTP proxy we cannot limit this based on
671*6236dae4SAndroid Build Coastguard Worker * protocol.
672*6236dae4SAndroid Build Coastguard Worker */
673*6236dae4SAndroid Build Coastguard Worker if(data->set.str[STRING_USERAGENT]) {
674*6236dae4SAndroid Build Coastguard Worker Curl_safefree(data->state.aptr.uagent);
675*6236dae4SAndroid Build Coastguard Worker data->state.aptr.uagent =
676*6236dae4SAndroid Build Coastguard Worker aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
677*6236dae4SAndroid Build Coastguard Worker if(!data->state.aptr.uagent)
678*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
679*6236dae4SAndroid Build Coastguard Worker }
680*6236dae4SAndroid Build Coastguard Worker
681*6236dae4SAndroid Build Coastguard Worker if(data->set.str[STRING_USERNAME] ||
682*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_PASSWORD])
683*6236dae4SAndroid Build Coastguard Worker data->state.creds_from = CREDS_OPTION;
684*6236dae4SAndroid Build Coastguard Worker if(!result)
685*6236dae4SAndroid Build Coastguard Worker result = Curl_setstropt(&data->state.aptr.user,
686*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_USERNAME]);
687*6236dae4SAndroid Build Coastguard Worker if(!result)
688*6236dae4SAndroid Build Coastguard Worker result = Curl_setstropt(&data->state.aptr.passwd,
689*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_PASSWORD]);
690*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
691*6236dae4SAndroid Build Coastguard Worker if(!result)
692*6236dae4SAndroid Build Coastguard Worker result = Curl_setstropt(&data->state.aptr.proxyuser,
693*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_PROXYUSERNAME]);
694*6236dae4SAndroid Build Coastguard Worker if(!result)
695*6236dae4SAndroid Build Coastguard Worker result = Curl_setstropt(&data->state.aptr.proxypasswd,
696*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_PROXYPASSWORD]);
697*6236dae4SAndroid Build Coastguard Worker #endif
698*6236dae4SAndroid Build Coastguard Worker
699*6236dae4SAndroid Build Coastguard Worker data->req.headerbytecount = 0;
700*6236dae4SAndroid Build Coastguard Worker Curl_headers_cleanup(data);
701*6236dae4SAndroid Build Coastguard Worker return result;
702*6236dae4SAndroid Build Coastguard Worker }
703*6236dae4SAndroid Build Coastguard Worker
704*6236dae4SAndroid Build Coastguard Worker /* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.
705*6236dae4SAndroid Build Coastguard Worker
706*6236dae4SAndroid Build Coastguard Worker NOTE: that the *url is malloc()ed. */
Curl_retry_request(struct Curl_easy * data,char ** url)707*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
708*6236dae4SAndroid Build Coastguard Worker {
709*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
710*6236dae4SAndroid Build Coastguard Worker bool retry = FALSE;
711*6236dae4SAndroid Build Coastguard Worker *url = NULL;
712*6236dae4SAndroid Build Coastguard Worker
713*6236dae4SAndroid Build Coastguard Worker /* if we are talking upload, we cannot do the checks below, unless the
714*6236dae4SAndroid Build Coastguard Worker protocol is HTTP as when uploading over HTTP we will still get a
715*6236dae4SAndroid Build Coastguard Worker response */
716*6236dae4SAndroid Build Coastguard Worker if(data->state.upload &&
717*6236dae4SAndroid Build Coastguard Worker !(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)))
718*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
719*6236dae4SAndroid Build Coastguard Worker
720*6236dae4SAndroid Build Coastguard Worker if((data->req.bytecount + data->req.headerbytecount == 0) &&
721*6236dae4SAndroid Build Coastguard Worker conn->bits.reuse &&
722*6236dae4SAndroid Build Coastguard Worker (!data->req.no_body || (conn->handler->protocol & PROTO_FAMILY_HTTP))
723*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_RTSP
724*6236dae4SAndroid Build Coastguard Worker && (data->set.rtspreq != RTSPREQ_RECEIVE)
725*6236dae4SAndroid Build Coastguard Worker #endif
726*6236dae4SAndroid Build Coastguard Worker )
727*6236dae4SAndroid Build Coastguard Worker /* We got no data, we attempted to reuse a connection. For HTTP this
728*6236dae4SAndroid Build Coastguard Worker can be a retry so we try again regardless if we expected a body.
729*6236dae4SAndroid Build Coastguard Worker For other protocols we only try again only if we expected a body.
730*6236dae4SAndroid Build Coastguard Worker
731*6236dae4SAndroid Build Coastguard Worker This might happen if the connection was left alive when we were
732*6236dae4SAndroid Build Coastguard Worker done using it before, but that was closed when we wanted to read from
733*6236dae4SAndroid Build Coastguard Worker it again. Bad luck. Retry the same request on a fresh connect! */
734*6236dae4SAndroid Build Coastguard Worker retry = TRUE;
735*6236dae4SAndroid Build Coastguard Worker else if(data->state.refused_stream &&
736*6236dae4SAndroid Build Coastguard Worker (data->req.bytecount + data->req.headerbytecount == 0) ) {
737*6236dae4SAndroid Build Coastguard Worker /* This was sent on a refused stream, safe to rerun. A refused stream
738*6236dae4SAndroid Build Coastguard Worker error can typically only happen on HTTP/2 level if the stream is safe
739*6236dae4SAndroid Build Coastguard Worker to issue again, but the nghttp2 API can deliver the message to other
740*6236dae4SAndroid Build Coastguard Worker streams as well, which is why this adds the check the data counters
741*6236dae4SAndroid Build Coastguard Worker too. */
742*6236dae4SAndroid Build Coastguard Worker infof(data, "REFUSED_STREAM, retrying a fresh connect");
743*6236dae4SAndroid Build Coastguard Worker data->state.refused_stream = FALSE; /* clear again */
744*6236dae4SAndroid Build Coastguard Worker retry = TRUE;
745*6236dae4SAndroid Build Coastguard Worker }
746*6236dae4SAndroid Build Coastguard Worker if(retry) {
747*6236dae4SAndroid Build Coastguard Worker #define CONN_MAX_RETRIES 5
748*6236dae4SAndroid Build Coastguard Worker if(data->state.retrycount++ >= CONN_MAX_RETRIES) {
749*6236dae4SAndroid Build Coastguard Worker failf(data, "Connection died, tried %d times before giving up",
750*6236dae4SAndroid Build Coastguard Worker CONN_MAX_RETRIES);
751*6236dae4SAndroid Build Coastguard Worker data->state.retrycount = 0;
752*6236dae4SAndroid Build Coastguard Worker return CURLE_SEND_ERROR;
753*6236dae4SAndroid Build Coastguard Worker }
754*6236dae4SAndroid Build Coastguard Worker infof(data, "Connection died, retrying a fresh connect (retry count: %d)",
755*6236dae4SAndroid Build Coastguard Worker data->state.retrycount);
756*6236dae4SAndroid Build Coastguard Worker *url = strdup(data->state.url);
757*6236dae4SAndroid Build Coastguard Worker if(!*url)
758*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
759*6236dae4SAndroid Build Coastguard Worker
760*6236dae4SAndroid Build Coastguard Worker connclose(conn, "retry"); /* close this connection */
761*6236dae4SAndroid Build Coastguard Worker conn->bits.retry = TRUE; /* mark this as a connection we are about
762*6236dae4SAndroid Build Coastguard Worker to retry. Marking it this way should
763*6236dae4SAndroid Build Coastguard Worker prevent i.e HTTP transfers to return
764*6236dae4SAndroid Build Coastguard Worker error just because nothing has been
765*6236dae4SAndroid Build Coastguard Worker transferred! */
766*6236dae4SAndroid Build Coastguard Worker Curl_creader_set_rewind(data, TRUE);
767*6236dae4SAndroid Build Coastguard Worker }
768*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
769*6236dae4SAndroid Build Coastguard Worker }
770*6236dae4SAndroid Build Coastguard Worker
771*6236dae4SAndroid Build Coastguard Worker /*
772*6236dae4SAndroid Build Coastguard Worker * xfer_setup() is called to setup basic properties for the transfer.
773*6236dae4SAndroid Build Coastguard Worker */
xfer_setup(struct Curl_easy * data,int sockindex,curl_off_t size,bool getheader,int writesockindex,bool shutdown,bool shutdown_err_ignore)774*6236dae4SAndroid Build Coastguard Worker static void xfer_setup(
775*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data, /* transfer */
776*6236dae4SAndroid Build Coastguard Worker int sockindex, /* socket index to read from or -1 */
777*6236dae4SAndroid Build Coastguard Worker curl_off_t size, /* -1 if unknown at this point */
778*6236dae4SAndroid Build Coastguard Worker bool getheader, /* TRUE if header parsing is wanted */
779*6236dae4SAndroid Build Coastguard Worker int writesockindex, /* socket index to write to, it may be the same we
780*6236dae4SAndroid Build Coastguard Worker read from. -1 disables */
781*6236dae4SAndroid Build Coastguard Worker bool shutdown, /* shutdown connection at transfer end. Only
782*6236dae4SAndroid Build Coastguard Worker * supported when sending OR receiving. */
783*6236dae4SAndroid Build Coastguard Worker bool shutdown_err_ignore /* errors during shutdown do not fail the
784*6236dae4SAndroid Build Coastguard Worker * transfer */
785*6236dae4SAndroid Build Coastguard Worker )
786*6236dae4SAndroid Build Coastguard Worker {
787*6236dae4SAndroid Build Coastguard Worker struct SingleRequest *k = &data->req;
788*6236dae4SAndroid Build Coastguard Worker struct connectdata *conn = data->conn;
789*6236dae4SAndroid Build Coastguard Worker bool want_send = Curl_req_want_send(data);
790*6236dae4SAndroid Build Coastguard Worker
791*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(conn != NULL);
792*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
793*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT((writesockindex <= 1) && (writesockindex >= -1));
794*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!shutdown || (sockindex == -1) || (writesockindex == -1));
795*6236dae4SAndroid Build Coastguard Worker
796*6236dae4SAndroid Build Coastguard Worker if(conn->bits.multiplex || conn->httpversion >= 20 || want_send) {
797*6236dae4SAndroid Build Coastguard Worker /* when multiplexing, the read/write sockets need to be the same! */
798*6236dae4SAndroid Build Coastguard Worker conn->sockfd = sockindex == -1 ?
799*6236dae4SAndroid Build Coastguard Worker ((writesockindex == -1 ? CURL_SOCKET_BAD : conn->sock[writesockindex])) :
800*6236dae4SAndroid Build Coastguard Worker conn->sock[sockindex];
801*6236dae4SAndroid Build Coastguard Worker conn->writesockfd = conn->sockfd;
802*6236dae4SAndroid Build Coastguard Worker if(want_send)
803*6236dae4SAndroid Build Coastguard Worker /* special and HTTP-specific */
804*6236dae4SAndroid Build Coastguard Worker writesockindex = FIRSTSOCKET;
805*6236dae4SAndroid Build Coastguard Worker }
806*6236dae4SAndroid Build Coastguard Worker else {
807*6236dae4SAndroid Build Coastguard Worker conn->sockfd = sockindex == -1 ?
808*6236dae4SAndroid Build Coastguard Worker CURL_SOCKET_BAD : conn->sock[sockindex];
809*6236dae4SAndroid Build Coastguard Worker conn->writesockfd = writesockindex == -1 ?
810*6236dae4SAndroid Build Coastguard Worker CURL_SOCKET_BAD : conn->sock[writesockindex];
811*6236dae4SAndroid Build Coastguard Worker }
812*6236dae4SAndroid Build Coastguard Worker
813*6236dae4SAndroid Build Coastguard Worker k->getheader = getheader;
814*6236dae4SAndroid Build Coastguard Worker k->size = size;
815*6236dae4SAndroid Build Coastguard Worker k->shutdown = shutdown;
816*6236dae4SAndroid Build Coastguard Worker k->shutdown_err_ignore = shutdown_err_ignore;
817*6236dae4SAndroid Build Coastguard Worker
818*6236dae4SAndroid Build Coastguard Worker /* The code sequence below is placed in this function just because all
819*6236dae4SAndroid Build Coastguard Worker necessary input is not always known in do_complete() as this function may
820*6236dae4SAndroid Build Coastguard Worker be called after that */
821*6236dae4SAndroid Build Coastguard Worker
822*6236dae4SAndroid Build Coastguard Worker if(!k->getheader) {
823*6236dae4SAndroid Build Coastguard Worker k->header = FALSE;
824*6236dae4SAndroid Build Coastguard Worker if(size > 0)
825*6236dae4SAndroid Build Coastguard Worker Curl_pgrsSetDownloadSize(data, size);
826*6236dae4SAndroid Build Coastguard Worker }
827*6236dae4SAndroid Build Coastguard Worker /* we want header and/or body, if neither then do not do this! */
828*6236dae4SAndroid Build Coastguard Worker if(k->getheader || !data->req.no_body) {
829*6236dae4SAndroid Build Coastguard Worker
830*6236dae4SAndroid Build Coastguard Worker if(sockindex != -1)
831*6236dae4SAndroid Build Coastguard Worker k->keepon |= KEEP_RECV;
832*6236dae4SAndroid Build Coastguard Worker
833*6236dae4SAndroid Build Coastguard Worker if(writesockindex != -1)
834*6236dae4SAndroid Build Coastguard Worker k->keepon |= KEEP_SEND;
835*6236dae4SAndroid Build Coastguard Worker } /* if(k->getheader || !data->req.no_body) */
836*6236dae4SAndroid Build Coastguard Worker
837*6236dae4SAndroid Build Coastguard Worker }
838*6236dae4SAndroid Build Coastguard Worker
Curl_xfer_setup_nop(struct Curl_easy * data)839*6236dae4SAndroid Build Coastguard Worker void Curl_xfer_setup_nop(struct Curl_easy *data)
840*6236dae4SAndroid Build Coastguard Worker {
841*6236dae4SAndroid Build Coastguard Worker xfer_setup(data, -1, -1, FALSE, -1, FALSE, FALSE);
842*6236dae4SAndroid Build Coastguard Worker }
843*6236dae4SAndroid Build Coastguard Worker
Curl_xfer_setup1(struct Curl_easy * data,int send_recv,curl_off_t recv_size,bool getheader)844*6236dae4SAndroid Build Coastguard Worker void Curl_xfer_setup1(struct Curl_easy *data,
845*6236dae4SAndroid Build Coastguard Worker int send_recv,
846*6236dae4SAndroid Build Coastguard Worker curl_off_t recv_size,
847*6236dae4SAndroid Build Coastguard Worker bool getheader)
848*6236dae4SAndroid Build Coastguard Worker {
849*6236dae4SAndroid Build Coastguard Worker int recv_index = (send_recv & CURL_XFER_RECV) ? FIRSTSOCKET : -1;
850*6236dae4SAndroid Build Coastguard Worker int send_index = (send_recv & CURL_XFER_SEND) ? FIRSTSOCKET : -1;
851*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT((recv_index >= 0) || (recv_size == -1));
852*6236dae4SAndroid Build Coastguard Worker xfer_setup(data, recv_index, recv_size, getheader, send_index, FALSE, FALSE);
853*6236dae4SAndroid Build Coastguard Worker }
854*6236dae4SAndroid Build Coastguard Worker
Curl_xfer_setup2(struct Curl_easy * data,int send_recv,curl_off_t recv_size,bool shutdown,bool shutdown_err_ignore)855*6236dae4SAndroid Build Coastguard Worker void Curl_xfer_setup2(struct Curl_easy *data,
856*6236dae4SAndroid Build Coastguard Worker int send_recv,
857*6236dae4SAndroid Build Coastguard Worker curl_off_t recv_size,
858*6236dae4SAndroid Build Coastguard Worker bool shutdown,
859*6236dae4SAndroid Build Coastguard Worker bool shutdown_err_ignore)
860*6236dae4SAndroid Build Coastguard Worker {
861*6236dae4SAndroid Build Coastguard Worker int recv_index = (send_recv & CURL_XFER_RECV) ? SECONDARYSOCKET : -1;
862*6236dae4SAndroid Build Coastguard Worker int send_index = (send_recv & CURL_XFER_SEND) ? SECONDARYSOCKET : -1;
863*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT((recv_index >= 0) || (recv_size == -1));
864*6236dae4SAndroid Build Coastguard Worker xfer_setup(data, recv_index, recv_size, FALSE, send_index,
865*6236dae4SAndroid Build Coastguard Worker shutdown, shutdown_err_ignore);
866*6236dae4SAndroid Build Coastguard Worker }
867*6236dae4SAndroid Build Coastguard Worker
Curl_xfer_write_resp(struct Curl_easy * data,const char * buf,size_t blen,bool is_eos)868*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_xfer_write_resp(struct Curl_easy *data,
869*6236dae4SAndroid Build Coastguard Worker const char *buf, size_t blen,
870*6236dae4SAndroid Build Coastguard Worker bool is_eos)
871*6236dae4SAndroid Build Coastguard Worker {
872*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
873*6236dae4SAndroid Build Coastguard Worker
874*6236dae4SAndroid Build Coastguard Worker if(data->conn->handler->write_resp) {
875*6236dae4SAndroid Build Coastguard Worker /* protocol handlers offering this function take full responsibility
876*6236dae4SAndroid Build Coastguard Worker * for writing all received download data to the client. */
877*6236dae4SAndroid Build Coastguard Worker result = data->conn->handler->write_resp(data, buf, blen, is_eos);
878*6236dae4SAndroid Build Coastguard Worker }
879*6236dae4SAndroid Build Coastguard Worker else {
880*6236dae4SAndroid Build Coastguard Worker /* No special handling by protocol handler, write all received data
881*6236dae4SAndroid Build Coastguard Worker * as BODY to the client. */
882*6236dae4SAndroid Build Coastguard Worker if(blen || is_eos) {
883*6236dae4SAndroid Build Coastguard Worker int cwtype = CLIENTWRITE_BODY;
884*6236dae4SAndroid Build Coastguard Worker if(is_eos)
885*6236dae4SAndroid Build Coastguard Worker cwtype |= CLIENTWRITE_EOS;
886*6236dae4SAndroid Build Coastguard Worker result = Curl_client_write(data, cwtype, buf, blen);
887*6236dae4SAndroid Build Coastguard Worker }
888*6236dae4SAndroid Build Coastguard Worker }
889*6236dae4SAndroid Build Coastguard Worker
890*6236dae4SAndroid Build Coastguard Worker if(!result && is_eos) {
891*6236dae4SAndroid Build Coastguard Worker /* If we wrote the EOS, we are definitely done */
892*6236dae4SAndroid Build Coastguard Worker data->req.eos_written = TRUE;
893*6236dae4SAndroid Build Coastguard Worker data->req.download_done = TRUE;
894*6236dae4SAndroid Build Coastguard Worker }
895*6236dae4SAndroid Build Coastguard Worker CURL_TRC_WRITE(data, "xfer_write_resp(len=%zu, eos=%d) -> %d",
896*6236dae4SAndroid Build Coastguard Worker blen, is_eos, result);
897*6236dae4SAndroid Build Coastguard Worker return result;
898*6236dae4SAndroid Build Coastguard Worker }
899*6236dae4SAndroid Build Coastguard Worker
Curl_xfer_write_resp_hd(struct Curl_easy * data,const char * hd0,size_t hdlen,bool is_eos)900*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_xfer_write_resp_hd(struct Curl_easy *data,
901*6236dae4SAndroid Build Coastguard Worker const char *hd0, size_t hdlen, bool is_eos)
902*6236dae4SAndroid Build Coastguard Worker {
903*6236dae4SAndroid Build Coastguard Worker if(data->conn->handler->write_resp_hd) {
904*6236dae4SAndroid Build Coastguard Worker /* protocol handlers offering this function take full responsibility
905*6236dae4SAndroid Build Coastguard Worker * for writing all received download data to the client. */
906*6236dae4SAndroid Build Coastguard Worker return data->conn->handler->write_resp_hd(data, hd0, hdlen, is_eos);
907*6236dae4SAndroid Build Coastguard Worker }
908*6236dae4SAndroid Build Coastguard Worker /* No special handling by protocol handler, write as response bytes */
909*6236dae4SAndroid Build Coastguard Worker return Curl_xfer_write_resp(data, hd0, hdlen, is_eos);
910*6236dae4SAndroid Build Coastguard Worker }
911*6236dae4SAndroid Build Coastguard Worker
Curl_xfer_write_done(struct Curl_easy * data,bool premature)912*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_xfer_write_done(struct Curl_easy *data, bool premature)
913*6236dae4SAndroid Build Coastguard Worker {
914*6236dae4SAndroid Build Coastguard Worker (void)premature;
915*6236dae4SAndroid Build Coastguard Worker return Curl_cw_out_done(data);
916*6236dae4SAndroid Build Coastguard Worker }
917*6236dae4SAndroid Build Coastguard Worker
Curl_xfer_needs_flush(struct Curl_easy * data)918*6236dae4SAndroid Build Coastguard Worker bool Curl_xfer_needs_flush(struct Curl_easy *data)
919*6236dae4SAndroid Build Coastguard Worker {
920*6236dae4SAndroid Build Coastguard Worker int sockindex;
921*6236dae4SAndroid Build Coastguard Worker sockindex = ((data->conn->writesockfd != CURL_SOCKET_BAD) &&
922*6236dae4SAndroid Build Coastguard Worker (data->conn->writesockfd == data->conn->sock[SECONDARYSOCKET]));
923*6236dae4SAndroid Build Coastguard Worker return Curl_conn_needs_flush(data, sockindex);
924*6236dae4SAndroid Build Coastguard Worker }
925*6236dae4SAndroid Build Coastguard Worker
Curl_xfer_flush(struct Curl_easy * data)926*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_xfer_flush(struct Curl_easy *data)
927*6236dae4SAndroid Build Coastguard Worker {
928*6236dae4SAndroid Build Coastguard Worker int sockindex;
929*6236dae4SAndroid Build Coastguard Worker sockindex = ((data->conn->writesockfd != CURL_SOCKET_BAD) &&
930*6236dae4SAndroid Build Coastguard Worker (data->conn->writesockfd == data->conn->sock[SECONDARYSOCKET]));
931*6236dae4SAndroid Build Coastguard Worker return Curl_conn_flush(data, sockindex);
932*6236dae4SAndroid Build Coastguard Worker }
933*6236dae4SAndroid Build Coastguard Worker
Curl_xfer_send(struct Curl_easy * data,const void * buf,size_t blen,bool eos,size_t * pnwritten)934*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_xfer_send(struct Curl_easy *data,
935*6236dae4SAndroid Build Coastguard Worker const void *buf, size_t blen, bool eos,
936*6236dae4SAndroid Build Coastguard Worker size_t *pnwritten)
937*6236dae4SAndroid Build Coastguard Worker {
938*6236dae4SAndroid Build Coastguard Worker CURLcode result;
939*6236dae4SAndroid Build Coastguard Worker int sockindex;
940*6236dae4SAndroid Build Coastguard Worker
941*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data);
942*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn);
943*6236dae4SAndroid Build Coastguard Worker
944*6236dae4SAndroid Build Coastguard Worker sockindex = ((data->conn->writesockfd != CURL_SOCKET_BAD) &&
945*6236dae4SAndroid Build Coastguard Worker (data->conn->writesockfd == data->conn->sock[SECONDARYSOCKET]));
946*6236dae4SAndroid Build Coastguard Worker result = Curl_conn_send(data, sockindex, buf, blen, eos, pnwritten);
947*6236dae4SAndroid Build Coastguard Worker if(result == CURLE_AGAIN) {
948*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
949*6236dae4SAndroid Build Coastguard Worker *pnwritten = 0;
950*6236dae4SAndroid Build Coastguard Worker }
951*6236dae4SAndroid Build Coastguard Worker else if(!result && *pnwritten)
952*6236dae4SAndroid Build Coastguard Worker data->info.request_size += *pnwritten;
953*6236dae4SAndroid Build Coastguard Worker
954*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "Curl_xfer_send(len=%zu, eos=%d) -> %d, %zu",
955*6236dae4SAndroid Build Coastguard Worker blen, eos, result, *pnwritten));
956*6236dae4SAndroid Build Coastguard Worker return result;
957*6236dae4SAndroid Build Coastguard Worker }
958*6236dae4SAndroid Build Coastguard Worker
Curl_xfer_recv(struct Curl_easy * data,char * buf,size_t blen,ssize_t * pnrcvd)959*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_xfer_recv(struct Curl_easy *data,
960*6236dae4SAndroid Build Coastguard Worker char *buf, size_t blen,
961*6236dae4SAndroid Build Coastguard Worker ssize_t *pnrcvd)
962*6236dae4SAndroid Build Coastguard Worker {
963*6236dae4SAndroid Build Coastguard Worker int sockindex;
964*6236dae4SAndroid Build Coastguard Worker
965*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data);
966*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn);
967*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->set.buffer_size > 0);
968*6236dae4SAndroid Build Coastguard Worker
969*6236dae4SAndroid Build Coastguard Worker sockindex = ((data->conn->sockfd != CURL_SOCKET_BAD) &&
970*6236dae4SAndroid Build Coastguard Worker (data->conn->sockfd == data->conn->sock[SECONDARYSOCKET]));
971*6236dae4SAndroid Build Coastguard Worker if((size_t)data->set.buffer_size < blen)
972*6236dae4SAndroid Build Coastguard Worker blen = (size_t)data->set.buffer_size;
973*6236dae4SAndroid Build Coastguard Worker return Curl_conn_recv(data, sockindex, buf, blen, pnrcvd);
974*6236dae4SAndroid Build Coastguard Worker }
975*6236dae4SAndroid Build Coastguard Worker
Curl_xfer_send_close(struct Curl_easy * data)976*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_xfer_send_close(struct Curl_easy *data)
977*6236dae4SAndroid Build Coastguard Worker {
978*6236dae4SAndroid Build Coastguard Worker Curl_conn_ev_data_done_send(data);
979*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
980*6236dae4SAndroid Build Coastguard Worker }
981*6236dae4SAndroid Build Coastguard Worker
Curl_xfer_is_blocked(struct Curl_easy * data)982*6236dae4SAndroid Build Coastguard Worker bool Curl_xfer_is_blocked(struct Curl_easy *data)
983*6236dae4SAndroid Build Coastguard Worker {
984*6236dae4SAndroid Build Coastguard Worker bool want_send = ((data)->req.keepon & KEEP_SEND);
985*6236dae4SAndroid Build Coastguard Worker bool want_recv = ((data)->req.keepon & KEEP_RECV);
986*6236dae4SAndroid Build Coastguard Worker if(!want_send)
987*6236dae4SAndroid Build Coastguard Worker return (want_recv && Curl_cwriter_is_paused(data));
988*6236dae4SAndroid Build Coastguard Worker else if(!want_recv)
989*6236dae4SAndroid Build Coastguard Worker return (want_send && Curl_creader_is_paused(data));
990*6236dae4SAndroid Build Coastguard Worker else
991*6236dae4SAndroid Build Coastguard Worker return Curl_creader_is_paused(data) && Curl_cwriter_is_paused(data);
992*6236dae4SAndroid Build Coastguard Worker }
993