<> <> <> <> <> 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.