<> <> <<>> <> 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 <<[h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];>> ~ { EachNameInStream: BulkDataValueProc <<[stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE]>> ~ { 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 <<[h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];>> ~ { heAborted: BOOL _ FALSE; EachElement: PROC [element: Element] ~ { WriteTheElement: BulkDataValueProc <<[stream: IO.STREAM] RETURNS [abort: BOOL]>> ~ { 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 <<[h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];>> ~ { EachElementInStream: BulkDataValueProc <<[stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE]>> ~ { 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 <<[h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];>> ~ { EachNameInStream: BulkDataValueProc <<[stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE]>> ~ { 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 <<[h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];>> ~ { EachNameInStream: BulkDataValueProc <<[stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE]>> ~ { 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 <<[h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];>> ~ { EachOrganizationInStream: BulkDataValueProc <<[stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE]>> ~ { 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 <<[h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];>> ~ { EachDomainInStream: BulkDataValueProc <<[stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE]>> ~ { 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 <<[h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];>> ~ { EachDomainInStream: BulkDataValueProc <<[stream: IO.STREAM] RETURNS [abort: BOOL _ FALSE]>> ~ { 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]; }; <> <<(Un)marshalling>> <> 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; }; < Rope conversion>> 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 { < "Xerox:PARC">> 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] }; }.