sendf.h (16241B)
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 bool Curl_cwriter_is_content_decoding(struct Curl_easy *data); 186 187 /** 188 * Unpause client writer and flush any buffered date to the client. 189 */ 190 CURLcode Curl_cwriter_unpause(struct Curl_easy *data); 191 192 /** 193 * Default implementations for do_init, do_write, do_close that 194 * do nothing and pass the data through. 195 */ 196 CURLcode Curl_cwriter_def_init(struct Curl_easy *data, 197 struct Curl_cwriter *writer); 198 CURLcode Curl_cwriter_def_write(struct Curl_easy *data, 199 struct Curl_cwriter *writer, int type, 200 const char *buf, size_t nbytes); 201 void Curl_cwriter_def_close(struct Curl_easy *data, 202 struct Curl_cwriter *writer); 203 204 205 206 /* Client Reader Type, provides the implementation */ 207 struct Curl_crtype { 208 const char *name; /* writer name. */ 209 CURLcode (*do_init)(struct Curl_easy *data, struct Curl_creader *reader); 210 CURLcode (*do_read)(struct Curl_easy *data, struct Curl_creader *reader, 211 char *buf, size_t blen, size_t *nread, bool *eos); 212 void (*do_close)(struct Curl_easy *data, struct Curl_creader *reader); 213 bool (*needs_rewind)(struct Curl_easy *data, struct Curl_creader *reader); 214 curl_off_t (*total_length)(struct Curl_easy *data, 215 struct Curl_creader *reader); 216 CURLcode (*resume_from)(struct Curl_easy *data, 217 struct Curl_creader *reader, curl_off_t offset); 218 CURLcode (*rewind)(struct Curl_easy *data, struct Curl_creader *reader); 219 CURLcode (*unpause)(struct Curl_easy *data, struct Curl_creader *reader); 220 bool (*is_paused)(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 bool Curl_creader_def_is_paused(struct Curl_easy *data, 272 struct Curl_creader *reader); 273 void Curl_creader_def_done(struct Curl_easy *data, 274 struct Curl_creader *reader, int premature); 275 276 /** 277 * Convenience method for calling `reader->do_read()` that 278 * checks for NULL reader. 279 */ 280 CURLcode Curl_creader_read(struct Curl_easy *data, 281 struct Curl_creader *reader, 282 char *buf, size_t blen, size_t *nread, bool *eos); 283 284 /** 285 * Create a new creader instance with given type and phase. Is not 286 * inserted into the writer chain by this call. 287 * Invokes `reader->do_init()`. 288 */ 289 CURLcode Curl_creader_create(struct Curl_creader **preader, 290 struct Curl_easy *data, 291 const struct Curl_crtype *cr_handler, 292 Curl_creader_phase phase); 293 294 /** 295 * Free a creader instance. 296 * Invokes `reader->do_close()`. 297 */ 298 void Curl_creader_free(struct Curl_easy *data, struct Curl_creader *reader); 299 300 /** 301 * Adds a reader to the transfer's reader chain. 302 * The readers `phase` determines where in the chain it is inserted. 303 */ 304 CURLcode Curl_creader_add(struct Curl_easy *data, 305 struct Curl_creader *reader); 306 307 /** 308 * Set the given reader, which needs to be of type CURL_CR_CLIENT, 309 * as the new first reader. Discard any installed readers and init 310 * the reader chain anew. 311 * The function takes ownership of `r`. 312 */ 313 CURLcode Curl_creader_set(struct Curl_easy *data, struct Curl_creader *r); 314 315 /** 316 * Read at most `blen` bytes at `buf` from the client. 317 * @param data the transfer to read client bytes for 318 * @param buf the memory location to read to 319 * @param blen the amount of memory at `buf` 320 * @param nread on return the number of bytes read into `buf` 321 * @param eos TRUE iff bytes are the end of data from client 322 * @return CURLE_OK on successful read (even 0 length) or error 323 */ 324 CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen, 325 size_t *nread, bool *eos) WARN_UNUSED_RESULT; 326 327 /** 328 * TRUE iff client reader needs rewing before it can be used for 329 * a retry request. 330 */ 331 bool Curl_creader_needs_rewind(struct Curl_easy *data); 332 333 /** 334 * TRUE iff client reader will rewind at next start 335 */ 336 bool Curl_creader_will_rewind(struct Curl_easy *data); 337 338 /** 339 * En-/disable rewind of client reader at next start. 340 */ 341 void Curl_creader_set_rewind(struct Curl_easy *data, bool enable); 342 343 /** 344 * Get the total length of bytes provided by the installed readers. 345 * This is independent of the amount already delivered and is calculated 346 * by all readers in the stack. If a reader like "chunked" or 347 * "crlf conversion" is installed, the returned length will be -1. 348 * @return -1 if length is indeterminate 349 */ 350 curl_off_t Curl_creader_total_length(struct Curl_easy *data); 351 352 /** 353 * Get the total length of bytes provided by the reader at phase 354 * CURL_CR_CLIENT. This may not match the amount of bytes read 355 * for a request, depending if other, encoding readers are also installed. 356 * However it allows for rough estimation of the overall length. 357 * @return -1 if length is indeterminate 358 */ 359 curl_off_t Curl_creader_client_length(struct Curl_easy *data); 360 361 /** 362 * Ask the installed reader at phase CURL_CR_CLIENT to start 363 * reading from the given offset. On success, this will reduce 364 * the `total_length()` by the amount. 365 * @param data the transfer to read client bytes for 366 * @param offset the offset where to start reads from, negative 367 * values will be ignored. 368 * @return CURLE_OK if offset could be set 369 * CURLE_READ_ERROR if not supported by reader or seek/read failed 370 * of offset larger then total length 371 * CURLE_PARTIAL_FILE if offset led to 0 total length 372 */ 373 CURLcode Curl_creader_resume_from(struct Curl_easy *data, curl_off_t offset); 374 375 /** 376 * Unpause all installed readers. 377 */ 378 CURLcode Curl_creader_unpause(struct Curl_easy *data); 379 380 /** 381 * Return TRUE iff any of the installed readers is paused. 382 */ 383 bool Curl_creader_is_paused(struct Curl_easy *data); 384 385 /** 386 * Tell all client readers that they are done. 387 */ 388 void Curl_creader_done(struct Curl_easy *data, int premature); 389 390 /** 391 * Look up an installed client reader on `data` by its type. 392 * @return first reader with that type or NULL 393 */ 394 struct Curl_creader *Curl_creader_get_by_type(struct Curl_easy *data, 395 const struct Curl_crtype *crt); 396 397 398 /** 399 * Set the client reader to provide 0 bytes, immediate EOS. 400 */ 401 CURLcode Curl_creader_set_null(struct Curl_easy *data); 402 403 /** 404 * Set the client reader the reads from fread callback. 405 */ 406 CURLcode Curl_creader_set_fread(struct Curl_easy *data, curl_off_t len); 407 408 /** 409 * Set the client reader the reads from the supplied buf (NOT COPIED). 410 */ 411 CURLcode Curl_creader_set_buf(struct Curl_easy *data, 412 const char *buf, size_t blen); 413 414 #endif /* HEADER_CURL_SENDF_H */