cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: [PATCH] ftp code turned state machine, step 1?

From: Richard Atterer <richard_at_2005.atterer.net>
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