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