ThParty.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Last modified by Swinehart, December 17, 1985 12:43:02 pm PST
Parties and Conversations
DIRECTORY
BasicTime USING [ GMT ],
Lark,
RefID USING [ ID ],
RPC USING [ InterfaceName ],
Thrush USING [
AlertKind, CallUrgency, ConversationID, ConvEvent, Credentials, Machine, NB, nullID, PartyID, PartyType, Reason, ROPE, SHHH, SmartsID, StateInConv, unencrypted ],
ThSmartsRpcControl
;
ThParty: CEDAR DEFINITIONS = {
Definitions
ConversationID: TYPE = Thrush.ConversationID;
PartyID: TYPE = Thrush.PartyID;
SmartsID: TYPE = Thrush.SmartsID;
nullID: RefID.ID = Thrush.nullID;
Credentials: TYPE = Thrush.Credentials;
NB: TYPE = Thrush.NB;
ROPE: TYPE = Thrush.ROPE;
SHHH: TYPE = Thrush.SHHH;
none: SHHH = Thrush.unencrypted;
SmartsInterfaceName: TYPE = RPC.InterfaceName;
SmartsInterfaceRecord: TYPE = ThSmartsRpcControl.InterfaceRecord;
SmartsProperties: TYPE=RECORD[
role: SmartsRole←NIL,
machine: Thrush.Machine←[[0],[0]]
];
SmartsRole: TYPE= ATOM; -- { $voiceTerminal, $controller, ? };
voiceTerminal represents a role corresponding to Lark Smarts, front or back door, or BluejaySmarts; an actual source/sink of audio information, as well as the smarts control functions.
controller represents an entity that can perform control functions, but cannot supply or accept the voice transmission protocol. Standard and only present example: FinchSmarts. Controllers generally get to hear about changes in conversations before their associated voice terminals do.
Conversation Management
Discussion
A Smarts must relay all call-placement requests through a Party it is associated with. This is because we don't trust all Smarts as much as we trust all Parties; the Parties should validate the requests. The party level, however, only concerns itself with maintaining the "truth" about the current state of all parties in a conversation, reporting state transitions to interested smarts, and storing/computing some values that smarts may be interested in. Smarts are responsible for initiating their own state transitions and in interpreting the meaning of being in one state or another.
Exceptions: 1) One smarts may advance another party into the $notified state in order to initiate a call. 2) When all parties in a conversation are in the $idle state, the party code can eliminate all the data structures associated with the conversation.
CreateConversation produces a new conversation and puts the calling party in it, in the indicated state; one can destroy the conversation only by idling onesself with respect to it, and expecting others to do the same. CreateConversation accepts other call parameters as a convenience. The conversation's creator is henceforth known to the system as the $originator of the conversation.
Alert adds another party to the conversation, in $notified state -- this is always legal, assuming the party's not in the conversation already! The notified party is expected to advance to a further state and report it to the $originator (caller of Alert). The originator can not subsequently influence the behavior of the notified party, except by suggestion.
Advance is called by smarts to progress its own party through a call. See Thrush.StateInConv for a description of the states and their meanings. The reason/comment fields are most useful when going idle, to indicate whether it was due to some problem or just because the call is over.
Most ThParty functions return an NB (nota bene) code. If this value is not $success, usually any other return values will be NIL, nullID, or meaningless, and the requested operation will not have been performed. The NB values indicate generally what went wrong. $stateMismatch means that some other party has changed state and the caller has not yet been informed of that. This will only be returned from functions that operate on the conversation state.
CreateConversation: PROC[
shhh: SHHH ← none,
credentials: Credentials,
state: Thrush.StateInConv←$initiating,
urgency: Thrush.CallUrgency←NIL, -- $normal
alertKind: Thrush.AlertKind←NIL, -- $standard
subject: Thrush.ROPENIL
] RETURNS [ nb: NB, convEvent: Thrush.ConvEvent ];
Alert: PROC[
shhh: SHHH ← none,
credentials: Credentials,
calledPartyID: PartyID←nullID,
comment: ROPENIL
] RETURNS [nb: NB ];
ConvEvent will be reported to alerted party, not us; if this fails, give up on the call.
Advance: PROC[
shhh: SHHH ← none,
credentials: Credentials,
state: Thrush.StateInConv,
reportToAll: BOOLFALSE,
IF TRUE, advance is reported to all parties; if FALSE, to calling party only (smarts other than the calling smarts; in no case is an advance reported back to the caller).
reason: Thrush.Reason←NIL, -- wontSay
comment: ROPENIL
] RETURNS [nb: NB, convEvent: Thrush.ConvEvent ];
Conversations
MergeConversations: PROC[
shhh: SHHH ← none,
credentials: Credentials, -- of surviving conversation
otherStateID: Thrush.StateID, -- of dissolving conversation
otherConvID: ConversationID
] RETURNS [ nb: NB ];
OtherParty: PROC[
shhh: SHHH←none,
credentials: Credentials
] RETURNS[ nb: NB, partyID: PartyID, description: Thrush.ROPE, conference: BOOL ];
Produces ID of one other party, + description. If # parties > 2, description is best efforts description of who's in it with credentials.partyID, conference is TRUE.
Enumerations, queries
ConversationInfo: TYPE = RECORD [
Information about the conversation as a whole
subject: ROPENIL,
urgency: Thrush.CallUrgency←NIL,
alertKind: Thrush.AlertKind←NIL,
startTime: BasicTime.GMT←TRASH,
conferenceHost: Thrush.Machine←TRASH,
numParties: NATTRASH,
numActive: NATTRASH,
numIdle: NATTRASH,
originator: Thrush.PartyID ← TRASH
lastTime: BasicTime.GMTTRASH, -- Time of last state transition, any party
];
GetConversationInfo: PROC [ shh: SHHH←none, convID: ConversationID ]
RETURNS [
Readily-available (and not too big) information about the conversation
nb: NB, -- one of $success, $noSuchConv
cInfo: ConversationInfo
];
PartyInfo: TYPE = REF PartyInfoSeq;
Socket numbers and host names for each of the voice terminals in this conversation; own entry, if any, comes first.
PartyInfoSeq: TYPE = RECORD [
numParties: NAT𡤀, -- number of valid entries in this sequence
conferenceHost: Thrush.Machine←TRASH, -- needed for connection spec. stuff.
parties: SEQUENCE len: NAT OF PartyInfoSpec
];
PartyInfoSpec: TYPE = RECORD [
partyID: PartyID←nullID,
type: Thrush.PartyType←NIL,
state: Thrush.StateInConv←$neverWas, -- of this party in the conversation
stateID: Thrush.StateID←TRASH, -- last transition.
lastTime: BasicTime.GMTTRASH, -- of last transition
name: Thrush.ROPENIL, -- owner, current name, or description, see below
numConvs: NAT←TRASH,
enabled: BOOL←TRASH,
partyActive: BOOL←TRASH,
socket: Lark.VoiceSocket←TRASH -- in1 (tx1) socket template for voice terminal for this party
];
NameReq: TYPE = ATOM; -- { $owner, $current, $description, $address, $none };
$owner: RName of creator of this party; same as $current for telephone and individual parties; RName of trunk's owner for trunks; Idle service RName for services.
$current: Current assignment; identity of party on the other end of a $trunk, or modified service name identifying user.
$address: meaningless but same as $current for all but $trunk, where it's the phone number
$description: dolled-up version of $current, suitable for framing, including all known names and numbers, for Finch and so on.
GetPartyInfo: PROC [
shh: SHHH←none,
credentials: Credentials,
nameReq: NameReq←$current,
allParties: BOOLFALSE -- IF FALSE, just calling party; else all parties, calling party first
]
RETURNS [
Information about the parties (or just one party) in a conversation
Credentials should have either a ConversationID or PartyID or both; other fields irrelevant.
nb: NB, -- one of $success, $noSuchConv, $noSuchParty, $notInConv
pInfo: PartyInfo
];
GetPartyInfo[nameReq: $current, allParties: FALSE] replaces GetRname.
GetPartyInfo[nameReq: $description, allParties: FALSE] replaces DescribeParty
GetKeyTable: PROC [ shh: SHHH←none, credentials: Credentials ]
RETURNS [
nb: NB, -- one of $success, $noSuchConv, $noSuchParty, $notInConv
keyTable: Lark.KeyTable
];
DescribeParty: PROC[partyID: Thrush.PartyID, nameReq: NameReq]
RETURNS[nb: NB, description: Thrush.ROPE];
ConversationsForParty: PROC [ shh: SHHH←none, partyID: PartyID ];
Caller should expect to be informed of all conversations currently in progress for this party. So should all of the other Smartses connected to the party. Thus, a Smarts must be prepared to hear about the same event twice. <<Could cause trouble when interval specs, connection specs, and conversation keys are being distributed.>>
Recorded voice management.
SetIntervals: PROC[
shhh: SHHH ← none,
credentials: Credentials,
intervalSpecs: Thrush.IntervalSpecs -- a list allows some queueing at request site.
]
RETURNS [ nb: NB ];
This is provided as a convenience. It simply calls a similar procedure in the currently connected Jukebox service to describe the loud and silence intervals within the specified interval. Implementation tries to keep things unlocked; nonexistence of an interval might arise due to tunes in transition.
DescribeInterval: PROC[
shhh: SHHH ← none,
credentials: Credentials,
targetInterval: Thrush.IntervalSpec,
minSilence: Thrush.VoiceTime ← 1 -- Smallest silent interval that will be considered silence.
]
RETURNS [ nb: NB, exists: BOOL, intervals: Thrush.IntervalSpecs ];
RegisterKey: PROC[
shh: SHHH ← none,
credentials: Credentials,
key: Thrush.EncryptionKey
]
RETURNS [ nb: NB, keyIndex: [0..17B] ];
Synthesized-voice management (intend to fold into voice-rope-style design next round)
SetProse: PROC[
shhh: SHHH ← none,
credentials: Credentials,
proseSpecs: Thrush.ProseSpecs -- a list allows some queueing at request site.
]
RETURNS [ nb: NB ];
GetParty and friends
Discussion
Parties represent participants in conversations. Depending on type, they represent:
service: a recording service, synthesizer, and the like.
trunk: the party at the other end of a "back door" telephone line.
telephone: the user of a Lark (Etherphone) in an office.
individual: an authenticated user of a Lark and/or a client program registered with the server.
GetParty and friends map names into parties. (Register creates new parties.) The rName is either the name of an individual (including registry), a service (e.g., "recording"), or (in the case of trunks) NIL.
partyID is the ID for one's own party -- the "self" of object-style references. This form is followed throughout this interface.
GetParty: PROC[
shh: SHHH←none, partyID: PartyID, rName: ROPENIL,
type: Thrush.PartyType←NIL
] RETURNS [nb: NB, newPartyID: PartyID];
IF nb#success, it gives some idea of what went wrong. Thrush.NB can be extended with specialized error values in cases where the caller is expected to understand more about it (when obtaining services, for instance)
IF type=NIL, it's a request for an $individual (preferably) or $telephone (otherwise).
GetParty will return one's own trunk, properly configured, if type=$telephone and no Etherphone party can be found.
GetPartyFromNumber: PROC[
shh: SHHH←none,
partyID: PartyID,
phoneNumber: Thrush.ROPENIL, description: ROPENIL
] RETURNS [nb: NB, newPartyID: PartyID];
phoneNumber is a valid extension or outside telephone number. Description is probably a name, but may not be an RName; we can use it to help the user, but not to look up anything. Unless trunkOK, number must be an internal extension representing an Etherphone user.
GetPartyFromFeepNum: PROC[
shh: SHHH←none,
partyID: PartyID,
feepNum: Thrush.ROPENIL
] RETURNS [nb: NB, newPartyID: PartyID];
FeepNum is a string of the form "*nnnnn", where "nnnnn" is a prefix of some rName, mapped with information loss into the corresponding DTMF buttons. The prefix should be long enough to be guaranteed unique within the system. This isn't at all good yet.
GetCurrentParty: PROC[shh: SHHH←none, smartsID: SmartsID]
RETURNS [nb: NB, partyID: Thrush.PartyID];
Who do we represent when we initiate an outgoing call? After obtaining this party, it may become invalid (due to the party dropping out), so be prepared for $noSuchParty problems all along the line.
Information about people and parties
GetNumbersForRName: PROC[shh: SHHH←none, rName: ROPE]
RETURNS [fullRName: ROPE, number: ROPE, homeNumber: ROPE];
fullRName is NIL if nothing found.
Party and Smarts creation, initialization
Discussion
A Smarts implementation uses Register to create the server's identifier for the Smarts, to create the corresponding party, and to establish the necessary links between these objects and the reset of the system. <There used to be some authentication involved in this step, but for now we're trusting RPC to provide authorized identities.>
Since the server needs to be able to deal with more than one Smarts implementation, they are implemented as objects and must use RPC's object-oriented option.
Options include:
Local or remote registration: in the local case, the Smarts implementation is on the same machine and can supply the interface record directly.
Cloning: a service can request additional registrations based on an initial prototype. This allows the service to support a number of simultaneous conversations.
Calling Register with identical party identification results in the immediate destruction (via Deregister) of the previous version of the party and creation of a new one. CheckIn can be used to determine whether such a step is necessary.
Register: PROC[
shh: SHHH←none,
Identification of party -- requires either:
Description of party
rName: ROPENIL,
type: Thrush.PartyType← $individual,
Or ID of party to replicate (used to provide multiple instances of services)
clonePartyID: PartyID ← nullID,
Identification of smarts implementation -- requires either:
RPC Interface allowing an instance to be imported
interface: SmartsInterfaceName,
Or Local Interface record matching that produced by RPC -- see ThPartyPrivate.RegisterLocal
Kind of Smarts being registered, and from what host
properties: SmartsProperties
] RETURNS [
nb: NB, credentials: Credentials ];
nb will indicate something about what went wrong if anything did; if nb=$success,
credentials contains the resulting PartyID and SmartsID.
CheckIn: PROC[shh: SHHH←none, credentials: Credentials] RETURNS [nb: NB];
Verifies that the credentials are still valid, (conv can be null), or if not, which problem is the most pronounced. Can be used as basis for occasional Smarts to party polling.
Deregister: PROC[shh: SHHH←none, smartsID: SmartsID] RETURNS [nb: NB];
nb will be noSuchSmarts or success, or something else (which implies things are confused)
Enable: PROC[shh: SHHH←none, smartsID: SmartsID]
RETURNS [nb: Thrush.NB];
nb=success unless something went wrong. Any parties connected to this smarts will now be available to GetParty; this smarts is an active voice smarts.
Disable: PROC[shh: SHHH←none, smartsID: SmartsID]
RETURNS [nb: Thrush.NB];
This smarts can no longer supply a voice connection to its parties.
}.
Swinehart, May 15, 1985 10:01:11 am PDT
Cedar 6.0
changes to: GetParty stuff simplified (from client standpoint), Prose functions added, some unused procedures removed.
Swinehart, October 31, 1985 5:18:48 pm PST
Major changes to argument structure, Smarts/Party structure
changes to: Alert, Advance, CreateConversation, GetParty, SetRingEnable, DIRECTORY, LocalSmartsInterface, SmartsProperties, SmartsRole, Register, GetPartyFromFeepNum
Swinehart, November 7, 1985 9:50:41 am PST
Revamping ThParty, (lean, mean Thrush)
changes to: CreateConversation, Alert, Advance