Subject: Bug in 1.7.6?

From: [email-masked]
Date: Mon, 11 Oct 1993 19:08:36 -0700

Okay, I've changed ForeMOO over to 1.7.6, and this verb is
giving me problems:
 
#34:"verify*_email_address"   this none this
 1:  if (!caller_perms().wizard)
 2:    return E_PERM;
 3:  endif
 4:  address = args[1];
 5:  parsed = $network:parse_address(address);
 6:  username = parsed[1];
 7:  hostname = parsed[2];
 8:  conn = open_network_connection(hostname, 25);
 9:  fork (0)
10:    while (1)
11:      line = read(conn);
12:      if (line[1..3] == "250")
13:        boot_player(conn);
14:        return E_NONE;
15:      elseif (line[1..3] == "550")
16:        player:tell("E-mail address is NOT valid.");
17:        return E_INVARG;
18:      endif
19:    endwhile
20:  endfork
21:  vrfycmd = "VRFY " + username;
22:  notify(conn, vrfycmd);
 
=======================================================
Here's what I get when I used the verb:
 
;$network:verify("[email-masked]")
=> 0
 
;$network:verify("[email-masked]")
=> 0
E-mail address is NOT valid.
 
Now, I KNOW there's nothing in the code that could return a 0
value. And I also know that this verb worked under, well, 1.7.0
anyway, and I'm pretty sure under 1.7.5, though I don't really
know when and if it was used under 1.7.5. Is this a bug? Or
is it a new feature whose effects I have not extrapolated to
this result?
 
Just wondering,
====Rob.

---

From: Pavel Curtis <[email-masked]>
Date: Tue, 12 Oct 1993 22:54:31 -0700

> Date:	Mon, 11 Oct 1993 19:08:36 -0700
> From:	[email-masked]
>  
> value.

Knowledge is a funny thing, really, since what we know and what is true are
such different things... :-)

This verb will *always* return zero unless it returns E_PERM on line 2.  The
reason is that it always lets control fall off the end of the verb and that
always results in a returned value of 0.

The MOO bug in this code (as opposed to the various SMTP/DNS bugs pointed out
by others) is that, contrary to the explicit and strenuous recommendations of
the LambdaMOO Programmer's Manual, it does not do all of the read()ing from the
opened network connection in the *same task* that did the call to onc().  This
is necessary because otherwise it is possible (and usually likely) for some of
the output from the connection to get treated as normal command input by the
server.  To keep this from happening in 1.7.*, you *must* do all of your
read()s in the very task that called onc().  In any other situation, it is
possible for input to arrive in the task queue without a waiting read()ing task
to gobble it up and from there to find its way into the built-in command
parser.

Thus, instead of this pattern from above:

	...
	x = open_network_connection(...)
	...
	fork (..)
	  ...
	  while (read(x) ...)
	  ...
	  endwhile
 	  ...
	endfork
	...
	notify(x, ...);
	...

one should use this pattern:

	...
	x = open_network_connection(...)
	...
	notify(x, ...);
	...
	while (read(x) ...)
	  ...
	endwhile

===============================================================================

Now, that was the truth, but *should* it be so?  I propose in version 1.8.0 to
eliminate the possibility of output from an open_network_connection() being
treated as normal MOO commands.  Outbound network connections would be
completely distinguished from inbound ones and only read() would drain the
received output from the connection.

I am aware that such a change would be incompatible with the way some onc()
applications are currently written, notably at least one of the various MOO-net
implementations.  I believe, however, that such a change would (1) make it
easier to write reliable onc() applications, and (2) be much easier to explain
to people.

Since I am going to resume full-time work on 1.8.0 within the next week or so,
now is the time to speak up about this proposed change.  Absent any persuasive
arguments in favor of the status quo (and more persuasive than "but I'd have to
rewrite parts of MOO-net"), I will implement the proposal.

Please let me hear from you (preferably in mail sent to MOO-Cows, so that
others can respond) if you have major problems with this change.

	Pavel

---

From: [email-masked] (Jonathan Bradshaw)
Date: Tue, 12 Oct 1993 23:25:51 -0700

As I working on a method for interacting with an IMAP mail server from the
MOO I disliked having a process sitting in a read() loop since information
could be sent at any time from the IMAP server (new mail etc) I would
run forever while the connection was valid. So I tried something. I
had $network.pipes {}, along with a '$network:create_pipe' verb. The
$network:close() automaticly removed any references in both
.open_connections and .pipes. 

#0:do_login_command was modified to do a check:

if (data = $list_utils:iassoc($network.pipes, player))
  data[2]:(data[3])(argstr);
  return;
endif;

Well, you get the idea. Basically, I was saying 'if this connection sends
any data to the moo, go run this verb' [yes, I know argstr does not work
in server verbs up until 1.7.6 <grin>]

Anyway, it works quite well. The negative side is that it creates a new
process for each line of data but the forked() reads did that too. 

Anyway, its an idea that can be improved upon and maybe a server mod would
improve it. I welcome ideas. It means I don't have a bunch of suspended
programs sitting around anymore waiting for data.

Comments? Suggestions?

-- 
 Jonathan Bradshaw | Preferred E-Mail is: [email-masked] | Ham N9OXE
 WNDU-AM/FM/TV South Bend IN | Opinions stated are mine and not of my employer
 PGP 2.2 Key fingerprint is:  EA 16 1B 5D 5D 94 6B 06  58 FD E6 E9 52 F3 6E 11 
 "If any girl rejects you, don't you doubt it's part of the .plan" - D. Gibson

---

From: Pavel Curtis <[email-masked]>
Date: Wed, 13 Oct 1993 09:44:55 -0700

> Date:	Tue, 12 Oct 1993 23:25:51 -0700
> From:	[email-masked] (Jonathan Bradshaw)
> 
> run forever while the connection was valid.

But a read() task that's just waiting for input is cheap; it doesn't use much
memory and it doesn't cost any time anywhere else in the server.  I'd say it's
the cheapest, simplest, and most reliable technique for handling the input.

	Pavel