XNSServerLocationImpl.mesa
Demers, October 2, 1986 5:14:34 pm PDT
DIRECTORY
CrRPC USING [Call, CreateClientHandle, DestroyClientHandle, Error, GetCARDINAL, GetFWORD, GetHWORD, GetResultsProc, Handle, PutArgsProc, SetHops, SetTimeout],
Endian USING [FWORD, HWORD],
XNS USING [Address, broadcastHost, broadcastNet, Socket],
XNSServerLocation USING [EachAddressProc];
XNSServerLocationImpl: CEDAR PROGRAM
IMPORTS CrRPC
EXPORTS XNSServerLocation
~ {
FWORD: TYPE ~ Endian.FWORD;
HWORD: TYPE ~ Endian.HWORD;
maxPermissibleRadius: CARDINAL ~ 6; -- broadcasting to the entire Internet would be antisocial
GetXNSAddress: PROC [h: CrRPC.Handle] RETURNS [XNS.Address] ~ {
xNet: FWORD;
xHost: MACHINE DEPENDENT RECORD [a, b, c: HWORD];
xSocket: HWORD;
xNet ← CrRPC.GetFWORD[h];
xHost.a ← CrRPC.GetHWORD[h];
xHost.b ← CrRPC.GetHWORD[h];
xHost.c ← CrRPC.GetHWORD[h];
xSocket ← CrRPC.GetHWORD[h];
TRUSTED { RETURN [
[net~LOOPHOLE[xNet], host~LOOPHOLE[xHost], socket~LOOPHOLE[xSocket]] ] };
};
StopListening: ERROR ~ CODE;
LocateServers: PUBLIC PROC [
socket: XNS.Socket, -- destination socket for broadcast
maxHops: CARDINAL, -- radius of broadcast
remotePgm: CARD,
remotePgmVersion: CARDINAL,
eachAddress: XNSServerLocation.EachAddressProc, -- called with address of each responding server
firstResponseOnly: BOOLTRUE
] ~ {
h: CrRPC.Handle;
PutArgs: CrRPC.PutArgsProc ~ { NULL };
GetResults: CrRPC.GetResultsProc ~ {
n: CARDINAL;
addr: XNS.Address;
n ← CrRPC.GetCARDINAL[h];
IF n > 0 THEN {
addr ← GetXNSAddress[h];
eachAddress[addr];
IF firstResponseOnly THEN ERROR StopListening[] }
};
maxHops ← MIN[maxHops, maxPermissibleRadius];
h ← CrRPC.CreateClientHandle[
class~$EXCHANGE,
remote~[net~XNS.broadcastNet, host~XNS.broadcastHost, socket~socket]];
BEGIN
ENABLE StopListening => CONTINUE;
FOR hops: CARDINAL IN [0..maxHops] DO
h ← CrRPC.SetHops[h~h, low~hops, high~hops];
h ← CrRPC.SetTimeout[h, 200 + 300 * hops];
THROUGH [0..4) DO
CrRPC.Call[
h~h, remotePgm~remotePgm, remotePgmVersion~remotePgmVersion, remoteProc~0,
putArgs~PutArgs, getResults~GetResults
! CrRPC.Error => CONTINUE];
ENDLOOP;
ENDLOOP;
END;
CrRPC.DestroyClientHandle[h];
};
}.