curl_multi_fdset: correct fdset with FTP PORT use

After a PORT has been issued, and the multi handle would switch to the
CURLM_STATE_DO_MORE state (which is unique for FTP), libcurl would
return the wrong fdset to wait for when curl_multi_fdset() is
called. The code would blindly assume that it was waiting for a connect
of the second connection, while that isn't true immediately after the
PORT command.

Also, the function multi.c:domore_getsock() was highly FTP-centric and
therefore ugly to keep in protocol-agnostic code. I solved this problem
by introducing a new function pointer in the Curl_handler struct called
domore_getsock() which is only called during the DOMORE state for
protocols that set that pointer.

The new ftp.c:ftp_domore_getsock() function now returns fdset info about
the control connection's command/response handling while such a state is
in use, and goes over to waiting for a writable second connection first
once the commands are done.

The original problem could be seen by running test 525 and checking the
time stamps in the FTP server log. I can verify that this fix at least
fixes this problem.

Bug: http://curl.haxx.se/mail/lib-2011-10/0250.html
Reported by: Gokhan Sengun
This commit is contained in:
Daniel Stenberg
2011-10-21 23:36:54 +02:00
parent d67b75c9f9
commit d7934b8bd4
18 changed files with 81 additions and 14 deletions

View File

@@ -816,20 +816,12 @@ static int waitconnect_getsock(struct connectdata *conn,
}
static int domore_getsock(struct connectdata *conn,
curl_socket_t *sock,
curl_socket_t *socks,
int numsocks)
{
if(!numsocks)
return GETSOCK_BLANK;
/* 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. It makes a difference in the way: if we
connect to the site we wait for the socket to become writable, if
the site connects to us we wait for it to become readable */
sock[0] = conn->sock[SECONDARYSOCKET];
return GETSOCK_WRITESOCK(0);
if(conn && conn->handler->domore_getsock)
return conn->handler->domore_getsock(conn, socks, numsocks);
return GETSOCK_BLANK;
}
/* returns bitmapped flags for this handle and its sockets */