]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
conncontrol: reuse handling
authorStefan Eissing <stefan@eissing.org>
Mon, 3 Nov 2025 12:12:50 +0000 (13:12 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 27 Nov 2025 13:30:14 +0000 (14:30 +0100)
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

21 files changed:
lib/cf-h1-proxy.c
lib/cf-h2-proxy.c
lib/conncache.c
lib/ftp.c
lib/http.c
lib/http2.c
lib/imap.c
lib/multi.c
lib/openldap.c
lib/pop3.c
lib/rtsp.c
lib/smb.c
lib/smtp.c
lib/url.c
lib/urldata.h
lib/vquic/curl_ngtcp2.c
lib/vquic/curl_osslq.c
lib/vquic/curl_quiche.c
lib/vssh/libssh.c
lib/vssh/libssh2.c
lib/vtls/openssl.c

index 985500f23e063bd534ba784dd56834d83f83f5ab..e496d7634dceb20fb2a8986d4a9d472309d2a330 100644 (file)
@@ -127,7 +127,6 @@ static CURLcode tunnel_init(struct Curl_cfilter *cf,
   Curl_httpchunk_init(data, &ts->ch, TRUE);
 
   *pts = ts;
-  connkeep(cf->conn, "HTTP proxy CONNECT");
   return tunnel_reinit(cf, data, ts);
 }
 
@@ -591,7 +590,6 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
           CURL_TRC_CF(data, cf, "CONNECT need to close+open");
           infof(data, "Connect me again please");
           Curl_conn_cf_close(cf, data);
-          connkeep(conn, "HTTP proxy CONNECT");
           result = Curl_conn_cf_connect(cf->next, data, &done);
           goto out;
         }
@@ -612,8 +610,6 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
   if(data->info.httpproxycode/100 != 2) {
     /* a non-2xx response and we have no next URL to try. */
     Curl_safefree(data->req.newurl);
-    /* failure, close this connection to avoid reuse */
-    streamclose(conn, "proxy CONNECT failure");
     h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
     failf(data, "CONNECT tunnel failed, response %d", data->req.httpcode);
     return CURLE_RECV_ERROR;
index b963bb718ce966675dc275702333ba9fbd9986bc..89bc7cc23f4804125dea6437bdc54de9c2aa1ae2 100644 (file)
@@ -488,10 +488,6 @@ static CURLcode proxy_h2_progress_ingress(struct Curl_cfilter *cf,
       return result;
   }
 
-  if(ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) {
-    connclose(cf->conn, "GOAWAY received");
-  }
-
   return CURLE_OK;
 }
 
@@ -1265,7 +1261,7 @@ static CURLcode h2_handle_tunnel_close(struct Curl_cfilter *cf,
   if(ctx->tunnel.error == NGHTTP2_REFUSED_STREAM) {
     CURL_TRC_CF(data, cf, "[%d] REFUSED_STREAM, try again on a new "
                 "connection", ctx->tunnel.stream_id);
-    connclose(cf->conn, "REFUSED_STREAM"); /* do not use this anymore */
+    failf(data, "proxy server refused HTTP/2 stream");
     return CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
   }
   else if(ctx->tunnel.error != NGHTTP2_NO_ERROR) {
index 275e490f23e83a616553876a33f5367a30db7bfe..9d3b69bec356bbb0a9fffdb3200afe850a55b938 100644 (file)
@@ -220,7 +220,6 @@ void Curl_cpool_destroy(struct cpool *cpool)
     while(conn) {
       cpool_remove_conn(cpool, conn);
       sigpipe_apply(cpool->idata, &pipe_st);
-      connclose(conn, "kill all");
       cpool_discard_conn(cpool, cpool->idata, conn, FALSE);
       conn = cpool_get_first(cpool);
     }
index c289581fd5a48fdf91ad85adfffe58a2e48c58fe..ce400122682314f84f704fda201207086233fd72 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -270,7 +270,8 @@ const struct Curl_handler Curl_handler_ftp = {
   CURLPROTO_FTP,                   /* family */
   PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD |
   PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP |
-  PROTOPT_WILDCARD | PROTOPT_SSL_REUSE /* flags */
+  PROTOPT_WILDCARD | PROTOPT_SSL_REUSE |
+  PROTOPT_CONN_REUSE /* flags */
 };
 
 
@@ -302,7 +303,8 @@ const struct Curl_handler Curl_handler_ftps = {
   CURLPROTO_FTPS,                  /* protocol */
   CURLPROTO_FTP,                   /* family */
   PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
-  PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD /* flags */
+  PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD |
+  PROTOPT_CONN_REUSE /* flags */
 };
 #endif
 
@@ -3183,9 +3185,6 @@ static CURLcode ftp_connect(struct Curl_easy *data,
   if(!ftpc)
     return CURLE_FAILED_INIT;
   pp = &ftpc->pp;
-  /* We always support persistent connections on ftp */
-  connkeep(conn, "FTP default");
-
   PINGPONG_SETUP(pp, ftp_pp_statemachine, ftp_endofresp);
 
   if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
index 144a898ea0ebdc97ca683a6a6934f82f58b2685d..0319be3b657b9c1b3450002aaa0e86f32141d9c9 100644 (file)
@@ -142,7 +142,8 @@ const struct Curl_handler Curl_handler_http = {
   CURLPROTO_HTTP,                       /* protocol */
   CURLPROTO_HTTP,                       /* family */
   PROTOPT_CREDSPERREQUEST |             /* flags */
-  PROTOPT_USERPWDCTRL
+  PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE
+
 };
 
 #ifdef USE_SSL
@@ -172,7 +173,7 @@ const struct Curl_handler Curl_handler_https = {
   CURLPROTO_HTTPS,                      /* protocol */
   CURLPROTO_HTTP,                       /* family */
   PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN | /* flags */
-  PROTOPT_USERPWDCTRL
+  PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE
 };
 
 #endif
@@ -220,7 +221,6 @@ CURLcode Curl_http_setup_conn(struct Curl_easy *data,
 {
   /* allocate the HTTP-specific struct for the Curl_easy, only to survive
      during this request */
-  connkeep(conn, "HTTP default");
   if(data->state.http_neg.wanted == CURL_HTTP_V3x) {
     /* only HTTP/3, needs to work */
     CURLcode result = Curl_conn_may_http3(data, conn, conn->transport_wanted);
@@ -1548,12 +1548,6 @@ Curl_compareheader(const char *headerline, /* line to check */
  */
 CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
 {
-  struct connectdata *conn = data->conn;
-
-  /* We default to persistent connections. We set this already in this connect
-     function to make the reuse checks properly be able to check this bit. */
-  connkeep(conn, "HTTP default");
-
   return Curl_conn_connect(data, FIRSTSOCKET, FALSE, done);
 }
 
@@ -3257,14 +3251,15 @@ static CURLcode http_header_c(struct Curl_easy *data,
     }
     return CURLE_OK;
   }
-  if(HD_IS_AND_SAYS(hd, hdlen, "Connection:", "close")) {
+  if((k->httpversion < 20) &&
+     HD_IS_AND_SAYS(hd, hdlen, "Connection:", "close")) {
     /*
      * [RFC 2616, section 8.1.2.1]
      * "Connection: close" is HTTP/1.1 language and means that
      * the connection will close when this request has been
      * served.
      */
-    streamclose(conn, "Connection: close used");
+    connclose(conn, "Connection: close used");
     return CURLE_OK;
   }
   if((k->httpversion == 10) &&
index 7b94930a21a7cb7d501dc8154da7d3903d7493da..4f5f5ea52dd30a37b90b12f6b252b672990add41 100644 (file)
@@ -2071,7 +2071,7 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
   size_t nread;
 
   if(should_close_session(ctx)) {
-    CURL_TRC_CF(data, cf, "progress ingress, session is closed");
+    CURL_TRC_CF(data, cf, "[0] ingress: session is closed");
     return CURLE_HTTP2;
   }
 
@@ -2128,15 +2128,16 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
     result = h2_process_pending_input(cf, data);
     if(result)
       return result;
-    CURL_TRC_CF(data, cf, "[0] progress ingress: inbufg=%zu",
+    CURL_TRC_CF(data, cf, "[0] ingress: nw-in buffered %zu",
                 Curl_bufq_len(&ctx->inbufq));
   }
 
   if(ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) {
-    connclose(cf->conn, "GOAWAY received");
+    connclose(cf->conn, ctx->rcvd_goaway ? "server closed with GOAWAY" :
+              "server closed abruptly");
   }
 
-  CURL_TRC_CF(data, cf, "[0] progress ingress: done");
+  CURL_TRC_CF(data, cf, "[0] ingress: done");
   return CURLE_OK;
 }
 
index 181b0d7009d6bc270ba4af79f242c80f9803bd75..af9b124d1e7230523e0865482711e01f73fe41aa 100644 (file)
@@ -210,9 +210,9 @@ const struct Curl_handler Curl_handler_imap = {
   PORT_IMAP,                        /* defport */
   CURLPROTO_IMAP,                   /* protocol */
   CURLPROTO_IMAP,                   /* family */
-  PROTOPT_CLOSEACTION             /* flags */
-  PROTOPT_URLOPTIONS|
-  PROTOPT_SSL_REUSE
+  PROTOPT_CLOSEACTION |             /* flags */
+  PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE |
+  PROTOPT_CONN_REUSE
 };
 
 #ifdef USE_SSL
@@ -243,7 +243,7 @@ const struct Curl_handler Curl_handler_imaps = {
   CURLPROTO_IMAPS,                  /* protocol */
   CURLPROTO_IMAP,                   /* family */
   PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */
-  PROTOPT_URLOPTIONS
+  PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE
 };
 #endif
 
@@ -1680,9 +1680,6 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done)
   if(!imapc)
     return CURLE_FAILED_INIT;
 
-  /* We always support persistent connections in IMAP */
-  connkeep(data->conn, "IMAP default");
-
   /* Parse the URL options */
   result = imap_parse_url_options(data->conn, imapc);
   if(result)
index 57c574a681765a0ced6a6d25224057f94fe59464..f7265a94a9ece6c3a372d9c0a5125573e0764aca 100644 (file)
@@ -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;
   }
index 9d6174defe3757754e3892e6a7773b0e8ad81164..41419df21b2003eee94454d0b041b3d31fd775b8 100644 (file)
@@ -139,7 +139,8 @@ const struct Curl_handler Curl_handler_ldap = {
   PORT_LDAP,                            /* defport */
   CURLPROTO_LDAP,                       /* protocol */
   CURLPROTO_LDAP,                       /* family */
-  PROTOPT_SSL_REUSE                     /* flags */
+  PROTOPT_SSL_REUSE |                   /* flags */
+  PROTOPT_CONN_REUSE
 };
 
 #ifdef USE_SSL
@@ -169,7 +170,8 @@ const struct Curl_handler Curl_handler_ldaps = {
   PORT_LDAPS,                           /* defport */
   CURLPROTO_LDAPS,                      /* protocol */
   CURLPROTO_LDAP,                       /* family */
-  PROTOPT_SSL                           /* flags */
+  PROTOPT_SSL |                         /* flags */
+  PROTOPT_CONN_REUSE
 };
 #endif
 
@@ -992,7 +994,6 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done)
 
   if(!li)
     return CURLE_FAILED_INIT;
-  connkeep(conn, "OpenLDAP do");
 
   infof(data, "LDAP local: %s", data->state.url);
 
index 05203c1a074e66b9f793c92158b4df7308845a53..503f4ecb2bd5430d4b119426494552644ce9f44f 100644 (file)
@@ -200,7 +200,8 @@ const struct Curl_handler Curl_handler_pop3 = {
   CURLPROTO_POP3,                   /* protocol */
   CURLPROTO_POP3,                   /* family */
   PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
-  PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE
+  PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE |
+  PROTOPT_CONN_REUSE
 };
 
 #ifdef USE_SSL
@@ -230,8 +231,9 @@ const struct Curl_handler Curl_handler_pop3s = {
   PORT_POP3S,                       /* defport */
   CURLPROTO_POP3S,                  /* protocol */
   CURLPROTO_POP3,                   /* family */
-  PROTOPT_CLOSEACTION | PROTOPT_SSL
-  | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */
+  PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */
+  PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS |
+  PROTOPT_CONN_REUSE
 };
 #endif
 
@@ -1295,9 +1297,6 @@ static CURLcode pop3_connect(struct Curl_easy *data, bool *done)
   if(!pop3c)
     return CURLE_FAILED_INIT;
 
-  /* We always support persistent connections in POP3 */
-  connkeep(conn, "POP3 default");
-
   PINGPONG_SETUP(pp, pop3_statemachine, pop3_endofresp);
 
   /* Set the default preferred authentication type and mechanism */
index b4b3d6dd556d6b98df21be4a61d82d78a4e1c4da..dd49ebc42b4da67aec8641ec585d6756793087dd 100644 (file)
@@ -152,7 +152,7 @@ const struct Curl_handler Curl_handler_rtsp = {
   PORT_RTSP,                            /* defport */
   CURLPROTO_RTSP,                       /* protocol */
   CURLPROTO_RTSP,                       /* family */
-  PROTOPT_NONE                          /* flags */
+  PROTOPT_CONN_REUSE                    /* flags */
 };
 
 #define MAX_RTP_BUFFERSIZE 1000000 /* arbitrary */
index 4ef35c295d152435cab48ec58e9931376fbca0ca..e5fca3ec0bef73778247d3c5765d2116857d4e9f 100644 (file)
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -329,7 +329,7 @@ const struct Curl_handler Curl_handler_smb = {
   PORT_SMB,                             /* defport */
   CURLPROTO_SMB,                        /* protocol */
   CURLPROTO_SMB,                        /* family */
-  PROTOPT_NONE                          /* flags */
+  PROTOPT_CONN_REUSE                    /* flags */
 };
 
 #ifdef USE_SSL
@@ -358,7 +358,7 @@ const struct Curl_handler Curl_handler_smbs = {
   PORT_SMBS,                            /* defport */
   CURLPROTO_SMBS,                       /* protocol */
   CURLPROTO_SMB,                        /* family */
-  PROTOPT_SSL                           /* flags */
+  PROTOPT_SSL | PROTOPT_CONN_REUSE      /* flags */
 };
 #endif
 
@@ -513,9 +513,6 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done)
   if(!smbc->send_buf)
     return CURLE_OUT_OF_MEMORY;
 
-  /* Multiple requests are allowed with this connection */
-  connkeep(conn, "SMB default");
-
   /* Parse the username, domain, and password */
   slash = strchr(conn->user, '/');
   if(!slash)
index af4676dc182d7173f210c2ab851ded36fb06b460..eca27f1465252efc17e678bf1040869ee5b1300e 100644 (file)
@@ -205,7 +205,8 @@ const struct Curl_handler Curl_handler_smtp = {
   CURLPROTO_SMTP,                   /* protocol */
   CURLPROTO_SMTP,                   /* family */
   PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
-  PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE
+  PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE |
+  PROTOPT_CONN_REUSE
 };
 
 #ifdef USE_SSL
@@ -235,8 +236,9 @@ const struct Curl_handler Curl_handler_smtps = {
   PORT_SMTPS,                       /* defport */
   CURLPROTO_SMTPS,                  /* protocol */
   CURLPROTO_SMTP,                   /* family */
-  PROTOPT_CLOSEACTION | PROTOPT_SSL
-  | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */
+  PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */
+  PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS |
+  PROTOPT_CONN_REUSE
 };
 #endif
 
@@ -1440,9 +1442,6 @@ static CURLcode smtp_connect(struct Curl_easy *data, bool *done)
   if(!smtpc)
     return CURLE_FAILED_INIT;
 
-  /* We always support persistent connections in SMTP */
-  connkeep(data->conn, "SMTP default");
-
   PINGPONG_SETUP(&smtpc->pp, smtp_pp_statemachine, smtp_endofresp);
 
   /* Initialize the SASL storage */
index 8b3f7f5ab7388da6f4c363c6a73ee04473b12205..b6a60feb38b2500876e5fd47e6080298cbaa812c 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -1364,11 +1364,6 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->connection_id = -1;    /* no ID */
   conn->remote_port = -1; /* unknown at this point */
 
-  /* Default protocol-independent behavior does not support persistent
-     connections, so we set this to force-close. Protocols that support
-     this need to set this to FALSE in their "curl_do" functions. */
-  connclose(conn, "Default to force-close");
-
   /* Store creation time to help future close decision making */
   conn->created = curlx_now();
 
@@ -1428,6 +1423,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
 #ifdef HAVE_GSSAPI
   conn->gssapi_delegation = data->set.gssapi_delegation;
 #endif
+  DEBUGF(infof(data, "alloc connection, bits.close=%d", conn->bits.close));
   return conn;
 error:
 
@@ -2035,11 +2031,13 @@ static CURLcode setup_connection_internals(struct Curl_easy *data,
   int port;
   CURLcode result;
 
+  DEBUGF(infof(data, "setup connection, bits.close=%d", conn->bits.close));
   if(conn->handler->setup_connection) {
     result = conn->handler->setup_connection(data, conn);
     if(result)
       return result;
   }
+  DEBUGF(infof(data, "setup connection, bits.close=%d", conn->bits.close));
 
   /* Now create the destination name */
 #ifndef CURL_DISABLE_PROXY
@@ -3664,6 +3662,7 @@ static CURLcode create_conn(struct Curl_easy *data,
     /* We have decided that we want a new connection. However, we may not
        be able to do that if we have reached the limit of how many
        connections we are allowed to open. */
+    DEBUGF(infof(data, "new connection, bits.close=%d", conn->bits.close));
 
     if(conn->handler->flags & PROTOPT_ALPN) {
       /* The protocol wants it, so set the bits if enabled in the easy handle
index c71607ea7d2bfc67dd0a51c0e44a8d27bb9f8e11..37ecd1ff9db726ac43df429cc1b5f90e037d8d0c 100644 (file)
@@ -567,6 +567,7 @@ struct Curl_handler {
 #define PROTOPT_SSL_REUSE (1<<15)   /* this protocol may reuse an existing
                                        SSL connection in the same family
                                        without having PROTOPT_SSL. */
+#define PROTOPT_CONN_REUSE (1<<16)  /* this protocol can reuse connections */
 
 #define CONNCHECK_NONE 0                 /* No checks */
 #define CONNCHECK_ISDEAD (1<<0)          /* Check if the connection is dead. */
index 61b233e4ffc00bdc0022a67256c8543c9e9eb579..de767f28dc04cd3d074f6a7940bc324dc765737e 100644 (file)
@@ -2647,7 +2647,6 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
       CURL_TRC_CF(data, cf, "peer verified");
       cf->connected = TRUE;
       *done = TRUE;
-      connkeep(cf->conn, "HTTP/3 default");
     }
   }
 
index 0f7cc7a91a2a933546e47064f303a860041de684..376705e5166789d6ecd74959e609f8ab768e970c 100644 (file)
@@ -1816,7 +1816,6 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
       CURL_TRC_CF(data, cf, "peer verified");
       cf->connected = TRUE;
       *done = TRUE;
-      connkeep(cf->conn, "HTTP/3 default");
     }
   }
   else {
index 5082dc750bb53249af3c17b503648146f06d35fe..92749297901355332c60dfa8e7f79f785eb03a59 100644 (file)
@@ -446,7 +446,6 @@ static CURLcode cf_recv_body(struct Curl_cfilter *cf,
     stream->closed = TRUE;
     stream->reset = TRUE;
     stream->send_closed = TRUE;
-    streamclose(cf->conn, "Reset of stream");
     return result;
   }
   return CURLE_OK;
@@ -510,7 +509,6 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf,
     stream->closed = TRUE;
     stream->reset = TRUE;
     stream->send_closed = TRUE;
-    streamclose(cf->conn, "Reset of stream");
     break;
 
   case QUICHE_H3_EVENT_FINISHED:
@@ -522,7 +520,6 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf,
       stream->resp_hds_complete = TRUE;
     }
     stream->closed = TRUE;
-    streamclose(cf->conn, "End of stream");
     break;
 
   case QUICHE_H3_EVENT_GOAWAY:
@@ -1415,7 +1412,6 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
       }
       cf->connected = TRUE;
       *done = TRUE;
-      connkeep(cf->conn, "HTTP/3 default");
     }
   }
   else if(quiche_conn_is_draining(ctx->qconn)) {
index 77a915884aaf72c37337facfb95fb7378081c3a3..c76478bc2a57bec118804dd891ce25cfc4d241ab 100644 (file)
@@ -156,7 +156,8 @@ const struct Curl_handler Curl_handler_scp = {
   PORT_SSH,                     /* defport */
   CURLPROTO_SCP,                /* protocol */
   CURLPROTO_SCP,                /* family */
-  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY    /* flags */
+  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */
+  PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE
 };
 
 /*
@@ -185,8 +186,8 @@ const struct Curl_handler Curl_handler_sftp = {
   PORT_SSH,                             /* defport */
   CURLPROTO_SFTP,                       /* protocol */
   CURLPROTO_SFTP,                       /* family */
-  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
-  | PROTOPT_NOURLQUERY                  /* flags */
+  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */
+  PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE
 };
 
 static CURLcode sftp_error_to_CURLE(int err)
@@ -2572,10 +2573,6 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
   if(!sshc || !ssh)
     return CURLE_FAILED_INIT;
 
-  /* We default to persistent connections. We set this already in this connect
-     function to make the reuse checks properly be able to check this bit. */
-  connkeep(conn, "SSH default");
-
   if(conn->handler->protocol & CURLPROTO_SCP) {
     conn->recv[FIRSTSOCKET] = scp_recv;
     conn->send[FIRSTSOCKET] = scp_send;
index 714e3953730a4bc1c16f4e57abb20761799afc9b..1c9fe5ac0154d3ce08aa1131211130ea3e7a19c5 100644 (file)
@@ -123,8 +123,8 @@ const struct Curl_handler Curl_handler_scp = {
   PORT_SSH,                             /* defport */
   CURLPROTO_SCP,                        /* protocol */
   CURLPROTO_SCP,                        /* family */
-  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
-  | PROTOPT_NOURLQUERY                  /* flags */
+  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */
+  PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE
 };
 
 
@@ -154,8 +154,8 @@ const struct Curl_handler Curl_handler_sftp = {
   PORT_SSH,                             /* defport */
   CURLPROTO_SFTP,                       /* protocol */
   CURLPROTO_SFTP,                       /* family */
-  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
-  | PROTOPT_NOURLQUERY                  /* flags */
+  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */
+  PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE
 };
 
 static void
@@ -3323,10 +3323,6 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
   if(!sshc)
     return CURLE_FAILED_INIT;
 
-  /* We default to persistent connections. We set this already in this connect
-     function to make the reuse checks properly be able to check this bit. */
-  connkeep(conn, "SSH default");
-
   infof(data, "User: '%s'", conn->user);
 #ifdef CURL_LIBSSH2_DEBUG
   infof(data, "Password: %s", conn->passwd);
index 8991d965d9becf8478e806ccf43e3564a2a3f41d..2f526479c5f4062802218e2d676c5151f02c4178 100644 (file)
@@ -5175,7 +5175,6 @@ static CURLcode ossl_recv(struct Curl_cfilter *cf,
   char error_buffer[256];
   unsigned long sslerror;
   int buffsize;
-  struct connectdata *conn = cf->conn;
   struct ssl_connect_data *connssl = cf->ctx;
   struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
   CURLcode result = CURLE_OK;
@@ -5205,7 +5204,7 @@ static CURLcode ossl_recv(struct Curl_cfilter *cf,
       if(cf->sockindex == FIRSTSOCKET)
         /* mark the connection for close if it is indeed the control
            connection */
-        connclose(conn, "TLS close_notify");
+        CURL_TRC_CF(data, cf, "TLS close_notify");
       break;
     case SSL_ERROR_WANT_READ:
       connssl->io_need = CURL_SSL_IO_NEED_RECV;