The server uses the same overall design as the LP server made by
Lars Pensjö. However, there are several important differences:
it uses less memory because it is disk-based; it can dump state and later
restart from a snapshot; it uses LPC as an internal interpreted language,
but also offers the option of precompiling LPC objects to C, making them
part of the program itself.
There are two special objects which determine the interface with the
server for all other objects: the auto object and the driver object.
The auto object (short for automatically inherited object) is
inherited by all other objects, except for the driver object. It can
redeclare the predefined functions (called kfuns, kernel functions)
that the server provides, and it can also define standard properties that
every object should have. Some kfuns <have> to be redeclared in an
environment with several users programming together; for instance, by
default there is no file security.
The auto object has some other special properties; static functions
declared in the auto object cannot be called using this_object()->func()
(i.e. they behave like kfuns).
The driver object defines several functions which are called by the
driver, mostly to translate pathnames.
The following functions will be called by the driver:
- in the driver object:

void initialize()

Called when the system starts up after a reboot.

void restored(varargs int hotboot)

Called after the system has restarted from a snapshot. The argument
will be 1 if connections and editor sessions were restored as well.

string path_read(string path)

Used to translate a path for an editor read command. If nil is
returned, the file cannot be read.

string path_write(string path)

Used to translate a path for an editor write command. If nil is
returned, the file cannot be written to.

object call_object(string objname)

Get the object named by objname as the first argument of a call_other().
compile_object() may be called from here.

int touch(object obj, string function)

Called just before a function is called in an object which has been
marked by call_touch(). A non-zero return value indicates that the
object's "untouched" status should be preserved through the following
call.

object inherit_program(string file, string program, int priv)

Get the object named by program as an object to inherit. The third
argument is 1 for private inheritance, 0 otherwise.
compile_object() may be called from here.

mixed include_file(string file, string path)

Used to translate include path <path> when included from the file
<file>. The return value can be either string for the translated path,
in which case an attempt is made to read the included file from that
location, or an array of strings, the concatenation of which represents
the included file itself. If any other value is returned, the file
<path> cannot be included.

void recompile(object obj)

If an object A is loaded, A inherits B, B inherits C, and the
version of C inherited by B is out of date, recompile(B) will be
called in the driver object. If B should actually be recompiled
(inheriting the new version of C from B), the driver object must
destruct B; if this is done, A will inherit the most recent
versions of B and C.

object telnet_connect(int port)

Return an object for a new connection on the given telnet port.

object binary_connect(int port)

Return an object for a new connection on the given binary port.

object datagram_connect(int port)

Return an object for a new connection on the given datagram port.

void interrupt()

Called if the driver receives a kill signal. The function should
shut down the system, and possibly dump state.

void compile_error(string file, int line, string err)

Handle a compile-time error; there can be several for the same
LPC file before a runtime error results (calling runtime_error).

string runtime_error(string error, int caught, int ticks)

Called when a runtime error occurs. <caught> is 0 if the error
is not caught, or 1 + an index in the return value of call_trace(),
indicating the frame in which the error is caught. runtime_error()
is called with rlimits (-1; -1) so it will not run out of stack or
ticks. <ticks> specifies the amount of ticks left at the moment
the error occurred. The return value is the new error string.

string atomic_error(string error, int atom, int ticks)

Called when a runtime error occurs in atomic code. <atom> is an
an index in the return value of call_trace(), indicating the frame in
which the atomically executed code starts. atomic_error() is called
with rlimits (-1; -1) so it will not run out of stack or ticks.
<ticks> specifies the amount of ticks left at the moment the error
occurred. The return value is the new error string.

string object_type(string file, string type)

Called when <file> is compiled, to translate the object path <type>
used in a type declaration, cast or <- operator.

int compile_rlimits(string objname)

An object uses the rlimits (stackdepth; ticks) { /* code */ }
construct, which can be used to assign arbitrary limits to function
call stack depth and ticks; running out of ticks during execution
causes an error. -1 signifies an infinite amount of stack space or
ticks.
During compilation, driver->compile_rlimits(objname) is called. If
non-zero is returned, the object will be able to use rlimits at
runtime with no restrictions. If 0 is returned,
driver->runtime_rlimits() will be called at runtime to further
verify if an object is allowed to change its rlimits (resource
limits).

int runtime_rlimits(object obj, int stack, int ticks)

Called at runtime for rlimits constructs not already cleared by
compile_rlimits(). If 0 is returned, the rlimits usage is illegal
and is aborted with an error.
Values for stack and ticks: < 0: infinite, 0: no change,
> 0: set to specified amount.

void remove_program(string objname, int timestamp, int index)

Called whenever the program of a master object is removed (because
the object has been destructed, and all clones and inheriting objects
have also been destructed). This function is called with
rlimits (-1; -1).
The "index" is a unique number for each master object, also
available with status(obj), which can help distinguishing between
different issues of the same object.

- in every object:

void create()

Called in an object which has just been cloned, or if it is not a
clone, just before a function is called in it for the first time.
The actual name of this function is configurable.

- in the user object (created by connect(), or returned by
driver->telnet_connect() or driver->binary_connect()):

int open()

A connection has just been opened for this object.
For a binary connection, if the return value of this function is
non-zero, a UDP channel will be opened for the same object. UDP
datagrams can be received from the same host and port as the TCP
connection is on, and after at least one datagram has been
received, send_datagram() can be used to send datagrams to that
destination.
For a telnet connection, the return value will be ignored.

void close(int flag)

The connection for this object has just been closed. close() is
called when the user goes linkdead, or when the user object is
destructed. The flag argument is 1 if the object is destructed,
0 otherwise.

void receive_message(string message)

This function is called with the text the user typed. For telnet
connections, this is always an entire line, with the newline at
the end filtered out. For binary connections, this is whatever
the other side of the connection saw fit to send, without any
filtering or processing.

void message_done()

This function is called when a string sent by send_message was
fully transmitted.

void datagram_attach()

This function is called when a response to the datagram challenge
has been received, opening a datagram channel on the current
connection.

void receive_datagram(string packet)

This function is called when a packet is received on the datagram
channel of the connection.

- in an object where connect() has been called:

void unconnected(int refused)

Called when an outbound connection failed to be established. The
flag argument is 1 when the connection was refused by the remote
host.


On startup, the system is configured with a configuration file, which
must specify the following configuration parameters:

param type meaning
--------------------------------------------------------------------------
telnet_port mapping A mapping containing host:port pairs, where the host
or string is a name, an IP number or "*", and the port
number number is a port on which to accept telnet connections.
Alternatively, a telnet port number.
binary_port mapping A mapping containing host:port pairs, where the host
or string is a name, an IP number or "*", and the port
number number is a port on which to accept raw TCP/IP
connections. Alternatively, a binary port number.
datagram_port mapping A mapping containing host:port pairs, where the host
or string is a name, an IP number or "*", and the port
number number is a port on which to accept datagram
connections. Alternatively, a datagram port number.
(optional)
directory string The base directory for the system.
modules mapping A mapping containing module:config pairs, where the
module string is the path of a runtime extension
module, and the config string is used to initialize it.
(optional)
users number The maximum number of active telnet and binary
connections.
datagram_users number The maximum number of active datagram connections.
(optional)
editors number The maximum number of simultaneously active
editor instances.
ed_tmpfile string The proto editor temporary file (actual files
will have a number appended).
swap_file string The name of the swap file.
swap_size number The total number of sectors in the swap file.
cache_size number The number of sectors in the swap cache in memory.
sector_size number The size of a swap sector in bytes.
swap_fragment number The fragment of all objects to swap out at the end of
each task (e.g. with a swap_fragment of 32, 1/32th
of all objects will be swapped out).
static_chunk number The size in bytes of a static or dynamic chunk
dynamic_chunk number of memory. Memory is divided into static memory
and dynamic memory; static memory is never freed.
Both are allocated in chunks of the specified size.
Setting the size of the static chunk to 0 will
cause the system never to swap out everything to
make more room for static memory, but will also
increase fragmentation.
dump_file string The name of the snapshot file.
dump_interval number The expected interval between snapshots, in seconds.
Effectively, the time during which the swapfile will be
fully recreated.
hotboot string* Program, with arguments, to execute during hotboot.
(optional)
typechecking number If zero, only functions with a declared type are
typechecked.
If one, all LPC functions are typechecked.
If two, additionally, nil (the value of an uninitialized
string, object, array or mapping variable) is a value
distinct from integer 0.
include_file string The standard include file, which is always
included automatically for each compiled object
(relative to the base directory).
include_dirs string* The standard system include directories (relative
to the base directory). In the first of those,
the include files which are automatically
generated on startup will be placed.
auto_object string The file name of the auto object (relative to the
base directory).
driver_object string The file name of the driver object (relative to
the base directory).
create string The name of the create function.
array_size int The maximum array and mapping size.
objects int The maximum number of objects.
call_outs int The maximum number of simultaneously active
callouts.