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.