curl-library
Re: [PATCH] ftp code turned state machine, step 1?
Date: Wed, 5 Jan 2005 20:02:07 +0100
On Wed, Jan 05, 2005 at 03:35:11PM +0100, Daniel Stenberg wrote:
> I'm about to improve this situation by converting the FTP code into a
> state machine, where sending and receiving data is done in a
> multi-interface-friendly way.
Very cool - many thanks! Do you also have plans to do the same for the CWD
commands?
> Anyway, attached to this mail is my first trembling attempt that converts
> parts of the FTP code into a state machine. This is mainly only done for
> the connect phase (just after the TCP connect) so far but shows pretty
> good how the code will end up looking if we go this route.
/me puts "hacked libwww and survived" T-shirt on... ;-)
I'm not familiar enough with the curl code to say whether this looks
"good". I hope that it won't end up as convoluted as libwww. I think what
happened with libwww was that over time, "if-then-else" constructs were
added to deal with certain server behaviour. However, such constructs
result in additional states, and once a dozen or so is exceeded, it can get
confusing...
libwww's FTP state machine has 6 states (excluding "success" and "error"),
some of which have several sub-states. All in all, there are about 17
sub-states, each of which typically has 2 sub-sub-states %-|. Almost the
entire code consists of huge switch and and if-then-else statements. When I
did some minor hacking, it was fairly easy to change certain behaviour in
the way that I wanted. However, it was difficult to ascertain whether my
changes had unexpected side-effects elsewhere, because I had to check
manually how the state is reached.
A snippet of libwww code is below for its entertainment value. Maybe a bit
of advice: In contrast to libwww, try to keep your functions small, e.g. no
longer than one screen. :) Luckily, curl has a test suite, I would have
liked one for libwww...
Many thanks for your work!
Richard
-- __ _ |_) /| Richard Atterer | GnuPG key: | \/¯| http://atterer.net | 0x888354F7 ¯ '` ¯ } else { status = HTHost_read(HTNet_host(cnet), cnet); if (status == HT_WOULD_BLOCK) return HT_WOULD_BLOCK; else if (status == HT_LOADED) { int code = ctrl->repcode/100; if (code == 2) /* Logged in with passwd */ ctrl->substate = SUB_SUCCESS; else if (code == 3) { /* Account required */ HTAlertCallback *cbf = HTAlert_find(HT_A_PROMPT); HTAlertPar * reply = HTAlert_newReply(); if (cbf && (*cbf)(request, HT_A_PROMPT, HT_MSG_ACCOUNT, NULL, NULL, reply)) { ctrl->account = HTAlert_replyMessage(reply); ctrl->substate = NEED_ACCOUNT; } else ctrl->substate = SUB_ERROR; HTAlert_deleteReply(reply); } else if (ctrl->repcode == 530) ctrl->substate = PROMPT_USER; else ctrl->substate = SUB_ERROR; } else ctrl->substate = SUB_ERROR; ctrl->sent = NO; }Received on 2005-01-05