DIRECTORY Basics USING [ShortNumber], CHEntriesP0V0 USING [addressList], CHOpsP2V3 USING [AddGroupProperty, AddItemProperty, AddMember, AddSelf, Authenticator, ChangeItem, CreateAlias, CreateObject, DeleteAlias, DeleteMember, DeleteSelf, DeleteObject, DeleteProperty, IsMember, ItemObject, ListAliases, ListAliasesOf, ListDomains, ListDomainsServed, ListObjects, ListOrganizations, ListProperties, LookupObject, NetworkAddressList, RetrieveAddresses, RetrieveItem, RetrieveMembers], CrRPC USING [BulkDataCheckAbortProc, BulkDataXferProc, Error, Handle, MarshalledROPEHWords], Endian USING [CardFromH, HWORD, HFromCard], IO USING [EndOfStream, Error, GetChar, PutChar, STREAM], RefText USING [AppendChar, ObtainScratch, ReleaseScratch], Rope USING [Cat, FromRefText, Index, InlineFetch, IsEmpty, Length, ROPE, Substr], XNS USING [Address, Host, unknownAddress], XNSAuth USING [Identity], XNSCH USING [Conversation, Element, ElementStreamProc, EnumeratorProc, ErrorCode, InitiateConversation, Item, Name, NameStreamProc, notUsable, Pattern, Properties, PropertyID, TerminateConversation, unspecified, Which], XNSCHPrivate USING [BulkDataValueProc, CallRemote, GetAuthenticator, IsGeneric, RemoteProc], XNSRouter USING [GetHops], XNSStream USING [ConnectionClosed] ; XNSCHImpl: CEDAR PROGRAM IMPORTS CHOpsP2V3, CrRPC, Endian, IO, RefText, Rope, XNSCH, XNSCHPrivate, XNSRouter, XNSStream EXPORTS XNSCH, XNSCHPrivate ~ { OPEN CHEntries: CHEntriesP0V0, CHOps: CHOpsP2V3; CARD16: TYPE ~ CARDINAL; -- temporary until Mimosa ???? ROPE: TYPE ~ Rope.ROPE; Name: TYPE ~ XNSCH.Name; Pattern: TYPE ~ XNSCH.Pattern; Element: TYPE ~ XNSCH.Element; PropertyID: TYPE ~ XNSCH.PropertyID; Properties: TYPE ~ XNSCH.Properties; Item: TYPE ~ XNSCH.Item; Conversation: TYPE ~ XNSCH.Conversation; HWORD: TYPE ~ Endian.HWORD; RemoteProc: TYPE ~ XNSCHPrivate.RemoteProc; BulkDataValueProc: TYPE ~ XNSCHPrivate.BulkDataValueProc; shiftInName: ROPE ~ "CHServers"; chServiceName: Name ~ [organization~shiftInName, domain~shiftInName, object~"Clearinghouse Service"]; Error: PUBLIC ERROR [code: XNSCH.ErrorCode, which: XNSCH.Which] ~ CODE; Add: PUBLIC PROC [c: Conversation, name: Name] ~ { DoAdd: RemoteProc -- [handle, host] -- ~ { CHOps.CreateObject[handle, name, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoAdd, DomainFromElement[name]]; }; Delete: PUBLIC PROC [c: Conversation, name: Name] ~ { DoDelete: RemoteProc -- [handle, host] -- ~ { CHOps.DeleteObject[handle, name, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoDelete, DomainFromElement[name]]; }; Lookup: PUBLIC PROC [c: Conversation, pattern: Pattern] RETURNS [distingName: Name] ~ { DoLookup: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.LookupObject[handle, pattern, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoLookup, DomainFromElement[pattern]]; }; AddAlias: PUBLIC PROC [c: Conversation, name, alias: Name] RETURNS [distingName: Name] ~ { DoAddAlias: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.CreateAlias[handle, alias, name, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoAddAlias, DomainFromElement[alias--????--]]; }; DeleteAlias: PUBLIC PROC [c: Conversation, alias: Name] RETURNS [distingName: Name] ~ { DoDeleteAlias: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.DeleteAlias[handle, alias, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoDeleteAlias, DomainFromElement[alias]]; }; ListAliases: PUBLIC PROC [c: Conversation, pattern: Pattern, eachAlias: XNSCH.NameStreamProc] RETURNS [distingName: Name] ~ { ReadStreamOfNames: CrRPC.BulkDataXferProc ~ { EachNameInStream: BulkDataValueProc ~ { eachAlias[ReadElement[stream]] }; RETURN [ReadBulkDataStream[h, stream, checkAbort, EachNameInStream]]; }; DoListAliases: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.ListAliasesOf[handle, pattern, ReadStreamOfNames, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoListAliases, DomainFromElement[pattern], FALSE]; }; GetProperties: PUBLIC PROC [c: Conversation, pattern: Pattern] RETURNS [distingName: Name, properties: Properties] ~ { DoGetProperties: RemoteProc -- [handle, host] -- ~ { [distinguishedObject~distingName, properties~properties] _ CHOps.ListProperties[handle, pattern, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoGetProperties, DomainFromElement[pattern]]; }; DeleteProperty: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID] RETURNS [distingName: Name] ~ { DoDeleteProperty: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.DeleteProperty[handle, name, pID, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoDeleteProperty, DomainFromElement[name]]; }; AddItemProperty: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, item: Item] RETURNS [distingName: Name] ~ { DoAddItemProperty: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.AddItemProperty[handle, name, pID, item, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoAddItemProperty, DomainFromElement[name]]; }; ChangeItemProperty: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, item: Item] RETURNS [distingName: Name] ~ { DoChangeItemProperty: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.ChangeItem[handle, name, pID, item, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoChangeItemProperty, DomainFromElement[name]]; }; LookupItemProperty: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID] RETURNS [distingName: Name, item: Item] ~ { DoLookupItemProperty: RemoteProc -- [handle, host] -- ~ { [distinguishedObject~distingName, value~item] _ CHOps.RetrieveItem[handle, pattern, pID, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoLookupItemProperty, DomainFromElement[pattern]]; }; LookupAddress: PUBLIC PROC [c: Conversation, pattern: Pattern] RETURNS [distingName: Name, address: XNS.Address] ~ { DoLookupAddress: RemoteProc -- [handle, host] -- ~ { item: Item; addresses: LIST OF XNS.Address; [distinguishedObject~distingName, value~item] _ CHOps.RetrieveItem[handle, pattern, CHEntries.addressList, XNSCHPrivate.GetAuthenticator[c, host]]; addresses _ AddressesFromItem[item]; IF addresses # NIL THEN address _ BestAddressInList[addresses] ELSE address _ XNS.unknownAddress; }; XNSCHPrivate.CallRemote[c, DoLookupAddress, DomainFromElement[pattern]]; }; LookupRopeProperty: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID] RETURNS [distingName: Name, ropeProperty: ROPE] ~ { DoLookupRopeProperty: RemoteProc -- [handle, host] -- ~ { item: Item; [distinguishedObject~distingName, value~item] _ CHOps.RetrieveItem[handle, pattern, pID, XNSCHPrivate.GetAuthenticator[c, host]]; ropeProperty _ RopeFromItem[item]; }; XNSCHPrivate.CallRemote[c, DoLookupRopeProperty, DomainFromElement[pattern]]; }; LookupNameProperty: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID] RETURNS [distingName: Name, nameProperty: Name] ~ { DoLookupNameProperty: RemoteProc -- [handle, host] -- ~ { item: Item; [distinguishedObject~distingName, value~item] _ CHOps.RetrieveItem[handle, pattern, pID, XNSCHPrivate.GetAuthenticator[c, host]]; nameProperty _ ElementFromItem[item]; }; XNSCHPrivate.CallRemote[c, DoLookupNameProperty, DomainFromElement[pattern]]; }; HeAborted: ERROR ~ CODE; AddGroupProperty: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, enumerator: XNSCH.EnumeratorProc] RETURNS [distingName: Name] ~ { WriteStreamOfElements: CrRPC.BulkDataXferProc ~ { heAborted: BOOL _ FALSE; EachElement: PROC [element: Element] ~ { WriteTheElement: BulkDataValueProc ~ { WriteElement[stream, element]; RETURN [FALSE] }; [heAborted~heAborted] _ WriteSegment[h, stream, checkAbort, WriteTheElement, 1]; IF heAborted THEN ERROR HeAborted[]; }; enumerator[EachElement ! HeAborted => CONTINUE ]; IF NOT heAborted THEN [] _ WriteSegment[h, stream, NIL, NIL, 0]; RETURN [FALSE] }; DoAddGroupProperty: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.AddGroupProperty[handle, name, pID, WriteStreamOfElements, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoAddGroupProperty, DomainFromElement[name]]; }; AddMember: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, member: Element] RETURNS [distingName: Name] ~ { DoAddMember: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.AddMember[handle, name, pID, member, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoAddMember, DomainFromElement[name]]; }; AddSelf: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID] RETURNS [distingName: Name] ~ { DoAddSelf: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.AddSelf[handle, name, pID, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoAddSelf, DomainFromElement[name]]; }; DeleteMember: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, member: Element] RETURNS [distingName: Name] ~ { DoDeleteMember: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.DeleteMember[handle, name, pID, member, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoDeleteMember, DomainFromElement[name]]; }; DeleteSelf: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID] RETURNS [distingName: Name] ~ { DoDeleteSelf: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.DeleteSelf[handle, name, pID, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoDeleteSelf, DomainFromElement[name]]; }; ListMembers: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, eachMember: XNSCH.ElementStreamProc] RETURNS [distingName: Name] ~ { ReadStreamOfElements: CrRPC.BulkDataXferProc ~ { EachElementInStream: BulkDataValueProc ~ { eachMember[ReadElement[stream]] }; RETURN [ReadBulkDataStream[h, stream, checkAbort, EachElementInStream]]; }; DoListMembers: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.RetrieveMembers[handle, pattern, pID, ReadStreamOfElements, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoListMembers, DomainFromElement[pattern], FALSE]; }; IsMember: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, member: Element] RETURNS [distingName: Name, isMember: BOOL] ~ { DoIsMember: RemoteProc -- [handle, host] -- ~ { [isMember~isMember, distinguishedObject~distingName] _ CHOps.IsMember[handle, pattern, pID, XNSCH.notUsable, member, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoIsMember, DomainFromElement[pattern]]; }; IsMemberClosure: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, member: Element, pID2: PropertyID] RETURNS [distingName: Name, isMember: BOOL] ~ { DoIsMemberClosure: RemoteProc -- [handle, host] -- ~ { [isMember~isMember, distinguishedObject~distingName] _ CHOps.IsMember[handle, pattern, pID, pID2, member, XNSCHPrivate.GetAuthenticator[c, host]]; }; IF pID2 = XNSCH.unspecified THEN pID2 _ pID; XNSCHPrivate.CallRemote[c, DoIsMemberClosure, DomainFromElement[pattern]]; }; Enumerate: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, eachObject: XNSCH.NameStreamProc] ~ { ReadStreamOfNames: CrRPC.BulkDataXferProc ~ { EachNameInStream: BulkDataValueProc ~ { eachObject[ReadElement[stream]] }; RETURN [ReadBulkDataStream[h, stream, checkAbort, EachNameInStream]]; }; DoEnumerate: RemoteProc -- [handle, host] -- ~ { CHOps.ListObjects[handle, pattern, pID, ReadStreamOfNames, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoEnumerate, DomainFromElement[pattern], FALSE]; }; EnumerateAliases: PUBLIC PROC [c: Conversation, pattern: Pattern, eachName: XNSCH.NameStreamProc] ~ { ReadStreamOfNames: CrRPC.BulkDataXferProc ~ { EachNameInStream: BulkDataValueProc ~ { eachName[ReadElement[stream]] }; RETURN [ReadBulkDataStream[h, stream, checkAbort, EachNameInStream]]; }; DoEnumerateAliases: RemoteProc -- [handle, host] -- ~ { CHOps.ListAliases[handle, pattern, ReadStreamOfNames, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoEnumerateAliases, DomainFromElement[pattern], FALSE]; }; EnumerateOrganizations: PUBLIC PROC [c: Conversation, pattern: Pattern, eachOrganization: XNSCH.ElementStreamProc] ~ { ReadStreamOfOrganizations: CrRPC.BulkDataXferProc ~ { EachOrganizationInStream: BulkDataValueProc ~ { eachOrganization[ReadOrganization[stream]] }; RETURN [ReadBulkDataStream[h, stream, checkAbort, EachOrganizationInStream]]; }; DoEnumerateOrganizations: RemoteProc -- [handle, host] -- ~ { CHOps.ListOrganizations[handle, pattern.organization, ReadStreamOfOrganizations, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoEnumerateOrganizations, NIL, FALSE]; }; EnumerateDomains: PUBLIC PROC [c: Conversation, pattern: Pattern, eachDomain: XNSCH.ElementStreamProc] ~ { ReadStreamOfDomains: CrRPC.BulkDataXferProc ~ { EachDomainInStream: BulkDataValueProc ~ { eachDomain[ReadDomain[stream]] }; RETURN [ReadBulkDataStream[h, stream, checkAbort, EachDomainInStream]]; }; DoEnumerateDomains: RemoteProc -- [handle, host] -- ~ { CHOps.ListDomains[handle, [organization~pattern.organization, domain~pattern.domain], ReadStreamOfDomains, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoEnumerateDomains, NIL, FALSE]; }; LookupAddressFromRope: PUBLIC PROC [rope: ROPE] RETURNS [distingName: Name, address: XNS.Address] ~ { c: Conversation ~ XNSCH.InitiateConversation[]; [distingName, address] _ LookupAddress[c, ElementFromRope[rope] ! Error => { distingName _ [NIL,NIL,NIL]; address _ XNS.unknownAddress; CONTINUE }]; XNSCH.TerminateConversation[c] }; GetServerAddresses: PUBLIC PROC [c: Conversation] RETURNS [addresses: LIST OF XNS.Address] ~ { list: CHOps.NetworkAddressList; DoGetServerAddresses: RemoteProc -- [handle, host] -- ~ { i: CARDINAL; list _ CHOps.RetrieveAddresses[handle]; i _ list.length; addresses _ NIL; WHILE i > 0 DO i _ i - 1; addresses _ CONS [LOOPHOLE[list.body[i]], addresses]; ENDLOOP; }; IF XNSCHPrivate.IsGeneric[c] THEN ERROR Error[inappropriateConversation, first]; XNSCHPrivate.CallRemote[c, DoGetServerAddresses, NIL]; }; EnumerateDomainsServed: PUBLIC PROC [c: Conversation, eachDomain: XNSCH.ElementStreamProc] ~ { ReadStreamOfDomains: CrRPC.BulkDataXferProc ~ { EachDomainInStream: BulkDataValueProc ~ { eachDomain[ReadDomain[stream]] }; RETURN [ReadBulkDataStream[h, stream, checkAbort, EachDomainInStream]]; }; DoEnumerateDomainsServed: RemoteProc -- [handle, host] -- ~ { CHOps.ListDomainsServed[handle, ReadStreamOfDomains, XNSCHPrivate.GetAuthenticator[c, host]]; }; IF XNSCHPrivate.IsGeneric[c] THEN ERROR Error[inappropriateConversation, first]; XNSCHPrivate.CallRemote[c, DoEnumerateDomainsServed, NIL]; }; adrHWORDS: CARDINAL ~ 6; -- FIX THIS ???? AddressesFromItem: PUBLIC PROC [item: Item] RETURNS [addresses: LIST OF XNS.Address] ~ { buf: ARRAY [0..adrHWORDS) OF HWORD; cnt: CARD16 _ item.body[0]; index: CARDINAL _ 1; IF item.length < 1+cnt*adrHWORDS THEN RETURN[NIL]; THROUGH [1..cnt] DO FOR i: CARDINAL IN [0..adrHWORDS) DO buf[i] _ Endian.HFromCard[item.body[index]]; index _ index + 1; ENDLOOP; addresses _ CONS[LOOPHOLE[buf], addresses]; ENDLOOP; }; ItemFromAddresses: PUBLIC PROC [addresses: LIST OF XNS.Address] RETURNS [item: Item] ~ { buf: ARRAY [0..adrHWORDS) OF HWORD; index: CARDINAL; cnt: CARD16 _ 0; FOR temp: LIST OF XNS.Address _ addresses, temp.rest WHILE temp # NIL DO cnt _ cnt + 1; ENDLOOP; item _ NEW[CHOps.ItemObject[1+cnt*adrHWORDS]]; item.body[0] _ cnt; index _ 1; FOR temp: LIST OF XNS.Address _ addresses, temp.rest WHILE temp # NIL DO buf _ LOOPHOLE[temp.first]; FOR i: CARDINAL IN [0..adrHWORDS) DO item.body[index] _ Endian.CardFromH[buf[i]]; index _ index + 1; ENDLOOP; ENDLOOP; }; RopeFromItem: PUBLIC PROC [item: Item] RETURNS [rope: ROPE] ~ { [rope~rope] _ RopeFromItemInner[item,0] }; ElementFromItem: PUBLIC PROC [item: Item] RETURNS [element: Element] ~ { pos: INT; [rope~element.organization, newPos~pos] _ RopeFromItemInner[item, 0]; [rope~element.domain, newPos~pos] _ RopeFromItemInner[item, pos]; [rope~element.object] _ RopeFromItemInner[item, pos]; }; RopeFromItemInner: PROC [item: Item, pos: INT] RETURNS [rope: ROPE, newPos: INT] ~ { buf: Basics.ShortNumber; text: REF TEXT; cnt: CARDINAL; IF item.length <= pos THEN RETURN [NIL, pos]; cnt _ item.body[pos]; IF (item.length-pos-1)*2 < cnt THEN RETURN [NIL, pos]; -- ERROR text _ RefText.ObtainScratch[cnt]; newPos _ pos+1; DO IF cnt = 0 THEN EXIT; buf.lc _ item.body[newPos]; newPos _ newPos+1; text _ RefText.AppendChar[to~text, from~LOOPHOLE[buf.hi]]; cnt _ cnt-1; IF cnt = 0 THEN EXIT; text _ RefText.AppendChar[to~text, from~LOOPHOLE[buf.lo]]; cnt _ cnt-1; ENDLOOP; rope _ Rope.FromRefText[text]; RefText.ReleaseScratch[text]; }; ItemFromRope: PUBLIC PROC [rope: ROPE] RETURNS [item: Item] ~ { itemLen: INT ~ 1 + CrRPC.MarshalledROPEHWords[rope]; item _ NEW[CHOps.ItemObject[itemLen]]; ItemFromRopeInner[rope, item, 0]; }; ItemFromElement: PUBLIC PROC [element: Element] RETURNS [item: Item] ~ { orgLen: INT ~ CrRPC.MarshalledROPEHWords[element.organization]; domLen: INT ~ CrRPC.MarshalledROPEHWords[element.domain]; objLen: INT ~ CrRPC.MarshalledROPEHWords[element.object]; itemLen: INT ~ orgLen + domLen + objLen; item _ NEW[CHOps.ItemObject[itemLen]]; ItemFromRopeInner[element.organization, item, 0]; ItemFromRopeInner[element.domain, item, orgLen]; ItemFromRopeInner[element.object, item, orgLen + domLen] }; ItemFromRopeInner: PROC [rope: ROPE, item: Item, pos: INT] ~ { buf: Basics.ShortNumber; ropeLen: INT ~ Rope.Length[rope]; itemLen: INT ~ 1+(ropeLen+1)/2; iFrom: INT _ 0; item.body[pos] _ ropeLen; pos _ pos + 1; DO IF iFrom >= ropeLen THEN EXIT; buf.hi _ ORD[Rope.InlineFetch[rope, iFrom]]; iFrom _ iFrom+1; buf.lo _ IF iFrom < ropeLen THEN ORD[Rope.InlineFetch[rope, iFrom]] ELSE 0; iFrom _ iFrom+1; item.body[pos] _ buf.lc; pos _ pos + 1; ENDLOOP; }; ElementFromRope: PUBLIC PROC [rope: ROPE, defaultDomain: ROPE _ NIL, defaultOrganization: ROPE _ NIL] RETURNS [element: Element] ~ { GetDefaultDomain: PROC RETURNS [ROPE] ~ INLINE { IF Rope.IsEmpty[defaultDomain] THEN defaultDomain _ "PARC"; -- BOGUS RETURN [defaultDomain] }; GetDefaultOrganization: PROC RETURNS [ROPE] ~ INLINE { IF Rope.IsEmpty[defaultOrganization] THEN defaultOrganization _ "Xerox"; -- BOGUS RETURN [defaultOrganization] }; pos1, pos2, len: INT; len _ Rope.Length[rope]; pos1 _ Rope.Index[s1~rope, pos1~0, s2~":"]; pos2 _ Rope.Index[s1~rope, pos1~pos1+1, s2~":"]; element.object _ Rope.Substr[base~rope, start~0, len~pos1]; element.domain _ IF pos1 < len THEN Rope.Substr[base~rope, start~pos1+1, len~pos2-pos1-1] ELSE NIL; IF Rope.IsEmpty[element.domain] THEN element.domain _ GetDefaultDomain[]; element.organization _ IF pos2 < len THEN Rope.Substr[base~rope, start~pos2+1, len~len-pos2-1] ELSE NIL; IF Rope.IsEmpty[element.organization] THEN element.organization _ GetDefaultOrganization[]; }; RopeFromElement: PUBLIC PROC [element: Element] RETURNS [rope: ROPE] ~ { rope _ Rope.Cat[element.object, ":", "element.domain", ":", element.organization]; }; DomainFromElement: PROC [element: Element] RETURNS [rope: ROPE] ~ INLINE { rope _ Rope.Cat[element.organization, ":", element.domain] }; BestAddressInList: PUBLIC PROC [list: LIST OF XNS.Address] RETURNS [bestAddress: XNS.Address] ~ { bestHops: CARDINAL _ LAST[CARDINAL]; WHILE list # NIL DO tempHops: CARDINAL ~ XNSRouter.GetHops[list.first.net]; IF tempHops < bestHops THEN { bestAddress _ list.first; bestHops _ tempHops }; list _ list.rest; ENDLOOP; }; ReadBulkDataStream: PUBLIC PROC [h: CrRPC.Handle, stream: IO.STREAM, checkAbort: CrRPC.BulkDataCheckAbortProc, readValue: BulkDataValueProc] RETURNS [abort: BOOL] ~ { ENABLE IO.EndOfStream, IO.Error, XNSStream.ConnectionClosed => ERROR CrRPC.Error[NIL, communicationFailure, "communication failure"]; segmentKind: CARD16; lastSegment: CARD16 ~ 1; len: CARD16; DO IF checkAbort[h] THEN RETURN[FALSE]; segmentKind _ ReadCard16[stream]; len _ ReadCard16[stream]; THROUGH [1..len] DO IF checkAbort[h] THEN RETURN[FALSE]; IF readValue[stream].abort THEN RETURN[TRUE]; ENDLOOP; IF segmentKind = lastSegment THEN EXIT; ENDLOOP; RETURN[FALSE]; }; WriteSegment: PUBLIC PROC [h: CrRPC.Handle, stream: IO.STREAM, checkAbort: CrRPC.BulkDataCheckAbortProc, writeValue: BulkDataValueProc, n: CARDINAL] RETURNS [abort: BOOL _ FALSE, heAborted: BOOL _ FALSE] ~ { ENABLE IO.EndOfStream, IO.Error, XNSStream.ConnectionClosed => ERROR CrRPC.Error[NIL, communicationFailure, "communication failure"]; nextSegment: CARD16 ~ 0; lastSegment: CARD16 ~ 1; WriteCard16[stream, (IF n > 0 THEN nextSegment ELSE lastSegment)]; WriteCard16[stream, n]; THROUGH [1..n] DO IF checkAbort[h] THEN { heAborted _ TRUE; RETURN }; IF writeValue[stream].abort THEN { abort _ TRUE; RETURN }; ENDLOOP; }; ReadCard16: PUBLIC PROC [stream: IO.STREAM] RETURNS [CARD16] ~ { buf: Basics.ShortNumber; buf.hi _ ORD[IO.GetChar[stream]]; buf.lo _ ORD[IO.GetChar[stream]]; RETURN [buf.lc] }; ReadRope: PUBLIC PROC [stream: IO.STREAM] RETURNS [rope: ROPE] ~ { text: REF TEXT; len: CARD16; len _ ReadCard16[stream]; text _ RefText.ObtainScratch[len]; FOR i: INT IN [0 .. len) DO text _ RefText.AppendChar[to~text, from~IO.GetChar[stream]] ENDLOOP; IF (len MOD 2) # 0 THEN [] _ IO.GetChar[stream]; rope _ Rope.FromRefText[text]; RefText.ReleaseScratch[text]; }; ReadElement: PUBLIC PROC [stream: IO.STREAM] RETURNS [element: Element] ~ { element.organization _ ReadRope[stream]; element.domain _ ReadRope[stream]; element.object _ ReadRope[stream] }; ReadOrganization: PUBLIC PROC [stream: IO.STREAM] RETURNS [element: Element] ~ { element.organization _ ReadRope[stream]; element.domain _ NIL; element.object _ NIL }; ReadDomain: PUBLIC PROC [stream: IO.STREAM] RETURNS [element: Element] ~ { element.organization _ ReadRope[stream]; element.domain _ ReadRope[stream]; element.object _ NIL }; WriteCard16: PUBLIC PROC [stream: IO.STREAM, card16: CARD16] ~ { buf: Basics.ShortNumber; buf.lc _ card16; IO.PutChar[stream, VAL[buf.hi]]; IO.PutChar[stream, VAL[buf.lo]] }; WriteRope: PUBLIC PROC [stream: IO.STREAM, rope: ROPE] ~ { ENABLE IO.Error, XNSStream.ConnectionClosed => ERROR CrRPC.Error[NIL, communicationFailure, "communication failure"]; len: INT ~ Rope.Length[rope]; WriteCard16[stream, len]; FOR i: INT IN [0..len) DO IO.PutChar[stream, Rope.InlineFetch[rope, i]]; ENDLOOP; IF (len MOD 2) # 0 THEN IO.PutChar[stream, VAL[0]]; }; WriteElement: PUBLIC PROC [stream: IO.STREAM, element: Element] ~ { WriteRope[stream, element.organization]; WriteRope[stream, element.domain]; WriteRope[stream, element.object] }; }. ’XNSCHImpl.mesa Demers, December 11, 1986 8:27:23 pm PST To Do: Check whether CrRPCRuntime support catches errors in bulk data i/o procs. Operations on Objects [h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE] Operations on Properties [h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [stream: IO.STREAM] RETURNS [abort: BOOL] [h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE] Enumeration operations [h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE] [h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE] [h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE] [h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE] Common Lookups Server-Specific Queries [h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE] Utilities (Un)marshalling These are strange because the Items have already been byte-swapped to internal representation, which can mess up objects like XNS.Addresses that are stored inside them. Element <-> Rope conversion e.g. ["Xerox", "PARC", "*"] -> "Xerox:PARC" Address List Manipulation Bulk Data Stream Procs ʯ˜code™K™(K™K™PK˜—šÏk ˜ Kšœœ˜Kšœœ˜"Kšœ œŠ˜™KšœœQ˜\Kšœœ œ ˜+Kšœœ(œ˜8Kšœœ-˜:Kšœœ9œ ˜QKšœœ!˜*Kšœœ ˜KšœœÐ˜ÛKšœ œJ˜\Kšœ œ ˜Kšœ œ˜"Kšœ˜K˜—šÏn œœ˜Kšœœœ$˜^Kšœœ˜K˜Kšœž œžœ ˜0K˜KšœœœÏc˜7K˜Kšœœœ˜K˜Kšœœœ˜Kšœ œœ ˜Kšœ œœ ˜Kšœ œœ ˜$Kšœ œœ ˜$Kšœœœ˜Kšœœœ˜(K˜Kšœœ œ˜K˜Kšœ œ˜+Kšœœ"˜9K˜Kšœ œ˜ Kšœe˜eK˜Kš žœœœœœ œ˜Ghead™šžœœœ"˜2šžœ Ÿœ˜*KšœI˜IK˜—Kšœ;˜;K˜K˜—šžœœœ"˜5šžœ Ÿœ˜-KšœI˜IK˜—Kšœ>˜>K˜K˜—šžœœœ%œ˜Wšžœ Ÿœ˜-KšœZ˜ZK˜—KšœA˜AK˜K˜—šžœœœ&œ˜Zšž œ Ÿœ˜/Kšœ]˜]K˜—Kšœ>Ÿœ˜IK˜K˜—šž œœœ œ˜Wšž œ Ÿœ˜2KšœW˜WK˜—KšœD˜DK˜K˜—šž œ œ0œœ˜}šžœ˜)Kš œœœ&œ œ™YK˜šžœ˜#Kš œ œœœ œœ™1Kšœ%˜%—Kšœ?˜EKšœ˜—šž œ Ÿœ˜2Kšœn˜nK˜—KšœFœ˜MK˜K˜——™šž œœœ%œ0˜všžœ Ÿœ˜4šœ:˜:KšœN˜N—K˜—KšœH˜HK˜K˜—šžœœœ0œ˜jšžœ Ÿœ˜5Kšœ^˜^K˜—KšœF˜FK˜K˜—šžœœœ<œ˜wšžœ Ÿœ˜6Kšœe˜eK˜—KšœG˜GK˜K˜—šžœœœ<œ˜zšžœ Ÿœ˜9Kšœ`˜`K˜—KšœJ˜JK˜K˜—šžœœœ6œ$˜€šžœ Ÿœ˜9šœ/˜/KšœQ˜Q—K˜—KšœM˜MK˜K˜—šž œœœ%œ.˜tšžœ Ÿœ˜4K˜ Kšœ œœœ ˜šœ/˜/Kšœc˜c—Kšœ$˜$šœ ˜Kšœ'˜+Kšœ œ˜"—K˜—KšœH˜HK˜K˜—š žœœœ6œ#œ˜ˆšžœ Ÿœ˜9K˜ šœ/˜/KšœQ˜Q—Kšœ"˜"K˜—KšœM˜MK˜K˜—šžœœœ6œ,˜ˆšžœ Ÿœ˜9K˜ šœ/˜/KšœQ˜Q—Kšœ%˜%K˜—KšœM˜MK˜K˜—Kšž œœœ˜K˜š žœœœ<œœ˜Žšžœ˜-Kš œœœ&œ œ™YK˜Kšœ œœ˜šž œœ˜(šžœ˜"Kš œ œœœ œ™)Kšœ#œœ˜4—KšœP˜PKšœ œœ ˜$K˜—Kšœ&œ˜1Kš œœ œœœ˜@Kšœœ˜—šžœ Ÿœ˜7Kšœw˜wK˜—KšœH˜HK˜K˜—šž œ œAœ˜všž œ Ÿœ˜0Kšœa˜aK˜—KšœA˜AK˜K˜—šžœ œ0œ˜cšž œ Ÿœ˜.KšœW˜WK˜—Kšœ?˜?K˜K˜—šž œ œAœ˜yšžœ Ÿœ˜3Kšœd˜dK˜—KšœD˜DK˜—K˜šž œ œ0œ˜fšž œ Ÿœ˜1KšœZ˜ZK˜—KšœB˜BK˜K˜—šž œ œBœœ˜’šžœ˜,Kš œœœ&œ œ™YK˜šžœ˜&Kš œ œœœ œœ™1Kšœ&˜&—KšœB˜HKšœ˜—šž œ Ÿœ˜2Kšœx˜xK˜—KšœFœ˜MK˜K˜—šžœ œGœœ˜‹šž œ Ÿœ˜/Kšœ\œ<˜K˜—KšœC˜CK˜K˜—šžœ œYœœ˜¤šžœ Ÿœ˜6Kšœ’˜’K˜—Kšœœ ˜,KšœJ˜JK˜——™šž œ œBœ˜qšžœ˜)Kš œœœ&œ œ™YK˜šžœ˜#Kš œ œœœ œœ™1Kšœ&˜&—Kšœ?˜EKšœ˜—šž œ Ÿœ˜0Kšœc˜cK˜—KšœDœ˜KK˜K˜—šžœ œ/œ˜ešžœ˜)Kš œœœ&œ œ™YK˜šžœ˜#Kš œ œœœ œœ™1Kšœ$˜$—Kšœ?˜EKšœ˜—šžœ Ÿœ˜7Kšœ^˜^K˜—KšœKœ˜RK˜K˜—šžœ œ7œ˜všžœ˜1Kš œœœ&œ œ™YK˜šžœ˜+Kš œ œœœ œœ™1Kšœ1˜1—KšœG˜MKšœ˜—šžœ Ÿœ˜=Kšœy˜yK˜—Kšœ5œœ˜AK˜K˜—šžœ œ1œ˜jšžœ˜+Kš œœœ&œ œ™YK˜šžœ˜%Kš œ œœœ œœ™1Kšœ%˜%—KšœA˜GKšœ˜—šžœ Ÿœ˜7Kšœ“˜“K˜—Kšœ/œœ˜;K˜——™š žœœœœœœ ˜eKšœ/˜/šœ?˜?šœ ˜ Kš œœœœœœ˜H——Kšœ!˜!——™šžœœœœ œœœ ˜^Kšœ˜šžœ Ÿœ˜9Kšœœ˜ Kšœ'˜'Kšœ˜Kšœ œ˜šœ˜K˜ Kšœ œœ˜5Kšœ˜—K˜—Kšœœœ)˜PKšœ1œ˜6Kšœ˜K˜—šžœœœœ˜^šžœ˜+Kš œœœ&œ œ™YK˜šžœ˜%Kš œ œœœ œœ™1Kšœ%˜%—KšœA˜GKšœ˜—šžœ Ÿœ˜=Kšœ]˜]K˜—Kšœœœ)˜PKšœ5œ˜:Kšœ˜——™ ™K™¨K˜Kšœ œŸ˜)K˜š žœ œœ œœœ ˜XKšœœœœ˜#Kšœ œ ˜Kšœœ˜Kšœœœœ˜2šœ ˜šœœœ˜$K˜,K˜Kšœ˜—Kšœ œœ˜+Kšœ˜—K˜K˜—š žœ œ œœœ œ˜XKšœœœœ˜#Kšœœ˜Kšœ˜š œœœœ œœ˜HKšœ˜Kšœ˜—Kšœœ$˜.K˜K˜ š œœœœ œœ˜HKšœœ ˜šœœœ˜$K˜,K˜Kšœ˜—Kšœ˜—K˜K˜—šž œ œœœ˜?K˜*K˜—šžœ œœ˜HKšœœ˜ KšœE˜EKšœA˜AKšœ8˜8K˜—š žœœœœœ œ˜TK˜Kšœœœ˜Kšœœ˜Kšœœœœ˜-Kšœ˜Kš œœœœŸ˜?Kšœ"˜"Kšœ˜š˜Kšœ œœ˜Kšœ.˜.Kšœ(œ ˜:Kšœ ˜ Kšœ œœ˜Kšœ(œ ˜:Kšœ ˜ Kšœ˜—K˜K˜Kšœ˜K˜—šž œ œœœ˜?Kšœ œ(˜4Kšœœ˜&K˜!K˜K˜—šžœ œœ˜HKšœœ4˜?Kšœœ.˜9Kšœœ.˜9Kšœ œ˜(Kšœœ˜&Kšœ1˜1Kšœ0˜0Kšœ;˜;K˜—šžœœœœ˜>K˜Kšœ œ˜!Kšœ œ˜Kšœœ˜Kšœ)˜)š˜Kšœœœ˜Kšœ œ ˜,Kšœ˜Kš œ œœœ œ˜KKšœ˜Kšœ(˜(Kšœ˜—K˜——™šžœœœœœœœœœ˜„š žœœœœœ˜0KšœœŸ˜DKšœ˜—š žœœœœœ˜6Kšœ#œ Ÿ˜QKšœ˜—Kšœœ˜Kšœ˜K˜+K˜0K˜;šœ˜Kšœ œ7œœ˜R—šœ˜Kšœ%˜)—šœ˜Kšœ œ6œœ˜Q—šœ#˜%Kšœ1˜5—Kšœ˜K˜—š žœœœœœ˜HKšœR˜RK˜K˜—š žœœœœœ˜JK™+K˜=——™šžœ œœœœ œœ ˜aKšœ œœœ˜$šœœ˜Kšœ œ%˜7šœœ˜K˜K˜—K˜Kšœ˜—K˜———™š žœ œœœJœ œ˜¦š œœ%˜>Kšœ œ1˜F—Kšœ œ˜Kšœ œ˜Kšœœ˜ š˜Kšœœœœ˜$Kšœ!˜!Kšœ˜šœ ˜Kšœœœœ˜$Kšœœœœ˜-Kšœ˜—Kšœœœ˜'Kšœ˜—Kšœœ˜K˜K˜—šž œœœœœNœœ œœ œœ˜Ïš œœ%˜>Kšœ œ1˜F—Jšœ œ˜Kšœ œ˜Kšœœœ œ˜BK˜šœ˜Kšœœœœ˜3Kšœœ œœ˜:Kšœ˜—Kšœ˜K˜—š ž œ œ œœœœ˜@K˜Kšœ œœ˜!Kšœ œœ˜!Kšœ ˜K˜—š žœ œ œœœœ˜BKšœœœ˜Kšœœ˜ Kšœ˜K˜"šœœœ ˜Kšœ(œ˜;Kšœ˜—Kšœœœœ˜0K˜K˜Kšœ˜K˜—š ž œ œ œœœ˜KKšœ(˜(Kšœ"˜"Kšœ$˜$K˜—š žœ œ œœœ˜PKšœ(˜(Kšœœ˜Kšœœ˜K˜—š ž œ œ œœœ˜JKšœ(˜(Kšœ"˜"Kšœœ˜K˜—š ž œ œ œœ œ˜@K˜Kšœ˜Kšœœ ˜ Kšœœ ˜"K˜—š ž œ œ œœœ˜:šœœ%˜.Kšœ œ1˜F—Kšœœ˜K˜šœœœ ˜Kšœ,˜.Kšœ˜—Kš œœœœœ˜3K˜K˜—šž œ œ œœ˜CK˜(K˜"K˜$K˜——K˜—J˜—…—X¾vÿ