22 December 2003

So, as it’s been awhile since I’ve updated, I have lots of new developments. I’ve been fortunate to find some time to tinker with IS, and there’s lots of cool stuff coming along.

I’ve also removed the CVS directory from sourceforge, as I wasn’t using it, since I prefer to use my own repository for now. Once I get to a releasable 1.0 candidate, I may mirror my repository to sf, but for now you can access the bubblehouse web-repository using the links to the left. I will eventually open up pserver access through my firewall, but until i get some more interest in this I’m not going to bother.

Oh, and I’ve also started adding some unit-testing, using python’s unittest modules. I’m quickly becoming a believer in unit-testing, since I found a slew of bugs in the parser and registry (the only two tests i’ve made yet). I will need to make a unit-test for the entity.py behemoth, but i’m probably going to hold off until I implement ACLs for permissions instead of the “rwx” business, which will probably happen in the near future.

You can read the rest of this entry for more details, but the improvements/changes include:

  • Licensing - now under the GPL
  • Parser - all new parser engine
  • Verbs - enhanced developer functionality
  • Plugins - support for new “core” packages
  • Observations - dynamic observations engine for different clients
  • Security - ideas on a secure environment for verb authors
  • Build System - building and installation of client and server packages

Licenses

After much hemming and hawing, I’ve decided to license InnerSpace under the GNU Public License. There’s been a lot of talk around the GPL lately, what with SCO Group’s relentless lawsuits and subpoenas, and a number of groklaw pundits have convinced me, at least, that the GPL is a viable extension of copyright law. I’m not one of those people that’s super concerned about this kind of stuff usually, but I’ve been working on this project for a long time.

Parser

I’ve revamped the parser, and it’s a hundred times better. Previously, all sentences/commands had to be of the (BNF) form:

verb[[ object-specifier] direct-object[ preposition[ object-specifier] object-of-the-preposition]]

This sucked for a couple of reasons. In addition to the actual style of the sentences being rather limited, you were also limited to one preposition-object pair. The new parser form is:

verb[[[ object-specifier] direct-object]+[ preposition[ object-specifier] object-of-the-preposition]*]

I might be mixing up my BNF with RegEx, but basically what this comes down to is that you can now write verbs that support multiple preposition-object pairs (“take the coal from the fire with the tongs”), as well as skipping the direct object entirely (“look at phil”).

Verbs

The changes in the parser required some changes at the verb level, but they are few, and add some nice time-saving elements to verb authors.

First of all, the “vargs” verb attribute will be going away soon, though it was never really used anyways. The code editor on the client will also no longer present those fields as options (additionally, I’ve borrowed the jEdit text pane, which was placed into the public domain, to use inside the verb editor. It’s a big improvement).

The replacement for the functionality that “vargs” was supposed to provide will be provided by new functions in the verb environment, called getdobj, getpobj, hasdobj, haspobj, and their string equivalents, getdobjstr, etc…

For the “get” functions, if that object was not found, or that string was not used in the sentence, a NoSuchObjectError will be thrown. Also, as getpobj requires a preposition argument, possibly a NoSuchPrepositionError will be thrown, if the preposition given was not used in the sentence.

However, this still leaves open the problem of what to do if someone tries to use a player to do something, i.e., there’s a verb “kill” on a player called “wizard”, at this point, another player could say “kill phil with wizard”. This might be alleviated with the rwx bits on a verb, or rather, by adding another bit. More likely is that the “rwx” Unix-type permissions system will be repalced by ACLs.

I also want to implement a system for delaying events, using the twisted deferred system. Since deferreds already run as part of the reactor event loop, i think it could be added in relatively easily…

Plugins

It is now possible to subclass inner.space.entity.Verb, which I’m using to write the most basic verbs, such as Look, Emote, Say, etc…as well as some programmer-oriented ones. The cool thing about this is that all of these verbs are installed by dropping a twisted-plugin-based package into your PYTHONPATH. This would make it easier for third parties to distribute new core packages (kinda like LambdaMOO has LambdaCore and JHCore, and others). When subclassing a verb, authors override execute() and use the object passed in to access variables from the parser.

Observations

The current system for controlling what the “client” sees is hard-coded to send a number of attributes from the object. I’m going to change this so that if the object defines a verb called “get_observations”, that is called, and the result (presumably a hashtable) is sent to the client. If there is no verb defined, then the system object (#0) is checked for a verb with the same name that is passed an entity and the client object requesting it as arguments. I’m not sure if there will be a default after this, or if it will be required that the system object supports that verb.

Security

In my last post, I discussed ideas for a restricted execution enviroment. Since then I had a couple of talks with glyph about the idea, and he brought up some good points, that made me realize it’s truly difficult to allow totally untrusted code to run safely.

I realized long ago that one of the biggest issues to deal with is infinite recursion/looping, either with memory constraints, or infinite process spawning. A solution to this is to use the memory/process constraints placed on individual processes by the POSIX environment, i.e., forking processes for each verb. A prior version of InnerSpace attempted this, but had no simple way to provide interaction with the parent process.

One of my ideas is that, in combination with my SaferPython module, I could create a transaction-based verb environment. Hopefully to the coder, it would be relatively unintrusive, but basically we trust that if the parent process receives a transaction list from the child, then we know that there was no ouroboros action going on.

One thing that is really fruitless is keeping people who are really determined to hack the server from doing so. I mean the kind of people who are willing to overflow buffers in Python’s unicode handling, etc. I think it’s just as likely that an exploit could be found in any other aspect of the codebase.

I think that the combination of forking, transactions, and restricted environments could provide a safe environment for generally untrusted, but registered users of the system.

Build System

Finally, I’ve begun using distutils to provide a means for installing the server packages, and creating a JAR for the java client. Also, I have rudimentary support built-in for building a MacOS X double-clickable application. Right now, during build it asks you for a classpath to your TwistedJava.jar file, since hardcoding class paths into the Info.plist file seems to be the only way to access code outside the package.

Also, at the moment I am distributing a copy of the JavaApplicationStub binary which needs to be copied into the bundle for it to work. This is almost certainly illegal. I’m hoping that until I figure out a solution, Apple doesn’t sue me over 51 bytes of binary.

In conclusion…

Anyways, that’s pretty much everything for now. I’m trying really hard to keep everything updated, but this is the part of the process I hate the most, i.e., the documentation. I have to work on that.