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