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 * Return TRUE iff client writer is paused. 185 */ 186 bool Curl_cwriter_is_paused(struct Curl_easy *data); 187 188 /** 189 * Unpause client writer and flush any buffered date to the client. 190 */ 191 CURLcode Curl_cwriter_unpause(struct Curl_easy *data); 192 193 /** 194 * Default implementations for do_init, do_write, do_close that 195 * do nothing and pass the data through. 196 */ 197 CURLcode Curl_cwriter_def_init(struct Curl_easy *data, 198 struct Curl_cwriter *writer); 199 CURLcode Curl_cwriter_def_write(struct Curl_easy *data, 200 struct Curl_cwriter *writer, int type, 201 const char *buf, size_t nbytes); 202 void Curl_cwriter_def_close(struct Curl_easy *data, 203 struct Curl_cwriter *writer); 204 205 206 207 /* Client Reader Type, provides the implementation */ 208 struct Curl_crtype { 209 const char *name; /* writer name. */ 210 CURLcode (*do_init)(struct Curl_easy *data, struct Curl_creader *reader); 211 CURLcode (*do_read)(struct Curl_easy *data, struct Curl_creader *reader, 212 char *buf, size_t blen, size_t *nread, bool *eos); 213 void (*do_close)(struct Curl_easy *data, struct Curl_creader *reader); 214 bool (*needs_rewind)(struct Curl_easy *data, struct Curl_creader *reader); 215 curl_off_t (*total_length)(struct Curl_easy *data, 216 struct Curl_creader *reader); 217 CURLcode (*resume_from)(struct Curl_easy *data, 218 struct Curl_creader *reader, curl_off_t offset); 219 CURLcode (*rewind)(struct Curl_easy *data, struct Curl_creader *reader); 220 CURLcode (*unpause)(struct Curl_easy *data, struct Curl_creader *reader); 221 bool (*is_paused)(struct Curl_easy *data, struct Curl_creader *reader); 222 void (*done)(struct Curl_easy *data, 223 struct Curl_creader *reader, int premature); 224 size_t creader_size; /* sizeof() allocated struct Curl_creader */ 225 }; 226 227 /* Phase a reader operates at. */ 228 typedef enum { 229 CURL_CR_NET, /* data send to the network (connection filters) */ 230 CURL_CR_TRANSFER_ENCODE, /* add transfer-encodings */ 231 CURL_CR_PROTOCOL, /* before transfer, but after content decoding */ 232 CURL_CR_CONTENT_ENCODE, /* add content-encodings */ 233 CURL_CR_CLIENT /* data read from client */ 234 } Curl_creader_phase; 235 236 /* Client reader instance, allocated on creation. 237 * `void *ctx` is the pointer from the allocation of 238 * the `struct Curl_cwriter` itself. This is suitable for "downcasting" 239 * by the writers implementation. See https://github.com/curl/curl/pull/13054 240 * for the alignment problems that arise otherwise. 241 */ 242 struct Curl_creader { 243 const struct Curl_crtype *crt; /* type implementation */ 244 struct Curl_creader *next; /* Downstream reader. */ 245 void *ctx; 246 Curl_creader_phase phase; /* phase at which it operates */ 247 }; 248 249 /** 250 * Default implementations for do_init, do_write, do_close that 251 * do nothing and pass the data through. 252 */ 253 CURLcode Curl_creader_def_init(struct Curl_easy *data, 254 struct Curl_creader *reader); 255 void Curl_creader_def_close(struct Curl_easy *data, 256 struct Curl_creader *reader); 257 CURLcode Curl_creader_def_read(struct Curl_easy *data, 258 struct Curl_creader *reader, 259 char *buf, size_t blen, 260 size_t *nread, bool *eos); 261 bool Curl_creader_def_needs_rewind(struct Curl_easy *data, 262 struct Curl_creader *reader); 263 curl_off_t Curl_creader_def_total_length(struct Curl_easy *data, 264 struct Curl_creader *reader); 265 CURLcode Curl_creader_def_resume_from(struct Curl_easy *data, 266 struct Curl_creader *reader, 267 curl_off_t offset); 268 CURLcode Curl_creader_def_rewind(struct Curl_easy *data, 269 struct Curl_creader *reader); 270 CURLcode Curl_creader_def_unpause(struct Curl_easy *data, 271 struct Curl_creader *reader); 272 bool Curl_creader_def_is_paused(struct Curl_easy *data, 273 struct Curl_creader *reader); 274 void Curl_creader_def_done(struct Curl_easy *data, 275 struct Curl_creader *reader, int premature); 276 277 /** 278 * Convenience method for calling `reader->do_read()` that 279 * checks for NULL reader. 280 */ 281 CURLcode Curl_creader_read(struct Curl_easy *data, 282 struct Curl_creader *reader, 283 char *buf, size_t blen, size_t *nread, bool *eos); 284 285 /** 286 * Create a new creader instance with given type and phase. Is not 287 * inserted into the writer chain by this call. 288 * Invokes `reader->do_init()`. 289 */ 290 CURLcode Curl_creader_create(struct Curl_creader **preader, 291 struct Curl_easy *data, 292 const struct Curl_crtype *cr_handler, 293 Curl_creader_phase phase); 294 295 /** 296 * Free a creader instance. 297 * Invokes `reader->do_close()`. 298 */ 299 void Curl_creader_free(struct Curl_easy *data, struct Curl_creader *reader); 300 301 /** 302 * Adds a reader to the transfer's reader chain. 303 * The readers `phase` determines where in the chain it is inserted. 304 */ 305 CURLcode Curl_creader_add(struct Curl_easy *data, 306 struct Curl_creader *reader); 307 308 /** 309 * Set the given reader, which needs to be of type CURL_CR_CLIENT, 310 * as the new first reader. Discard any installed readers and init 311 * the reader chain anew. 312 * The function takes ownership of `r`. 313 */ 314 CURLcode Curl_creader_set(struct Curl_easy *data, struct Curl_creader *r); 315 316 /** 317 * Read at most `blen` bytes at `buf` from the client. 318 * @param data the transfer to read client bytes for 319 * @param buf the memory location to read to 320 * @param blen the amount of memory at `buf` 321 * @param nread on return the number of bytes read into `buf` 322 * @param eos TRUE iff bytes are the end of data from client 323 * @return CURLE_OK on successful read (even 0 length) or error 324 */ 325 CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen, 326 size_t *nread, bool *eos) WARN_UNUSED_RESULT; 327 328 /** 329 * TRUE iff client reader needs rewing before it can be used for 330 * a retry request. 331 */ 332 bool Curl_creader_needs_rewind(struct Curl_easy *data); 333 334 /** 335 * TRUE iff client reader will rewind at next start 336 */ 337 bool Curl_creader_will_rewind(struct Curl_easy *data); 338 339 /** 340 * En-/disable rewind of client reader at next start. 341 */ 342 void Curl_creader_set_rewind(struct Curl_easy *data, bool enable); 343 344 /** 345 * Get the total length of bytes provided by the installed readers. 346 * This is independent of the amount already delivered and is calculated 347 * by all readers in the stack. If a reader like "chunked" or 348 * "crlf conversion" is installed, the returned length will be -1. 349 * @return -1 if length is indeterminate 350 */ 351 curl_off_t Curl_creader_total_length(struct Curl_easy *data); 352 353 /** 354 * Get the total length of bytes provided by the reader at phase 355 * CURL_CR_CLIENT. This may not match the amount of bytes read 356 * for a request, depending if other, encoding readers are also installed. 357 * However it allows for rough estimation of the overall length. 358 * @return -1 if length is indeterminate 359 */ 360 curl_off_t Curl_creader_client_length(struct Curl_easy *data); 361 362 /** 363 * Ask the installed reader at phase CURL_CR_CLIENT to start 364 * reading from the given offset. On success, this will reduce 365 * the `total_length()` by the amount. 366 * @param data the transfer to read client bytes for 367 * @param offset the offset where to start reads from, negative 368 * values will be ignored. 369 * @return CURLE_OK if offset could be set 370 * CURLE_READ_ERROR if not supported by reader or seek/read failed 371 * of offset larger then total length 372 * CURLE_PARTIAL_FILE if offset led to 0 total length 373 */ 374 CURLcode Curl_creader_resume_from(struct Curl_easy *data, curl_off_t offset); 375 376 /** 377 * Unpause all installed readers. 378 */ 379 CURLcode Curl_creader_unpause(struct Curl_easy *data); 380 381 /** 382 * Return TRUE iff any of the installed readers is paused. 383 */ 384 bool Curl_creader_is_paused(struct Curl_easy *data); 385 386 /** 387 * Tell all client readers that they are done. 388 */ 389 void Curl_creader_done(struct Curl_easy *data, int premature); 390 391 /** 392 * Look up an installed client reader on `data` by its type. 393 * @return first reader with that type or NULL 394 */ 395 struct Curl_creader *Curl_creader_get_by_type(struct Curl_easy *data, 396 const struct Curl_crtype *crt); 397 398 399 /** 400 * Set the client reader to provide 0 bytes, immediate EOS. 401 */ 402 CURLcode Curl_creader_set_null(struct Curl_easy *data); 403 404 /** 405 * Set the client reader the reads from fread callback. 406 */ 407 CURLcode Curl_creader_set_fread(struct Curl_easy *data, curl_off_t len); 408 409 /** 410 * Set the client reader the reads from the supplied buf (NOT COPIED). 411 */ 412 CURLcode Curl_creader_set_buf(struct Curl_easy *data, 413 const char *buf, size_t blen); 414 415 #endif /* HEADER_CURL_SENDF_H */ 416