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.
|