1#ifndef HEADER_CURL_HTTP_H
2#define HEADER_CURL_HTTP_H
3/***************************************************************************
4 * _ _ ____ _
5 * Project ___| | | | _ \| |
6 * / __| | | | |_) | |
7 * | (__| |_| | _ <| |___
8 * \___|\___/|_| \_\_____|
9 *
10 * Copyright (C) 1998 - 2022, Daniel Stenberg, <[email protected]>, 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#include "curl_setup.h"
27
28typedef enum {
29 HTTPREQ_GET,
30 HTTPREQ_POST,
31 HTTPREQ_POST_FORM, /* we make a difference internally */
32 HTTPREQ_POST_MIME, /* we make a difference internally */
33 HTTPREQ_PUT,
34 HTTPREQ_HEAD
35} Curl_HttpReq;
36
37#ifndef CURL_DISABLE_HTTP
38
39#ifdef USE_NGHTTP2
40#include <nghttp2/nghttp2.h>
41#endif
42
43#if defined(_WIN32) && defined(ENABLE_QUIC)
44#include <stdint.h>
45#endif
46
47extern const struct Curl_handler Curl_handler_http;
48
49#ifdef USE_SSL
50extern const struct Curl_handler Curl_handler_https;
51#endif
52
53/* Header specific functions */
54bool Curl_compareheader(const char *headerline, /* line to check */
55 const char *header, /* header keyword _with_ colon */
56 const size_t hlen, /* len of the keyword in bytes */
57 const char *content, /* content string to find */
58 const size_t clen); /* len of the content in bytes */
59
60char *Curl_copy_header_value(const char *header);
61
62char *Curl_checkProxyheaders(struct Curl_easy *data,
63 const struct connectdata *conn,
64 const char *thisheader,
65 const size_t thislen);
66CURLcode Curl_buffer_send(struct dynbuf *in,
67 struct Curl_easy *data,
68 curl_off_t *bytes_written,
69 curl_off_t included_body_bytes,
70 int socketindex);
71
72CURLcode Curl_add_timecondition(struct Curl_easy *data,
73#ifndef USE_HYPER
74 struct dynbuf *req
75#else
76 void *headers
77#endif
78 );
79CURLcode Curl_add_custom_headers(struct Curl_easy *data,
80 bool is_connect,
81#ifndef USE_HYPER
82 struct dynbuf *req
83#else
84 void *headers
85#endif
86 );
87CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
88 struct dynbuf *buf,
89 struct Curl_easy *handle);
90
91void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
92 const char **method, Curl_HttpReq *);
93CURLcode Curl_http_useragent(struct Curl_easy *data);
94CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn);
95CURLcode Curl_http_target(struct Curl_easy *data, struct connectdata *conn,
96 struct dynbuf *req);
97CURLcode Curl_http_statusline(struct Curl_easy *data,
98 struct connectdata *conn);
99CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
100 char *headp);
101CURLcode Curl_transferencode(struct Curl_easy *data);
102CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
103 Curl_HttpReq httpreq,
104 const char **teep);
105CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
106 struct dynbuf *r, Curl_HttpReq httpreq);
107bool Curl_use_http_1_1plus(const struct Curl_easy *data,
108 const struct connectdata *conn);
109#ifndef CURL_DISABLE_COOKIES
110CURLcode Curl_http_cookies(struct Curl_easy *data,
111 struct connectdata *conn,
112 struct dynbuf *r);
113#else
114#define Curl_http_cookies(a,b,c) CURLE_OK
115#endif
116CURLcode Curl_http_resume(struct Curl_easy *data,
117 struct connectdata *conn,
118 Curl_HttpReq httpreq);
119CURLcode Curl_http_range(struct Curl_easy *data,
120 Curl_HttpReq httpreq);
121CURLcode Curl_http_firstwrite(struct Curl_easy *data,
122 struct connectdata *conn,
123 bool *done);
124
125/* protocol-specific functions set up to be called by the main engine */
126CURLcode Curl_http(struct Curl_easy *data, bool *done);
127CURLcode Curl_http_done(struct Curl_easy *data, CURLcode, bool premature);
128CURLcode Curl_http_connect(struct Curl_easy *data, bool *done);
129
130/* These functions are in http.c */
131CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
132 const char *auth);
133CURLcode Curl_http_auth_act(struct Curl_easy *data);
134
135/* If only the PICKNONE bit is set, there has been a round-trip and we
136 selected to use no auth at all. Ie, we actively select no auth, as opposed
137 to not having one selected. The other CURLAUTH_* defines are present in the
138 public curl/curl.h header. */
139#define CURLAUTH_PICKNONE (1<<30) /* don't use auth */
140
141/* MAX_INITIAL_POST_SIZE indicates the number of bytes that will make the POST
142 data get included in the initial data chunk sent to the server. If the
143 data is larger than this, it will automatically get split up in multiple
144 system calls.
145
146 This value used to be fairly big (100K), but we must take into account that
147 if the server rejects the POST due for authentication reasons, this data
148 will always be unconditionally sent and thus it may not be larger than can
149 always be afforded to send twice.
150
151 It must not be greater than 64K to work on VMS.
152*/
153#ifndef MAX_INITIAL_POST_SIZE
154#define MAX_INITIAL_POST_SIZE (64*1024)
155#endif
156
157/* EXPECT_100_THRESHOLD is the request body size limit for when libcurl will
158 * automatically add an "Expect: 100-continue" header in HTTP requests. When
159 * the size is unknown, it will always add it.
160 *
161 */
162#ifndef EXPECT_100_THRESHOLD
163#define EXPECT_100_THRESHOLD (1024*1024)
164#endif
165
166#endif /* CURL_DISABLE_HTTP */
167
168#ifdef USE_NGHTTP3
169struct h3out; /* see ngtcp2 */
170#endif
171
172#ifdef USE_MSH3
173#ifdef _WIN32
174#define msh3_lock CRITICAL_SECTION
175#define msh3_lock_initialize(lock) InitializeCriticalSection(lock)
176#define msh3_lock_uninitialize(lock) DeleteCriticalSection(lock)
177#define msh3_lock_acquire(lock) EnterCriticalSection(lock)
178#define msh3_lock_release(lock) LeaveCriticalSection(lock)
179#else /* !_WIN32 */
180#include <pthread.h>
181#define msh3_lock pthread_mutex_t
182#define msh3_lock_initialize(lock) { \
183 pthread_mutexattr_t attr; \
184 pthread_mutexattr_init(&attr); \
185 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \
186 pthread_mutex_init(lock, &attr); \
187 pthread_mutexattr_destroy(&attr); \
188}
189#define msh3_lock_uninitialize(lock) pthread_mutex_destroy(lock)
190#define msh3_lock_acquire(lock) pthread_mutex_lock(lock)
191#define msh3_lock_release(lock) pthread_mutex_unlock(lock)
192#endif /* _WIN32 */
193#endif /* USE_MSH3 */
194
195/****************************************************************************
196 * HTTP unique setup
197 ***************************************************************************/
198struct HTTP {
199 curl_mimepart *sendit;
200 curl_off_t postsize; /* off_t to handle large file sizes */
201 const char *postdata;
202
203 const char *p_pragma; /* Pragma: string */
204
205 /* For FORM posting */
206 curl_mimepart form;
207
208 struct back {
209 curl_read_callback fread_func; /* backup storage for fread pointer */
210 void *fread_in; /* backup storage for fread_in pointer */
211 const char *postdata;
212 curl_off_t postsize;
213 } backup;
214
215 enum {
216 HTTPSEND_NADA, /* init */
217 HTTPSEND_REQUEST, /* sending a request */
218 HTTPSEND_BODY /* sending body */
219 } sending;
220
221#ifndef CURL_DISABLE_HTTP
222 struct dynbuf send_buffer; /* used if the request couldn't be sent in one
223 chunk, points to an allocated send_buffer
224 struct */
225#endif
226#ifdef USE_NGHTTP2
227 /*********** for HTTP/2 we store stream-local data here *************/
228 int32_t stream_id; /* stream we are interested in */
229
230 /* We store non-final and final response headers here, per-stream */
231 struct dynbuf header_recvbuf;
232 size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into
233 upper layer */
234 struct dynbuf trailer_recvbuf;
235 const uint8_t *pausedata; /* pointer to data received in on_data_chunk */
236 size_t pauselen; /* the number of bytes left in data */
237 bool close_handled; /* TRUE if stream closure is handled by libcurl */
238
239 char **push_headers; /* allocated array */
240 size_t push_headers_used; /* number of entries filled in */
241 size_t push_headers_alloc; /* number of entries allocated */
242 uint32_t error; /* HTTP/2 stream error code */
243#endif
244#if defined(USE_NGHTTP2) || defined(USE_NGHTTP3)
245 bool bodystarted;
246 int status_code; /* HTTP status code */
247 bool closed; /* TRUE on HTTP2 stream close */
248 char *mem; /* points to a buffer in memory to store received data */
249 size_t len; /* size of the buffer 'mem' points to */
250 size_t memlen; /* size of data copied to mem */
251#endif
252#if defined(USE_NGHTTP2) || defined(ENABLE_QUIC)
253 /* fields used by both HTTP/2 and HTTP/3 */
254 const uint8_t *upload_mem; /* points to a buffer to read from */
255 size_t upload_len; /* size of the buffer 'upload_mem' points to */
256 curl_off_t upload_left; /* number of bytes left to upload */
257#endif
258
259#ifdef ENABLE_QUIC
260#ifndef USE_MSH3
261 /*********** for HTTP/3 we store stream-local data here *************/
262 int64_t stream3_id; /* stream we are interested in */
263 uint64_t error3; /* HTTP/3 stream error code */
264 bool firstheader; /* FALSE until headers arrive */
265 bool firstbody; /* FALSE until body arrives */
266 bool h3req; /* FALSE until request is issued */
267#endif
268 bool upload_done;
269#endif
270#ifdef USE_NGHTTP3
271 size_t unacked_window;
272 struct h3out *h3out; /* per-stream buffers for upload */
273 struct dynbuf overflow; /* excess data received during a single Curl_read */
274#endif
275#ifdef USE_MSH3
276 struct MSH3_REQUEST *req;
277 msh3_lock recv_lock;
278 /* Receive Buffer (Headers and Data) */
279 uint8_t* recv_buf;
280 size_t recv_buf_alloc;
281 /* Receive Headers */
282 size_t recv_header_len;
283 bool recv_header_complete;
284 /* Receive Data */
285 size_t recv_data_len;
286 bool recv_data_complete;
287 /* General Receive Error */
288 CURLcode recv_error;
289#endif
290};
291
292#ifdef USE_NGHTTP2
293/* h2 settings for this connection */
294struct h2settings {
295 uint32_t max_concurrent_streams;
296 bool enable_push;
297};
298#endif
299
300struct http_conn {
301#ifdef USE_NGHTTP2
302#define H2_BINSETTINGS_LEN 80
303 uint8_t binsettings[H2_BINSETTINGS_LEN];
304 size_t binlen; /* length of the binsettings data */
305
306 /* We associate the connnectdata struct with the connection, but we need to
307 make sure we can identify the current "driving" transfer. This is a
308 work-around for the lack of nghttp2_session_set_user_data() in older
309 nghttp2 versions that we want to support. (Added in 1.31.0) */
310 struct Curl_easy *trnsfr;
311
312 nghttp2_session *h2;
313 Curl_send *send_underlying; /* underlying send Curl_send callback */
314 Curl_recv *recv_underlying; /* underlying recv Curl_recv callback */
315 char *inbuf; /* buffer to receive data from underlying socket */
316 size_t inbuflen; /* number of bytes filled in inbuf */
317 size_t nread_inbuf; /* number of bytes read from in inbuf */
318 /* We need separate buffer for transmission and reception because we
319 may call nghttp2_session_send() after the
320 nghttp2_session_mem_recv() but mem buffer is still not full. In
321 this case, we wrongly sends the content of mem buffer if we share
322 them for both cases. */
323 int32_t pause_stream_id; /* stream ID which paused
324 nghttp2_session_mem_recv */
325 size_t drain_total; /* sum of all stream's UrlState.drain */
326
327 /* this is a hash of all individual streams (Curl_easy structs) */
328 struct h2settings settings;
329
330 /* list of settings that will be sent */
331 nghttp2_settings_entry local_settings[3];
332 size_t local_settings_num;
333#else
334 int unused; /* prevent a compiler warning */
335#endif
336};
337
338CURLcode Curl_http_size(struct Curl_easy *data);
339
340CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
341 struct connectdata *conn,
342 ssize_t *nread,
343 bool *stop_reading);
344
345/**
346 * Curl_http_output_auth() setups the authentication headers for the
347 * host/proxy and the correct authentication
348 * method. data->state.authdone is set to TRUE when authentication is
349 * done.
350 *
351 * @param data all information about the current transfer
352 * @param conn all information about the current connection
353 * @param request pointer to the request keyword
354 * @param httpreq is the request type
355 * @param path pointer to the requested path
356 * @param proxytunnel boolean if this is the request setting up a "proxy
357 * tunnel"
358 *
359 * @returns CURLcode
360 */
361CURLcode
362Curl_http_output_auth(struct Curl_easy *data,
363 struct connectdata *conn,
364 const char *request,
365 Curl_HttpReq httpreq,
366 const char *path,
367 bool proxytunnel); /* TRUE if this is the request setting
368 up the proxy tunnel */
369
370/*
371 * Curl_allow_auth_to_host() tells if authentication, cookies or other
372 * "sensitive data" can (still) be sent to this host.
373 */
374bool Curl_allow_auth_to_host(struct Curl_easy *data);
375
376#endif /* HEADER_CURL_HTTP_H */
377