DIRECTORY
Basics USING [Card16FromH, HFromCard16, HWORD, Word16],
CHACLOpsP127V1 USING [AddMemberToDomainACL, AddMemberToOrganizationACL, AddMemberToPropertyACL, DeleteMemberFromDomainACL, DeleteMemberFromOrganizationACL, DeleteMemberFromPropertyACL, DomainName, IsInDomainACL, IsInOrganizationACL, IsInPropertyACL, OrganizationName, RetrieveDomainACL, RetrieveOrganizationACL, RetrievePropertyACL],
CHEntriesP0V0 USING [addressList, associatedWorkstation, members],
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],
Convert USING [Error, RopeFromXNSAddress, XNSAddressFromRope],
CrRPC USING [BulkDataCheckAbortProc, BulkDataValueProc, BulkDataXferProc, GetRope, Handle, MarshalledRopeHWords, PutRope, ReadBulkDataStream, WriteBulkDataSegment],
IO USING [STREAM],
RefText USING [AppendChar, ObtainScratch, ReleaseScratch],
Rope USING [Cat, Concat, FromRefText, Fetch, IsEmpty, Length, ROPE],
ThisMachineRegistry USING [RegisterThisMachineProcs, ThisMachineProcsRec, ThisMachineRef],
XNS USING [Address, GetThisHost, Host, unknownAddress],
XNSAuth USING [GetIdentityDetails, Identity],
XNSCH USING [Conversation, Element, ElementStreamProc, EnumeratorProc, ErrorCode, InitiateConversation, Item, Name, NameStreamProc, notUsable, Pattern, Properties, PropertyID, TerminateConversation, unspecified, Which],
XNSCHACL USING [AccessList],
XNSCHName USING [FieldTooLong, Name, NameFromRope, RopeFromName],
XNSCHPrivate USING [CallRemote, GetAuthenticator, IsGeneric, NACacheInsert, NACacheLookup, RemoteProc],
XNSCredentials USING [GetIdentity],
XNSRouter USING [GetHops]
;
XNSCHImpl:
CEDAR
MONITOR
IMPORTS Basics, CHACLOpsP127V1, CHOpsP2V3, Convert, CrRPC, RefText, Rope, ThisMachineRegistry, XNS, XNSAuth, XNSCH, XNSCHName, XNSCHPrivate, XNSCredentials, XNSRouter
EXPORTS XNSCH, XNSCHACL, XNSCHPrivate
This is a monitor only because of the nCache stuff in "Common Lookups".
~ {
OPEN CHEntries: CHEntriesP0V0, CHOps: CHOpsP2V3, CHACLOps: CHACLOpsP127V1;
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;
AccessList: TYPE ~ XNSCHACL.AccessList;
DomainName: TYPE ~ CHACLOps.DomainName;
OrganizationName: TYPE ~ CHACLOps.OrganizationName;
HWORD: TYPE ~ Basics.HWORD;
RemoteProc: TYPE ~ XNSCHPrivate.RemoteProc;
BulkDataXferProc: TYPE ~ CrRPC.BulkDataXferProc;
BulkDataValueProc: TYPE ~ CrRPC.BulkDataValueProc;
shiftInName: ROPE ~ "CHServers";
chServiceName: Name ~
[organization~shiftInName, domain~shiftInName, object~"Clearinghouse Service"];
Error: PUBLIC ERROR [code: XNSCH.ErrorCode, which: XNSCH.Which] ~ CODE;
Operations on Objects
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: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachNameInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOL ← FALSE]
~ { eachAlias[GetElement[s]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachNameInStream]];
};
DoListAliases: RemoteProc
-- [handle, host] -- ~ {
distingName ¬ CHOps.ListAliasesOf[handle, pattern, ReadStreamOfNames, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoListAliases, DomainFromElement[pattern], FALSE];
};
Operations on Properties
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: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
heAborted: BOOL ¬ FALSE;
EachElement:
PROC [element: Element] ~ {
WriteTheElement: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOL]
~ { PutElement[s, element]; RETURN [FALSE] };
[heAborted~heAborted] ¬ CrRPC.WriteBulkDataSegment[h, s, checkAbort, WriteTheElement, 1];
IF heAborted THEN ERROR HeAborted[];
};
enumerator[EachElement ! HeAborted => CONTINUE ];
IF NOT heAborted THEN [] ¬ CrRPC.WriteBulkDataSegment[h, s, 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: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachElementInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOL ← FALSE]
~ { eachMember[GetElement[s]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, 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]];
};
Enumeration operations
Enumerate:
PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID,
eachObject:
XNSCH.NameStreamProc] ~ {
ReadStreamOfStrings: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachStringInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOL ← FALSE]
~ { eachObject[[organization~pattern.organization, domain~pattern.domain, object~CrRPC.GetRope[s]]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachStringInStream]];
};
DoEnumerate: RemoteProc
-- [handle, host] -- ~ {
CHOps.ListObjects[handle, pattern, pID, ReadStreamOfStrings, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoEnumerate, DomainFromElement[pattern], FALSE];
};
EnumerateAliases:
PUBLIC PROC [c: Conversation, pattern: Pattern,
eachName:
XNSCH.NameStreamProc] ~ {
ReadStreamOfStrings: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachStringInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOL ← FALSE]
~ { eachName[[organization~pattern.organization, domain~pattern.domain, object~CrRPC.GetRope[s]]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachStringInStream]];
};
DoEnumerateAliases: RemoteProc
-- [handle, host] -- ~ {
CHOps.ListAliases[handle, pattern, ReadStreamOfStrings, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoEnumerateAliases, DomainFromElement[pattern], FALSE];
};
EnumerateOrganizations:
PUBLIC PROC [c: Conversation, pattern: Pattern,
eachOrganization:
XNSCH.ElementStreamProc] ~ {
ReadStreamOfStrings: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachStringInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOL ← FALSE]
~ { eachOrganization[[organization~CrRPC.GetRope[s], domain~NIL, object~NIL]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachStringInStream]];
};
DoEnumerateOrganizations: RemoteProc
-- [handle, host] -- ~ {
CHOps.ListOrganizations[handle, pattern.organization, ReadStreamOfStrings, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoEnumerateOrganizations, NIL, FALSE];
};
EnumerateDomains:
PUBLIC PROC [c: Conversation, pattern: Pattern,
eachDomain:
XNSCH.ElementStreamProc] ~ {
ReadStreamOfStrings: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachStringInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOL ← FALSE]
~ { eachDomain[[organization~pattern.organization, domain~CrRPC.GetRope[s], object~NIL]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachStringInStream]];
};
DoEnumerateDomains: RemoteProc
-- [handle, host] -- ~ {
CHOps.ListDomains[handle, [organization~pattern.organization, domain~pattern.domain], ReadStreamOfStrings, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoEnumerateDomains, DomainFromOrgElement[pattern], FALSE];
};
Operations on Property ACLs
ListMembersOfPropertyACL:
PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, acl: AccessList, eachMember:
XNSCH.ElementStreamProc]
RETURNS [distingName: Name] ~ {
ReadStreamOfElements: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachElementInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOL ← FALSE]
~ { eachMember[GetElement[s]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachElementInStream]];
};
DoListMembersOfPropertyACL: RemoteProc
-- [handle, host] -- ~ {
distingName ¬ CHACLOps.RetrievePropertyACL[handle, pattern, pID, acl, ReadStreamOfElements, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoListMembersOfPropertyACL, DomainFromElement[pattern], FALSE];
};
IsMemberOfPropertyACLClosure:
PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, acl: AccessList, member: Element, pID2: PropertyID]
RETURNS [distingName: Name, isMember:
BOOL] ~ {
DoIsMemberOfPropertyACLClosure: RemoteProc
-- [handle, host] -- ~ {
[inACL~isMember, distinguishedObject~distingName] ¬
CHACLOps.IsInPropertyACL[handle, pattern, pID, acl, pID2, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
IF pID2 = XNSCH.unspecified THEN pID2 ¬ pID;
XNSCHPrivate.CallRemote[c, DoIsMemberOfPropertyACLClosure, DomainFromElement[pattern]];
};
AddMemberToPropertyACL:
PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, acl: AccessList, member: Element]
RETURNS [distingName: Name] ~ {
DoAddMemberToPropertyACL: RemoteProc
-- [handle, host] -- ~ {
distingName ¬ CHACLOps.AddMemberToPropertyACL[handle, name, pID, acl, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoAddMemberToPropertyACL, DomainFromElement[name]];
};
DeleteMemberFromPropertyACL:
PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, acl: AccessList, member: Element]
RETURNS [distingName: Name] ~ {
DoDeleteMemberFromPropertyACL: RemoteProc
-- [handle, host] -- ~ {
distingName ¬ CHACLOps.DeleteMemberFromPropertyACL[handle, name, pID, acl, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoDeleteMemberFromPropertyACL, DomainFromElement[name]];
};
Operations on Domain ACLs
ListMembersOfDomainACL:
PUBLIC PROC [c: Conversation, domain: Name, acl: AccessList, eachMember:
XNSCH.ElementStreamProc] ~ {
domainName: DomainName ~ [domain~domain.domain, organization~domain.organization];
ReadStreamOfElements: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachElementInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOL ← FALSE]
~ { eachMember[GetElement[s]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachElementInStream]];
};
DoListMembersOfDomainACL: RemoteProc
-- [handle, host] -- ~ {
[] ¬ CHACLOps.RetrieveDomainACL[handle, domainName, acl, ReadStreamOfElements, XNSCHPrivate.GetAuthenticator[c, host]]; -- RETURNS SOMETHING ????
};
XNSCHPrivate.CallRemote[c, DoListMembersOfDomainACL, DomainFromElement[domain], FALSE];
};
IsMemberOfDomainACLClosure:
PUBLIC PROC [c: Conversation, domain: Name, acl: AccessList, member: Element, pID2: PropertyID]
RETURNS [isMember:
BOOL] ~ {
domainName: DomainName ~ [domain~domain.domain, organization~domain.organization];
DoIsMemberOfDomainACLClosure: RemoteProc
-- [handle, host] -- ~ {
isMember ¬ CHACLOps.IsInDomainACL[handle, domainName, acl, pID2, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
IF pID2 = XNSCH.unspecified THEN pID2 ¬ CHEntries.members;
XNSCHPrivate.CallRemote[c, DoIsMemberOfDomainACLClosure, DomainFromElement[domain]];
};
AddMemberToDomainACL:
PUBLIC PROC [c: Conversation, domain: Name, acl: AccessList, member: Element] ~ {
domainName: DomainName ~ [domain~domain.domain, organization~domain.organization];
DoAddMemberToDomainACL: RemoteProc
-- [handle, host] -- ~ {
CHACLOps.AddMemberToDomainACL[handle, domainName, acl, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoAddMemberToDomainACL, DomainFromElement[domain]];
};
DeleteMemberFromDomainACL:
PUBLIC PROC [c: Conversation, domain: Name, acl: AccessList, member: Element] ~ {
domainName: DomainName ~ [domain~domain.domain, organization~domain.organization];
DoDeleteMemberFromDomainACL: RemoteProc
-- [handle, host] -- ~ {
CHACLOps.DeleteMemberFromDomainACL[handle, domainName, acl, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoDeleteMemberFromDomainACL, DomainFromElement[domain]];
};
Operations on Organization ACLs
ListMembersOfOrganizationACL:
PUBLIC PROC [c: Conversation, organization: Name, acl: AccessList, eachMember:
XNSCH.ElementStreamProc] ~ {
organizationName: OrganizationName ~ organization.organization;
ReadStreamOfElements: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachElementInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOL ← FALSE]
~ { eachMember[GetElement[s]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachElementInStream]];
};
DoListMembersOfOrganizationACL: RemoteProc
-- [handle, host] -- ~ {
CHACLOps.RetrieveOrganizationACL[handle, organizationName, acl, ReadStreamOfElements, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoListMembersOfOrganizationACL, DomainFromOrgElement[organization], FALSE];
};
IsMemberOfOrganizationACLClosure:
PUBLIC PROC [c: Conversation, organization: Name, acl: AccessList, member: Element, pID2: PropertyID]
RETURNS [isMember:
BOOL] ~ {
organizationName: OrganizationName ~ organization.organization;
DoIsMemberOfOrganizationACLClosure: RemoteProc
-- [handle, host] -- ~ {
isMember ¬ CHACLOps.IsInOrganizationACL[handle, organizationName, acl, pID2, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
IF pID2 = XNSCH.unspecified THEN pID2 ¬ CHEntries.members;
XNSCHPrivate.CallRemote[c, DoIsMemberOfOrganizationACLClosure, DomainFromOrgElement[organization]];
};
AddMemberToOrganizationACL:
PUBLIC PROC [c: Conversation, organization: Name, acl: AccessList, member: Element] ~ {
organizationName: OrganizationName ~ organization.organization;
DoAddMemberToOrganizationACL: RemoteProc
-- [handle, host] -- ~ {
CHACLOps.AddMemberToOrganizationACL[handle, organizationName, acl, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoAddMemberToOrganizationACL, DomainFromOrgElement[organization]];
};
DeleteMemberFromOrganizationACL:
PUBLIC PROC [c: Conversation, organization: Name, acl: AccessList, member: Element] ~ {
organizationName: OrganizationName ~ organization.organization;
DoDeleteMemberFromOrganizationACL: RemoteProc
-- [handle, host] -- ~ {
CHACLOps.DeleteMemberFromOrganizationACL[handle, organizationName, acl, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoDeleteMemberFromOrganizationACL, DomainFromOrgElement[organization]];
};
Common Lookups
LookupAddressFromRopeInner:
PROC [rope:
ROPE, doClosure:
BOOL ¬
FALSE]
RETURNS [distingName: Name ¬ [NIL,NIL,NIL], address: XNS.Address ¬ XNS.unknownAddress, didClosure: BOOL ¬ FALSE]
~ {
c: Conversation ¬ XNSCH.InitiateConversation[];
name: Name;
{
{
ENABLE Convert.Error =>
CONTINUE;
address ¬ Convert.XNSAddressFromRope[rope];
GOTO Good };
{
ENABLE XNSCHName.FieldTooLong =>
GOTO Bad;
name ¬ XNSCHName.NameFromRope[rope];
};
DO
{ found:
BOOL;
[found, distingName, address] ¬ XNSCHPrivate.NACacheLookup[name];
IF found THEN GOTO Good;
};
{
ENABLE Error =>
CONTINUE;
[distingName, address] ¬ LookupAddress[c, name];
XNSCHPrivate.NACacheInsert[name, distingName, address]; -- Note we cache direct mappings only, not closure mappings.
GOTO Good };
IF doClosure
THEN {
ENABLE Error => CONTINUE;
item: Item;
[item~item] ¬ LookupItemProperty[c~c, pattern~name, pID~CHEntries.associatedWorkstation];
name ¬ ElementFromItem[item];
didClosure ¬ TRUE;
LOOP;
};
GOTO Bad;
ENDLOOP;
};
XNSCH.TerminateConversation[c];
};
LookupAddressFromRope:
PUBLIC
PROC [rope:
ROPE]
RETURNS [distingName: Name, address:
XNS.Address]
~ {
[distingName~distingName, address~address] ¬
LookupAddressFromRopeInner[rope, FALSE];
};
LookupAddressFromRopeClosure:
PUBLIC
PROC [rope:
ROPE]
RETURNS [distingName: Name, address:
XNS.Address, didClosure:
BOOL]
~ {
[distingName, address, didClosure] ¬
LookupAddressFromRopeInner[rope, TRUE];
};
Server-Specific Queries
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: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachDomainInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOL ← FALSE]
~ { eachDomain[GetDomain[s]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, 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];
};
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.
adrHWords: CARDINAL ~ BITS[XNS.Address]/BITS[HWORD];
AddressesFromItem:
PUBLIC PROC [item: Item]
RETURNS [addresses:
LIST
OF
XNS.Address] ~ {
buf: PACKED ARRAY [0..adrHWords) OF HWORD;
cnt: CARD16;
index: CARDINAL ¬ 1;
IF item.length < 1 THEN RETURN[NIL];
cnt ¬ item.body[0];
IF item.length < 1+cnt*adrHWords THEN RETURN[NIL];
THROUGH [1..cnt]
DO
FOR i:
CARDINAL
IN [0..adrHWords)
DO
buf[i] ¬ Basics.HFromCard16[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: PACKED 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] ¬ Basics.Card16FromH[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: CARD32;
[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:
CARD32]
RETURNS [rope:
ROPE, newPos:
CARD32] ~ {
buf: Basics.Word16;
text: REF TEXT;
cnt: CARD32;
IF item.length <= pos THEN RETURN [NIL, pos];
cnt ¬ item.body[pos];
IF (CARD[item.length-pos-1]*BYTES[HWORD]) < cnt THEN RETURN [NIL, pos]; -- ERROR
text ¬ RefText.ObtainScratch[cnt];
newPos ¬ pos+1;
DO
IF cnt = 0 THEN EXIT;
buf.card ¬ 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: CARD32 ~ CrRPC.MarshalledRopeHWords[rope];
item ¬ NEW[CHOps.ItemObject[itemLen]];
ItemFromRopeInner[rope, item, 0];
};
ItemFromElement:
PUBLIC PROC [element: Element]
RETURNS [item: Item] ~ {
orgLen: CARD32 ~ CrRPC.MarshalledRopeHWords[element.organization];
domLen: CARD32 ~ CrRPC.MarshalledRopeHWords[element.domain];
objLen: CARD32 ~ CrRPC.MarshalledRopeHWords[element.object];
itemLen: CARD32 ~ 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:
CARD32] ~ {
buf: Basics.Word16;
ropeLen, iFrom: INT;
IF CrRPC.MarshalledRopeHWords[rope] > (item.length - pos) THEN ERROR;
item.body[pos] ¬ ropeLen ¬ Rope.Length[rope]; pos ¬ pos + 1;
iFrom ¬ 0;
DO
IF iFrom >= ropeLen THEN EXIT;
buf.hi ¬ ORD[Rope.Fetch[rope, iFrom]];
iFrom ¬ iFrom+1;
buf.lo ¬ IF iFrom < ropeLen THEN ORD[Rope.Fetch[rope, iFrom]] ELSE 0;
iFrom ¬ iFrom+1;
item.body[pos] ¬ buf.card; pos ¬ pos + 1;
ENDLOOP;
};
Domain Name Ropes
DomainFromElement:
PROC [element: Element]
RETURNS [rope:
ROPE] ~
INLINE {
e.g. ["Xerox", "PARC", "*"] -> "PARC:Xerox"
rope ¬ Rope.Cat[element.domain, ":", element.organization] };
DomainFromOrgElement:
PROC [element: Element]
RETURNS [rope:
ROPE] ~
INLINE {
e.g. ["Xerox", "foo", "bar"] -> "Xerox:CHServers"
rope ¬ Rope.Cat[element.organization, ":", shiftInName] };
Address List Manipulation
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;
};
Bulk Data Stream / Marshalling Procs
GetElement:
PUBLIC PROC [stream:
IO.
STREAM]
RETURNS [element: Element] ~ {
element.organization ¬ CrRPC.GetRope[stream];
element.domain ¬ CrRPC.GetRope[stream];
element.object ¬ CrRPC.GetRope[stream] };
GetOrganization:
PUBLIC PROC [stream:
IO.
STREAM]
RETURNS [element: Element] ~ {
element.organization ¬ CrRPC.GetRope[stream];
element.domain ¬ NIL;
element.object ¬ NIL };
GetDomain:
PUBLIC PROC [stream:
IO.
STREAM]
RETURNS [element: Element] ~ {
element.organization ¬ CrRPC.GetRope[stream];
element.domain ¬ CrRPC.GetRope[stream];
element.object ¬ NIL };
PutElement:
PUBLIC PROC [stream:
IO.
STREAM, element: Element] ~ {
CrRPC.PutRope[stream, element.organization];
CrRPC.PutRope[stream, element.domain];
CrRPC.PutRope[stream, element.object] };
taken from ThisMachineImpl; registered with ThisMachineRegistry
cachedXNSName: ROPE ¬ NIL;
cachedXNSNameOK: BOOL ¬ FALSE;
TMName:
PROC
RETURNS[rope:
ROPE ¬
NIL] = {
Someday the XNS world will have to get its act together and allow address-to-name mapping. For now, we try to construct an XNS name either as <username>-WS or by getting the Pup name and using the default domain and organization. We try this at most once, since it takes awhile if there isn't a Pup name service on the network.
GuessXNSName:
PROC [guess:
ROPE] ~ {
address: XNS.Address;
distingName: XNSCHName.Name;
IF Rope.IsEmpty[guess] THEN RETURN;
guess ¬ XNSCHName.RopeFromName[XNSCHName.NameFromRope[guess]];
[distingName, address] ¬ LookupAddressFromRope[guess];
IF address.host =
XNS.GetThisHost[]
THEN {
cachedXNSName ¬ XNSCHName.RopeFromName[distingName];
cachedXNSNameOK ¬ TRUE };
};
IF
NOT cachedXNSNameOK
THEN {
item: XNSCH.Item;
c: XNSCH.Conversation;
tempIdentity: XNSAuth.Identity ¬ XNSCredentials.GetIdentity[];
IF tempIdentity = NIL THEN GOTO Out;
c ¬ XNSCH.InitiateConversation[];
[item~item] ¬ LookupItemProperty[c~c, pattern~XNSAuth.GetIdentityDetails[tempIdentity].name, pID~CHEntries.associatedWorkstation
! Error => { XNSCH.TerminateConversation[c]; GOTO Out } ];
XNSCH.TerminateConversation[c];
GuessXNSName[XNSCHName.RopeFromName[ElementFromItem[item]]];
};
IF
NOT cachedXNSNameOK
THEN {
Guess <userName>-WS ...
tempIdentity: XNSAuth.Identity ¬ XNSCredentials.GetIdentity[];
IF tempIdentity #
NIL
THEN
GuessXNSName[Rope.Concat[XNSAuth.GetIdentityDetails[tempIdentity].name.object, "-ws"]];
};
IF
NOT cachedXNSNameOK
THEN {
Give up ...
cachedXNSName ¬ NIL;
cachedXNSNameOK ¬ TRUE;
};
rope ¬ cachedXNSName;
};
TMAddress:
PROC
RETURNS[rope:
ROPE ¬
NIL] = {
rope ¬ Convert.RopeFromXNSAddress[Convert.XNSAddressFromRope["ME"]];
};
InitProcs:
PROC = {
thisMachineProcs: ThisMachineRegistry.ThisMachineRef ¬
NEW[ThisMachineRegistry.ThisMachineProcsRec ¬ [
which: $xns,
Name: TMName,
Address: TMAddress,
ProcessorID: NIL
]];
ThisMachineRegistry.RegisterThisMachineProcs[thisMachineProcs];
Booting.RegisterProcs[r~Rollback];
};
Rollback: Booting.RollbackProc ~ {
cachedXNSNameOK ← FALSE;
cachedXNSName ← NIL;
};
InitProcs[];
}.