<<>> <> <> <> <> <> DIRECTORY Arpa USING [Address, MyAddress], Basics USING [HFromCard16], RefText USING [New], SunPMap USING [CallitProc, DumpProc, GetPortProc, ipProtocolUDP, MapEntry, NullProc, SetProc, UnsetProc], SunPMapLocal USING [], SunPMapServer USING [], SunRPC USING [BytesRemaining, Destroy, Error, GetBlock, Handle, PutBlock, SendCallAndReceiveReply, StartCall], SunRPCOnUDP USING [Create], SunRPCAuth USING [Conversation, Initiate, Terminate] ; SunPMapServerImpl: CEDAR MONITOR IMPORTS Arpa, Basics, RefText, SunRPC, SunRPCOnUDP, SunRPCAuth EXPORTS SunPMapLocal, SunPMapServer ~ { <> tableSize: CARDINAL ~ 31; longTimeout: CARD ¬ 5000; <> Address: TYPE ~ Arpa.Address; Handle: TYPE ~ SunRPC.Handle; Conversation: TYPE ~ SunRPCAuth.Conversation; MapEntry: TYPE ~ SunPMap.MapEntry; <> Item: TYPE ~ REF ItemObject; ItemObject: TYPE ~ RECORD [ next: Item, entry: MapEntry ]; Headers: TYPE ~ REF HeadersObject; HeadersObject: TYPE ~ ARRAY [0 .. tableSize) OF Item; headers: Headers ¬ NEW[HeadersObject]; Hash: PROC [program, version: CARD] RETURNS [CARD] ~ { RETURN [(3*program + version) MOD tableSize]; }; <> Null: PUBLIC SunPMap.NullProc -- [h: Handle, c: Conversation] -- ~ { NULL; }; Set: PUBLIC SunPMap.SetProc -- [h: Handle, c: Conversation, program, version, protocol, port: CARD32] RETURNS [success: BOOL] -- ~ { RETURN [SetLocal[program, version, protocol, port]]; }; SetLocal: PUBLIC ENTRY PROC [program, version, protocol, port: CARD32] RETURNS [success: BOOL] ~ { index: CARD ¬ Hash[program, version]; FOR item: Item ¬ headers[index], item.next WHILE item # NIL DO IF (item.entry.program = program) AND (item.entry.version = version) AND (item.entry.protocol = protocol) AND (item.entry.port = port) THEN RETURN [FALSE]; ENDLOOP; headers[index] ¬ NEW[ItemObject ¬ [headers[index], [program, version, protocol, port]]]; RETURN [TRUE]; }; Unset: PUBLIC SunPMap.UnsetProc -- [h: Handle, c: Conversation, program, version: CARD32] RETURNS [success: BOOL] -- ~ { RETURN [UnsetLocal[program, version]]; }; UnsetLocal: PUBLIC ENTRY PROC [program, version: CARD32] RETURNS [success: BOOL] ~ { prev, p: Item; index: CARD ¬ Hash[program, version]; success ¬ FALSE; prev ¬ NIL; p ¬ headers[index]; DO IF p = NIL THEN RETURN; IF (p.entry.program = program) AND (p.entry.version = version) THEN { success ¬ TRUE; IF prev = NIL THEN headers[index] ¬ p.next ELSE prev.next ¬ p.next; } ELSE { prev ¬ p; }; p ¬ p.next; ENDLOOP; }; GetPort: PUBLIC SunPMap.GetPortProc -- [h: Handle, c: Conversation, program, version, protocol: CARD32] RETURNS [port: CARD32] -- ~ { RETURN [GetPortLocal[program, version, protocol]]; }; GetPortLocal: PUBLIC ENTRY PROC [program, version, protocol: CARD32] RETURNS [port: CARD32] ~ { index: CARD ¬ Hash[program, version]; FOR item: Item ¬ headers[index], item.next WHILE item # NIL DO IF (item.entry.program = program) AND (item.entry.version = version) AND (item.entry.protocol = protocol) THEN RETURN [item.entry.port]; ENDLOOP; RETURN [0]; }; Dump: PUBLIC SunPMap.DumpProc -- [h: Handle, c: Conversation, eachMapEntry: PROC[MapEntry]] -- ~ { DumpLocal[eachMapEntry]; }; DumpLocal: PUBLIC PROC [eachMapEntry: PROC[MapEntry]] ~ { <> FOR i: CARDINAL IN [0 .. tableSize) DO FOR p: Item ¬ headers[i], p.next WHILE p # NIL DO eachMapEntry[p.entry]; ENDLOOP; ENDLOOP; }; Callit: PUBLIC SunPMap.CallitProc -- [h: Handle, c: Conversation, program, version, proc: CARD32, args: REF TEXT] RETURNS [port: CARD32, result: REF TEXT] -- ~ { gotError: BOOL ¬ FALSE; [port, result] ¬ CallitLocal[program, version, proc, args, longTimeout, 0 ! SunRPC.Error => { gotError ¬ TRUE; CONTINUE }]; IF gotError THEN ERROR SunRPC.Error[$abortWithoutReturn]; }; CallitLocal: PUBLIC PROC [program, version, proc: CARD32, args: REF TEXT, timeout: CARD, retries: CARD] RETURNS [port: CARD32, result: REF TEXT] ~ { hLocal: Handle ¬ NIL; conversation: Conversation ¬ NIL; CleanUp: PROC ~ { IF hLocal # NIL THEN { SunRPC.Destroy[hLocal]; hLocal ¬ NIL }; IF conversation # NIL THEN { SunRPCAuth.Terminate[conversation]; conversation ¬ NIL }; }; { ENABLE UNWIND => CleanUp[]; bytes: CARDINAL; port ¬ GetPortLocal[program, version, SunPMap.ipProtocolUDP]; IF port = 0 THEN ERROR SunRPC.Error[$serviceNotRegistered]; hLocal ¬ SunRPCOnUDP.Create[remoteAddress~Arpa.MyAddress[], remotePort~Basics.HFromCard16[port]]; conversation ¬ SunRPCAuth.Initiate[]; SunRPC.StartCall[hLocal, conversation, program, version, proc]; SunRPC.PutBlock[hLocal, args, 0, args.length]; [] ¬ SunRPC.SendCallAndReceiveReply[hLocal, timeout, retries]; bytes ¬ SunRPC.BytesRemaining[hLocal]; result ¬ RefText.New[bytes]; SunRPC.GetBlock[hLocal, result, 0, bytes]; }; CleanUp[]; }; }...