MOO-cows Mailing List Archive


New bf suggestion: connect_player(CONN, OBJ) [Key: HTTP]

Hello everyone --

Playing around with ways to make MOO and HTTP be friendlier, we realized
we wanted to do "read(player, 0)" on a not-yet-logged-in connection to
read in the HTTP headers before deciding whether or not to log the
connection in.  Unfortunately :do_login_command() must return immediately,
or else the connection will not be logged in.  Any calls to suspend() or a
blocking read() result in OUTCOME_BLOCKED instead of an immediate return
(and thus no login!) While it's possible to use a non-blocking read() in a
polling loop to read multiple lines, no other processes can run on the MOO
until that polling loop exits. 

So we would like to be able to do blocking I/O on a not-yet-logged-in
connection.  One solution to this would be to change the way players are
logged in.  Currently if (Listening Object):do_login_command() returns a
valid player object, the server logs in a connection as that player.  If
we had a builtin function "connect_player(CONN, OBJ)" that actually logged
in connection CONN as player OBJ, :do_login_command() could use this
function to log in players at its leisure, after any blocking read() or
suspend() calls it wanted. 

Writing a "connect_player()" bf appears to be fairly easy, using the C
function player_connected() in server.c (with some thought given to
transfering task queues as well.) Current :do_command_task() verbs would
have to be slightly modified.  Line 20 of LambdaCore's :do_command_task()
would be replaced by: 

	candidate = $login:(args[1])(@listdelete(args, 1));
	return (valid(candidate) ? connect_player(player, candidate)
				 | candidate );

(Remember "player" in :do_login_command() is set to the negative object
number of the unlogged-in connection.) Needless to say it would have to be
a wizard-only builtin, and used with exceeding care. 

What are the uses of a such a builtin?

	(1) Being able to login an HTTP connection after reading all lines
of the request, without stopping all the other MOO processes during a
network-slow read().  This would prevent a slow incoming connection from
lagging an entire MOO. 

	(2) Transfering players between linked MOOs.  Let's say player X 
tries to walk from a room on MOO A to a room on MOO B.  MOO A sends a 
login/transfer-player message to MOO B, but MOO B may wish to read 
some data about player X from MOO A (e.g. description, last connection 
time, some kind of magical state on RPG MOOs, etc.) before deciding 
whether to allow or disallow a login.

	(3) Managing load on multi-processor MOOs.  If someone tries to
connect to processor A running "EnorMOOs", processor A may wish to first
query the other processors to find if one of them has a lighter load than
it does.  If so, it might deny a login and redirect the person to another

We would like to know what people think of such a builtin.  Would it break
anything other than current :do_command_task() verbs?  Could it be useful
for anything other than the above three thing?  Does it make sense to
include it in the server? 

And of course, is there some easier way to do blocking I/O on unlogged-in

Thanks for your help!

Colin McCormick
Nate Kurz
Tripod, Inc.

Home | Subject Index | Thread Index