1 #ifndef HEADER_CURL_REQUEST_H 2 #define HEADER_CURL_REQUEST_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 /* This file is for lib internal stuff */ 28 29 #include "curl_setup.h" 30 31 #include "bufq.h" 32 33 /* forward declarations */ 34 struct UserDefined; 35 36 enum expect100 { 37 EXP100_SEND_DATA, /* enough waiting, just send the body now */ 38 EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */ 39 EXP100_SENDING_REQUEST, /* still sending the request but will wait for 40 the 100 header once done with the request */ 41 EXP100_FAILED /* used on 417 Expectation Failed */ 42 }; 43 44 enum upgrade101 { 45 UPGR101_INIT, /* default state */ 46 UPGR101_WS, /* upgrade to WebSockets requested */ 47 UPGR101_H2, /* upgrade to HTTP/2 requested */ 48 UPGR101_RECEIVED, /* 101 response received */ 49 UPGR101_WORKING /* talking upgraded protocol */ 50 }; 51 52 53 /* 54 * Request specific data in the easy handle (Curl_easy). Previously, 55 * these members were on the connectdata struct but since a conn struct may 56 * now be shared between different Curl_easys, we store connection-specific 57 * data here. This struct only keeps stuff that's interesting for *this* 58 * request, as it will be cleared between multiple ones 59 */ 60 struct SingleRequest { 61 curl_off_t size; /* -1 if unknown at this point */ 62 curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch, 63 -1 means unlimited */ 64 curl_off_t bytecount; /* total number of bytes read */ 65 curl_off_t writebytecount; /* number of bytes written */ 66 67 struct curltime start; /* transfer started at this time */ 68 unsigned int headerbytecount; /* received server headers (not CONNECT 69 headers) */ 70 unsigned int allheadercount; /* all received headers (server + CONNECT) */ 71 unsigned int deductheadercount; /* this amount of bytes doesn't count when 72 we check if anything has been transferred 73 at the end of a connection. We use this 74 counter to make only a 100 reply (without 75 a following second response code) result 76 in a CURLE_GOT_NOTHING error code */ 77 int headerline; /* counts header lines to better track the 78 first one */ 79 curl_off_t offset; /* possible resume offset read from the 80 Content-Range: header */ 81 int httpversion; /* Version in response (09, 10, 11, etc.) */ 82 int httpcode; /* error code from the 'HTTP/1.? XXX' or 83 'RTSP/1.? XXX' line */ 84 int keepon; 85 enum upgrade101 upgr101; /* 101 upgrade state */ 86 87 /* Client Writer stack, handles transfer- and content-encodings, protocol 88 * checks, pausing by client callbacks. */ 89 struct Curl_cwriter *writer_stack; 90 /* Client Reader stack, handles transfer- and content-encodings, protocol 91 * checks, pausing by client callbacks. */ 92 struct Curl_creader *reader_stack; 93 struct bufq sendbuf; /* data which needs to be send to the server */ 94 size_t sendbuf_hds_len; /* amount of header bytes in sendbuf */ 95 time_t timeofdoc; 96 long bodywrites; 97 char *location; /* This points to an allocated version of the Location: 98 header data */ 99 char *newurl; /* Set to the new URL to use when a redirect or a retry is 100 wanted */ 101 102 /* Allocated protocol-specific data. Each protocol handler makes sure this 103 points to data it needs. */ 104 union { 105 struct FILEPROTO *file; 106 struct FTP *ftp; 107 struct HTTP *http; 108 struct IMAP *imap; 109 struct ldapreqinfo *ldap; 110 struct MQTT *mqtt; 111 struct POP3 *pop3; 112 struct RTSP *rtsp; 113 struct smb_request *smb; 114 struct SMTP *smtp; 115 struct SSHPROTO *ssh; 116 struct TELNET *telnet; 117 } p; 118 #ifndef CURL_DISABLE_DOH 119 struct dohdata *doh; /* DoH specific data for this request */ 120 #endif 121 #ifndef CURL_DISABLE_COOKIES 122 unsigned char setcookies; 123 #endif 124 BIT(header); /* incoming data has HTTP header */ 125 BIT(done); /* request is done, e.g. no more send/recv should 126 * happen. This can be TRUE before `upload_done` or 127 * `download_done` is TRUE. */ 128 BIT(content_range); /* set TRUE if Content-Range: was found */ 129 BIT(download_done); /* set to TRUE when download is complete */ 130 BIT(eos_written); /* iff EOS has been written to client */ 131 BIT(eos_read); /* iff EOS has been read from the client */ 132 BIT(rewind_read); /* iff reader needs rewind at next start */ 133 BIT(upload_done); /* set to TRUE when all request data has been sent */ 134 BIT(upload_aborted); /* set to TRUE when upload was aborted. Will also 135 * show `upload_done` as TRUE. */ 136 BIT(ignorebody); /* we read a response-body but we ignore it! */ 137 BIT(http_bodyless); /* HTTP response status code is between 100 and 199, 138 204 or 304 */ 139 BIT(chunk); /* if set, this is a chunked transfer-encoding */ 140 BIT(ignore_cl); /* ignore content-length */ 141 BIT(upload_chunky); /* set TRUE if we are doing chunked transfer-encoding 142 on upload */ 143 BIT(getheader); /* TRUE if header parsing is wanted */ 144 BIT(no_body); /* the response has no body */ 145 BIT(authneg); /* TRUE when the auth phase has started, which means 146 that we are creating a request with an auth header, 147 but it is not the final request in the auth 148 negotiation. */ 149 BIT(sendbuf_init); /* sendbuf is initialized */ 150 }; 151 152 /** 153 * Initialize the state of the request for first use. 154 */ 155 void Curl_req_init(struct SingleRequest *req); 156 157 /** 158 * The request is about to start. Record time and do a soft reset. 159 */ 160 CURLcode Curl_req_start(struct SingleRequest *req, 161 struct Curl_easy *data); 162 163 /** 164 * The request may continue with a follow up. Reset 165 * members, but keep start time for overall duration calc. 166 */ 167 CURLcode Curl_req_soft_reset(struct SingleRequest *req, 168 struct Curl_easy *data); 169 170 /** 171 * The request is done. If not aborted, make sure that buffers are 172 * flushed to the client. 173 * @param req the request 174 * @param data the transfer 175 * @param aborted TRUE iff the request was aborted/errored 176 */ 177 CURLcode Curl_req_done(struct SingleRequest *req, 178 struct Curl_easy *data, bool aborted); 179 180 /** 181 * Free the state of the request, not usable afterwards. 182 */ 183 void Curl_req_free(struct SingleRequest *req, struct Curl_easy *data); 184 185 /** 186 * Hard reset the state of the request to virgin state base on 187 * transfer settings. 188 */ 189 void Curl_req_hard_reset(struct SingleRequest *req, struct Curl_easy *data); 190 191 #ifndef USE_HYPER 192 /** 193 * Send request headers. If not all could be sent 194 * they will be buffered. Use `Curl_req_flush()` to make sure 195 * bytes are really send. 196 * @param data the transfer making the request 197 * @param buf the complete header bytes, no body 198 * @return CURLE_OK (on blocking with *pnwritten == 0) or error. 199 */ 200 CURLcode Curl_req_send(struct Curl_easy *data, struct dynbuf *buf); 201 202 #endif /* !USE_HYPER */ 203 204 /** 205 * TRUE iff the request has sent all request headers and data. 206 */ 207 bool Curl_req_done_sending(struct Curl_easy *data); 208 209 /* 210 * Read more from client and flush all buffered request bytes. 211 * @return CURLE_OK on success or the error on the sending. 212 * Never returns CURLE_AGAIN. 213 */ 214 CURLcode Curl_req_send_more(struct Curl_easy *data); 215 216 /** 217 * TRUE iff the request wants to send, e.g. has buffered bytes. 218 */ 219 bool Curl_req_want_send(struct Curl_easy *data); 220 221 /** 222 * Stop sending any more request data to the server. 223 * Will clear the send buffer and mark request sending as done. 224 */ 225 CURLcode Curl_req_abort_sending(struct Curl_easy *data); 226 227 #endif /* HEADER_CURL_REQUEST_H */ 228