Gossip Net
Volume Number: 3
Issue Number: 8
Column Tag: Advanced Mac'ing
Build a Gossip Net on Appletalk in C 
By Ty Shipman, San Diego, CA
What? I don’t understand! Where’s the tea? Like Arthur Dent these phrases
have been commonly uttered by most (if not all) programmers who have looked at and
used the chapter on AppleTalk. But, hopefully with the running example program
presented here you won’t hear those famous phrases quite so often.
The program entitled DON’T PANIC is a simple AppleTalk communications
program using Apple’s Pascal Interface. The program will allow a user to become an
active node on the network, see who else is on, and send and receive messages over that
network. A perfect example of a simple gossip net on Appletalk as MacTutor’s own
Shelly and Mona demonstrate in the figures shown on the right.
I’m assuming that you have a working knowledge of ‘C’, if you do not my code is
heavily commented. You should have read the section “Calling The AppleTalk Manager
From Pascal” in the chapter on AppleTalk Manager. If you have not read the section
skim it, now, then read the rest of the article. By the way, don’t read the whole
section, just the sub-sections on AppleTalk Transaction Protocol(ATP) and Name
Binding Protocol(NBP).
Now that you have skimed the sections lets go over some of the important
vocabulary you should become familiar with:
Network- a collection of 1 or more zones.
Zone- a collection of at least 2 nodes.
Node- a station(device) that occupies only one address on the zone.
Socket- the subaddress that does all the work.
Requester- The node that starts a session.
Responder- The node to which the requester sent the first message.
Because of the lopsided construction of the ATP, these definitions can change
depending on the way you set up your application. For example, a requester could send
a message to a responder to instruct it to be the requester, after this message. At that
point the definitions still hold, but the logic does not. Some print servers do this
because more data is sent to the printer than from the printer to the host.
InterNet
Address- the zone, node and socket numbers that are known to the net.
Entity- the name, type, and zone by which a device is known. This is the
only way you want to access other devices.
Tuple- the result that is formed with the Entity and the corresponding
InterNet Address.
BDSElement- (Buffer Data Structure) is a structure that contains information
required to access the data dealing with a response.
Mona asks Shelley about Boston on gossip net
Setup
Lets start our discussion with the function of ATCheck(). This function is the
first step in setting up any calls to the AppleTalk Manager in any language. The routine
takes care of checking and setting the two system globals, explained below, and opening
the correct drivers and system routines. The drivers that must be loaded and opened
are the .MPP(#9) and .ATP(#10). On the 128k Macintoshes the NBP routines must
be loaded explicitly so this routine checks to make sure that it is loaded -- as well.
The two system globals that should be examined before any thing is done with the
AppleTalk drivers are the Port Configuration byte, SPConfig, and PortBUse. SPConfig
located at 0x1FB, contains both the current configuration for both the modem (Port A)
and printer (Port b) ports. Figure 1 shows the layout of these bytes. You will notice
for AppleTalk we only need be interested in bit number 1 of SPConFig. If this bit is set
then we may not open AppleTalk because a Serial Driver is currently installed in the
port. The other global is the PortBUse byte at 0x291. This byte tell us the current
condition of port B (printer port)on the Macintosh 1. Currently, we only need to look
at the low nibble and the high bit. If the low nibble is set to 4 then the ATP driver has
been loaded and a node number has been assigned to this station. If the high bit is NOT
set this could mean that the port is currently being used by some other client (If you
are this far in the examination of the port bits, then the client is probably an
AppleTalk client), otherwise it could be a special driver associated with this port. (See
figure 1)
Shelley responds on gossip net
Lookup
Now that the drivers are loaded and running you will want to see who or what is
currently on the net. This is done through my routine Lookup(). In this routine you
will: get this device’s node and zone number; open a socket to receive requests;
register the name, type, and zone, with the respective socket, node, and zone number
on the network; do a network zone lookup; and set up to receive requests from other
devices.
You will notice I stated, “a network zone lookup.” This is because of the
redefinition of the wildcard ‘*’ for the zone. Apple had originally wanted this to be
“all zones” but changed it later to mean “the current zone” only. So what does that
mean -- you can’t look up anything on another zone unless you know the zone name or
number -- ahead of time. I hope this will be fixed, otherwise you will have to write
you own lookup type function.
The node and zone numbers were assigned when you opened the drivers in
ATCheck(). The zone number is set to zero unless there is a bridge on the zone and
then some non-zero number may be assigned. The node number the Macintosh receives
is a unique number that may or may not be the same as the last time. It is not a good
idea to depend upon the node number being the same even if you have not added other
devices to the net. If the user changes or updates the system on his or her station the
number may no longer be the same, but the name should be. We will talk about the
name a little bit later.
If you are following along in the code as I explain the different routines you will
notice that Inside Macintosh has the argument atpSocket of the ATPOpenSocket()
defined as a pointer to a byte. In my code it is a pointer to an integer. The difference is
that Apple’s byte here is 16 bits long. Don’t ask why, just watch out for this
inconsistency , it took me three day to find this oversight (thanks Steve).
A zone lookup is done quite simply. By setting six fields in the .nbpProto and
calling the NBPLookup() function you will get back all of the named entities known on
the current zone. If you are wondering how to filter out unwanted responses you set
the elements of the .nbpEntity structure to what you want returned. The entity is a
character string representation of a name (object), a type and a zone. So, lets say you
only wanted every thing from type “GORILLA”; you would just set the type to
“GORILLA” and leave the name (object) and zone in the wildcard state.
Another structure we have not seen is the retransmission information. This
structure contains two byte quantities that specify the time-out, in 8 tick quantities,
and the number of retries the system should attempt during the NBPlookup() calls.
You want the time-out to be large because some device may be busy and may not be able
to respond immediately If the retries is set to 0 the system will execute the call 0
times. (It should be noted here that most of the other calls requiring the
retransmission information take the time-out in seconds and the retries as n + 1
times). The buffer that holds the returned tuples is accessed by the pointer
.nbpBufPtr. The size of the buffer should be large enough to handle all expected tuples:
33 bytes for the object, type, and zone; and a byte each for the socket and node, then an
integer for the zone number.
To keep the code simple you want to make this call synchronous. The number of
named entities on the zone are returned in .nbpDataField. This field is set to 0 and
incremented with each tuple found. It does not include your name because a requester
and responder can not be on the same node. And if you don’t know who you are you’re in
sorry shape.
Notice that the Receive() function is called a total of five times. This is for two
reasons. One, you should be able to receive more than one request at a time. You may
not be able to respond to more that one at a time, but you should be able to receive