Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - silenus

Pages: 1 2 [3]
31
Design Lab / security- what should determine resource/user access?
« on: November 13, 2007, 01:50:02 AM »
I have finished writing a prototype daemon for a security module which can be plugged into an existing mudos library with minimal hassle. The main problem I am having is determining what policy is appropriate for resources and users in the system. I intend to leave these decisions up to a policy daemon or customized policy functions inside the existing daemon.

The question is what parameters should be passed to these functions? i.e. what information is relevant to the object in question and what should determine user/resource access. So far I only know of two simple systems one is primarily file based line *nix where user/resource access for the most part is determined by the objectid path only. The other is DGD's kernel lib where there is a fixed policy in most cases and only certain parts of the path have significant meaning (outside of /kernel and maybe to some extent /System)  and access for the most part is determined by who clones the object (this affects ownership and various things like management of resource pools).

So thus far we have two parameters the object_id (or file path) and the "creator". But should there be others? and can there be a systematic uniform policy that makes sense if you do per object access permissions?





 

32
Design Lab / initialization code and persistent servers
« on: October 18, 2007, 02:23:40 AM »
Alot of code on most muds consists of data initialization code- but I am curious with persistent servers now (or people running servers with persistence modules or DB's for backends)- whether as some people have begun suggesting it might be safe in many cases to use an init once scheme throw away the initialization code scheme.

Of course there are certain things in terms of security you would have to be able to guarantee. For example data integrity becomes a critical issue in this situation since you no longer have the script for redundancy in case the data is deleted.

I suspect even in a traditional LPmud with persistence builtin you could perhaps take advantage of this to some extent. For example things like rooms would only have to be generated once using a system like Dead souls QCS perhaps without modifying the underlying script but instead by just cloning a copy of some base object and linking it into the system configuring it's properties until you are satisfied then locking it. For other certain types of items which do not need resets this would be true as well.

As for the reset() issue I wonder if it is possible to some extent to do away with it. This seems more a limitation of current area design than a problem with the general scheme of discarding initialization code. Not sure if anyone has any thoughts on this but it came up when I was working with DGD.






 

33
Design Lab / multi-threaded versus single threaded mud servers
« on: September 19, 2007, 12:35:19 PM »
I am in the early stages of designing a new driver which hopefully I can implement over the course of time. One issue for me is the advantage and extent that multi-threading should be used in a driver or server design. I know for certain types of applications the speed up you get from using OS threads might be quite limited. I am curious if mudding is one of those applications where if you even exposed fully a nice parallel model that was easy to work with and fast would the inherent limitations of the application restrict the speed up.

I would be curious to hear different peoples opinions on this.

Thanks in advance,

34
Design Lab / new server design- call for features
« on: July 25, 2007, 01:03:20 PM »
I have been considering building a new server for muds and this is a project which is still in the early planning stages. I have certain features mapped out and others which I am still debating how best to implement. However my main problem is that currently I dont have enough features to differentiate myself from the current generation of servers. I am curious what sorts of features people would like to see if such a project were brought to fruition.

Some current features I have been considering include-

functional language design
a graph-based virtual machine.
persistence(via XML)
metaprogramming/reflection support
support for distributed middleware such as ICE/CORBA
builtin security kernel(capability based or ACL based)


Thanks in advance,

Silenus.







35
Code Vault / Almost full persistance under MudOS (DS)
« on: June 09, 2007, 03:02:31 PM »
Here is a prototype version of a rudimentary persistence mechanism I wrote for MudOS (DS). Currently it's not without it's flaws- specifically on a large mud with alot of objects the memory usage of the daemon is not optimized. I will add this feature in the future. The code consists of two files and requires some minor modifications to /lib/user/autosave.c to get it to work. Some of the other files need some minor modifications also since the new inheritable does not contain currently contain SetSaveRecurse() and SetSave() has been changed to return int instead of string array. Here is both the inheritable and the daemon. Hopefully someone will find it useful.

Code: [Select]
/*
        /lib/persist.c
  Silenus@Desperate Sorrows - 2007-06-10
Designed to work with the DeadSouls Library v2.4.x
Version : 0.001
*/

#include <daemons.h>

private static array Save = ({});

protected int AddSave(string array a)
{
Save += a;
return 1;
}

string array GetSave() { return copy(Save); }

void eventRestore(mapping m)
{
if( previous_object() != find_object(PERSIST_D) ) error("Illegal call to eventRestore()." + identify( previous_object(-1) ) );

foreach(string v in Save)
{
store_variable(v, m[v] );
}

foreach(object o in m["#inventory#"] )
{
o->eventMove( this_object() );
}
}

void eventSave()
{
PERSIST_D->SaveObject( this_object() );
}

int eventDestruct()
{
PERSIST_D->SaveObject( this_object() );
return destruct( this_object() );
}

mapping GetSaveMap()
{
// if( previous_object() != PERSIST_D ) error("Illegal call to GetSaveMap().");

mapping sMap = ([]);
foreach(mixed v in Save)
{
sMap[v] = fetch_variable(v);
}
sMap["#inventory#"] = ({});
foreach(object o in all_inventory( this_object() ) )
{
sMap["#inventory#"] += ({ o });
}

sMap["#base_name#"] = base_name( this_object() );
return sMap;
}

protected void create()
{
PERSIST_D->GetObjectID( this_object() );
}

Code: [Select]
/*
    /secure/daemon/persist_d.c
  Silenus@Desperate Sorrows - 2007-06-10
Designed to work with the DeadSouls Library v2.4.x
Version : 0.001
*/
 

#include <save.h>

string GetObjectID(object);
object GetObject(string);
mapping ConvertSaveMap(mapping);
mapping ConvertRestoreMap(mapping);
string array FindMapObjectIDs(mapping);
mixed ConvertSaveVariable(mixed);
mixed ConvertRestoreVariable(mixed);
string array FindVarObjectIDs(mixed);

private static mapping Objects = ([]);
private static mapping ObjectIDs = ([]);
private mapping SavedObjects = ([]);

private string GenerateObjectID(object o)
{
string baseName, objectID;
int n;

baseName = base_name(o);
if( file_name(o) == baseName )
{
objectID = baseName;
}
else
{
n = 0;
while( !undefinedp( SavedObjects[baseName + "#" + n] ) )
{
++n;
}
objectID = baseName + "#" + n;
}
ObjectIDs[o] = objectID;
Objects[ objectID ] = o;
SavedObjects[ objectID ] = ConvertSaveMap( o->GetSaveMap() );
return objectID;
}

string SaveObject(object o)
{
string objectID;

if( !inherits(LIB_PERSIST, o ) ) return 0;
if( undefinedp( ObjectIDs[o] ) )
return GenerateObjectID(o);

SavedObjects[ ObjectIDs[o] ] = ConvertSaveMap( o->GetSaveMap() );

return ObjectIDs[o];
}

string GetObjectID(object o)
{
string objectID;

if( !inherits(LIB_PERSIST, o ) ) return 0;
if( !undefinedp( ObjectIDs[o] ) ) return ObjectIDs[o];
// otherwise return a new reference not in the SavedObjects keys

return GenerateObjectID(o);
}

int RemoveObjectID(string s)
{
// might need to add a secure override here for stray references...
if( undefinedp( SavedObjects[s] ) ) return 0;
if( previous_object() != Objects[s] ) return 0;
map_delete( SavedObjects, s );
map_delete( Objects, s);
map_delete( ObjectIDs, previous_object() );
return 1;
}

varargs object GetObject(string s)
{
object o;

if( !undefinedp( Objects[s] ) || Objects[s] != 0 ) return Objects[s];

if( SavedObjects[s] )
{
if( SavedObjects[s]["#base_name#"][1] == s )
o = load_object(s);
else 
o = new( SavedObjects[s]["#base_name#"][1] );
// maybe add patching behavior here as well......
o->eventRestore( ConvertRestoreMap( SavedObjects[s] ) );

ObjectIDs[o] = s;
Objects[s] = o;


return o;
}
return 0;
}

mapping ConvertSaveMap(mapping m)
{
mapping cMap = ([]);
foreach( string v in keys(m) )
{
cMap[v] = ConvertSaveVariable( m[v] );
}
return cMap;
}

mapping ConvertRestoreMap(mapping m)
{
mapping cMap = ([]);
foreach( string v in keys(m) )
{
cMap[v] = ConvertRestoreVariable( m[v] );
}
return cMap;
}

string array FindMapObjectIDs(mapping m)
{
string array a = ({});
foreach(string v in keys(m) )
{
a += FindVarObjectIDs( m[v] );
}
return a;
}

mixed ConvertSaveVariable(mixed v)
{
mapping m;
switch ( typeof(v) )
{
case "int": case "float": case "string": case "function": case "class":
return ({ typeof(v), v });
case "object":
return ({ "object", GetObjectID(v) });
case "array" :
return ({ "array", map( v, (: ConvertSaveVariable($1) :) ) });
case "mapping" :
m = ([]);
foreach( mixed k in keys( v ) )
{
m[ k ] = ConvertSaveVariable( v[k] );
}
return ({"mapping", m});
}
}

mixed ConvertRestoreVariable(mixed v)
{
mapping m;
switch( v[0] )
{
case "int": case "float": case "string": case "function": case "class":
return v[1];
case "object":
return GetObject(v[1]);
case "array":
return map( v[1], (: ConvertRestoreVariable($1) :) );
case "mapping":
m = ([]);
foreach( mixed k in keys( v[1] ) )
{
m[ k ] = ConvertRestoreVariable( v[1][k] );
}
return m;
}
}

string array FindVarObjectIDs(mixed v)
{
string array a;
switch( v[0] )
{
case "int": case "float": case "string": case "function": case "class":
return ({});
case "object" :
return ({ v[1] });
case "array" :
return implode( map( v[1], (: FindVarObjectIDs($1) :) ), (: $1 + $2 :), ({}) );
case "mapping":
a = ({});
foreach( mixed k in keys( v[1] ) )
{
a += FindVarObjectIDs( v[1][k] );
}
return a;
}
}

void eventGarbageCollect()
{
//what is the terminal condition?

    mapping CheckedMap = ([]);
    mapping CheckMap = ([]); //until check list is empty
    string array CheckArr = ({});
    string Current;

foreach( string i in keys(SavedObjects) )
{
debug("a",i);
debug("b", SavedObjects[i]["#base_name#"] );
if(i == SavedObjects[i]["#base_name#"][1] )
{
debug("c", i );
CheckMap[i] = 1;
CheckArr += ({i});
}
}

while( sizeof(CheckArr) )
{
Current = CheckArr[0];

foreach( string i in FindMapObjectIDs( SavedObjects[ Current ] ) )
{
debug("hmmmm", i );
if( !CheckedMap[i] && !CheckMap[i] )
{
CheckMap[i] = 1;
CheckArr += ({i});
}
}

CheckArr = CheckArr[1..];
map_delete(CheckMap, Current);
CheckedMap[Current] = 1;
}

foreach( string j in keys(SavedObjects) )
{
if( !CheckedMap[j] ) map_delete(SavedObjects,j);
}
}

mapping GetSavedObjectsMap()
{
return copy(SavedObjects);
}

private int eventSave()
{
call_out( (: eventSave :), 1800 );
return save_object(SAVE_PERSIST, 1);
}

int eventDestruct()
{
save_object(SAVE_PERSIST, 1);
return destruct( this_object() );
}

static protected void create()
{
unguarded( (: restore_object, SAVE_PERSIST, 1 :) );
call_out( (: eventSave :), 1800 );
eventGarbageCollect();
}
 

36
Drivers / DGD 1.2.128 with network patch and intermud3
« on: June 03, 2007, 04:04:00 PM »
Hi everyone,

I have been lately taking a look at DGD but would like some of the capabilities in the network patch (which is slightly out of date with respect to the experimental patches) and was wondering if anyone had any experience getting the latest experimental patches to work with the network patch. I am also wondering if the specification document for intermud3 is still out there somewhere.

Thanks in advance,

Silenus

37
Code Vault / a pair function adapters for sort_array
« on: April 17, 2007, 08:53:23 AM »
I wrote a pair of function adapters for sort array which came up in a problem in sorting and displaying list data. The first comparator() converts a binary "greater or equal than" comparison into the 3 value comparison needed by sort_array that returns 1,0, or -1 depending on if the value is greater, equal or less than the respective second value respectively for example to sort a list of integers with this function one would do the following:

sort_array(array_of_ints, comparator( (: $1 >= $2 :) ) )


The second function is for sorting tuples when you have to sort a list of items which consist of lists of data or tuples where each element at a given index is of the same type. i.e. ({"Silenus", 1, "orc", "warrior"}), ({"Cratylus", 1, "human", "mage"}) it creates a comparison function which gives priority to the indexes as ordered. An example usage might be (using the previous data)-

sort_array(array_of_tuples, tuple_comparator( ({ comparator( (: $1 >= $2 :) ), (: strcmp($1,$2) :) }), ({1,0}) ) )

which prioritizes the sort by level and if the levels are found to be equal sorts by name.

Both functions rely on tricks from functional programming in that they both create functions on the fly based on a function or functions passed in. The code might be a bit cryptic to those not use to this style but is illustrative of this approach.




/* Converts a greator or equal binary comparator into a 3 value comparator */
public function comparator(function f)
{
   return (: evaluate($(f), $1, $2) ? ( evaluate($(f), $2, $1) ? 0 : 1) : -1 :);
}


/*
    Compares two tuples in the order specified by the indices. If a comparator
    applied to an index early in the order results in equality, the next
    comparator is used on the next index on the list. 
*/
private function tuple_comparator_(function array, int array);

public function tuple_comparator(function array f, int array i)
{
   if( sizeof(f) != sizeof(i) ) error("Argument arrays must be of the same size.");
   return tuple_comparator_(f,i);
}

private function tuple_comparator_(function array f,int array i)
{   
   if( sizeof(f) == 0 ) return (: 0 :);
   return (: evaluate( $(f[0]), $1[$(i[0])], $2[$(i[0])] ) != 0 ? evaluate( $(f[0]), $1[$(i[0])], $2[$(i[0])] ) : evaluate( $(tuple_comparator_(f[1..],i[1..])), $1, $2 ) :);
}

 

   

38
Design Lab / meta programming and LPC etc
« on: April 09, 2007, 03:01:02 PM »
Hi folks,

I have been working on a meta programming tool for MudOS which so far seems to work on DS 2.4.1 but I am sure will work for the most part on other libraries for MudOS. The issue that I am wrestling with is how to further develop this tool. The basic idea I have so far implemented is quite simple-

The code simply hooks into compile_object with a slightly altered syntax. The file is parsed and converted into a generator LPC object which then is used to create the real LPC code which is compiled as an object and returned as object.

The issue here for me is my syntax so far is far from pretty. Currently @@@ tags are used to mark special regions and these are parsed as either text functions or copied wholesale into the constructed object file. The text functions are called by the user in a special block which is used to construct the remainder of the file. I wish however that this syntax could be a bit cleaner.

I am curious if there have been other projects for extending LPC in this manner which might have a nicer syntax I could perhaps emulate. Or if anyone has better ideas of how to mix LPC as data and LPC as generative functions in a single file.

Regards,

Silenus.


39
Code Vault / partition_array sefun
« on: April 04, 2007, 03:08:22 PM »
Someone mentioned a problem on intercre/ds channel(can't remember which) about grouping users with the same ip addresses into clusters and I thought of this as a possible solution and decided to post it. It's a bit more general and is based on the idea of partitions and equivalence classes though there is in this case only a partition function. I hope someone finds it useful. For example to solve the above problem would be quite easy once you have this function just do- partition_array( map( users(), (: query_ip_number($1) :) ) ) and implode the result as needed.

/*
   partitions an array into equivalence classes based on a partition function
    example usage- partition_array( ({1,2,3,4,5,6}), (: $1 % 2 :) ) would return
    ({ ({2, 4, 6}), ({1, 3, 5}) }).   
*/

varargs mixed array partition_array(mixed array ar, function f)
{
   mapping m = ([]);
   f = undefinedp(f) ? (: $1 :) : f;
   
   foreach(mixed elem in ar)
   {
      if( undefinedp( m[ evaluate(f, elem) ] ) ) m[ evaluate(f, elem) ] = ({ elem });
      else m[ evaluate(f, elem) ] += ({ elem });
   }
   return values( m );
}


Pages: 1 2 [3]