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
27*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
28*6236dae4SAndroid Build Coastguard Worker #include <netinet/in.h>
29*6236dae4SAndroid Build Coastguard Worker #endif
30*6236dae4SAndroid Build Coastguard Worker
31*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_LINUX_TCP_H
32*6236dae4SAndroid Build Coastguard Worker #include <linux/tcp.h>
33*6236dae4SAndroid Build Coastguard Worker #elif defined(HAVE_NETINET_TCP_H)
34*6236dae4SAndroid Build Coastguard Worker #include <netinet/tcp.h>
35*6236dae4SAndroid Build Coastguard Worker #endif
36*6236dae4SAndroid Build Coastguard Worker
37*6236dae4SAndroid Build Coastguard Worker #include <curl/curl.h>
38*6236dae4SAndroid Build Coastguard Worker
39*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
40*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
41*6236dae4SAndroid Build Coastguard Worker #include "cfilters.h"
42*6236dae4SAndroid Build Coastguard Worker #include "connect.h"
43*6236dae4SAndroid Build Coastguard Worker #include "content_encoding.h"
44*6236dae4SAndroid Build Coastguard Worker #include "cw-out.h"
45*6236dae4SAndroid Build Coastguard Worker #include "vtls/vtls.h"
46*6236dae4SAndroid Build Coastguard Worker #include "vssh/ssh.h"
47*6236dae4SAndroid Build Coastguard Worker #include "easyif.h"
48*6236dae4SAndroid Build Coastguard Worker #include "multiif.h"
49*6236dae4SAndroid Build Coastguard Worker #include "strerror.h"
50*6236dae4SAndroid Build Coastguard Worker #include "select.h"
51*6236dae4SAndroid Build Coastguard Worker #include "strdup.h"
52*6236dae4SAndroid Build Coastguard Worker #include "http2.h"
53*6236dae4SAndroid Build Coastguard Worker #include "progress.h"
54*6236dae4SAndroid Build Coastguard Worker #include "warnless.h"
55*6236dae4SAndroid Build Coastguard Worker #include "ws.h"
56*6236dae4SAndroid Build Coastguard Worker
57*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
58*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
59*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
60*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
61*6236dae4SAndroid Build Coastguard Worker
62*6236dae4SAndroid Build Coastguard Worker
63*6236dae4SAndroid Build Coastguard Worker static CURLcode do_init_writer_stack(struct Curl_easy *data);
64*6236dae4SAndroid Build Coastguard Worker
65*6236dae4SAndroid Build Coastguard Worker /* Curl_client_write() sends data to the write callback(s)
66*6236dae4SAndroid Build Coastguard Worker
67*6236dae4SAndroid Build Coastguard Worker The bit pattern defines to what "streams" to write to. Body and/or header.
68*6236dae4SAndroid Build Coastguard Worker The defines are in sendf.h of course.
69*6236dae4SAndroid Build Coastguard Worker */
Curl_client_write(struct Curl_easy * data,int type,const char * buf,size_t blen)70*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_client_write(struct Curl_easy *data,
71*6236dae4SAndroid Build Coastguard Worker int type, const char *buf, size_t blen)
72*6236dae4SAndroid Build Coastguard Worker {
73*6236dae4SAndroid Build Coastguard Worker CURLcode result;
74*6236dae4SAndroid Build Coastguard Worker
75*6236dae4SAndroid Build Coastguard Worker /* it is one of those, at least */
76*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(type & (CLIENTWRITE_BODY|CLIENTWRITE_HEADER|CLIENTWRITE_INFO));
77*6236dae4SAndroid Build Coastguard Worker /* BODY is only BODY (with optional EOS) */
78*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!(type & CLIENTWRITE_BODY) ||
79*6236dae4SAndroid Build Coastguard Worker ((type & ~(CLIENTWRITE_BODY|CLIENTWRITE_EOS)) == 0));
80*6236dae4SAndroid Build Coastguard Worker /* INFO is only INFO (with optional EOS) */
81*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!(type & CLIENTWRITE_INFO) ||
82*6236dae4SAndroid Build Coastguard Worker ((type & ~(CLIENTWRITE_INFO|CLIENTWRITE_EOS)) == 0));
83*6236dae4SAndroid Build Coastguard Worker
84*6236dae4SAndroid Build Coastguard Worker if(!data->req.writer_stack) {
85*6236dae4SAndroid Build Coastguard Worker result = do_init_writer_stack(data);
86*6236dae4SAndroid Build Coastguard Worker if(result)
87*6236dae4SAndroid Build Coastguard Worker return result;
88*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->req.writer_stack);
89*6236dae4SAndroid Build Coastguard Worker }
90*6236dae4SAndroid Build Coastguard Worker
91*6236dae4SAndroid Build Coastguard Worker result = Curl_cwriter_write(data, data->req.writer_stack, type, buf, blen);
92*6236dae4SAndroid Build Coastguard Worker CURL_TRC_WRITE(data, "client_write(type=%x, len=%zu) -> %d",
93*6236dae4SAndroid Build Coastguard Worker type, blen, result);
94*6236dae4SAndroid Build Coastguard Worker return result;
95*6236dae4SAndroid Build Coastguard Worker }
96*6236dae4SAndroid Build Coastguard Worker
cl_reset_writer(struct Curl_easy * data)97*6236dae4SAndroid Build Coastguard Worker static void cl_reset_writer(struct Curl_easy *data)
98*6236dae4SAndroid Build Coastguard Worker {
99*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer = data->req.writer_stack;
100*6236dae4SAndroid Build Coastguard Worker while(writer) {
101*6236dae4SAndroid Build Coastguard Worker data->req.writer_stack = writer->next;
102*6236dae4SAndroid Build Coastguard Worker writer->cwt->do_close(data, writer);
103*6236dae4SAndroid Build Coastguard Worker free(writer);
104*6236dae4SAndroid Build Coastguard Worker writer = data->req.writer_stack;
105*6236dae4SAndroid Build Coastguard Worker }
106*6236dae4SAndroid Build Coastguard Worker }
107*6236dae4SAndroid Build Coastguard Worker
cl_reset_reader(struct Curl_easy * data)108*6236dae4SAndroid Build Coastguard Worker static void cl_reset_reader(struct Curl_easy *data)
109*6236dae4SAndroid Build Coastguard Worker {
110*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader = data->req.reader_stack;
111*6236dae4SAndroid Build Coastguard Worker while(reader) {
112*6236dae4SAndroid Build Coastguard Worker data->req.reader_stack = reader->next;
113*6236dae4SAndroid Build Coastguard Worker reader->crt->do_close(data, reader);
114*6236dae4SAndroid Build Coastguard Worker free(reader);
115*6236dae4SAndroid Build Coastguard Worker reader = data->req.reader_stack;
116*6236dae4SAndroid Build Coastguard Worker }
117*6236dae4SAndroid Build Coastguard Worker }
118*6236dae4SAndroid Build Coastguard Worker
Curl_client_cleanup(struct Curl_easy * data)119*6236dae4SAndroid Build Coastguard Worker void Curl_client_cleanup(struct Curl_easy *data)
120*6236dae4SAndroid Build Coastguard Worker {
121*6236dae4SAndroid Build Coastguard Worker cl_reset_reader(data);
122*6236dae4SAndroid Build Coastguard Worker cl_reset_writer(data);
123*6236dae4SAndroid Build Coastguard Worker
124*6236dae4SAndroid Build Coastguard Worker data->req.bytecount = 0;
125*6236dae4SAndroid Build Coastguard Worker data->req.headerline = 0;
126*6236dae4SAndroid Build Coastguard Worker }
127*6236dae4SAndroid Build Coastguard Worker
Curl_client_reset(struct Curl_easy * data)128*6236dae4SAndroid Build Coastguard Worker void Curl_client_reset(struct Curl_easy *data)
129*6236dae4SAndroid Build Coastguard Worker {
130*6236dae4SAndroid Build Coastguard Worker if(data->req.rewind_read) {
131*6236dae4SAndroid Build Coastguard Worker /* already requested */
132*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "client_reset, will rewind reader");
133*6236dae4SAndroid Build Coastguard Worker }
134*6236dae4SAndroid Build Coastguard Worker else {
135*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "client_reset, clear readers");
136*6236dae4SAndroid Build Coastguard Worker cl_reset_reader(data);
137*6236dae4SAndroid Build Coastguard Worker }
138*6236dae4SAndroid Build Coastguard Worker cl_reset_writer(data);
139*6236dae4SAndroid Build Coastguard Worker
140*6236dae4SAndroid Build Coastguard Worker data->req.bytecount = 0;
141*6236dae4SAndroid Build Coastguard Worker data->req.headerline = 0;
142*6236dae4SAndroid Build Coastguard Worker }
143*6236dae4SAndroid Build Coastguard Worker
Curl_client_start(struct Curl_easy * data)144*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_client_start(struct Curl_easy *data)
145*6236dae4SAndroid Build Coastguard Worker {
146*6236dae4SAndroid Build Coastguard Worker if(data->req.rewind_read) {
147*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *r = data->req.reader_stack;
148*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
149*6236dae4SAndroid Build Coastguard Worker
150*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "client start, rewind readers");
151*6236dae4SAndroid Build Coastguard Worker while(r) {
152*6236dae4SAndroid Build Coastguard Worker result = r->crt->rewind(data, r);
153*6236dae4SAndroid Build Coastguard Worker if(result) {
154*6236dae4SAndroid Build Coastguard Worker failf(data, "rewind of client reader '%s' failed: %d",
155*6236dae4SAndroid Build Coastguard Worker r->crt->name, result);
156*6236dae4SAndroid Build Coastguard Worker return result;
157*6236dae4SAndroid Build Coastguard Worker }
158*6236dae4SAndroid Build Coastguard Worker r = r->next;
159*6236dae4SAndroid Build Coastguard Worker }
160*6236dae4SAndroid Build Coastguard Worker data->req.rewind_read = FALSE;
161*6236dae4SAndroid Build Coastguard Worker cl_reset_reader(data);
162*6236dae4SAndroid Build Coastguard Worker }
163*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
164*6236dae4SAndroid Build Coastguard Worker }
165*6236dae4SAndroid Build Coastguard Worker
Curl_creader_will_rewind(struct Curl_easy * data)166*6236dae4SAndroid Build Coastguard Worker bool Curl_creader_will_rewind(struct Curl_easy *data)
167*6236dae4SAndroid Build Coastguard Worker {
168*6236dae4SAndroid Build Coastguard Worker return data->req.rewind_read;
169*6236dae4SAndroid Build Coastguard Worker }
170*6236dae4SAndroid Build Coastguard Worker
Curl_creader_set_rewind(struct Curl_easy * data,bool enable)171*6236dae4SAndroid Build Coastguard Worker void Curl_creader_set_rewind(struct Curl_easy *data, bool enable)
172*6236dae4SAndroid Build Coastguard Worker {
173*6236dae4SAndroid Build Coastguard Worker data->req.rewind_read = !!enable;
174*6236dae4SAndroid Build Coastguard Worker }
175*6236dae4SAndroid Build Coastguard Worker
176*6236dae4SAndroid Build Coastguard Worker /* Write data using an unencoding writer stack. */
Curl_cwriter_write(struct Curl_easy * data,struct Curl_cwriter * writer,int type,const char * buf,size_t nbytes)177*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_cwriter_write(struct Curl_easy *data,
178*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer, int type,
179*6236dae4SAndroid Build Coastguard Worker const char *buf, size_t nbytes)
180*6236dae4SAndroid Build Coastguard Worker {
181*6236dae4SAndroid Build Coastguard Worker if(!writer)
182*6236dae4SAndroid Build Coastguard Worker return CURLE_WRITE_ERROR;
183*6236dae4SAndroid Build Coastguard Worker return writer->cwt->do_write(data, writer, type, buf, nbytes);
184*6236dae4SAndroid Build Coastguard Worker }
185*6236dae4SAndroid Build Coastguard Worker
Curl_cwriter_def_init(struct Curl_easy * data,struct Curl_cwriter * writer)186*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_cwriter_def_init(struct Curl_easy *data,
187*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer)
188*6236dae4SAndroid Build Coastguard Worker {
189*6236dae4SAndroid Build Coastguard Worker (void)data;
190*6236dae4SAndroid Build Coastguard Worker (void)writer;
191*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
192*6236dae4SAndroid Build Coastguard Worker }
193*6236dae4SAndroid Build Coastguard Worker
Curl_cwriter_def_write(struct Curl_easy * data,struct Curl_cwriter * writer,int type,const char * buf,size_t nbytes)194*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_cwriter_def_write(struct Curl_easy *data,
195*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer, int type,
196*6236dae4SAndroid Build Coastguard Worker const char *buf, size_t nbytes)
197*6236dae4SAndroid Build Coastguard Worker {
198*6236dae4SAndroid Build Coastguard Worker return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
199*6236dae4SAndroid Build Coastguard Worker }
200*6236dae4SAndroid Build Coastguard Worker
Curl_cwriter_def_close(struct Curl_easy * data,struct Curl_cwriter * writer)201*6236dae4SAndroid Build Coastguard Worker void Curl_cwriter_def_close(struct Curl_easy *data,
202*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer)
203*6236dae4SAndroid Build Coastguard Worker {
204*6236dae4SAndroid Build Coastguard Worker (void) data;
205*6236dae4SAndroid Build Coastguard Worker (void) writer;
206*6236dae4SAndroid Build Coastguard Worker }
207*6236dae4SAndroid Build Coastguard Worker
get_max_body_write_len(struct Curl_easy * data,curl_off_t limit)208*6236dae4SAndroid Build Coastguard Worker static size_t get_max_body_write_len(struct Curl_easy *data, curl_off_t limit)
209*6236dae4SAndroid Build Coastguard Worker {
210*6236dae4SAndroid Build Coastguard Worker if(limit != -1) {
211*6236dae4SAndroid Build Coastguard Worker /* How much more are we allowed to write? */
212*6236dae4SAndroid Build Coastguard Worker curl_off_t remain_diff;
213*6236dae4SAndroid Build Coastguard Worker remain_diff = limit - data->req.bytecount;
214*6236dae4SAndroid Build Coastguard Worker if(remain_diff < 0) {
215*6236dae4SAndroid Build Coastguard Worker /* already written too much! */
216*6236dae4SAndroid Build Coastguard Worker return 0;
217*6236dae4SAndroid Build Coastguard Worker }
218*6236dae4SAndroid Build Coastguard Worker #if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T
219*6236dae4SAndroid Build Coastguard Worker else if(remain_diff > SSIZE_T_MAX) {
220*6236dae4SAndroid Build Coastguard Worker return SIZE_T_MAX;
221*6236dae4SAndroid Build Coastguard Worker }
222*6236dae4SAndroid Build Coastguard Worker #endif
223*6236dae4SAndroid Build Coastguard Worker else {
224*6236dae4SAndroid Build Coastguard Worker return (size_t)remain_diff;
225*6236dae4SAndroid Build Coastguard Worker }
226*6236dae4SAndroid Build Coastguard Worker }
227*6236dae4SAndroid Build Coastguard Worker return SIZE_T_MAX;
228*6236dae4SAndroid Build Coastguard Worker }
229*6236dae4SAndroid Build Coastguard Worker
230*6236dae4SAndroid Build Coastguard Worker struct cw_download_ctx {
231*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter super;
232*6236dae4SAndroid Build Coastguard Worker BIT(started_response);
233*6236dae4SAndroid Build Coastguard Worker };
234*6236dae4SAndroid Build Coastguard Worker /* Download client writer in phase CURL_CW_PROTOCOL that
235*6236dae4SAndroid Build Coastguard Worker * sees the "real" download body data. */
cw_download_write(struct Curl_easy * data,struct Curl_cwriter * writer,int type,const char * buf,size_t nbytes)236*6236dae4SAndroid Build Coastguard Worker static CURLcode cw_download_write(struct Curl_easy *data,
237*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer, int type,
238*6236dae4SAndroid Build Coastguard Worker const char *buf, size_t nbytes)
239*6236dae4SAndroid Build Coastguard Worker {
240*6236dae4SAndroid Build Coastguard Worker struct cw_download_ctx *ctx = writer->ctx;
241*6236dae4SAndroid Build Coastguard Worker CURLcode result;
242*6236dae4SAndroid Build Coastguard Worker size_t nwrite, excess_len = 0;
243*6236dae4SAndroid Build Coastguard Worker bool is_connect = !!(type & CLIENTWRITE_CONNECT);
244*6236dae4SAndroid Build Coastguard Worker
245*6236dae4SAndroid Build Coastguard Worker if(!is_connect && !ctx->started_response) {
246*6236dae4SAndroid Build Coastguard Worker Curl_pgrsTime(data, TIMER_STARTTRANSFER);
247*6236dae4SAndroid Build Coastguard Worker ctx->started_response = TRUE;
248*6236dae4SAndroid Build Coastguard Worker }
249*6236dae4SAndroid Build Coastguard Worker
250*6236dae4SAndroid Build Coastguard Worker if(!(type & CLIENTWRITE_BODY)) {
251*6236dae4SAndroid Build Coastguard Worker if(is_connect && data->set.suppress_connect_headers)
252*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
253*6236dae4SAndroid Build Coastguard Worker result = Curl_cwriter_write(data, writer->next, type, buf, nbytes);
254*6236dae4SAndroid Build Coastguard Worker CURL_TRC_WRITE(data, "download_write header(type=%x, blen=%zu) -> %d",
255*6236dae4SAndroid Build Coastguard Worker type, nbytes, result);
256*6236dae4SAndroid Build Coastguard Worker return result;
257*6236dae4SAndroid Build Coastguard Worker }
258*6236dae4SAndroid Build Coastguard Worker
259*6236dae4SAndroid Build Coastguard Worker /* Here, we deal with REAL BODY bytes. All filtering and transfer
260*6236dae4SAndroid Build Coastguard Worker * encodings have been applied and only the true content, e.g. BODY,
261*6236dae4SAndroid Build Coastguard Worker * bytes are passed here.
262*6236dae4SAndroid Build Coastguard Worker * This allows us to check sizes, update stats, etc. independent
263*6236dae4SAndroid Build Coastguard Worker * from the protocol in play. */
264*6236dae4SAndroid Build Coastguard Worker
265*6236dae4SAndroid Build Coastguard Worker if(data->req.no_body && nbytes > 0) {
266*6236dae4SAndroid Build Coastguard Worker /* BODY arrives although we want none, bail out */
267*6236dae4SAndroid Build Coastguard Worker streamclose(data->conn, "ignoring body");
268*6236dae4SAndroid Build Coastguard Worker CURL_TRC_WRITE(data, "download_write body(type=%x, blen=%zu), "
269*6236dae4SAndroid Build Coastguard Worker "did not want a BODY", type, nbytes);
270*6236dae4SAndroid Build Coastguard Worker data->req.download_done = TRUE;
271*6236dae4SAndroid Build Coastguard Worker if(data->info.header_size)
272*6236dae4SAndroid Build Coastguard Worker /* if headers have been received, this is fine */
273*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
274*6236dae4SAndroid Build Coastguard Worker return CURLE_WEIRD_SERVER_REPLY;
275*6236dae4SAndroid Build Coastguard Worker }
276*6236dae4SAndroid Build Coastguard Worker
277*6236dae4SAndroid Build Coastguard Worker /* Determine if we see any bytes in excess to what is allowed.
278*6236dae4SAndroid Build Coastguard Worker * We write the allowed bytes and handle excess further below.
279*6236dae4SAndroid Build Coastguard Worker * This gives deterministic BODY writes on varying buffer receive
280*6236dae4SAndroid Build Coastguard Worker * lengths. */
281*6236dae4SAndroid Build Coastguard Worker nwrite = nbytes;
282*6236dae4SAndroid Build Coastguard Worker if(-1 != data->req.maxdownload) {
283*6236dae4SAndroid Build Coastguard Worker size_t wmax = get_max_body_write_len(data, data->req.maxdownload);
284*6236dae4SAndroid Build Coastguard Worker if(nwrite > wmax) {
285*6236dae4SAndroid Build Coastguard Worker excess_len = nbytes - wmax;
286*6236dae4SAndroid Build Coastguard Worker nwrite = wmax;
287*6236dae4SAndroid Build Coastguard Worker }
288*6236dae4SAndroid Build Coastguard Worker
289*6236dae4SAndroid Build Coastguard Worker if(nwrite == wmax) {
290*6236dae4SAndroid Build Coastguard Worker data->req.download_done = TRUE;
291*6236dae4SAndroid Build Coastguard Worker }
292*6236dae4SAndroid Build Coastguard Worker
293*6236dae4SAndroid Build Coastguard Worker if((type & CLIENTWRITE_EOS) && !data->req.no_body &&
294*6236dae4SAndroid Build Coastguard Worker (data->req.maxdownload > data->req.bytecount)) {
295*6236dae4SAndroid Build Coastguard Worker failf(data, "end of response with %" FMT_OFF_T " bytes missing",
296*6236dae4SAndroid Build Coastguard Worker data->req.maxdownload - data->req.bytecount);
297*6236dae4SAndroid Build Coastguard Worker return CURLE_PARTIAL_FILE;
298*6236dae4SAndroid Build Coastguard Worker }
299*6236dae4SAndroid Build Coastguard Worker }
300*6236dae4SAndroid Build Coastguard Worker
301*6236dae4SAndroid Build Coastguard Worker /* Error on too large filesize is handled below, after writing
302*6236dae4SAndroid Build Coastguard Worker * the permitted bytes */
303*6236dae4SAndroid Build Coastguard Worker if(data->set.max_filesize && !data->req.ignorebody) {
304*6236dae4SAndroid Build Coastguard Worker size_t wmax = get_max_body_write_len(data, data->set.max_filesize);
305*6236dae4SAndroid Build Coastguard Worker if(nwrite > wmax) {
306*6236dae4SAndroid Build Coastguard Worker nwrite = wmax;
307*6236dae4SAndroid Build Coastguard Worker }
308*6236dae4SAndroid Build Coastguard Worker }
309*6236dae4SAndroid Build Coastguard Worker
310*6236dae4SAndroid Build Coastguard Worker if(!data->req.ignorebody && (nwrite || (type & CLIENTWRITE_EOS))) {
311*6236dae4SAndroid Build Coastguard Worker result = Curl_cwriter_write(data, writer->next, type, buf, nwrite);
312*6236dae4SAndroid Build Coastguard Worker CURL_TRC_WRITE(data, "download_write body(type=%x, blen=%zu) -> %d",
313*6236dae4SAndroid Build Coastguard Worker type, nbytes, result);
314*6236dae4SAndroid Build Coastguard Worker if(result)
315*6236dae4SAndroid Build Coastguard Worker return result;
316*6236dae4SAndroid Build Coastguard Worker }
317*6236dae4SAndroid Build Coastguard Worker /* Update stats, write and report progress */
318*6236dae4SAndroid Build Coastguard Worker data->req.bytecount += nwrite;
319*6236dae4SAndroid Build Coastguard Worker #ifdef USE_HYPER
320*6236dae4SAndroid Build Coastguard Worker data->req.bodywritten = TRUE;
321*6236dae4SAndroid Build Coastguard Worker #endif
322*6236dae4SAndroid Build Coastguard Worker result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
323*6236dae4SAndroid Build Coastguard Worker if(result)
324*6236dae4SAndroid Build Coastguard Worker return result;
325*6236dae4SAndroid Build Coastguard Worker
326*6236dae4SAndroid Build Coastguard Worker if(excess_len) {
327*6236dae4SAndroid Build Coastguard Worker if(!data->req.ignorebody) {
328*6236dae4SAndroid Build Coastguard Worker infof(data,
329*6236dae4SAndroid Build Coastguard Worker "Excess found writing body:"
330*6236dae4SAndroid Build Coastguard Worker " excess = %zu"
331*6236dae4SAndroid Build Coastguard Worker ", size = %" FMT_OFF_T
332*6236dae4SAndroid Build Coastguard Worker ", maxdownload = %" FMT_OFF_T
333*6236dae4SAndroid Build Coastguard Worker ", bytecount = %" FMT_OFF_T,
334*6236dae4SAndroid Build Coastguard Worker excess_len, data->req.size, data->req.maxdownload,
335*6236dae4SAndroid Build Coastguard Worker data->req.bytecount);
336*6236dae4SAndroid Build Coastguard Worker connclose(data->conn, "excess found in a read");
337*6236dae4SAndroid Build Coastguard Worker }
338*6236dae4SAndroid Build Coastguard Worker }
339*6236dae4SAndroid Build Coastguard Worker else if((nwrite < nbytes) && !data->req.ignorebody) {
340*6236dae4SAndroid Build Coastguard Worker failf(data, "Exceeded the maximum allowed file size "
341*6236dae4SAndroid Build Coastguard Worker "(%" FMT_OFF_T ") with %" FMT_OFF_T " bytes",
342*6236dae4SAndroid Build Coastguard Worker data->set.max_filesize, data->req.bytecount);
343*6236dae4SAndroid Build Coastguard Worker return CURLE_FILESIZE_EXCEEDED;
344*6236dae4SAndroid Build Coastguard Worker }
345*6236dae4SAndroid Build Coastguard Worker
346*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
347*6236dae4SAndroid Build Coastguard Worker }
348*6236dae4SAndroid Build Coastguard Worker
349*6236dae4SAndroid Build Coastguard Worker static const struct Curl_cwtype cw_download = {
350*6236dae4SAndroid Build Coastguard Worker "protocol",
351*6236dae4SAndroid Build Coastguard Worker NULL,
352*6236dae4SAndroid Build Coastguard Worker Curl_cwriter_def_init,
353*6236dae4SAndroid Build Coastguard Worker cw_download_write,
354*6236dae4SAndroid Build Coastguard Worker Curl_cwriter_def_close,
355*6236dae4SAndroid Build Coastguard Worker sizeof(struct cw_download_ctx)
356*6236dae4SAndroid Build Coastguard Worker };
357*6236dae4SAndroid Build Coastguard Worker
358*6236dae4SAndroid Build Coastguard Worker /* RAW client writer in phase CURL_CW_RAW that
359*6236dae4SAndroid Build Coastguard Worker * enabled tracing of raw data. */
cw_raw_write(struct Curl_easy * data,struct Curl_cwriter * writer,int type,const char * buf,size_t nbytes)360*6236dae4SAndroid Build Coastguard Worker static CURLcode cw_raw_write(struct Curl_easy *data,
361*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer, int type,
362*6236dae4SAndroid Build Coastguard Worker const char *buf, size_t nbytes)
363*6236dae4SAndroid Build Coastguard Worker {
364*6236dae4SAndroid Build Coastguard Worker if(type & CLIENTWRITE_BODY && data->set.verbose && !data->req.ignorebody) {
365*6236dae4SAndroid Build Coastguard Worker Curl_debug(data, CURLINFO_DATA_IN, (char *)buf, nbytes);
366*6236dae4SAndroid Build Coastguard Worker }
367*6236dae4SAndroid Build Coastguard Worker return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
368*6236dae4SAndroid Build Coastguard Worker }
369*6236dae4SAndroid Build Coastguard Worker
370*6236dae4SAndroid Build Coastguard Worker static const struct Curl_cwtype cw_raw = {
371*6236dae4SAndroid Build Coastguard Worker "raw",
372*6236dae4SAndroid Build Coastguard Worker NULL,
373*6236dae4SAndroid Build Coastguard Worker Curl_cwriter_def_init,
374*6236dae4SAndroid Build Coastguard Worker cw_raw_write,
375*6236dae4SAndroid Build Coastguard Worker Curl_cwriter_def_close,
376*6236dae4SAndroid Build Coastguard Worker sizeof(struct Curl_cwriter)
377*6236dae4SAndroid Build Coastguard Worker };
378*6236dae4SAndroid Build Coastguard Worker
379*6236dae4SAndroid Build Coastguard Worker /* Create an unencoding writer stage using the given handler. */
Curl_cwriter_create(struct Curl_cwriter ** pwriter,struct Curl_easy * data,const struct Curl_cwtype * cwt,Curl_cwriter_phase phase)380*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter,
381*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
382*6236dae4SAndroid Build Coastguard Worker const struct Curl_cwtype *cwt,
383*6236dae4SAndroid Build Coastguard Worker Curl_cwriter_phase phase)
384*6236dae4SAndroid Build Coastguard Worker {
385*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer = NULL;
386*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OUT_OF_MEMORY;
387*6236dae4SAndroid Build Coastguard Worker void *p;
388*6236dae4SAndroid Build Coastguard Worker
389*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(cwt->cwriter_size >= sizeof(struct Curl_cwriter));
390*6236dae4SAndroid Build Coastguard Worker p = calloc(1, cwt->cwriter_size);
391*6236dae4SAndroid Build Coastguard Worker if(!p)
392*6236dae4SAndroid Build Coastguard Worker goto out;
393*6236dae4SAndroid Build Coastguard Worker
394*6236dae4SAndroid Build Coastguard Worker writer = (struct Curl_cwriter *)p;
395*6236dae4SAndroid Build Coastguard Worker writer->cwt = cwt;
396*6236dae4SAndroid Build Coastguard Worker writer->ctx = p;
397*6236dae4SAndroid Build Coastguard Worker writer->phase = phase;
398*6236dae4SAndroid Build Coastguard Worker result = cwt->do_init(data, writer);
399*6236dae4SAndroid Build Coastguard Worker
400*6236dae4SAndroid Build Coastguard Worker out:
401*6236dae4SAndroid Build Coastguard Worker *pwriter = result ? NULL : writer;
402*6236dae4SAndroid Build Coastguard Worker if(result)
403*6236dae4SAndroid Build Coastguard Worker free(writer);
404*6236dae4SAndroid Build Coastguard Worker return result;
405*6236dae4SAndroid Build Coastguard Worker }
406*6236dae4SAndroid Build Coastguard Worker
Curl_cwriter_free(struct Curl_easy * data,struct Curl_cwriter * writer)407*6236dae4SAndroid Build Coastguard Worker void Curl_cwriter_free(struct Curl_easy *data,
408*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer)
409*6236dae4SAndroid Build Coastguard Worker {
410*6236dae4SAndroid Build Coastguard Worker if(writer) {
411*6236dae4SAndroid Build Coastguard Worker writer->cwt->do_close(data, writer);
412*6236dae4SAndroid Build Coastguard Worker free(writer);
413*6236dae4SAndroid Build Coastguard Worker }
414*6236dae4SAndroid Build Coastguard Worker }
415*6236dae4SAndroid Build Coastguard Worker
Curl_cwriter_count(struct Curl_easy * data,Curl_cwriter_phase phase)416*6236dae4SAndroid Build Coastguard Worker size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase)
417*6236dae4SAndroid Build Coastguard Worker {
418*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *w;
419*6236dae4SAndroid Build Coastguard Worker size_t n = 0;
420*6236dae4SAndroid Build Coastguard Worker
421*6236dae4SAndroid Build Coastguard Worker for(w = data->req.writer_stack; w; w = w->next) {
422*6236dae4SAndroid Build Coastguard Worker if(w->phase == phase)
423*6236dae4SAndroid Build Coastguard Worker ++n;
424*6236dae4SAndroid Build Coastguard Worker }
425*6236dae4SAndroid Build Coastguard Worker return n;
426*6236dae4SAndroid Build Coastguard Worker }
427*6236dae4SAndroid Build Coastguard Worker
do_init_writer_stack(struct Curl_easy * data)428*6236dae4SAndroid Build Coastguard Worker static CURLcode do_init_writer_stack(struct Curl_easy *data)
429*6236dae4SAndroid Build Coastguard Worker {
430*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer;
431*6236dae4SAndroid Build Coastguard Worker CURLcode result;
432*6236dae4SAndroid Build Coastguard Worker
433*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!data->req.writer_stack);
434*6236dae4SAndroid Build Coastguard Worker result = Curl_cwriter_create(&data->req.writer_stack,
435*6236dae4SAndroid Build Coastguard Worker data, &Curl_cwt_out, CURL_CW_CLIENT);
436*6236dae4SAndroid Build Coastguard Worker if(result)
437*6236dae4SAndroid Build Coastguard Worker return result;
438*6236dae4SAndroid Build Coastguard Worker
439*6236dae4SAndroid Build Coastguard Worker result = Curl_cwriter_create(&writer, data, &cw_download, CURL_CW_PROTOCOL);
440*6236dae4SAndroid Build Coastguard Worker if(result)
441*6236dae4SAndroid Build Coastguard Worker return result;
442*6236dae4SAndroid Build Coastguard Worker result = Curl_cwriter_add(data, writer);
443*6236dae4SAndroid Build Coastguard Worker if(result) {
444*6236dae4SAndroid Build Coastguard Worker Curl_cwriter_free(data, writer);
445*6236dae4SAndroid Build Coastguard Worker }
446*6236dae4SAndroid Build Coastguard Worker
447*6236dae4SAndroid Build Coastguard Worker result = Curl_cwriter_create(&writer, data, &cw_raw, CURL_CW_RAW);
448*6236dae4SAndroid Build Coastguard Worker if(result)
449*6236dae4SAndroid Build Coastguard Worker return result;
450*6236dae4SAndroid Build Coastguard Worker result = Curl_cwriter_add(data, writer);
451*6236dae4SAndroid Build Coastguard Worker if(result) {
452*6236dae4SAndroid Build Coastguard Worker Curl_cwriter_free(data, writer);
453*6236dae4SAndroid Build Coastguard Worker }
454*6236dae4SAndroid Build Coastguard Worker return result;
455*6236dae4SAndroid Build Coastguard Worker }
456*6236dae4SAndroid Build Coastguard Worker
Curl_cwriter_add(struct Curl_easy * data,struct Curl_cwriter * writer)457*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_cwriter_add(struct Curl_easy *data,
458*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer)
459*6236dae4SAndroid Build Coastguard Worker {
460*6236dae4SAndroid Build Coastguard Worker CURLcode result;
461*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter **anchor = &data->req.writer_stack;
462*6236dae4SAndroid Build Coastguard Worker
463*6236dae4SAndroid Build Coastguard Worker if(!*anchor) {
464*6236dae4SAndroid Build Coastguard Worker result = do_init_writer_stack(data);
465*6236dae4SAndroid Build Coastguard Worker if(result)
466*6236dae4SAndroid Build Coastguard Worker return result;
467*6236dae4SAndroid Build Coastguard Worker }
468*6236dae4SAndroid Build Coastguard Worker
469*6236dae4SAndroid Build Coastguard Worker /* Insert the writer as first in its phase.
470*6236dae4SAndroid Build Coastguard Worker * Skip existing writers of lower phases. */
471*6236dae4SAndroid Build Coastguard Worker while(*anchor && (*anchor)->phase < writer->phase)
472*6236dae4SAndroid Build Coastguard Worker anchor = &((*anchor)->next);
473*6236dae4SAndroid Build Coastguard Worker writer->next = *anchor;
474*6236dae4SAndroid Build Coastguard Worker *anchor = writer;
475*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
476*6236dae4SAndroid Build Coastguard Worker }
477*6236dae4SAndroid Build Coastguard Worker
Curl_cwriter_get_by_name(struct Curl_easy * data,const char * name)478*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *Curl_cwriter_get_by_name(struct Curl_easy *data,
479*6236dae4SAndroid Build Coastguard Worker const char *name)
480*6236dae4SAndroid Build Coastguard Worker {
481*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer;
482*6236dae4SAndroid Build Coastguard Worker for(writer = data->req.writer_stack; writer; writer = writer->next) {
483*6236dae4SAndroid Build Coastguard Worker if(!strcmp(name, writer->cwt->name))
484*6236dae4SAndroid Build Coastguard Worker return writer;
485*6236dae4SAndroid Build Coastguard Worker }
486*6236dae4SAndroid Build Coastguard Worker return NULL;
487*6236dae4SAndroid Build Coastguard Worker }
488*6236dae4SAndroid Build Coastguard Worker
Curl_cwriter_get_by_type(struct Curl_easy * data,const struct Curl_cwtype * cwt)489*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *Curl_cwriter_get_by_type(struct Curl_easy *data,
490*6236dae4SAndroid Build Coastguard Worker const struct Curl_cwtype *cwt)
491*6236dae4SAndroid Build Coastguard Worker {
492*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *writer;
493*6236dae4SAndroid Build Coastguard Worker for(writer = data->req.writer_stack; writer; writer = writer->next) {
494*6236dae4SAndroid Build Coastguard Worker if(writer->cwt == cwt)
495*6236dae4SAndroid Build Coastguard Worker return writer;
496*6236dae4SAndroid Build Coastguard Worker }
497*6236dae4SAndroid Build Coastguard Worker return NULL;
498*6236dae4SAndroid Build Coastguard Worker }
499*6236dae4SAndroid Build Coastguard Worker
Curl_cwriter_remove_by_name(struct Curl_easy * data,const char * name)500*6236dae4SAndroid Build Coastguard Worker void Curl_cwriter_remove_by_name(struct Curl_easy *data,
501*6236dae4SAndroid Build Coastguard Worker const char *name)
502*6236dae4SAndroid Build Coastguard Worker {
503*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter **anchor = &data->req.writer_stack;
504*6236dae4SAndroid Build Coastguard Worker
505*6236dae4SAndroid Build Coastguard Worker while(*anchor) {
506*6236dae4SAndroid Build Coastguard Worker if(!strcmp(name, (*anchor)->cwt->name)) {
507*6236dae4SAndroid Build Coastguard Worker struct Curl_cwriter *w = (*anchor);
508*6236dae4SAndroid Build Coastguard Worker *anchor = w->next;
509*6236dae4SAndroid Build Coastguard Worker Curl_cwriter_free(data, w);
510*6236dae4SAndroid Build Coastguard Worker continue;
511*6236dae4SAndroid Build Coastguard Worker }
512*6236dae4SAndroid Build Coastguard Worker anchor = &((*anchor)->next);
513*6236dae4SAndroid Build Coastguard Worker }
514*6236dae4SAndroid Build Coastguard Worker }
515*6236dae4SAndroid Build Coastguard Worker
Curl_cwriter_is_paused(struct Curl_easy * data)516*6236dae4SAndroid Build Coastguard Worker bool Curl_cwriter_is_paused(struct Curl_easy *data)
517*6236dae4SAndroid Build Coastguard Worker {
518*6236dae4SAndroid Build Coastguard Worker return Curl_cw_out_is_paused(data);
519*6236dae4SAndroid Build Coastguard Worker }
520*6236dae4SAndroid Build Coastguard Worker
Curl_cwriter_unpause(struct Curl_easy * data)521*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_cwriter_unpause(struct Curl_easy *data)
522*6236dae4SAndroid Build Coastguard Worker {
523*6236dae4SAndroid Build Coastguard Worker return Curl_cw_out_unpause(data);
524*6236dae4SAndroid Build Coastguard Worker }
525*6236dae4SAndroid Build Coastguard Worker
Curl_creader_read(struct Curl_easy * data,struct Curl_creader * reader,char * buf,size_t blen,size_t * nread,bool * eos)526*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_read(struct Curl_easy *data,
527*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader,
528*6236dae4SAndroid Build Coastguard Worker char *buf, size_t blen, size_t *nread, bool *eos)
529*6236dae4SAndroid Build Coastguard Worker {
530*6236dae4SAndroid Build Coastguard Worker *nread = 0;
531*6236dae4SAndroid Build Coastguard Worker *eos = FALSE;
532*6236dae4SAndroid Build Coastguard Worker if(!reader)
533*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
534*6236dae4SAndroid Build Coastguard Worker return reader->crt->do_read(data, reader, buf, blen, nread, eos);
535*6236dae4SAndroid Build Coastguard Worker }
536*6236dae4SAndroid Build Coastguard Worker
Curl_creader_def_init(struct Curl_easy * data,struct Curl_creader * reader)537*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_def_init(struct Curl_easy *data,
538*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
539*6236dae4SAndroid Build Coastguard Worker {
540*6236dae4SAndroid Build Coastguard Worker (void)data;
541*6236dae4SAndroid Build Coastguard Worker (void)reader;
542*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
543*6236dae4SAndroid Build Coastguard Worker }
544*6236dae4SAndroid Build Coastguard Worker
Curl_creader_def_close(struct Curl_easy * data,struct Curl_creader * reader)545*6236dae4SAndroid Build Coastguard Worker void Curl_creader_def_close(struct Curl_easy *data,
546*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
547*6236dae4SAndroid Build Coastguard Worker {
548*6236dae4SAndroid Build Coastguard Worker (void)data;
549*6236dae4SAndroid Build Coastguard Worker (void)reader;
550*6236dae4SAndroid Build Coastguard Worker }
551*6236dae4SAndroid Build Coastguard Worker
Curl_creader_def_read(struct Curl_easy * data,struct Curl_creader * reader,char * buf,size_t blen,size_t * nread,bool * eos)552*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_def_read(struct Curl_easy *data,
553*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader,
554*6236dae4SAndroid Build Coastguard Worker char *buf, size_t blen,
555*6236dae4SAndroid Build Coastguard Worker size_t *nread, bool *eos)
556*6236dae4SAndroid Build Coastguard Worker {
557*6236dae4SAndroid Build Coastguard Worker if(reader->next)
558*6236dae4SAndroid Build Coastguard Worker return reader->next->crt->do_read(data, reader->next, buf, blen,
559*6236dae4SAndroid Build Coastguard Worker nread, eos);
560*6236dae4SAndroid Build Coastguard Worker else {
561*6236dae4SAndroid Build Coastguard Worker *nread = 0;
562*6236dae4SAndroid Build Coastguard Worker *eos = FALSE;
563*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
564*6236dae4SAndroid Build Coastguard Worker }
565*6236dae4SAndroid Build Coastguard Worker }
566*6236dae4SAndroid Build Coastguard Worker
Curl_creader_def_needs_rewind(struct Curl_easy * data,struct Curl_creader * reader)567*6236dae4SAndroid Build Coastguard Worker bool Curl_creader_def_needs_rewind(struct Curl_easy *data,
568*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
569*6236dae4SAndroid Build Coastguard Worker {
570*6236dae4SAndroid Build Coastguard Worker (void)data;
571*6236dae4SAndroid Build Coastguard Worker (void)reader;
572*6236dae4SAndroid Build Coastguard Worker return FALSE;
573*6236dae4SAndroid Build Coastguard Worker }
574*6236dae4SAndroid Build Coastguard Worker
Curl_creader_def_total_length(struct Curl_easy * data,struct Curl_creader * reader)575*6236dae4SAndroid Build Coastguard Worker curl_off_t Curl_creader_def_total_length(struct Curl_easy *data,
576*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
577*6236dae4SAndroid Build Coastguard Worker {
578*6236dae4SAndroid Build Coastguard Worker return reader->next ?
579*6236dae4SAndroid Build Coastguard Worker reader->next->crt->total_length(data, reader->next) : -1;
580*6236dae4SAndroid Build Coastguard Worker }
581*6236dae4SAndroid Build Coastguard Worker
Curl_creader_def_resume_from(struct Curl_easy * data,struct Curl_creader * reader,curl_off_t offset)582*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_def_resume_from(struct Curl_easy *data,
583*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader,
584*6236dae4SAndroid Build Coastguard Worker curl_off_t offset)
585*6236dae4SAndroid Build Coastguard Worker {
586*6236dae4SAndroid Build Coastguard Worker (void)data;
587*6236dae4SAndroid Build Coastguard Worker (void)reader;
588*6236dae4SAndroid Build Coastguard Worker (void)offset;
589*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
590*6236dae4SAndroid Build Coastguard Worker }
591*6236dae4SAndroid Build Coastguard Worker
Curl_creader_def_rewind(struct Curl_easy * data,struct Curl_creader * reader)592*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_def_rewind(struct Curl_easy *data,
593*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
594*6236dae4SAndroid Build Coastguard Worker {
595*6236dae4SAndroid Build Coastguard Worker (void)data;
596*6236dae4SAndroid Build Coastguard Worker (void)reader;
597*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
598*6236dae4SAndroid Build Coastguard Worker }
599*6236dae4SAndroid Build Coastguard Worker
Curl_creader_def_unpause(struct Curl_easy * data,struct Curl_creader * reader)600*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_def_unpause(struct Curl_easy *data,
601*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
602*6236dae4SAndroid Build Coastguard Worker {
603*6236dae4SAndroid Build Coastguard Worker (void)data;
604*6236dae4SAndroid Build Coastguard Worker (void)reader;
605*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
606*6236dae4SAndroid Build Coastguard Worker }
607*6236dae4SAndroid Build Coastguard Worker
Curl_creader_def_is_paused(struct Curl_easy * data,struct Curl_creader * reader)608*6236dae4SAndroid Build Coastguard Worker bool Curl_creader_def_is_paused(struct Curl_easy *data,
609*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
610*6236dae4SAndroid Build Coastguard Worker {
611*6236dae4SAndroid Build Coastguard Worker (void)data;
612*6236dae4SAndroid Build Coastguard Worker (void)reader;
613*6236dae4SAndroid Build Coastguard Worker return FALSE;
614*6236dae4SAndroid Build Coastguard Worker }
615*6236dae4SAndroid Build Coastguard Worker
Curl_creader_def_done(struct Curl_easy * data,struct Curl_creader * reader,int premature)616*6236dae4SAndroid Build Coastguard Worker void Curl_creader_def_done(struct Curl_easy *data,
617*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader, int premature)
618*6236dae4SAndroid Build Coastguard Worker {
619*6236dae4SAndroid Build Coastguard Worker (void)data;
620*6236dae4SAndroid Build Coastguard Worker (void)reader;
621*6236dae4SAndroid Build Coastguard Worker (void)premature;
622*6236dae4SAndroid Build Coastguard Worker }
623*6236dae4SAndroid Build Coastguard Worker
624*6236dae4SAndroid Build Coastguard Worker struct cr_in_ctx {
625*6236dae4SAndroid Build Coastguard Worker struct Curl_creader super;
626*6236dae4SAndroid Build Coastguard Worker curl_read_callback read_cb;
627*6236dae4SAndroid Build Coastguard Worker void *cb_user_data;
628*6236dae4SAndroid Build Coastguard Worker curl_off_t total_len;
629*6236dae4SAndroid Build Coastguard Worker curl_off_t read_len;
630*6236dae4SAndroid Build Coastguard Worker CURLcode error_result;
631*6236dae4SAndroid Build Coastguard Worker BIT(seen_eos);
632*6236dae4SAndroid Build Coastguard Worker BIT(errored);
633*6236dae4SAndroid Build Coastguard Worker BIT(has_used_cb);
634*6236dae4SAndroid Build Coastguard Worker BIT(is_paused);
635*6236dae4SAndroid Build Coastguard Worker };
636*6236dae4SAndroid Build Coastguard Worker
cr_in_init(struct Curl_easy * data,struct Curl_creader * reader)637*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_in_init(struct Curl_easy *data, struct Curl_creader *reader)
638*6236dae4SAndroid Build Coastguard Worker {
639*6236dae4SAndroid Build Coastguard Worker struct cr_in_ctx *ctx = reader->ctx;
640*6236dae4SAndroid Build Coastguard Worker (void)data;
641*6236dae4SAndroid Build Coastguard Worker ctx->read_cb = data->state.fread_func;
642*6236dae4SAndroid Build Coastguard Worker ctx->cb_user_data = data->state.in;
643*6236dae4SAndroid Build Coastguard Worker ctx->total_len = -1;
644*6236dae4SAndroid Build Coastguard Worker ctx->read_len = 0;
645*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
646*6236dae4SAndroid Build Coastguard Worker }
647*6236dae4SAndroid Build Coastguard Worker
648*6236dae4SAndroid Build Coastguard Worker /* Real client reader to installed client callbacks. */
cr_in_read(struct Curl_easy * data,struct Curl_creader * reader,char * buf,size_t blen,size_t * pnread,bool * peos)649*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_in_read(struct Curl_easy *data,
650*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader,
651*6236dae4SAndroid Build Coastguard Worker char *buf, size_t blen,
652*6236dae4SAndroid Build Coastguard Worker size_t *pnread, bool *peos)
653*6236dae4SAndroid Build Coastguard Worker {
654*6236dae4SAndroid Build Coastguard Worker struct cr_in_ctx *ctx = reader->ctx;
655*6236dae4SAndroid Build Coastguard Worker size_t nread;
656*6236dae4SAndroid Build Coastguard Worker
657*6236dae4SAndroid Build Coastguard Worker ctx->is_paused = FALSE;
658*6236dae4SAndroid Build Coastguard Worker
659*6236dae4SAndroid Build Coastguard Worker /* Once we have errored, we will return the same error forever */
660*6236dae4SAndroid Build Coastguard Worker if(ctx->errored) {
661*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
662*6236dae4SAndroid Build Coastguard Worker *peos = FALSE;
663*6236dae4SAndroid Build Coastguard Worker return ctx->error_result;
664*6236dae4SAndroid Build Coastguard Worker }
665*6236dae4SAndroid Build Coastguard Worker if(ctx->seen_eos) {
666*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
667*6236dae4SAndroid Build Coastguard Worker *peos = TRUE;
668*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
669*6236dae4SAndroid Build Coastguard Worker }
670*6236dae4SAndroid Build Coastguard Worker /* respect length limitations */
671*6236dae4SAndroid Build Coastguard Worker if(ctx->total_len >= 0) {
672*6236dae4SAndroid Build Coastguard Worker curl_off_t remain = ctx->total_len - ctx->read_len;
673*6236dae4SAndroid Build Coastguard Worker if(remain <= 0)
674*6236dae4SAndroid Build Coastguard Worker blen = 0;
675*6236dae4SAndroid Build Coastguard Worker else if(remain < (curl_off_t)blen)
676*6236dae4SAndroid Build Coastguard Worker blen = (size_t)remain;
677*6236dae4SAndroid Build Coastguard Worker }
678*6236dae4SAndroid Build Coastguard Worker nread = 0;
679*6236dae4SAndroid Build Coastguard Worker if(ctx->read_cb && blen) {
680*6236dae4SAndroid Build Coastguard Worker Curl_set_in_callback(data, TRUE);
681*6236dae4SAndroid Build Coastguard Worker nread = ctx->read_cb(buf, 1, blen, ctx->cb_user_data);
682*6236dae4SAndroid Build Coastguard Worker Curl_set_in_callback(data, FALSE);
683*6236dae4SAndroid Build Coastguard Worker ctx->has_used_cb = TRUE;
684*6236dae4SAndroid Build Coastguard Worker }
685*6236dae4SAndroid Build Coastguard Worker
686*6236dae4SAndroid Build Coastguard Worker switch(nread) {
687*6236dae4SAndroid Build Coastguard Worker case 0:
688*6236dae4SAndroid Build Coastguard Worker if((ctx->total_len >= 0) && (ctx->read_len < ctx->total_len)) {
689*6236dae4SAndroid Build Coastguard Worker failf(data, "client read function EOF fail, "
690*6236dae4SAndroid Build Coastguard Worker "only %"FMT_OFF_T"/%"FMT_OFF_T " of needed bytes read",
691*6236dae4SAndroid Build Coastguard Worker ctx->read_len, ctx->total_len);
692*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
693*6236dae4SAndroid Build Coastguard Worker }
694*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
695*6236dae4SAndroid Build Coastguard Worker *peos = TRUE;
696*6236dae4SAndroid Build Coastguard Worker ctx->seen_eos = TRUE;
697*6236dae4SAndroid Build Coastguard Worker break;
698*6236dae4SAndroid Build Coastguard Worker
699*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_ABORT:
700*6236dae4SAndroid Build Coastguard Worker failf(data, "operation aborted by callback");
701*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
702*6236dae4SAndroid Build Coastguard Worker *peos = FALSE;
703*6236dae4SAndroid Build Coastguard Worker ctx->errored = TRUE;
704*6236dae4SAndroid Build Coastguard Worker ctx->error_result = CURLE_ABORTED_BY_CALLBACK;
705*6236dae4SAndroid Build Coastguard Worker return CURLE_ABORTED_BY_CALLBACK;
706*6236dae4SAndroid Build Coastguard Worker
707*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_PAUSE:
708*6236dae4SAndroid Build Coastguard Worker if(data->conn->handler->flags & PROTOPT_NONETWORK) {
709*6236dae4SAndroid Build Coastguard Worker /* protocols that work without network cannot be paused. This is
710*6236dae4SAndroid Build Coastguard Worker actually only FILE:// just now, and it cannot pause since the transfer
711*6236dae4SAndroid Build Coastguard Worker is not done using the "normal" procedure. */
712*6236dae4SAndroid Build Coastguard Worker failf(data, "Read callback asked for PAUSE when not supported");
713*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
714*6236dae4SAndroid Build Coastguard Worker }
715*6236dae4SAndroid Build Coastguard Worker /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
716*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "cr_in_read, callback returned CURL_READFUNC_PAUSE");
717*6236dae4SAndroid Build Coastguard Worker ctx->is_paused = TRUE;
718*6236dae4SAndroid Build Coastguard Worker data->req.keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */
719*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
720*6236dae4SAndroid Build Coastguard Worker *peos = FALSE;
721*6236dae4SAndroid Build Coastguard Worker break; /* nothing was read */
722*6236dae4SAndroid Build Coastguard Worker
723*6236dae4SAndroid Build Coastguard Worker default:
724*6236dae4SAndroid Build Coastguard Worker if(nread > blen) {
725*6236dae4SAndroid Build Coastguard Worker /* the read function returned a too large value */
726*6236dae4SAndroid Build Coastguard Worker failf(data, "read function returned funny value");
727*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
728*6236dae4SAndroid Build Coastguard Worker *peos = FALSE;
729*6236dae4SAndroid Build Coastguard Worker ctx->errored = TRUE;
730*6236dae4SAndroid Build Coastguard Worker ctx->error_result = CURLE_READ_ERROR;
731*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
732*6236dae4SAndroid Build Coastguard Worker }
733*6236dae4SAndroid Build Coastguard Worker ctx->read_len += nread;
734*6236dae4SAndroid Build Coastguard Worker if(ctx->total_len >= 0)
735*6236dae4SAndroid Build Coastguard Worker ctx->seen_eos = (ctx->read_len >= ctx->total_len);
736*6236dae4SAndroid Build Coastguard Worker *pnread = nread;
737*6236dae4SAndroid Build Coastguard Worker *peos = ctx->seen_eos;
738*6236dae4SAndroid Build Coastguard Worker break;
739*6236dae4SAndroid Build Coastguard Worker }
740*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "cr_in_read(len=%zu, total=%"FMT_OFF_T
741*6236dae4SAndroid Build Coastguard Worker ", read=%"FMT_OFF_T") -> %d, nread=%zu, eos=%d",
742*6236dae4SAndroid Build Coastguard Worker blen, ctx->total_len, ctx->read_len, CURLE_OK,
743*6236dae4SAndroid Build Coastguard Worker *pnread, *peos);
744*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
745*6236dae4SAndroid Build Coastguard Worker }
746*6236dae4SAndroid Build Coastguard Worker
cr_in_needs_rewind(struct Curl_easy * data,struct Curl_creader * reader)747*6236dae4SAndroid Build Coastguard Worker static bool cr_in_needs_rewind(struct Curl_easy *data,
748*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
749*6236dae4SAndroid Build Coastguard Worker {
750*6236dae4SAndroid Build Coastguard Worker struct cr_in_ctx *ctx = reader->ctx;
751*6236dae4SAndroid Build Coastguard Worker (void)data;
752*6236dae4SAndroid Build Coastguard Worker return ctx->has_used_cb;
753*6236dae4SAndroid Build Coastguard Worker }
754*6236dae4SAndroid Build Coastguard Worker
cr_in_total_length(struct Curl_easy * data,struct Curl_creader * reader)755*6236dae4SAndroid Build Coastguard Worker static curl_off_t cr_in_total_length(struct Curl_easy *data,
756*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
757*6236dae4SAndroid Build Coastguard Worker {
758*6236dae4SAndroid Build Coastguard Worker struct cr_in_ctx *ctx = reader->ctx;
759*6236dae4SAndroid Build Coastguard Worker (void)data;
760*6236dae4SAndroid Build Coastguard Worker return ctx->total_len;
761*6236dae4SAndroid Build Coastguard Worker }
762*6236dae4SAndroid Build Coastguard Worker
cr_in_resume_from(struct Curl_easy * data,struct Curl_creader * reader,curl_off_t offset)763*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_in_resume_from(struct Curl_easy *data,
764*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader,
765*6236dae4SAndroid Build Coastguard Worker curl_off_t offset)
766*6236dae4SAndroid Build Coastguard Worker {
767*6236dae4SAndroid Build Coastguard Worker struct cr_in_ctx *ctx = reader->ctx;
768*6236dae4SAndroid Build Coastguard Worker int seekerr = CURL_SEEKFUNC_CANTSEEK;
769*6236dae4SAndroid Build Coastguard Worker
770*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn);
771*6236dae4SAndroid Build Coastguard Worker /* already started reading? */
772*6236dae4SAndroid Build Coastguard Worker if(ctx->read_len)
773*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
774*6236dae4SAndroid Build Coastguard Worker
775*6236dae4SAndroid Build Coastguard Worker if(data->set.seek_func) {
776*6236dae4SAndroid Build Coastguard Worker Curl_set_in_callback(data, TRUE);
777*6236dae4SAndroid Build Coastguard Worker seekerr = data->set.seek_func(data->set.seek_client, offset, SEEK_SET);
778*6236dae4SAndroid Build Coastguard Worker Curl_set_in_callback(data, FALSE);
779*6236dae4SAndroid Build Coastguard Worker }
780*6236dae4SAndroid Build Coastguard Worker
781*6236dae4SAndroid Build Coastguard Worker if(seekerr != CURL_SEEKFUNC_OK) {
782*6236dae4SAndroid Build Coastguard Worker curl_off_t passed = 0;
783*6236dae4SAndroid Build Coastguard Worker
784*6236dae4SAndroid Build Coastguard Worker if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
785*6236dae4SAndroid Build Coastguard Worker failf(data, "Could not seek stream");
786*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
787*6236dae4SAndroid Build Coastguard Worker }
788*6236dae4SAndroid Build Coastguard Worker /* when seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */
789*6236dae4SAndroid Build Coastguard Worker do {
790*6236dae4SAndroid Build Coastguard Worker char scratch[4*1024];
791*6236dae4SAndroid Build Coastguard Worker size_t readthisamountnow =
792*6236dae4SAndroid Build Coastguard Worker (offset - passed > (curl_off_t)sizeof(scratch)) ?
793*6236dae4SAndroid Build Coastguard Worker sizeof(scratch) :
794*6236dae4SAndroid Build Coastguard Worker curlx_sotouz(offset - passed);
795*6236dae4SAndroid Build Coastguard Worker size_t actuallyread;
796*6236dae4SAndroid Build Coastguard Worker
797*6236dae4SAndroid Build Coastguard Worker Curl_set_in_callback(data, TRUE);
798*6236dae4SAndroid Build Coastguard Worker actuallyread = ctx->read_cb(scratch, 1, readthisamountnow,
799*6236dae4SAndroid Build Coastguard Worker ctx->cb_user_data);
800*6236dae4SAndroid Build Coastguard Worker Curl_set_in_callback(data, FALSE);
801*6236dae4SAndroid Build Coastguard Worker
802*6236dae4SAndroid Build Coastguard Worker passed += actuallyread;
803*6236dae4SAndroid Build Coastguard Worker if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
804*6236dae4SAndroid Build Coastguard Worker /* this checks for greater-than only to make sure that the
805*6236dae4SAndroid Build Coastguard Worker CURL_READFUNC_ABORT return code still aborts */
806*6236dae4SAndroid Build Coastguard Worker failf(data, "Could only read %" FMT_OFF_T " bytes from the input",
807*6236dae4SAndroid Build Coastguard Worker passed);
808*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
809*6236dae4SAndroid Build Coastguard Worker }
810*6236dae4SAndroid Build Coastguard Worker } while(passed < offset);
811*6236dae4SAndroid Build Coastguard Worker }
812*6236dae4SAndroid Build Coastguard Worker
813*6236dae4SAndroid Build Coastguard Worker /* now, decrease the size of the read */
814*6236dae4SAndroid Build Coastguard Worker if(ctx->total_len > 0) {
815*6236dae4SAndroid Build Coastguard Worker ctx->total_len -= offset;
816*6236dae4SAndroid Build Coastguard Worker
817*6236dae4SAndroid Build Coastguard Worker if(ctx->total_len <= 0) {
818*6236dae4SAndroid Build Coastguard Worker failf(data, "File already completely uploaded");
819*6236dae4SAndroid Build Coastguard Worker return CURLE_PARTIAL_FILE;
820*6236dae4SAndroid Build Coastguard Worker }
821*6236dae4SAndroid Build Coastguard Worker }
822*6236dae4SAndroid Build Coastguard Worker /* we have passed, proceed as normal */
823*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
824*6236dae4SAndroid Build Coastguard Worker }
825*6236dae4SAndroid Build Coastguard Worker
cr_in_rewind(struct Curl_easy * data,struct Curl_creader * reader)826*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_in_rewind(struct Curl_easy *data,
827*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
828*6236dae4SAndroid Build Coastguard Worker {
829*6236dae4SAndroid Build Coastguard Worker struct cr_in_ctx *ctx = reader->ctx;
830*6236dae4SAndroid Build Coastguard Worker
831*6236dae4SAndroid Build Coastguard Worker /* If we never invoked the callback, there is noting to rewind */
832*6236dae4SAndroid Build Coastguard Worker if(!ctx->has_used_cb)
833*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
834*6236dae4SAndroid Build Coastguard Worker
835*6236dae4SAndroid Build Coastguard Worker if(data->set.seek_func) {
836*6236dae4SAndroid Build Coastguard Worker int err;
837*6236dae4SAndroid Build Coastguard Worker
838*6236dae4SAndroid Build Coastguard Worker Curl_set_in_callback(data, TRUE);
839*6236dae4SAndroid Build Coastguard Worker err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
840*6236dae4SAndroid Build Coastguard Worker Curl_set_in_callback(data, FALSE);
841*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "cr_in, rewind via set.seek_func -> %d", err);
842*6236dae4SAndroid Build Coastguard Worker if(err) {
843*6236dae4SAndroid Build Coastguard Worker failf(data, "seek callback returned error %d", (int)err);
844*6236dae4SAndroid Build Coastguard Worker return CURLE_SEND_FAIL_REWIND;
845*6236dae4SAndroid Build Coastguard Worker }
846*6236dae4SAndroid Build Coastguard Worker }
847*6236dae4SAndroid Build Coastguard Worker else if(data->set.ioctl_func) {
848*6236dae4SAndroid Build Coastguard Worker curlioerr err;
849*6236dae4SAndroid Build Coastguard Worker
850*6236dae4SAndroid Build Coastguard Worker Curl_set_in_callback(data, TRUE);
851*6236dae4SAndroid Build Coastguard Worker err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
852*6236dae4SAndroid Build Coastguard Worker data->set.ioctl_client);
853*6236dae4SAndroid Build Coastguard Worker Curl_set_in_callback(data, FALSE);
854*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "cr_in, rewind via set.ioctl_func -> %d", (int)err);
855*6236dae4SAndroid Build Coastguard Worker if(err) {
856*6236dae4SAndroid Build Coastguard Worker failf(data, "ioctl callback returned error %d", (int)err);
857*6236dae4SAndroid Build Coastguard Worker return CURLE_SEND_FAIL_REWIND;
858*6236dae4SAndroid Build Coastguard Worker }
859*6236dae4SAndroid Build Coastguard Worker }
860*6236dae4SAndroid Build Coastguard Worker else {
861*6236dae4SAndroid Build Coastguard Worker /* If no CURLOPT_READFUNCTION is used, we know that we operate on a
862*6236dae4SAndroid Build Coastguard Worker given FILE * stream and we can actually attempt to rewind that
863*6236dae4SAndroid Build Coastguard Worker ourselves with fseek() */
864*6236dae4SAndroid Build Coastguard Worker if(data->state.fread_func == (curl_read_callback)fread) {
865*6236dae4SAndroid Build Coastguard Worker int err = fseek(data->state.in, 0, SEEK_SET);
866*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "cr_in, rewind via fseek -> %d(%d)",
867*6236dae4SAndroid Build Coastguard Worker (int)err, (int)errno);
868*6236dae4SAndroid Build Coastguard Worker if(-1 != err)
869*6236dae4SAndroid Build Coastguard Worker /* successful rewind */
870*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
871*6236dae4SAndroid Build Coastguard Worker }
872*6236dae4SAndroid Build Coastguard Worker
873*6236dae4SAndroid Build Coastguard Worker /* no callback set or failure above, makes us fail at once */
874*6236dae4SAndroid Build Coastguard Worker failf(data, "necessary data rewind was not possible");
875*6236dae4SAndroid Build Coastguard Worker return CURLE_SEND_FAIL_REWIND;
876*6236dae4SAndroid Build Coastguard Worker }
877*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
878*6236dae4SAndroid Build Coastguard Worker }
879*6236dae4SAndroid Build Coastguard Worker
cr_in_unpause(struct Curl_easy * data,struct Curl_creader * reader)880*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_in_unpause(struct Curl_easy *data,
881*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
882*6236dae4SAndroid Build Coastguard Worker {
883*6236dae4SAndroid Build Coastguard Worker struct cr_in_ctx *ctx = reader->ctx;
884*6236dae4SAndroid Build Coastguard Worker (void)data;
885*6236dae4SAndroid Build Coastguard Worker ctx->is_paused = FALSE;
886*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
887*6236dae4SAndroid Build Coastguard Worker }
888*6236dae4SAndroid Build Coastguard Worker
cr_in_is_paused(struct Curl_easy * data,struct Curl_creader * reader)889*6236dae4SAndroid Build Coastguard Worker static bool cr_in_is_paused(struct Curl_easy *data,
890*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
891*6236dae4SAndroid Build Coastguard Worker {
892*6236dae4SAndroid Build Coastguard Worker struct cr_in_ctx *ctx = reader->ctx;
893*6236dae4SAndroid Build Coastguard Worker (void)data;
894*6236dae4SAndroid Build Coastguard Worker return ctx->is_paused;
895*6236dae4SAndroid Build Coastguard Worker }
896*6236dae4SAndroid Build Coastguard Worker
897*6236dae4SAndroid Build Coastguard Worker static const struct Curl_crtype cr_in = {
898*6236dae4SAndroid Build Coastguard Worker "cr-in",
899*6236dae4SAndroid Build Coastguard Worker cr_in_init,
900*6236dae4SAndroid Build Coastguard Worker cr_in_read,
901*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_close,
902*6236dae4SAndroid Build Coastguard Worker cr_in_needs_rewind,
903*6236dae4SAndroid Build Coastguard Worker cr_in_total_length,
904*6236dae4SAndroid Build Coastguard Worker cr_in_resume_from,
905*6236dae4SAndroid Build Coastguard Worker cr_in_rewind,
906*6236dae4SAndroid Build Coastguard Worker cr_in_unpause,
907*6236dae4SAndroid Build Coastguard Worker cr_in_is_paused,
908*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_done,
909*6236dae4SAndroid Build Coastguard Worker sizeof(struct cr_in_ctx)
910*6236dae4SAndroid Build Coastguard Worker };
911*6236dae4SAndroid Build Coastguard Worker
Curl_creader_create(struct Curl_creader ** preader,struct Curl_easy * data,const struct Curl_crtype * crt,Curl_creader_phase phase)912*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_create(struct Curl_creader **preader,
913*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
914*6236dae4SAndroid Build Coastguard Worker const struct Curl_crtype *crt,
915*6236dae4SAndroid Build Coastguard Worker Curl_creader_phase phase)
916*6236dae4SAndroid Build Coastguard Worker {
917*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader = NULL;
918*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OUT_OF_MEMORY;
919*6236dae4SAndroid Build Coastguard Worker void *p;
920*6236dae4SAndroid Build Coastguard Worker
921*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(crt->creader_size >= sizeof(struct Curl_creader));
922*6236dae4SAndroid Build Coastguard Worker p = calloc(1, crt->creader_size);
923*6236dae4SAndroid Build Coastguard Worker if(!p)
924*6236dae4SAndroid Build Coastguard Worker goto out;
925*6236dae4SAndroid Build Coastguard Worker
926*6236dae4SAndroid Build Coastguard Worker reader = (struct Curl_creader *)p;
927*6236dae4SAndroid Build Coastguard Worker reader->crt = crt;
928*6236dae4SAndroid Build Coastguard Worker reader->ctx = p;
929*6236dae4SAndroid Build Coastguard Worker reader->phase = phase;
930*6236dae4SAndroid Build Coastguard Worker result = crt->do_init(data, reader);
931*6236dae4SAndroid Build Coastguard Worker
932*6236dae4SAndroid Build Coastguard Worker out:
933*6236dae4SAndroid Build Coastguard Worker *preader = result ? NULL : reader;
934*6236dae4SAndroid Build Coastguard Worker if(result)
935*6236dae4SAndroid Build Coastguard Worker free(reader);
936*6236dae4SAndroid Build Coastguard Worker return result;
937*6236dae4SAndroid Build Coastguard Worker }
938*6236dae4SAndroid Build Coastguard Worker
Curl_creader_free(struct Curl_easy * data,struct Curl_creader * reader)939*6236dae4SAndroid Build Coastguard Worker void Curl_creader_free(struct Curl_easy *data, struct Curl_creader *reader)
940*6236dae4SAndroid Build Coastguard Worker {
941*6236dae4SAndroid Build Coastguard Worker if(reader) {
942*6236dae4SAndroid Build Coastguard Worker reader->crt->do_close(data, reader);
943*6236dae4SAndroid Build Coastguard Worker free(reader);
944*6236dae4SAndroid Build Coastguard Worker }
945*6236dae4SAndroid Build Coastguard Worker }
946*6236dae4SAndroid Build Coastguard Worker
947*6236dae4SAndroid Build Coastguard Worker struct cr_lc_ctx {
948*6236dae4SAndroid Build Coastguard Worker struct Curl_creader super;
949*6236dae4SAndroid Build Coastguard Worker struct bufq buf;
950*6236dae4SAndroid Build Coastguard Worker BIT(read_eos); /* we read an EOS from the next reader */
951*6236dae4SAndroid Build Coastguard Worker BIT(eos); /* we have returned an EOS */
952*6236dae4SAndroid Build Coastguard Worker BIT(prev_cr); /* the last byte was a CR */
953*6236dae4SAndroid Build Coastguard Worker };
954*6236dae4SAndroid Build Coastguard Worker
cr_lc_init(struct Curl_easy * data,struct Curl_creader * reader)955*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_lc_init(struct Curl_easy *data, struct Curl_creader *reader)
956*6236dae4SAndroid Build Coastguard Worker {
957*6236dae4SAndroid Build Coastguard Worker struct cr_lc_ctx *ctx = reader->ctx;
958*6236dae4SAndroid Build Coastguard Worker (void)data;
959*6236dae4SAndroid Build Coastguard Worker Curl_bufq_init2(&ctx->buf, (16 * 1024), 1, BUFQ_OPT_SOFT_LIMIT);
960*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
961*6236dae4SAndroid Build Coastguard Worker }
962*6236dae4SAndroid Build Coastguard Worker
cr_lc_close(struct Curl_easy * data,struct Curl_creader * reader)963*6236dae4SAndroid Build Coastguard Worker static void cr_lc_close(struct Curl_easy *data, struct Curl_creader *reader)
964*6236dae4SAndroid Build Coastguard Worker {
965*6236dae4SAndroid Build Coastguard Worker struct cr_lc_ctx *ctx = reader->ctx;
966*6236dae4SAndroid Build Coastguard Worker (void)data;
967*6236dae4SAndroid Build Coastguard Worker Curl_bufq_free(&ctx->buf);
968*6236dae4SAndroid Build Coastguard Worker }
969*6236dae4SAndroid Build Coastguard Worker
970*6236dae4SAndroid Build Coastguard Worker /* client reader doing line end conversions. */
cr_lc_read(struct Curl_easy * data,struct Curl_creader * reader,char * buf,size_t blen,size_t * pnread,bool * peos)971*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_lc_read(struct Curl_easy *data,
972*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader,
973*6236dae4SAndroid Build Coastguard Worker char *buf, size_t blen,
974*6236dae4SAndroid Build Coastguard Worker size_t *pnread, bool *peos)
975*6236dae4SAndroid Build Coastguard Worker {
976*6236dae4SAndroid Build Coastguard Worker struct cr_lc_ctx *ctx = reader->ctx;
977*6236dae4SAndroid Build Coastguard Worker CURLcode result;
978*6236dae4SAndroid Build Coastguard Worker size_t nread, i, start, n;
979*6236dae4SAndroid Build Coastguard Worker bool eos;
980*6236dae4SAndroid Build Coastguard Worker
981*6236dae4SAndroid Build Coastguard Worker if(ctx->eos) {
982*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
983*6236dae4SAndroid Build Coastguard Worker *peos = TRUE;
984*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
985*6236dae4SAndroid Build Coastguard Worker }
986*6236dae4SAndroid Build Coastguard Worker
987*6236dae4SAndroid Build Coastguard Worker if(Curl_bufq_is_empty(&ctx->buf)) {
988*6236dae4SAndroid Build Coastguard Worker if(ctx->read_eos) {
989*6236dae4SAndroid Build Coastguard Worker ctx->eos = TRUE;
990*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
991*6236dae4SAndroid Build Coastguard Worker *peos = TRUE;
992*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
993*6236dae4SAndroid Build Coastguard Worker }
994*6236dae4SAndroid Build Coastguard Worker /* Still getting data form the next reader, ctx->buf is empty */
995*6236dae4SAndroid Build Coastguard Worker result = Curl_creader_read(data, reader->next, buf, blen, &nread, &eos);
996*6236dae4SAndroid Build Coastguard Worker if(result)
997*6236dae4SAndroid Build Coastguard Worker return result;
998*6236dae4SAndroid Build Coastguard Worker ctx->read_eos = eos;
999*6236dae4SAndroid Build Coastguard Worker
1000*6236dae4SAndroid Build Coastguard Worker if(!nread || !memchr(buf, '\n', nread)) {
1001*6236dae4SAndroid Build Coastguard Worker /* nothing to convert, return this right away */
1002*6236dae4SAndroid Build Coastguard Worker if(ctx->read_eos)
1003*6236dae4SAndroid Build Coastguard Worker ctx->eos = TRUE;
1004*6236dae4SAndroid Build Coastguard Worker *pnread = nread;
1005*6236dae4SAndroid Build Coastguard Worker *peos = ctx->eos;
1006*6236dae4SAndroid Build Coastguard Worker goto out;
1007*6236dae4SAndroid Build Coastguard Worker }
1008*6236dae4SAndroid Build Coastguard Worker
1009*6236dae4SAndroid Build Coastguard Worker /* at least one \n might need conversion to '\r\n', place into ctx->buf */
1010*6236dae4SAndroid Build Coastguard Worker for(i = start = 0; i < nread; ++i) {
1011*6236dae4SAndroid Build Coastguard Worker /* if this byte is not an LF character, or if the preceding character is
1012*6236dae4SAndroid Build Coastguard Worker a CR (meaning this already is a CRLF pair), go to next */
1013*6236dae4SAndroid Build Coastguard Worker if((buf[i] != '\n') || ctx->prev_cr) {
1014*6236dae4SAndroid Build Coastguard Worker ctx->prev_cr = (buf[i] == '\r');
1015*6236dae4SAndroid Build Coastguard Worker continue;
1016*6236dae4SAndroid Build Coastguard Worker }
1017*6236dae4SAndroid Build Coastguard Worker ctx->prev_cr = FALSE;
1018*6236dae4SAndroid Build Coastguard Worker /* on a soft limit bufq, we do not need to check length */
1019*6236dae4SAndroid Build Coastguard Worker result = Curl_bufq_cwrite(&ctx->buf, buf + start, i - start, &n);
1020*6236dae4SAndroid Build Coastguard Worker if(!result)
1021*6236dae4SAndroid Build Coastguard Worker result = Curl_bufq_cwrite(&ctx->buf, STRCONST("\r\n"), &n);
1022*6236dae4SAndroid Build Coastguard Worker if(result)
1023*6236dae4SAndroid Build Coastguard Worker return result;
1024*6236dae4SAndroid Build Coastguard Worker start = i + 1;
1025*6236dae4SAndroid Build Coastguard Worker if(!data->set.crlf && (data->state.infilesize != -1)) {
1026*6236dae4SAndroid Build Coastguard Worker /* we are here only because FTP is in ASCII mode...
1027*6236dae4SAndroid Build Coastguard Worker bump infilesize for the LF we just added */
1028*6236dae4SAndroid Build Coastguard Worker data->state.infilesize++;
1029*6236dae4SAndroid Build Coastguard Worker /* comment: this might work for FTP, but in HTTP we could not change
1030*6236dae4SAndroid Build Coastguard Worker * the content length after having started the request... */
1031*6236dae4SAndroid Build Coastguard Worker }
1032*6236dae4SAndroid Build Coastguard Worker }
1033*6236dae4SAndroid Build Coastguard Worker
1034*6236dae4SAndroid Build Coastguard Worker if(start < i) { /* leftover */
1035*6236dae4SAndroid Build Coastguard Worker result = Curl_bufq_cwrite(&ctx->buf, buf + start, i - start, &n);
1036*6236dae4SAndroid Build Coastguard Worker if(result)
1037*6236dae4SAndroid Build Coastguard Worker return result;
1038*6236dae4SAndroid Build Coastguard Worker }
1039*6236dae4SAndroid Build Coastguard Worker }
1040*6236dae4SAndroid Build Coastguard Worker
1041*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!Curl_bufq_is_empty(&ctx->buf));
1042*6236dae4SAndroid Build Coastguard Worker *peos = FALSE;
1043*6236dae4SAndroid Build Coastguard Worker result = Curl_bufq_cread(&ctx->buf, buf, blen, pnread);
1044*6236dae4SAndroid Build Coastguard Worker if(!result && ctx->read_eos && Curl_bufq_is_empty(&ctx->buf)) {
1045*6236dae4SAndroid Build Coastguard Worker /* no more data, read all, done. */
1046*6236dae4SAndroid Build Coastguard Worker ctx->eos = TRUE;
1047*6236dae4SAndroid Build Coastguard Worker *peos = TRUE;
1048*6236dae4SAndroid Build Coastguard Worker }
1049*6236dae4SAndroid Build Coastguard Worker
1050*6236dae4SAndroid Build Coastguard Worker out:
1051*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "cr_lc_read(len=%zu) -> %d, nread=%zu, eos=%d",
1052*6236dae4SAndroid Build Coastguard Worker blen, result, *pnread, *peos);
1053*6236dae4SAndroid Build Coastguard Worker return result;
1054*6236dae4SAndroid Build Coastguard Worker }
1055*6236dae4SAndroid Build Coastguard Worker
cr_lc_total_length(struct Curl_easy * data,struct Curl_creader * reader)1056*6236dae4SAndroid Build Coastguard Worker static curl_off_t cr_lc_total_length(struct Curl_easy *data,
1057*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
1058*6236dae4SAndroid Build Coastguard Worker {
1059*6236dae4SAndroid Build Coastguard Worker /* this reader changes length depending on input */
1060*6236dae4SAndroid Build Coastguard Worker (void)data;
1061*6236dae4SAndroid Build Coastguard Worker (void)reader;
1062*6236dae4SAndroid Build Coastguard Worker return -1;
1063*6236dae4SAndroid Build Coastguard Worker }
1064*6236dae4SAndroid Build Coastguard Worker
1065*6236dae4SAndroid Build Coastguard Worker static const struct Curl_crtype cr_lc = {
1066*6236dae4SAndroid Build Coastguard Worker "cr-lineconv",
1067*6236dae4SAndroid Build Coastguard Worker cr_lc_init,
1068*6236dae4SAndroid Build Coastguard Worker cr_lc_read,
1069*6236dae4SAndroid Build Coastguard Worker cr_lc_close,
1070*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_needs_rewind,
1071*6236dae4SAndroid Build Coastguard Worker cr_lc_total_length,
1072*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_resume_from,
1073*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_rewind,
1074*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_unpause,
1075*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_is_paused,
1076*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_done,
1077*6236dae4SAndroid Build Coastguard Worker sizeof(struct cr_lc_ctx)
1078*6236dae4SAndroid Build Coastguard Worker };
1079*6236dae4SAndroid Build Coastguard Worker
cr_lc_add(struct Curl_easy * data)1080*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_lc_add(struct Curl_easy *data)
1081*6236dae4SAndroid Build Coastguard Worker {
1082*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader = NULL;
1083*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1084*6236dae4SAndroid Build Coastguard Worker
1085*6236dae4SAndroid Build Coastguard Worker result = Curl_creader_create(&reader, data, &cr_lc,
1086*6236dae4SAndroid Build Coastguard Worker CURL_CR_CONTENT_ENCODE);
1087*6236dae4SAndroid Build Coastguard Worker if(!result)
1088*6236dae4SAndroid Build Coastguard Worker result = Curl_creader_add(data, reader);
1089*6236dae4SAndroid Build Coastguard Worker
1090*6236dae4SAndroid Build Coastguard Worker if(result && reader)
1091*6236dae4SAndroid Build Coastguard Worker Curl_creader_free(data, reader);
1092*6236dae4SAndroid Build Coastguard Worker return result;
1093*6236dae4SAndroid Build Coastguard Worker }
1094*6236dae4SAndroid Build Coastguard Worker
do_init_reader_stack(struct Curl_easy * data,struct Curl_creader * r)1095*6236dae4SAndroid Build Coastguard Worker static CURLcode do_init_reader_stack(struct Curl_easy *data,
1096*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *r)
1097*6236dae4SAndroid Build Coastguard Worker {
1098*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1099*6236dae4SAndroid Build Coastguard Worker curl_off_t clen;
1100*6236dae4SAndroid Build Coastguard Worker
1101*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(r);
1102*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(r->crt);
1103*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(r->phase == CURL_CR_CLIENT);
1104*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!data->req.reader_stack);
1105*6236dae4SAndroid Build Coastguard Worker
1106*6236dae4SAndroid Build Coastguard Worker data->req.reader_stack = r;
1107*6236dae4SAndroid Build Coastguard Worker clen = r->crt->total_length(data, r);
1108*6236dae4SAndroid Build Coastguard Worker /* if we do not have 0 length init, and crlf conversion is wanted,
1109*6236dae4SAndroid Build Coastguard Worker * add the reader for it */
1110*6236dae4SAndroid Build Coastguard Worker if(clen && (data->set.crlf
1111*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_PREFER_LF_LINEENDS
1112*6236dae4SAndroid Build Coastguard Worker || data->state.prefer_ascii
1113*6236dae4SAndroid Build Coastguard Worker #endif
1114*6236dae4SAndroid Build Coastguard Worker )) {
1115*6236dae4SAndroid Build Coastguard Worker result = cr_lc_add(data);
1116*6236dae4SAndroid Build Coastguard Worker if(result)
1117*6236dae4SAndroid Build Coastguard Worker return result;
1118*6236dae4SAndroid Build Coastguard Worker }
1119*6236dae4SAndroid Build Coastguard Worker
1120*6236dae4SAndroid Build Coastguard Worker return result;
1121*6236dae4SAndroid Build Coastguard Worker }
1122*6236dae4SAndroid Build Coastguard Worker
Curl_creader_set_fread(struct Curl_easy * data,curl_off_t len)1123*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_set_fread(struct Curl_easy *data, curl_off_t len)
1124*6236dae4SAndroid Build Coastguard Worker {
1125*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1126*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *r;
1127*6236dae4SAndroid Build Coastguard Worker struct cr_in_ctx *ctx;
1128*6236dae4SAndroid Build Coastguard Worker
1129*6236dae4SAndroid Build Coastguard Worker result = Curl_creader_create(&r, data, &cr_in, CURL_CR_CLIENT);
1130*6236dae4SAndroid Build Coastguard Worker if(result)
1131*6236dae4SAndroid Build Coastguard Worker goto out;
1132*6236dae4SAndroid Build Coastguard Worker ctx = r->ctx;
1133*6236dae4SAndroid Build Coastguard Worker ctx->total_len = len;
1134*6236dae4SAndroid Build Coastguard Worker
1135*6236dae4SAndroid Build Coastguard Worker cl_reset_reader(data);
1136*6236dae4SAndroid Build Coastguard Worker result = do_init_reader_stack(data, r);
1137*6236dae4SAndroid Build Coastguard Worker out:
1138*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "add fread reader, len=%"FMT_OFF_T " -> %d",
1139*6236dae4SAndroid Build Coastguard Worker len, result);
1140*6236dae4SAndroid Build Coastguard Worker return result;
1141*6236dae4SAndroid Build Coastguard Worker }
1142*6236dae4SAndroid Build Coastguard Worker
Curl_creader_add(struct Curl_easy * data,struct Curl_creader * reader)1143*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_add(struct Curl_easy *data,
1144*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
1145*6236dae4SAndroid Build Coastguard Worker {
1146*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1147*6236dae4SAndroid Build Coastguard Worker struct Curl_creader **anchor = &data->req.reader_stack;
1148*6236dae4SAndroid Build Coastguard Worker
1149*6236dae4SAndroid Build Coastguard Worker if(!*anchor) {
1150*6236dae4SAndroid Build Coastguard Worker result = Curl_creader_set_fread(data, data->state.infilesize);
1151*6236dae4SAndroid Build Coastguard Worker if(result)
1152*6236dae4SAndroid Build Coastguard Worker return result;
1153*6236dae4SAndroid Build Coastguard Worker }
1154*6236dae4SAndroid Build Coastguard Worker
1155*6236dae4SAndroid Build Coastguard Worker /* Insert the writer as first in its phase.
1156*6236dae4SAndroid Build Coastguard Worker * Skip existing readers of lower phases. */
1157*6236dae4SAndroid Build Coastguard Worker while(*anchor && (*anchor)->phase < reader->phase)
1158*6236dae4SAndroid Build Coastguard Worker anchor = &((*anchor)->next);
1159*6236dae4SAndroid Build Coastguard Worker reader->next = *anchor;
1160*6236dae4SAndroid Build Coastguard Worker *anchor = reader;
1161*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1162*6236dae4SAndroid Build Coastguard Worker }
1163*6236dae4SAndroid Build Coastguard Worker
Curl_creader_set(struct Curl_easy * data,struct Curl_creader * r)1164*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_set(struct Curl_easy *data, struct Curl_creader *r)
1165*6236dae4SAndroid Build Coastguard Worker {
1166*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1167*6236dae4SAndroid Build Coastguard Worker
1168*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(r);
1169*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(r->crt);
1170*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(r->phase == CURL_CR_CLIENT);
1171*6236dae4SAndroid Build Coastguard Worker
1172*6236dae4SAndroid Build Coastguard Worker cl_reset_reader(data);
1173*6236dae4SAndroid Build Coastguard Worker result = do_init_reader_stack(data, r);
1174*6236dae4SAndroid Build Coastguard Worker if(result)
1175*6236dae4SAndroid Build Coastguard Worker Curl_creader_free(data, r);
1176*6236dae4SAndroid Build Coastguard Worker return result;
1177*6236dae4SAndroid Build Coastguard Worker }
1178*6236dae4SAndroid Build Coastguard Worker
Curl_client_read(struct Curl_easy * data,char * buf,size_t blen,size_t * nread,bool * eos)1179*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen,
1180*6236dae4SAndroid Build Coastguard Worker size_t *nread, bool *eos)
1181*6236dae4SAndroid Build Coastguard Worker {
1182*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1183*6236dae4SAndroid Build Coastguard Worker
1184*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(buf);
1185*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(blen);
1186*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(nread);
1187*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(eos);
1188*6236dae4SAndroid Build Coastguard Worker
1189*6236dae4SAndroid Build Coastguard Worker if(!data->req.reader_stack) {
1190*6236dae4SAndroid Build Coastguard Worker result = Curl_creader_set_fread(data, data->state.infilesize);
1191*6236dae4SAndroid Build Coastguard Worker if(result)
1192*6236dae4SAndroid Build Coastguard Worker return result;
1193*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->req.reader_stack);
1194*6236dae4SAndroid Build Coastguard Worker }
1195*6236dae4SAndroid Build Coastguard Worker
1196*6236dae4SAndroid Build Coastguard Worker result = Curl_creader_read(data, data->req.reader_stack, buf, blen,
1197*6236dae4SAndroid Build Coastguard Worker nread, eos);
1198*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "client_read(len=%zu) -> %d, nread=%zu, eos=%d",
1199*6236dae4SAndroid Build Coastguard Worker blen, result, *nread, *eos);
1200*6236dae4SAndroid Build Coastguard Worker return result;
1201*6236dae4SAndroid Build Coastguard Worker }
1202*6236dae4SAndroid Build Coastguard Worker
Curl_creader_needs_rewind(struct Curl_easy * data)1203*6236dae4SAndroid Build Coastguard Worker bool Curl_creader_needs_rewind(struct Curl_easy *data)
1204*6236dae4SAndroid Build Coastguard Worker {
1205*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader = data->req.reader_stack;
1206*6236dae4SAndroid Build Coastguard Worker while(reader) {
1207*6236dae4SAndroid Build Coastguard Worker if(reader->crt->needs_rewind(data, reader)) {
1208*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "client reader needs rewind before next request");
1209*6236dae4SAndroid Build Coastguard Worker return TRUE;
1210*6236dae4SAndroid Build Coastguard Worker }
1211*6236dae4SAndroid Build Coastguard Worker reader = reader->next;
1212*6236dae4SAndroid Build Coastguard Worker }
1213*6236dae4SAndroid Build Coastguard Worker return FALSE;
1214*6236dae4SAndroid Build Coastguard Worker }
1215*6236dae4SAndroid Build Coastguard Worker
cr_null_read(struct Curl_easy * data,struct Curl_creader * reader,char * buf,size_t blen,size_t * pnread,bool * peos)1216*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_null_read(struct Curl_easy *data,
1217*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader,
1218*6236dae4SAndroid Build Coastguard Worker char *buf, size_t blen,
1219*6236dae4SAndroid Build Coastguard Worker size_t *pnread, bool *peos)
1220*6236dae4SAndroid Build Coastguard Worker {
1221*6236dae4SAndroid Build Coastguard Worker (void)data;
1222*6236dae4SAndroid Build Coastguard Worker (void)reader;
1223*6236dae4SAndroid Build Coastguard Worker (void)buf;
1224*6236dae4SAndroid Build Coastguard Worker (void)blen;
1225*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
1226*6236dae4SAndroid Build Coastguard Worker *peos = TRUE;
1227*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1228*6236dae4SAndroid Build Coastguard Worker }
1229*6236dae4SAndroid Build Coastguard Worker
cr_null_total_length(struct Curl_easy * data,struct Curl_creader * reader)1230*6236dae4SAndroid Build Coastguard Worker static curl_off_t cr_null_total_length(struct Curl_easy *data,
1231*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
1232*6236dae4SAndroid Build Coastguard Worker {
1233*6236dae4SAndroid Build Coastguard Worker /* this reader changes length depending on input */
1234*6236dae4SAndroid Build Coastguard Worker (void)data;
1235*6236dae4SAndroid Build Coastguard Worker (void)reader;
1236*6236dae4SAndroid Build Coastguard Worker return 0;
1237*6236dae4SAndroid Build Coastguard Worker }
1238*6236dae4SAndroid Build Coastguard Worker
1239*6236dae4SAndroid Build Coastguard Worker static const struct Curl_crtype cr_null = {
1240*6236dae4SAndroid Build Coastguard Worker "cr-null",
1241*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_init,
1242*6236dae4SAndroid Build Coastguard Worker cr_null_read,
1243*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_close,
1244*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_needs_rewind,
1245*6236dae4SAndroid Build Coastguard Worker cr_null_total_length,
1246*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_resume_from,
1247*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_rewind,
1248*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_unpause,
1249*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_is_paused,
1250*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_done,
1251*6236dae4SAndroid Build Coastguard Worker sizeof(struct Curl_creader)
1252*6236dae4SAndroid Build Coastguard Worker };
1253*6236dae4SAndroid Build Coastguard Worker
Curl_creader_set_null(struct Curl_easy * data)1254*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_set_null(struct Curl_easy *data)
1255*6236dae4SAndroid Build Coastguard Worker {
1256*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *r;
1257*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1258*6236dae4SAndroid Build Coastguard Worker
1259*6236dae4SAndroid Build Coastguard Worker result = Curl_creader_create(&r, data, &cr_null, CURL_CR_CLIENT);
1260*6236dae4SAndroid Build Coastguard Worker if(result)
1261*6236dae4SAndroid Build Coastguard Worker return result;
1262*6236dae4SAndroid Build Coastguard Worker
1263*6236dae4SAndroid Build Coastguard Worker cl_reset_reader(data);
1264*6236dae4SAndroid Build Coastguard Worker return do_init_reader_stack(data, r);
1265*6236dae4SAndroid Build Coastguard Worker }
1266*6236dae4SAndroid Build Coastguard Worker
1267*6236dae4SAndroid Build Coastguard Worker struct cr_buf_ctx {
1268*6236dae4SAndroid Build Coastguard Worker struct Curl_creader super;
1269*6236dae4SAndroid Build Coastguard Worker const char *buf;
1270*6236dae4SAndroid Build Coastguard Worker size_t blen;
1271*6236dae4SAndroid Build Coastguard Worker size_t index;
1272*6236dae4SAndroid Build Coastguard Worker };
1273*6236dae4SAndroid Build Coastguard Worker
cr_buf_read(struct Curl_easy * data,struct Curl_creader * reader,char * buf,size_t blen,size_t * pnread,bool * peos)1274*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_buf_read(struct Curl_easy *data,
1275*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader,
1276*6236dae4SAndroid Build Coastguard Worker char *buf, size_t blen,
1277*6236dae4SAndroid Build Coastguard Worker size_t *pnread, bool *peos)
1278*6236dae4SAndroid Build Coastguard Worker {
1279*6236dae4SAndroid Build Coastguard Worker struct cr_buf_ctx *ctx = reader->ctx;
1280*6236dae4SAndroid Build Coastguard Worker size_t nread = ctx->blen - ctx->index;
1281*6236dae4SAndroid Build Coastguard Worker
1282*6236dae4SAndroid Build Coastguard Worker (void)data;
1283*6236dae4SAndroid Build Coastguard Worker if(!nread || !ctx->buf) {
1284*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
1285*6236dae4SAndroid Build Coastguard Worker *peos = TRUE;
1286*6236dae4SAndroid Build Coastguard Worker }
1287*6236dae4SAndroid Build Coastguard Worker else {
1288*6236dae4SAndroid Build Coastguard Worker if(nread > blen)
1289*6236dae4SAndroid Build Coastguard Worker nread = blen;
1290*6236dae4SAndroid Build Coastguard Worker memcpy(buf, ctx->buf + ctx->index, nread);
1291*6236dae4SAndroid Build Coastguard Worker *pnread = nread;
1292*6236dae4SAndroid Build Coastguard Worker ctx->index += nread;
1293*6236dae4SAndroid Build Coastguard Worker *peos = (ctx->index == ctx->blen);
1294*6236dae4SAndroid Build Coastguard Worker }
1295*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "cr_buf_read(len=%zu) -> 0, nread=%zu, eos=%d",
1296*6236dae4SAndroid Build Coastguard Worker blen, *pnread, *peos);
1297*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1298*6236dae4SAndroid Build Coastguard Worker }
1299*6236dae4SAndroid Build Coastguard Worker
cr_buf_needs_rewind(struct Curl_easy * data,struct Curl_creader * reader)1300*6236dae4SAndroid Build Coastguard Worker static bool cr_buf_needs_rewind(struct Curl_easy *data,
1301*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
1302*6236dae4SAndroid Build Coastguard Worker {
1303*6236dae4SAndroid Build Coastguard Worker struct cr_buf_ctx *ctx = reader->ctx;
1304*6236dae4SAndroid Build Coastguard Worker (void)data;
1305*6236dae4SAndroid Build Coastguard Worker return ctx->index > 0;
1306*6236dae4SAndroid Build Coastguard Worker }
1307*6236dae4SAndroid Build Coastguard Worker
cr_buf_total_length(struct Curl_easy * data,struct Curl_creader * reader)1308*6236dae4SAndroid Build Coastguard Worker static curl_off_t cr_buf_total_length(struct Curl_easy *data,
1309*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
1310*6236dae4SAndroid Build Coastguard Worker {
1311*6236dae4SAndroid Build Coastguard Worker struct cr_buf_ctx *ctx = reader->ctx;
1312*6236dae4SAndroid Build Coastguard Worker (void)data;
1313*6236dae4SAndroid Build Coastguard Worker return (curl_off_t)ctx->blen;
1314*6236dae4SAndroid Build Coastguard Worker }
1315*6236dae4SAndroid Build Coastguard Worker
cr_buf_resume_from(struct Curl_easy * data,struct Curl_creader * reader,curl_off_t offset)1316*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_buf_resume_from(struct Curl_easy *data,
1317*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader,
1318*6236dae4SAndroid Build Coastguard Worker curl_off_t offset)
1319*6236dae4SAndroid Build Coastguard Worker {
1320*6236dae4SAndroid Build Coastguard Worker struct cr_buf_ctx *ctx = reader->ctx;
1321*6236dae4SAndroid Build Coastguard Worker size_t boffset;
1322*6236dae4SAndroid Build Coastguard Worker
1323*6236dae4SAndroid Build Coastguard Worker (void)data;
1324*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data->conn);
1325*6236dae4SAndroid Build Coastguard Worker /* already started reading? */
1326*6236dae4SAndroid Build Coastguard Worker if(ctx->index)
1327*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
1328*6236dae4SAndroid Build Coastguard Worker if(offset <= 0)
1329*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1330*6236dae4SAndroid Build Coastguard Worker boffset = (size_t)offset;
1331*6236dae4SAndroid Build Coastguard Worker if(boffset > ctx->blen)
1332*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
1333*6236dae4SAndroid Build Coastguard Worker
1334*6236dae4SAndroid Build Coastguard Worker ctx->buf += boffset;
1335*6236dae4SAndroid Build Coastguard Worker ctx->blen -= boffset;
1336*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1337*6236dae4SAndroid Build Coastguard Worker }
1338*6236dae4SAndroid Build Coastguard Worker
1339*6236dae4SAndroid Build Coastguard Worker static const struct Curl_crtype cr_buf = {
1340*6236dae4SAndroid Build Coastguard Worker "cr-buf",
1341*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_init,
1342*6236dae4SAndroid Build Coastguard Worker cr_buf_read,
1343*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_close,
1344*6236dae4SAndroid Build Coastguard Worker cr_buf_needs_rewind,
1345*6236dae4SAndroid Build Coastguard Worker cr_buf_total_length,
1346*6236dae4SAndroid Build Coastguard Worker cr_buf_resume_from,
1347*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_rewind,
1348*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_unpause,
1349*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_is_paused,
1350*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_done,
1351*6236dae4SAndroid Build Coastguard Worker sizeof(struct cr_buf_ctx)
1352*6236dae4SAndroid Build Coastguard Worker };
1353*6236dae4SAndroid Build Coastguard Worker
Curl_creader_set_buf(struct Curl_easy * data,const char * buf,size_t blen)1354*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_set_buf(struct Curl_easy *data,
1355*6236dae4SAndroid Build Coastguard Worker const char *buf, size_t blen)
1356*6236dae4SAndroid Build Coastguard Worker {
1357*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1358*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *r;
1359*6236dae4SAndroid Build Coastguard Worker struct cr_buf_ctx *ctx;
1360*6236dae4SAndroid Build Coastguard Worker
1361*6236dae4SAndroid Build Coastguard Worker result = Curl_creader_create(&r, data, &cr_buf, CURL_CR_CLIENT);
1362*6236dae4SAndroid Build Coastguard Worker if(result)
1363*6236dae4SAndroid Build Coastguard Worker goto out;
1364*6236dae4SAndroid Build Coastguard Worker ctx = r->ctx;
1365*6236dae4SAndroid Build Coastguard Worker ctx->buf = buf;
1366*6236dae4SAndroid Build Coastguard Worker ctx->blen = blen;
1367*6236dae4SAndroid Build Coastguard Worker ctx->index = 0;
1368*6236dae4SAndroid Build Coastguard Worker
1369*6236dae4SAndroid Build Coastguard Worker cl_reset_reader(data);
1370*6236dae4SAndroid Build Coastguard Worker result = do_init_reader_stack(data, r);
1371*6236dae4SAndroid Build Coastguard Worker out:
1372*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "add buf reader, len=%zu -> %d", blen, result);
1373*6236dae4SAndroid Build Coastguard Worker return result;
1374*6236dae4SAndroid Build Coastguard Worker }
1375*6236dae4SAndroid Build Coastguard Worker
Curl_creader_total_length(struct Curl_easy * data)1376*6236dae4SAndroid Build Coastguard Worker curl_off_t Curl_creader_total_length(struct Curl_easy *data)
1377*6236dae4SAndroid Build Coastguard Worker {
1378*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *r = data->req.reader_stack;
1379*6236dae4SAndroid Build Coastguard Worker return r ? r->crt->total_length(data, r) : -1;
1380*6236dae4SAndroid Build Coastguard Worker }
1381*6236dae4SAndroid Build Coastguard Worker
Curl_creader_client_length(struct Curl_easy * data)1382*6236dae4SAndroid Build Coastguard Worker curl_off_t Curl_creader_client_length(struct Curl_easy *data)
1383*6236dae4SAndroid Build Coastguard Worker {
1384*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *r = data->req.reader_stack;
1385*6236dae4SAndroid Build Coastguard Worker while(r && r->phase != CURL_CR_CLIENT)
1386*6236dae4SAndroid Build Coastguard Worker r = r->next;
1387*6236dae4SAndroid Build Coastguard Worker return r ? r->crt->total_length(data, r) : -1;
1388*6236dae4SAndroid Build Coastguard Worker }
1389*6236dae4SAndroid Build Coastguard Worker
Curl_creader_resume_from(struct Curl_easy * data,curl_off_t offset)1390*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_resume_from(struct Curl_easy *data, curl_off_t offset)
1391*6236dae4SAndroid Build Coastguard Worker {
1392*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *r = data->req.reader_stack;
1393*6236dae4SAndroid Build Coastguard Worker while(r && r->phase != CURL_CR_CLIENT)
1394*6236dae4SAndroid Build Coastguard Worker r = r->next;
1395*6236dae4SAndroid Build Coastguard Worker return r ? r->crt->resume_from(data, r, offset) : CURLE_READ_ERROR;
1396*6236dae4SAndroid Build Coastguard Worker }
1397*6236dae4SAndroid Build Coastguard Worker
Curl_creader_unpause(struct Curl_easy * data)1398*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_unpause(struct Curl_easy *data)
1399*6236dae4SAndroid Build Coastguard Worker {
1400*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader = data->req.reader_stack;
1401*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1402*6236dae4SAndroid Build Coastguard Worker
1403*6236dae4SAndroid Build Coastguard Worker while(reader) {
1404*6236dae4SAndroid Build Coastguard Worker result = reader->crt->unpause(data, reader);
1405*6236dae4SAndroid Build Coastguard Worker if(result)
1406*6236dae4SAndroid Build Coastguard Worker break;
1407*6236dae4SAndroid Build Coastguard Worker reader = reader->next;
1408*6236dae4SAndroid Build Coastguard Worker }
1409*6236dae4SAndroid Build Coastguard Worker return result;
1410*6236dae4SAndroid Build Coastguard Worker }
1411*6236dae4SAndroid Build Coastguard Worker
Curl_creader_is_paused(struct Curl_easy * data)1412*6236dae4SAndroid Build Coastguard Worker bool Curl_creader_is_paused(struct Curl_easy *data)
1413*6236dae4SAndroid Build Coastguard Worker {
1414*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader = data->req.reader_stack;
1415*6236dae4SAndroid Build Coastguard Worker
1416*6236dae4SAndroid Build Coastguard Worker while(reader) {
1417*6236dae4SAndroid Build Coastguard Worker if(reader->crt->is_paused(data, reader))
1418*6236dae4SAndroid Build Coastguard Worker return TRUE;
1419*6236dae4SAndroid Build Coastguard Worker reader = reader->next;
1420*6236dae4SAndroid Build Coastguard Worker }
1421*6236dae4SAndroid Build Coastguard Worker return FALSE;
1422*6236dae4SAndroid Build Coastguard Worker }
1423*6236dae4SAndroid Build Coastguard Worker
Curl_creader_done(struct Curl_easy * data,int premature)1424*6236dae4SAndroid Build Coastguard Worker void Curl_creader_done(struct Curl_easy *data, int premature)
1425*6236dae4SAndroid Build Coastguard Worker {
1426*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader = data->req.reader_stack;
1427*6236dae4SAndroid Build Coastguard Worker while(reader) {
1428*6236dae4SAndroid Build Coastguard Worker reader->crt->done(data, reader, premature);
1429*6236dae4SAndroid Build Coastguard Worker reader = reader->next;
1430*6236dae4SAndroid Build Coastguard Worker }
1431*6236dae4SAndroid Build Coastguard Worker }
1432*6236dae4SAndroid Build Coastguard Worker
Curl_creader_get_by_type(struct Curl_easy * data,const struct Curl_crtype * crt)1433*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *Curl_creader_get_by_type(struct Curl_easy *data,
1434*6236dae4SAndroid Build Coastguard Worker const struct Curl_crtype *crt)
1435*6236dae4SAndroid Build Coastguard Worker {
1436*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *r;
1437*6236dae4SAndroid Build Coastguard Worker for(r = data->req.reader_stack; r; r = r->next) {
1438*6236dae4SAndroid Build Coastguard Worker if(r->crt == crt)
1439*6236dae4SAndroid Build Coastguard Worker return r;
1440*6236dae4SAndroid Build Coastguard Worker }
1441*6236dae4SAndroid Build Coastguard Worker return NULL;
1442*6236dae4SAndroid Build Coastguard Worker
1443*6236dae4SAndroid Build Coastguard Worker }
1444