113498266Sopenharmony_ci#ifndef HEADER_CURL_HTTP_CHUNKS_H 213498266Sopenharmony_ci#define HEADER_CURL_HTTP_CHUNKS_H 313498266Sopenharmony_ci/*************************************************************************** 413498266Sopenharmony_ci * _ _ ____ _ 513498266Sopenharmony_ci * Project ___| | | | _ \| | 613498266Sopenharmony_ci * / __| | | | |_) | | 713498266Sopenharmony_ci * | (__| |_| | _ <| |___ 813498266Sopenharmony_ci * \___|\___/|_| \_\_____| 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 1113498266Sopenharmony_ci * 1213498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1313498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1413498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1513498266Sopenharmony_ci * 1613498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1713498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1813498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1913498266Sopenharmony_ci * 2013498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 2113498266Sopenharmony_ci * KIND, either express or implied. 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci * SPDX-License-Identifier: curl 2413498266Sopenharmony_ci * 2513498266Sopenharmony_ci ***************************************************************************/ 2613498266Sopenharmony_ci 2713498266Sopenharmony_ci#ifndef CURL_DISABLE_HTTP 2813498266Sopenharmony_ci 2913498266Sopenharmony_ci#include "dynbuf.h" 3013498266Sopenharmony_ci 3113498266Sopenharmony_cistruct connectdata; 3213498266Sopenharmony_ci 3313498266Sopenharmony_ci/* 3413498266Sopenharmony_ci * The longest possible hexadecimal number we support in a chunked transfer. 3513498266Sopenharmony_ci * Neither RFC2616 nor the later HTTP specs define a maximum chunk size. 3613498266Sopenharmony_ci * For 64 bit curl_off_t we support 16 digits. For 32 bit, 8 digits. 3713498266Sopenharmony_ci */ 3813498266Sopenharmony_ci#define CHUNK_MAXNUM_LEN (SIZEOF_CURL_OFF_T * 2) 3913498266Sopenharmony_ci 4013498266Sopenharmony_citypedef enum { 4113498266Sopenharmony_ci /* await and buffer all hexadecimal digits until we get one that isn't a 4213498266Sopenharmony_ci hexadecimal digit. When done, we go CHUNK_LF */ 4313498266Sopenharmony_ci CHUNK_HEX, 4413498266Sopenharmony_ci 4513498266Sopenharmony_ci /* wait for LF, ignore all else */ 4613498266Sopenharmony_ci CHUNK_LF, 4713498266Sopenharmony_ci 4813498266Sopenharmony_ci /* We eat the amount of data specified. When done, we move on to the 4913498266Sopenharmony_ci POST_CR state. */ 5013498266Sopenharmony_ci CHUNK_DATA, 5113498266Sopenharmony_ci 5213498266Sopenharmony_ci /* POSTLF should get a CR and then a LF and nothing else, then move back to 5313498266Sopenharmony_ci HEX as the CRLF combination marks the end of a chunk. A missing CR is no 5413498266Sopenharmony_ci big deal. */ 5513498266Sopenharmony_ci CHUNK_POSTLF, 5613498266Sopenharmony_ci 5713498266Sopenharmony_ci /* Used to mark that we're out of the game. NOTE: that there's a 'datasize' 5813498266Sopenharmony_ci field in the struct that will tell how many bytes that were not passed to 5913498266Sopenharmony_ci the client in the end of the last buffer! */ 6013498266Sopenharmony_ci CHUNK_STOP, 6113498266Sopenharmony_ci 6213498266Sopenharmony_ci /* At this point optional trailer headers can be found, unless the next line 6313498266Sopenharmony_ci is CRLF */ 6413498266Sopenharmony_ci CHUNK_TRAILER, 6513498266Sopenharmony_ci 6613498266Sopenharmony_ci /* A trailer CR has been found - next state is CHUNK_TRAILER_POSTCR. 6713498266Sopenharmony_ci Next char must be a LF */ 6813498266Sopenharmony_ci CHUNK_TRAILER_CR, 6913498266Sopenharmony_ci 7013498266Sopenharmony_ci /* A trailer LF must be found now, otherwise CHUNKE_BAD_CHUNK will be 7113498266Sopenharmony_ci signalled If this is an empty trailer CHUNKE_STOP will be signalled. 7213498266Sopenharmony_ci Otherwise the trailer will be broadcasted via Curl_client_write() and the 7313498266Sopenharmony_ci next state will be CHUNK_TRAILER */ 7413498266Sopenharmony_ci CHUNK_TRAILER_POSTCR, 7513498266Sopenharmony_ci 7613498266Sopenharmony_ci /* Successfully de-chunked everything */ 7713498266Sopenharmony_ci CHUNK_DONE, 7813498266Sopenharmony_ci 7913498266Sopenharmony_ci /* Failed on seeing a bad or not correctly terminated chunk */ 8013498266Sopenharmony_ci CHUNK_FAILED 8113498266Sopenharmony_ci} ChunkyState; 8213498266Sopenharmony_ci 8313498266Sopenharmony_citypedef enum { 8413498266Sopenharmony_ci CHUNKE_OK = 0, 8513498266Sopenharmony_ci CHUNKE_TOO_LONG_HEX = 1, 8613498266Sopenharmony_ci CHUNKE_ILLEGAL_HEX, 8713498266Sopenharmony_ci CHUNKE_BAD_CHUNK, 8813498266Sopenharmony_ci CHUNKE_BAD_ENCODING, 8913498266Sopenharmony_ci CHUNKE_OUT_OF_MEMORY, 9013498266Sopenharmony_ci CHUNKE_PASSTHRU_ERROR /* Curl_httpchunk_read() returns a CURLcode to use */ 9113498266Sopenharmony_ci} CHUNKcode; 9213498266Sopenharmony_ci 9313498266Sopenharmony_cistruct Curl_chunker { 9413498266Sopenharmony_ci curl_off_t datasize; 9513498266Sopenharmony_ci ChunkyState state; 9613498266Sopenharmony_ci CHUNKcode last_code; 9713498266Sopenharmony_ci struct dynbuf trailer; /* for chunked-encoded trailer */ 9813498266Sopenharmony_ci unsigned char hexindex; 9913498266Sopenharmony_ci char hexbuffer[CHUNK_MAXNUM_LEN + 1]; /* +1 for null-terminator */ 10013498266Sopenharmony_ci BIT(ignore_body); /* never write response body data */ 10113498266Sopenharmony_ci}; 10213498266Sopenharmony_ci 10313498266Sopenharmony_ci/* The following functions are defined in http_chunks.c */ 10413498266Sopenharmony_civoid Curl_httpchunk_init(struct Curl_easy *data, struct Curl_chunker *ch, 10513498266Sopenharmony_ci bool ignore_body); 10613498266Sopenharmony_civoid Curl_httpchunk_free(struct Curl_easy *data, struct Curl_chunker *ch); 10713498266Sopenharmony_civoid Curl_httpchunk_reset(struct Curl_easy *data, struct Curl_chunker *ch, 10813498266Sopenharmony_ci bool ignore_body); 10913498266Sopenharmony_ci 11013498266Sopenharmony_ci/* 11113498266Sopenharmony_ci * Read BODY bytes in HTTP/1.1 chunked encoding from `buf` and return 11213498266Sopenharmony_ci * the amount of bytes consumed. The actual response bytes and trailer 11313498266Sopenharmony_ci * headers are written out to the client. 11413498266Sopenharmony_ci * On success, this will consume all bytes up to the end of the response, 11513498266Sopenharmony_ci * e.g. the last chunk, has been processed. 11613498266Sopenharmony_ci * @param data the transfer involved 11713498266Sopenharmony_ci * @param ch the chunker instance keeping state across calls 11813498266Sopenharmony_ci * @param buf the response data 11913498266Sopenharmony_ci * @param blen amount of bytes in `buf` 12013498266Sopenharmony_ci * @param pconsumed on successful return, the number of bytes in `buf` 12113498266Sopenharmony_ci * consumed 12213498266Sopenharmony_ci * 12313498266Sopenharmony_ci * This function always uses ASCII hex values to accommodate non-ASCII hosts. 12413498266Sopenharmony_ci * For example, 0x0d and 0x0a are used instead of '\r' and '\n'. 12513498266Sopenharmony_ci */ 12613498266Sopenharmony_ciCURLcode Curl_httpchunk_read(struct Curl_easy *data, struct Curl_chunker *ch, 12713498266Sopenharmony_ci char *buf, size_t blen, size_t *pconsumed); 12813498266Sopenharmony_ci 12913498266Sopenharmony_ci/** 13013498266Sopenharmony_ci * @return TRUE iff chunked decoded has finished successfully. 13113498266Sopenharmony_ci */ 13213498266Sopenharmony_cibool Curl_httpchunk_is_done(struct Curl_easy *data, struct Curl_chunker *ch); 13313498266Sopenharmony_ci 13413498266Sopenharmony_ciextern const struct Curl_cwtype Curl_httpchunk_unencoder; 13513498266Sopenharmony_ci 13613498266Sopenharmony_ci#endif /* !CURL_DISABLE_HTTP */ 13713498266Sopenharmony_ci 13813498266Sopenharmony_ci#endif /* HEADER_CURL_HTTP_CHUNKS_H */ 139