DIRECTORY CommDriver USING [GetNetworkChain, Network], Convert USING [RopeFromCard], Pup USING [allHosts, allNets, Address, nullAddress, nullHost, nullNet, nullSocket, Socket], PupBuffer USING [Buffer, maxAddresses], PupHop USING [GetHop, Hop, unreachable], PupName USING [Code], PupSocket USING [AllocBuffer, Broadcast, CopyRope, CreateEphemeral, Destroy, ExtractRope, FreeBuffer, Get, GetUserSize, Socket, SetNoErrors, SetUserSize], PupType USING [CardFromSocket, SocketFromCard], PupWKS USING [misc], Rope USING [Cat, Equal, Fetch, Length, ROPE]; PupNameImpl: CEDAR PROGRAM IMPORTS CommDriver, Convert, PupHop, PupSocket, PupType, Rope EXPORTS PupName = { ROPE: TYPE = Rope.ROPE; Error: PUBLIC ERROR [code: PupName.Code, text: ROPE] = CODE; MyName: PUBLIC PROC RETURNS [rope: ROPE] = { network: CommDriver.Network _ CommDriver.GetNetworkChain[]; me: Pup.Address _ Pup.nullAddress; IF network # NIL THEN me _ NameLookup["ME", Pup.nullSocket]; rope _ HisName[me]; }; MyRope: PUBLIC PROC RETURNS [rope: ROPE] = { network: CommDriver.Network _ CommDriver.GetNetworkChain[]; me: Pup.Address _ Pup.nullAddress; IF network # NIL THEN me _ [network.pup.net, network.pup.host, Pup.nullSocket]; rope _ AddressToRope[me]; }; NameLookup: PUBLIC PROC [name: ROPE, default: Pup.Socket] RETURNS [Pup.Address] = { addresses: LIST OF Pup.Address _ HisAddresses[name, default]; hops: PupHop.Hop; IF addresses = NIL THEN ERROR; hops _ PupHop.GetHop[addresses.first.net]; IF hops = PupHop.unreachable THEN Error[noRoute, "No route to host"]; RETURN[addresses.first]; }; HisAddresses: PUBLIC PROC [name: ROPE, default: Pup.Socket] RETURNS [LIST OF Pup.Address] = { address: Pup.Address; parsed: BOOL; socket: PupSocket.Socket; [parsed, address] _ CheckForME[name, default]; IF parsed THEN RETURN[LIST[address]]; [parsed, address] _ ParseAddress[name, default]; IF parsed THEN RETURN[LIST[address]]; socket _ PupSocket.CreateEphemeral[ remote: [Pup.allNets, Pup.allHosts, PupWKS.misc], getTimeout: 3000 ]; PupSocket.SetNoErrors[socket]; FOR try: CARDINAL IN [0..10) DO b: PupBuffer.Buffer _ PupSocket.AllocBuffer[socket]; b.type _ nameLookup; b.id _ [try, try]; PupSocket.CopyRope[b, name]; PupSocket.Broadcast[socket, b]; DO b _ PupSocket.Get[socket]; IF b = NIL THEN EXIT; SELECT b.type FROM nameReply => { head: LIST OF Pup.Address _ NIL; maxAnswers: NAT = PupBuffer.maxAddresses; hops: ARRAY [0..maxAnswers) OF PupHop.Hop _ ALL[PupHop.unreachable]; howMany: CARDINAL; howMany _ MIN[ maxAnswers, PupSocket.GetUserSize[b]/SIZE[Pup.Address]]; FOR i: NAT IN [0..howMany) DO hops[i] _ PupHop.GetHop[b.addresses[i].net]; IF b.addresses[i].socket = Pup.nullSocket THEN b.addresses[i].socket _ default; ENDLOOP; FOR j: PupHop.Hop DECREASING IN PupHop.Hop DO FOR i: NAT DECREASING IN [0..howMany) DO IF hops[i] # j THEN LOOP; head _ CONS[b.addresses[i], head]; ENDLOOP; ENDLOOP; PupSocket.FreeBuffer[b]; PupSocket.Destroy[socket]; RETURN[head]; }; nameError => { err: ROPE _ PupSocket.ExtractRope[b]; ERROR Error[errorFromServer, err]; }; ENDCASE => PupSocket.FreeBuffer[b]; ENDLOOP; ENDLOOP; ERROR Error[noResponse, "No name lookup server responded"]; }; CheckForME: PROCEDURE [name: Rope.ROPE, default: Pup.Socket] RETURNS [ok: BOOLEAN, him: Pup.Address] = { network: CommDriver.Network; IF ~Rope.Equal["ME", name, FALSE] THEN RETURN[FALSE, ]; ok _ TRUE; network _ CommDriver.GetNetworkChain[]; IF network = NIL THEN RETURN[ok, [Pup.nullNet, Pup.nullHost, default]]; him _ [network.pup.net, network.pup.host, default]; }; ParseAddress: PROCEDURE [name: Rope.ROPE, default: Pup.Socket] RETURNS [ok: BOOLEAN, him: Pup.Address] = { length: INT = Rope.Length[name]; net, host: CARDINAL _ 0; socket: LONG CARDINAL _ 0; him.socket _ default; ok _ FALSE; IF length = 0 THEN RETURN; FOR i: CARDINAL _ 0, i + 1 UNTIL i = length DO c: CHARACTER _ Rope.Fetch[name, i]; SELECT c FROM '# => { IF net # 0 OR socket > 0FFH THEN RETURN; net _ host; host _ socket; socket _ 0; }; IN ['0..'9] => { IF socket > LAST[LONG CARDINAL]/8 THEN RETURN; socket _ socket*8 + CARDINAL[c - '0]; }; ENDCASE => RETURN; ENDLOOP; IF net > 0FFH THEN RETURN; IF host > 0FFH THEN RETURN; him.net _ [net]; him.host _ [host]; IF socket # 0 THEN him.socket _ PupType.SocketFromCard[socket]; ok _ TRUE; }; AddressToRope: PUBLIC PROC [him: Pup.Address] RETURNS [rope: ROPE] = { net: ROPE = Convert.RopeFromCard[him.net, 8, FALSE]; host: ROPE = Convert.RopeFromCard[him.host, 8, FALSE]; rope _ Rope.Cat[net, "#", host, "#"]; IF him.socket # Pup.nullSocket THEN rope _ Rope.Cat[rope, Convert.RopeFromCard[PupType.CardFromSocket[him.socket], 8, FALSE] ]; }; HisName: PUBLIC PROC [him: Pup.Address] RETURNS [rope: ROPE] = { him.socket _ Pup.nullSocket; rope _ AddressLookup[him ! Error => { rope _ AddressToRope[him]; CONTINUE; }]; }; AddressLookup: PUBLIC PROC [him: Pup.Address] RETURNS [rope: ROPE] = { socket: PupSocket.Socket _ PupSocket.CreateEphemeral[ remote: [Pup.allNets, Pup.allHosts, PupWKS.misc], getTimeout: 3000 ]; PupSocket.SetNoErrors[socket]; FOR try: CARDINAL IN [0..10) DO b: PupBuffer.Buffer _ PupSocket.AllocBuffer[socket]; b.type _ addressLookup; b.id _ [try, try]; b.address _ him; PupSocket.SetUserSize[b, SIZE[Pup.Address]]; PupSocket.Broadcast[socket, b]; DO b _ PupSocket.Get[socket]; IF b = NIL THEN EXIT; SELECT b.type FROM addressReply => { rope _ PupSocket.ExtractRope[b]; PupSocket.FreeBuffer[b]; PupSocket.Destroy[socket]; RETURN; }; nameError => { err: ROPE _ PupSocket.ExtractRope[b]; ERROR Error[errorFromServer, err]; }; ENDCASE => PupSocket.FreeBuffer[b]; ENDLOOP; ENDLOOP; ERROR Error[noResponse, "No name lookup server responded"]; }; }. :PupNameImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Hal Murray, June 2, 1986 5:37:05 pm PDT This module deliberately drops buffers and sockets on the floor on error paths to make sure they really work and/or provide a handy test case. Errors Local name Name/Address translation Κœ˜codešœ™Kšœ Οmœ1™<™'K™K™Ž——K™šΟk ˜ Kšœ žœ˜,Kšœžœ˜KšœžœR˜[Kšœ žœ˜'Kšœžœ˜(Kšœžœ˜Kšœ žœ‹˜šKšœžœ"˜/Kšœžœ˜Kšœžœžœ˜-K˜—šœ žœž˜Kšžœ6˜=Kšžœ ˜K˜Kšžœžœžœ˜—headšΟn™Kš œžœžœžœžœ˜<—šŸ ™ š Ÿœžœžœžœžœ˜,Kšœ;˜;Kšœ"˜"Kšžœ žœžœ'˜Kšžœžœ˜+Kšœžœ˜ Kšœ žœ˜Kšœž œ˜Kšœ˜Kšœžœ˜ Kšžœ žœžœ˜šžœžœ žœ ž˜.Kšœž œ˜#šžœž˜ šœž˜Kšžœ žœžœžœ˜(K˜ Kšœ˜Kšœ žœ˜—šžœ ž˜Kš žœ žœžœžœžœžœ˜.Kšœžœ žœ˜(—Kšžœžœ˜—Kšžœ˜—Kšžœžœžœžœ˜Kšžœžœžœžœ˜K˜K˜Kšžœ žœ-˜?Kšœžœ˜ Kšžœ˜K˜K™—š Ÿ œžœžœžœžœ˜FKšœžœ$žœ˜4Kšœžœ%žœ˜6Kšœ%˜%šžœž˜#KšœRžœ˜[—Kšžœ˜K˜—š Ÿœžœžœžœžœ˜@K˜KšœAžœ˜NK˜K˜—š Ÿ œžœžœžœžœ˜Fšœ5˜5K˜1K˜—Kšœ˜šžœžœžœ ž˜Kšœ4˜4K˜K˜K˜Kšœžœ˜,K˜šž˜Kšœ˜Kšžœžœžœžœ˜šžœž˜˜Kšœ ˜ Kšœ˜Kšœ˜Kšžœ˜ —šœ˜Kšœžœ˜%Kšžœ ˜%—Kšžœ˜#—Kšžœ˜—Kšžœ˜—Kšžœ6˜;Kšœ˜K˜——šœ˜K˜——…—φΜ