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] }; }. ζXNSServerLocationImpl.mesa Demers, December 20, 1986 1:20:53 pm PST Parameters Expedited Courier Message Buffers Call buffer Body is empty Return buffer. Unmarshalling Logic of LocateServers begins here ... Debugging Aids Κν˜code™K™(J™—šΟk ˜ Kšœœ+œœ˜RKšœ œ ˜Kšœœ”˜§Kšœœ3˜@Kšœœ5˜>Kšœœ˜Kšœœ˜3Kšœœ(˜>Kšœ œ2˜AKšœœ˜*Kšœ œ”˜£Kšœœ ˜$K˜—šΟnœœ˜$Kšœ9˜@Kšœ˜Kšœ˜K˜Kšœœ œ˜Kšœœ œ˜head™ Kšœ œ˜(Kšœ œœœ2˜\Kšœœœœ=˜nKšœ œ˜Kšœ;˜;—™!™ Kšœ œœ˜(š œœœ œœ˜3Kšœ˜K˜K˜K˜%J˜$J™ K˜K˜—šœœ[˜wK˜——™Kšœœœ˜,š œœœ œœ˜5Kšœ˜K˜K˜K˜%Kšœ)˜)Jš œœœœœ˜/K˜K˜—Kšœœ]˜{Kšœœa˜wKšœœ%˜<——K˜™ Kš œœœœ œœ˜6Kš œœœœ œœ˜8K˜šžœœœœ˜FKšœ œ˜Kšœœ˜5KšœF˜FKšœ'˜'Kšœ œ˜K˜K˜—š ž œœœœœ ˜LKšœœœœ˜(Kšœ œ˜Kšœ˜Kšœœœœ˜AJšœœ ˜K˜K˜——Kšž œœœœ˜#K˜šž œœœœœ:œœœ œ˜ΗKšœ œ˜Kšœœœ˜K˜(Kšœœ˜Kšœœ˜Kšœœ˜K˜šžœœ˜K˜Jšœ œ˜:Kšœ œœ.œ˜JKšœ œœ.œ˜JK˜K˜—K˜šžœœ˜Kšœ œ˜Kšœ œ˜Kšœœ˜K˜šœœ˜Kšœ œ˜*Kšœ˜Kšœ%œ˜Aš˜Kšœœœ˜šœ˜šœ˜Kšœœœ˜Kšœ&˜&Kšœœ˜K˜$—šœ˜Kšœœ˜——K˜Kšœ˜—K˜—Kšœœ˜K˜K˜K˜—šž œœ˜Kšœ œœœ˜,Kšœ œœœ˜-Kšœœ˜Kšœœ˜ šžœœœ+˜BKšœ˜Kšœ%œ˜AKšœ(˜(—šœœœ˜%Kšœœ˜0Kšœ˜Kšœ˜—Kšœœ˜ šœœ˜Kšœœœ˜Kšœœ˜ šœœœ˜%šœ ˜"šœ˜Kšœœ˜Kšœœ˜—šœ˜šœœ˜'K˜7Kšœœ˜ K˜)Kšœœ˜—K˜——Kšœ˜—K˜Kšœ˜—Kšœœ˜K˜K˜—K˜šž œœ˜Kšœ˜Kšœœ)˜?K˜K˜Kšœ9Οc3˜lšœœ7˜AK˜/—Kšœ:˜:KšœŒ˜ŒKšœ5˜5K˜K˜—šž œœ˜Kšœœ˜Kšœ œœœ˜$Kšœ œ ˜Kšœ:œœ˜HKšœœœ˜-Kšœœ ˜#Kšœœœ˜&Kšœ9œœ˜GKšœOœœ˜]KšœPœœ˜^Kšœ=œœ˜Lšœœœ˜2Kšœœ˜(Kšœœ˜-Kšœœ)˜@Kšœ˜—Kšœ œœœ˜;K˜—K˜K™&K˜Kšœœ œœ˜/Kšœ œ˜"Kšœ˜K˜8K˜9K˜šœœ ˜Kšœœœ˜1Kšœœœ˜:—šœœ˜šœ˜Kšœ˜Kšœœ˜K˜—K˜šœ œœ˜Kšœ˜Kšœ+œ˜1—Kšœ˜—Kšœ ˜ K˜K˜—™Kš œ œœœ œ˜%šž œœœ ˜)Kšœ œ˜$——K˜—J˜—…—X'+