CourierBindingClientImpl.mesa
Copyright (C) 1985, 1986 by Xerox Corporation. All rights reserved.
kam 17-Jan-86 10:45:56
Bill Jackson (bj) June 23, 1986 1:13:50 pm PDT
DIRECTORY
CrRPC USING [Call, CreateClientHandle, DestroyClientHandle, GetCARDINAL, GetFWORD, GetHWORD, GetResultsProc, Handle, PutArgsProc, PutCARD, PutCARDINAL, SetHops, SetTimeout],
Endian USING [FWORD, HWORD],
XNS USING [broadcastHost, broadcastNet, unknownAddress],
CourierBindingProtocol,
CourierBinding;
CourierBindingClientImpl:
CEDAR
PROGRAM
IMPORTS CrRPC
EXPORTS CourierBinding ~ {
OPEN CourierBindingProtocol;
Types
CARD: TYPE ~ LONG CARDINAL;
FWORD: TYPE ~ Endian.FWORD;
HWORD: TYPE ~ Endian.HWORD;
AddressList: TYPE ~ LIST OF Address;
Handle: TYPE ~ CrRPC.Handle;
Magic Stuff
BASICTIMEOUT: CARDINAL ← 200;
ROUTERDELAY: CARDINAL ← 300;
RETRIES: CARDINAL ← 4;
TimeoutHeuristic:
PROC [hops:
CARDINAL]
RETURNS [
CARDINAL] ~
INLINE {
RETURN [BASICTIMEOUT + (ROUTERDELAY * hops)];
};
Procs
AddToAddressList:
PROC [new: Address, list: AddressList]
RETURNS [AddressList] ~ {
FOR temp: AddressList ← list, temp.rest
WHILE
(temp #
NIL)
DO
IF (temp.first = new) THEN RETURN [list];
ENDLOOP;
RETURN [ CONS[new, list] ];
};
Bind:
PUBLIC
PROC [predicate:
CARD, versions: Range, maxHops:
CARDINAL, stubPutPred: CrRPC.PutArgsProc]
RETURNS [answer: Address ←
XNS.unknownAddress] ~ {
answerList: AddressList ← AddToAddressList[answer, NIL];
h: Handle ← CrRPC.CreateClientHandle[
class~$EXCHANGE,
remote~[net~XNS.broadcastNet, host~XNS.broadcastHost, socket~socket],
timeoutMsec~BASICTIMEOUT];
h ← CrRPC.CreateClientHandle[
class~$EXCHANGE,
remote~XNSName.AddressFromRope["1234B.25205403463B.1750B"],
timeoutMsec~BASICTIMEOUT];
{
FOR hops:
CARDINAL
IN [0..maxHops]
DO
IF TRUE THEN h ← CrRPC.SetHops[h~h, low~hops, high~hops];
h ← CrRPC.SetTimeout[h, TimeoutHeuristic[hops]];
THROUGH [0..
RETRIES)
DO
answerList ← RingPredicate[h, answerList, predicate, versions, stubPutPred];
IF (answerList.first # XNS.unknownAddress) THEN GOTO Found;
ENDLOOP;
ENDLOOP;
EXITS
Found => { answer ← answerList.first; }; -- maybe first isn't best?
};
CrRPC.DestroyClientHandle[h];
};
GetRange:
PROC [h: Handle]
RETURNS [r: Range] ~ {
r.lowVersion ← CrRPC.GetCARDINAL[h];
r.highVersion ← CrRPC.GetCARDINAL[h];
};
PutRange:
PROC [h: Handle, r: Range] ~ {
CrRPC.PutCARDINAL[h, r.lowVersion];
CrRPC.PutCARDINAL[h, r.highVersion];
};
GetXNSAddress:
PROC [h: Handle]
RETURNS [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]] ] };
};
RingPredicate:
PROC [h: Handle, oldList: AddressList, predicate:
CARD, versions: Range, stubPutPred: CrRPC.PutArgsProc]
RETURNS [newList: AddressList] ~ {
PutArgs: CrRPC.PutArgsProc ~ {
CrRPC.PutCARD[h, predicate];
PutRange[h, versions];
IF (stubPutPred # NIL) THEN stubPutPred[h];
};
GetResults: CrRPC.GetResultsProc ~ {
r: Range ← GetRange[h];
newList ← AddToAddressList[GetXNSAddress[h], newList];
};
newList ← oldList;
CrRPC.Call[h~h, remotePgm~
program, remotePgmVersion~
version, remoteProc~
bind, putArgs~PutArgs, getResults~GetResults
];
};