}
/*
- * 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);
}
/*
#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;
}
/*
#include "url.h"
#include "multiif.h"
#include "curl_threads.h"
+#include "select.h"
#include "strdup.h"
#ifdef USE_ARES
}
}
-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
Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
}
- return ret_val;
+ return result;
}
#ifndef HAVE_GETADDRINFO
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
*/
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()
/* 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
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
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,
#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 */
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) ||
!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) {
!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,
#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"
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 = {
#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 */
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,
#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 */
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,
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,
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
* 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
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,
{
#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;
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)) {
/* 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) {
}
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;
}
out:
+ Curl_pollset_cleanup(&ps);
Curl_pollfds_cleanup(&cpfds);
return result;
}
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;
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,
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,
*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;
-}
* @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);
/* 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,
/**
* 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`.
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.
{
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"
*maxfd = (int)ps.sockets[i];
}
}
+ Curl_pollset_cleanup(&ps);
}
}
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;
}
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;
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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,
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 */
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 */
}
/* 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.
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 */
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 */
}
#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
}
struct hostent;
struct Curl_easy;
struct connectdata;
+struct easy_pollset;
enum alpnid {
ALPN_none = 0,
#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);
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 */
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 */
/* 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);
}
/*
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);
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);
(!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) {
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,
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);
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 */
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 */
}
/* 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;
}
/***********************************************************************
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 */
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 */
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);
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 */
/* 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)
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:
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;
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:
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. */
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),
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) &&
infof(data, "WARNING: no socket in pollset or timer, transfer may stall!");
DEBUGASSERT(0);
}
+out:
+ return mresult;
}
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 */
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;
read_fd_set, write_fd_set, &this_max_fd);
*max_fd = this_max_fd;
+ Curl_pollset_cleanup(&ps);
return CURLM_OK;
}
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))
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));
if(fd_count)
*fd_count = need;
+ Curl_pollset_cleanup(&ps);
return result;
}
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 */
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);
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;
}
out:
+ Curl_pollset_cleanup(&ps);
Curl_pollfds_cleanup(&cpfds);
return result;
}
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 */
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;
}
/* 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;
} /* 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*
{
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))
{
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))
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,
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
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
/* 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
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 */
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 */
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,
/* 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);
/***********************************************************************
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);
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 */
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 */
}
/* 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;
}
/***********************************************************************
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.
/* 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
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 */
#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"
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;
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;
}
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;
+}
} 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;
#include "connect.h"
#include "progress.h"
#include "transfer.h"
+#include "select.h"
#include "vtls/vtls.h"
#include "curl_ntlm_core.h"
#include "escape.h"
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);
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 */
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 */
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)
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);
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 */
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 */
}
/* 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;
}
/***********************************************************************
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
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,
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 */
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);
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 */
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]);
}
/**********************************************************
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);
#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.
*/
/* 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
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))
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,
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 */
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.
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,
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) {
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;
}
/*
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);
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 */
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 */
/* 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,
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;
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);
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 */
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 */
/* 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;
}
/*
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;
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);
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 */
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 */
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;
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)
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
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,
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,
/* 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);
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.
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 */
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 */
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];
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,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
+ ctx->idx = test_idx++;
ctx->ai_family = ai->ai_family;
ctx->transport = transport;
ctx->started = curlx_now();