mirror of
https://github.com/curl/curl.git
synced 2026-07-30 23:18:08 +03:00
conncontrol: reuse handling
Add protocol handler flag `PROTOPT_CONN_REUSE` to indicate that the protocol allows reusing connections for other tranfers. Add that to all handlers that support it. Create connections with `conn->bits.close = FALSE` and remove all the `connkeep()` calls in protocol handlers setup/connect implementations. `PROTOPT_CONN_REUSE` assures that the default behaviour applies at the end of a transfer without need to juggle the close bit. `conn->bits.close` now serves as an additional indication that a connection cannot be reused. Only protocol handles that allow reuse need to set it to override the default behaviour. Remove all `connclose()` and `connkeep()` calls from connection filters. Filters should not modify connection flags. They are supposed to run in eyeballing situations where a filter is just one of many determining the outcome. Fix http response header handling to only honour `Connection: close` for HTTP/1.x versions. Closes #19333
This commit is contained in:
parent
a9e7a027ed
commit
feea968512
21 changed files with 93 additions and 114 deletions
70
lib/multi.c
70
lib/multi.c
|
|
@ -547,6 +547,47 @@ struct multi_done_ctx {
|
|||
BIT(premature);
|
||||
};
|
||||
|
||||
static bool multi_conn_should_close(struct connectdata *conn,
|
||||
struct Curl_easy *data,
|
||||
bool premature)
|
||||
{
|
||||
/* if conn->bits.close is TRUE, it means that the connection should be
|
||||
closed in spite of everything else. */
|
||||
if(conn->bits.close)
|
||||
return TRUE;
|
||||
|
||||
/* if data->set.reuse_forbid is TRUE, it means the libcurl client has
|
||||
forced us to close this connection. This is ignored for requests taking
|
||||
place in a NTLM/NEGOTIATE authentication handshake. */
|
||||
if(data->set.reuse_forbid
|
||||
#ifdef USE_NTLM
|
||||
&& !(conn->http_ntlm_state == NTLMSTATE_TYPE2 ||
|
||||
conn->proxy_ntlm_state == NTLMSTATE_TYPE2)
|
||||
#endif
|
||||
#ifdef USE_SPNEGO
|
||||
&& !(conn->http_negotiate_state == GSS_AUTHRECV ||
|
||||
conn->proxy_negotiate_state == GSS_AUTHRECV)
|
||||
#endif
|
||||
)
|
||||
return TRUE;
|
||||
|
||||
/* Unless this connection is for a "connect-only" transfer, it
|
||||
* needs to be closed if the protocol handler does not support reuse. */
|
||||
if(!data->set.connect_only && conn->handler &&
|
||||
!(conn->handler->flags & PROTOPT_CONN_REUSE))
|
||||
return TRUE;
|
||||
|
||||
/* if premature is TRUE, it means this connection was said to be DONE before
|
||||
the entire request operation is complete and thus we cannot know in what
|
||||
state it is for reusing, so we are forced to close it. In a perfect world
|
||||
we can add code that keep track of if we really must close it here or not,
|
||||
but currently we have no such detail knowledge. */
|
||||
if(premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void multi_done_locked(struct connectdata *conn,
|
||||
struct Curl_easy *data,
|
||||
void *userdata)
|
||||
|
|
@ -587,32 +628,7 @@ static void multi_done_locked(struct connectdata *conn,
|
|||
Curl_resolv_unlink(data, &data->state.dns[1]);
|
||||
Curl_dnscache_prune(data);
|
||||
|
||||
/* if data->set.reuse_forbid is TRUE, it means the libcurl client has
|
||||
forced us to close this connection. This is ignored for requests taking
|
||||
place in a NTLM/NEGOTIATE authentication handshake
|
||||
|
||||
if conn->bits.close is TRUE, it means that the connection should be
|
||||
closed in spite of all our efforts to be nice, due to protocol
|
||||
restrictions in our or the server's end
|
||||
|
||||
if premature is TRUE, it means this connection was said to be DONE before
|
||||
the entire request operation is complete and thus we cannot know in what
|
||||
state it is for reusing, so we are forced to close it. In a perfect world
|
||||
we can add code that keep track of if we really must close it here or not,
|
||||
but currently we have no such detail knowledge.
|
||||
*/
|
||||
|
||||
if((data->set.reuse_forbid
|
||||
#ifdef USE_NTLM
|
||||
&& !(conn->http_ntlm_state == NTLMSTATE_TYPE2 ||
|
||||
conn->proxy_ntlm_state == NTLMSTATE_TYPE2)
|
||||
#endif
|
||||
#ifdef USE_SPNEGO
|
||||
&& !(conn->http_negotiate_state == GSS_AUTHRECV ||
|
||||
conn->proxy_negotiate_state == GSS_AUTHRECV)
|
||||
#endif
|
||||
) || conn->bits.close
|
||||
|| (mdctx->premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))) {
|
||||
if(multi_conn_should_close(conn, data, mdctx->premature)) {
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
CURL_TRC_M(data, "multi_done, terminating conn #%" FMT_OFF_T " to %s:%d, "
|
||||
"forbid=%d, close=%d, premature=%d, conn_multiplex=%d",
|
||||
|
|
@ -2127,8 +2143,6 @@ static CURLMcode state_do(struct Curl_easy *data,
|
|||
}
|
||||
|
||||
if(data->set.connect_only && !data->set.connect_only_ws) {
|
||||
/* keep connection open for application to use the socket */
|
||||
connkeep(data->conn, "CONNECT_ONLY");
|
||||
multistate(data, MSTATE_DONE);
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue