<> <> <<>> DIRECTORY Basics USING [bytesPerHWord, Card16FromH, FFromCard32, FWORD, HFromCard16, HWORD], CommBuffer USING [Overhead], CrRPCBackdoor USING [CallMsgHdr, callMsgHdrBytes, callMsgType, courierVersionNum, MsgHdr, ReturnMsgHdr, returnMsgHdrBytes, returnMsgType, SessionHdr, sessionHdrBytes], Process USING [Abort, CheckForAbort, MsecToTicks, Pause, Ticks], XNS USING [Address, broadcastHost, broadcastNet, Net, Socket], XNSBuf USING [Buffer, Hdr], XNSExchangeBuf USING [Hdr, hdrBytes, maxBodyBytes], XNSExchangeTypes USING [clearinghouseServiceType, ExchangeID], XNSRouter USING [Enumerate, GetHops, maxHops, RoutingTableEntry], XNSServerLocation USING [EachAddressProc], XNSSocket USING [AllocBuffer, Create, Destroy, FreeBuffer, Get, GetUnique32, GetUserBytes, Handle, Kick, SetNoErrors, SetRemoteAddress, SetUserBytes, waitForever], XNSSocketBackdoor USING [PutCached]; XNSServerLocationImpl: CEDAR PROGRAM IMPORTS Basics, Process, XNSRouter, XNSSocket, XNSSocketBackdoor EXPORTS XNSServerLocation ~ { FWORD: TYPE ~ Basics.FWORD; HWORD: TYPE ~ Basics.HWORD; <> maxRadius: CARDINAL ~ XNSRouter.maxHops; maxTries: ARRAY [0..maxRadius) OF CARDINAL _ [ 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6]; clicksPerResend: ARRAY [0..maxRadius) OF CARDINAL _ [ 2, 4, 6, 8, 10, 12, 12, 14, 14, 16, 16, 16, 18, 18, 18]; clickMSec: CARD ~ 200; clickTicks: Process.Ticks _ Process.MsecToTicks[clickMSec]; <> <> CallBuffer: TYPE ~ REF CallBufferObject; CallBufferObject: TYPE ~ MACHINE DEPENDENT RECORD [ ovh: CommBuffer.Overhead, hdr1: XNSBuf.Hdr, hdr2: XNSExchangeBuf.Hdr, sessionHdr: CrRPCBackdoor.SessionHdr, callMsgHdr: CrRPCBackdoor.CallMsgHdr <> ]; callBufferOverhead: CARDINAL ~ XNSExchangeBuf.hdrBytes + CrRPCBackdoor.sessionHdrBytes + CrRPCBackdoor.callMsgHdrBytes; <> ReturnBuffer: TYPE ~ REF ReturnBufferObject; ReturnBufferObject: TYPE ~ MACHINE DEPENDENT RECORD [ ovh: CommBuffer.Overhead, hdr1: XNSBuf.Hdr, hdr2: XNSExchangeBuf.Hdr, sessionHdr: CrRPCBackdoor.SessionHdr, returnMsgHdr: CrRPCBackdoor.ReturnMsgHdr, body: PACKED ARRAY [0..maxBodyHWords) OF HWORD ]; returnBufferOverhead: CARDINAL ~ XNSExchangeBuf.hdrBytes + CrRPCBackdoor.sessionHdrBytes + CrRPCBackdoor.returnMsgHdrBytes; maxBodyBytes: CARDINAL ~ XNSExchangeBuf.maxBodyBytes - CrRPCBackdoor.sessionHdrBytes - CrRPCBackdoor.returnMsgHdrBytes; maxBodyHWords: CARDINAL ~ maxBodyBytes/Basics.bytesPerHWord; <> addressBytes: CARDINAL ~ BITS[XNS.Address]/BITS[BYTE]; addressHWords: CARDINAL ~ BITS[XNS.Address]/BITS[HWORD]; NumberOfXNSAddresses: PROC [b: ReturnBuffer] RETURNS [n: CARDINAL] ~ { nB, nCheck: CARDINAL; TRUSTED { nB _ XNSSocket.GetUserBytes[LOOPHOLE[b]] }; n _ (nB - returnBufferOverhead - Basics.bytesPerHWord) / addressBytes; nCheck _ Basics.Card16FromH[b.body[0]]; IF nCheck # n THEN n _ 0; }; GetXNSAddress: PROC [b: ReturnBuffer, i: CARDINAL] RETURNS [XNS.Address] ~ { temp: ARRAY [0..addressHWords) OF HWORD; j, delta: CARDINAL; delta _ i*addressHWords + 1; FOR j IN [0..addressHWords) DO temp[j] _ b.body[j+delta] ENDLOOP; RETURN[ LOOPHOLE[temp] ]; }; StopBroadcast: PUBLIC ERROR ~ CODE; LocateServers: PUBLIC PROC [ remotePgm: CARD, remotePgmVersion: CARDINAL, eachAddress: XNSServerLocation.EachAddressProc, socket: XNS.Socket, net: XNS.Net, maxHops: CARDINAL, tryLimit: CARDINAL ] ~ { broadcaster: PROCESS; broadcasterDone: BOOL _ FALSE; exchangeID: XNSExchangeTypes.ExchangeID; sH: XNSSocket.Handle _ NIL; queryBuf: XNSBuf.Buffer _ NIL; replyBuf: XNSBuf.Buffer _ NIL; CleanUp: PROC ~ { XNSSocket.SetNoErrors[sH]; TRUSTED { Process.Abort[broadcaster]; JOIN broadcaster }; IF queryBuf # NIL THEN { XNSSocket.FreeBuffer[queryBuf]; queryBuf _ NIL }; IF replyBuf # NIL THEN { XNSSocket.FreeBuffer[replyBuf]; replyBuf _ NIL }; XNSSocket.Destroy[sH]; }; DirectedBroadcaster: PROC ~ { triesLeft: CARDINAL; clicksLeft: CARDINAL; hops: CARDINAL; hops _ XNSRouter.GetHops[net]; IF hops < maxRadius THEN { triesLeft _ MIN[maxTries[hops], tryLimit]; clicksLeft _ 0; XNSSocket.SetRemoteAddress[sH, [net, XNS.broadcastHost, socket]]; DO ENABLE ABORTED => EXIT; IF clicksLeft = 0 THEN { IF triesLeft = 0 THEN EXIT; XNSSocketBackdoor.PutCached[queryBuf]; triesLeft _ triesLeft.PRED; clicksLeft _ clicksPerResend[hops] } ELSE { clicksLeft _ clicksLeft.PRED }; Process.Pause[clickTicks]; ENDLOOP; }; broadcasterDone _ TRUE; XNSSocket.Kick[sH]; }; Broadcaster: PROC ~ { triesLeft: ARRAY [0..maxRadius) OF CARDINAL; clicksLeft: ARRAY [0..maxRadius) OF CARDINAL; tries, clicks: CARDINAL; done: BOOL; EachNet: PROC [net: XNS.Net, rte: XNSRouter.RoutingTableEntry] ~ { Process.CheckForAbort[]; XNSSocket.SetRemoteAddress[sH, [net, XNS.broadcastHost, socket]]; XNSSocketBackdoor.PutCached[queryBuf] }; FOR hops: CARDINAL IN [0..maxHops) DO triesLeft[hops] _ MIN[maxTries[hops], tryLimit]; clicksLeft[hops] _ hops; ENDLOOP; done _ FALSE; WHILE NOT done DO ENABLE ABORTED => EXIT; done _ TRUE; FOR hops: CARDINAL IN [0..maxHops) DO IF (clicks _ clicksLeft[hops]) > 0 THEN { clicksLeft[hops] _ clicks.PRED; done _ FALSE } ELSE { IF (tries _ triesLeft[hops]) > 0 THEN { XNSRouter.Enumerate[low~hops, high~hops, proc~EachNet]; done _ FALSE; clicksLeft[hops] _ clicksPerResend[hops]; triesLeft[hops] _ tries.PRED }; }; ENDLOOP; Process.Pause[clickTicks]; ENDLOOP; broadcasterDone _ TRUE; XNSSocket.Kick[sH]; }; CreateQuery: PROC ~ { b: CallBuffer; TRUSTED { b _ LOOPHOLE[queryBuf _ XNSSocket.AllocBuffer[sH]] }; b.hdr1.type _ exchange; b.hdr2.id _ exchangeID; b.hdr2.type _ XNSExchangeTypes.clearinghouseServiceType; -- BOGUS NAME  it really means "Expedited Courier" { v: HWORD ~ Basics.HFromCard16[CrRPCBackdoor.courierVersionNum]; b.sessionHdr _ [lowVersion~v, highVersion~v] }; b.callMsgHdr.msgHdr _ [msgType~CrRPCBackdoor.callMsgType]; b.callMsgHdr.callHdr _ [ tID~[0, 0], pgmNum~Basics.FFromCard32[remotePgm], pgmVersion~Basics.HFromCard16[remotePgmVersion], procNum~[0, 0]]; XNSSocket.SetUserBytes[queryBuf, callBufferOverhead]; }; ProcessReply: PROC ~ { b: ReturnBuffer _ NIL; bestHops: CARDINAL _ LAST[CARDINAL]; bestAddress: XNS.Address; IF XNSSocket.GetUserBytes[replyBuf] <= returnBufferOverhead THEN RETURN; IF replyBuf.hdr1.type # exchange THEN RETURN; TRUSTED { b _ LOOPHOLE[replyBuf] }; IF b.hdr2.id # exchangeID THEN RETURN; IF b.hdr2.type # XNSExchangeTypes.clearinghouseServiceType THEN RETURN; IF Basics.Card16FromH[b.sessionHdr.lowVersion] > CrRPCBackdoor.courierVersionNum THEN RETURN; IF Basics.Card16FromH[b.sessionHdr.highVersion] < CrRPCBackdoor.courierVersionNum THEN RETURN; IF b.returnMsgHdr.msgHdr.msgType # CrRPCBackdoor.returnMsgType THEN RETURN; FOR i: CARDINAL IN [0..NumberOfXNSAddresses[b]) DO addr: XNS.Address ~ GetXNSAddress[b, i]; hops: CARDINAL ~ XNSRouter.GetHops[addr.net]; IF hops < bestHops THEN { bestHops _ hops; bestAddress _ addr }; ENDLOOP; IF bestHops < LAST[CARDINAL] THEN eachAddress[bestAddress]; }; <> IF tryLimit = 0 THEN tryLimit _ LAST[CARDINAL]; maxHops _ MIN[maxHops, maxRadius]; sH _ XNSSocket.Create[getTimeout~XNSSocket.waitForever]; exchangeID _ Basics.FFromCard32[XNSSocket.GetUnique32[]]; CreateQuery[]; IF net = XNS.broadcastNet THEN TRUSTED { broadcaster _ FORK Broadcaster[] } ELSE TRUSTED { broadcaster _ FORK DirectedBroadcaster[] }; WHILE NOT broadcasterDone DO ENABLE { UNWIND => CleanUp[]; StopBroadcast => EXIT; }; replyBuf _ XNSSocket.Get[sH]; IF replyBuf # NIL THEN { ProcessReply[]; XNSSocket.FreeBuffer[replyBuf]; replyBuf _ NIL }; ENDLOOP; CleanUp[]; }; <> addresses: LIST OF XNS.Address _ NIL; EachAddress: PROC [addr: XNS.Address] ~ { addresses _ CONS[addr, addresses] }; }.