1 | #ifndef HEADER_CURL_SENDF_H
|
---|
2 | #define HEADER_CURL_SENDF_H
|
---|
3 | /***************************************************************************
|
---|
4 | * _ _ ____ _
|
---|
5 | * Project ___| | | | _ \| |
|
---|
6 | * / __| | | | |_) | |
|
---|
7 | * | (__| |_| | _ <| |___
|
---|
8 | * \___|\___/|_| \_\_____|
|
---|
9 | *
|
---|
10 | * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
|
---|
11 | *
|
---|
12 | * This software is licensed as described in the file COPYING, which
|
---|
13 | * you should have received as part of this distribution. The terms
|
---|
14 | * are also available at https://curl.se/docs/copyright.html.
|
---|
15 | *
|
---|
16 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
---|
17 | * copies of the Software, and permit persons to whom the Software is
|
---|
18 | * furnished to do so, under the terms of the COPYING file.
|
---|
19 | *
|
---|
20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
---|
21 | * KIND, either express or implied.
|
---|
22 | *
|
---|
23 | * SPDX-License-Identifier: curl
|
---|
24 | *
|
---|
25 | ***************************************************************************/
|
---|
26 |
|
---|
27 | #include "curl_setup.h"
|
---|
28 |
|
---|
29 | #include "curl_trc.h"
|
---|
30 |
|
---|
31 | /**
|
---|
32 | * Type of data that is being written to the client (application)
|
---|
33 | * - data written can be either BODY or META data
|
---|
34 | * - META data is either INFO or HEADER
|
---|
35 | * - INFO is meta information, e.g. not BODY, that cannot be interpreted
|
---|
36 | * as headers of a response. Example FTP/IMAP pingpong answers.
|
---|
37 | * - HEADER can have additional bits set (more than one)
|
---|
38 | * - STATUS special "header", e.g. response status line in HTTP
|
---|
39 | * - CONNECT header was received during proxying the connection
|
---|
40 | * - 1XX header is part of an intermediate response, e.g. HTTP 1xx code
|
---|
41 | * - TRAILER header is trailing response data, e.g. HTTP trailers
|
---|
42 | * BODY, INFO and HEADER should not be mixed, as this would lead to
|
---|
43 | * confusion on how to interpret/format/convert the data.
|
---|
44 | */
|
---|
45 | #define CLIENTWRITE_BODY (1<<0) /* non-meta information, BODY */
|
---|
46 | #define CLIENTWRITE_INFO (1<<1) /* meta information, not a HEADER */
|
---|
47 | #define CLIENTWRITE_HEADER (1<<2) /* meta information, HEADER */
|
---|
48 | #define CLIENTWRITE_STATUS (1<<3) /* a special status HEADER */
|
---|
49 | #define CLIENTWRITE_CONNECT (1<<4) /* a CONNECT related HEADER */
|
---|
50 | #define CLIENTWRITE_1XX (1<<5) /* a 1xx response related HEADER */
|
---|
51 | #define CLIENTWRITE_TRAILER (1<<6) /* a trailer HEADER */
|
---|
52 | #define CLIENTWRITE_EOS (1<<7) /* End Of transfer download Stream */
|
---|
53 |
|
---|
54 | /**
|
---|
55 | * Write `len` bytes at `prt` to the client. `type` indicates what
|
---|
56 | * kind of data is being written.
|
---|
57 | */
|
---|
58 | CURLcode Curl_client_write(struct Curl_easy *data, int type, const char *ptr,
|
---|
59 | size_t len) WARN_UNUSED_RESULT;
|
---|
60 |
|
---|
61 | /**
|
---|
62 | * Free all resources related to client writing.
|
---|
63 | */
|
---|
64 | void Curl_client_cleanup(struct Curl_easy *data);
|
---|
65 |
|
---|
66 | /**
|
---|
67 | * Reset readers and writer chains, keep rewind information
|
---|
68 | * when necessary.
|
---|
69 | */
|
---|
70 | void Curl_client_reset(struct Curl_easy *data);
|
---|
71 |
|
---|
72 | /**
|
---|
73 | * A new request is starting, perform any ops like rewinding
|
---|
74 | * previous readers when needed.
|
---|
75 | */
|
---|
76 | CURLcode Curl_client_start(struct Curl_easy *data);
|
---|
77 |
|
---|
78 | /**
|
---|
79 | * Client Writers - a chain passing transfer BODY data to the client.
|
---|
80 | * Main application: HTTP and related protocols
|
---|
81 | * Other uses: monitoring of download progress
|
---|
82 | *
|
---|
83 | * Writers in the chain are order by their `phase`. First come all
|
---|
84 | * writers in CURL_CW_RAW, followed by any in CURL_CW_TRANSFER_DECODE,
|
---|
85 | * followed by any in CURL_CW_PROTOCOL, etc.
|
---|
86 | *
|
---|
87 | * When adding a writer, it is inserted as first in its phase. This means
|
---|
88 | * the order of adding writers of the same phase matters, but writers for
|
---|
89 | * different phases may be added in any order.
|
---|
90 | *
|
---|
91 | * Writers which do modify the BODY data written are expected to be of
|
---|
92 | * phases TRANSFER_DECODE or CONTENT_DECODE. The other phases are intended
|
---|
93 | * for monitoring writers. Which do *not* modify the data but gather
|
---|
94 | * statistics or update progress reporting.
|
---|
95 | */
|
---|
96 |
|
---|
97 | /* Phase a writer operates at. */
|
---|
98 | typedef enum {
|
---|
99 | CURL_CW_RAW, /* raw data written, before any decoding */
|
---|
100 | CURL_CW_TRANSFER_DECODE, /* remove transfer-encodings */
|
---|
101 | CURL_CW_PROTOCOL, /* after transfer, but before content decoding */
|
---|
102 | CURL_CW_CONTENT_DECODE, /* remove content-encodings */
|
---|
103 | CURL_CW_CLIENT /* data written to client */
|
---|
104 | } Curl_cwriter_phase;
|
---|
105 |
|
---|
106 | /* Client Writer Type, provides the implementation */
|
---|
107 | struct Curl_cwtype {
|
---|
108 | const char *name; /* writer name. */
|
---|
109 | const char *alias; /* writer name alias, maybe NULL. */
|
---|
110 | CURLcode (*do_init)(struct Curl_easy *data,
|
---|
111 | struct Curl_cwriter *writer);
|
---|
112 | CURLcode (*do_write)(struct Curl_easy *data,
|
---|
113 | struct Curl_cwriter *writer, int type,
|
---|
114 | const char *buf, size_t nbytes);
|
---|
115 | void (*do_close)(struct Curl_easy *data,
|
---|
116 | struct Curl_cwriter *writer);
|
---|
117 | size_t cwriter_size; /* sizeof() allocated struct Curl_cwriter */
|
---|
118 | };
|
---|
119 |
|
---|
120 | /* Client writer instance, allocated on creation.
|
---|
121 | * `void *ctx` is the pointer from the allocation of
|
---|
122 | * the `struct Curl_cwriter` itself. This is suitable for "downcasting"
|
---|
123 | * by the writers implementation. See https://github.com/curl/curl/pull/13054
|
---|
124 | * for the alignment problems that arise otherwise.
|
---|
125 | */
|
---|
126 | struct Curl_cwriter {
|
---|
127 | const struct Curl_cwtype *cwt; /* type implementation */
|
---|
128 | struct Curl_cwriter *next; /* Downstream writer. */
|
---|
129 | void *ctx; /* allocated instance pointer */
|
---|
130 | Curl_cwriter_phase phase; /* phase at which it operates */
|
---|
131 | };
|
---|
132 |
|
---|
133 | /**
|
---|
134 | * Create a new cwriter instance with given type and phase. Is not
|
---|
135 | * inserted into the writer chain by this call.
|
---|
136 | * Invokes `writer->do_init()`.
|
---|
137 | */
|
---|
138 | CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter,
|
---|
139 | struct Curl_easy *data,
|
---|
140 | const struct Curl_cwtype *ce_handler,
|
---|
141 | Curl_cwriter_phase phase);
|
---|
142 |
|
---|
143 | /**
|
---|
144 | * Free a cwriter instance.
|
---|
145 | * Invokes `writer->do_close()`.
|
---|
146 | */
|
---|
147 | void Curl_cwriter_free(struct Curl_easy *data,
|
---|
148 | struct Curl_cwriter *writer);
|
---|
149 |
|
---|
150 | /**
|
---|
151 | * Count the number of writers installed of the given phase.
|
---|
152 | */
|
---|
153 | size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase);
|
---|
154 |
|
---|
155 | /**
|
---|
156 | * Adds a writer to the transfer's writer chain.
|
---|
157 | * The writers `phase` determines where in the chain it is inserted.
|
---|
158 | */
|
---|
159 | CURLcode Curl_cwriter_add(struct Curl_easy *data,
|
---|
160 | struct Curl_cwriter *writer);
|
---|
161 |
|
---|
162 | /**
|
---|
163 | * Look up an installed client writer on `data` by its type.
|
---|
164 | * @return first writer with that type or NULL
|
---|
165 | */
|
---|
166 | struct Curl_cwriter *Curl_cwriter_get_by_type(struct Curl_easy *data,
|
---|
167 | const struct Curl_cwtype *cwt);
|
---|
168 |
|
---|
169 | void Curl_cwriter_remove_by_name(struct Curl_easy *data,
|
---|
170 | const char *name);
|
---|
171 |
|
---|
172 | struct Curl_cwriter *Curl_cwriter_get_by_name(struct Curl_easy *data,
|
---|
173 | const char *name);
|
---|
174 |
|
---|
175 | /**
|
---|
176 | * Convenience method for calling `writer->do_write()` that
|
---|
177 | * checks for NULL writer.
|
---|
178 | */
|
---|
179 | CURLcode Curl_cwriter_write(struct Curl_easy *data,
|
---|
180 | struct Curl_cwriter *writer, int type,
|
---|
181 | const char *buf, size_t nbytes);
|
---|
182 |
|
---|
183 | /**
|
---|
184 | * Default implementations for do_init, do_write, do_close that
|
---|
185 | * do nothing and pass the data through.
|
---|
186 | */
|
---|
187 | CURLcode Curl_cwriter_def_init(struct Curl_easy *data,
|
---|
188 | struct Curl_cwriter *writer);
|
---|
189 | CURLcode Curl_cwriter_def_write(struct Curl_easy *data,
|
---|
190 | struct Curl_cwriter *writer, int type,
|
---|
191 | const char *buf, size_t nbytes);
|
---|
192 | void Curl_cwriter_def_close(struct Curl_easy *data,
|
---|
193 | struct Curl_cwriter *writer);
|
---|
194 |
|
---|
195 |
|
---|
196 |
|
---|
197 | /* Client Reader Type, provides the implementation */
|
---|
198 | struct Curl_crtype {
|
---|
199 | const char *name; /* writer name. */
|
---|
200 | CURLcode (*do_init)(struct Curl_easy *data, struct Curl_creader *reader);
|
---|
201 | CURLcode (*do_read)(struct Curl_easy *data, struct Curl_creader *reader,
|
---|
202 | char *buf, size_t blen, size_t *nread, bool *eos);
|
---|
203 | void (*do_close)(struct Curl_easy *data, struct Curl_creader *reader);
|
---|
204 | bool (*needs_rewind)(struct Curl_easy *data, struct Curl_creader *reader);
|
---|
205 | curl_off_t (*total_length)(struct Curl_easy *data,
|
---|
206 | struct Curl_creader *reader);
|
---|
207 | CURLcode (*resume_from)(struct Curl_easy *data,
|
---|
208 | struct Curl_creader *reader, curl_off_t offset);
|
---|
209 | CURLcode (*rewind)(struct Curl_easy *data, struct Curl_creader *reader);
|
---|
210 | CURLcode (*unpause)(struct Curl_easy *data, struct Curl_creader *reader);
|
---|
211 | void (*done)(struct Curl_easy *data,
|
---|
212 | struct Curl_creader *reader, int premature);
|
---|
213 | size_t creader_size; /* sizeof() allocated struct Curl_creader */
|
---|
214 | };
|
---|
215 |
|
---|
216 | /* Phase a reader operates at. */
|
---|
217 | typedef enum {
|
---|
218 | CURL_CR_NET, /* data send to the network (connection filters) */
|
---|
219 | CURL_CR_TRANSFER_ENCODE, /* add transfer-encodings */
|
---|
220 | CURL_CR_PROTOCOL, /* before transfer, but after content decoding */
|
---|
221 | CURL_CR_CONTENT_ENCODE, /* add content-encodings */
|
---|
222 | CURL_CR_CLIENT /* data read from client */
|
---|
223 | } Curl_creader_phase;
|
---|
224 |
|
---|
225 | /* Client reader instance, allocated on creation.
|
---|
226 | * `void *ctx` is the pointer from the allocation of
|
---|
227 | * the `struct Curl_cwriter` itself. This is suitable for "downcasting"
|
---|
228 | * by the writers implementation. See https://github.com/curl/curl/pull/13054
|
---|
229 | * for the alignment problems that arise otherwise.
|
---|
230 | */
|
---|
231 | struct Curl_creader {
|
---|
232 | const struct Curl_crtype *crt; /* type implementation */
|
---|
233 | struct Curl_creader *next; /* Downstream reader. */
|
---|
234 | void *ctx;
|
---|
235 | Curl_creader_phase phase; /* phase at which it operates */
|
---|
236 | };
|
---|
237 |
|
---|
238 | /**
|
---|
239 | * Default implementations for do_init, do_write, do_close that
|
---|
240 | * do nothing and pass the data through.
|
---|
241 | */
|
---|
242 | CURLcode Curl_creader_def_init(struct Curl_easy *data,
|
---|
243 | struct Curl_creader *reader);
|
---|
244 | void Curl_creader_def_close(struct Curl_easy *data,
|
---|
245 | struct Curl_creader *reader);
|
---|
246 | CURLcode Curl_creader_def_read(struct Curl_easy *data,
|
---|
247 | struct Curl_creader *reader,
|
---|
248 | char *buf, size_t blen,
|
---|
249 | size_t *nread, bool *eos);
|
---|
250 | bool Curl_creader_def_needs_rewind(struct Curl_easy *data,
|
---|
251 | struct Curl_creader *reader);
|
---|
252 | curl_off_t Curl_creader_def_total_length(struct Curl_easy *data,
|
---|
253 | struct Curl_creader *reader);
|
---|
254 | CURLcode Curl_creader_def_resume_from(struct Curl_easy *data,
|
---|
255 | struct Curl_creader *reader,
|
---|
256 | curl_off_t offset);
|
---|
257 | CURLcode Curl_creader_def_rewind(struct Curl_easy *data,
|
---|
258 | struct Curl_creader *reader);
|
---|
259 | CURLcode Curl_creader_def_unpause(struct Curl_easy *data,
|
---|
260 | struct Curl_creader *reader);
|
---|
261 | void Curl_creader_def_done(struct Curl_easy *data,
|
---|
262 | struct Curl_creader *reader, int premature);
|
---|
263 |
|
---|
264 | /**
|
---|
265 | * Convenience method for calling `reader->do_read()` that
|
---|
266 | * checks for NULL reader.
|
---|
267 | */
|
---|
268 | CURLcode Curl_creader_read(struct Curl_easy *data,
|
---|
269 | struct Curl_creader *reader,
|
---|
270 | char *buf, size_t blen, size_t *nread, bool *eos);
|
---|
271 |
|
---|
272 | /**
|
---|
273 | * Create a new creader instance with given type and phase. Is not
|
---|
274 | * inserted into the writer chain by this call.
|
---|
275 | * Invokes `reader->do_init()`.
|
---|
276 | */
|
---|
277 | CURLcode Curl_creader_create(struct Curl_creader **preader,
|
---|
278 | struct Curl_easy *data,
|
---|
279 | const struct Curl_crtype *cr_handler,
|
---|
280 | Curl_creader_phase phase);
|
---|
281 |
|
---|
282 | /**
|
---|
283 | * Free a creader instance.
|
---|
284 | * Invokes `reader->do_close()`.
|
---|
285 | */
|
---|
286 | void Curl_creader_free(struct Curl_easy *data, struct Curl_creader *reader);
|
---|
287 |
|
---|
288 | /**
|
---|
289 | * Adds a reader to the transfer's reader chain.
|
---|
290 | * The readers `phase` determines where in the chain it is inserted.
|
---|
291 | */
|
---|
292 | CURLcode Curl_creader_add(struct Curl_easy *data,
|
---|
293 | struct Curl_creader *reader);
|
---|
294 |
|
---|
295 | /**
|
---|
296 | * Set the given reader, which needs to be of type CURL_CR_CLIENT,
|
---|
297 | * as the new first reader. Discard any installed readers and init
|
---|
298 | * the reader chain anew.
|
---|
299 | * The function takes ownership of `r`.
|
---|
300 | */
|
---|
301 | CURLcode Curl_creader_set(struct Curl_easy *data, struct Curl_creader *r);
|
---|
302 |
|
---|
303 | /**
|
---|
304 | * Read at most `blen` bytes at `buf` from the client.
|
---|
305 | * @param date the transfer to read client bytes for
|
---|
306 | * @param buf the memory location to read to
|
---|
307 | * @param blen the amount of memory at `buf`
|
---|
308 | * @param nread on return the number of bytes read into `buf`
|
---|
309 | * @param eos TRUE iff bytes are the end of data from client
|
---|
310 | * @return CURLE_OK on successful read (even 0 length) or error
|
---|
311 | */
|
---|
312 | CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen,
|
---|
313 | size_t *nread, bool *eos) WARN_UNUSED_RESULT;
|
---|
314 |
|
---|
315 | /**
|
---|
316 | * TRUE iff client reader needs rewing before it can be used for
|
---|
317 | * a retry request.
|
---|
318 | */
|
---|
319 | bool Curl_creader_needs_rewind(struct Curl_easy *data);
|
---|
320 |
|
---|
321 | /**
|
---|
322 | * TRUE iff client reader will rewind at next start
|
---|
323 | */
|
---|
324 | bool Curl_creader_will_rewind(struct Curl_easy *data);
|
---|
325 |
|
---|
326 | /**
|
---|
327 | * En-/disable rewind of client reader at next start.
|
---|
328 | */
|
---|
329 | void Curl_creader_set_rewind(struct Curl_easy *data, bool enable);
|
---|
330 |
|
---|
331 | /**
|
---|
332 | * Get the total length of bytes provided by the installed readers.
|
---|
333 | * This is independent of the amount already delivered and is calculated
|
---|
334 | * by all readers in the stack. If a reader like "chunked" or
|
---|
335 | * "crlf conversion" is installed, the returned length will be -1.
|
---|
336 | * @return -1 if length is indeterminate
|
---|
337 | */
|
---|
338 | curl_off_t Curl_creader_total_length(struct Curl_easy *data);
|
---|
339 |
|
---|
340 | /**
|
---|
341 | * Get the total length of bytes provided by the reader at phase
|
---|
342 | * CURL_CR_CLIENT. This may not match the amount of bytes read
|
---|
343 | * for a request, depending if other, encoding readers are also installed.
|
---|
344 | * However it allows for rough estimation of the overall length.
|
---|
345 | * @return -1 if length is indeterminate
|
---|
346 | */
|
---|
347 | curl_off_t Curl_creader_client_length(struct Curl_easy *data);
|
---|
348 |
|
---|
349 | /**
|
---|
350 | * Ask the installed reader at phase CURL_CR_CLIENT to start
|
---|
351 | * reading from the given offset. On success, this will reduce
|
---|
352 | * the `total_length()` by the amount.
|
---|
353 | * @param date the transfer to read client bytes for
|
---|
354 | * param offset the offset where to start reads from, negative
|
---|
355 | * values will be ignored.
|
---|
356 | * @return CURLE_OK if offset could be set
|
---|
357 | * CURLE_READ_ERROR if not supported by reader or seek/read failed
|
---|
358 | * of offset larger then total length
|
---|
359 | * CURLE_PARTIAL_FILE if offset led to 0 total length
|
---|
360 | */
|
---|
361 | CURLcode Curl_creader_resume_from(struct Curl_easy *data, curl_off_t offset);
|
---|
362 |
|
---|
363 | /**
|
---|
364 | * Unpause all installed readers.
|
---|
365 | */
|
---|
366 | CURLcode Curl_creader_unpause(struct Curl_easy *data);
|
---|
367 |
|
---|
368 | /**
|
---|
369 | * Tell all client readers that they are done.
|
---|
370 | */
|
---|
371 | void Curl_creader_done(struct Curl_easy *data, int premature);
|
---|
372 |
|
---|
373 | /**
|
---|
374 | * Look up an installed client reader on `data` by its type.
|
---|
375 | * @return first reader with that type or NULL
|
---|
376 | */
|
---|
377 | struct Curl_creader *Curl_creader_get_by_type(struct Curl_easy *data,
|
---|
378 | const struct Curl_crtype *crt);
|
---|
379 |
|
---|
380 |
|
---|
381 | /**
|
---|
382 | * Set the client reader to provide 0 bytes, immediate EOS.
|
---|
383 | */
|
---|
384 | CURLcode Curl_creader_set_null(struct Curl_easy *data);
|
---|
385 |
|
---|
386 | /**
|
---|
387 | * Set the client reader the reads from fread callback.
|
---|
388 | */
|
---|
389 | CURLcode Curl_creader_set_fread(struct Curl_easy *data, curl_off_t len);
|
---|
390 |
|
---|
391 | /**
|
---|
392 | * Set the client reader the reads from the supplied buf (NOT COPIED).
|
---|
393 | */
|
---|
394 | CURLcode Curl_creader_set_buf(struct Curl_easy *data,
|
---|
395 | const char *buf, size_t blen);
|
---|
396 |
|
---|
397 | #endif /* HEADER_CURL_SENDF_H */
|
---|