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, 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
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
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←$success, partyID: Thrush.PartyID←Thrush.nullID];
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,
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.
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
] RETURNS [nb: Thrush.NB, convEvent: Thrush.ConvEvent];
AlertOne:
PROC[
credentials: Thrush.Credentials,
calledPartyID: Thrush.PartyID,
intendedPartyID: Thrush.PartyID←Thrush.nullID
] RETURNS [ nb: Thrush.NB, calledParty: PartyData←NIL ];
GetConvState: PROC[ conv: ConversationData, party: PartyData, createOK: BOOL←FALSE] RETURNS [convState: ConvState←NIL];
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.
UnvisitInternal:
PROC[visitingParty: Thrush.PartyID];
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.
}.
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
Swinehart, November 7, 1985 11:57:15 am PST
Remove several fields from these data structures, move socket ID to ConversationBody, modify CFRef.
changes to: SmartsBody, ConversationBody, CFRec, outsideRingTune