[MUD-Dev] Re: DevMUD module configuration

James Wilson jwilson at rochester.rr.com
Mon Oct 26 20:30:04 CET 1998


On Mon, 26 Oct 1998, Jon Leonard wrote:
>As I was putting together a prototype this weekend, I realized that we
>don't yet have a sufficiently flexible scheme for configuring modules
>when we assemble them into a server.

the way this was done in linux is instructive. modules are initialized
much like executables, i.e.

/sbin/insmod 3c509.o io=0x300

(I'm sure you know this, I'm just being rhetorical.) this seems a useful
paradigm (modules in Perl are also amenable to this sort of treatment). As I
mentioned, the system I built a couple years ago used a text config file
for just this purpose. I like your proposal much better though for runtime
configuration.

>The most sophisticated system I've seen described involves having each
>module have a list of dependencies and other requirements, along with
>a list of features that it provides.  The loader would then be
>responsible for picking out modules to load when some feature is required,
>pointing out conflicts, and so on.
>
>The problem with this is that there are quite a few collections of modules
>(that I'd like to see, anyway) which are ambiguous or otherwise fail to
>correctly initialize in such a scheme.
>
>For example, suppose I have three modules:
>
>1) Socket, which provides network communication privliges
>
>2) Telnet, which sits on top of Socket to provide Telnet protocol
>    features and RFC compliance.  It has the same interface (or
>    a superset), for mix-and-match capability.
>
>3) World, which provides all of the non-transport functionality of a MUD.
>
>When loading World, how does the driver know whether to load telnet or not?
>Similarly, if Socket, Telnet and World are loaded, how does the loader
>know to connect World to Telnet instead of to Socket?

World could specify, "load me a telnet" or "load me a socket". Or it could
refer to something which telnet uniquely provided, e.g. "load me something
that provides RFC xyz compliance" and (assumimg Telnet claims to 
provide said compliance) all would be well. Or World could be invoked with

insmod World.o input=rawsocket.o
or
insmod World.o input=telnetd.o

[another example snipped]

>As a result, I have a new proposal.
>
>In addition to the special Bootstrap module (the only module known to always
>be part of the server), there is a special Config module.  The Config module
>is like any other module, except:
>
>1) There can only be one Config module in a server.
>
>2) The Bootstrap module automatically loads Config on startup, and passes
>   control to it.
>
>3) The config module is responsible for requesting modules to be loaded and
>   telling loaded modules which other modules to use in which ways.  It may
>   delegate this responsibility. 
>
>I expect most Config modules will immediately load a game language module
>and delegate responsibility to a program in that language.  This allows
>great flexibility including command-driven reconfiguration during run time,
>while allowing minimal Config modules for simpler MUDs.

indeed. /etc/rc.d, anyone?

>More details about the prototype mentioned above:
>
>In order to get a different perspective on how modules might fit together
>to make a MUD, I threw together a prototype.  (There's nothing quite like
>a segmentation fault to tell you that there's something wrong with a
>design.)
>
>It's missing some important abstractions, and I don't expect any of the
>code to survive into a distributable DevMUD.  Much like my IPC example,
>it only has two commands, "say" and "quit".  It does, however, use
>dynamic linking and separately compiled modules to build a runnable mud.

bravo.

>It's running at mud.slimy.com on port 2121, and the source can be found
>from http://mud.slimy.com/devmud/ by following the proto_1 link.
>(The name mud.slimy.com isn't very special: Mud.slimy.com = frost.slimy.com
>= devmud.slimy.com, etc.)

it has a certain Zen appeal, don't you think? heh.

looking through your source code, I immediately began thinking that the
inter-module protocol, so to speak, is going to have to be done quite
carefully so modules can really interoperate with a maximum of safety,
especially since the modules they'll be communicating with will ideally
be written by a heterogenous group of people. I get scared when I see 
function pointers being cast to void * and  back. Chris and Nick have
mentioned a couple of times the idea of defining interface types for 
modules, which makes me wonder

1. how are interfaces defined? ideally the mud-lang would be able to 
extend the set of interfaces at runtime.
and 
2. how are external interface implementations obtained in a type-safe way?

1. is a language issue I'm not brave enough to tackle at the moment. However,
a thought occurs to me as to how to do #2 in C++:

Every module defines a list of named objects which it exports. Each such
object  has some set of interfaces which it implements. There are no raw
function pointers; function objects or namespace-like objects with lots of
virtual methods are used instead. Every interface maintains a symbol table
listing all of the symbols which implement it (and perhaps, if a certain
symbol is  not currently in memory, the module exporting it is pointed to).
This would look something like

struct some_interface
{
	// normal functions
	virtual int foo (...) = 0;
	virtual int bar (...) = 0;

	// factory function
	virtual socket *hotline_to_jesus (void) = 0;
	
	/* these could go here or in a global table, or some tricks could be
	 * done with name mangling */
 	static some_interface *lookup_symbol (const string &name);

	/* for auto-install of the name in the symbol table. could also have a
	 * no-parameters constructor for anonymous objects. */
 	some_interface (const string &name)
	{ some_interface::install_symbol (name, this); }
private:
	static void install_symbol (const string &name, some_interface *i);
};

SO, a number of symbols could implement 'some_interface' and be
accessible in a type-safe manner via their names. Name conflicts would
be an error, of course, but since the names are just strings they could
be qualified, and the linker could do a scoped search for the most
appropriate match.

A similar thing could be done in other languages, of course, and name 
mangling is an obvious alternative to using per-type tables. I like this
approach  because it suits my design aesthetics (interfaces, factory 
classes and so on).

James




More information about the mud-dev-archive mailing list