<> <> <> DIRECTORY Basics USING [BytePair, HighByte, LongNumber, LowByte], Rope USING [Concat, Fetch, Find, FromChar, Length, ROPE, Substr], IPDefs USING [Byte, DByte, Address], IPNameUdp USING [Class, DomainHeader, Type], UDP USING [BodyRec, minLength, maxLength]; IPNameUdpImpl: CEDAR PROGRAM IMPORTS Basics, Rope EXPORTS IPNameUdp = BEGIN ROPE: TYPE = Rope.ROPE; Class: TYPE = IPNameUdp.Class; DomainHeader: TYPE = IPNameUdp.DomainHeader; Type: TYPE = IPNameUdp.Type; EndOfData: PUBLIC SIGNAL = CODE; <> AppendQuery: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec, domain: LONG POINTER TO DomainHeader, query: ROPE, type: Type, class: Class] = TRUSTED { AppendName[udp, query]; AppendTwoBytes[udp, type]; AppendTwoBytes[udp, class]; domain.qdCount _ domain.qdCount + 1; }; AppendInverse: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec, domain: LONG POINTER TO DomainHeader, address: IPDefs.Address, type: Type, class: Class] = TRUSTED { AppendName[udp, "Foo"]; AppendTwoBytes[udp, type]; AppendTwoBytes[udp, class]; AppendTwoBytes[udp, 0]; -- Mumble AppendTwoBytes[udp, 0]; -- TTL AppendTwoBytes[udp, 4]; -- rDataLength AppendIPAddress[udp, address]; domain.anCount _ domain.anCount + 1; }; AppendName: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec, name: ROPE] = TRUSTED { DO dot: INT _ Rope.Find[name, "."]; IF dot = -1 THEN EXIT; IF dot = 0 THEN EXIT; -- Bounds fault AppendFragment[udp, Rope.Substr[name, 0, dot]]; name _ Rope.Substr[name, dot+1] ENDLOOP; IF Rope.Length[name] # 0 THEN AppendFragment[udp, name]; AppendFragment[udp, NIL]; }; AppendFragment: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec, rope: ROPE] = TRUSTED { length: INT _ udp.length; chars: INT _ Rope.Length[rope]; udp.data[length] _ chars; FOR i: INT IN [0..chars) DO udp.data[length+i+1] _ LOOPHOLE[Rope.Fetch[rope, i]]; ENDLOOP; udp.length _ udp.length + chars + 1; }; AppendTwoBytes: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec, data: UNSPECIFIED] = TRUSTED { length: INT _ udp.length; udp.data[length] _ Basics.HighByte[data]; udp.data[length+1] _ Basics.LowByte[data]; udp.length _ udp.length + 2; }; AppendIPAddress: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec, address: IPDefs.Address] = TRUSTED { length: INT _ udp.length; udp.data[length+0] _ address[0]; udp.data[length+1] _ address[1]; udp.data[length+2] _ address[2]; udp.data[length+3] _ address[3]; udp.length _ udp.length + 4; }; SkipQuery: PUBLIC PROC [udp: LONG POINTER TO UDP.BodyRec] = TRUSTED { [] _ GetName[udp]; -- Name [] _ GetTwoBytes[udp]; -- Type [] _ GetTwoBytes[udp]; }; -- Class SkipRR: PUBLIC PROC [udp: LONG POINTER TO UDP.BodyRec] = TRUSTED { name: ROPE _ GetName[udp]; type: Type _ GetTwoBytes[udp]; class: Class _ GetTwoBytes[udp]; ttl: INT _ GetTtl[udp]; rDataLength: CARDINAL _ GetTwoBytes[udp]; udp.length _ udp.length + rDataLength; }; -- rDataLength, and rData GetName: PUBLIC PROC [udp: LONG POINTER TO UDP.BodyRec] RETURNS [rope: ROPE] = TRUSTED { length: INT _ udp.length; indirect: INT _ 300B; rope _ NIL; DO bytes: INT; IF length >= UDP.maxLength THEN SIGNAL EndOfData; bytes _ udp.data[length]; length _ length + 1; IF bytes = 0 THEN EXIT; IF bytes >= indirect THEN { -- Indirect link, keep length we have temp: INT; IF length >= UDP.maxLength THEN SIGNAL EndOfData; temp _ (bytes-indirect)*256 + udp.data[length]; temp _ temp + UDP.minLength; length _ length + 1; udp.length _ temp; rope _ Rope.Concat[rope, GetName[udp]]; EXIT; }; FOR i: INT IN [0..bytes) DO IF length >= UDP.maxLength THEN SIGNAL EndOfData; rope _ Rope.Concat[rope, Rope.FromChar[LOOPHOLE[udp.data[length]]]]; length _ length + 1; ENDLOOP; IF length >= UDP.maxLength THEN SIGNAL EndOfData; IF udp.data[length] # 0 THEN rope _ Rope.Concat[rope, "."]; ENDLOOP; udp.length _ length; }; longTime: LONG CARDINAL = 10*365*86400; GetTtl: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec] RETURNS [INT] = { card: LONG CARDINAL _ GetCard[udp]; IF card > longTime THEN card _ longTime; RETURN[card]; }; GetCard: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec] RETURNS [LONG CARDINAL] = { ln: Basics.LongNumber; ln.hi _ GetCardinal[udp]; ln.lo _ GetCardinal[udp]; RETURN[ln.lc]; }; GetCardinal: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec] RETURNS [CARDINAL] = { RETURN[GetTwoBytes[udp]]; }; GetTwoBytes: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec] RETURNS [UNSPECIFIED] = TRUSTED { length: INT _ udp.length; temp: Basics.BytePair; IF length +1 >= UDP.maxLength THEN SIGNAL EndOfData; temp.high _ udp.data[length]; temp.low _ udp.data[length+1]; udp.length _ udp.length + 2; RETURN[temp]; }; GetIPAddress: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec] RETURNS [a: IPDefs.Address] = TRUSTED { length: INT _ udp.length; IF length +3 >= UDP.maxLength THEN SIGNAL EndOfData; a[0] _ udp.data[length+0]; a[1] _ udp.data[length+1]; a[2] _ udp.data[length+2]; a[3] _ udp.data[length+3]; udp.length _ udp.length + 4; }; GetOneByte: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec] RETURNS [UNSPECIFIED] = TRUSTED { length: INT _ udp.length; temp: Basics.BytePair; IF length >= UDP.maxLength THEN SIGNAL EndOfData; temp.high _ 0; temp.low _ udp.data[length]; udp.length _ udp.length + 1; RETURN[temp]; }; GetChar: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec] RETURNS [c: CHAR] = TRUSTED { length: INT _ udp.length; IF length >= UDP.maxLength THEN SIGNAL EndOfData; c _ LOOPHOLE[udp.data[length]]; udp.length _ udp.length + 1; RETURN[c]; }; GetRope: PUBLIC PROC [ udp: LONG POINTER TO UDP.BodyRec] RETURNS [rope: Rope.ROPE] = TRUSTED { chars: CARDINAL _ GetOneByte[udp]; FOR i: INT IN [0..chars) DO rope _ Rope.Concat[rope, Rope.FromChar[GetChar[udp]]]; ENDLOOP; RETURN[rope]; }; END.