<> <> <> <<>> <> 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; }; <> 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; }; Start[]; END.