Coverage Report

Created: 2026-09-01 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl/lib/request.h
Line
Count
Source
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
/* This file is for lib internal stuff */
27
#include "curl_setup.h"
28
29
#include "bufq.h"
30
31
/* forward declarations */
32
struct UserDefined;
33
34
/* Bits on the io_flags member of SingleRequest */
35
16.6k
#define REQ_IO_RECV       (1 << 0) /* there is or may be data to read */
36
15.1k
#define REQ_IO_SEND       (1 << 1) /* there is or may be data to write */
37
38
/* Low level request receive/send io_flags checks. */
39
15.5k
#define CURL_REQ_WANT_SEND(d)  ((d)->req.io_flags & REQ_IO_SEND)
40
12.3k
#define CURL_REQ_WANT_RECV(d)  ((d)->req.io_flags & REQ_IO_RECV)
41
#define CURL_REQ_WANT_IO(d)    \
42
3.62k
  ((d)->req.io_flags & (REQ_IO_RECV | REQ_IO_SEND))
43
/* Low level request receive/send io_flags manipulations. */
44
0
#define CURL_REQ_SET_SEND(d)   ((d)->req.io_flags |= REQ_IO_SEND)
45
1.55k
#define CURL_REQ_SET_RECV(d)   ((d)->req.io_flags |= REQ_IO_RECV)
46
#define CURL_REQ_CLEAR_SEND(d) \
47
0
  ((d)->req.io_flags &= (uint8_t)~REQ_IO_SEND)
48
#define CURL_REQ_CLEAR_RECV(d) \
49
1.48k
  ((d)->req.io_flags &= (uint8_t)~REQ_IO_RECV)
50
#define CURL_REQ_CLEAR_IO(d)  \
51
1.48k
  ((d)->req.io_flags &= (uint8_t)~(REQ_IO_RECV | REQ_IO_SEND))
52
53
enum expect100 {
54
  EXP100_SEND_DATA,           /* enough waiting, send the body now */
55
  EXP100_AWAITING_CONTINUE,   /* waiting for the 100 Continue header */
56
  EXP100_SENDING_REQUEST,     /* still sending the request but will wait for
57
                                 the 100 header once done with the request */
58
  EXP100_FAILED               /* used on 417 Expectation Failed */
59
};
60
61
enum upgrade101 {
62
  UPGR101_NONE,               /* default state */
63
  UPGR101_WS,                 /* upgrade to WebSocket requested */
64
  UPGR101_H2,                 /* upgrade to HTTP/2 requested */
65
  UPGR101_RECEIVED            /* 101 response received */
66
};
67
68
/*
69
 * Request specific data in the easy handle (Curl_easy). Previously,
70
 * these members were on the connectdata struct but since a conn struct may
71
 * now be shared between different Curl_easys, we store connection-specific
72
 * data here. This struct only keeps stuff that is interesting for *this*
73
 * request, as it will be cleared between multiple ones
74
 */
75
struct SingleRequest {
76
  curl_off_t size;        /* -1 if unknown at this point */
77
  curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch,
78
                             -1 means unlimited */
79
  curl_off_t bytecount;         /* total number of bytes read */
80
  curl_off_t writebytecount;    /* number of bytes written */
81
  curl_off_t offset;            /* possible resume offset read from the
82
                                   Content-Range: header */
83
84
  struct curltime start;         /* transfer started at this time */
85
  unsigned int headerbytecount;  /* received server headers (not CONNECT
86
                                    headers) */
87
  unsigned int allheadercount;   /* all received headers (server + CONNECT) */
88
  unsigned int deductheadercount; /* this amount of bytes does not count when
89
                                     we check if anything has been transferred
90
                                     at the end of a connection. We use this
91
                                     counter to make only a 100 reply (without
92
                                     a following second response code) result
93
                                     in a CURLE_GOT_NOTHING error code */
94
  int headerline;               /* counts header lines to better track the
95
                                   first one */
96
  int httpcode;                 /* error code from the 'HTTP/1.? XXX' or
97
                                   'RTSP/1.? XXX' line */
98
  uint8_t httpversion_sent;     /* Version in request (09, 10, 11, etc.) */
99
  uint8_t httpversion;          /* Version in response (09, 10, 11, etc.) */
100
  uint8_t upgr101;              /* 101 upgrade state */
101
  uint8_t io_flags;             /* REQ_IO_RECV | REQ_IO_SEND */
102
103
  /* Client Writer stack, handles transfer- and content-encodings, protocol
104
   * checks, pausing by client callbacks. */
105
  struct {
106
    struct Curl_cwriter *stack;
107
    BIT(paused);
108
  } writer;
109
  /* Client Reader stack, handles transfer- and content-encodings, protocol
110
   * checks, pausing by client callbacks. */
111
  struct {
112
    struct Curl_creader *stack;
113
  } reader;
114
  struct bufq sendbuf; /* data which needs to be send to the server */
115
  size_t sendbuf_hds_len; /* amount of header bytes in sendbuf */
116
  time_t timeofdoc;
117
  char *location;   /* This points to an allocated version of the Location:
118
                       header data */
119
  char *newurl;     /* Set to the new URL to use when a redirect or a retry is
120
                       wanted */
121
122
  char *hd_auth;      /* Authorization header, full HTTP/1.x line */
123
#ifndef CURL_DISABLE_PROXY
124
  char *hd_proxy_auth; /* Proxy-Authorization header, full HTTP/1.x line */
125
#endif
126
#ifndef CURL_DISABLE_COOKIES
127
  char *cookiehost;
128
#endif
129
#ifndef CURL_DISABLE_COOKIES
130
  unsigned char setcookies;
131
#endif
132
  BIT(header);        /* incoming data has HTTP header */
133
  BIT(done);          /* request is done, e.g. no more send/recv should
134
                       * happen. This can be TRUE before `upload_done` or
135
                       * `download_done` is TRUE. */
136
  BIT(content_range); /* set TRUE if Content-Range: was found */
137
  BIT(download_done); /* set to TRUE when download is complete */
138
  BIT(eos_written);   /* iff EOS has been written to client */
139
  BIT(eos_read);      /* iff EOS has been read from the client */
140
  BIT(eos_sent);      /* iff EOS has been sent to the server */
141
  BIT(rewind_read);   /* iff reader needs rewind at next start */
142
  BIT(upload_done);   /* set to TRUE when all request data has been sent */
143
  BIT(upload_aborted); /* set to TRUE when upload was aborted. Also
144
                        * shows `upload_done` as TRUE. */
145
  BIT(ignorebody);    /* we read a response-body but we ignore it! */
146
  BIT(http_bodyless); /* HTTP response status code is between 100 and 199,
147
                         204 or 304 */
148
  BIT(chunk);         /* if set, this is a chunked transfer-encoding */
149
  BIT(resp_trailer);  /* response carried 'Trailer:' header field */
150
  BIT(ignore_cl);     /* ignore content-length */
151
  BIT(upload_chunky); /* set TRUE if we are doing chunked transfer-encoding
152
                         on upload */
153
  BIT(no_body);      /* the response has no body */
154
  BIT(authneg);      /* TRUE when the auth phase has started, which means
155
                        that we are creating a request with an auth header,
156
                        but it is not the final request in the auth
157
                        negotiation. */
158
  BIT(sendbuf_init); /* sendbuf is initialized */
159
  BIT(shutdown);     /* request end will shutdown connection */
160
  BIT(shutdown_err_ignore); /* errors in shutdown will not fail request */
161
  BIT(reader_started); /* client reads have started */
162
};
163
164
/**
165
 * Initialize the state of the request for first use.
166
 */
167
void Curl_req_init(struct SingleRequest *req);
168
169
/**
170
 * The request is about to start. Record time and do a soft reset.
171
 */
172
CURLcode Curl_req_start(struct SingleRequest *req,
173
                        struct Curl_easy *data);
174
175
/**
176
 * The request may continue with a follow up. Reset
177
 * members, but keep start time for overall duration calc.
178
 */
179
CURLcode Curl_req_soft_reset(struct SingleRequest *req,
180
                             struct Curl_easy *data);
181
182
/**
183
 * The request is done. If not aborted, make sure that buffers are
184
 * flushed to the client.
185
 * @param req        the request
186
 * @param data       the transfer
187
 * @param aborted    TRUE iff the request was aborted/errored
188
 */
189
CURLcode Curl_req_done(struct SingleRequest *req,
190
                       struct Curl_easy *data, bool aborted);
191
192
/**
193
 * Free the state of the request, not usable afterwards.
194
 */
195
void Curl_req_free(struct SingleRequest *req, struct Curl_easy *data);
196
197
/**
198
 * Hard reset the state of the request to virgin state base on
199
 * transfer settings.
200
 */
201
void Curl_req_hard_reset(struct SingleRequest *req, struct Curl_easy *data);
202
203
/**
204
 * Send request headers. If not all could be sent
205
 * they will be buffered. Use `Curl_req_flush()` to make sure
206
 * bytes are really send.
207
 * @param data      the transfer making the request
208
 * @param req       the complete header bytes, no body
209
 * @param httpversion version used in request (09, 10, 11, etc.)
210
 * @return CURLE_OK (on blocking with *pnwritten == 0) or error.
211
 */
212
CURLcode Curl_req_send(struct Curl_easy *data, struct dynbuf *req,
213
                       unsigned char httpversion);
214
215
/**
216
 * TRUE iff the request has sent all request headers and data.
217
 */
218
bool Curl_req_done_sending(struct Curl_easy *data);
219
220
/*
221
 * Read more from client and flush all buffered request bytes.
222
 * @return CURLE_OK on success or the error on the sending.
223
 *         Never returns CURLE_AGAIN.
224
 */
225
CURLcode Curl_req_send_more(struct Curl_easy *data);
226
227
/* TRUE if the request wants to send, e.g. is not done sending
228
 * and is not blocked. */
229
bool Curl_req_want_send(struct Curl_easy *data);
230
231
/* TRUE if the request wants to receive and is not blocked. */
232
bool Curl_req_want_recv(struct Curl_easy *data);
233
234
/**
235
 * TRUE iff the request has no buffered bytes yet to send.
236
 */
237
bool Curl_req_sendbuf_empty(struct Curl_easy *data);
238
239
/**
240
 * Stop sending any more request data to the server.
241
 * Clear the send buffer and mark request sending as done.
242
 */
243
CURLcode Curl_req_abort_sending(struct Curl_easy *data);
244
245
/**
246
 * Stop sending and receiving any more request data.
247
 * Abort sending if not done.
248
 */
249
CURLcode Curl_req_stop_send_recv(struct Curl_easy *data);
250
251
/**
252
 * Invoked when all request data has been uploaded.
253
 */
254
CURLcode Curl_req_set_upload_done(struct Curl_easy *data);
255
256
#endif /* HEADER_CURL_REQUEST_H */