XNSReachableImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Demers, December 2, 1986 0:47:06 am PST
DIRECTORY
Process USING [Abort, Pause, SecondsToTicks],
XNS USING [Address, broadcastHost, Host, Net, Socket],
XNSBuf USING [Buffer],
XNSEchoBuf USING [Buffer, hdrBytes],
XNSReachable USING [],
XNSRouter USING [Enumerate, GetHops, RoutingTableEntry, unreachable],
XNSRouterPrivate USING [Network, Route],
XNSSocket USING [AllocBuffer, Create, Destroy, FreeBuffer, Get, Handle, Put, SetGetTimeout, SetNoErrors, SetRemoteAddress, SetUserBytes],
XNSWKS USING [echo];
XNSReachableImpl:
CEDAR
MONITOR
IMPORTS Process, XNSRouter, XNSRouterPrivate, XNSSocket
EXPORTS XNSReachable
~
BEGIN
doIt: BOOL ← FALSE;
firstHopOnly: BOOL ← TRUE;
initialTimeoutMilliseconds: INT ← 250;
perHopTimeoutMilliseconds: INT ← 250;
maxTries: CARDINAL ← 10;
numQuickTries: CARDINAL ← 2;
EnsureHostReachable:
PUBLIC PROC [hisAddress: XNS.Address]
RETURNS [reachable:
BOOL] ~ {
network: XNSRouterPrivate.Network;
b: XNSBuf.Buffer ← NIL;
tempSocket: XNSSocket.Handle;
pingAddress: XNS.Address;
destHops: CARDINAL;
getTimeout, getTimeoutIncrement: INT;
IF NOT doIt THEN RETURN [TRUE];
destHops ← XNSRouter.GetHops[hisAddress.net];
SELECT destHops
FROM
XNSRouter.unreachable => RETURN [FALSE];
0 => RETURN [TRUE];
ENDCASE;
IF firstHopOnly
THEN {
[network, pingAddress.host] ← XNSRouterPrivate.Route[hisAddress];
IF network.xns.translation = NIL THEN RETURN [TRUE];
pingAddress.net ← network.xns.net;
pingAddress.socket ← XNSWKS.echo;
getTimeout ← initialTimeoutMilliseconds;
getTimeoutIncrement ← initialTimeoutMilliseconds }
ELSE {
pingAddress ← hisAddress;
pingAddress.socket ← XNSWKS.echo;
getTimeout ← initialTimeoutMilliseconds;
getTimeoutIncrement ← destHops * perHopTimeoutMilliseconds };
tempSocket ← GetTempSocket[];
XNSSocket.SetRemoteAddress[tempSocket, pingAddress];
reachable ← FALSE;
FOR try:
CARD
IN [1..maxTries]
DO
IF try > numQuickTries THEN getTimeout ← getTimeout + getTimeoutIncrement;
XNSSocket.SetGetTimeout[tempSocket, getTimeout];
IF b = NIL THEN b ← XNSSocket.AllocBuffer[tempSocket];
SendRequest[tempSocket, b];
b ← XNSSocket.Get[tempSocket];
IF (b #
NIL)
AND (b.hdr1.source.host = pingAddress.host)
THEN { reachable ← TRUE; EXIT };
ENDLOOP;
IF b # NIL THEN XNSSocket.FreeBuffer[b];
PutTempSocket[tempSocket];
};
SendRequest:
PROC [socket: XNSSocket.Handle, b: XNSBuf.Buffer] ~ {
eB: XNSEchoBuf.Buffer;
TRUSTED { eB ← LOOPHOLE[b] };
eB.hdr1.type ← echo;
eB.hdr2 ← [filler~0, type~request];
XNSSocket.SetUserBytes[b, XNSEchoBuf.hdrBytes];
XNSSocket.Put[b] };
theTempSocket: XNSSocket.Handle ← NIL;
GetTempSocket:
ENTRY
PROC
RETURNS [socket: XNSSocket.Handle] ~ {
ENABLE UNWIND => NULL;
IF theTempSocket = NIL THEN RETURN [XNSSocket.Create[]];
socket ← theTempSocket;
theTempSocket ← NIL;
XNSSocket.SetNoErrors[handle~socket, noErrors~FALSE];
};
PutTempSocket:
ENTRY
PROC [socket: XNSSocket.Handle] ~ {
ENABLE UNWIND => NULL;
XNSSocket.SetNoErrors[handle~socket, noErrors~TRUE];
IF theTempSocket #
NIL
THEN XNSSocket.Destroy[socket]
ELSE theTempSocket ← socket;
};
Daemon to ping all routers on directly connected nets
worker: PROCESS ← NIL;
workerSweepSeconds:
INT ← 150;
Start:
ENTRY
PROC ~ {
ENABLE UNWIND => NULL;
IF worker = NIL THEN worker ← FORK Worker[];
};
Stop:
ENTRY
PROC ~ {
ENABLE UNWIND => NULL;
IF worker #
NIL
THEN
TRUSTED {
Process.Abort[worker]; JOIN worker; worker ← NIL };
};
Worker:
PROC ~ {
EachEntry:
PROC[net:
XNS.Net, entry: XNSRouter.RoutingTableEntry] ~ {
network: XNSRouterPrivate.Network;
host: XNS.Host;
[network, host] ← XNSRouterPrivate.Route[
[net~net, host~XNS.broadcastHost, socket~XNSWKS.echo]];
IF network.xns.translation = NIL THEN RETURN;
[] ← network.xns.getEncapsulation[network, host];
};
DO
XNSRouter.Enumerate[proc~EachEntry];
Process.Pause[Process.SecondsToTicks[workerSweepSeconds]];
ENDLOOP;
};
END.