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 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 void (*done)(struct Curl_easy *data, 222 struct Curl_creader *reader, int premature); 223 size_t creader_size; /* sizeof() allocated struct Curl_creader */ 224 }; 225 226 /* Phase a reader operates at. */ 227 typedef enum { 228 CURL_CR_NET, /* data send to the network (connection filters) */ 229 CURL_CR_TRANSFER_ENCODE, /* add transfer-encodings */ 230 CURL_CR_PROTOCOL, /* before transfer, but after content decoding */ 231 CURL_CR_CONTENT_ENCODE, /* add content-encodings */ 232 CURL_CR_CLIENT /* data read from client */ 233 } Curl_creader_phase; 234 235 /* Client reader instance, allocated on creation. 236 * `void *ctx` is the pointer from the allocation of 237 * the `struct Curl_cwriter` itself. This is suitable for "downcasting" 238 * by the writers implementation. See https://github.com/curl/curl/pull/13054 239 * for the alignment problems that arise otherwise. 240 */ 241 struct Curl_creader { 242 const struct Curl_crtype *crt; /* type implementation */ 243 struct Curl_creader *next; /* Downstream reader. */ 244 void *ctx; 245 Curl_creader_phase phase; /* phase at which it operates */ 246 }; 247 248 /** 249 * Default implementations for do_init, do_write, do_close that 250 * do nothing and pass the data through. 251 */ 252 CURLcode Curl_creader_def_init(struct Curl_easy *data, 253 struct Curl_creader *reader); 254 void Curl_creader_def_close(struct Curl_easy *data, 255 struct Curl_creader *reader); 256 CURLcode Curl_creader_def_read(struct Curl_easy *data, 257 struct Curl_creader *reader, 258 char *buf, size_t blen, 259 size_t *nread, bool *eos); 260 bool Curl_creader_def_needs_rewind(struct Curl_easy *data, 261 struct Curl_creader *reader); 262 curl_off_t Curl_creader_def_total_length(struct Curl_easy *data, 263 struct Curl_creader *reader); 264 CURLcode Curl_creader_def_resume_from(struct Curl_easy *data, 265 struct Curl_creader *reader, 266 curl_off_t offset); 267 CURLcode Curl_creader_def_rewind(struct Curl_easy *data, 268 struct Curl_creader *reader); 269 CURLcode Curl_creader_def_unpause(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 * Tell all client readers that they are done. 380 */ 381 void Curl_creader_done(struct Curl_easy *data, int premature); 382 383 /** 384 * Look up an installed client reader on `data` by its type. 385 * @return first reader with that type or NULL 386 */ 387 struct Curl_creader *Curl_creader_get_by_type(struct Curl_easy *data, 388 const struct Curl_crtype *crt); 389 390 391 /** 392 * Set the client reader to provide 0 bytes, immediate EOS. 393 */ 394 CURLcode Curl_creader_set_null(struct Curl_easy *data); 395 396 /** 397 * Set the client reader the reads from fread callback. 398 */ 399 CURLcode Curl_creader_set_fread(struct Curl_easy *data, curl_off_t len); 400 401 /** 402 * Set the client reader the reads from the supplied buf (NOT COPIED). 403 */ 404 CURLcode Curl_creader_set_buf(struct Curl_easy *data, 405 const char *buf, size_t blen); 406 407 #endif /* HEADER_CURL_SENDF_H */ 408