]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
lib: replace `getsock()` logic with pollsets
authorStefan Eissing <stefan@eissing.org>
Mon, 4 Aug 2025 14:17:37 +0000 (16:17 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 4 Aug 2025 21:43:13 +0000 (23:43 +0200)
`getsock()` calls operated on a global limit that could
not be configure beyond 16 sockets. This is no longer adequate
with the new happy eyeballing strategy.

Instead, do the following:
- make `struct easy_pollset` dynamic. Starting with
  a minimal room for two sockets, the very common case,
  allow it to grow on demand.
- replace all protocol handler getsock() calls with pollsets
  and a CURLcode to return failures
- add CURLcode return for all connection filter `adjust_pollset()`
  callbacks, since they too can now fail.
- use appropriately in multi.c and multi_ev.c
- fix unit2600 to trigger pollset growth

Closes #18164

54 files changed:
lib/asyn-ares.c
lib/asyn-base.c
lib/asyn-thrdd.c
lib/asyn.h
lib/cf-h1-proxy.c
lib/cf-h2-proxy.c
lib/cf-haproxy.c
lib/cf-https-connect.c
lib/cf-ip-happy.c
lib/cf-socket.c
lib/cfilters.c
lib/cfilters.h
lib/cshutdn.c
lib/curl_rtmp.c
lib/dict.c
lib/file.c
lib/ftp.c
lib/gopher.c
lib/hostip.c
lib/hostip.h
lib/http.c
lib/http.h
lib/http2.c
lib/imap.c
lib/ldap.c
lib/mqtt.c
lib/multi.c
lib/multi_ev.c
lib/multihandle.h
lib/multiif.h
lib/openldap.c
lib/pingpong.c
lib/pingpong.h
lib/pop3.c
lib/rtsp.c
lib/select.c
lib/select.h
lib/smb.c
lib/smtp.c
lib/socks.c
lib/telnet.c
lib/tftp.c
lib/transfer.h
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/vssh/wolfssh.c
lib/vtls/vtls.c
lib/vtls/vtls_int.h
lib/ws.c
tests/unit/unit2600.c

index 007f1d7123c77a5212816e24a59ef8eb95183e95..375f1a6eb625ac08766cb1125fd6039fd5bbc8d3 100644 (file)
@@ -273,15 +273,15 @@ static void async_ares_cleanup(struct Curl_easy *data)
 }
 
 /*
- * Curl_async_getsock() is called when someone from the outside world
+ * Curl_async_pollset() is called when someone from the outside world
  * (using curl_multi_fdset()) wants to get our fd_set setup.
  */
 
-int Curl_async_getsock(struct Curl_easy *data, curl_socket_t *socks)
+CURLcode Curl_async_pollset(struct Curl_easy *data, struct easy_pollset *ps)
 {
   struct async_ares_ctx *ares = &data->state.async.ares;
   DEBUGASSERT(ares->channel);
-  return Curl_ares_getsock(data, ares->channel, socks);
+  return Curl_ares_pollset(data, ares->channel, ps);
 }
 
 /*
index ea89fba15c329979b9c93e1a3368a26f989aeb16..c0df7aac5e0c5a3a050cc54d25ceb3db4ebce1ca 100644 (file)
@@ -70,7 +70,7 @@
 #endif
 
 /*
- * Curl_ares_getsock() is called when the outside world (using
+ * Curl_ares_pollset() is called when the outside world (using
  * curl_multi_fdset()) wants to get our fd_set setup and we are talking with
  * ares. The caller must make sure that this function is only called when we
  * have a working ares channel.
  * Returns: sockets-in-use-bitmap
  */
 
-int Curl_ares_getsock(struct Curl_easy *data,
-                      ares_channel channel,
-                      curl_socket_t *socks)
+
+CURLcode Curl_ares_pollset(struct Curl_easy *data,
+                           ares_channel channel,
+                           struct easy_pollset *ps)
 {
   struct timeval maxtime = { CURL_TIMEOUT_RESOLVE, 0 };
   struct timeval timebuf;
-  int max = ares_getsock(channel,
-                         (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
-  struct timeval *timeout = ares_timeout(channel, &maxtime, &timebuf);
-  timediff_t milli = curlx_tvtoms(timeout);
+  curl_socket_t sockets[16];  /* ARES documented limit */
+  unsigned int bitmap, i;
+  struct timeval *timeout;
+  timediff_t milli;
+  CURLcode result = CURLE_OK;
+
+  bitmap = ares_getsock(channel, (ares_socket_t *)sockets,
+                        CURL_ARRAYSIZE(sockets));
+  for(i = 0; i < CURL_ARRAYSIZE(sockets); ++i) {
+    int flags = 0;
+    if(ARES_GETSOCK_READABLE(bitmap, i))
+      flags |= CURL_POLL_IN;
+    if(ARES_GETSOCK_WRITABLE(bitmap, i))
+      flags |= CURL_POLL_OUT;
+    if(!flags)
+      break;
+    result = Curl_pollset_change(data, ps, sockets[i], flags, 0);
+    if(result)
+      return result;
+  }
+
+  timeout = ares_timeout(channel, &maxtime, &timebuf);
+  milli = curlx_tvtoms(timeout);
   Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
-  return max;
+  return result;
 }
 
 /*
index 19d1336854c6ec915c01feb341e4a2c04a27825c..6a56f92c4e3c93a4869323b56c0b769597222681 100644 (file)
@@ -63,6 +63,7 @@
 #include "url.h"
 #include "multiif.h"
 #include "curl_threads.h"
+#include "select.h"
 #include "strdup.h"
 
 #ifdef USE_ARES
@@ -629,33 +630,25 @@ CURLcode Curl_async_is_resolved(struct Curl_easy *data,
   }
 }
 
-int Curl_async_getsock(struct Curl_easy *data, curl_socket_t *socks)
+CURLcode Curl_async_pollset(struct Curl_easy *data, struct easy_pollset *ps)
 {
   struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
-  int ret_val = 0;
-#if !defined(CURL_DISABLE_SOCKETPAIR) || defined(USE_HTTPSRR_ARES)
-  int socketi = 0;
-#else
-  (void)socks;
-#endif
+  CURLcode result = CURLE_OK;
 
 #ifdef USE_HTTPSRR_ARES
   if(thrdd->rr.channel) {
-    ret_val = Curl_ares_getsock(data, thrdd->rr.channel, socks);
-    for(socketi = 0; socketi < (MAX_SOCKSPEREASYHANDLE - 1); socketi++)
-      if(!ARES_GETSOCK_READABLE(ret_val, socketi) &&
-         !ARES_GETSOCK_WRITABLE(ret_val, socketi))
-        break;
+    result = Curl_ares_pollset(data, thrdd->rr.channel, ps);
+    if(result)
+      return result;
   }
 #endif
   if(!thrdd->addr)
-    return ret_val;
+    return result;
 
 #ifndef CURL_DISABLE_SOCKETPAIR
   if(thrdd->addr) {
     /* return read fd to client for polling the DNS resolution status */
-    socks[socketi] = thrdd->addr->sock_pair[0];
-    ret_val |= GETSOCK_READSOCK(socketi);
+    result = Curl_pollset_add_in(data, ps, thrdd->addr->sock_pair[0]);
   }
   else
 #endif
@@ -673,7 +666,7 @@ int Curl_async_getsock(struct Curl_easy *data, curl_socket_t *socks)
     Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
   }
 
-  return ret_val;
+  return result;
 }
 
 #ifndef HAVE_GETADDRINFO
index a336c1e2547ae03a09f7d1f9d5d697af7593ea6c..69aeb8b4822a9a3a682f3b7e2df06c75fd832dde 100644 (file)
@@ -37,6 +37,7 @@ struct Curl_dns_entry;
 struct addrinfo;
 struct hostent;
 struct connectdata;
+struct easy_pollset;
 
 #if defined(CURLRES_ARES) && defined(CURLRES_THREADED)
 #error cannot have both CURLRES_ARES and CURLRES_THREADED defined
@@ -70,15 +71,15 @@ void Curl_async_global_cleanup(void);
  */
 CURLcode Curl_async_get_impl(struct Curl_easy *easy, void **impl);
 
-/* Curl_async_getsock()
+/* Curl_async_pollset()
  *
- * This function is called from the Curl_multi_getsock() function.  'sock' is a
+ * This function is called from the Curl_multi_pollset() function.  'sock' is a
  * pointer to an array to hold the file descriptors, with 'numsock' being the
  * size of that array (in number of entries). This function is supposed to
  * return bitmask indicating what file descriptors (referring to array indexes
  * in the 'sock' array) to wait for, read/write.
  */
-int Curl_async_getsock(struct Curl_easy *data, curl_socket_t *sock);
+CURLcode Curl_async_pollset(struct Curl_easy *data, struct easy_pollset *ps);
 
 /*
  * Curl_async_is_resolved()
@@ -127,9 +128,10 @@ struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data,
 /* common functions for c-ares and threaded resolver with HTTPSRR */
 #include <ares.h>
 
-int Curl_ares_getsock(struct Curl_easy *data,
-                      ares_channel channel,
-                      curl_socket_t *socks);
+CURLcode Curl_ares_pollset(struct Curl_easy *data,
+                           ares_channel channel,
+                           struct easy_pollset *ps);
+
 int Curl_ares_perform(ares_channel channel,
                       timediff_t timeout_ms);
 #endif
index 4aac877fc1854446413dcc9e5ca350e588d559f9..798d6e9f6681e22d2f039f6f30a36915b03a9990 100644 (file)
@@ -682,11 +682,12 @@ out:
   return result;
 }
 
-static void cf_h1_proxy_adjust_pollset(struct Curl_cfilter *cf,
-                                       struct Curl_easy *data,
-                                       struct easy_pollset *ps)
+static CURLcode cf_h1_proxy_adjust_pollset(struct Curl_cfilter *cf,
+                                           struct Curl_easy *data,
+                                           struct easy_pollset *ps)
 {
   struct h1_tunnel_state *ts = cf->ctx;
+  CURLcode result = CURLE_OK;
 
   if(!cf->connected) {
     /* If we are not connected, but the filter "below" is
@@ -698,13 +699,14 @@ static void cf_h1_proxy_adjust_pollset(struct Curl_cfilter *cf,
          response headers or if we are still sending the request, wait
          for write. */
       if(tunnel_want_send(ts))
-        Curl_pollset_set_out_only(data, ps, sock);
+        result = Curl_pollset_set_out_only(data, ps, sock);
       else
-        Curl_pollset_set_in_only(data, ps, sock);
+        result = Curl_pollset_set_in_only(data, ps, sock);
     }
     else
-      Curl_pollset_set_out_only(data, ps, sock);
+      result = Curl_pollset_set_out_only(data, ps, sock);
   }
+  return result;
 }
 
 static void cf_h1_proxy_destroy(struct Curl_cfilter *cf,
index 162881b17eacdfcd17e0d219833808d6898809f0..18803ed50b4b8a5a0193c8c7a1b3307851760289 100644 (file)
@@ -41,6 +41,7 @@
 #include "http_proxy.h"
 #include "multiif.h"
 #include "sendf.h"
+#include "select.h"
 #include "cf-h2-proxy.h"
 
 /* The last 3 #include files should be in this order */
@@ -1202,14 +1203,15 @@ static bool cf_h2_proxy_data_pending(struct Curl_cfilter *cf,
   return cf->next ? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
 }
 
-static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf,
-                                       struct Curl_easy *data,
-                                       struct easy_pollset *ps)
+static CURLcode cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf,
+                                           struct Curl_easy *data,
+                                           struct easy_pollset *ps)
 {
   struct cf_h2_proxy_ctx *ctx = cf->ctx;
   struct cf_call_data save;
   curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
   bool want_recv, want_send;
+  CURLcode result = CURLE_OK;
 
   if(!cf->connected && ctx->h2) {
     want_send = nghttp2_session_want_write(ctx->h2) ||
@@ -1234,9 +1236,9 @@ static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf,
                 !Curl_bufq_is_empty(&ctx->outbufq) ||
                 !Curl_bufq_is_empty(&ctx->tunnel.sendbuf);
 
-    Curl_pollset_set(data, ps, sock, want_recv, want_send);
-    CURL_TRC_CF(data, cf, "adjust_pollset, want_recv=%d want_send=%d",
-                want_recv, want_send);
+    result = Curl_pollset_set(data, ps, sock, want_recv, want_send);
+    CURL_TRC_CF(data, cf, "adjust_pollset, want_recv=%d want_send=%d -> %d",
+                want_recv, want_send, result);
     CF_DATA_RESTORE(cf, save);
   }
   else if(ctx->sent_goaway && !cf->shutdown) {
@@ -1246,11 +1248,12 @@ static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf,
                 !Curl_bufq_is_empty(&ctx->outbufq) ||
                 !Curl_bufq_is_empty(&ctx->tunnel.sendbuf);
     want_recv = nghttp2_session_want_read(ctx->h2);
-    Curl_pollset_set(data, ps, sock, want_recv, want_send);
-    CURL_TRC_CF(data, cf, "adjust_pollset, want_recv=%d want_send=%d",
-                want_recv, want_send);
+    result = Curl_pollset_set(data, ps, sock, want_recv, want_send);
+    CURL_TRC_CF(data, cf, "adjust_pollset, want_recv=%d want_send=%d -> %d",
+                want_recv, want_send, result);
     CF_DATA_RESTORE(cf, save);
   }
+  return result;
 }
 
 static CURLcode h2_handle_tunnel_close(struct Curl_cfilter *cf,
index 62ac89e819f8b8bc7ded7323e518c585e16ccf7f..2d66efea90400ff0ad7db90e945141f544376f58 100644 (file)
@@ -32,6 +32,7 @@
 #include "cf-haproxy.h"
 #include "curl_trc.h"
 #include "multiif.h"
+#include "select.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -178,15 +179,17 @@ static void cf_haproxy_close(struct Curl_cfilter *cf,
     cf->next->cft->do_close(cf->next, data);
 }
 
-static void cf_haproxy_adjust_pollset(struct Curl_cfilter *cf,
-                                      struct Curl_easy *data,
-                                      struct easy_pollset *ps)
+static CURLcode cf_haproxy_adjust_pollset(struct Curl_cfilter *cf,
+                                          struct Curl_easy *data,
+                                          struct easy_pollset *ps)
 {
   if(cf->next->connected && !cf->connected) {
     /* If we are not connected, but the filter "below" is
      * and not waiting on something, we are sending. */
-    Curl_pollset_set_out_only(data, ps, Curl_conn_cf_get_socket(cf, data));
+    return Curl_pollset_set_out_only(
+      data, ps, Curl_conn_cf_get_socket(cf, data));
   }
+  return CURLE_OK;
 }
 
 struct Curl_cftype Curl_cft_haproxy = {
index f36d227b117a4d6113779ed6a4da681ea5965030..b4a46052950225bd03e13d096baf34c700364aba 100644 (file)
@@ -35,6 +35,7 @@
 #include "multiif.h"
 #include "cf-https-connect.h"
 #include "http2.h"
+#include "select.h"
 #include "vquic/vquic.h"
 
 /* The last 3 #include files should be in this order */
@@ -426,22 +427,24 @@ static CURLcode cf_hc_shutdown(struct Curl_cfilter *cf,
   return result;
 }
 
-static void cf_hc_adjust_pollset(struct Curl_cfilter *cf,
-                                 struct Curl_easy *data,
-                                 struct easy_pollset *ps)
+static CURLcode cf_hc_adjust_pollset(struct Curl_cfilter *cf,
+                                     struct Curl_easy *data,
+                                     struct easy_pollset *ps)
 {
+  CURLcode result = CURLE_OK;
   if(!cf->connected) {
     struct cf_hc_ctx *ctx = cf->ctx;
     size_t i;
 
-    for(i = 0; i < ctx->baller_count; i++) {
+    for(i = 0; (i < ctx->baller_count) && !result; i++) {
       struct cf_hc_baller *b = &ctx->ballers[i];
       if(!cf_hc_baller_is_active(b))
         continue;
-      Curl_conn_cf_adjust_pollset(b->cf, data, ps);
+      result = Curl_conn_cf_adjust_pollset(b->cf, data, ps);
     }
-    CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
+    CURL_TRC_CF(data, cf, "adjust_pollset -> %d, %d socks", result, ps->n);
   }
+  return result;
 }
 
 static bool cf_hc_data_pending(struct Curl_cfilter *cf,
index 6dbb5c5fdc5c087984e198283a517b6310efbd1a..59b34ae46ffde4e1b45cc8d6231c6c430a5aa604 100644 (file)
@@ -60,6 +60,7 @@
 #include "curl_trc.h"
 #include "multiif.h"
 #include "progress.h"
+#include "select.h"
 #include "vquic/vquic.h" /* for quic cfilters */
 
 /* The last 3 #include files should be in this order */
@@ -533,16 +534,18 @@ static CURLcode cf_ip_ballers_shutdown(struct cf_ip_ballers *bs,
   return CURLE_OK;
 }
 
-static void cf_ip_ballers_pollset(struct cf_ip_ballers *bs,
-                                  struct Curl_easy *data,
-                                  struct easy_pollset *ps)
+static CURLcode cf_ip_ballers_pollset(struct cf_ip_ballers *bs,
+                                      struct Curl_easy *data,
+                                      struct easy_pollset *ps)
 {
   struct cf_ip_attempt *a;
-  for(a = bs->running; a; a = a->next) {
+  CURLcode result = CURLE_OK;
+  for(a = bs->running; a && !result; a = a->next) {
     if(a->result)
       continue;
-    Curl_conn_cf_adjust_pollset(a->cf, data, ps);
+    result = Curl_conn_cf_adjust_pollset(a->cf, data, ps);
   }
+  return result;
 }
 
 static bool cf_ip_ballers_pending(struct cf_ip_ballers *bs,
@@ -713,16 +716,18 @@ static CURLcode cf_ip_happy_shutdown(struct Curl_cfilter *cf,
   return result;
 }
 
-static void cf_ip_happy_adjust_pollset(struct Curl_cfilter *cf,
-                                       struct Curl_easy *data,
-                                       struct easy_pollset *ps)
+static CURLcode cf_ip_happy_adjust_pollset(struct Curl_cfilter *cf,
+                                           struct Curl_easy *data,
+                                           struct easy_pollset *ps)
 {
   struct cf_ip_happy_ctx *ctx = cf->ctx;
+  CURLcode result = CURLE_OK;
 
   if(!cf->connected) {
-    cf_ip_ballers_pollset(&ctx->ballers, data, ps);
-    CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
+    result = cf_ip_ballers_pollset(&ctx->ballers, data, ps);
+    CURL_TRC_CF(data, cf, "adjust_pollset -> %d, %d socks", result, ps->n);
   }
+  return result;
 }
 
 static CURLcode cf_ip_happy_connect(struct Curl_cfilter *cf,
index 06c9a743687d11a18517034e9ec76d5861f8612e..7f3f8e60ff424a6b988d16aee29432b6d4dbafbb 100644 (file)
@@ -1376,11 +1376,12 @@ out:
   return result;
 }
 
-static void cf_socket_adjust_pollset(struct Curl_cfilter *cf,
-                                     struct Curl_easy *data,
-                                     struct easy_pollset *ps)
+static CURLcode cf_socket_adjust_pollset(struct Curl_cfilter *cf,
+                                         struct Curl_easy *data,
+                                         struct easy_pollset *ps)
 {
   struct cf_socket_ctx *ctx = cf->ctx;
+  CURLcode result = CURLE_OK;
 
   if(ctx->sock != CURL_SOCKET_BAD) {
     /* A listening socket filter needs to be connected before the accept
@@ -1388,21 +1389,22 @@ static void cf_socket_adjust_pollset(struct Curl_cfilter *cf,
      * FTP no longer does the socket checks and accept calls and delegates
      * all that to the filter. */
     if(ctx->listening) {
-      Curl_pollset_set_in_only(data, ps, ctx->sock);
+      result = Curl_pollset_set_in_only(data, ps, ctx->sock);
       CURL_TRC_CF(data, cf, "adjust_pollset, listening, POLLIN fd=%"
                   FMT_SOCKET_T, ctx->sock);
     }
     else if(!cf->connected) {
-      Curl_pollset_set_out_only(data, ps, ctx->sock);
+      result = Curl_pollset_set_out_only(data, ps, ctx->sock);
       CURL_TRC_CF(data, cf, "adjust_pollset, !connected, POLLOUT fd=%"
                   FMT_SOCKET_T, ctx->sock);
     }
     else if(!ctx->active) {
-      Curl_pollset_add_in(data, ps, ctx->sock);
+      result = Curl_pollset_add_in(data, ps, ctx->sock);
       CURL_TRC_CF(data, cf, "adjust_pollset, !active, POLLIN fd=%"
                   FMT_SOCKET_T, ctx->sock);
     }
   }
+  return result;
 }
 
 #ifdef USE_WINSOCK
index c7333e12b0bc20f92c10ee957989da30709db76a..e4b630bc8fe4dc187527b26aae77233666190ef3 100644 (file)
@@ -67,14 +67,15 @@ CURLcode Curl_cf_def_shutdown(struct Curl_cfilter *cf,
 static void conn_report_connect_stats(struct Curl_easy *data,
                                       struct connectdata *conn);
 
-void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
-                                struct Curl_easy *data,
-                                struct easy_pollset *ps)
+CURLcode Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
+                                    struct Curl_easy *data,
+                                    struct easy_pollset *ps)
 {
   /* NOP */
   (void)cf;
   (void)data;
   (void)ps;
+  return CURLE_OK;
 }
 
 bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
@@ -469,6 +470,7 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
 {
 #define CF_CONN_NUM_POLLS_ON_STACK 5
   struct pollfd a_few_on_stack[CF_CONN_NUM_POLLS_ON_STACK];
+  struct easy_pollset ps;
   struct curl_pollfds cpfds;
   struct Curl_cfilter *cf;
   CURLcode result = CURLE_OK;
@@ -486,6 +488,7 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
   if(*done)
     return CURLE_OK;
 
+  Curl_pollset_init(&ps);
   Curl_pollfds_init(&cpfds, a_few_on_stack, CF_CONN_NUM_POLLS_ON_STACK);
   while(!*done) {
     if(Curl_conn_needs_flush(data, sockindex)) {
@@ -523,7 +526,6 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
       /* check allowed time left */
       const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
       curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
-      struct easy_pollset ps;
       int rc;
 
       if(timeout_ms < 0) {
@@ -534,12 +536,14 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
       }
 
       CURL_TRC_CF(data, cf, "Curl_conn_connect(block=1), do poll");
+      Curl_pollset_reset(&ps);
       Curl_pollfds_reset(&cpfds);
-      memset(&ps, 0, sizeof(ps));
       /* In general, we want to send after connect, wait on that. */
       if(sockfd != CURL_SOCKET_BAD)
         Curl_pollset_set_out_only(data, &ps, sockfd);
-      Curl_conn_adjust_pollset(data, data->conn, &ps);
+      result = Curl_conn_adjust_pollset(data, data->conn, &ps);
+      if(result)
+        goto out;
       result = Curl_pollfds_add_ps(&cpfds, &ps);
       if(result)
         goto out;
@@ -557,6 +561,7 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
   }
 
 out:
+  Curl_pollset_cleanup(&ps);
   Curl_pollfds_cleanup(&cpfds);
   return result;
 }
@@ -710,10 +715,11 @@ bool Curl_conn_needs_flush(struct Curl_easy *data, int sockindex)
   return Curl_conn_cf_needs_flush(data->conn->cfilter[sockindex], data);
 }
 
-void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
-                                 struct Curl_easy *data,
-                                 struct easy_pollset *ps)
+CURLcode Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
+                                     struct Curl_easy *data,
+                                     struct easy_pollset *ps)
 {
+  CURLcode result = CURLE_OK;
   /* Get the lowest not-connected filter, if there are any */
   while(cf && !cf->connected && cf->next && !cf->next->connected)
     cf = cf->next;
@@ -722,23 +728,26 @@ void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
     cf = cf->next;
   /* From there on, give all filters a chance to adjust the pollset.
    * Lower filters are called later, so they may override */
-  while(cf) {
-    cf->cft->adjust_pollset(cf, data, ps);
+  while(cf && !result) {
+    result = cf->cft->adjust_pollset(cf, data, ps);
     cf = cf->next;
   }
+  return result;
 }
 
-void Curl_conn_adjust_pollset(struct Curl_easy *data,
-                              struct connectdata *conn,
-                              struct easy_pollset *ps)
+CURLcode Curl_conn_adjust_pollset(struct Curl_easy *data,
+                                  struct connectdata *conn,
+                                  struct easy_pollset *ps)
 {
+  CURLcode result = CURLE_OK;
   int i;
 
   DEBUGASSERT(data);
   DEBUGASSERT(conn);
-  for(i = 0; i < 2; ++i) {
-    Curl_conn_cf_adjust_pollset(conn->cfilter[i], data, ps);
+  for(i = 0; (i < 2) && !result; ++i) {
+    result = Curl_conn_cf_adjust_pollset(conn->cfilter[i], data, ps);
   }
+  return result;
 }
 
 int Curl_conn_cf_poll(struct Curl_cfilter *cf,
@@ -746,35 +755,18 @@ int Curl_conn_cf_poll(struct Curl_cfilter *cf,
                       timediff_t timeout_ms)
 {
   struct easy_pollset ps;
-  struct pollfd pfds[MAX_SOCKSPEREASYHANDLE];
-  unsigned int i, npfds = 0;
+  int result;
 
   DEBUGASSERT(cf);
   DEBUGASSERT(data);
   DEBUGASSERT(data->conn);
-  memset(&ps, 0, sizeof(ps));
-  memset(pfds, 0, sizeof(pfds));
-
-  Curl_conn_cf_adjust_pollset(cf, data, &ps);
-  DEBUGASSERT(ps.num <= MAX_SOCKSPEREASYHANDLE);
-  for(i = 0; i < ps.num; ++i) {
-    short events = 0;
-    if(ps.actions[i] & CURL_POLL_IN) {
-      events |= POLLIN;
-    }
-    if(ps.actions[i] & CURL_POLL_OUT) {
-      events |= POLLOUT;
-    }
-    if(events) {
-      pfds[npfds].fd = ps.sockets[i];
-      pfds[npfds].events = events;
-      ++npfds;
-    }
-  }
+  Curl_pollset_init(&ps);
 
-  if(!npfds)
-    DEBUGF(infof(data, "no sockets to poll!"));
-  return Curl_poll(pfds, npfds, timeout_ms);
+  result = Curl_conn_cf_adjust_pollset(cf, data, &ps);
+  if(!result)
+    result = Curl_pollset_poll(data, &ps, timeout_ms);
+  Curl_pollset_cleanup(&ps);
+  return result;
 }
 
 void Curl_conn_get_current_host(struct Curl_easy *data, int sockindex,
@@ -1099,142 +1091,3 @@ CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
   *pnwritten = 0;
   return CURLE_FAILED_INIT;
 }
-
-void Curl_pollset_reset(struct Curl_easy *data,
-                        struct easy_pollset *ps)
-{
-  size_t i;
-  (void)data;
-  memset(ps, 0, sizeof(*ps));
-  for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++)
-    ps->sockets[i] = CURL_SOCKET_BAD;
-}
-
-/**
- *
- */
-void Curl_pollset_change(struct Curl_easy *data,
-                         struct easy_pollset *ps, curl_socket_t sock,
-                         int add_flags, int remove_flags)
-{
-  unsigned int i;
-
-  (void)data;
-  DEBUGASSERT(VALID_SOCK(sock));
-  if(!VALID_SOCK(sock))
-    return;
-
-  DEBUGASSERT(add_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
-  DEBUGASSERT(remove_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
-  DEBUGASSERT((add_flags&remove_flags) == 0); /* no overlap */
-  for(i = 0; i < ps->num; ++i) {
-    if(ps->sockets[i] == sock) {
-      ps->actions[i] &= (unsigned char)(~remove_flags);
-      ps->actions[i] |= (unsigned char)add_flags;
-      /* all gone? remove socket */
-      if(!ps->actions[i]) {
-        if((i + 1) < ps->num) {
-          memmove(&ps->sockets[i], &ps->sockets[i + 1],
-                  (ps->num - (i + 1)) * sizeof(ps->sockets[0]));
-          memmove(&ps->actions[i], &ps->actions[i + 1],
-                  (ps->num - (i + 1)) * sizeof(ps->actions[0]));
-        }
-        --ps->num;
-      }
-      return;
-    }
-  }
-  /* not present */
-  if(add_flags) {
-    /* Having more SOCKETS per easy handle than what is defined
-     * is a programming error. This indicates that we need
-     * to raise this limit, making easy_pollset larger.
-     * Since we use this in tight loops, we do not want to make
-     * the pollset dynamic unnecessarily.
-     * The current maximum in practise is HTTP/3 eyeballing where
-     * we have up to 4 sockets involved in connection setup.
-     */
-    DEBUGASSERT(i < MAX_SOCKSPEREASYHANDLE);
-    if(i < MAX_SOCKSPEREASYHANDLE) {
-      ps->sockets[i] = sock;
-      ps->actions[i] = (unsigned char)add_flags;
-      ps->num = i + 1;
-    }
-  }
-}
-
-void Curl_pollset_set(struct Curl_easy *data,
-                      struct easy_pollset *ps, curl_socket_t sock,
-                      bool do_in, bool do_out)
-{
-  Curl_pollset_change(data, ps, sock,
-                      (do_in ? CURL_POLL_IN : 0)|
-                      (do_out ? CURL_POLL_OUT : 0),
-                      (!do_in ? CURL_POLL_IN : 0)|
-                      (!do_out ? CURL_POLL_OUT : 0));
-}
-
-static void ps_add(struct Curl_easy *data, struct easy_pollset *ps,
-                   int bitmap, curl_socket_t *socks)
-{
-  if(bitmap) {
-    int i;
-    for(i = 0; i < MAX_SOCKSPEREASYHANDLE; ++i) {
-      if(!(bitmap & GETSOCK_MASK_RW(i)) || !VALID_SOCK((socks[i]))) {
-        break;
-      }
-      if(bitmap & GETSOCK_READSOCK(i)) {
-        if(bitmap & GETSOCK_WRITESOCK(i))
-          Curl_pollset_add_inout(data, ps, socks[i]);
-        else
-          /* is READ, since we checked MASK_RW above */
-          Curl_pollset_add_in(data, ps, socks[i]);
-      }
-      else
-        Curl_pollset_add_out(data, ps, socks[i]);
-    }
-  }
-}
-
-void Curl_pollset_add_socks(struct Curl_easy *data,
-                            struct easy_pollset *ps,
-                            int (*get_socks_cb)(struct Curl_easy *data,
-                                                curl_socket_t *socks))
-{
-  curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
-  int bitmap;
-
-  bitmap = get_socks_cb(data, socks);
-  ps_add(data, ps, bitmap, socks);
-}
-
-void Curl_pollset_check(struct Curl_easy *data,
-                        struct easy_pollset *ps, curl_socket_t sock,
-                        bool *pwant_read, bool *pwant_write)
-{
-  unsigned int i;
-
-  (void)data;
-  DEBUGASSERT(VALID_SOCK(sock));
-  for(i = 0; i < ps->num; ++i) {
-    if(ps->sockets[i] == sock) {
-      *pwant_read = !!(ps->actions[i] & CURL_POLL_IN);
-      *pwant_write = !!(ps->actions[i] & CURL_POLL_OUT);
-      return;
-    }
-  }
-  *pwant_read = *pwant_write = FALSE;
-}
-
-bool Curl_pollset_want_read(struct Curl_easy *data,
-                            struct easy_pollset *ps,
-                            curl_socket_t sock)
-{
-  unsigned int i;
-  (void)data;
-  for(i = 0; i < ps->num; ++i) {
-    if((ps->sockets[i] == sock) && (ps->actions[i] & CURL_POLL_IN))
-      return TRUE;
-  }
-  return FALSE;
-}
index 0b6e1044fc2bfa41a5a6df6fb7d1603b636be178..458ce589372058df3e5bf0660fe90c538e31f33b 100644 (file)
@@ -80,7 +80,7 @@ struct easy_pollset;
  * @param data   the easy handle the pollset is about
  * @param ps     the pollset (inout) for the easy handle
  */
-typedef void     Curl_cft_adjust_pollset(struct Curl_cfilter *cf,
+typedef CURLcode Curl_cft_adjust_pollset(struct Curl_cfilter *cf,
                                          struct Curl_easy *data,
                                          struct easy_pollset *ps);
 
@@ -244,7 +244,7 @@ void Curl_cf_def_destroy_this(struct Curl_cfilter *cf,
 
 /* Default implementations for the type functions, implementing pass-through
  * the filter chain. */
-void     Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
+CURLcode Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
                                     struct Curl_easy *data,
                                     struct easy_pollset *ps);
 bool     Curl_cf_def_data_pending(struct Curl_cfilter *cf,
@@ -477,16 +477,16 @@ void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex);
 /**
  * Adjust the pollset for the filter chain starting at `cf`.
  */
-void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
-                                 struct Curl_easy *data,
-                                 struct easy_pollset *ps);
+CURLcode Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
+                                     struct Curl_easy *data,
+                                     struct easy_pollset *ps);
 
 /**
  * Adjust pollset from filters installed at transfer's connection.
  */
-void Curl_conn_adjust_pollset(struct Curl_easy *data,
-                              struct connectdata *conn,
-                              struct easy_pollset *ps);
+CURLcode Curl_conn_adjust_pollset(struct Curl_easy *data,
+                                  struct connectdata *conn,
+                                  struct easy_pollset *ps);
 
 /**
  * Curl_poll() the filter chain at `cf` with timeout `timeout_ms`.
@@ -632,56 +632,6 @@ CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
                         size_t *pnwritten);
 
 
-void Curl_pollset_reset(struct Curl_easy *data,
-                        struct easy_pollset *ps);
-
-/* Change the poll flags (CURL_POLL_IN/CURL_POLL_OUT) to the poll set for
- * socket `sock`. If the socket is not already part of the poll set, it
- * will be added.
- * If the socket is present and all poll flags are cleared, it will be removed.
- */
-void Curl_pollset_change(struct Curl_easy *data,
-                         struct easy_pollset *ps, curl_socket_t sock,
-                         int add_flags, int remove_flags);
-
-void Curl_pollset_set(struct Curl_easy *data,
-                      struct easy_pollset *ps, curl_socket_t sock,
-                      bool do_in, bool do_out);
-
-#define Curl_pollset_add_in(data, ps, sock) \
-          Curl_pollset_change((data), (ps), (sock), CURL_POLL_IN, 0)
-#define Curl_pollset_add_out(data, ps, sock) \
-          Curl_pollset_change((data), (ps), (sock), CURL_POLL_OUT, 0)
-#define Curl_pollset_add_inout(data, ps, sock) \
-          Curl_pollset_change((data), (ps), (sock), \
-                               CURL_POLL_IN|CURL_POLL_OUT, 0)
-#define Curl_pollset_set_in_only(data, ps, sock) \
-          Curl_pollset_change((data), (ps), (sock), \
-                               CURL_POLL_IN, CURL_POLL_OUT)
-#define Curl_pollset_set_out_only(data, ps, sock) \
-          Curl_pollset_change((data), (ps), (sock), \
-                               CURL_POLL_OUT, CURL_POLL_IN)
-
-void Curl_pollset_add_socks(struct Curl_easy *data,
-                            struct easy_pollset *ps,
-                            int (*get_socks_cb)(struct Curl_easy *data,
-                                                curl_socket_t *socks));
-
-/**
- * Check if the pollset, as is, wants to read and/or write regarding
- * the given socket.
- */
-void Curl_pollset_check(struct Curl_easy *data,
-                        struct easy_pollset *ps, curl_socket_t sock,
-                        bool *pwant_read, bool *pwant_write);
-
-/**
- * Return TRUE if the pollset contains socket with CURL_POLL_IN.
- */
-bool Curl_pollset_want_read(struct Curl_easy *data,
-                            struct easy_pollset *ps,
-                            curl_socket_t sock);
-
 /**
  * Types and macros used to keep the current easy handle in filter calls,
  * allowing for nested invocations. See #10336.
index aeea9bdc3e08f6b47c07f2d64d7c614e6599ee0e..1c144c6025f48f5f6cd2020d5f7b554556d05c53 100644 (file)
@@ -486,18 +486,24 @@ void Curl_cshutdn_setfds(struct cshutdn *cshutdn,
 {
   if(Curl_llist_head(&cshutdn->list)) {
     struct Curl_llist_node *e;
+    struct easy_pollset ps;
 
+    Curl_pollset_init(&ps);
     for(e = Curl_llist_head(&cshutdn->list); e;
         e = Curl_node_next(e)) {
-      struct easy_pollset ps;
       unsigned int i;
       struct connectdata *conn = Curl_node_elem(e);
-      memset(&ps, 0, sizeof(ps));
+      CURLcode result;
+
+      Curl_pollset_reset(&ps);
       Curl_attach_connection(data, conn);
-      Curl_conn_adjust_pollset(data, conn, &ps);
+      result = Curl_conn_adjust_pollset(data, conn, &ps);
       Curl_detach_connection(data);
 
-      for(i = 0; i < ps.num; i++) {
+      if(result)
+        continue;
+
+      for(i = 0; i < ps.n; i++) {
 #ifdef __DJGPP__
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Warith-conversion"
@@ -514,6 +520,7 @@ void Curl_cshutdn_setfds(struct cshutdn *cshutdn,
           *maxfd = (int)ps.sockets[i];
       }
     }
+    Curl_pollset_cleanup(&ps);
   }
 }
 
@@ -528,17 +535,21 @@ unsigned int Curl_cshutdn_add_waitfds(struct cshutdn *cshutdn,
     struct Curl_llist_node *e;
     struct easy_pollset ps;
     struct connectdata *conn;
+    CURLcode result;
 
+    Curl_pollset_init(&ps);
     for(e = Curl_llist_head(&cshutdn->list); e;
         e = Curl_node_next(e)) {
       conn = Curl_node_elem(e);
-      memset(&ps, 0, sizeof(ps));
+      Curl_pollset_reset(&ps);
       Curl_attach_connection(data, conn);
-      Curl_conn_adjust_pollset(data, conn, &ps);
+      result = Curl_conn_adjust_pollset(data, conn, &ps);
       Curl_detach_connection(data);
 
-      need += Curl_waitfds_add_ps(cwfds, &ps);
+      if(!result)
+        need += Curl_waitfds_add_ps(cwfds, &ps);
     }
+    Curl_pollset_cleanup(&ps);
   }
   return need;
 }
@@ -554,20 +565,24 @@ CURLcode Curl_cshutdn_add_pollfds(struct cshutdn *cshutdn,
     struct easy_pollset ps;
     struct connectdata *conn;
 
+    Curl_pollset_init(&ps);
     for(e = Curl_llist_head(&cshutdn->list); e;
         e = Curl_node_next(e)) {
       conn = Curl_node_elem(e);
-      memset(&ps, 0, sizeof(ps));
+      Curl_pollset_reset(&ps);
       Curl_attach_connection(data, conn);
-      Curl_conn_adjust_pollset(data, conn, &ps);
+      result = Curl_conn_adjust_pollset(data, conn, &ps);
       Curl_detach_connection(data);
 
-      result = Curl_pollfds_add_ps(cpfds, &ps);
+      if(!result)
+        result = Curl_pollfds_add_ps(cpfds, &ps);
       if(result) {
+        Curl_pollset_cleanup(&ps);
         Curl_pollfds_cleanup(cpfds);
         goto out;
       }
     }
+    Curl_pollset_cleanup(&ps);
   }
 out:
   return result;
index 0be1f7c7681ce3da67922ec22594b327aa753127..584c8a9df6b69d3d155cfe3644e22bc50482b21d 100644 (file)
@@ -81,10 +81,10 @@ const struct Curl_handler Curl_handler_rtmp = {
   rtmp_connect,                         /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   rtmp_disconnect,                      /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -106,10 +106,10 @@ const struct Curl_handler Curl_handler_rtmpt = {
   rtmp_connect,                         /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   rtmp_disconnect,                      /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -131,10 +131,10 @@ const struct Curl_handler Curl_handler_rtmpe = {
   rtmp_connect,                         /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   rtmp_disconnect,                      /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -156,10 +156,10 @@ const struct Curl_handler Curl_handler_rtmpte = {
   rtmp_connect,                         /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   rtmp_disconnect,                      /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -181,10 +181,10 @@ const struct Curl_handler Curl_handler_rtmps = {
   rtmp_connect,                         /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   rtmp_disconnect,                      /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -206,10 +206,10 @@ const struct Curl_handler Curl_handler_rtmpts = {
   rtmp_connect,                         /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   rtmp_disconnect,                      /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
index 7f13e6f7ea981b569e5ca2e5dced7ee0772261cf..30e13b45479ec7375dc79bd28689869c16e35ab5 100644 (file)
@@ -92,10 +92,10 @@ const struct Curl_handler Curl_handler_dict = {
   ZERO_NULL,                            /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
index d59d1478f6bb3e32b30c86247ba7b92d7d5b1828..0b44d2257d7cf5f6099eecf1eebc4b1af505f427 100644 (file)
@@ -120,10 +120,10 @@ const struct Curl_handler Curl_handler_file = {
   file_connect,                         /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   file_disconnect,                      /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
index 18613ae80e59039fc944e49675ae1dd9cd475153..3eec2f14eeb34119a1880015a9a094508ea5ae11 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -214,10 +214,10 @@ static CURLcode ftp_disconnect(struct Curl_easy *data,
                                struct connectdata *conn, bool dead_connection);
 static CURLcode ftp_do_more(struct Curl_easy *data, int *completed);
 static CURLcode ftp_multi_statemach(struct Curl_easy *data, bool *done);
-static int ftp_getsock(struct Curl_easy *data, struct connectdata *conn,
-                       curl_socket_t *socks);
-static int ftp_domore_getsock(struct Curl_easy *data,
-                              struct connectdata *conn, curl_socket_t *socks);
+static CURLcode ftp_pollset(struct Curl_easy *data,
+                            struct easy_pollset *ps);
+static CURLcode ftp_domore_pollset(struct Curl_easy *data,
+                                   struct easy_pollset *ps);
 static CURLcode ftp_doing(struct Curl_easy *data,
                           bool *dophase_done);
 static CURLcode ftp_setup_connection(struct Curl_easy *data,
@@ -257,10 +257,10 @@ const struct Curl_handler Curl_handler_ftp = {
   ftp_connect,                     /* connect_it */
   ftp_multi_statemach,             /* connecting */
   ftp_doing,                       /* doing */
-  ftp_getsock,                     /* proto_getsock */
-  ftp_getsock,                     /* doing_getsock */
-  ftp_domore_getsock,              /* domore_getsock */
-  ZERO_NULL,                       /* perform_getsock */
+  ftp_pollset,                     /* proto_pollset */
+  ftp_pollset,                     /* doing_pollset */
+  ftp_domore_pollset,              /* domore_pollset */
+  ZERO_NULL,                       /* perform_pollset */
   ftp_disconnect,                  /* disconnect */
   ZERO_NULL,                       /* write_resp */
   ZERO_NULL,                       /* write_resp_hd */
@@ -290,10 +290,10 @@ const struct Curl_handler Curl_handler_ftps = {
   ftp_connect,                     /* connect_it */
   ftp_multi_statemach,             /* connecting */
   ftp_doing,                       /* doing */
-  ftp_getsock,                     /* proto_getsock */
-  ftp_getsock,                     /* doing_getsock */
-  ftp_domore_getsock,              /* domore_getsock */
-  ZERO_NULL,                       /* perform_getsock */
+  ftp_pollset,                     /* proto_pollset */
+  ftp_pollset,                     /* doing_pollset */
+  ftp_domore_pollset,              /* domore_pollset */
+  ZERO_NULL,                       /* perform_pollset */
   ftp_disconnect,                  /* disconnect */
   ZERO_NULL,                       /* write_resp */
   ZERO_NULL,                       /* write_resp_hd */
@@ -781,42 +781,39 @@ static CURLcode ftp_state_pwd(struct Curl_easy *data,
 }
 
 /* For the FTP "protocol connect" and "doing" phases only */
-static int ftp_getsock(struct Curl_easy *data,
-                       struct connectdata *conn,
-                       curl_socket_t *socks)
+static CURLcode ftp_pollset(struct Curl_easy *data,
+                            struct easy_pollset *ps)
 {
-  struct ftp_conn *ftpc = Curl_conn_meta_get(conn, CURL_META_FTP_CONN);
-  return ftpc ? Curl_pp_getsock(data, &ftpc->pp, socks) : GETSOCK_BLANK;
+  struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
+  return ftpc ? Curl_pp_pollset(data, &ftpc->pp, ps) : CURLE_OK;
 }
 
 /* For the FTP "DO_MORE" phase only */
-static int ftp_domore_getsock(struct Curl_easy *data,
-                              struct connectdata *conn, curl_socket_t *socks)
+static CURLcode ftp_domore_pollset(struct Curl_easy *data,
+                                   struct easy_pollset *ps)
 {
-  struct ftp_conn *ftpc = Curl_conn_meta_get(conn, CURL_META_FTP_CONN);
-  (void)data;
+  struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
 
   if(!ftpc)
-    return GETSOCK_BLANK;
+    return CURLE_OK;
 
   /* When in DO_MORE state, we could be either waiting for us to connect to a
    * remote site, or we could wait for that site to connect to us. Or just
    * handle ordinary commands.
    */
-  CURL_TRC_FTP(data, "[%s] ftp_domore_getsock()", FTP_CSTATE(ftpc));
+  CURL_TRC_FTP(data, "[%s] ftp_domore_pollset()", FTP_CSTATE(ftpc));
 
   if(FTP_STOP == ftpc->state) {
     /* if stopped and still in this state, then we are also waiting for a
        connect on the secondary connection */
-    DEBUGASSERT(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD ||
-               (conn->cfilter[SECONDARYSOCKET] &&
-                !Curl_conn_is_connected(conn, SECONDARYSOCKET)));
-    socks[0] = conn->sock[FIRSTSOCKET];
+    DEBUGASSERT(data->conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD ||
+               (data->conn->cfilter[SECONDARYSOCKET] &&
+                !Curl_conn_is_connected(data->conn, SECONDARYSOCKET)));
     /* An unconnected SECONDARY will add its socket by itself
      * via its adjust_pollset() */
-    return GETSOCK_READSOCK(0);
+    return Curl_pollset_add_in(data, ps, data->conn->sock[FIRSTSOCKET]);
   }
-  return Curl_pp_getsock(data, &ftpc->pp, socks);
+  return Curl_pp_pollset(data, &ftpc->pp, ps);
 }
 
 /* This is called after the FTP_QUOTE state is passed.
index 68ccb59e408a419ab63eececccbf2d4e477d3195..82e02ed17034d4b634e0dc6c8bb3020ac1b95cf1 100644 (file)
@@ -70,10 +70,10 @@ const struct Curl_handler Curl_handler_gopher = {
   ZERO_NULL,                            /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -96,10 +96,10 @@ const struct Curl_handler Curl_handler_gophers = {
   gopher_connect,                       /* connect_it */
   gopher_connecting,                    /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
index e01f111a64b534329bb5f538c99a68fd45a7f723..06fa3bc47e8a04c77cb8253f7db73ebdc75a6143 100644 (file)
@@ -1527,21 +1527,21 @@ CURLcode Curl_resolv_check(struct Curl_easy *data,
 }
 #endif
 
-int Curl_resolv_getsock(struct Curl_easy *data,
-                        curl_socket_t *socks)
+CURLcode Curl_resolv_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps)
 {
 #ifdef CURLRES_ASYNCH
 #ifndef CURL_DISABLE_DOH
   if(data->conn->bits.doh)
     /* nothing to wait for during DoH resolve, those handles have their own
        sockets */
-    return GETSOCK_BLANK;
+    return CURLE_OK;
 #endif
-  return Curl_async_getsock(data, socks);
+  return Curl_async_pollset(data, ps);
 #else
   (void)data;
-  (void)socks;
-  return GETSOCK_BLANK;
+  (void)ps;
+  return CURLE_OK;
 #endif
 }
 
index 5548a6f125d3e3f5694e096425b9846636c0ba8c..3743b73961e1842867b0f1ebf94d449eddeca2c7 100644 (file)
@@ -53,6 +53,7 @@ struct addrinfo;
 struct hostent;
 struct Curl_easy;
 struct connectdata;
+struct easy_pollset;
 
 enum alpnid {
   ALPN_none = 0,
@@ -199,8 +200,8 @@ CURLcode Curl_resolv_check(struct Curl_easy *data,
 #else
 #define Curl_resolv_check(x,y) CURLE_NOT_BUILT_IN
 #endif
-int Curl_resolv_getsock(struct Curl_easy *data,
-                        curl_socket_t *socks);
+CURLcode Curl_resolv_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps);
 
 CURLcode Curl_resolver_error(struct Curl_easy *data);
 
index aa48887723d0dbf498796a85fcaf94c961fc27b3..08daab6dc900a297fd5879c22480afb1625c82c5 100644 (file)
@@ -137,10 +137,10 @@ const struct Curl_handler Curl_handler_http = {
   Curl_http_connect,                    /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  Curl_http_getsock_do,                 /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  Curl_http_do_pollset,                 /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   Curl_http_write_resp,                 /* write_resp */
   Curl_http_write_resp_hd,              /* write_resp_hd */
@@ -167,10 +167,10 @@ const struct Curl_handler Curl_handler_https = {
   Curl_http_connect,                    /* connect_it */
   NULL,                                 /* connecting */
   ZERO_NULL,                            /* doing */
-  NULL,                                 /* proto_getsock */
-  Curl_http_getsock_do,                 /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  NULL,                                 /* proto_pollset */
+  Curl_http_do_pollset,                 /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   Curl_http_write_resp,                 /* write_resp */
   Curl_http_write_resp_hd,              /* write_resp_hd */
@@ -1524,14 +1524,12 @@ CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
 /* this returns the socket to wait for in the DO and DOING state for the multi
    interface and then we are always _sending_ a request and thus we wait for
    the single socket to become writable only */
-int Curl_http_getsock_do(struct Curl_easy *data,
-                         struct connectdata *conn,
-                         curl_socket_t *socks)
+CURLcode Curl_http_do_pollset(struct Curl_easy *data,
+                              struct easy_pollset *ps)
 {
   /* write mode */
-  (void)conn;
-  socks[0] = Curl_conn_get_socket(data, FIRSTSOCKET);
-  return GETSOCK_WRITESOCK(0);
+  curl_socket_t sock = Curl_conn_get_socket(data, FIRSTSOCKET);
+  return Curl_pollset_add_out(data, ps, sock);
 }
 
 /*
index a7bc2c6537ab57b54c73bb2d3f609c565b725769..50279aedfaad7b02221855783d2c9c061e24b84b 100644 (file)
@@ -115,8 +115,8 @@ CURLcode Curl_http_setup_conn(struct Curl_easy *data,
 CURLcode Curl_http(struct Curl_easy *data, bool *done);
 CURLcode Curl_http_done(struct Curl_easy *data, CURLcode, bool premature);
 CURLcode Curl_http_connect(struct Curl_easy *data, bool *done);
-int Curl_http_getsock_do(struct Curl_easy *data, struct connectdata *conn,
-                         curl_socket_t *socks);
+CURLcode Curl_http_do_pollset(struct Curl_easy *data,
+                              struct easy_pollset *ps);
 CURLcode Curl_http_write_resp(struct Curl_easy *data,
                               const char *buf, size_t blen,
                               bool is_eos);
index c6c7c21474154c04cc4b7adf64b641df7de09a38..e550abc8f84792fa08066e73aa39a744bd89d5e7 100644 (file)
@@ -2465,17 +2465,18 @@ out:
   return result;
 }
 
-static void cf_h2_adjust_pollset(struct Curl_cfilter *cf,
-                                 struct Curl_easy *data,
-                                 struct easy_pollset *ps)
+static CURLcode cf_h2_adjust_pollset(struct Curl_cfilter *cf,
+                                     struct Curl_easy *data,
+                                     struct easy_pollset *ps)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
   struct cf_call_data save;
   curl_socket_t sock;
   bool want_recv, want_send;
+  CURLcode result = CURLE_OK;
 
   if(!ctx->h2)
-    return;
+    return CURLE_OK;
 
   sock = Curl_conn_cf_get_socket(cf, data);
   Curl_pollset_check(data, ps, sock, &want_recv, &want_send);
@@ -2493,7 +2494,7 @@ static void cf_h2_adjust_pollset(struct Curl_cfilter *cf,
                 (!c_exhaust && nghttp2_session_want_write(ctx->h2)) ||
                 !Curl_bufq_is_empty(&ctx->outbufq);
 
-    Curl_pollset_set(data, ps, sock, want_recv, want_send);
+    result = Curl_pollset_set(data, ps, sock, want_recv, want_send);
     CF_DATA_RESTORE(cf, save);
   }
   else if(ctx->sent_goaway && !cf->shutdown) {
@@ -2502,9 +2503,10 @@ static void cf_h2_adjust_pollset(struct Curl_cfilter *cf,
     want_send = nghttp2_session_want_write(ctx->h2) ||
                 !Curl_bufq_is_empty(&ctx->outbufq);
     want_recv = nghttp2_session_want_read(ctx->h2);
-    Curl_pollset_set(data, ps, sock, want_recv, want_send);
+    result = Curl_pollset_set(data, ps, sock, want_recv, want_send);
     CF_DATA_RESTORE(cf, save);
   }
+  return result;
 }
 
 static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
index f25176bb9e274e46c93ff8383e7f214ed1ff7aaf..5949b667e98021df4f9c1424eed5bdca68c559b7 100644 (file)
@@ -157,8 +157,8 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done);
 static CURLcode imap_disconnect(struct Curl_easy *data,
                                 struct connectdata *conn, bool dead);
 static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done);
-static int imap_getsock(struct Curl_easy *data, struct connectdata *conn,
-                        curl_socket_t *socks);
+static CURLcode imap_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps);
 static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done);
 static CURLcode imap_setup_connection(struct Curl_easy *data,
                                       struct connectdata *conn);
@@ -196,10 +196,10 @@ const struct Curl_handler Curl_handler_imap = {
   imap_connect,                     /* connect_it */
   imap_multi_statemach,             /* connecting */
   imap_doing,                       /* doing */
-  imap_getsock,                     /* proto_getsock */
-  imap_getsock,                     /* doing_getsock */
-  ZERO_NULL,                        /* domore_getsock */
-  ZERO_NULL,                        /* perform_getsock */
+  imap_pollset,                     /* proto_pollset */
+  imap_pollset,                     /* doing_pollset */
+  ZERO_NULL,                        /* domore_pollset */
+  ZERO_NULL,                        /* perform_pollset */
   imap_disconnect,                  /* disconnect */
   ZERO_NULL,                        /* write_resp */
   ZERO_NULL,                        /* write_resp_hd */
@@ -227,10 +227,10 @@ const struct Curl_handler Curl_handler_imaps = {
   imap_connect,                     /* connect_it */
   imap_multi_statemach,             /* connecting */
   imap_doing,                       /* doing */
-  imap_getsock,                     /* proto_getsock */
-  imap_getsock,                     /* doing_getsock */
-  ZERO_NULL,                        /* domore_getsock */
-  ZERO_NULL,                        /* perform_getsock */
+  imap_pollset,                     /* proto_pollset */
+  imap_pollset,                     /* doing_pollset */
+  ZERO_NULL,                        /* domore_pollset */
+  ZERO_NULL,                        /* perform_pollset */
   imap_disconnect,                  /* disconnect */
   ZERO_NULL,                        /* write_resp */
   ZERO_NULL,                        /* write_resp_hd */
@@ -1560,13 +1560,12 @@ static CURLcode imap_block_statemach(struct Curl_easy *data,
 }
 
 /* For the IMAP "protocol connect" and "doing" phases only */
-static int imap_getsock(struct Curl_easy *data,
-                        struct connectdata *conn,
-                        curl_socket_t *socks)
+static CURLcode imap_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps)
 {
-  struct imap_conn *imapc = Curl_conn_meta_get(conn, CURL_META_IMAP_CONN);
-  return imapc ?
-         Curl_pp_getsock(data, &imapc->pp, socks) : GETSOCK_BLANK;
+  struct imap_conn *imapc =
+    Curl_conn_meta_get(data->conn, CURL_META_IMAP_CONN);
+  return imapc ? Curl_pp_pollset(data, &imapc->pp, ps) : CURLE_OK;
 }
 
 /***********************************************************************
index 3880d35d60c2ddbd8aa963cbec61af9aa7ac8609..c66a56d7bb243abeacee1fd8bc0d3c26a251c748 100644 (file)
@@ -177,10 +177,10 @@ const struct Curl_handler Curl_handler_ldap = {
   ZERO_NULL,                            /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -207,10 +207,10 @@ const struct Curl_handler Curl_handler_ldaps = {
   ZERO_NULL,                            /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
index 90f857dca56cb0b56be4390989e56f7406125c14..35afe012075fd174c97872e13d1aca34cbc05a64 100644 (file)
@@ -107,8 +107,8 @@ static CURLcode mqtt_do(struct Curl_easy *data, bool *done);
 static CURLcode mqtt_done(struct Curl_easy *data,
                           CURLcode status, bool premature);
 static CURLcode mqtt_doing(struct Curl_easy *data, bool *done);
-static int mqtt_getsock(struct Curl_easy *data, struct connectdata *conn,
-                        curl_socket_t *sock);
+static CURLcode mqtt_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps);
 static CURLcode mqtt_setup_conn(struct Curl_easy *data,
                                 struct connectdata *conn);
 
@@ -125,10 +125,10 @@ const struct Curl_handler Curl_handler_mqtt = {
   ZERO_NULL,                          /* connect_it */
   ZERO_NULL,                          /* connecting */
   mqtt_doing,                         /* doing */
-  ZERO_NULL,                          /* proto_getsock */
-  mqtt_getsock,                       /* doing_getsock */
-  ZERO_NULL,                          /* domore_getsock */
-  ZERO_NULL,                          /* perform_getsock */
+  ZERO_NULL,                          /* proto_pollset */
+  mqtt_pollset,                       /* doing_pollset */
+  ZERO_NULL,                          /* domore_pollset */
+  ZERO_NULL,                          /* perform_pollset */
   ZERO_NULL,                          /* disconnect */
   ZERO_NULL,                          /* write_resp */
   ZERO_NULL,                          /* write_resp_hd */
@@ -213,13 +213,10 @@ static CURLcode mqtt_send(struct Curl_easy *data,
 /* Generic function called by the multi interface to figure out what socket(s)
    to wait for and for what actions during the DOING and PROTOCONNECT
    states */
-static int mqtt_getsock(struct Curl_easy *data,
-                        struct connectdata *conn,
-                        curl_socket_t *sock)
+static CURLcode mqtt_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps)
 {
-  (void)data;
-  sock[0] = conn->sock[FIRSTSOCKET];
-  return GETSOCK_READSOCK(FIRSTSOCKET);
+  return Curl_pollset_add_in(data, ps, data->conn->sock[FIRSTSOCKET]);
 }
 
 static int mqtt_encode_len(char *buf, size_t len)
index 194cf75d400e2e57e9cacdba310161e13b16e556..b5a6970eee1d0fc7f6ccda9bca4c69f6f8434817 100644 (file)
@@ -907,118 +907,103 @@ void Curl_attach_connection(struct Curl_easy *data,
     conn->handler->attach(data, conn);
 }
 
-static int connecting_getsock(struct Curl_easy *data, curl_socket_t *socks)
+static CURLcode mstate_connecting_pollset(struct Curl_easy *data,
+                                          struct easy_pollset *ps)
 {
-  struct connectdata *conn = data->conn;
-  curl_socket_t sockfd;
-
-  if(!conn)
-    return GETSOCK_BLANK;
-  sockfd = Curl_conn_get_socket(data, FIRSTSOCKET);
-  if(sockfd != CURL_SOCKET_BAD) {
-    /* Default is to wait to something from the server */
-    socks[0] = sockfd;
-    return GETSOCK_READSOCK(0);
+  if(data->conn) {
+    curl_socket_t sockfd = Curl_conn_get_socket(data, FIRSTSOCKET);
+    if(sockfd != CURL_SOCKET_BAD) {
+      /* Default is to wait to something from the server */
+      return Curl_pollset_change(data, ps, sockfd, CURL_POLL_IN, 0);
+    }
   }
-  return GETSOCK_BLANK;
+  return CURLE_OK;
 }
 
-static int protocol_getsock(struct Curl_easy *data, curl_socket_t *socks)
+static CURLcode mstate_protocol_pollset(struct Curl_easy *data,
+                                        struct easy_pollset *ps)
 {
-  struct connectdata *conn = data->conn;
-  curl_socket_t sockfd;
-
-  if(!conn)
-    return GETSOCK_BLANK;
-  if(conn->handler->proto_getsock)
-    return conn->handler->proto_getsock(data, conn, socks);
-  sockfd = Curl_conn_get_socket(data, FIRSTSOCKET);
-  if(sockfd != CURL_SOCKET_BAD) {
-    /* Default is to wait to something from the server */
-    socks[0] = sockfd;
-    return GETSOCK_READSOCK(0);
+  if(data->conn) {
+    curl_socket_t sockfd;
+    if(data->conn->handler->proto_pollset)
+      return data->conn->handler->proto_pollset(data, ps);
+    sockfd = Curl_conn_get_socket(data, FIRSTSOCKET);
+    if(sockfd != CURL_SOCKET_BAD) {
+      /* Default is to wait to something from the server */
+      return Curl_pollset_change(data, ps, sockfd, CURL_POLL_IN, 0);
+    }
   }
-  return GETSOCK_BLANK;
+  return CURLE_OK;
 }
 
-static int domore_getsock(struct Curl_easy *data, curl_socket_t *socks)
+static CURLcode mstate_do_pollset(struct Curl_easy *data,
+                                  struct easy_pollset *ps)
 {
   struct connectdata *conn = data->conn;
-  if(!conn)
-    return GETSOCK_BLANK;
-  if(conn->handler->domore_getsock)
-    return conn->handler->domore_getsock(data, conn, socks);
-  else if(conn->sockfd != CURL_SOCKET_BAD) {
-    /* Default is that we want to send something to the server */
-    socks[0] = conn->sockfd;
-    return GETSOCK_WRITESOCK(0);
+  if(data->conn) {
+    if(data->conn->handler->doing_pollset)
+      return data->conn->handler->doing_pollset(data, ps);
+    else if(conn->sockfd != CURL_SOCKET_BAD) {
+      /* Default is that we want to send something to the server */
+      return Curl_pollset_add_out(data, ps, conn->sockfd);
+    }
   }
-  return GETSOCK_BLANK;
+  return CURLE_OK;
 }
 
-static int doing_getsock(struct Curl_easy *data, curl_socket_t *socks)
+static CURLcode mstate_domore_pollset(struct Curl_easy *data,
+                                      struct easy_pollset *ps)
 {
-  struct connectdata *conn = data->conn;
-  if(!conn)
-    return GETSOCK_BLANK;
-  if(conn->handler->doing_getsock)
-    return conn->handler->doing_getsock(data, conn, socks);
-  else if(conn->sockfd != CURL_SOCKET_BAD) {
-    /* Default is that we want to send something to the server */
-    socks[0] = conn->sockfd;
-    return GETSOCK_WRITESOCK(0);
+  if(data->conn) {
+    if(data->conn->handler->domore_pollset)
+      return data->conn->handler->domore_pollset(data, ps);
+    else if(data->conn->sockfd != CURL_SOCKET_BAD) {
+      /* Default is that we want to send something to the server */
+      return Curl_pollset_add_out(data, ps, data->conn->sockfd);
+    }
   }
-  return GETSOCK_BLANK;
+  return CURLE_OK;
 }
 
-static int perform_getsock(struct Curl_easy *data, curl_socket_t *sock)
+static CURLcode mstate_perform_pollset(struct Curl_easy *data,
+                                       struct easy_pollset *ps)
 {
-  struct connectdata *conn = data->conn;
-  if(!conn)
-    return GETSOCK_BLANK;
-  else if(conn->handler->perform_getsock)
-    return conn->handler->perform_getsock(data, conn, sock);
+  if(!data->conn)
+    return CURLE_OK;
+  else if(data->conn->handler->perform_pollset)
+    return data->conn->handler->perform_pollset(data, ps);
   else {
     /* Default is to obey the data->req.keepon flags for send/recv */
-    int bitmap = GETSOCK_BLANK;
-    unsigned sockindex = 0;
+    CURLcode result = CURLE_OK;
     if(CURL_WANT_RECV(data)) {
-      DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
-      bitmap |= GETSOCK_READSOCK(sockindex);
-      sock[sockindex] = conn->sockfd;
+      DEBUGASSERT(data->conn->sockfd != CURL_SOCKET_BAD);
+      result = Curl_pollset_add_in(data, ps, data->conn->sockfd);
     }
 
-    if(Curl_req_want_send(data)) {
-      if((conn->sockfd != conn->writesockfd) ||
-         bitmap == GETSOCK_BLANK) {
-        /* only if they are not the same socket and we have a readable
-           one, we increase index */
-        if(bitmap != GETSOCK_BLANK)
-          sockindex++; /* increase index if we need two entries */
-
-        DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD);
-        sock[sockindex] = conn->writesockfd;
-      }
-      bitmap |= GETSOCK_WRITESOCK(sockindex);
+    if(!result && Curl_req_want_send(data)) {
+      DEBUGASSERT(data->conn->writesockfd != CURL_SOCKET_BAD);
+      result = Curl_pollset_add_out(data, ps, data->conn->writesockfd);
     }
-    return bitmap;
+    return result;
   }
 }
 
 /* Initializes `poll_set` with the current socket poll actions needed
  * for transfer `data`. */
-void Curl_multi_getsock(struct Curl_easy *data,
-                        struct easy_pollset *ps,
-                        const char *caller)
+CURLMcode Curl_multi_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps,
+                             const char *caller)
 {
+  CURLMcode mresult = CURLM_OK;
+  CURLcode result = CURLE_OK;
   bool expect_sockets = TRUE;
 
   /* If the transfer has no connection, this is fine. Happens when
      called via curl_multi_remove_handle() => Curl_multi_ev_assess() =>
-     Curl_multi_getsock(). */
-  Curl_pollset_reset(data, ps);
+     Curl_multi_pollset(). */
+  Curl_pollset_reset(ps);
   if(!data->conn)
-    return;
+    return CURLM_OK;
 
   switch(data->mstate) {
   case MSTATE_INIT:
@@ -1030,7 +1015,7 @@ void Curl_multi_getsock(struct Curl_easy *data,
     break;
 
   case MSTATE_RESOLVING:
-    Curl_pollset_add_socks(data, ps, Curl_resolv_getsock);
+    result = Curl_resolv_pollset(data, ps);
     /* connection filters are not involved in this phase. It's ok if we get no
      * sockets to wait for. Resolving can wake up from other sources. */
     expect_sockets = FALSE;
@@ -1038,31 +1023,36 @@ void Curl_multi_getsock(struct Curl_easy *data,
 
   case MSTATE_CONNECTING:
   case MSTATE_TUNNELING:
-    Curl_pollset_add_socks(data, ps, connecting_getsock);
-    Curl_conn_adjust_pollset(data, data->conn, ps);
+    result = mstate_connecting_pollset(data, ps);
+    if(!result)
+      result = Curl_conn_adjust_pollset(data, data->conn, ps);
     break;
 
   case MSTATE_PROTOCONNECT:
   case MSTATE_PROTOCONNECTING:
-    Curl_pollset_add_socks(data, ps, protocol_getsock);
-    Curl_conn_adjust_pollset(data, data->conn, ps);
+    result = mstate_protocol_pollset(data, ps);
+    if(!result)
+      result = Curl_conn_adjust_pollset(data, data->conn, ps);
     break;
 
   case MSTATE_DO:
   case MSTATE_DOING:
-    Curl_pollset_add_socks(data, ps, doing_getsock);
-    Curl_conn_adjust_pollset(data, data->conn, ps);
+    result = mstate_do_pollset(data, ps);
+    if(!result)
+      result = Curl_conn_adjust_pollset(data, data->conn, ps);
     break;
 
   case MSTATE_DOING_MORE:
-    Curl_pollset_add_socks(data, ps, domore_getsock);
-    Curl_conn_adjust_pollset(data, data->conn, ps);
+    result = mstate_domore_pollset(data, ps);
+    if(!result)
+      result = Curl_conn_adjust_pollset(data, data->conn, ps);
     break;
 
   case MSTATE_DID: /* same as PERFORMING in regard to polling */
   case MSTATE_PERFORMING:
-    Curl_pollset_add_socks(data, ps, perform_getsock);
-    Curl_conn_adjust_pollset(data, data->conn, ps);
+    result = mstate_perform_pollset(data, ps);
+    if(!result)
+      result = Curl_conn_adjust_pollset(data, data->conn, ps);
     break;
 
   case MSTATE_RATELIMITING:
@@ -1084,6 +1074,15 @@ void Curl_multi_getsock(struct Curl_easy *data,
     break;
   }
 
+  if(result) {
+    if(result == CURLE_OUT_OF_MEMORY)
+      mresult = CURLM_OUT_OF_MEMORY;
+    else {
+      failf(data, "error determining pollset: %d", result);
+      mresult = CURLM_INTERNAL_ERROR;
+    }
+    goto out;
+  }
 
   /* Unblocked and waiting to receive with buffered input.
    * Make transfer run again at next opportunity. */
@@ -1097,7 +1096,7 @@ void Curl_multi_getsock(struct Curl_easy *data,
     Curl_multi_mark_dirty(data);
   }
 
-  switch(ps->num) {
+  switch(ps->n) {
     case 0:
       CURL_TRC_M(data, "%s pollset[], timeouts=%zu, paused %d/%d (r/w)",
                  caller, Curl_llist_count(&data->state.timeoutlist),
@@ -1124,10 +1123,10 @@ void Curl_multi_getsock(struct Curl_easy *data,
       break;
     default:
       CURL_TRC_M(data, "%s pollset[fds=%u], timeouts=%zu",
-                 caller, ps->num, Curl_llist_count(&data->state.timeoutlist));
+                 caller, ps->n, Curl_llist_count(&data->state.timeoutlist));
       break;
   }
-  if(expect_sockets && !ps->num && data->multi &&
+  if(expect_sockets && !ps->n && data->multi &&
      !Curl_uint_bset_contains(&data->multi->dirty, data->mid) &&
      !Curl_llist_count(&data->state.timeoutlist) &&
      !Curl_cwriter_is_paused(data) && !Curl_creader_is_paused(data) &&
@@ -1140,6 +1139,8 @@ void Curl_multi_getsock(struct Curl_easy *data,
     infof(data, "WARNING: no socket in pollset or timer, transfer may stall!");
     DEBUGASSERT(0);
   }
+out:
+  return mresult;
 }
 
 CURLMcode curl_multi_fdset(CURLM *m,
@@ -1151,6 +1152,7 @@ CURLMcode curl_multi_fdset(CURLM *m,
      and then we must make sure that is done. */
   int this_max_fd = -1;
   struct Curl_multi *multi = m;
+  struct easy_pollset ps;
   unsigned int i, mid;
   (void)exc_fd_set; /* not used */
 
@@ -1160,18 +1162,18 @@ CURLMcode curl_multi_fdset(CURLM *m,
   if(multi->in_callback)
     return CURLM_RECURSIVE_API_CALL;
 
+  Curl_pollset_init(&ps);
   if(Curl_uint_bset_first(&multi->process, &mid)) {
     do {
       struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
-      struct easy_pollset ps;
 
       if(!data) {
         DEBUGASSERT(0);
         continue;
       }
 
-      Curl_multi_getsock(data, &ps, "curl_multi_fdset");
-      for(i = 0; i < ps.num; i++) {
+      Curl_multi_pollset(data, &ps, "curl_multi_fdset");
+      for(i = 0; i < ps.n; i++) {
         if(!FDSET_SOCK(ps.sockets[i]))
           /* pretend it does not exist */
           continue;
@@ -1197,6 +1199,7 @@ CURLMcode curl_multi_fdset(CURLM *m,
                       read_fd_set, write_fd_set, &this_max_fd);
 
   *max_fd = this_max_fd;
+  Curl_pollset_cleanup(&ps);
 
   return CURLM_OK;
 }
@@ -1209,6 +1212,7 @@ CURLMcode curl_multi_waitfds(CURLM *m,
   struct Curl_waitfds cwfds;
   CURLMcode result = CURLM_OK;
   struct Curl_multi *multi = m;
+  struct easy_pollset ps;
   unsigned int need = 0, mid;
 
   if(!ufds && (size || !fd_count))
@@ -1220,18 +1224,18 @@ CURLMcode curl_multi_waitfds(CURLM *m,
   if(multi->in_callback)
     return CURLM_RECURSIVE_API_CALL;
 
+  Curl_pollset_init(&ps);
   Curl_waitfds_init(&cwfds, ufds, size);
   if(Curl_uint_bset_first(&multi->process, &mid)) {
     do {
       struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
-      struct easy_pollset ps;
       if(!data) {
         DEBUGASSERT(0);
         Curl_uint_bset_remove(&multi->process, mid);
         Curl_uint_bset_remove(&multi->dirty, mid);
         continue;
       }
-      Curl_multi_getsock(data, &ps, "curl_multi_waitfds");
+      Curl_multi_pollset(data, &ps, "curl_multi_waitfds");
       need += Curl_waitfds_add_ps(&cwfds, &ps);
     }
     while(Curl_uint_bset_next(&multi->process, mid, &mid));
@@ -1245,6 +1249,7 @@ CURLMcode curl_multi_waitfds(CURLM *m,
 
   if(fd_count)
     *fd_count = need;
+  Curl_pollset_cleanup(&ps);
   return result;
 }
 
@@ -1278,6 +1283,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
   struct curltime expire_time;
   long timeout_internal;
   int retcode = 0;
+  struct easy_pollset ps;
   struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
   struct curl_pollfds cpfds;
   unsigned int curl_nfds = 0; /* how many pfds are for curl transfers */
@@ -1302,12 +1308,12 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
   if(timeout_ms < 0)
     return CURLM_BAD_FUNCTION_ARGUMENT;
 
+  Curl_pollset_init(&ps);
   Curl_pollfds_init(&cpfds, a_few_on_stack, NUM_POLLS_ON_STACK);
 
   /* Add the curl handles to our pollfds first */
   if(Curl_uint_bset_first(&multi->process, &mid)) {
     do {
-      struct easy_pollset ps;
       data = Curl_multi_get_easy(multi, mid);
       if(!data) {
         DEBUGASSERT(0);
@@ -1315,7 +1321,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
         Curl_uint_bset_remove(&multi->dirty, mid);
         continue;
       }
-      Curl_multi_getsock(data, &ps, "multi_wait");
+      Curl_multi_pollset(data, &ps, "multi_wait");
       if(Curl_pollfds_add_ps(&cpfds, &ps)) {
         result = CURLM_OUT_OF_MEMORY;
         goto out;
@@ -1514,6 +1520,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
   }
 
 out:
+  Curl_pollset_cleanup(&ps);
   Curl_pollfds_cleanup(&cpfds);
   return result;
 }
index 4cde6038054be033100f7634c80573f059caede2..61c639d9e48d1ad3b38506c358b04a5807c66ad5 100644 (file)
@@ -317,7 +317,7 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
   DEBUGASSERT(prev_ps);
 
   /* Handle changes to sockets the transfer is interested in. */
-  for(i = 0; i < ps->num; i++) {
+  for(i = 0; i < ps->n; i++) {
     unsigned char last_action;
     bool first_time = FALSE; /* data/conn appears first time on socket */
 
@@ -362,7 +362,7 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
                  entry->conn ? 1 : 0);
     }
     else {
-      for(j = 0; j < prev_ps->num; j++) {
+      for(j = 0; j < prev_ps->n; j++) {
         if(s == prev_ps->sockets[j]) {
           last_action = prev_ps->actions[j];
           break;
@@ -377,11 +377,11 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
   }
 
   /* Handle changes to sockets the transfer is NO LONGER interested in. */
-  for(i = 0; i < prev_ps->num; i++) {
+  for(i = 0; i < prev_ps->n; i++) {
     bool stillused = FALSE;
 
     s = prev_ps->sockets[i];
-    for(j = 0; j < ps->num; j++) {
+    for(j = 0; j < ps->n; j++) {
       if(s == ps->sockets[j]) {
         /* socket is still supervised */
         stillused = TRUE;
@@ -437,15 +437,19 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
   } /* for loop over num */
 
   /* Remember for next time */
-  memcpy(prev_ps, ps, sizeof(*prev_ps));
+  Curl_pollset_move(prev_ps, ps);
   return CURLM_OK;
 }
 
 static void mev_pollset_dtor(void *key, size_t klen, void *entry)
 {
+  struct easy_pollset *ps = entry;
   (void)key;
   (void)klen;
-  free(entry);
+  if(ps) {
+    Curl_pollset_cleanup(ps);
+    free(ps);
+  }
 }
 
 static struct easy_pollset*
@@ -453,7 +457,7 @@ mev_add_new_conn_pollset(struct connectdata *conn)
 {
   struct easy_pollset *ps;
 
-  ps = calloc(1, sizeof(*ps));
+  ps = Curl_pollset_create();
   if(!ps)
     return NULL;
   if(Curl_conn_meta_set(conn, CURL_META_MEV_POLLSET, ps, mev_pollset_dtor))
@@ -466,7 +470,7 @@ mev_add_new_xfer_pollset(struct Curl_easy *data)
 {
   struct easy_pollset *ps;
 
-  ps = calloc(1, sizeof(*ps));
+  ps = Curl_pollset_create();
   if(!ps)
     return NULL;
   if(Curl_meta_set(data, CURL_META_MEV_POLLSET, ps, mev_pollset_dtor))
@@ -486,42 +490,47 @@ mev_get_last_pollset(struct Curl_easy *data,
   return NULL;
 }
 
-static void mev_init_cur_pollset(struct easy_pollset *ps,
-                                 struct Curl_easy *data,
-                                 struct connectdata *conn)
-{
-  memset(ps, 0, sizeof(*ps));
-  if(conn)
-    Curl_conn_adjust_pollset(data, conn, ps);
-  else if(data)
-    Curl_multi_getsock(data, ps, "ev assess");
-}
-
 static CURLMcode mev_assess(struct Curl_multi *multi,
                             struct Curl_easy *data,
                             struct connectdata *conn)
 {
-  if(multi && multi->socket_cb) {
-    struct easy_pollset ps, *last_ps;
+  struct easy_pollset ps, *last_ps;
+  CURLMcode res = CURLM_OK;
 
-    mev_init_cur_pollset(&ps, data, conn);
-    last_ps = mev_get_last_pollset(data, conn);
+  if(!multi || !multi->socket_cb)
+    return CURLM_OK;
 
-    if(!last_ps && ps.num) {
-      if(conn)
-        last_ps = mev_add_new_conn_pollset(conn);
-      else
-        last_ps = mev_add_new_xfer_pollset(data);
-      if(!last_ps)
-        return CURLM_OUT_OF_MEMORY;
+  Curl_pollset_init(&ps);
+  if(conn) {
+    CURLcode r = Curl_conn_adjust_pollset(data, conn, &ps);
+    if(r) {
+      res = (r == CURLE_OUT_OF_MEMORY) ?
+            CURLM_OUT_OF_MEMORY : CURLM_INTERNAL_ERROR;
+      goto out;
     }
+  }
+  else if(data)
+    Curl_multi_pollset(data, &ps, "ev assess");
+  last_ps = mev_get_last_pollset(data, conn);
 
-    if(last_ps)
-      return mev_pollset_diff(multi, data, conn, &ps, last_ps);
+  if(!last_ps && ps.n) {
+    if(conn)
+      last_ps = mev_add_new_conn_pollset(conn);
     else
-      DEBUGASSERT(!ps.num);
+      last_ps = mev_add_new_xfer_pollset(data);
+    if(!last_ps) {
+      res = CURLM_OUT_OF_MEMORY;
+      goto out;
+    }
   }
-  return CURLM_OK;
+
+  if(last_ps)
+    res = mev_pollset_diff(multi, data, conn, &ps, last_ps);
+  else
+    DEBUGASSERT(!ps.n);
+out:
+  Curl_pollset_cleanup(&ps);
+  return res;
 }
 
 CURLMcode Curl_multi_ev_assess_xfer(struct Curl_multi *multi,
index dbad164bc53d8512474d44152807488247e4f3b2..cdedfb08ab0663d85f98046b41d243c98eb10fc7 100644 (file)
@@ -72,12 +72,6 @@ typedef enum {
   MSTATE_LAST          /* 18 - not a true state, never use this */
 } CURLMstate;
 
-/* we support N sockets per easy handle. Set the corresponding bit to what
-   action we should wait for */
-#define MAX_SOCKSPEREASYHANDLE 5
-#define GETSOCK_READABLE (0x00ff)
-#define GETSOCK_WRITABLE (0xff00)
-
 #define CURLPIPE_ANY (CURLPIPE_MULTIPLEX)
 
 #ifndef CURL_DISABLE_SOCKETPAIR
index 1ba0d0f83879b652a5fa2d17d1c65b9fc5145166..5cf22bc0467d97247470e9e331cf711481871d03 100644 (file)
@@ -53,20 +53,6 @@ struct Curl_multi *Curl_multi_handle(unsigned int xfer_table_size,
                                      size_t dnssize,
                                      size_t sesssize);
 
-/* the write bits start at bit 16 for the *getsock() bitmap */
-#define GETSOCK_WRITEBITSTART 16
-
-#define GETSOCK_BLANK 0 /* no bits set */
-
-/* set the bit for the given sock number to make the bitmap for writable */
-#define GETSOCK_WRITESOCK(x) (1 << (GETSOCK_WRITEBITSTART + (x)))
-
-/* set the bit for the given sock number to make the bitmap for readable */
-#define GETSOCK_READSOCK(x) (1 << (x))
-
-/* mask for checking if read and/or write is set for index x */
-#define GETSOCK_MASK_RW(x) (GETSOCK_READSOCK(x)|GETSOCK_WRITESOCK(x))
-
 /**
  * Let the multi handle know that the socket is about to be closed.
  * The multi will then remove anything it knows about the socket, so
@@ -86,9 +72,9 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
 /* Return the value of the CURLMOPT_MAX_CONCURRENT_STREAMS option */
 unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi);
 
-void Curl_multi_getsock(struct Curl_easy *data,
-                        struct easy_pollset *ps,
-                        const char *caller);
+CURLMcode Curl_multi_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps,
+                             const char *caller);
 
 /**
  * Borrow the transfer buffer from the multi, suitable
index b0cb26c7ffa733ca23467bfbb648966eb90cc3c9..c532be3f3243e7e5928ebec7835bf9582ee30a04 100644 (file)
@@ -126,10 +126,10 @@ const struct Curl_handler Curl_handler_ldap = {
   oldap_connect,                        /* connect_it */
   oldap_connecting,                     /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   oldap_disconnect,                     /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -156,10 +156,10 @@ const struct Curl_handler Curl_handler_ldaps = {
   oldap_connect,                        /* connect_it */
   oldap_connecting,                     /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   oldap_disconnect,                     /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
index a661a0285b524e026708e3e6f45501e810f3fbc7..003ad58441c7b672bc8e0857ad96e7293fe5d624 100644 (file)
@@ -397,19 +397,13 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
   return result;
 }
 
-int Curl_pp_getsock(struct Curl_easy *data,
-                    struct pingpong *pp, curl_socket_t *socks)
+CURLcode Curl_pp_pollset(struct Curl_easy *data,
+                         struct pingpong *pp,
+                         struct easy_pollset *ps)
 {
-  struct connectdata *conn = data->conn;
-  socks[0] = conn->sock[FIRSTSOCKET];
-
-  if(pp->sendleft) {
-    /* write mode */
-    return GETSOCK_WRITESOCK(0);
-  }
-
-  /* read mode */
-  return GETSOCK_READSOCK(0);
+  int flags = pp->sendleft ? CURL_POLL_OUT : CURL_POLL_IN;
+  return Curl_pollset_change(data, ps, data->conn->sock[FIRSTSOCKET],
+                             flags, 0);
 }
 
 bool Curl_pp_needs_flush(struct Curl_easy *data,
index c6d0a56f0d2611195ebb22b51ef0fc052101266c..5db96c4345f8af8909fcfafbf15d8f6e81e27024 100644 (file)
@@ -147,8 +147,9 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data,
 /* call this when a pingpong connection is disconnected */
 CURLcode Curl_pp_disconnect(struct pingpong *pp);
 
-int Curl_pp_getsock(struct Curl_easy *data, struct pingpong *pp,
-                    curl_socket_t *socks);
+CURLcode Curl_pp_pollset(struct Curl_easy *data,
+                         struct pingpong *pp,
+                         struct easy_pollset *ps);
 
 
 /***********************************************************************
index 514c4b8fa539da9483239cf784d2aea295f446ad..493b36f45fdede608f63375fdce28da4636a402a 100644 (file)
@@ -153,8 +153,8 @@ static CURLcode pop3_connect(struct Curl_easy *data, bool *done);
 static CURLcode pop3_disconnect(struct Curl_easy *data,
                                 struct connectdata *conn, bool dead);
 static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done);
-static int pop3_getsock(struct Curl_easy *data,
-                        struct connectdata *conn, curl_socket_t *socks);
+static CURLcode pop3_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps);
 static CURLcode pop3_doing(struct Curl_easy *data, bool *dophase_done);
 static CURLcode pop3_setup_connection(struct Curl_easy *data,
                                       struct connectdata *conn);
@@ -186,10 +186,10 @@ const struct Curl_handler Curl_handler_pop3 = {
   pop3_connect,                     /* connect_it */
   pop3_multi_statemach,             /* connecting */
   pop3_doing,                       /* doing */
-  pop3_getsock,                     /* proto_getsock */
-  pop3_getsock,                     /* doing_getsock */
-  ZERO_NULL,                        /* domore_getsock */
-  ZERO_NULL,                        /* perform_getsock */
+  pop3_pollset,                     /* proto_pollset */
+  pop3_pollset,                     /* doing_pollset */
+  ZERO_NULL,                        /* domore_pollset */
+  ZERO_NULL,                        /* perform_pollset */
   pop3_disconnect,                  /* disconnect */
   pop3_write,                       /* write_resp */
   ZERO_NULL,                        /* write_resp_hd */
@@ -217,10 +217,10 @@ const struct Curl_handler Curl_handler_pop3s = {
   pop3_connect,                     /* connect_it */
   pop3_multi_statemach,             /* connecting */
   pop3_doing,                       /* doing */
-  pop3_getsock,                     /* proto_getsock */
-  pop3_getsock,                     /* doing_getsock */
-  ZERO_NULL,                        /* domore_getsock */
-  ZERO_NULL,                        /* perform_getsock */
+  pop3_pollset,                     /* proto_pollset */
+  pop3_pollset,                     /* doing_pollset */
+  ZERO_NULL,                        /* domore_pollset */
+  ZERO_NULL,                        /* perform_pollset */
   pop3_disconnect,                  /* disconnect */
   pop3_write,                       /* write_resp */
   ZERO_NULL,                        /* write_resp_hd */
@@ -1269,13 +1269,12 @@ static CURLcode pop3_block_statemach(struct Curl_easy *data,
 }
 
 /* For the POP3 "protocol connect" and "doing" phases only */
-static int pop3_getsock(struct Curl_easy *data,
-                        struct connectdata *conn, curl_socket_t *socks)
+static CURLcode pop3_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps)
 {
-  struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
-  if(pop3c)
-    return Curl_pp_getsock(data, &pop3c->pp, socks);
-  return GETSOCK_BLANK;
+  struct pop3_conn *pop3c =
+    Curl_conn_meta_get(data->conn, CURL_META_POP3_CONN);
+  return pop3c ? Curl_pp_pollset(data, &pop3c->pp, ps) : CURLE_OK;
 }
 
 /***********************************************************************
index d50624158e9a11ca14eab503b227297ac658c625..46ff660aed852640152742a2cf8a0ada408e108a 100644 (file)
@@ -83,8 +83,8 @@ struct RTSP {
 static CURLcode rtsp_do(struct Curl_easy *data, bool *done);
 static CURLcode rtsp_done(struct Curl_easy *data, CURLcode, bool premature);
 static CURLcode rtsp_connect(struct Curl_easy *data, bool *done);
-static int rtsp_getsock_do(struct Curl_easy *data,
-                           struct connectdata *conn, curl_socket_t *socks);
+static CURLcode rtsp_do_pollset(struct Curl_easy *data,
+                                struct easy_pollset *ps);
 
 /*
  * Parse and write out an RTSP response.
@@ -110,13 +110,11 @@ static unsigned int rtsp_conncheck(struct Curl_easy *data,
 /* this returns the socket to wait for in the DO and DOING state for the multi
    interface and then we are always _sending_ a request and thus we wait for
    the single socket to become writable only */
-static int rtsp_getsock_do(struct Curl_easy *data, struct connectdata *conn,
-                           curl_socket_t *socks)
+static CURLcode rtsp_do_pollset(struct Curl_easy *data,
+                                struct easy_pollset *ps)
 {
   /* write mode */
-  (void)data;
-  socks[0] = conn->sock[FIRSTSOCKET];
-  return GETSOCK_WRITESOCK(0);
+  return Curl_pollset_add_out(data, ps, data->conn->sock[FIRSTSOCKET]);
 }
 
 static
@@ -137,10 +135,10 @@ const struct Curl_handler Curl_handler_rtsp = {
   rtsp_connect,                         /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  rtsp_getsock_do,                      /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  rtsp_do_pollset,                      /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   rtsp_rtp_write_resp,                  /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
index 2353c474df3ae147ce0de39213665fb9a026f22c..af78cb836b0be26b3af581478507c3b8b5d7eac6 100644 (file)
@@ -41,6 +41,7 @@
 #include "urldata.h"
 #include "connect.h"
 #include "select.h"
+#include "curl_trc.h"
 #include "curlx/timediff.h"
 #include "curlx/wait.h"
 #include "curlx/warnless.h"
@@ -423,7 +424,7 @@ CURLcode Curl_pollfds_add_ps(struct curl_pollfds *cpfds,
 
   DEBUGASSERT(cpfds);
   DEBUGASSERT(ps);
-  for(i = 0; i < ps->num; i++) {
+  for(i = 0; i < ps->n; i++) {
     short events = 0;
     if(ps->actions[i] & CURL_POLL_IN)
       events |= POLLIN;
@@ -481,7 +482,7 @@ unsigned int Curl_waitfds_add_ps(struct Curl_waitfds *cwfds,
 
   DEBUGASSERT(cwfds);
   DEBUGASSERT(ps);
-  for(i = 0; i < ps->num; i++) {
+  for(i = 0; i < ps->n; i++) {
     short events = 0;
     if(ps->actions[i] & CURL_POLL_IN)
       events |= CURL_WAIT_POLLIN;
@@ -492,3 +493,233 @@ unsigned int Curl_waitfds_add_ps(struct Curl_waitfds *cwfds,
   }
   return need;
 }
+
+void Curl_pollset_reset(struct easy_pollset *ps)
+{
+  unsigned int i;
+  ps->n = 0;
+#ifdef DEBUGBUILD
+  DEBUGASSERT(ps->init == CURL_EASY_POLLSET_MAGIC);
+#endif
+  DEBUGASSERT(ps->count);
+  for(i = 0; i < ps->count; i++)
+    ps->sockets[i] = CURL_SOCKET_BAD;
+  memset(ps->actions, 0, ps->count * sizeof(ps->actions[0]));
+}
+
+void Curl_pollset_init(struct easy_pollset *ps)
+{
+#ifdef DEBUGBUILD
+  ps->init = CURL_EASY_POLLSET_MAGIC;
+#endif
+  ps->sockets = ps->def_sockets;
+  ps->actions = ps->def_actions;
+  ps->count = CURL_ARRAYSIZE(ps->def_sockets);
+  ps->n = 0;
+  Curl_pollset_reset(ps);
+}
+
+struct easy_pollset *Curl_pollset_create(void)
+{
+  struct easy_pollset *ps = calloc(1, sizeof(*ps));
+  if(ps)
+    Curl_pollset_init(ps);
+  return ps;
+}
+
+void Curl_pollset_cleanup(struct easy_pollset *ps)
+{
+#ifdef DEBUGBUILD
+  DEBUGASSERT(ps->init == CURL_EASY_POLLSET_MAGIC);
+#endif
+  if(ps->sockets != ps->def_sockets) {
+    free(ps->sockets);
+    ps->sockets = ps->def_sockets;
+  }
+  if(ps->actions != ps->def_actions) {
+    free(ps->actions);
+    ps->actions = ps->def_actions;
+  }
+  ps->count = CURL_ARRAYSIZE(ps->def_sockets);
+  Curl_pollset_reset(ps);
+}
+
+void Curl_pollset_move(struct easy_pollset *to, struct easy_pollset *from)
+{
+  Curl_pollset_cleanup(to); /* deallocate anything in to */
+  if(from->sockets != from->def_sockets) {
+    DEBUGASSERT(from->actions != from->def_actions);
+    to->sockets = from->sockets;
+    to->actions = from->actions;
+    to->count = from->count;
+    to->n = from->n;
+    Curl_pollset_init(from);
+  }
+  else {
+    DEBUGASSERT(to->sockets == to->def_sockets);
+    DEBUGASSERT(to->actions == to->def_actions);
+    memcpy(to->sockets, from->sockets, to->count * sizeof(to->sockets[0]));
+    memcpy(to->actions, from->actions, to->count * sizeof(to->actions[0]));
+    to->n = from->n;
+    Curl_pollset_init(from);
+  }
+}
+
+/**
+ *
+ */
+CURLcode Curl_pollset_change(struct Curl_easy *data,
+                             struct easy_pollset *ps, curl_socket_t sock,
+                             int add_flags, int remove_flags)
+{
+  unsigned int i;
+
+#ifdef DEBUGBUILD
+  DEBUGASSERT(ps->init == CURL_EASY_POLLSET_MAGIC);
+#endif
+
+  (void)data;
+  DEBUGASSERT(VALID_SOCK(sock));
+  if(!VALID_SOCK(sock))
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  DEBUGASSERT(add_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
+  DEBUGASSERT(remove_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
+  DEBUGASSERT((add_flags&remove_flags) == 0); /* no overlap */
+  for(i = 0; i < ps->n; ++i) {
+    if(ps->sockets[i] == sock) {
+      ps->actions[i] &= (unsigned char)(~remove_flags);
+      ps->actions[i] |= (unsigned char)add_flags;
+      /* all gone? remove socket */
+      if(!ps->actions[i]) {
+        if((i + 1) < ps->n) {
+          memmove(&ps->sockets[i], &ps->sockets[i + 1],
+                  (ps->n - (i + 1)) * sizeof(ps->sockets[0]));
+          memmove(&ps->actions[i], &ps->actions[i + 1],
+                  (ps->n - (i + 1)) * sizeof(ps->actions[0]));
+        }
+        --ps->n;
+      }
+      return CURLE_OK;
+    }
+  }
+  /* not present */
+  if(add_flags) {
+    if(i >= ps->count) { /* need to grow */
+      unsigned int new_count = CURLMAX(ps->count * 2, 8);
+      curl_socket_t *nsockets;
+      unsigned char *nactions;
+
+      CURL_TRC_M(data, "growing pollset capacity from %u to %u",
+                 ps->count, new_count);
+      if(new_count <= ps->count)
+        return CURLE_OUT_OF_MEMORY;
+      nsockets = calloc(new_count, sizeof(nsockets[0]));
+      if(!nsockets)
+        return CURLE_OUT_OF_MEMORY;
+      nactions = calloc(new_count, sizeof(nactions[0]));
+      if(!nactions) {
+        free(nsockets);
+        return CURLE_OUT_OF_MEMORY;
+      }
+      memcpy(nsockets, ps->sockets, ps->count * sizeof(ps->sockets[0]));
+      memcpy(nactions, ps->actions, ps->count * sizeof(ps->actions[0]));
+      if(ps->sockets != ps->def_sockets)
+        free(ps->sockets);
+      ps->sockets = nsockets;
+      if(ps->actions != ps->def_actions)
+        free(ps->actions);
+      ps->actions = nactions;
+      ps->count = new_count;
+    }
+    DEBUGASSERT(i < ps->count);
+    if(i < ps->count) {
+      ps->sockets[i] = sock;
+      ps->actions[i] = (unsigned char)add_flags;
+      ps->n = i + 1;
+    }
+  }
+  return CURLE_OK;
+}
+
+CURLcode Curl_pollset_set(struct Curl_easy *data,
+                          struct easy_pollset *ps, curl_socket_t sock,
+                          bool do_in, bool do_out)
+{
+  return Curl_pollset_change(data, ps, sock,
+                             (do_in ? CURL_POLL_IN : 0)|
+                             (do_out ? CURL_POLL_OUT : 0),
+                             (!do_in ? CURL_POLL_IN : 0)|
+                             (!do_out ? CURL_POLL_OUT : 0));
+}
+
+int Curl_pollset_poll(struct Curl_easy *data,
+                      struct easy_pollset *ps,
+                      timediff_t timeout_ms)
+{
+  struct pollfd *pfds;
+  unsigned int i, npfds;
+  int result;
+
+  (void)data;
+  DEBUGASSERT(data);
+  DEBUGASSERT(data->conn);
+
+  if(!ps->n)
+    return curlx_wait_ms(timeout_ms);
+
+  pfds = calloc(ps->n, sizeof(*pfds));
+  if(!pfds)
+    return -1;
+
+  npfds = 0;
+  for(i = 0; i < ps->n; ++i) {
+    short events = 0;
+    if(ps->actions[i] & CURL_POLL_IN) {
+      events |= POLLIN;
+    }
+    if(ps->actions[i] & CURL_POLL_OUT) {
+      events |= POLLOUT;
+    }
+    if(events) {
+      pfds[npfds].fd = ps->sockets[i];
+      pfds[npfds].events = events;
+      ++npfds;
+    }
+  }
+
+  result = Curl_poll(pfds, npfds, timeout_ms);
+  free(pfds);
+  return result;
+}
+
+void Curl_pollset_check(struct Curl_easy *data,
+                        struct easy_pollset *ps, curl_socket_t sock,
+                        bool *pwant_read, bool *pwant_write)
+{
+  unsigned int i;
+
+  (void)data;
+  DEBUGASSERT(VALID_SOCK(sock));
+  for(i = 0; i < ps->n; ++i) {
+    if(ps->sockets[i] == sock) {
+      *pwant_read = !!(ps->actions[i] & CURL_POLL_IN);
+      *pwant_write = !!(ps->actions[i] & CURL_POLL_OUT);
+      return;
+    }
+  }
+  *pwant_read = *pwant_write = FALSE;
+}
+
+bool Curl_pollset_want_read(struct Curl_easy *data,
+                            struct easy_pollset *ps,
+                            curl_socket_t sock)
+{
+  unsigned int i;
+  (void)data;
+  for(i = 0; i < ps->n; ++i) {
+    if((ps->sockets[i] == sock) && (ps->actions[i] & CURL_POLL_IN))
+      return TRUE;
+  }
+  return FALSE;
+}
index e9cec600f3b7eea9927896faad1ca0bf184ab2a1..47cdd31267f2d2241f578e2e26f384ffcfa38a5b 100644 (file)
@@ -110,6 +110,90 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms);
   } while(0)
 #endif
 
+
+/* Keep the sockets to poll for an easy handle.
+ * `actions` are bitmaps of CURL_POLL_IN and CURL_POLL_OUT.
+ * Starts with small capacity, grows on demand.
+ */
+#define EZ_POLLSET_DEF_COUNT    2
+
+struct easy_pollset {
+  curl_socket_t *sockets;
+  unsigned char *actions;
+  unsigned int n;
+  unsigned int count;
+#ifdef DEBUGBUILD
+  int init;
+#endif
+  curl_socket_t def_sockets[EZ_POLLSET_DEF_COUNT];
+  unsigned char def_actions[EZ_POLLSET_DEF_COUNT];
+};
+
+#ifdef DEBUGBUILD
+#define CURL_EASY_POLLSET_MAGIC  0x7a657370
+#endif
+
+
+/* allocate and initialise */
+struct easy_pollset *Curl_pollset_create(void);
+
+/* Initialize before first use */
+void Curl_pollset_init(struct easy_pollset *ps);
+/* Free any allocated resources */
+void Curl_pollset_cleanup(struct easy_pollset *ps);
+/* Reset to an empty pollset */
+void Curl_pollset_reset(struct easy_pollset *ps);
+/* Move pollset from to pollset to, replacing all in to,
+ * leaving from empty. */
+void Curl_pollset_move(struct easy_pollset *to, struct easy_pollset *from);
+
+/* Change the poll flags (CURL_POLL_IN/CURL_POLL_OUT) to the poll set for
+ * socket `sock`. If the socket is not already part of the poll set, it
+ * will be added.
+ * If the socket is present and all poll flags are cleared, it will be removed.
+ */
+CURLcode Curl_pollset_change(struct Curl_easy *data,
+                             struct easy_pollset *ps, curl_socket_t sock,
+                             int add_flags, int remove_flags);
+
+CURLcode Curl_pollset_set(struct Curl_easy *data,
+                          struct easy_pollset *ps, curl_socket_t sock,
+                          bool do_in, bool do_out);
+
+#define Curl_pollset_add_in(data, ps, sock) \
+          Curl_pollset_change((data), (ps), (sock), CURL_POLL_IN, 0)
+#define Curl_pollset_add_out(data, ps, sock) \
+          Curl_pollset_change((data), (ps), (sock), CURL_POLL_OUT, 0)
+#define Curl_pollset_add_inout(data, ps, sock) \
+          Curl_pollset_change((data), (ps), (sock), \
+                               CURL_POLL_IN|CURL_POLL_OUT, 0)
+#define Curl_pollset_set_in_only(data, ps, sock) \
+          Curl_pollset_change((data), (ps), (sock), \
+                               CURL_POLL_IN, CURL_POLL_OUT)
+#define Curl_pollset_set_out_only(data, ps, sock) \
+          Curl_pollset_change((data), (ps), (sock), \
+                               CURL_POLL_OUT, CURL_POLL_IN)
+
+/* return < = on error, 0 on timeout or how many sockets are ready */
+int Curl_pollset_poll(struct Curl_easy *data,
+                      struct easy_pollset *ps,
+                      timediff_t timeout_ms);
+
+/**
+ * Check if the pollset, as is, wants to read and/or write regarding
+ * the given socket.
+ */
+void Curl_pollset_check(struct Curl_easy *data,
+                        struct easy_pollset *ps, curl_socket_t sock,
+                        bool *pwant_read, bool *pwant_write);
+
+/**
+ * Return TRUE if the pollset contains socket with CURL_POLL_IN.
+ */
+bool Curl_pollset_want_read(struct Curl_easy *data,
+                            struct easy_pollset *ps,
+                            curl_socket_t sock);
+
 struct curl_pollfds {
   struct pollfd *pfds;
   unsigned int n;
index d6ef8f6f1df31ee396e855bc34ecad9d58d663cc..81cf6e7cc1f4707421b46ba03554d672c2f7b807 100644 (file)
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -36,6 +36,7 @@
 #include "connect.h"
 #include "progress.h"
 #include "transfer.h"
+#include "select.h"
 #include "vtls/vtls.h"
 #include "curl_ntlm_core.h"
 #include "escape.h"
@@ -298,8 +299,8 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done);
 static CURLcode smb_connection_state(struct Curl_easy *data, bool *done);
 static CURLcode smb_do(struct Curl_easy *data, bool *done);
 static CURLcode smb_request_state(struct Curl_easy *data, bool *done);
-static int smb_getsock(struct Curl_easy *data, struct connectdata *conn,
-                       curl_socket_t *socks);
+static CURLcode smb_pollset(struct Curl_easy *data,
+                            struct easy_pollset *ps);
 static CURLcode smb_parse_url_path(struct Curl_easy *data,
                                    struct smb_conn *smbc,
                                    struct smb_request *req);
@@ -316,10 +317,10 @@ const struct Curl_handler Curl_handler_smb = {
   smb_connect,                          /* connect_it */
   smb_connection_state,                 /* connecting */
   smb_request_state,                    /* doing */
-  smb_getsock,                          /* proto_getsock */
-  smb_getsock,                          /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  smb_pollset,                          /* proto_pollset */
+  smb_pollset,                          /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -345,10 +346,10 @@ const struct Curl_handler Curl_handler_smbs = {
   smb_connect,                          /* connect_it */
   smb_connection_state,                 /* connecting */
   smb_request_state,                    /* doing */
-  smb_getsock,                          /* proto_getsock */
-  smb_getsock,                          /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  smb_pollset,                          /* proto_pollset */
+  smb_pollset,                          /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -1204,12 +1205,10 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
   return CURLE_OK;
 }
 
-static int smb_getsock(struct Curl_easy *data,
-                       struct connectdata *conn, curl_socket_t *socks)
+static CURLcode smb_pollset(struct Curl_easy *data,
+                            struct easy_pollset *ps)
 {
-  (void)data;
-  socks[0] = conn->sock[FIRSTSOCKET];
-  return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
+  return Curl_pollset_add_inout(data, ps, data->conn->sock[FIRSTSOCKET]);
 }
 
 static CURLcode smb_do(struct Curl_easy *data, bool *done)
index 13b89b6ecce1fd881d7803054637f5441fed3fac..4bb3bde4afa4d882e28ed92482a1cc88ccd4de85 100644 (file)
@@ -157,8 +157,8 @@ static CURLcode smtp_connect(struct Curl_easy *data, bool *done);
 static CURLcode smtp_disconnect(struct Curl_easy *data,
                                 struct connectdata *conn, bool dead);
 static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done);
-static int smtp_getsock(struct Curl_easy *data,
-                        struct connectdata *conn, curl_socket_t *socks);
+static CURLcode smtp_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps);
 static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done);
 static CURLcode smtp_setup_connection(struct Curl_easy *data,
                                       struct connectdata *conn);
@@ -192,10 +192,10 @@ const struct Curl_handler Curl_handler_smtp = {
   smtp_connect,                     /* connect_it */
   smtp_multi_statemach,             /* connecting */
   smtp_doing,                       /* doing */
-  smtp_getsock,                     /* proto_getsock */
-  smtp_getsock,                     /* doing_getsock */
-  ZERO_NULL,                        /* domore_getsock */
-  ZERO_NULL,                        /* perform_getsock */
+  smtp_pollset,                     /* proto_pollset */
+  smtp_pollset,                     /* doing_pollset */
+  ZERO_NULL,                        /* domore_pollset */
+  ZERO_NULL,                        /* perform_pollset */
   smtp_disconnect,                  /* disconnect */
   ZERO_NULL,                        /* write_resp */
   ZERO_NULL,                        /* write_resp_hd */
@@ -223,10 +223,10 @@ const struct Curl_handler Curl_handler_smtps = {
   smtp_connect,                     /* connect_it */
   smtp_multi_statemach,             /* connecting */
   smtp_doing,                       /* doing */
-  smtp_getsock,                     /* proto_getsock */
-  smtp_getsock,                     /* doing_getsock */
-  ZERO_NULL,                        /* domore_getsock */
-  ZERO_NULL,                        /* perform_getsock */
+  smtp_pollset,                     /* proto_pollset */
+  smtp_pollset,                     /* doing_pollset */
+  ZERO_NULL,                        /* domore_pollset */
+  ZERO_NULL,                        /* perform_pollset */
   smtp_disconnect,                  /* disconnect */
   ZERO_NULL,                        /* write_resp */
   ZERO_NULL,                        /* write_resp_hd */
@@ -1413,12 +1413,12 @@ static CURLcode smtp_block_statemach(struct Curl_easy *data,
 }
 
 /* For the SMTP "protocol connect" and "doing" phases only */
-static int smtp_getsock(struct Curl_easy *data,
-                        struct connectdata *conn, curl_socket_t *socks)
+static CURLcode smtp_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps)
 {
-  struct smtp_conn *smtpc = Curl_conn_meta_get(conn, CURL_META_SMTP_CONN);
-  return smtpc ?
-         Curl_pp_getsock(data, &smtpc->pp, socks) : GETSOCK_BLANK;
+  struct smtp_conn *smtpc =
+    Curl_conn_meta_get(data->conn, CURL_META_SMTP_CONN);
+  return smtpc ? Curl_pp_pollset(data, &smtpc->pp, ps) : CURLE_OK;
 }
 
 /***********************************************************************
index 64795d69ee8b62418fc73bcead0ef6dbe9360d3d..4f9c98dbaad6dc35b2f352db2b846553b5d17553 100644 (file)
@@ -1161,11 +1161,12 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
   return result;
 }
 
-static void socks_cf_adjust_pollset(struct Curl_cfilter *cf,
-                                    struct Curl_easy *data,
-                                    struct easy_pollset *ps)
+static CURLcode socks_cf_adjust_pollset(struct Curl_cfilter *cf,
+                                        struct Curl_easy *data,
+                                        struct easy_pollset *ps)
 {
   struct socks_state *sx = cf->ctx;
+  CURLcode result = CURLE_OK;
 
   if(!cf->connected && sx) {
     /* If we are not connected, the filter below is and has nothing
@@ -1177,13 +1178,14 @@ static void socks_cf_adjust_pollset(struct Curl_cfilter *cf,
     case CONNECT_AUTH_READ:
     case CONNECT_REQ_READ:
     case CONNECT_REQ_READ_MORE:
-      Curl_pollset_set_in_only(data, ps, sock);
+      result = Curl_pollset_set_in_only(data, ps, sock);
       break;
     default:
-      Curl_pollset_set_out_only(data, ps, sock);
+      result = Curl_pollset_set_out_only(data, ps, sock);
       break;
     }
   }
+  return result;
 }
 
 static void socks_proxy_cf_close(struct Curl_cfilter *cf,
index bd599dece260eaa25eceab17c443d8c98eca01e9..731789e4636e8ca78c912e16070220d3510e5274 100644 (file)
@@ -188,10 +188,10 @@ const struct Curl_handler Curl_handler_telnet = {
   ZERO_NULL,                            /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  ZERO_NULL,                            /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  ZERO_NULL,                            /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
index 5ea986dbb4b01adc29f28a931823364b9d04e032..6a9f964a079f96a48876dcf5dee30d3b264bbabc 100644 (file)
@@ -160,8 +160,8 @@ static CURLcode tftp_setup_connection(struct Curl_easy *data,
                                       struct connectdata *conn);
 static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done);
 static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done);
-static int tftp_getsock(struct Curl_easy *data, struct connectdata *conn,
-                        curl_socket_t *socks);
+static CURLcode tftp_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps);
 static CURLcode tftp_translate_code(tftp_error_t error);
 
 
@@ -178,10 +178,10 @@ const struct Curl_handler Curl_handler_tftp = {
   tftp_connect,                         /* connect_it */
   tftp_multi_statemach,                 /* connecting */
   tftp_doing,                           /* doing */
-  tftp_getsock,                         /* proto_getsock */
-  tftp_getsock,                         /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  tftp_pollset,                         /* proto_pollset */
+  tftp_pollset,                         /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -1074,19 +1074,10 @@ static CURLcode tftp_done(struct Curl_easy *data, CURLcode status,
   return result;
 }
 
-/**********************************************************
- *
- * tftp_getsock
- *
- * The getsock callback
- *
- **********************************************************/
-static int tftp_getsock(struct Curl_easy *data,
-                        struct connectdata *conn, curl_socket_t *socks)
+static CURLcode tftp_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps)
 {
-  (void)data;
-  socks[0] = conn->sock[FIRSTSOCKET];
-  return GETSOCK_READSOCK(0);
+  return Curl_pollset_add_in(data, ps, data->conn->sock[FIRSTSOCKET]);
 }
 
 /**********************************************************
index 92278226be25b4ae55dc5454ed30c4a6c97b43f0..157c6b991ea5baeec1220ffa867061496f4c3eee 100644 (file)
@@ -34,8 +34,6 @@ void Curl_init_CONNECT(struct Curl_easy *data);
 CURLcode Curl_pretransfer(struct Curl_easy *data);
 
 CURLcode Curl_sendrecv(struct Curl_easy *data, struct curltime *nowp);
-int Curl_single_getsock(struct Curl_easy *data,
-                        struct connectdata *conn, curl_socket_t *socks);
 CURLcode Curl_retry_request(struct Curl_easy *data, char **url);
 bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc);
 
index 83d7b50e448d2382dc6c36820fe22db94fd0801e..ea31d9f5c80a3c139921a3ee50318ed4387c9eaf 100644 (file)
@@ -471,15 +471,6 @@ struct hostname {
 #define FIRSTSOCKET     0
 #define SECONDARYSOCKET 1
 
-/* Polling requested by an easy handle.
- * `action` is CURL_POLL_IN, CURL_POLL_OUT or CURL_POLL_INOUT.
- */
-struct easy_pollset {
-  curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
-  unsigned int num;
-  unsigned char actions[MAX_SOCKSPEREASYHANDLE];
-};
-
 /*
  * Specific protocol handler.
  */
@@ -516,24 +507,24 @@ struct Curl_handler {
 
   /* Called from the multi interface during the PROTOCONNECT phase, and it
      should then return a proper fd set */
-  int (*proto_getsock)(struct Curl_easy *data,
-                       struct connectdata *conn, curl_socket_t *socks);
+  CURLcode (*proto_pollset)(struct Curl_easy *data,
+                            struct easy_pollset *ps);
 
   /* Called from the multi interface during the DOING phase, and it should
      then return a proper fd set */
-  int (*doing_getsock)(struct Curl_easy *data,
-                       struct connectdata *conn, curl_socket_t *socks);
+  CURLcode (*doing_pollset)(struct Curl_easy *data,
+                            struct easy_pollset *ps);
 
   /* Called from the multi interface during the DO_MORE phase, and it should
      then return a proper fd set */
-  int (*domore_getsock)(struct Curl_easy *data,
-                        struct connectdata *conn, curl_socket_t *socks);
+  CURLcode (*domore_pollset)(struct Curl_easy *data,
+                            struct easy_pollset *ps);
 
   /* Called from the multi interface during the DO_DONE, PERFORM and
      WAITPERFORM phases, and it should then return a proper fd set. Not setting
      this will make libcurl use the generic default one. */
-  int (*perform_getsock)(struct Curl_easy *data,
-                         struct connectdata *conn, curl_socket_t *socks);
+  CURLcode (*perform_pollset)(struct Curl_easy *data,
+                              struct easy_pollset *ps);
 
   /* This function *MAY* be set to a protocol-dependent function that is run
    * by the curl_disconnect(), as a step in the disconnection. If the handler
index 8d6f94bc831d0988f0f6d7d005a7c29930a52a26..1cb99aaea8694bb3240623696cf362ac8222e738 100644 (file)
@@ -898,15 +898,16 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
   return CURLE_OK;
 }
 
-static void cf_ngtcp2_adjust_pollset(struct Curl_cfilter *cf,
-                                     struct Curl_easy *data,
-                                     struct easy_pollset *ps)
+static CURLcode cf_ngtcp2_adjust_pollset(struct Curl_cfilter *cf,
+                                         struct Curl_easy *data,
+                                         struct easy_pollset *ps)
 {
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
   bool want_recv, want_send;
+  CURLcode result = CURLE_OK;
 
   if(!ctx->qconn)
-    return;
+    return CURLE_OK;
 
   Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
   if(!want_send && !Curl_bufq_is_empty(&ctx->q.sendbuf))
@@ -926,9 +927,10 @@ static void cf_ngtcp2_adjust_pollset(struct Curl_cfilter *cf,
     want_send = (!s_exhaust && want_send) ||
                  !Curl_bufq_is_empty(&ctx->q.sendbuf);
 
-    Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send);
+    result = Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send);
     CF_DATA_RESTORE(cf, save);
   }
+  return result;
 }
 
 static int cb_h3_stream_close(nghttp3_conn *conn, int64_t sid,
index 05362e2396feb4694e58e2fd4ffe33ad587ba03c..c18801d811f6aec900db63bd5cad044831bc738a 100644 (file)
@@ -2266,11 +2266,12 @@ out:
   return alive;
 }
 
-static void cf_osslq_adjust_pollset(struct Curl_cfilter *cf,
-                                    struct Curl_easy *data,
-                                    struct easy_pollset *ps)
+static CURLcode cf_osslq_adjust_pollset(struct Curl_cfilter *cf,
+                                        struct Curl_easy *data,
+                                        struct easy_pollset *ps)
 {
   struct cf_osslq_ctx *ctx = cf->ctx;
+  CURLcode result = CURLE_OK;
 
   if(!ctx->tls.ossl.ssl) {
     /* NOP */
@@ -2278,9 +2279,9 @@ static void cf_osslq_adjust_pollset(struct Curl_cfilter *cf,
   else if(!cf->connected) {
     /* during handshake, transfer has not started yet. we always
      * add our socket for polling if SSL wants to send/recv */
-    Curl_pollset_set(data, ps, ctx->q.sockfd,
-                     SSL_net_read_desired(ctx->tls.ossl.ssl),
-                     SSL_net_write_desired(ctx->tls.ossl.ssl));
+    result = Curl_pollset_set(data, ps, ctx->q.sockfd,
+                              SSL_net_read_desired(ctx->tls.ossl.ssl),
+                              SSL_net_write_desired(ctx->tls.ossl.ssl));
   }
   else {
     /* once connected, we only modify the socket if it is present.
@@ -2288,15 +2289,16 @@ static void cf_osslq_adjust_pollset(struct Curl_cfilter *cf,
     bool want_recv, want_send;
     Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
     if(want_recv || want_send) {
-      Curl_pollset_set(data, ps, ctx->q.sockfd,
-                       SSL_net_read_desired(ctx->tls.ossl.ssl),
-                       SSL_net_write_desired(ctx->tls.ossl.ssl));
+      result = Curl_pollset_set(data, ps, ctx->q.sockfd,
+                                SSL_net_read_desired(ctx->tls.ossl.ssl),
+                                SSL_net_write_desired(ctx->tls.ossl.ssl));
     }
     else if(ctx->need_recv || ctx->need_send) {
-      Curl_pollset_set(data, ps, ctx->q.sockfd,
-                       ctx->need_recv, ctx->need_send);
+      result = Curl_pollset_set(data, ps, ctx->q.sockfd,
+                                ctx->need_recv, ctx->need_send);
     }
   }
+  return result;
 }
 
 static CURLcode cf_osslq_query(struct Curl_cfilter *cf,
index 9bb72511e98238b48480c64b0b9b6543b8d55e84..b981f4d780c154aab4ab556142bcbb2c8c099758 100644 (file)
@@ -1142,15 +1142,16 @@ static bool stream_is_writeable(struct Curl_cfilter *cf,
     ctx->qconn, (curl_uint64_t)stream->id, 1) > 0);
 }
 
-static void cf_quiche_adjust_pollset(struct Curl_cfilter *cf,
-                                     struct Curl_easy *data,
-                                     struct easy_pollset *ps)
+static CURLcode cf_quiche_adjust_pollset(struct Curl_cfilter *cf,
+                                         struct Curl_easy *data,
+                                         struct easy_pollset *ps)
 {
   struct cf_quiche_ctx *ctx = cf->ctx;
   bool want_recv, want_send;
+  CURLcode result = CURLE_OK;
 
   if(!ctx->qconn)
-    return;
+    return CURLE_OK;
 
   Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
   if(want_recv || want_send) {
@@ -1165,8 +1166,9 @@ static void cf_quiche_adjust_pollset(struct Curl_cfilter *cf,
     want_send = (!s_exhaust && want_send) ||
                  !Curl_bufq_is_empty(&ctx->q.sendbuf);
 
-    Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send);
+    result = Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send);
   }
+  return result;
 }
 
 /*
index d9c37f9db5541120893d68ebd65c441d989b879b..d6ce1a65f4aa26dee4904e65b568fa221aa8f1f0 100644 (file)
@@ -125,8 +125,8 @@ CURLcode sftp_perform(struct Curl_easy *data,
                       bool *connected,
                       bool *dophase_done);
 
-static int myssh_getsock(struct Curl_easy *data,
-                         struct connectdata *conn, curl_socket_t *sock);
+static CURLcode myssh_pollset(struct Curl_easy *data,
+                              struct easy_pollset *ps);
 static void myssh_block2waitfor(struct connectdata *conn,
                                 struct ssh_conn *sshc,
                                 bool block);
@@ -148,10 +148,10 @@ const struct Curl_handler Curl_handler_scp = {
   myssh_connect,                /* connect_it */
   myssh_multi_statemach,        /* connecting */
   scp_doing,                    /* doing */
-  myssh_getsock,                /* proto_getsock */
-  myssh_getsock,                /* doing_getsock */
-  ZERO_NULL,                    /* domore_getsock */
-  myssh_getsock,                /* perform_getsock */
+  myssh_pollset,                /* proto_pollset */
+  myssh_pollset,                /* doing_pollset */
+  ZERO_NULL,                    /* domore_pollset */
+  myssh_pollset,                /* perform_pollset */
   scp_disconnect,               /* disconnect */
   ZERO_NULL,                    /* write_resp */
   ZERO_NULL,                    /* write_resp_hd */
@@ -177,10 +177,10 @@ const struct Curl_handler Curl_handler_sftp = {
   myssh_connect,                        /* connect_it */
   myssh_multi_statemach,                /* connecting */
   sftp_doing,                           /* doing */
-  myssh_getsock,                        /* proto_getsock */
-  myssh_getsock,                        /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  myssh_getsock,                        /* perform_getsock */
+  myssh_pollset,                        /* proto_pollset */
+  myssh_pollset,                        /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  myssh_pollset,                        /* perform_pollset */
   sftp_disconnect,                      /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -2390,25 +2390,19 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
 
 /* called by the multi interface to figure out what socket(s) to wait for and
    for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
-static int myssh_getsock(struct Curl_easy *data,
-                         struct connectdata *conn,
-                         curl_socket_t *sock)
+static CURLcode myssh_pollset(struct Curl_easy *data,
+                              struct easy_pollset *ps)
 {
-  int bitmap = GETSOCK_BLANK;
-  (void)data;
-  sock[0] = conn->sock[FIRSTSOCKET];
-
-  if(conn->waitfor & KEEP_RECV)
-    bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
-
-  if(conn->waitfor & KEEP_SEND)
-    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
-
-  if(!conn->waitfor)
-    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
-
-  DEBUGF(infof(data, "ssh_getsock -> %x", bitmap));
-  return bitmap;
+  int flags = 0;
+  if(data->conn->waitfor & KEEP_RECV)
+    flags |= CURL_POLL_IN;
+  if(data->conn->waitfor & KEEP_SEND)
+    flags |= CURL_POLL_OUT;
+  if(!data->conn->waitfor)
+    flags |= CURL_POLL_OUT;
+  return flags ?
+    Curl_pollset_change(data, ps, data->conn->sock[FIRSTSOCKET], flags, 0) :
+    CURLE_OK;
 }
 
 static void myssh_block2waitfor(struct connectdata *conn,
@@ -2437,7 +2431,7 @@ static CURLcode myssh_multi_statemach(struct Curl_easy *data,
   struct connectdata *conn = data->conn;
   struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
   struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
-  bool block;    /* we store the status and use that to provide a ssh_getsock()
+  bool block;    /* we store the status and use that to provide a ssh_pollset()
                     implementation */
   CURLcode result;
 
index ab57dd87f55a7bcffbd49a27806efe0b8f11bbf7..bac362dd5c0a5e9876c2ec486307594ecf5e42f1 100644 (file)
@@ -99,8 +99,8 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
                                 struct connectdata *conn, bool dead);
 static CURLcode sftp_perform(struct Curl_easy *data, bool *connected,
                              bool *dophase_done);
-static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn,
-                       curl_socket_t *sock);
+static CURLcode ssh_pollset(struct Curl_easy *data,
+                            struct easy_pollset *ps);
 static CURLcode ssh_setup_connection(struct Curl_easy *data,
                                      struct connectdata *conn);
 static void ssh_attach(struct Curl_easy *data, struct connectdata *conn);
@@ -119,10 +119,10 @@ const struct Curl_handler Curl_handler_scp = {
   ssh_connect,                          /* connect_it */
   ssh_multi_statemach,                  /* connecting */
   scp_doing,                            /* doing */
-  ssh_getsock,                          /* proto_getsock */
-  ssh_getsock,                          /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ssh_getsock,                          /* perform_getsock */
+  ssh_pollset,                          /* proto_pollset */
+  ssh_pollset,                          /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ssh_pollset,                          /* perform_pollset */
   scp_disconnect,                       /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -150,10 +150,10 @@ const struct Curl_handler Curl_handler_sftp = {
   ssh_connect,                          /* connect_it */
   ssh_multi_statemach,                  /* connecting */
   sftp_doing,                           /* doing */
-  ssh_getsock,                          /* proto_getsock */
-  ssh_getsock,                          /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ssh_getsock,                          /* perform_getsock */
+  ssh_pollset,                          /* proto_pollset */
+  ssh_pollset,                          /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ssh_pollset,                          /* perform_pollset */
   sftp_disconnect,                      /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -3087,22 +3087,17 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
 
 /* called by the multi interface to figure out what socket(s) to wait for and
    for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
-static int ssh_getsock(struct Curl_easy *data,
-                       struct connectdata *conn,
-                       curl_socket_t *sock)
+static CURLcode ssh_pollset(struct Curl_easy *data,
+                            struct easy_pollset *ps)
 {
-  int bitmap = GETSOCK_BLANK;
-  (void)data;
-
-  sock[0] = conn->sock[FIRSTSOCKET];
-
-  if(conn->waitfor & KEEP_RECV)
-    bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
-
-  if(conn->waitfor & KEEP_SEND)
-    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
-
-  return bitmap;
+  int flags = 0;
+  if(data->conn->waitfor & KEEP_RECV)
+    flags |= CURL_POLL_IN;
+  if(data->conn->waitfor & KEEP_SEND)
+    flags |= CURL_POLL_OUT;
+  return flags ?
+    Curl_pollset_change(data, ps, data->conn->sock[FIRSTSOCKET], flags, 0) :
+    CURLE_OK;
 }
 
 /*
@@ -3139,7 +3134,7 @@ static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done)
   struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
   struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
   CURLcode result = CURLE_OK;
-  bool block; /* we store the status and use that to provide a ssh_getsock()
+  bool block; /* we store the status and use that to provide a ssh_pollset()
                  implementation */
   if(!sshc || !sshp)
     return CURLE_FAILED_INIT;
index eed73fd9192871469c2b9df5e71b121eac79218a..15f504a01c5b9f59280d18cf98ac82e7916d01cf 100644 (file)
@@ -66,9 +66,8 @@ static CURLcode wsftp_doing(struct Curl_easy *data,
 static CURLcode wsftp_disconnect(struct Curl_easy *data,
                                  struct connectdata *conn,
                                  bool dead);
-static int wssh_getsock(struct Curl_easy *data,
-                        struct connectdata *conn,
-                        curl_socket_t *sock);
+static CURLcode wssh_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps);
 static CURLcode wssh_setup_connection(struct Curl_easy *data,
                                       struct connectdata *conn);
 static void wssh_sshc_cleanup(struct ssh_conn *sshc);
@@ -87,10 +86,10 @@ const struct Curl_handler Curl_handler_scp = {
   wssh_connect,                         /* connect_it */
   wssh_multi_statemach,                 /* connecting */
   wscp_doing,                           /* doing */
-  wssh_getsock,                         /* proto_getsock */
-  wssh_getsock,                         /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  wssh_getsock,                         /* perform_getsock */
+  wssh_pollset,                         /* proto_pollset */
+  wssh_pollset,                         /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  wssh_pollset,                         /* perform_pollset */
   wscp_disconnect,                      /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -118,10 +117,10 @@ const struct Curl_handler Curl_handler_sftp = {
   wssh_connect,                         /* connect_it */
   wssh_multi_statemach,                 /* connecting */
   wsftp_doing,                          /* doing */
-  wssh_getsock,                         /* proto_getsock */
-  wssh_getsock,                         /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  wssh_getsock,                         /* perform_getsock */
+  wssh_pollset,                         /* proto_pollset */
+  wssh_pollset,                         /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  wssh_pollset,                         /* perform_pollset */
   wsftp_disconnect,                     /* disconnect */
   ZERO_NULL,                            /* write_resp */
   ZERO_NULL,                            /* write_resp_hd */
@@ -932,7 +931,7 @@ static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done)
   struct connectdata *conn = data->conn;
   struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
   CURLcode result = CURLE_OK;
-  bool block; /* we store the status and use that to provide a ssh_getsock()
+  bool block; /* we store the status and use that to provide a ssh_pollset()
                  implementation */
   if(!sshc)
     return CURLE_FAILED_INIT;
@@ -1185,21 +1184,17 @@ static CURLcode wsftp_disconnect(struct Curl_easy *data,
   return result;
 }
 
-static int wssh_getsock(struct Curl_easy *data,
-                        struct connectdata *conn,
-                        curl_socket_t *sock)
+static CURLcode wssh_pollset(struct Curl_easy *data,
+                             struct easy_pollset *ps)
 {
-  int bitmap = GETSOCK_BLANK;
-  int dir = conn->waitfor;
-  (void)data;
-  sock[0] = conn->sock[FIRSTSOCKET];
-
-  if(dir == KEEP_RECV)
-    bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
-  else if(dir == KEEP_SEND)
-    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
-
-  return bitmap;
+  int flags = 0;
+  if(data->conn->waitfor & KEEP_RECV)
+    flags |= CURL_POLL_IN;
+  if(data->conn->waitfor & KEEP_SEND)
+    flags |= CURL_POLL_OUT;
+  return flags ?
+    Curl_pollset_change(data, ps, data->conn->sock[FIRSTSOCKET], flags, 0) :
+    CURLE_OK;
 }
 
 void Curl_ssh_version(char *buffer, size_t buflen)
index 0ff79ea70b038010e874c8e242fbb1ceb6c78884..96d64dd606fdca96e8c84111313eaddaf35565c0 100644 (file)
@@ -503,26 +503,30 @@ void Curl_ssl_close_all(struct Curl_easy *data)
     Curl_ssl->close_all(data);
 }
 
-void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
-                             struct easy_pollset *ps)
+CURLcode  Curl_ssl_adjust_pollset(struct Curl_cfilter *cf,
+                                  struct Curl_easy *data,
+                                  struct easy_pollset *ps)
 {
   struct ssl_connect_data *connssl = cf->ctx;
 
   if(connssl->io_need) {
     curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
+    CURLcode result = CURLE_OK;
     if(sock != CURL_SOCKET_BAD) {
       if(connssl->io_need & CURL_SSL_IO_NEED_SEND) {
-        Curl_pollset_set_out_only(data, ps, sock);
+        result = Curl_pollset_set_out_only(data, ps, sock);
         CURL_TRC_CF(data, cf, "adjust_pollset, POLLOUT fd=%" FMT_SOCKET_T,
                     sock);
       }
       else {
-        Curl_pollset_set_in_only(data, ps, sock);
+        result = Curl_pollset_set_in_only(data, ps, sock);
         CURL_TRC_CF(data, cf, "adjust_pollset, POLLIN fd=%" FMT_SOCKET_T,
                     sock);
       }
     }
+    return result;
   }
+  return CURLE_OK;
 }
 
 /* Selects an SSL crypto engine
@@ -902,13 +906,13 @@ static CURLcode multissl_connect(struct Curl_cfilter *cf,
   return Curl_ssl->do_connect(cf, data, done);
 }
 
-static void multissl_adjust_pollset(struct Curl_cfilter *cf,
-                                    struct Curl_easy *data,
-                                    struct easy_pollset *ps)
+static CURLcode multissl_adjust_pollset(struct Curl_cfilter *cf,
+                                        struct Curl_easy *data,
+                                        struct easy_pollset *ps)
 {
   if(multissl_setup(NULL))
-    return;
-  Curl_ssl->adjust_pollset(cf, data, ps);
+    return CURLE_OK;
+  return Curl_ssl->adjust_pollset(cf, data, ps);
 }
 
 static void *multissl_get_internals(struct ssl_connect_data *connssl,
@@ -1545,16 +1549,18 @@ static CURLcode ssl_cf_shutdown(struct Curl_cfilter *cf,
   return result;
 }
 
-static void ssl_cf_adjust_pollset(struct Curl_cfilter *cf,
-                                  struct Curl_easy *data,
-                                  struct easy_pollset *ps)
+static CURLcode ssl_cf_adjust_pollset(struct Curl_cfilter *cf,
+                                      struct Curl_easy *data,
+                                      struct easy_pollset *ps)
 {
   struct ssl_connect_data *connssl = cf->ctx;
   struct cf_call_data save;
+  CURLcode result;
 
   CF_DATA_SAVE(save, cf, data);
-  connssl->ssl_impl->adjust_pollset(cf, data, ps);
+  result = connssl->ssl_impl->adjust_pollset(cf, data, ps);
   CF_DATA_RESTORE(cf, save);
+  return result;
 }
 
 static CURLcode ssl_cf_query(struct Curl_cfilter *cf,
index 11987c382a3ce1b8e08f900b99a31bed3110c59d..de0b735e22bf86022dabeee0ef677e9924b7a390 100644 (file)
@@ -166,8 +166,8 @@ struct Curl_ssl {
 
   /* During handshake/shutdown, adjust the pollset to include the socket
    * for POLLOUT or POLLIN as needed. Mandatory. */
-  void (*adjust_pollset)(struct Curl_cfilter *cf, struct Curl_easy *data,
-                          struct easy_pollset *ps);
+  CURLcode (*adjust_pollset)(struct Curl_cfilter *cf, struct Curl_easy *data,
+                             struct easy_pollset *ps);
   void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
   void (*close)(struct Curl_cfilter *cf, struct Curl_easy *data);
   void (*close_all)(struct Curl_easy *data);
@@ -190,8 +190,9 @@ struct Curl_ssl {
 
 extern const struct Curl_ssl *Curl_ssl;
 
-void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
-                             struct easy_pollset *ps);
+CURLcode Curl_ssl_adjust_pollset(struct Curl_cfilter *cf,
+                                 struct Curl_easy *data,
+                                 struct easy_pollset *ps);
 
 /**
  * Get the SSL filter below the given one or NULL if there is none.
index ac542fbc14901bed559712d7e7fbb10d04af9a3d..7d7bf481577acceee4ab7ba7fdf3ded5e789354c 100644 (file)
--- a/lib/ws.c
+++ b/lib/ws.c
@@ -1552,10 +1552,10 @@ const struct Curl_handler Curl_handler_ws = {
   Curl_http_connect,                    /* connect_it */
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  Curl_http_getsock_do,                 /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* proto_pollset */
+  Curl_http_do_pollset,                 /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   Curl_http_write_resp,                 /* write_resp */
   Curl_http_write_resp_hd,              /* write_resp_hd */
@@ -1579,10 +1579,10 @@ const struct Curl_handler Curl_handler_wss = {
   Curl_http_connect,                    /* connect_it */
   NULL,                                 /* connecting */
   ZERO_NULL,                            /* doing */
-  NULL,                                 /* proto_getsock */
-  Curl_http_getsock_do,                 /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
+  NULL,                                 /* proto_pollset */
+  Curl_http_do_pollset,                 /* doing_pollset */
+  ZERO_NULL,                            /* domore_pollset */
+  ZERO_NULL,                            /* perform_pollset */
   ZERO_NULL,                            /* disconnect */
   Curl_http_write_resp,                 /* write_resp */
   Curl_http_write_resp_hd,              /* write_resp_hd */
index 820176b2d9e8e87cc35e37123dc1f440121bd150..08b2ca6fbd57cef1d006ca762187a9385fbb76ac 100644 (file)
@@ -105,8 +105,10 @@ struct test_result {
 
 static const struct test_case *current_tc;
 static struct test_result *current_tr;
+static int test_idx;
 
 struct cf_test_ctx {
+  int idx;
   int ai_family;
   int transport;
   char id[16];
@@ -151,13 +153,13 @@ static CURLcode cf_test_connect(struct Curl_cfilter *cf,
   return CURLE_OK;
 }
 
-static void cf_test_adjust_pollset(struct Curl_cfilter *cf,
-                                   struct Curl_easy *data,
-                                   struct easy_pollset *ps)
+static CURLcode cf_test_adjust_pollset(struct Curl_cfilter *cf,
+                                       struct Curl_easy *data,
+                                       struct easy_pollset *ps)
 {
+  struct cf_test_ctx *ctx = cf->ctx;
   /* just for testing, give one socket with events back */
-  (void)cf;
-  Curl_pollset_set(data, ps, 1, TRUE, TRUE);
+  return Curl_pollset_set(data, ps, ctx->idx, TRUE, TRUE);
 }
 
 static CURLcode cf_test_create(struct Curl_cfilter **pcf,
@@ -196,6 +198,7 @@ static CURLcode cf_test_create(struct Curl_cfilter **pcf,
     result = CURLE_OUT_OF_MEMORY;
     goto out;
   }
+  ctx->idx = test_idx++;
   ctx->ai_family = ai->ai_family;
   ctx->transport = transport;
   ctx->started = curlx_now();