DIRECTORY
BasicTime USING [ GMT, nullGMT ],
Lark USING [ KeyTable],
LarkPlay USING [ ToneSpec],
MBQueue USING [ Queue ],
Pup USING [ nullSocket, Socket ],
PupSocket USING [ Socket ],
RefID USING [ ID ],
Thrush USING [ AlertKind, CallUrgency, ConversationID, ConvEvent, Credentials, InterfaceSpec, NetAddress, NB, none, nullConvID, nullID, PartyID, PartyType, Reason, ROPE, SHHH, SmartsID, StateID, StateInConv ],
ThParty USING [ NameReq, SmartsInterfaceRecord, SmartsProperties ]
;
Definitions
PartyData: data representing an individual, trunk, or voice recording within Thrush
PartyData: TYPE = REF PartyBody;
PartyBody:
TYPE =
RECORD [
type: Thrush.PartyType←, -- Must be specified.
numConvs: NAT ← 0,
enabled: BOOL←FALSE, -- must be TRUE for party to be visible to anybody.
partyActive: BOOL ← FALSE, -- if TRUE, party is active in exactly one conversation
partyEngaged: Thrush.ConversationID ← Thrush.nullConvID, -- if non-null, party has its associated voice hardware in use on behalf of this conversation
name: Thrush.
ROPE,
For services, this is set to the rName of the reserving party.
For trunks, this is set to the rName or other description of the called party; for other parties, this is the rName of the individual the party represents.
Fields used by trunk parties
outgoing: Thrush.ROPE ← NIL, -- *
reservedBy: Thrush.PartyID ← NULL, -- **
reservationTime: BasicTime.GMT ← BasicTime.nullGMT, -- ***
Registered Service action interfaces
actionInterfaces: LIST OF REF Thrush.InterfaceSpec ← NIL -- *
];
* Set at GetParty time to called party number. This number is just what's needed to complete the call, with all alternatives removed. *x* in the number indicates the need for a pause of x 100 ms ticks.
** Since GetParty custom-tailors a trunk party for the specific outgoing call before initiating a conversation, need a way to make sure that the same party does start the conversation. This field is also used to reserve a service party for a time before the party enters a conversation.
*** This is the time at which a service party is reserved through a call to GetParty. The reservation is honored (the party isn't assigned to another caller, even though it is idle) for some reasonable amount of time, to allow the reserving client to engage it in a conversation.
SmartsData: TYPE=REF SmartsBody;
Implementors say SmartsBody: PUBLIC TYPE=ThPartyPrivate.SmartsBody;
SmartsBody:
TYPE =
RECORD [
properties: ThParty.SmartsProperties,
type: Thrush.PartyType←$telephone,
interface: ThParty.SmartsInterfaceRecord, -- an RPC or direct interface
shh: Thrush.SHHH, -- outgoing encryption handle; should be one for each Party-Smarts pair? For now, callee in shh is RName associated of Party that creates smarts.
notifications: MBQueue.Queue, -- pending party->smarts notifications
pupSocket: PupSocket.Socket ←
NIL,
Explanation: Cedar now demands that non-well-known socket id's be assigned by the communications package. Multicast conference-listening demands that the socket id of the transmitting party be used as a listening id at all other parties. So that Bluejay can listen to Larks, we have to assign all actual socket id's in Thrush, by generating a socket for each smarts. This value will be re-used for every conversation. This value is also extracted into the socket field of properties. We must provide a function for extracting the actual PupSocket field from a smarts. This design demands that BluejaySmarts reside in the Thrush server machine. During the next interface party, Hal indicated we should include a range of socket numbers that clients can assign. Then some of this could get less awful.
failed: BOOL← FALSE, -- when TRUE, smarts has already been deregistered and will vanish when last report has been made.
enablesParty: BOOL ← FALSE -- when TRUE, we're contributing to party.numEnabled
];
ConversationData: TYPE = REF ConversationBody;
ConversationBody:
TYPE =
RECORD [
convID: Thrush.ConversationID←NULL,
subject: Thrush.ROPE ← NIL,
urgency: Thrush.CallUrgency←NIL,
alertKind: Thrush.AlertKind←NIL,
timeOfID: BasicTime.GMT, -- time of last report to anyone
startTime: BasicTime.GMT,
conferenceHost: Thrush.NetAddress←[[0],[0], Pup.nullSocket],
keyTable: Lark.KeyTable ← NIL, -- current key table for this conversation
keyUses: ARRAY [0..20B) OF INT ← ALL[0], -- use counts for key table
cStateBilateral: ConvState ← NIL, -- if non-NIL, a ConvState that is asserting a restriction to a bilateral conversation
numParties: NAT𡤀,
numActive: NAT𡤀,
numIdle: NAT𡤀,
numReportsOut: NAT𡤀 -- reports scheduled but not completed
];
ConvState:
TYPE =
REF ConvStateBody;
The state of a party in a conversation
ConvStateBody:
TYPE =
RECORD [
state: Thrush.StateInConv ← $neverWas,
stateID: Thrush.StateID ← 0,
intendedPartyID: Thrush.PartyID ← Thrush.nullID,
If non-null, party for whom call was originally intended. Another party may have eventually fielded it due either to forwarding or "visiting".
time: BasicTime.GMT←NULL
];
outsideRingTune: LarkPlay.ToneSpec;
Procedures
MakeServiceRname:
PROC[serviceName: Thrush.
ROPE]
RETURNS [serviceRname: Thrush.ROPE, serviceRnameAtom: ATOM];
Service Name is the formal descriptor of one of the voice services, such as "Recording", "Text-to-Speech", and so on. The result is "idle.<serviceName>.Lark", as a ROPE and as a corresponding ATOM. This is a procedure because the service name is stored, but several clients need the atom or rope values.
GetCurrentParty:
PROC[shh: Thrush.
SHHH←Thrush.none, smartsID: Thrush.SmartsID]
RETURNS [nb: Thrush.NB, partyID: Thrush.PartyID];
RegisterLocal:
PROC[
shh: Thrush.SHHH←Thrush.none,
Can't combine with ThParty.Register, because RPC complains about interfaceRecord param.
Description of party
rName: Thrush.ROPE←NIL,
type: Thrush.PartyType← $individual,
Or ID of party to replicate (used to provide multiple instances of services)
clonePartyID: Thrush.PartyID←Thrush.nullID,
Identification of smarts implementation -- requires either:
RPC Interface allowing an instance to be imported
See ThParty.Register
Or Local Interface record matching that produced by RPC
interfaceRecord: ThParty.SmartsInterfaceRecord ← NIL,
Optional pre-allocated smartsID (see LarkSmartsInitImpl),
smartsID: Thrush.SmartsID ← Thrush.nullID,
Kind of Smarts being registered, and from what host
properties: ThParty.SmartsProperties
] RETURNS [
nb: Thrush.
NB, credentials: Thrush.Credentials ];
nb will indicate something about what went wrong if anything did; if nb=$success,
credentials contains the resulting PartyID and SmartsID.
AssignSmartsID:
PROC
RETURNS [smartsID: Thrush.SmartsID];
It's not good for anything until supplied to RegisterLocal, but it's a way to get a SmartsID before registration time.
DoDescribeParty:
PROC[party: ThPartyPrivate.PartyData, nameReq: ThParty.NameReq]
RETURNS[ description: Thrush.ROPE ];
GetRnameFromParty:
PROC[party: ThPartyPrivate.PartyData, nameReq: ThParty.NameReq←$current]
RETURNS[ nb: Thrush.NB, rName: Thrush.ROPE←NIL, rAtom: ATOM←NIL ];
DoAdvance:
PROC [
credentials: Thrush.Credentials,
intendedPartyID: Thrush.PartyID ← Thrush.nullID,
state: Thrush.StateInConv,
reportToAll: BOOL←FALSE,
reason: Thrush.Reason←NIL,
comment: Thrush.ROPE←NIL,
newInConv: BOOL, -- if TRUE, party must not be in the conversation yet . . . and vice versa
bilateral: BOOL←FALSE,
checkConflict: BOOL←FALSE
] RETURNS [nb: Thrush.NB, convEvent: Thrush.ConvEvent];
AlertOne:
PROC[
credentials: Thrush.Credentials,
calledPartyID: Thrush.PartyID,
intendedPartyID: Thrush.PartyID←Thrush.nullID
] RETURNS [ nb: Thrush.NB ];
GetConvState: PROC[ conv: ConversationData, party: PartyData, createOK: BOOL←FALSE] RETURNS [convState: ConvState←NIL];
SetPoaching:
PROC[party: PartyData, callingParty: PartyData←
NIL];
If party.type = $individual, computes and records the identity of the party's current voice terminal. callingParty may be supplied to allow for the caller's trunk party to be used if no other suitable voice terminal is found. See the implementation.
MakeSubstitution:
PROC[oldParty: PartyData, newParty: PartyData];
If both parties exist, either a poacher is arriving or leaving. In either case, the oldParty might be involved in conversations that the new party should inherit. Arrange for that here.
GetPupSocket:
PROC[partyID: Thrush.PartyID]
RETURNS [PupSocket.Socket];
See earlier discussion about sockets. This gets the socket from the $voiceTerminal smarts associated with the specified party. If any.
VoiceParty: PROC[party: PartyData] RETURNS [voiceParty: PartyData ];
EngageParty:
PROC[
party: PartyData, convID: Thrush.ConversationID, doEngage: BOOL, test: BOOL←FALSE]
RETURNS [nb: Thrush.NB←$success];
Either reserve (doEngage=TRUE) or release (FALSE) the "use of hardware" condition for this party with respect to this conversation; just test success test=TRUE
Release only if the party is currently engaged with respect to the same conversation.
Engage only if the party (and its $Other[party] partner) are not engaged in some other conversation. This replaces earlier "backdoor/frontdoor conflict" mechanisms.
These actions are determined by the current state of VoiceParty[party]; if party is a poacher, it then inherits the state of its VoiceParty.
May have to produce a semantics for what to do when convID is null; test only?
PollSpec: TYPE = REF PollSpecBody;
PollSpecBody: TYPE= RECORD [smarts: SmartsData, partyID: Thrush.PartyID, reason: Thrush.Reason, nextScheduledCheck: INT];
DoPoll:
PROC[r:
REF];
See ThPartyOpsImpl.PartyPoller for examples of use; checks in with Smarts at Party creation, party deletion, and at periodic intervals, specifying which event it is.
}.
Swinehart, October 25, 1985 5:52:58 pm PDT
Handle => ID (RefID's)
changes to: DIRECTORY, nullID, PartyBody, ConversationBody, CFRec, GetCurrentParty, GetPartySmarts, GetStdRingInfo, SetStdRingInfo, FindOtherParty, DoDescribeParty, DoAdvance, RegisterLocal, DehandleConv, DehandleParty, DehandleSmarts