☰ Contents ‹ Previous Next ›

Writing a SunNET protocol

The protocols of SunNET are what everything else rides on top of. Protocols are used when you wish to broadcast information to more than one site at the same time. If not for the protocol layer, SunNET would have a difficult time operating properly. This sample application is similar to the one above.

Planning

Instead of linking two rooms, this application will link rooms on several different sites. We will keep the .remote_contents property and the :tell_contents verb written above. To save bandwidth we will use only one protocol for addition, removal, and broadcasting of actions. We will need to decide on an appropriate protocol name. It may be wise to check $sunnet_utils:protocols with the argument of every MOO on the network to ensure that the protocol is free to use. For the purposes of this example, we will use ROOM as the protocol name. The message for this protocol will be a list with two elements. The first element is a switch that tells the handler what to do with the second part, whether it be an addition, removal, or action broadcast.

Creating

A room must be created on each MOO for which the protocol will be received. Create a property with the name .remote_contents, setting it to {}, and copy the :description verb from the General Programming section above. Since we are going to run across several MOOs, the .remote_site and .remote_room properties are unnecessary. We will need to override the same verbs as above, but they will be written slightly differently. Security checks, if needed, are identical to the one outlined in the section above, replacing $sunnet_protocols with just $sunnet.

Sending Actions

To send actions, we need to override the three :announce verbs. :announce and :announce_all can be combined into one verb, while it is easier to put :announce_all_but into a verb to itself. Once we have the message built, we use $sunnet_utils:broadcast to send the message. At a minimum, :broadcast takes three arguments: the destination, which is GENERAL in this case so that the packets will go to all connected sites; the protocol, which is ROOM; and the third element is the message. We will symbolically represent the switch parameter of the message as a string value. For sending actions, this will be "ACTION".

Keeping that in mind (as well as the fact that the :announce suite has no security checks), program "announce announce_all" as:

$sunnet_utils:broadcast("GENERAL", "ROOM", 
          {"ACTION", @args});

and :announce_all_but as:

$sunnet_utils:broadcast("GENERAL", "ROOM", 
          {"ACTION", @listdelete(args, 1)});

Sending Contents

To send contents, we must override the :enterfunc and :exitfunc verbs. The second argument in both cases will be the name of the object to add or remove. For adding an element to the contents, the switch will be "ADD" and for removal, it will be "REMOVE". Again, no security checks are needed. Program :enterfunc as:
pass(@args);
$sunnet_utils:broadcast("GENERAL", "ROOM", 
          {"ADD", args[1].name});

and program :exitfunc as:

pass(@args);
$sunnet_utils:broadcast("GENERAL", "ROOM", 
          {"REMOVE", args[1].name});

Programming the Handler

The protocol handler will be the most complicated verb discussed so far in these tutorials. Even so, the verb is still fairly simple. You will need the security check from the previous section (changing $sunnet_protocols to just $sunnet) in the top of the verb and the following line to ensure the arguments are properly handled. We will call this verb, :room_handler.
{from, protocol, message, path, packetid, packettime, @rest} = args;

Here’s a description of the arguments from left to right.

For simplicity, the line above can be replaced with:

{from, protocol, message, @rest} = args;

where the arguments are as described above.

There are three parts that must be addressed. The broadcast of actions can be handled with the following lines:

for x in (this:contents())
  x:tell(@listdelete(message, 1));
endfor

Notice that we used listdelete() to remove the switch part of the message. The actual use of the switch will be demonstrated later.

To add contents, we use the following line:

this.remote_contents = {@this.remote_contents, message[2]};

To remove contents, we use the following line:

this.remote_contents = `listdelete(this.remote_contents, message[2] in this.remote_contents) ! ANY => this.remote_contents;

Now we use a series of if and elseif, to determine which part to execute based on the switch embedded in the message. The skeleton of this structure looks like:

if (message[1]=="ACTION")
  ... code to tell all contents the action ...
elseif (message[1] == "ADD")
  ... code to add an item to the remote contents list ...
elseif (message[2] == "REMOVE")
  ... code to remove an item from the remote contents list ...
endif

Putting this all together, the verb code would be:

if (caller != $sunnet && !$perm_utils:controls(caller_perms(), this))
  raise(E_PERM);
endif
{from, protocol, message, @rest} = args;
if (message[1]=="ACTION")
  for x in (this:contents())
    x:tell(@listdelete(message, 1));
  endfor
elseif (message[1] == "ADD")
  this.remote_contents = {@this.remote_contents, message[2]};
elseif (message[2] == "REMOVE")
  this.remote_contents = `listdelete(this.remote_contents, message[2] in
          this.remote_contents) ! ANY => this.remote_contents;
endif

Displaying Remote Contents

Just use the :tell_contents from the above section to display the remote contents.

Registering the Protocol

The next step is to let SunNET know that it can now handle the protocol. To do this, just eval the following line:
;$sunnet:add_protocol("ROOM", #OfTheRoom, "room_handler");

From here on out, SunNET will call #OfTheRoom:room_handler whenever it receives a packet containing information for the "ROOM" protocol.

Done

Since this document is for programming on the SunNET, it may not be a good idea to leave the protocol created in this document registered. In order to remove the protocol, use the following eval:
;$sunnet:remove_protocol("ROOM");

Further enhancements for this tutorial are identical to the further enhancements for the general programming section. Please use protocols sparingly and research to ensure that a protocol or one similar is not already being used before implementing it.

Once again, like the previous section, this is untested and may have some unforeseen bugs.
☰ Contents ‹ Previous Next ›