xref: /curl/lib/sendf.c (revision 31d7cf42)
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