foundationI_fluffos_v1/
foundationI_fluffos_v1/bin/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/ChangeLog.old/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/Win32/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/compat/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/compat/simuls/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/include/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/clone/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/command/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/data/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/etc/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/include/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/inherit/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/inherit/master/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/log/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/single/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/single/tests/compiler/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/single/tests/efuns/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/single/tests/operators/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/u/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/tmp/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/windows/
foundationI_fluffos_v1/lib/
foundationI_fluffos_v1/lib/cmds/ambassador/
foundationI_fluffos_v1/lib/cmds/database/
foundationI_fluffos_v1/lib/cmds/soul/
foundationI_fluffos_v1/lib/daemon/include/
foundationI_fluffos_v1/lib/daemon/save/
foundationI_fluffos_v1/lib/daemon/services/
foundationI_fluffos_v1/lib/daemon/soul/
foundationI_fluffos_v1/lib/doc/build/
foundationI_fluffos_v1/lib/doc/build/room/
foundationI_fluffos_v1/lib/doc/build/virtual/
foundationI_fluffos_v1/lib/doc/driver/
foundationI_fluffos_v1/lib/doc/efun/
foundationI_fluffos_v1/lib/doc/etc/
foundationI_fluffos_v1/lib/doc/help/creator/
foundationI_fluffos_v1/lib/doc/help/hm/
foundationI_fluffos_v1/lib/doc/help/user/
foundationI_fluffos_v1/lib/doc/lpc/basic/
foundationI_fluffos_v1/lib/doc/lpc/data_types/
foundationI_fluffos_v1/lib/doc/lpc/etc/
foundationI_fluffos_v1/lib/doc/lpc/intermediate/
foundationI_fluffos_v1/lib/doc/lpc/types/
foundationI_fluffos_v1/lib/doc/mudlib/
foundationI_fluffos_v1/lib/doc/mudlib/features/
foundationI_fluffos_v1/lib/domains/Examples/etc/
foundationI_fluffos_v1/lib/domains/Examples/room/
foundationI_fluffos_v1/lib/domains/Examples/virtual/
foundationI_fluffos_v1/lib/domains/Examples/virtual/exaA/
foundationI_fluffos_v1/lib/domains/Examples/virtual/exaB/
foundationI_fluffos_v1/lib/domains/Examples/weapon/
foundationI_fluffos_v1/lib/domains/Standard/
foundationI_fluffos_v1/lib/domains/Standard/pools/
foundationI_fluffos_v1/lib/domains/Standard/std/
foundationI_fluffos_v1/lib/domains/Standard/xtra/
foundationI_fluffos_v1/lib/include/
foundationI_fluffos_v1/lib/news/
foundationI_fluffos_v1/lib/secure/cfg/
foundationI_fluffos_v1/lib/secure/cmds/adm/
foundationI_fluffos_v1/lib/secure/cmds/ambassador/
foundationI_fluffos_v1/lib/secure/cmds/mortal/
foundationI_fluffos_v1/lib/secure/etc/
foundationI_fluffos_v1/lib/secure/etc/approval/
foundationI_fluffos_v1/lib/secure/etc/elections/
foundationI_fluffos_v1/lib/secure/etc/mudlib/
foundationI_fluffos_v1/lib/secure/etc/quests/
foundationI_fluffos_v1/lib/secure/save/daemon/
foundationI_fluffos_v1/lib/secure/save/postal/d/descartes/
foundationI_fluffos_v1/lib/secure/save/users/d/
foundationI_fluffos_v1/lib/secure/std/
foundationI_fluffos_v1/lib/std/obj/
foundationI_fluffos_v1/lib/std/room/
foundationI_fluffos_v1/lib/std/user/
foundationI_fluffos_v1/lib/std/virtual/
foundationI_fluffos_v1/old/
foundationI_fluffos_v1/win32/
The Foundation I Mudlib automatically sets itself up so that you
are on the intermud network without any configuration on the part
of the administrator.  When your mud boots up for the first time,
it is on the network.  In addition, you never have to do anything
to maintain its status quo.  And adding new services when they are
invented is simple.

Network administration is handled by the object /daemon/network.c
You should never have to touch this file.  Services are handled by
the file /daemon/services.c  New services are added onto this file.

With the intrmud network, Each mud sets up on a port number 8 greater
than its login port (if your mus is at port 4000, the network daemon
listens to port 4008 for other muds).  When you boot up, you tell
another mud, your server mud, that you have booted up.  In return, it
adds you to its mudlist and then sends you a copy.  At that moment, you
are in full contact with all the muds with which it is in contact.

But what if your server mud is down?  The network daemon saves its mudlist,
so that in the event it goes a certain time after reboot without hearing from
the server mud, it will ask another mud on the old mudlist for mudlist info.
It will keep doing this using the old mudlist until it finally contacts
one of the muds from the old mudlist.  Muds which have not been
contacted over a certain period of time are dropped from the mudlist.

Every few minutes, the network daemon pings other muds to make sure they are
still there.  If they are there, it keeps them on the mudlist.  If they
are not there, it counts an absence of contact.  After so many contact
failures, it drops the mud from the mudlist.

Finally, when the mud shuts down, it sends to all the muds on the mudlist
shutdown notifcation so that they can remove your mud from the mudlist.

About the protocols:
The network daemon simply sends and receives strings of 256 characters or
less to other muds.  In incoming strings, it finds information about
which service is being requested, the name of the mud requesting, and its
port.  The network daemon then routes the incoming request to the
appropriate function in the services daemon as well as breaks up
the incoming string into a mapping.  That mapping is passed to the
function in question.  For example, the string:
"||NAME:Nightmare||PORTUDP:4008||ASKWIZ:descartes||WIZTO:forlock"
becomes:
([ "NAME" : "Nightmare", "PORTUDP" : "4008", "ASKWIZ" : "descartes", "WIZTO" :
  "forlock" ])
The function to which this information is passed is called:
incoming_<service name>()
Such that an incoming "mail_q" service request is routed to the function
incoming_mail_q() in services.c

Adding new services:
In order to add a new service, you need to know:
1) The name of the service
2) The name of the fields an incoming request sends
3) The name of the fields expected by the reply.
4) What the purpose of the new service is.

For example, let's add a locate service which locates a player on your
mud.  You already have the answer to number 4.  You know that the
asking mud sends "ASKWIZ", "TARGET", "NAME", and "PORTUDP" ("HOSTADDRESS" 
is added to all incoming requests by the network daemon).  In addition, you 
have leanred that that incoming queries have the service name "locate_q"
and outgoing answers are named "locate_a".  Outgoing answers are
expected to have the field "LOCATED" with a value of "yes" or "no".
You know have all of the information you need to build this new service.

First, setup a fucntion to handle incoming requests.  The name of this
function naturally will be "incoming_locate_q()".  And from the information
provided above, you know that a mapping with the fields "NAME", "ASKWIZ",
"TARGET", "PORTUDP", and "HOSTADDRESS" will be passed to the function.
So you have:

void incoming_locate_q(mapping info) {
    string ret;
    object ob;

/* first, make sure this is not some nasty wiz faking it */
    if(geteuid(previous_object()) != UID_SOCKET) return;
/* now, see if the taget is on the mud */
    if(!(ob = find_player(info["TARGET"]))) ret = "||LOCATED:no";
/* then make sure the person is not invis or hidden */
    else if(hiddenp(ob) || (int)ob->query_invis()) ret = "||LOCATED:no";
/* So the person is in fact on the mud */
    else ret = "||LOCATED:yes";
/* Set it up so we can have permission to send */
/* Now send an answer */
    NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
      "@@@"+SERVICE_UDP_LOCATE_A+"||NAME:"+mud_name()+"||PORTUDP:"+
      query_host_port()+"||ASKWIZ:"+info["ASKWIZ"]+ret+"||TARGET:"+
      info["TARGET"]+"@@@\n");
/* Return the obejct to nrmal permissions */
}

In the last line, you are telling the network daemon to send the string you
give to the address and port specified.  The function in the network daemon
is thus going to send the string:
"@@@locate_a||NAME:Nightmare||PORTUDP:4008||ASKWIZ:descartes||LOCATED:yes@@@\n"
to the mud which asked for the information.

You now can see exactly what sort of answer you would be getting back if
you were the mud asking for the information.  You would get this information
in the function "incoming_locate_a()".

void incoming_locate_a(mapping info) {
    object ob;

/* Again, make sure the call is being made from the right object */
    if(geteuid(previous_object()) != UID_SOCKET) return;
/* check to see if the asking person is even still on the mud */
    if(!(ob = find_player(info["ASKWIZ"]))) return;
/* Make sure there is something to tell */
    if(info["LOCATED"] != "yes") return;
/* The player the person was looking for was found! */
    message("info", capitalize(info["TARGET"])+" was located on "+
      info["NAME"]+".\n", ob);    
    return;
}

What else is missing?  You need to set up a function to send a query
for yourself!  Call it anything you like.  Currently, such functions are
called send_<service name>(), but nothing requires this.

void send_locate_q(string targ, string asking) {  
    mapping info;
    string *muds;
    int i;

    targ = lower_case(targ);
    asking = lower_case(asking);
/* Get a list of known muds to send to */
    info = (mapping)NETWORK_D->query_known_muds();
    i = sizeof(muds = keys(info));
/* Setup permissions to send a socket */
    while(i--) {
        NETWORK_D->send_udp(info[muds[i]]["HOSTADDRESS"], 
          info[muds[i]]["PORTUDP"], "@@@"+SERVICE_UDP_LOCATE_Q+"||NAME:"+
          mud_name()+"||PORTUDP:"+query_host_port()+"||ASKWIZ:"+asking+
          "||TARGET:"+targ+"@@@\n");
    }
/* Return to regular permissions */
}    

That is all there is to adding new services.  It is difficult to tell
what services will exist in the future.  Perhaps bulletin board reading,
http, and other services I cannot imagine now.  Since this will most
definitely happen, my goal in designing this system was to make it as
easy to setup and administrate a system which would grow in the future
without you having to become an expert in intermud protocols.  Current
supported intermud protocols:

finger
rwho
intercre (also known as interwiz and gwiz)
tell
mail
locate
support requests
startup requests
shutdown reauests
pings
mudlists

In addition, this is set up to be able to support any TCP services which
may some day come along.  That would require modification to the network
daemon.  But I do not foresee any use of TCP in the near future.  All
current services are UDP in part because Amylaar and CD sockets can only
handle UDP communications, but also because UDP is simpler at the mudlib
level with socket communications the way they exist today.