RPCTest.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Andrew Birrell September 7, 1983 6:34 pm
Bob Hagmann February 11, 1985 10:15:04 am PST
Hal Murray, January 20, 1986 7:10:07 pm PST
DIRECTORY
BasicTime, Process, Rope, RPC, RPCLupine, UserCredentials;
RPCTest:
MONITOR
IMPORTS BasicTime, Process, RPC, RPCLupine, UserCredentials =
BEGIN
-- ******** Parameters ******** --
Finished: SIGNAL = CODE;
signalFinished: BOOLEAN ← TRUE;
extraArgPkts: CARDINAL ← 0;
extraArgLength: RPCLupine.DataLength ← RPCLupine.maxDataLength-1;
argLength: RPCLupine.DataLength ← 1;
extraResPkts: CARDINAL ← 0;
extraResLength: RPCLupine.DataLength ← RPCLupine.maxDataLength;
resLength: RPCLupine.DataLength ← 2;
callDelaySecs: CARDINAL ← 0;
senderGapSecs: CARDINAL ← 0;
receiverGapSecs: CARDINAL ← 0;
callGapSecs: CARDINAL ← 0;
tries: CARDINAL ← 1000;
quit: BOOLEAN ← FALSE;
raiseSignal: BOOLEAN ← FALSE;
resumeSignal: BOOLEAN ← TRUE;
authenticate: BOOLEAN ← TRUE;
gvExport: BOOLEAN ← TRUE;
gvInstance: Rope.ROPE ← UserCredentials.Get[].name;
nongvInstance: Rope.ROPE ← "Tokay";
callerName: RPC.Principal ← gvInstance;
callerKey: RPC.EncryptionKey ← RPC.MakeKey[UserCredentials.Get[].password];
exporterName: RPC.Principal ← callerName;
exporterKey: RPC.EncryptionKey ← callerKey;
userTest: BOOLEAN ← TRUE;
minWanted: BOOLEAN ← TRUE;
caller: PROCESS;
pktSpace: ARRAY[1..RPCLupine.pktOverhead+RPCLupine.maxDataLength] OF WORD;
pkt: RPCLupine.StubPkt = RPCLupine.GetStubPkt[@pktSpace];
import: RPCLupine.ImportHandle ← NIL;
conversation: RPC.Conversation;
-- ******** Hand-crafted stubs ******** --
RemoteSignal: SIGNAL = CODE;
SignalDispatcher: RPCLupine.Dispatcher =
BEGIN
UNTIL lastPkt
DO [callLength,lastPkt] ← RPCLupine.ReceiveExtraPkt[pkt] ENDLOOP;
SIGNAL RemoteSignal[];
RETURN[0]
END;
Send:
PROC =
BEGIN
[] ← RPCLupine.StartCall[pkt, import, conversation];
FOR p: CARDINAL IN [1..extraArgPkts]
DO RPCLupine.SendPrelimPkt[pkt, extraArgLength];
IF senderGapSecs > 0
THEN Process.Pause[Process.SecondsToTicks[senderGapSecs]];
ENDLOOP;
BEGIN
length: RPCLupine.DataLength;
last: BOOLEAN;
[length, last] ← RPCLupine.Call[pkt, argLength, RPCLupine.maxDataLength, SignalDispatcher];
UNTIL last
DO
IF receiverGapSecs > 0
THEN Process.Pause[Process.SecondsToTicks[receiverGapSecs]];
[length, last] ← RPCLupine.ReceiveExtraPkt[pkt];
ENDLOOP;
END;
END;
TestDispatcher: RPCLupine.Dispatcher =
BEGIN
-- Dummy dispatcher: consumes args and sends dummy result --
UNTIL lastPkt
DO
IF receiverGapSecs > 0
THEN Process.Pause[Process.SecondsToTicks[receiverGapSecs]];
[callLength,lastPkt] ← RPCLupine.ReceiveExtraPkt[pkt];
ENDLOOP;
Client[ ! RemoteSignal =>
BEGIN
RPCLupine.StartSignal[pkt];
[callLength,lastPkt] ← RPCLupine.Call[pkt, 0, RPCLupine.maxDataLength, NIL];
UNTIL lastPkt
DO [callLength,lastPkt] ← RPCLupine.ReceiveExtraPkt[pkt] ENDLOOP;
RESUME
END ];
IF callDelaySecs > 0
THEN Process.Pause[Process.SecondsToTicks[callDelaySecs]];
FOR res: CARDINAL IN [1..extraResPkts]
DO RPCLupine.SendPrelimPkt[pkt,extraResLength];
IF senderGapSecs > 0
THEN Process.Pause[Process.SecondsToTicks[senderGapSecs]];
ENDLOOP;
RETURN[resLength];
END;
-- ******** Test version of client code ******** --
Client: PROC = { IF raiseSignal THEN SIGNAL RemoteSignal[] };
-- remote procedure being called! --
instance: Rope.ROPE ← IF gvExport THEN gvInstance ELSE nongvInstance;
exported: BOOLEAN ← FALSE;
expHandle: RPCLupine.ExportHandle;
Work:
PROC =
BEGIN
import ← RPCLupine.ImportInterface[["RPC-Test", instance], [0,0] !
RPC.ImportFailed =>
IF why = unbound OR why = communications
THEN
BEGIN
expHandle ← RPCLupine.ExportInterface[exporterName, exporterKey,
["RPC-Test", instance], TestDispatcher, [0,0]];
exported ← TRUE;
import ← RPCLupine.ImportInterface[["RPC-Test", instance],[0,0]];
CONTINUE
END ];
BEGIN
DO
UNTIL userTest
OR quit
DO Process.Pause[Process.SecondsToTicks[5]]
ENDLOOP;
IF quit THEN EXIT;
conversation ←
IF authenticate
THEN RPC.StartConversation[callerName, callerKey, exporterName, CBCCheck]
ELSE RPC.unencrypted;
Send[! RemoteSignal => IF resumeSignal THEN RESUME ELSE CONTINUE];
Send[! RemoteSignal => IF resumeSignal THEN RESUME ELSE CONTINUE];
BEGIN
start: BasicTime.Pulses = BasicTime.GetClockPulses[];
end: BasicTime.Pulses;
minPulses: LONG CARDINAL ← LAST[LONG CARDINAL];
elapsed: REAL;
minTime: LONG CARDINAL;
FOR call: CARDINAL IN [1..tries]
DO thisStart: BasicTime.Pulses;
thisPulses: LONG CARDINAL;
IF minWanted THEN thisStart ← BasicTime.GetClockPulses[];
Send[! RemoteSignal => IF resumeSignal THEN RESUME ELSE CONTINUE];
IF minWanted
THEN
BEGIN
IF thisPulses < minPulses THEN minPulses ← thisPulses;
thisPulses ← BasicTime.GetClockPulses[] - thisStart;
END;
IF callGapSecs > 0
THEN Process.Pause[Process.SecondsToTicks[callGapSecs]];
ENDLOOP;
end ← BasicTime.GetClockPulses[];
elapsed ← BasicTime.PulsesToSeconds[end-start];
minTime ← BasicTime.PulsesToMicroseconds[minPulses];
IF authenticate THEN RPC.EndConversation[conversation];
IF signalFinished THEN SIGNAL Finished[];
END;
ENDLOOP;
END;
IF exported THEN [] ← RPCLupine.UnexportInterface[expHandle];
END;
caller ← FORK Work[];
END.