cf-socket: fix pollset for listening

When FTP does an active data connection, the socket connection
filter is instantiated with a listening socket. When the filter
adjusts its pollset, it needs to POLLIN, not OUT.

Bug: https://curl.se/mail/lib-2024-08/0023.html
Reported-by: Yoshimasa Ohno
Closes #14766
This commit is contained in:
Stefan Eissing 2024-09-03 09:54:59 +02:00 committed by Daniel Stenberg
parent 81a3342877
commit a07ba37b5e
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -950,6 +950,7 @@ struct cf_socket_ctx {
size_t recv_max; /* max enforced read size */
#endif
BIT(got_first_byte); /* if first byte was received */
BIT(listening); /* socket is listening */
BIT(accepted); /* socket was accepted, not connected */
BIT(sock_connected); /* socket is "connected", e.g. in UDP */
BIT(active);
@ -1409,9 +1410,16 @@ static void cf_socket_adjust_pollset(struct Curl_cfilter *cf,
if(ctx->sock != CURL_SOCKET_BAD) {
if(!cf->connected) {
Curl_pollset_set_out_only(data, ps, ctx->sock);
CURL_TRC_CF(data, cf, "adjust_pollset, !connected, POLLOUT fd=%"
FMT_SOCKET_T, ctx->sock);
if(ctx->listening) {
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 {
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);
@ -2054,6 +2062,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
}
ctx->transport = conn->transport;
ctx->sock = *s;
ctx->listening = TRUE;
ctx->accepted = FALSE;
result = Curl_cf_create(&cf, &Curl_cft_tcp_accept, ctx);
if(result)
@ -2120,8 +2129,10 @@ CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
return CURLE_FAILED_INIT;
ctx = cf->ctx;
DEBUGASSERT(ctx->listening);
/* discard the listen socket */
socket_close(data, conn, TRUE, ctx->sock);
ctx->listening = FALSE;
ctx->sock = *s;
conn->sock[sockindex] = ctx->sock;
set_accepted_remote_ip(cf, data);