if(ctx->sock != CURL_SOCKET_BAD) {
if(!cf->connected)
Curl_pollset_set_out_only(data, ps, ctx->sock);
- else if(CURL_WANT_RECV(data))
+ else if(!ctx->active)
Curl_pollset_add_in(data, ps, ctx->sock);
CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
}
void Curl_pollset_add_socks(struct Curl_easy *data,
struct easy_pollset *ps,
int (*get_socks_cb)(struct Curl_easy *data,
- struct connectdata *conn,
curl_socket_t *socks))
{
curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
int bitmap;
- DEBUGASSERT(data->conn);
- bitmap = get_socks_cb(data, data->conn, socks);
- ps_add(data, ps, bitmap, socks);
-}
-
-void Curl_pollset_add_socks2(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_add_socks(struct Curl_easy *data,
struct easy_pollset *ps,
int (*get_socks_cb)(struct Curl_easy *data,
- struct connectdata *conn,
curl_socket_t *socks));
-void Curl_pollset_add_socks2(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
struct easy_pollset *ps)
{
struct cf_h2_ctx *ctx = cf->ctx;
- bool want_recv = CURL_WANT_RECV(data);
- bool want_send = CURL_WANT_SEND(data);
+ curl_socket_t sock;
+ bool want_recv, want_send;
- if(ctx->h2 && (want_recv || want_send)) {
+ if(!ctx->h2)
+ return;
+
+ sock = Curl_conn_cf_get_socket(cf, data);
+ Curl_pollset_check(data, ps, sock, &want_recv, &want_send);
+ if(want_recv || want_send) {
struct stream_ctx *stream = H2_STREAM_CTX(data);
- curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
struct cf_call_data save;
bool c_exhaust, s_exhaust;
Curl_conn_ev_data_attach(conn, data);
}
-static int domore_getsock(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t *socks)
+static int connecting_getsock(struct Curl_easy *data, curl_socket_t *socks)
{
+ struct connectdata *conn = data->conn;
+ (void)socks;
+ if(conn && conn->sockfd != CURL_SOCKET_BAD) {
+ /* Default is to wait to something from the server */
+ socks[0] = conn->sockfd;
+ return GETSOCK_READSOCK(0);
+ }
+ return GETSOCK_BLANK;
+}
+
+static int protocol_getsock(struct Curl_easy *data, curl_socket_t *socks)
+{
+ struct connectdata *conn = data->conn;
+ if(conn && conn->handler->proto_getsock)
+ return conn->handler->proto_getsock(data, conn, socks);
+ else if(conn && conn->sockfd != CURL_SOCKET_BAD) {
+ /* Default is to wait to something from the server */
+ socks[0] = conn->sockfd;
+ return GETSOCK_READSOCK(0);
+ }
+ return GETSOCK_BLANK;
+}
+
+static int domore_getsock(struct Curl_easy *data, curl_socket_t *socks)
+{
+ struct connectdata *conn = data->conn;
if(conn && conn->handler->domore_getsock)
return conn->handler->domore_getsock(data, conn, socks);
+ else if(conn && conn->sockfd != CURL_SOCKET_BAD) {
+ /* Default is that we want to send something to the server */
+ socks[0] = conn->sockfd;
+ return GETSOCK_WRITESOCK(0);
+ }
return GETSOCK_BLANK;
}
-static int doing_getsock(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t *socks)
+static int doing_getsock(struct Curl_easy *data, curl_socket_t *socks)
{
+ struct connectdata *conn = data->conn;
if(conn && conn->handler->doing_getsock)
return conn->handler->doing_getsock(data, conn, socks);
+ else if(conn && conn->sockfd != CURL_SOCKET_BAD) {
+ /* Default is that we want to send something to the server */
+ socks[0] = conn->sockfd;
+ return GETSOCK_WRITESOCK(0);
+ }
return GETSOCK_BLANK;
}
-static int protocol_getsock(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t *socks)
+static int perform_getsock(struct Curl_easy *data, curl_socket_t *sock)
{
- if(conn->handler->proto_getsock)
- return conn->handler->proto_getsock(data, conn, socks);
- return GETSOCK_BLANK;
+ struct connectdata *conn = data->conn;
+
+ if(!conn)
+ return GETSOCK_BLANK;
+ else if(conn->handler->perform_getsock)
+ return conn->handler->perform_getsock(data, conn, sock);
+ else {
+ /* Default is to obey the data->req.keepon flags for send/recv */
+ int bitmap = GETSOCK_BLANK;
+ unsigned sockindex = 0;
+ if(CURL_WANT_RECV(data)) {
+ DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
+ bitmap |= GETSOCK_READSOCK(sockindex);
+ sock[sockindex] = conn->sockfd;
+ }
+
+ if(CURL_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);
+ }
+ return bitmap;
+ }
}
/* Initializes `poll_set` with the current socket poll actions needed
return;
switch(data->mstate) {
- default:
+ case MSTATE_INIT:
+ case MSTATE_PENDING:
+ case MSTATE_CONNECT:
+ /* nothing to poll for yet */
break;
case MSTATE_RESOLVING:
- Curl_pollset_add_socks2(data, ps, Curl_resolv_getsock);
+ Curl_pollset_add_socks(data, ps, Curl_resolv_getsock);
/* connection filters are not involved in this phase */
- return;
+ break;
+
+ case MSTATE_CONNECTING:
+ case MSTATE_TUNNELING:
+ Curl_pollset_add_socks(data, ps, connecting_getsock);
+ Curl_conn_adjust_pollset(data, ps);
+ break;
- case MSTATE_PROTOCONNECTING:
case MSTATE_PROTOCONNECT:
+ case MSTATE_PROTOCONNECTING:
Curl_pollset_add_socks(data, ps, protocol_getsock);
+ Curl_conn_adjust_pollset(data, ps);
break;
case MSTATE_DO:
case MSTATE_DOING:
Curl_pollset_add_socks(data, ps, doing_getsock);
- break;
-
- case MSTATE_TUNNELING:
- case MSTATE_CONNECTING:
+ Curl_conn_adjust_pollset(data, ps);
break;
case MSTATE_DOING_MORE:
Curl_pollset_add_socks(data, ps, domore_getsock);
+ Curl_conn_adjust_pollset(data, ps);
break;
- case MSTATE_DID: /* since is set after DO is completed, we switch to
- waiting for the same as the PERFORMING state */
+ case MSTATE_DID: /* same as PERFORMING in regard to polling */
case MSTATE_PERFORMING:
- Curl_pollset_add_socks(data, ps, Curl_single_getsock);
+ Curl_pollset_add_socks(data, ps, perform_getsock);
+ Curl_conn_adjust_pollset(data, ps);
break;
case MSTATE_RATELIMITING:
- /* nothing to wait for */
- return;
- }
+ /* we need to let time pass, ignore socket(s) */
+ break;
+
+ case MSTATE_DONE:
+ case MSTATE_COMPLETED:
+ case MSTATE_MSGSENT:
+ /* nothing more to poll for */
+ break;
- /* Let connection filters add/remove as needed */
- Curl_conn_adjust_pollset(data, ps);
+ default:
+ failf(data, "multi_getsock: unexpected multi state %d", data->mstate);
+ DEBUGASSERT(0);
+ break;
+ }
}
CURLMcode curl_multi_fdset(struct Curl_multi *multi,
return result;
}
-/*
- * Curl_single_getsock() gets called by the multi interface code when the app
- * has requested to get the sockets for the current connection. This function
- * will then be called once for every connection that the multi interface
- * keeps track of. This function will only be called for connections that are
- * in the proper state to have this information available.
- */
-int Curl_single_getsock(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t *sock)
-{
- int bitmap = GETSOCK_BLANK;
- unsigned sockindex = 0;
-
- if(conn->handler->perform_getsock)
- return conn->handler->perform_getsock(data, conn, sock);
-
- /* don't include HOLD and PAUSE connections */
- if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) {
-
- DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
-
- bitmap |= GETSOCK_READSOCK(sockindex);
- sock[sockindex] = conn->sockfd;
- }
-
- /* don't include HOLD and PAUSE connections */
- if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) {
- 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);
- }
-
- return bitmap;
-}
-
/* Curl_init_CONNECT() gets called each time the handle switches to CONNECT
which means this gets called once for each subsequent redirect etc */
void Curl_init_CONNECT(struct Curl_easy *data)
followtype type);
CURLcode Curl_readwrite(struct connectdata *conn,
struct Curl_easy *data, bool *done);
-int Curl_single_getsock(struct Curl_easy *data,
- struct connectdata *conn, curl_socket_t *socks);
CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
size_t *nreadp);
CURLcode Curl_retry_request(struct Curl_easy *data, char **url);
(((data)->req.keepon & KEEP_SENDBITS) == KEEP_SEND)
/* transfer receive is not on PAUSE or HOLD */
#define CURL_WANT_RECV(data) \
- (!((data)->req.keepon & (KEEP_RECV_PAUSE|KEEP_RECV_HOLD)))
+ (((data)->req.keepon & KEEP_RECVBITS) == KEEP_RECV)
#if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH)
#define USE_CURL_ASYNC
struct easy_pollset *ps)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- bool want_recv = CURL_WANT_RECV(data);
- bool want_send = CURL_WANT_SEND(data);
+ bool want_recv, want_send;
- if(ctx->qconn && (want_recv || want_send)) {
+ if(!ctx->qconn)
+ return;
+
+ Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
+ if(want_recv || want_send) {
struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
struct cf_call_data save;
bool c_exhaust, s_exhaust;
struct easy_pollset *ps)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- bool want_recv = CURL_WANT_RECV(data);
- bool want_send = CURL_WANT_SEND(data);
+ bool want_recv, want_send;
- if(ctx->qconn && (want_recv || want_send)) {
+ if(!ctx->qconn)
+ return;
+
+ Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
+ if(want_recv || want_send) {
struct stream_ctx *stream = H3_STREAM_CTX(data);
bool c_exhaust, s_exhaust;