]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
cfilter: provide call to tell connection to forget a socket
authorStefan Eissing <stefan@eissing.org>
Thu, 26 Oct 2023 15:02:45 +0000 (17:02 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 27 Oct 2023 14:59:13 +0000 (16:59 +0200)
- fixed libssh.c workaround for a socket being closed by
  the library
- eliminate the terrible hack in cf-socket.c to guess when
  this happened and try not closing the socket again.
- fixes race in eyeballing when socket could have failed to
  be closed for a discarded connect attempt

Closes #12207

lib/cf-socket.c
lib/cfilters.c
lib/cfilters.h
lib/vssh/libssh.c

index a7822918555e4312d17bd91c3c9a6ce8eba411b6..05177bb78be225c5e6040db31c98086acbbe0f9a 100644 (file)
@@ -880,34 +880,14 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
   struct cf_socket_ctx *ctx = cf->ctx;
 
   if(ctx && CURL_SOCKET_BAD != ctx->sock) {
-    if(ctx->active) {
-      /* We share our socket at cf->conn->sock[cf->sockindex] when active.
-       * If it is no longer there, someone has stolen (and hopefully
-       * closed it) and we just forget about it.
-       */
-      if(ctx->sock == cf->conn->sock[cf->sockindex]) {
-        CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
-                    ", active)", ctx->sock);
-        socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
-        cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
-      }
-      else {
-        CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
-                    ") no longer at conn->sock[], discarding", ctx->sock);
-        /* TODO: we do not want this to happen. Need to check which
-         * code is messing with conn->sock[cf->sockindex] */
-      }
-      ctx->sock = CURL_SOCKET_BAD;
-      if(cf->sockindex == FIRSTSOCKET)
-        cf->conn->remote_addr = NULL;
-    }
-    else {
-      /* this is our local socket, we did never publish it */
-      CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
-                  ", not active)", ctx->sock);
-      socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
-      ctx->sock = CURL_SOCKET_BAD;
-    }
+    CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
+                ")", ctx->sock);
+    if(ctx->sock == cf->conn->sock[cf->sockindex])
+      cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
+    socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
+    ctx->sock = CURL_SOCKET_BAD;
+    if(ctx->active && cf->sockindex == FIRSTSOCKET)
+      cf->conn->remote_addr = NULL;
     Curl_bufq_reset(&ctx->recvbuf);
     ctx->active = FALSE;
     ctx->buffer_recv = FALSE;
@@ -1514,6 +1494,9 @@ static CURLcode cf_socket_cntrl(struct Curl_cfilter *cf,
   case CF_CTRL_DATA_SETUP:
     Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port);
     break;
+  case CF_CTRL_FORGET_SOCKET:
+    ctx->sock = CURL_SOCKET_BAD;
+    break;
   }
   return CURLE_OK;
 }
index 59d6c84b0171641d2066015a9172806d55940d0b..c7b034cb3766a6eafee4f19af4e8ce1f3348ac2b 100644 (file)
@@ -527,6 +527,18 @@ curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex)
   return data->conn? data->conn->sock[sockindex] : CURL_SOCKET_BAD;
 }
 
+void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex)
+{
+  if(data->conn) {
+    struct Curl_cfilter *cf = data->conn->cfilter[sockindex];
+    if(cf)
+      (void)Curl_conn_cf_cntrl(cf, data, TRUE,
+                               CF_CTRL_FORGET_SOCKET, 0, NULL);
+    fake_sclose(data->conn->sock[sockindex]);
+    data->conn->sock[sockindex] = CURL_SOCKET_BAD;
+  }
+}
+
 static CURLcode cf_cntrl_all(struct connectdata *conn,
                              struct Curl_easy *data,
                              bool ignore_result,
index 4d8520df1ab7d1c38d5ab900fc1e100cd3a68e0e..409c38b9a59648735ee191c0e3356ddaa6f92766 100644 (file)
@@ -130,6 +130,7 @@ typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf,
 #define CF_CTRL_DATA_DONE_SEND        8  /* 0          NULL     ignored */
 /* update conn info at connection and data */
 #define CF_CTRL_CONN_INFO_UPDATE (256+0) /* 0          NULL     ignored */
+#define CF_CTRL_FORGET_SOCKET    (256+1) /* 0          NULL     ignored */
 
 /**
  * Handle event/control for the filter.
@@ -380,6 +381,11 @@ bool Curl_conn_data_pending(struct Curl_easy *data,
  */
 curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex);
 
+/**
+ * Tell filters to forget about the soket at sockindex.
+ */
+void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex);
+
 /**
  * Adjust the pollset for the filter chain startgin at `cf`.
  */
index b0f49d60c90c9ed011b797b6772af00dfe23a898..80588d07312162da249cac8613e090de3b95f02b 100644 (file)
@@ -1963,10 +1963,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
       ssh_disconnect(sshc->ssh_session);
       if(!ssh_version(SSH_VERSION_INT(0, 10, 0))) {
         /* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back,
-           explicitly mark it as closed with the memdebug macro. This libssh
+           tell the connection to forget about it. This libssh
            bug is fixed in 0.10.0. */
-        fake_sclose(conn->sock[FIRSTSOCKET]);
-        conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;
+        Curl_conn_forget_socket(data, FIRSTSOCKET);
       }
 
       SSH_STRING_FREE_CHAR(sshc->homedir);