2012-12-11 00:04:13 +08:00
|
|
|
#ifndef HEADER_CURL_CONNCACHE_H
|
|
|
|
#define HEADER_CURL_CONNCACHE_H
|
2012-12-06 19:12:04 +08:00
|
|
|
/***************************************************************************
|
|
|
|
* _ _ ____ _
|
|
|
|
* Project ___| | | | _ \| |
|
|
|
|
* / __| | | | |_) | |
|
|
|
|
* | (__| |_| | _ <| |___
|
|
|
|
* \___|\___/|_| \_\_____|
|
|
|
|
*
|
2023-01-02 20:51:48 +08:00
|
|
|
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
|
|
* Copyright (C) Linus Nielsen Feltzing, <linus@haxx.se>
|
2012-12-06 19:12:04 +08:00
|
|
|
*
|
|
|
|
* This software is licensed as described in the file COPYING, which
|
|
|
|
* you should have received as part of this distribution. The terms
|
2020-11-04 21:02:01 +08:00
|
|
|
* are also available at https://curl.se/docs/copyright.html.
|
2012-12-06 19:12:04 +08:00
|
|
|
*
|
|
|
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
|
|
* copies of the Software, and permit persons to whom the Software is
|
|
|
|
* furnished to do so, under the terms of the COPYING file.
|
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: curl
|
2022-05-17 17:16:50 +08:00
|
|
|
*
|
2012-12-06 19:12:04 +08:00
|
|
|
***************************************************************************/
|
|
|
|
|
2017-12-02 21:27:00 +08:00
|
|
|
/*
|
|
|
|
* All accesses to struct fields and changing of data in the connection cache
|
|
|
|
* and connectbundles must be done with the conncache LOCKED. The cache might
|
|
|
|
* be shared.
|
|
|
|
*/
|
|
|
|
|
2022-09-07 18:19:29 +08:00
|
|
|
#include <curl/curl.h>
|
2020-12-11 16:05:47 +08:00
|
|
|
#include "timeval.h"
|
|
|
|
|
|
|
|
struct connectdata;
|
lib: graceful connection shutdown
When libcurl discards a connection there are two phases this may go
through: "shutdown" and "closing". If a connection is aborted, the
shutdown phase is skipped and it is closed right away.
The connection filters attached to the connection implement the phases
in their `do_shutdown()` and `do_close()` callbacks. Filters carry now a
`shutdown` flags next to `connected` to keep track of the shutdown
operation.
Filters are shut down from top to bottom. If a filter is not connected,
its shutdown is skipped. Notable filters that *do* something during
shutdown are HTTP/2 and TLS. HTTP/2 sends the GOAWAY frame. TLS sends
its close notify and expects to receive a close notify from the server.
As sends and receives may EAGAIN on the network, a shutdown is often not
successful right away and needs to poll the connection's socket(s). To
facilitate this, such connections are placed on a new shutdown list
inside the connection cache.
Since managing this list requires the cooperation of a multi handle,
only the connection cache belonging to a multi handle is used. If a
connection was in another cache when being discarded, it is removed
there and added to the multi's cache. If no multi handle is available at
that time, the connection is shutdown and closed in a one-time,
best-effort attempt.
When a multi handle is destroyed, all connection still on the shutdown
list are discarded with a final shutdown attempt and close. In curl
debug builds, the environment variable `CURL_GRACEFUL_SHUTDOWN` can be
set to make this graceful with a timeout in milliseconds given by the
variable.
The shutdown list is limited to the max number of connections configured
for a multi cache. Set via CURLMOPT_MAX_TOTAL_CONNECTIONS. When the
limit is reached, the oldest connection on the shutdown list is
discarded.
- In multi_wait() and multi_waitfds(), collect all connection caches
involved (each transfer might carry its own) into a temporary list.
Let each connection cache on the list contribute sockets and
POLLIN/OUT events it's connections are waiting for.
- in multi_perform() collect the connection caches the same way and let
them peform their maintenance. This will make another non-blocking
attempt to shutdown all connections on its shutdown list.
- for event based multis (multi->socket_cb set), add the sockets and
their poll events via the callback. When `multi_socket()` is invoked
for a socket not known by an active transfer, forward this to the
multi's cache for processing. On closing a connection, remove its
socket(s) via the callback.
TLS connection filters MUST NOT send close nofity messages in their
`do_close()` implementation. The reason is that a TLS close notify
signals a success. When a connection is aborted and skips its shutdown
phase, the server needs to see a missing close notify to detect
something has gone wrong.
A graceful shutdown of FTP's data connection is performed implicitly
before regarding the upload/download as complete and continuing on the
control connection. For FTP without TLS, there is just the socket close
happening. But with TLS, the sent/received close notify signals that the
transfer is complete and healthy. Servers like `vsftpd` verify that and
reject uploads without a TLS close notify.
- added test_19_* for shutdown related tests
- test_19_01 and test_19_02 test for TCP RST packets
which happen without a graceful shutdown and should
no longer appear otherwise.
- add test_19_03 for handling shutdowns by the server
- add test_19_04 for handling shutdowns by curl
- add test_19_05 for event based shutdowny by server
- add test_30_06/07 and test_31_06/07 for shutdown checks
on FTP up- and downloads.
Closes #13976
2024-06-19 18:40:06 +08:00
|
|
|
struct curl_pollfds;
|
|
|
|
struct curl_waitfds;
|
|
|
|
struct Curl_multi;
|
|
|
|
|
|
|
|
struct connshutdowns {
|
|
|
|
struct Curl_llist conn_list; /* The connectdata to shut down */
|
|
|
|
BIT(iter_locked); /* TRUE while iterating the list */
|
|
|
|
};
|
2020-12-11 16:05:47 +08:00
|
|
|
|
2012-12-06 19:12:04 +08:00
|
|
|
struct conncache {
|
2020-09-02 18:07:44 +08:00
|
|
|
struct Curl_hash hash;
|
2017-12-02 21:27:00 +08:00
|
|
|
size_t num_conn;
|
2023-05-23 18:48:58 +08:00
|
|
|
curl_off_t next_connection_id;
|
|
|
|
curl_off_t next_easy_id;
|
2017-07-28 21:49:36 +08:00
|
|
|
struct curltime last_cleanup;
|
lib: graceful connection shutdown
When libcurl discards a connection there are two phases this may go
through: "shutdown" and "closing". If a connection is aborted, the
shutdown phase is skipped and it is closed right away.
The connection filters attached to the connection implement the phases
in their `do_shutdown()` and `do_close()` callbacks. Filters carry now a
`shutdown` flags next to `connected` to keep track of the shutdown
operation.
Filters are shut down from top to bottom. If a filter is not connected,
its shutdown is skipped. Notable filters that *do* something during
shutdown are HTTP/2 and TLS. HTTP/2 sends the GOAWAY frame. TLS sends
its close notify and expects to receive a close notify from the server.
As sends and receives may EAGAIN on the network, a shutdown is often not
successful right away and needs to poll the connection's socket(s). To
facilitate this, such connections are placed on a new shutdown list
inside the connection cache.
Since managing this list requires the cooperation of a multi handle,
only the connection cache belonging to a multi handle is used. If a
connection was in another cache when being discarded, it is removed
there and added to the multi's cache. If no multi handle is available at
that time, the connection is shutdown and closed in a one-time,
best-effort attempt.
When a multi handle is destroyed, all connection still on the shutdown
list are discarded with a final shutdown attempt and close. In curl
debug builds, the environment variable `CURL_GRACEFUL_SHUTDOWN` can be
set to make this graceful with a timeout in milliseconds given by the
variable.
The shutdown list is limited to the max number of connections configured
for a multi cache. Set via CURLMOPT_MAX_TOTAL_CONNECTIONS. When the
limit is reached, the oldest connection on the shutdown list is
discarded.
- In multi_wait() and multi_waitfds(), collect all connection caches
involved (each transfer might carry its own) into a temporary list.
Let each connection cache on the list contribute sockets and
POLLIN/OUT events it's connections are waiting for.
- in multi_perform() collect the connection caches the same way and let
them peform their maintenance. This will make another non-blocking
attempt to shutdown all connections on its shutdown list.
- for event based multis (multi->socket_cb set), add the sockets and
their poll events via the callback. When `multi_socket()` is invoked
for a socket not known by an active transfer, forward this to the
multi's cache for processing. On closing a connection, remove its
socket(s) via the callback.
TLS connection filters MUST NOT send close nofity messages in their
`do_close()` implementation. The reason is that a TLS close notify
signals a success. When a connection is aborted and skips its shutdown
phase, the server needs to see a missing close notify to detect
something has gone wrong.
A graceful shutdown of FTP's data connection is performed implicitly
before regarding the upload/download as complete and continuing on the
control connection. For FTP without TLS, there is just the socket close
happening. But with TLS, the sent/received close notify signals that the
transfer is complete and healthy. Servers like `vsftpd` verify that and
reject uploads without a TLS close notify.
- added test_19_* for shutdown related tests
- test_19_01 and test_19_02 test for TCP RST packets
which happen without a graceful shutdown and should
no longer appear otherwise.
- add test_19_03 for handling shutdowns by the server
- add test_19_04 for handling shutdowns by curl
- add test_19_05 for event based shutdowny by server
- add test_30_06/07 and test_31_06/07 for shutdown checks
on FTP up- and downloads.
Closes #13976
2024-06-19 18:40:06 +08:00
|
|
|
struct connshutdowns shutdowns;
|
2017-11-02 06:37:45 +08:00
|
|
|
/* handle used for closing cached connections */
|
|
|
|
struct Curl_easy *closure_handle;
|
lib: graceful connection shutdown
When libcurl discards a connection there are two phases this may go
through: "shutdown" and "closing". If a connection is aborted, the
shutdown phase is skipped and it is closed right away.
The connection filters attached to the connection implement the phases
in their `do_shutdown()` and `do_close()` callbacks. Filters carry now a
`shutdown` flags next to `connected` to keep track of the shutdown
operation.
Filters are shut down from top to bottom. If a filter is not connected,
its shutdown is skipped. Notable filters that *do* something during
shutdown are HTTP/2 and TLS. HTTP/2 sends the GOAWAY frame. TLS sends
its close notify and expects to receive a close notify from the server.
As sends and receives may EAGAIN on the network, a shutdown is often not
successful right away and needs to poll the connection's socket(s). To
facilitate this, such connections are placed on a new shutdown list
inside the connection cache.
Since managing this list requires the cooperation of a multi handle,
only the connection cache belonging to a multi handle is used. If a
connection was in another cache when being discarded, it is removed
there and added to the multi's cache. If no multi handle is available at
that time, the connection is shutdown and closed in a one-time,
best-effort attempt.
When a multi handle is destroyed, all connection still on the shutdown
list are discarded with a final shutdown attempt and close. In curl
debug builds, the environment variable `CURL_GRACEFUL_SHUTDOWN` can be
set to make this graceful with a timeout in milliseconds given by the
variable.
The shutdown list is limited to the max number of connections configured
for a multi cache. Set via CURLMOPT_MAX_TOTAL_CONNECTIONS. When the
limit is reached, the oldest connection on the shutdown list is
discarded.
- In multi_wait() and multi_waitfds(), collect all connection caches
involved (each transfer might carry its own) into a temporary list.
Let each connection cache on the list contribute sockets and
POLLIN/OUT events it's connections are waiting for.
- in multi_perform() collect the connection caches the same way and let
them peform their maintenance. This will make another non-blocking
attempt to shutdown all connections on its shutdown list.
- for event based multis (multi->socket_cb set), add the sockets and
their poll events via the callback. When `multi_socket()` is invoked
for a socket not known by an active transfer, forward this to the
multi's cache for processing. On closing a connection, remove its
socket(s) via the callback.
TLS connection filters MUST NOT send close nofity messages in their
`do_close()` implementation. The reason is that a TLS close notify
signals a success. When a connection is aborted and skips its shutdown
phase, the server needs to see a missing close notify to detect
something has gone wrong.
A graceful shutdown of FTP's data connection is performed implicitly
before regarding the upload/download as complete and continuing on the
control connection. For FTP without TLS, there is just the socket close
happening. But with TLS, the sent/received close notify signals that the
transfer is complete and healthy. Servers like `vsftpd` verify that and
reject uploads without a TLS close notify.
- added test_19_* for shutdown related tests
- test_19_01 and test_19_02 test for TCP RST packets
which happen without a graceful shutdown and should
no longer appear otherwise.
- add test_19_03 for handling shutdowns by the server
- add test_19_04 for handling shutdowns by curl
- add test_19_05 for event based shutdowny by server
- add test_30_06/07 and test_31_06/07 for shutdown checks
on FTP up- and downloads.
Closes #13976
2024-06-19 18:40:06 +08:00
|
|
|
struct Curl_multi *multi; /* Optional, set if cache belongs to multi */
|
2012-12-06 19:12:04 +08:00
|
|
|
};
|
|
|
|
|
2015-05-18 14:56:29 +08:00
|
|
|
#define BUNDLE_NO_MULTIUSE -1
|
|
|
|
#define BUNDLE_UNKNOWN 0 /* initial value */
|
|
|
|
#define BUNDLE_MULTIPLEX 2
|
|
|
|
|
2024-05-20 20:21:05 +08:00
|
|
|
#ifdef DEBUGBUILD
|
2019-12-09 18:53:54 +08:00
|
|
|
/* the debug versions of these macros make extra certain that the lock is
|
|
|
|
never doubly locked or unlocked */
|
2020-12-26 22:43:25 +08:00
|
|
|
#define CONNCACHE_LOCK(x) \
|
|
|
|
do { \
|
|
|
|
if((x)->share) { \
|
|
|
|
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, \
|
|
|
|
CURL_LOCK_ACCESS_SINGLE); \
|
|
|
|
DEBUGASSERT(!(x)->state.conncache_lock); \
|
|
|
|
(x)->state.conncache_lock = TRUE; \
|
|
|
|
} \
|
|
|
|
} while(0)
|
2019-12-09 18:53:54 +08:00
|
|
|
|
2020-12-26 22:43:25 +08:00
|
|
|
#define CONNCACHE_UNLOCK(x) \
|
|
|
|
do { \
|
|
|
|
if((x)->share) { \
|
|
|
|
DEBUGASSERT((x)->state.conncache_lock); \
|
|
|
|
(x)->state.conncache_lock = FALSE; \
|
|
|
|
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \
|
|
|
|
} \
|
|
|
|
} while(0)
|
2019-12-09 18:53:54 +08:00
|
|
|
#else
|
2020-04-27 06:33:21 +08:00
|
|
|
#define CONNCACHE_LOCK(x) if((x)->share) \
|
2019-12-09 18:53:54 +08:00
|
|
|
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
|
2020-04-27 06:33:21 +08:00
|
|
|
#define CONNCACHE_UNLOCK(x) if((x)->share) \
|
2019-12-09 18:53:54 +08:00
|
|
|
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
|
|
|
|
#endif
|
|
|
|
|
2015-05-13 05:06:11 +08:00
|
|
|
struct connectbundle {
|
2015-05-18 14:56:29 +08:00
|
|
|
int multiuse; /* supports multi-use */
|
2015-05-13 05:06:11 +08:00
|
|
|
size_t num_connections; /* Number of connections in the bundle */
|
2020-09-02 18:06:20 +08:00
|
|
|
struct Curl_llist conn_list; /* The connectdata members of the bundle */
|
2015-05-13 05:06:11 +08:00
|
|
|
};
|
|
|
|
|
lib: graceful connection shutdown
When libcurl discards a connection there are two phases this may go
through: "shutdown" and "closing". If a connection is aborted, the
shutdown phase is skipped and it is closed right away.
The connection filters attached to the connection implement the phases
in their `do_shutdown()` and `do_close()` callbacks. Filters carry now a
`shutdown` flags next to `connected` to keep track of the shutdown
operation.
Filters are shut down from top to bottom. If a filter is not connected,
its shutdown is skipped. Notable filters that *do* something during
shutdown are HTTP/2 and TLS. HTTP/2 sends the GOAWAY frame. TLS sends
its close notify and expects to receive a close notify from the server.
As sends and receives may EAGAIN on the network, a shutdown is often not
successful right away and needs to poll the connection's socket(s). To
facilitate this, such connections are placed on a new shutdown list
inside the connection cache.
Since managing this list requires the cooperation of a multi handle,
only the connection cache belonging to a multi handle is used. If a
connection was in another cache when being discarded, it is removed
there and added to the multi's cache. If no multi handle is available at
that time, the connection is shutdown and closed in a one-time,
best-effort attempt.
When a multi handle is destroyed, all connection still on the shutdown
list are discarded with a final shutdown attempt and close. In curl
debug builds, the environment variable `CURL_GRACEFUL_SHUTDOWN` can be
set to make this graceful with a timeout in milliseconds given by the
variable.
The shutdown list is limited to the max number of connections configured
for a multi cache. Set via CURLMOPT_MAX_TOTAL_CONNECTIONS. When the
limit is reached, the oldest connection on the shutdown list is
discarded.
- In multi_wait() and multi_waitfds(), collect all connection caches
involved (each transfer might carry its own) into a temporary list.
Let each connection cache on the list contribute sockets and
POLLIN/OUT events it's connections are waiting for.
- in multi_perform() collect the connection caches the same way and let
them peform their maintenance. This will make another non-blocking
attempt to shutdown all connections on its shutdown list.
- for event based multis (multi->socket_cb set), add the sockets and
their poll events via the callback. When `multi_socket()` is invoked
for a socket not known by an active transfer, forward this to the
multi's cache for processing. On closing a connection, remove its
socket(s) via the callback.
TLS connection filters MUST NOT send close nofity messages in their
`do_close()` implementation. The reason is that a TLS close notify
signals a success. When a connection is aborted and skips its shutdown
phase, the server needs to see a missing close notify to detect
something has gone wrong.
A graceful shutdown of FTP's data connection is performed implicitly
before regarding the upload/download as complete and continuing on the
control connection. For FTP without TLS, there is just the socket close
happening. But with TLS, the sent/received close notify signals that the
transfer is complete and healthy. Servers like `vsftpd` verify that and
reject uploads without a TLS close notify.
- added test_19_* for shutdown related tests
- test_19_01 and test_19_02 test for TCP RST packets
which happen without a graceful shutdown and should
no longer appear otherwise.
- add test_19_03 for handling shutdowns by the server
- add test_19_04 for handling shutdowns by curl
- add test_19_05 for event based shutdowny by server
- add test_30_06/07 and test_31_06/07 for shutdown checks
on FTP up- and downloads.
Closes #13976
2024-06-19 18:40:06 +08:00
|
|
|
/* Init the cache, pass multi only if cache is owned by it.
|
|
|
|
* returns 1 on error, 0 is fine.
|
|
|
|
*/
|
|
|
|
int Curl_conncache_init(struct conncache *,
|
|
|
|
struct Curl_multi *multi,
|
|
|
|
size_t size);
|
2012-12-06 19:12:04 +08:00
|
|
|
void Curl_conncache_destroy(struct conncache *connc);
|
|
|
|
|
2015-03-11 18:54:22 +08:00
|
|
|
/* return the correct bundle, to a host or a proxy */
|
2021-01-18 18:56:50 +08:00
|
|
|
struct connectbundle *Curl_conncache_find_bundle(struct Curl_easy *data,
|
|
|
|
struct connectdata *conn,
|
2022-04-25 22:25:42 +08:00
|
|
|
struct conncache *connc);
|
2017-12-02 21:27:00 +08:00
|
|
|
/* returns number of connections currently held in the connection cache */
|
|
|
|
size_t Curl_conncache_size(struct Curl_easy *data);
|
2012-12-06 19:12:04 +08:00
|
|
|
|
2019-12-09 18:53:54 +08:00
|
|
|
bool Curl_conncache_return_conn(struct Curl_easy *data,
|
|
|
|
struct connectdata *conn);
|
2021-01-18 18:56:50 +08:00
|
|
|
CURLcode Curl_conncache_add_conn(struct Curl_easy *data) WARN_UNUSED_RESULT;
|
2018-12-20 23:39:02 +08:00
|
|
|
void Curl_conncache_remove_conn(struct Curl_easy *data,
|
|
|
|
struct connectdata *conn,
|
2017-12-02 21:27:00 +08:00
|
|
|
bool lock);
|
|
|
|
bool Curl_conncache_foreach(struct Curl_easy *data,
|
2017-11-02 06:37:45 +08:00
|
|
|
struct conncache *connc,
|
2012-12-06 19:12:04 +08:00
|
|
|
void *param,
|
2021-01-09 00:58:15 +08:00
|
|
|
int (*func)(struct Curl_easy *data,
|
|
|
|
struct connectdata *conn,
|
2012-12-12 03:13:29 +08:00
|
|
|
void *param));
|
2012-12-06 19:12:04 +08:00
|
|
|
|
|
|
|
struct connectdata *
|
|
|
|
Curl_conncache_find_first_connection(struct conncache *connc);
|
|
|
|
|
2017-11-02 06:37:45 +08:00
|
|
|
struct connectdata *
|
2017-12-02 21:27:00 +08:00
|
|
|
Curl_conncache_extract_bundle(struct Curl_easy *data,
|
|
|
|
struct connectbundle *bundle);
|
|
|
|
struct connectdata *
|
|
|
|
Curl_conncache_extract_oldest(struct Curl_easy *data);
|
2017-11-02 06:37:45 +08:00
|
|
|
void Curl_conncache_close_all_connections(struct conncache *connc);
|
2012-12-06 19:12:04 +08:00
|
|
|
void Curl_conncache_print(struct conncache *connc);
|
|
|
|
|
lib: graceful connection shutdown
When libcurl discards a connection there are two phases this may go
through: "shutdown" and "closing". If a connection is aborted, the
shutdown phase is skipped and it is closed right away.
The connection filters attached to the connection implement the phases
in their `do_shutdown()` and `do_close()` callbacks. Filters carry now a
`shutdown` flags next to `connected` to keep track of the shutdown
operation.
Filters are shut down from top to bottom. If a filter is not connected,
its shutdown is skipped. Notable filters that *do* something during
shutdown are HTTP/2 and TLS. HTTP/2 sends the GOAWAY frame. TLS sends
its close notify and expects to receive a close notify from the server.
As sends and receives may EAGAIN on the network, a shutdown is often not
successful right away and needs to poll the connection's socket(s). To
facilitate this, such connections are placed on a new shutdown list
inside the connection cache.
Since managing this list requires the cooperation of a multi handle,
only the connection cache belonging to a multi handle is used. If a
connection was in another cache when being discarded, it is removed
there and added to the multi's cache. If no multi handle is available at
that time, the connection is shutdown and closed in a one-time,
best-effort attempt.
When a multi handle is destroyed, all connection still on the shutdown
list are discarded with a final shutdown attempt and close. In curl
debug builds, the environment variable `CURL_GRACEFUL_SHUTDOWN` can be
set to make this graceful with a timeout in milliseconds given by the
variable.
The shutdown list is limited to the max number of connections configured
for a multi cache. Set via CURLMOPT_MAX_TOTAL_CONNECTIONS. When the
limit is reached, the oldest connection on the shutdown list is
discarded.
- In multi_wait() and multi_waitfds(), collect all connection caches
involved (each transfer might carry its own) into a temporary list.
Let each connection cache on the list contribute sockets and
POLLIN/OUT events it's connections are waiting for.
- in multi_perform() collect the connection caches the same way and let
them peform their maintenance. This will make another non-blocking
attempt to shutdown all connections on its shutdown list.
- for event based multis (multi->socket_cb set), add the sockets and
their poll events via the callback. When `multi_socket()` is invoked
for a socket not known by an active transfer, forward this to the
multi's cache for processing. On closing a connection, remove its
socket(s) via the callback.
TLS connection filters MUST NOT send close nofity messages in their
`do_close()` implementation. The reason is that a TLS close notify
signals a success. When a connection is aborted and skips its shutdown
phase, the server needs to see a missing close notify to detect
something has gone wrong.
A graceful shutdown of FTP's data connection is performed implicitly
before regarding the upload/download as complete and continuing on the
control connection. For FTP without TLS, there is just the socket close
happening. But with TLS, the sent/received close notify signals that the
transfer is complete and healthy. Servers like `vsftpd` verify that and
reject uploads without a TLS close notify.
- added test_19_* for shutdown related tests
- test_19_01 and test_19_02 test for TCP RST packets
which happen without a graceful shutdown and should
no longer appear otherwise.
- add test_19_03 for handling shutdowns by the server
- add test_19_04 for handling shutdowns by curl
- add test_19_05 for event based shutdowny by server
- add test_30_06/07 and test_31_06/07 for shutdown checks
on FTP up- and downloads.
Closes #13976
2024-06-19 18:40:06 +08:00
|
|
|
/**
|
|
|
|
* Tear down the connection. If `aborted` is FALSE, the connection
|
|
|
|
* will be shut down first before discarding. If the shutdown
|
|
|
|
* is not immediately complete, the connection
|
2024-07-01 22:47:21 +08:00
|
|
|
* will be placed into the cache is shutdown queue.
|
lib: graceful connection shutdown
When libcurl discards a connection there are two phases this may go
through: "shutdown" and "closing". If a connection is aborted, the
shutdown phase is skipped and it is closed right away.
The connection filters attached to the connection implement the phases
in their `do_shutdown()` and `do_close()` callbacks. Filters carry now a
`shutdown` flags next to `connected` to keep track of the shutdown
operation.
Filters are shut down from top to bottom. If a filter is not connected,
its shutdown is skipped. Notable filters that *do* something during
shutdown are HTTP/2 and TLS. HTTP/2 sends the GOAWAY frame. TLS sends
its close notify and expects to receive a close notify from the server.
As sends and receives may EAGAIN on the network, a shutdown is often not
successful right away and needs to poll the connection's socket(s). To
facilitate this, such connections are placed on a new shutdown list
inside the connection cache.
Since managing this list requires the cooperation of a multi handle,
only the connection cache belonging to a multi handle is used. If a
connection was in another cache when being discarded, it is removed
there and added to the multi's cache. If no multi handle is available at
that time, the connection is shutdown and closed in a one-time,
best-effort attempt.
When a multi handle is destroyed, all connection still on the shutdown
list are discarded with a final shutdown attempt and close. In curl
debug builds, the environment variable `CURL_GRACEFUL_SHUTDOWN` can be
set to make this graceful with a timeout in milliseconds given by the
variable.
The shutdown list is limited to the max number of connections configured
for a multi cache. Set via CURLMOPT_MAX_TOTAL_CONNECTIONS. When the
limit is reached, the oldest connection on the shutdown list is
discarded.
- In multi_wait() and multi_waitfds(), collect all connection caches
involved (each transfer might carry its own) into a temporary list.
Let each connection cache on the list contribute sockets and
POLLIN/OUT events it's connections are waiting for.
- in multi_perform() collect the connection caches the same way and let
them peform their maintenance. This will make another non-blocking
attempt to shutdown all connections on its shutdown list.
- for event based multis (multi->socket_cb set), add the sockets and
their poll events via the callback. When `multi_socket()` is invoked
for a socket not known by an active transfer, forward this to the
multi's cache for processing. On closing a connection, remove its
socket(s) via the callback.
TLS connection filters MUST NOT send close nofity messages in their
`do_close()` implementation. The reason is that a TLS close notify
signals a success. When a connection is aborted and skips its shutdown
phase, the server needs to see a missing close notify to detect
something has gone wrong.
A graceful shutdown of FTP's data connection is performed implicitly
before regarding the upload/download as complete and continuing on the
control connection. For FTP without TLS, there is just the socket close
happening. But with TLS, the sent/received close notify signals that the
transfer is complete and healthy. Servers like `vsftpd` verify that and
reject uploads without a TLS close notify.
- added test_19_* for shutdown related tests
- test_19_01 and test_19_02 test for TCP RST packets
which happen without a graceful shutdown and should
no longer appear otherwise.
- add test_19_03 for handling shutdowns by the server
- add test_19_04 for handling shutdowns by curl
- add test_19_05 for event based shutdowny by server
- add test_30_06/07 and test_31_06/07 for shutdown checks
on FTP up- and downloads.
Closes #13976
2024-06-19 18:40:06 +08:00
|
|
|
*/
|
|
|
|
void Curl_conncache_disconnect(struct Curl_easy *data,
|
|
|
|
struct connectdata *conn,
|
|
|
|
bool aborted);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add sockets and POLLIN/OUT flags for connections handled by the cache.
|
|
|
|
*/
|
|
|
|
CURLcode Curl_conncache_add_pollfds(struct conncache *connc,
|
|
|
|
struct curl_pollfds *cpfds);
|
|
|
|
CURLcode Curl_conncache_add_waitfds(struct conncache *connc,
|
|
|
|
struct curl_waitfds *cwfds);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Perform maintenance on connections in the cache. Specifically,
|
|
|
|
* progress the shutdown of connections in the queue.
|
|
|
|
*/
|
|
|
|
void Curl_conncache_multi_perform(struct Curl_multi *multi);
|
|
|
|
|
|
|
|
void Curl_conncache_multi_socket(struct Curl_multi *multi,
|
|
|
|
curl_socket_t s, int ev_bitmask);
|
|
|
|
void Curl_conncache_multi_close_all(struct Curl_multi *multi);
|
|
|
|
|
2012-12-11 00:04:13 +08:00
|
|
|
#endif /* HEADER_CURL_CONNCACHE_H */
|