1 | #ifndef HEADER_CURL_CFILTERS_H
|
---|
2 | #define HEADER_CURL_CFILTERS_H
|
---|
3 | /***************************************************************************
|
---|
4 | * _ _ ____ _
|
---|
5 | * Project ___| | | | _ \| |
|
---|
6 | * / __| | | | |_) | |
|
---|
7 | * | (__| |_| | _ <| |___
|
---|
8 | * \___|\___/|_| \_\_____|
|
---|
9 | *
|
---|
10 | * Copyright (C) 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 |
|
---|
27 | #include "timediff.h"
|
---|
28 |
|
---|
29 | struct Curl_cfilter;
|
---|
30 | struct Curl_easy;
|
---|
31 | struct Curl_dns_entry;
|
---|
32 | struct connectdata;
|
---|
33 | struct ip_quadruple;
|
---|
34 |
|
---|
35 | /* Callback to destroy resources held by this filter instance.
|
---|
36 | * Implementations MUST NOT chain calls to cf->next.
|
---|
37 | */
|
---|
38 | typedef void Curl_cft_destroy_this(struct Curl_cfilter *cf,
|
---|
39 | struct Curl_easy *data);
|
---|
40 |
|
---|
41 | /* Callback to close the connection immediately. */
|
---|
42 | typedef void Curl_cft_close(struct Curl_cfilter *cf,
|
---|
43 | struct Curl_easy *data);
|
---|
44 |
|
---|
45 | /* Callback to close the connection filter gracefully, non-blocking.
|
---|
46 | * Implementations MUST NOT chain calls to cf->next.
|
---|
47 | */
|
---|
48 | typedef CURLcode Curl_cft_shutdown(struct Curl_cfilter *cf,
|
---|
49 | struct Curl_easy *data,
|
---|
50 | bool *done);
|
---|
51 |
|
---|
52 | typedef CURLcode Curl_cft_connect(struct Curl_cfilter *cf,
|
---|
53 | struct Curl_easy *data,
|
---|
54 | bool blocking, bool *done);
|
---|
55 |
|
---|
56 | /* Return the hostname and port the connection goes to.
|
---|
57 | * This may change with the connection state of filters when tunneling
|
---|
58 | * is involved.
|
---|
59 | * @param cf the filter to ask
|
---|
60 | * @param data the easy handle currently active
|
---|
61 | * @param phost on return, points to the relevant, real hostname.
|
---|
62 | * this is owned by the connection.
|
---|
63 | * @param pdisplay_host on return, points to the printable hostname.
|
---|
64 | * this is owned by the connection.
|
---|
65 | * @param pport on return, contains the port number
|
---|
66 | */
|
---|
67 | typedef void Curl_cft_get_host(struct Curl_cfilter *cf,
|
---|
68 | struct Curl_easy *data,
|
---|
69 | const char **phost,
|
---|
70 | const char **pdisplay_host,
|
---|
71 | int *pport);
|
---|
72 |
|
---|
73 | struct easy_pollset;
|
---|
74 |
|
---|
75 | /* Passing in an easy_pollset for monitoring of sockets, let
|
---|
76 | * filters add or remove sockets actions (CURL_POLL_OUT, CURL_POLL_IN).
|
---|
77 | * This may add a socket or, in case no actions remain, remove
|
---|
78 | * a socket from the set.
|
---|
79 | *
|
---|
80 | * Filter implementations need to call filters "below" *after* they have
|
---|
81 | * made their adjustments. This allows lower filters to override "upper"
|
---|
82 | * actions. If a "lower" filter is unable to write, it needs to be able
|
---|
83 | * to disallow POLL_OUT.
|
---|
84 | *
|
---|
85 | * A filter without own restrictions/preferences should not modify
|
---|
86 | * the pollset. Filters, whose filter "below" is not connected, should
|
---|
87 | * also do no adjustments.
|
---|
88 | *
|
---|
89 | * Examples: a TLS handshake, while ongoing, might remove POLL_IN when it
|
---|
90 | * needs to write, or vice versa. An HTTP/2 filter might remove POLL_OUT when
|
---|
91 | * a stream window is exhausted and a WINDOW_UPDATE needs to be received first
|
---|
92 | * and add instead POLL_IN.
|
---|
93 | *
|
---|
94 | * @param cf the filter to ask
|
---|
95 | * @param data the easy handle the pollset is about
|
---|
96 | * @param ps the pollset (inout) for the easy handle
|
---|
97 | */
|
---|
98 | typedef void Curl_cft_adjust_pollset(struct Curl_cfilter *cf,
|
---|
99 | struct Curl_easy *data,
|
---|
100 | struct easy_pollset *ps);
|
---|
101 |
|
---|
102 | typedef bool Curl_cft_data_pending(struct Curl_cfilter *cf,
|
---|
103 | const struct Curl_easy *data);
|
---|
104 |
|
---|
105 | typedef ssize_t Curl_cft_send(struct Curl_cfilter *cf,
|
---|
106 | struct Curl_easy *data, /* transfer */
|
---|
107 | const void *buf, /* data to write */
|
---|
108 | size_t len, /* amount to write */
|
---|
109 | bool eos, /* last chunk */
|
---|
110 | CURLcode *err); /* error to return */
|
---|
111 |
|
---|
112 | typedef ssize_t Curl_cft_recv(struct Curl_cfilter *cf,
|
---|
113 | struct Curl_easy *data, /* transfer */
|
---|
114 | char *buf, /* store data here */
|
---|
115 | size_t len, /* amount to read */
|
---|
116 | CURLcode *err); /* error to return */
|
---|
117 |
|
---|
118 | typedef bool Curl_cft_conn_is_alive(struct Curl_cfilter *cf,
|
---|
119 | struct Curl_easy *data,
|
---|
120 | bool *input_pending);
|
---|
121 |
|
---|
122 | typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf,
|
---|
123 | struct Curl_easy *data);
|
---|
124 |
|
---|
125 | /**
|
---|
126 | * Events/controls for connection filters, their arguments and
|
---|
127 | * return code handling. Filter callbacks are invoked "top down".
|
---|
128 | * Return code handling:
|
---|
129 | * "first fail" meaning that the first filter returning != CURLE_OK, will
|
---|
130 | * abort further event distribution and determine the result.
|
---|
131 | * "ignored" meaning return values are ignored and the event is distributed
|
---|
132 | * to all filters in the chain. Overall result is always CURLE_OK.
|
---|
133 | */
|
---|
134 | /* data event arg1 arg2 return */
|
---|
135 | #define CF_CTRL_DATA_ATTACH 1 /* 0 NULL ignored */
|
---|
136 | #define CF_CTRL_DATA_DETACH 2 /* 0 NULL ignored */
|
---|
137 | #define CF_CTRL_DATA_SETUP 4 /* 0 NULL first fail */
|
---|
138 | #define CF_CTRL_DATA_IDLE 5 /* 0 NULL first fail */
|
---|
139 | #define CF_CTRL_DATA_PAUSE 6 /* on/off NULL first fail */
|
---|
140 | #define CF_CTRL_DATA_DONE 7 /* premature NULL ignored */
|
---|
141 | #define CF_CTRL_DATA_DONE_SEND 8 /* 0 NULL ignored */
|
---|
142 | /* update conn info at connection and data */
|
---|
143 | #define CF_CTRL_CONN_INFO_UPDATE (256+0) /* 0 NULL ignored */
|
---|
144 | #define CF_CTRL_FORGET_SOCKET (256+1) /* 0 NULL ignored */
|
---|
145 | #define CF_CTRL_FLUSH (256+2) /* 0 NULL first fail */
|
---|
146 |
|
---|
147 | /**
|
---|
148 | * Handle event/control for the filter.
|
---|
149 | * Implementations MUST NOT chain calls to cf->next.
|
---|
150 | */
|
---|
151 | typedef CURLcode Curl_cft_cntrl(struct Curl_cfilter *cf,
|
---|
152 | struct Curl_easy *data,
|
---|
153 | int event, int arg1, void *arg2);
|
---|
154 |
|
---|
155 |
|
---|
156 | /**
|
---|
157 | * Queries to ask via a `Curl_cft_query *query` method on a cfilter chain.
|
---|
158 | * - MAX_CONCURRENT: the maximum number of parallel transfers the filter
|
---|
159 | * chain expects to handle at the same time.
|
---|
160 | * default: 1 if no filter overrides.
|
---|
161 | * - CONNECT_REPLY_MS: milliseconds until the first indication of a server
|
---|
162 | * response was received on a connect. For TCP, this
|
---|
163 | * reflects the time until the socket connected. On UDP
|
---|
164 | * this gives the time the first bytes from the server
|
---|
165 | * were received.
|
---|
166 | * -1 if not determined yet.
|
---|
167 | * - CF_QUERY_SOCKET: the socket used by the filter chain
|
---|
168 | * - CF_QUERY_NEED_FLUSH: TRUE iff any of the filters have unsent data
|
---|
169 | * - CF_QUERY_IP_INFO: res1 says if connection used IPv6, res2 is the
|
---|
170 | * ip quadruple
|
---|
171 | */
|
---|
172 | /* query res1 res2 */
|
---|
173 | #define CF_QUERY_MAX_CONCURRENT 1 /* number - */
|
---|
174 | #define CF_QUERY_CONNECT_REPLY_MS 2 /* number - */
|
---|
175 | #define CF_QUERY_SOCKET 3 /* - curl_socket_t */
|
---|
176 | #define CF_QUERY_TIMER_CONNECT 4 /* - struct curltime */
|
---|
177 | #define CF_QUERY_TIMER_APPCONNECT 5 /* - struct curltime */
|
---|
178 | #define CF_QUERY_STREAM_ERROR 6 /* error code - */
|
---|
179 | #define CF_QUERY_NEED_FLUSH 7 /* TRUE/FALSE - */
|
---|
180 | #define CF_QUERY_IP_INFO 8 /* TRUE/FALSE struct ip_quadruple */
|
---|
181 |
|
---|
182 | /**
|
---|
183 | * Query the cfilter for properties. Filters ignorant of a query will
|
---|
184 | * pass it "down" the filter chain.
|
---|
185 | */
|
---|
186 | typedef CURLcode Curl_cft_query(struct Curl_cfilter *cf,
|
---|
187 | struct Curl_easy *data,
|
---|
188 | int query, int *pres1, void *pres2);
|
---|
189 |
|
---|
190 | /**
|
---|
191 | * Type flags for connection filters. A filter can have none, one or
|
---|
192 | * many of those. Use to evaluate state/capabilities of a filter chain.
|
---|
193 | *
|
---|
194 | * CF_TYPE_IP_CONNECT: provides an IP connection or sth equivalent, like
|
---|
195 | * a CONNECT tunnel, a UNIX domain socket, a QUIC
|
---|
196 | * connection, etc.
|
---|
197 | * CF_TYPE_SSL: provide SSL/TLS
|
---|
198 | * CF_TYPE_MULTIPLEX: provides multiplexing of easy handles
|
---|
199 | * CF_TYPE_PROXY provides proxying
|
---|
200 | */
|
---|
201 | #define CF_TYPE_IP_CONNECT (1 << 0)
|
---|
202 | #define CF_TYPE_SSL (1 << 1)
|
---|
203 | #define CF_TYPE_MULTIPLEX (1 << 2)
|
---|
204 | #define CF_TYPE_PROXY (1 << 3)
|
---|
205 |
|
---|
206 | /* A connection filter type, e.g. specific implementation. */
|
---|
207 | struct Curl_cftype {
|
---|
208 | const char *name; /* name of the filter type */
|
---|
209 | int flags; /* flags of filter type */
|
---|
210 | int log_level; /* log level for such filters */
|
---|
211 | Curl_cft_destroy_this *destroy; /* destroy resources of this cf */
|
---|
212 | Curl_cft_connect *do_connect; /* establish connection */
|
---|
213 | Curl_cft_close *do_close; /* close conn */
|
---|
214 | Curl_cft_shutdown *do_shutdown; /* shutdown conn */
|
---|
215 | Curl_cft_get_host *get_host; /* host filter talks to */
|
---|
216 | Curl_cft_adjust_pollset *adjust_pollset; /* adjust transfer poll set */
|
---|
217 | Curl_cft_data_pending *has_data_pending;/* conn has data pending */
|
---|
218 | Curl_cft_send *do_send; /* send data */
|
---|
219 | Curl_cft_recv *do_recv; /* receive data */
|
---|
220 | Curl_cft_cntrl *cntrl; /* events/control */
|
---|
221 | Curl_cft_conn_is_alive *is_alive; /* FALSE if conn is dead, Jim! */
|
---|
222 | Curl_cft_conn_keep_alive *keep_alive; /* try to keep it alive */
|
---|
223 | Curl_cft_query *query; /* query filter chain */
|
---|
224 | };
|
---|
225 |
|
---|
226 | /* A connection filter instance, e.g. registered at a connection */
|
---|
227 | struct Curl_cfilter {
|
---|
228 | const struct Curl_cftype *cft; /* the type providing implementation */
|
---|
229 | struct Curl_cfilter *next; /* next filter in chain */
|
---|
230 | void *ctx; /* filter type specific settings */
|
---|
231 | struct connectdata *conn; /* the connection this filter belongs to */
|
---|
232 | int sockindex; /* the index the filter is installed at */
|
---|
233 | BIT(connected); /* != 0 iff this filter is connected */
|
---|
234 | BIT(shutdown); /* != 0 iff this filter has shut down */
|
---|
235 | };
|
---|
236 |
|
---|
237 | /* Default implementations for the type functions, implementing nop. */
|
---|
238 | void Curl_cf_def_destroy_this(struct Curl_cfilter *cf,
|
---|
239 | struct Curl_easy *data);
|
---|
240 |
|
---|
241 | /* Default implementations for the type functions, implementing pass-through
|
---|
242 | * the filter chain. */
|
---|
243 | void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
|
---|
244 | const char **phost, const char **pdisplay_host,
|
---|
245 | int *pport);
|
---|
246 | void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
|
---|
247 | struct Curl_easy *data,
|
---|
248 | struct easy_pollset *ps);
|
---|
249 | bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
|
---|
250 | const struct Curl_easy *data);
|
---|
251 | ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
---|
252 | const void *buf, size_t len, bool eos,
|
---|
253 | CURLcode *err);
|
---|
254 | ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
---|
255 | char *buf, size_t len, CURLcode *err);
|
---|
256 | CURLcode Curl_cf_def_cntrl(struct Curl_cfilter *cf,
|
---|
257 | struct Curl_easy *data,
|
---|
258 | int event, int arg1, void *arg2);
|
---|
259 | bool Curl_cf_def_conn_is_alive(struct Curl_cfilter *cf,
|
---|
260 | struct Curl_easy *data,
|
---|
261 | bool *input_pending);
|
---|
262 | CURLcode Curl_cf_def_conn_keep_alive(struct Curl_cfilter *cf,
|
---|
263 | struct Curl_easy *data);
|
---|
264 | CURLcode Curl_cf_def_query(struct Curl_cfilter *cf,
|
---|
265 | struct Curl_easy *data,
|
---|
266 | int query, int *pres1, void *pres2);
|
---|
267 | CURLcode Curl_cf_def_shutdown(struct Curl_cfilter *cf,
|
---|
268 | struct Curl_easy *data, bool *done);
|
---|
269 |
|
---|
270 | /**
|
---|
271 | * Create a new filter instance, unattached to the filter chain.
|
---|
272 | * Use Curl_conn_cf_add() to add it to the chain.
|
---|
273 | * @param pcf on success holds the created instance
|
---|
274 | * @param cft the filter type
|
---|
275 | * @param ctx the type specific context to use
|
---|
276 | */
|
---|
277 | CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
|
---|
278 | const struct Curl_cftype *cft,
|
---|
279 | void *ctx);
|
---|
280 |
|
---|
281 | /**
|
---|
282 | * Add a filter instance to the `sockindex` filter chain at connection
|
---|
283 | * `conn`. The filter must not already be attached. It is inserted at
|
---|
284 | * the start of the chain (top).
|
---|
285 | */
|
---|
286 | void Curl_conn_cf_add(struct Curl_easy *data,
|
---|
287 | struct connectdata *conn,
|
---|
288 | int sockindex,
|
---|
289 | struct Curl_cfilter *cf);
|
---|
290 |
|
---|
291 | /**
|
---|
292 | * Insert a filter (chain) after `cf_at`.
|
---|
293 | * `cf_new` must not already be attached.
|
---|
294 | */
|
---|
295 | void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
|
---|
296 | struct Curl_cfilter *cf_new);
|
---|
297 |
|
---|
298 | /**
|
---|
299 | * Discard, e.g. remove and destroy `discard` iff
|
---|
300 | * it still is in the filter chain below `cf`. If `discard`
|
---|
301 | * is no longer found beneath `cf` return FALSE.
|
---|
302 | * if `destroy_always` is TRUE, will call `discard`s destroy
|
---|
303 | * function and free it even if not found in the subchain.
|
---|
304 | */
|
---|
305 | bool Curl_conn_cf_discard_sub(struct Curl_cfilter *cf,
|
---|
306 | struct Curl_cfilter *discard,
|
---|
307 | struct Curl_easy *data,
|
---|
308 | bool destroy_always);
|
---|
309 |
|
---|
310 | /**
|
---|
311 | * Discard all cfilters starting with `*pcf` and clearing it afterwards.
|
---|
312 | */
|
---|
313 | void Curl_conn_cf_discard_chain(struct Curl_cfilter **pcf,
|
---|
314 | struct Curl_easy *data);
|
---|
315 |
|
---|
316 | /**
|
---|
317 | * Remove and destroy all filters at chain `sockindex` on connection `conn`.
|
---|
318 | */
|
---|
319 | void Curl_conn_cf_discard_all(struct Curl_easy *data,
|
---|
320 | struct connectdata *conn,
|
---|
321 | int sockindex);
|
---|
322 |
|
---|
323 |
|
---|
324 | CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
|
---|
325 | struct Curl_easy *data,
|
---|
326 | bool blocking, bool *done);
|
---|
327 | void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data);
|
---|
328 | ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
---|
329 | const void *buf, size_t len, bool eos,
|
---|
330 | CURLcode *err);
|
---|
331 | ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
---|
332 | char *buf, size_t len, CURLcode *err);
|
---|
333 | CURLcode Curl_conn_cf_cntrl(struct Curl_cfilter *cf,
|
---|
334 | struct Curl_easy *data,
|
---|
335 | bool ignore_result,
|
---|
336 | int event, int arg1, void *arg2);
|
---|
337 |
|
---|
338 | /**
|
---|
339 | * Determine if the connection filter chain is using SSL to the remote host
|
---|
340 | * (or will be once connected).
|
---|
341 | */
|
---|
342 | bool Curl_conn_cf_is_ssl(struct Curl_cfilter *cf);
|
---|
343 |
|
---|
344 | /**
|
---|
345 | * Get the socket used by the filter chain starting at `cf`.
|
---|
346 | * Returns CURL_SOCKET_BAD if not available.
|
---|
347 | */
|
---|
348 | curl_socket_t Curl_conn_cf_get_socket(struct Curl_cfilter *cf,
|
---|
349 | struct Curl_easy *data);
|
---|
350 |
|
---|
351 | CURLcode Curl_conn_cf_get_ip_info(struct Curl_cfilter *cf,
|
---|
352 | struct Curl_easy *data,
|
---|
353 | int *is_ipv6, struct ip_quadruple *ipquad);
|
---|
354 |
|
---|
355 | bool Curl_conn_cf_needs_flush(struct Curl_cfilter *cf,
|
---|
356 | struct Curl_easy *data);
|
---|
357 |
|
---|
358 | #define CURL_CF_SSL_DEFAULT -1
|
---|
359 | #define CURL_CF_SSL_DISABLE 0
|
---|
360 | #define CURL_CF_SSL_ENABLE 1
|
---|
361 |
|
---|
362 | /**
|
---|
363 | * Bring the filter chain at `sockindex` for connection `data->conn` into
|
---|
364 | * connected state. Which will set `*done` to TRUE.
|
---|
365 | * This can be called on an already connected chain with no side effects.
|
---|
366 | * When not `blocking`, calls may return without error and `*done != TRUE`,
|
---|
367 | * while the individual filters negotiated the connection.
|
---|
368 | */
|
---|
369 | CURLcode Curl_conn_connect(struct Curl_easy *data, int sockindex,
|
---|
370 | bool blocking, bool *done);
|
---|
371 |
|
---|
372 | /**
|
---|
373 | * Check if the filter chain at `sockindex` for connection `conn` is
|
---|
374 | * completely connected.
|
---|
375 | */
|
---|
376 | bool Curl_conn_is_connected(struct connectdata *conn, int sockindex);
|
---|
377 |
|
---|
378 | /**
|
---|
379 | * Determine if we have reached the remote host on IP level, e.g.
|
---|
380 | * have a TCP connection. This turns TRUE before a possible SSL
|
---|
381 | * handshake has been started/done.
|
---|
382 | */
|
---|
383 | bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex);
|
---|
384 |
|
---|
385 | /**
|
---|
386 | * Determine if the connection is using SSL to the remote host
|
---|
387 | * (or will be once connected). This will return FALSE, if SSL
|
---|
388 | * is only used in proxying and not for the tunnel itself.
|
---|
389 | */
|
---|
390 | bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex);
|
---|
391 |
|
---|
392 | /**
|
---|
393 | * Connection provides multiplexing of easy handles at `socketindex`.
|
---|
394 | */
|
---|
395 | bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex);
|
---|
396 |
|
---|
397 | /**
|
---|
398 | * Close the filter chain at `sockindex` for connection `data->conn`.
|
---|
399 | * Filters remain in place and may be connected again afterwards.
|
---|
400 | */
|
---|
401 | void Curl_conn_close(struct Curl_easy *data, int sockindex);
|
---|
402 |
|
---|
403 | /**
|
---|
404 | * Shutdown the connection at `sockindex` non-blocking, using timeout
|
---|
405 | * from `data->set.shutdowntimeout`, default DEFAULT_SHUTDOWN_TIMEOUT_MS.
|
---|
406 | * Will return CURLE_OK and *done == FALSE if not finished.
|
---|
407 | */
|
---|
408 | CURLcode Curl_conn_shutdown(struct Curl_easy *data, int sockindex, bool *done);
|
---|
409 |
|
---|
410 | /**
|
---|
411 | * Return if data is pending in some connection filter at chain
|
---|
412 | * `sockindex` for connection `data->conn`.
|
---|
413 | */
|
---|
414 | bool Curl_conn_data_pending(struct Curl_easy *data,
|
---|
415 | int sockindex);
|
---|
416 |
|
---|
417 | /**
|
---|
418 | * Return TRUE if any of the connection filters at chain `sockindex`
|
---|
419 | * have data still to send.
|
---|
420 | */
|
---|
421 | bool Curl_conn_needs_flush(struct Curl_easy *data, int sockindex);
|
---|
422 |
|
---|
423 | /**
|
---|
424 | * Flush any pending data on the connection filters at chain `sockindex`.
|
---|
425 | */
|
---|
426 | CURLcode Curl_conn_flush(struct Curl_easy *data, int sockindex);
|
---|
427 |
|
---|
428 | /**
|
---|
429 | * Return the socket used on data's connection for the index.
|
---|
430 | * Returns CURL_SOCKET_BAD if not available.
|
---|
431 | */
|
---|
432 | curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex);
|
---|
433 |
|
---|
434 | /**
|
---|
435 | * Tell filters to forget about the socket at sockindex.
|
---|
436 | */
|
---|
437 | void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex);
|
---|
438 |
|
---|
439 | /**
|
---|
440 | * Adjust the pollset for the filter chain startgin at `cf`.
|
---|
441 | */
|
---|
442 | void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
|
---|
443 | struct Curl_easy *data,
|
---|
444 | struct easy_pollset *ps);
|
---|
445 |
|
---|
446 | /**
|
---|
447 | * Adjust pollset from filters installed at transfer's connection.
|
---|
448 | */
|
---|
449 | void Curl_conn_adjust_pollset(struct Curl_easy *data,
|
---|
450 | struct easy_pollset *ps);
|
---|
451 |
|
---|
452 | /**
|
---|
453 | * Curl_poll() the filter chain at `cf` with timeout `timeout_ms`.
|
---|
454 | * Returns 0 on timeout, negative on error or number of sockets
|
---|
455 | * with requested poll events.
|
---|
456 | */
|
---|
457 | int Curl_conn_cf_poll(struct Curl_cfilter *cf,
|
---|
458 | struct Curl_easy *data,
|
---|
459 | timediff_t timeout_ms);
|
---|
460 |
|
---|
461 | /**
|
---|
462 | * Receive data through the filter chain at `sockindex` for connection
|
---|
463 | * `data->conn`. Copy at most `len` bytes into `buf`. Return the
|
---|
464 | * actual number of bytes copied or a negative value on error.
|
---|
465 | * The error code is placed into `*code`.
|
---|
466 | */
|
---|
467 | ssize_t Curl_cf_recv(struct Curl_easy *data, int sockindex, char *buf,
|
---|
468 | size_t len, CURLcode *code);
|
---|
469 |
|
---|
470 | /**
|
---|
471 | * Send `len` bytes of data from `buf` through the filter chain `sockindex`
|
---|
472 | * at connection `data->conn`. Return the actual number of bytes written
|
---|
473 | * or a negative value on error.
|
---|
474 | * The error code is placed into `*code`.
|
---|
475 | */
|
---|
476 | ssize_t Curl_cf_send(struct Curl_easy *data, int sockindex,
|
---|
477 | const void *buf, size_t len, bool eos, CURLcode *code);
|
---|
478 |
|
---|
479 | /**
|
---|
480 | * The easy handle `data` is being attached to `conn`. This does
|
---|
481 | * not mean that data will actually do a transfer. Attachment is
|
---|
482 | * also used for temporary actions on the connection.
|
---|
483 | */
|
---|
484 | void Curl_conn_ev_data_attach(struct connectdata *conn,
|
---|
485 | struct Curl_easy *data);
|
---|
486 |
|
---|
487 | /**
|
---|
488 | * The easy handle `data` is being detached (no longer served)
|
---|
489 | * by connection `conn`. All filters are informed to release any resources
|
---|
490 | * related to `data`.
|
---|
491 | * Note: there may be several `data` attached to a connection at the same
|
---|
492 | * time.
|
---|
493 | */
|
---|
494 | void Curl_conn_ev_data_detach(struct connectdata *conn,
|
---|
495 | struct Curl_easy *data);
|
---|
496 |
|
---|
497 | /**
|
---|
498 | * Notify connection filters that they need to setup data for
|
---|
499 | * a transfer.
|
---|
500 | */
|
---|
501 | CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data);
|
---|
502 |
|
---|
503 | /**
|
---|
504 | * Notify connection filters that now would be a good time to
|
---|
505 | * perform any idle, e.g. time related, actions.
|
---|
506 | */
|
---|
507 | CURLcode Curl_conn_ev_data_idle(struct Curl_easy *data);
|
---|
508 |
|
---|
509 | /**
|
---|
510 | * Notify connection filters that the transfer represented by `data`
|
---|
511 | * is done with sending data (e.g. has uploaded everything).
|
---|
512 | */
|
---|
513 | void Curl_conn_ev_data_done_send(struct Curl_easy *data);
|
---|
514 |
|
---|
515 | /**
|
---|
516 | * Notify connection filters that the transfer represented by `data`
|
---|
517 | * is finished - eventually premature, e.g. before being complete.
|
---|
518 | */
|
---|
519 | void Curl_conn_ev_data_done(struct Curl_easy *data, bool premature);
|
---|
520 |
|
---|
521 | /**
|
---|
522 | * Notify connection filters that the transfer of data is paused/unpaused.
|
---|
523 | */
|
---|
524 | CURLcode Curl_conn_ev_data_pause(struct Curl_easy *data, bool do_pause);
|
---|
525 |
|
---|
526 | /**
|
---|
527 | * Check if FIRSTSOCKET's cfilter chain deems connection alive.
|
---|
528 | */
|
---|
529 | bool Curl_conn_is_alive(struct Curl_easy *data, struct connectdata *conn,
|
---|
530 | bool *input_pending);
|
---|
531 |
|
---|
532 | /**
|
---|
533 | * Try to upkeep the connection filters at sockindex.
|
---|
534 | */
|
---|
535 | CURLcode Curl_conn_keep_alive(struct Curl_easy *data,
|
---|
536 | struct connectdata *conn,
|
---|
537 | int sockindex);
|
---|
538 |
|
---|
539 | #ifdef UNITTESTS
|
---|
540 | void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data);
|
---|
541 | #endif
|
---|
542 | void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
|
---|
543 | const char **phost, const char **pdisplay_host,
|
---|
544 | int *pport);
|
---|
545 |
|
---|
546 | /**
|
---|
547 | * Get the maximum number of parallel transfers the connection
|
---|
548 | * expects to be able to handle at `sockindex`.
|
---|
549 | */
|
---|
550 | size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
|
---|
551 | struct connectdata *conn,
|
---|
552 | int sockindex);
|
---|
553 |
|
---|
554 | /**
|
---|
555 | * Get the underlying error code for a transfer stream or 0 if not known.
|
---|
556 | */
|
---|
557 | int Curl_conn_get_stream_error(struct Curl_easy *data,
|
---|
558 | struct connectdata *conn,
|
---|
559 | int sockindex);
|
---|
560 |
|
---|
561 | /**
|
---|
562 | * Get the index of the given socket in the connection's sockets.
|
---|
563 | * Useful in calling `Curl_conn_send()/Curl_conn_recv()` with the
|
---|
564 | * correct socket index.
|
---|
565 | */
|
---|
566 | int Curl_conn_sockindex(struct Curl_easy *data, curl_socket_t sockfd);
|
---|
567 |
|
---|
568 | /*
|
---|
569 | * Receive data on the connection, using FIRSTSOCKET/SECONDARYSOCKET.
|
---|
570 | * Will return CURLE_AGAIN iff blocked on receiving.
|
---|
571 | */
|
---|
572 | CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
|
---|
573 | char *buf, size_t buffersize,
|
---|
574 | ssize_t *pnread);
|
---|
575 |
|
---|
576 | /*
|
---|
577 | * Send data on the connection, using FIRSTSOCKET/SECONDARYSOCKET.
|
---|
578 | * Will return CURLE_AGAIN iff blocked on sending.
|
---|
579 | */
|
---|
580 | CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
|
---|
581 | const void *buf, size_t blen, bool eos,
|
---|
582 | size_t *pnwritten);
|
---|
583 |
|
---|
584 |
|
---|
585 | void Curl_pollset_reset(struct Curl_easy *data,
|
---|
586 | struct easy_pollset *ps);
|
---|
587 |
|
---|
588 | /* Change the poll flags (CURL_POLL_IN/CURL_POLL_OUT) to the poll set for
|
---|
589 | * socket `sock`. If the socket is not already part of the poll set, it
|
---|
590 | * will be added.
|
---|
591 | * If the socket is present and all poll flags are cleared, it will be removed.
|
---|
592 | */
|
---|
593 | void Curl_pollset_change(struct Curl_easy *data,
|
---|
594 | struct easy_pollset *ps, curl_socket_t sock,
|
---|
595 | int add_flags, int remove_flags);
|
---|
596 |
|
---|
597 | void Curl_pollset_set(struct Curl_easy *data,
|
---|
598 | struct easy_pollset *ps, curl_socket_t sock,
|
---|
599 | bool do_in, bool do_out);
|
---|
600 |
|
---|
601 | #define Curl_pollset_add_in(data, ps, sock) \
|
---|
602 | Curl_pollset_change((data), (ps), (sock), CURL_POLL_IN, 0)
|
---|
603 | #define Curl_pollset_add_out(data, ps, sock) \
|
---|
604 | Curl_pollset_change((data), (ps), (sock), CURL_POLL_OUT, 0)
|
---|
605 | #define Curl_pollset_add_inout(data, ps, sock) \
|
---|
606 | Curl_pollset_change((data), (ps), (sock), \
|
---|
607 | CURL_POLL_IN|CURL_POLL_OUT, 0)
|
---|
608 | #define Curl_pollset_set_in_only(data, ps, sock) \
|
---|
609 | Curl_pollset_change((data), (ps), (sock), \
|
---|
610 | CURL_POLL_IN, CURL_POLL_OUT)
|
---|
611 | #define Curl_pollset_set_out_only(data, ps, sock) \
|
---|
612 | Curl_pollset_change((data), (ps), (sock), \
|
---|
613 | CURL_POLL_OUT, CURL_POLL_IN)
|
---|
614 |
|
---|
615 | void Curl_pollset_add_socks(struct Curl_easy *data,
|
---|
616 | struct easy_pollset *ps,
|
---|
617 | int (*get_socks_cb)(struct Curl_easy *data,
|
---|
618 | curl_socket_t *socks));
|
---|
619 |
|
---|
620 | /**
|
---|
621 | * Check if the pollset, as is, wants to read and/or write regarding
|
---|
622 | * the given socket.
|
---|
623 | */
|
---|
624 | void Curl_pollset_check(struct Curl_easy *data,
|
---|
625 | struct easy_pollset *ps, curl_socket_t sock,
|
---|
626 | bool *pwant_read, bool *pwant_write);
|
---|
627 |
|
---|
628 | /**
|
---|
629 | * Types and macros used to keep the current easy handle in filter calls,
|
---|
630 | * allowing for nested invocations. See #10336.
|
---|
631 | *
|
---|
632 | * `cf_call_data` is intended to be a member of the cfilter's `ctx` type.
|
---|
633 | * A filter defines the macro `CF_CTX_CALL_DATA` to give access to that.
|
---|
634 | *
|
---|
635 | * With all values 0, the default, this indicates that there is no cfilter
|
---|
636 | * call with `data` ongoing.
|
---|
637 | * Macro `CF_DATA_SAVE` preserves the current `cf_call_data` in a local
|
---|
638 | * variable and sets the `data` given, incrementing the `depth` counter.
|
---|
639 | *
|
---|
640 | * Macro `CF_DATA_RESTORE` restores the old values from the local variable,
|
---|
641 | * while checking that `depth` values are as expected (debug build), catching
|
---|
642 | * cases where a "lower" RESTORE was not called.
|
---|
643 | *
|
---|
644 | * Finally, macro `CF_DATA_CURRENT` gives the easy handle of the current
|
---|
645 | * invocation.
|
---|
646 | */
|
---|
647 | struct cf_call_data {
|
---|
648 | struct Curl_easy *data;
|
---|
649 | #ifdef DEBUGBUILD
|
---|
650 | int depth;
|
---|
651 | #endif
|
---|
652 | };
|
---|
653 |
|
---|
654 | /**
|
---|
655 | * define to access the `struct cf_call_data for a cfilter. Normally
|
---|
656 | * a member in the cfilter's `ctx`.
|
---|
657 | *
|
---|
658 | * #define CF_CTX_CALL_DATA(cf) -> struct cf_call_data instance
|
---|
659 | */
|
---|
660 |
|
---|
661 | #ifdef DEBUGBUILD
|
---|
662 |
|
---|
663 | #define CF_DATA_SAVE(save, cf, data) \
|
---|
664 | do { \
|
---|
665 | (save) = CF_CTX_CALL_DATA(cf); \
|
---|
666 | DEBUGASSERT((save).data == NULL || (save).depth > 0); \
|
---|
667 | CF_CTX_CALL_DATA(cf).depth++; \
|
---|
668 | CF_CTX_CALL_DATA(cf).data = (struct Curl_easy *)data; \
|
---|
669 | } while(0)
|
---|
670 |
|
---|
671 | #define CF_DATA_RESTORE(cf, save) \
|
---|
672 | do { \
|
---|
673 | DEBUGASSERT(CF_CTX_CALL_DATA(cf).depth == (save).depth + 1); \
|
---|
674 | DEBUGASSERT((save).data == NULL || (save).depth > 0); \
|
---|
675 | CF_CTX_CALL_DATA(cf) = (save); \
|
---|
676 | } while(0)
|
---|
677 |
|
---|
678 | #else /* DEBUGBUILD */
|
---|
679 |
|
---|
680 | #define CF_DATA_SAVE(save, cf, data) \
|
---|
681 | do { \
|
---|
682 | (save) = CF_CTX_CALL_DATA(cf); \
|
---|
683 | CF_CTX_CALL_DATA(cf).data = (struct Curl_easy *)data; \
|
---|
684 | } while(0)
|
---|
685 |
|
---|
686 | #define CF_DATA_RESTORE(cf, save) \
|
---|
687 | do { \
|
---|
688 | CF_CTX_CALL_DATA(cf) = (save); \
|
---|
689 | } while(0)
|
---|
690 |
|
---|
691 | #endif /* !DEBUGBUILD */
|
---|
692 |
|
---|
693 | #define CF_DATA_CURRENT(cf) \
|
---|
694 | ((cf)? (CF_CTX_CALL_DATA(cf).data) : NULL)
|
---|
695 |
|
---|
696 | #endif /* HEADER_CURL_CFILTERS_H */
|
---|