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 = { 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, ? }; CreateConversation: PROC[ shhh: SHHH _ none, credentials: Credentials, state: Thrush.StateInConv_$initiating, urgency: Thrush.CallUrgency_NIL, -- $normal alertKind: Thrush.AlertKind_NIL, -- $standard subject: Thrush.ROPE_NIL ] RETURNS [ nb: NB, convEvent: Thrush.ConvEvent ]; Alert: PROC[ shhh: SHHH _ none, credentials: Credentials, calledPartyID: PartyID_nullID, comment: ROPE_NIL ] RETURNS [nb: NB ]; Advance: PROC[ shhh: SHHH _ none, credentials: Credentials, state: Thrush.StateInConv, reportToAll: BOOL_FALSE, reason: Thrush.Reason_NIL, -- wontSay comment: ROPE_NIL ] RETURNS [nb: NB, convEvent: Thrush.ConvEvent ]; ConversationInfo: TYPE = RECORD [ subject: ROPE_NIL, urgency: Thrush.CallUrgency_NIL, alertKind: Thrush.AlertKind_NIL, startTime: BasicTime.GMT_TRASH, conferenceHost: Thrush.Machine_TRASH, numParties: NAT_TRASH, numActive: NAT_TRASH, numIdle: NAT_TRASH, originator: Thrush.PartyID _ TRASH ]; GetConversationInfo: PROC [ shh: SHHH_none, convID: ConversationID ] RETURNS [ nb: NB, -- one of $success, $noSuchConv cInfo: ConversationInfo ]; PartyInfo: TYPE = REF PartyInfoSeq; PartyInfoSeq: TYPE = RECORD [ numParties: NAT_0, -- 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 name: Thrush.ROPE_NIL, -- 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 }; GetPartyInfo: PROC [ shh: SHHH_none, credentials: Credentials, nameReq: NameReq_$current, allParties: BOOL_FALSE -- IF FALSE, just calling party; else all parties, calling party first ] RETURNS [ nb: NB, -- one of $success, $noSuchConv, $noSuchParty, $notInConv pInfo: PartyInfo ]; 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]; GetParty: PROC[ shh: SHHH_none, partyID: PartyID, rName: ROPE_NIL, type: Thrush.PartyType_NIL ] RETURNS [nb: NB, newPartyID: PartyID]; GetPartyFromNumber: PROC[ shh: SHHH_none, partyID: PartyID, phoneNumber: Thrush.ROPE_NIL, description: ROPE_NIL ] RETURNS [nb: NB, newPartyID: PartyID]; GetPartyFromFeepNum: PROC[ shh: SHHH_none, partyID: PartyID, feepNum: Thrush.ROPE_NIL ] RETURNS [nb: NB, newPartyID: PartyID]; GetCurrentParty: PROC[shh: SHHH_none, smartsID: SmartsID] RETURNS [nb: NB, partyID: Thrush.PartyID]; GetNumbersForRName: PROC[shh: SHHH_none, rName: ROPE] RETURNS [fullRName: ROPE, number: ROPE, homeNumber: ROPE]; Register: PROC[ shh: SHHH_none, rName: ROPE_NIL, type: Thrush.PartyType_ $individual, clonePartyID: PartyID _ nullID, interface: SmartsInterfaceName, properties: SmartsProperties ] RETURNS [ nb: NB, credentials: Credentials ]; CheckIn: PROC[shh: SHHH_none, credentials: Credentials] RETURNS [nb: NB]; Deregister: PROC[shh: SHHH_none, smartsID: SmartsID] RETURNS [nb: NB]; Enable: PROC[shh: SHHH_none, smartsID: SmartsID] RETURNS [nb: Thrush.NB]; Disable: PROC[shh: SHHH_none, smartsID: SmartsID] RETURNS [nb: Thrush.NB]; }. ,"ThParty.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last modified by Swinehart, December 17, 1985 12:43:02 pm PST Parties and Conversations Definitions 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. ConvEvent will be reported to alerted party, not us; if this fails, give up on the call. 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). 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 Information about the conversation as a whole lastTime: BasicTime.GMT_TRASH, -- Time of last state transition, any party Readily-available (and not too big) information about the conversation Socket numbers and host names for each of the voice terminals in this conversation; own entry, if any, comes first. stateID: Thrush.StateID_TRASH, -- last transition. lastTime: BasicTime.GMT_TRASH, -- of last transition $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. Information about the parties (or just one party) in a conversation Credentials should have either a ConversationID or PartyID or both; other fields irrelevant. GetPartyInfo[nameReq: $current, allParties: FALSE] replaces GetRname. GetPartyInfo[nameReq: $description, allParties: FALSE] replaces DescribeParty 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. <> 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. 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. 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. 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. 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 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. 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. Identification of party -- requires either: Description of party Or ID of party to replicate (used to provide multiple instances of services) Identification of smarts implementation -- requires either: RPC Interface allowing an instance to be imported Or Local Interface record matching that produced by RPC -- see ThPartyPrivate.RegisterLocal Kind of Smarts being registered, and from what host nb will indicate something about what went wrong if anything did; if nb=$success, credentials contains the resulting PartyID and SmartsID. 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. nb will be noSuchSmarts or success, or something else (which implies things are confused) 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. 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 Ê T˜Jšœ ™ Jšœ Ïmœ1™JšÏb œ«™¸Jš  œ•™ŸJ™—J˜—™™ JšœÍ™ÍJ™€J™Jš œÊ œv  œ™„J™Jš œ,  œ©  œ|™êJ™Jš œ—™žJ™Jš œ!žœ[žœYžœ- œ³™ÊJ˜—šÏnœžœ˜Jšœžœ˜J˜J˜&JšœžœŸ ˜+JšœžœŸ ˜-Jšœžœž˜Jšœžœžœ ˜2J˜—š¡œžœ˜ Jšœžœ˜J˜J˜Jšœ žœž˜šœžœžœ˜JšœX™X—J˜—š¡œžœ˜Jšœžœ˜J˜J˜šœ žœžœ˜Jšœžœ)žœu™ª—J˜JšœžœŸ ˜%Jšœ žœž˜Jšœžœžœ ˜1J˜——šœ ™ š¡œžœ™Jšœžœ™JšœŸ™6JšœŸ™;J™Jšœžœ ™J™—š¡ œžœ™Jšœžœ™J™Jš œžœžœ(žœžœ™RJšœ žœ–ž™¦J™——šœ™šœžœžœ˜!J™-Jšœ žœžœ˜Jšœžœ˜ Jšœžœ˜ Jšœž œ˜Jšœžœ˜%Jšœ žœžœ˜Jšœ žœžœ˜Jšœ žœžœ˜Jšœž˜"JšœžœžœŸ+™JJ˜J˜—š¡œžœžœ˜Dšžœ˜ J™FJšœžœŸ˜(Jšœ˜J˜J˜——šœ žœžœ˜#J™s—šœžœžœ˜Jšœ žœŸ+˜>JšœžœŸ%˜KJšœ žœžœžœ˜+J˜—šœžœžœ˜Jšœ˜Jšœžœ˜Jšœž œŸ$˜IJšœžœŸ™2JšœžœžœŸ™4Jšœ žœžœŸ1˜HJšœ ž œ˜Jšœ ž œ˜Jšœ ž ˜JšœžœŸ>˜]J˜—šœ žœžœŸ7˜MJ™¢J™xJšœZ™ZJ™~J˜—š¡ œžœ˜Jšœžœ˜Jšœ˜Jšœ˜Jšœ žœžœŸF˜]Jšœ˜šžœ˜ J™CJ™\JšœžœŸ9˜BJšœ˜J˜—J™Ešœ0žœ™MJ˜——š¡ œžœžœ!˜>šžœ˜ JšœžœŸ9˜BJšœ˜J˜—J˜—š¡ œžœ+˜>Jšžœžœžœ˜*J˜—š¡œžœžœ™AJ™Í—J™—™J™š¡ œžœ™Jšœžœ™Jšœ™J™SJšœ™Jšžœžœ™J™¯—J™š¡œžœ™Jšœžœ™Jšœ™J™$J™]Jšœ™Jšžœžœ žœ$™BJ™—š¡ œžœ™Jšœžœ™Jšœ™J™J™Jšžœžœ™'—J™—šœÏs8™UJ™š¡œžœ™Jšœžœ™Jšœ™JšœŸ/™MJšœ™Jšžœžœ™—J™—™J˜™ ™TJ™8J™BJ™8J™_—J™ÑJ™—J˜š¡œžœ˜Jšœžœ žœžœ˜2Jšœž˜Jšœžœžœ˜(J™ØJšžœžœK™VJ™s—J˜š¡œžœ˜Jšœžœ˜Jšœ˜Jšœžœžœžœž˜3Jšœžœžœ˜(J™‹J˜—š¡œžœ˜Jšœžœ˜Jšœ˜Jšœžœž˜Jšœžœžœ˜(Jšœþ™þJ˜—š¡œžœžœ˜9Jšžœžœ˜*J™ÇJ˜——™$J™š¡œžœžœžœ˜5Jšžœ žœ žœžœ˜:Jšœ žœ™"—J™—™)J™™ JšœÕ™ÕJšœž™ž™J™J™¢J™î——J˜š¡œžœ˜Jšœžœ˜™+™Jšœžœžœ˜J˜$—™LJ˜——™;™1Jšœ˜—J™[—™3J˜—Jšœžœ˜ šœžœ˜#J™QJ™8——J˜š ¡œžœžœ!žœžœ˜IJ™±J˜—š ¡ œžœžœžœžœ˜FJ™Y—J˜š¡œžœžœ˜0Jšžœ žœ˜J™——J˜š¡œžœžœ˜1Jšžœ žœ˜J™C—J˜—J˜J˜J˜code™'K™ K™v—™*K™;Kšœ Ïr™™¥—K™K™™*K™&Kšœ £"™.—K™—…—8G®