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