ThPartyClientImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Swinehart, July 18, 1987 5:04:47 pm PDT
Automatic connection management for ThPartyRpcClientImpl.mesa
This is something Lupine could generate automatically. Better still, StartCall could include these capabilities. In that case, failures would have to be reported through errors, probably.
DIRECTORY
FinchSmarts USING [ FinchInfo, pd, Problem, ReportSystemStateProc ],
GVBasics USING [ Password ],
IO,
MBQueue USING [ QueueClientAction ],
NameDB USING [ Error, GetAttribute ],
ThPartyRpcControl,
RefID USING [ ID ],
Rope USING [ ROPE ],
RPC,
RPCLupine,
ThParty,
Thrush USING [ ActionReport, AlertKind, CallUrgency, ConvEvent, ConversationID, EncryptionKey, KeyTable, InterfaceSpec, PartyID, PartyType, SmartsID, nullID, Credentials, NB, Reason, ROPE, SHHH, StateInConv, unencrypted ],
ThVersions USING [ GetThrushVR, ThrushVersion ],
VoiceUtils USING [ NetAddress, NetAddressFromRope, OwnNetAddress, Problem ]
;
ThPartyClientImpl: CEDAR MONITOR
IMPORTS FinchSmarts, IO, MBQueue, NameDB, RealControl: ThPartyRpcControl, RealThParty: ThParty, RPC, ThVersions, VoiceUtils
EXPORTS FinchSmarts, ThParty = {
OPEN IO, pd: FinchSmarts.pd, ThParty;
Global data
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;
SmartsProperties: TYPE=ThParty.SmartsProperties;
SmartsRole: TYPE= ThParty.SmartsRole; -- { $voiceTerminal, $controller, ? };
myInfo: FinchSmarts.FinchInfo ← NIL;
unexpected: ROPE ← "Unexpected server failure";
Protected versions of ThParty Procedures
CreateConversation: PUBLIC ENTRY PROC[
shhh: SHHH,
credentials: Credentials,
state: Thrush.StateInConv,
urgency: Thrush.CallUrgency,
alertKind: Thrush.AlertKind,
reason: Thrush.Reason,
comment: ROPE,
subject: Thrush.ROPE,
checkConflict: BOOL
] RETURNS [ nb: NB, convEvent: Thrush.ConvEvent ] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
credentials.partyID ← myInfo.partyID;
credentials.smartsID ← myInfo.smartsID;
[nb, convEvent] ← RealThParty.CreateConversation[shhh, credentials, state, urgency, alertKind, reason, comment, subject, checkConflict];
SELECT nb FROM $noSuchParty, $noSuchSmarts => nb ← Quit[nb, unexpected]; ENDCASE;
};
CreateConversation.nb~$success
CreateConversation.nb~$voiceTerminalBusy -- checkConflict only
CreateConversation.Verify.nb~~$noSuchSmarts
CreateConversation.Verify.nb~~$noSuchParty
CreateConversation.nb~$<unexpectedErrors>
CreateConversation.nb~$serverDown
CreateConversation.nb~$notEnabled
Alert: PUBLIC ENTRY PROC[
shhh: SHHH,
credentials: Credentials,
calledPartyID: PartyID,
comment: ROPE
] RETURNS [nb: NB ] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
credentials.partyID ← myInfo.partyID;
credentials.smartsID ← myInfo.smartsID;
nb ← RealThParty.Alert[shhh, credentials, calledPartyID, comment];
SELECT nb FROM $noSuchParty, $noSuchSmarts => nb ← Quit[nb, unexpected]; ENDCASE;
};
Alert.nb~$success
Alert.nb~$narcissism
Alert.nb~$alreadyInConv
Alert.nb~$noSuchParty2
Alert.Verify.nb~~$noSuchSmarts
Alert.Verify.nb~~$noSuchParty
Alert.Verify.nb~~$noSuchConv
Alert.Verify.nb~~$notInConv
Alert.Verify.nb~~$stateMismatch
Alert.Verify.nb~~$interfaceError
Alert.DoAdvance.nb~~$convIdle
Alert.nb~$<unexpectedErrors>
Alert.nb~$serverDown
Alert.nb~$notEnabled
Advance: PUBLIC ENTRY PROC[
shhh: SHHH,
credentials: Credentials,
state: Thrush.StateInConv,
reportToAll: BOOL,
reason: Thrush.Reason,
comment: ROPE,
bilateral: BOOL,
checkConflict: BOOL
] RETURNS [nb: NB, convEvent: Thrush.ConvEvent ] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
credentials.partyID ← myInfo.partyID;
credentials.smartsID ← myInfo.smartsID;
[nb, convEvent] ←
RealThParty.Advance[shhh, credentials, state, reportToAll, reason, comment, bilateral, checkConflict];
SELECT nb FROM $noSuchParty, $noSuchSmarts => nb ← Quit[nb, unexpected]; ENDCASE;
};
Advance.nb~$success
Advance.nb~$convIdle
Advance.nb~$bilateralConv -- $active only
Advance.nb~$conferenceConv -- $active only
Advance.nb~$voiceTerminalUnavailable -- $active only
Advance.nb~$voiceTerminalBusy -- hardware-requiring states only
Advance.Verify.nb~~$noSuchSmarts
Advance.Verify.nb~~$noSuchParty
Advance.Verify.nb~~$noSuchConv
Advance.Verify.nb~~$notInConv
Advance.Verify.nb~~$stateMismatch
Advance.Verify.nb~~$interfaceError
Advance.nb~$serverDown
Advance.nb~$notEnabled
ReportAction: PUBLIC ENTRY PROC[
shhh: SHHH,
report: Thrush.ActionReport,
reportToAll: BOOL,
selfOnCompletion: BOOL
] RETURNS [nb: NB, numReportsIssued: NAT] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
report.other.partyID ← myInfo.partyID;
report.other.smartsID ← myInfo.smartsID;
[nb, numReportsIssued] ← RealThParty.ReportAction[shhh, report, reportToAll, selfOnCompletion];
SELECT nb FROM $noSuchParty, $noSuchSmarts => nb ← Quit[nb, unexpected]; ENDCASE;
};
ReportAction.nb~$success
ReportAction.Verify.nb~~$noSuchSmarts
ReportAction.Verify.nb~~$noSuchParty
ReportAction.Verify.nb~~$noSuchConv
ReportAction.Verify.nb~~$notInConv
ReportAction.Verify.nb~~$stateMismatch
ReportAction.Verify.nb~~$interfaceError
ReportAction.nb~$serverDown
ReportAction.nb~$notEnabled
GetConversationInfo: PUBLIC ENTRY PROC [ shh: SHHH, convID: ConversationID ]
RETURNS [
nb: NB,
cInfo: ConversationInfo
] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
[nb, cInfo] ← RealThParty.GetConversationInfo[shh, convID];
};
GetConversationInfo.nb~$success
GetConversationInfo.nb~$noSuchConv
GetConversationInfo.nb~$serverDown
GetConversationInfo.nb~$notEnabled
GetPartyInfo: PUBLIC ENTRY PROC [
shh: SHHH←none,
credentials: Credentials,
nameReq: NameReq,
allParties: BOOLFALSE
]
RETURNS [nb: NB, pInfo: PartyInfo] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
credentials.partyID ← myInfo.partyID;
credentials.smartsID ← myInfo.smartsID;
[nb, pInfo] ← RealThParty.GetPartyInfo[shh, credentials, nameReq, allParties];
};
GetPartyInfo.nb~$success
GetPartyInfo.nb~$noSuchConv
GetPartyInfo.nb~$noSuchParty
GetPartyInfo.nb~$notInConv
GetPartyInfo.nb~$serverDown
GetPartyInfo.nb~$notEnabled
DescribeParty: PUBLIC ENTRY PROC[partyID: Thrush.PartyID, nameReq: NameReq]
RETURNS[nb: NB, description: Thrush.ROPE, type: Thrush.PartyType,
partner: Thrush.PartyID, visitee: Thrush.PartyID,
visitors: LIST OF Thrush.PartyID
] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
[nb, description, type, partner, visitee, visitors] ← RealThParty.DescribeParty[partyID, nameReq];
};
DescribeParty.nb~$success
DescribeParty.GetRnameFromParty.nb~$noSuchParty
DescribeParty.GetRnameFromParty.nb~$noNameAvailable
DescribeParty.nb~$serverDown
DescribeParty.nb~$notEnabled
RegisterServiceInterface: PUBLIC ENTRY PROC[
shhh: SHHH,
credentials: Credentials,
interfaceSpecPattern: Thrush.InterfaceSpec
] RETURNS[nb: NB, interfaceSpec: Thrush.InterfaceSpec] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
credentials.partyID ← myInfo.partyID;
credentials.smartsID ← myInfo.smartsID;
[nb, interfaceSpec] ← RealThParty.RegisterServiceInterface[shhh, credentials, interfaceSpecPattern];
SELECT nb FROM $noSuchParty, $noSuchSmarts => nb ← Quit[nb, unexpected]; ENDCASE;
};
RegisterServiceInterface.nb~$success
Verify.nb~$noSuchParty
RegisterServiceInterface.nb~$serverDown
RegisterServiceInterface.nb~$notEnabled
LookupServiceInterface: PUBLIC ENTRY PROC[
shhh: SHHH,
credentials: Credentials,
serviceParty: PartyID,
type: RPC.ShortROPE
] RETURNS[nb: NB, interfaceSpec: Thrush.InterfaceSpec] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
credentials.partyID ← myInfo.partyID;
credentials.smartsID ← myInfo.smartsID;
[nb, interfaceSpec] ← RealThParty.LookupServiceInterface[shhh, credentials, serviceParty, type];
SELECT nb FROM $noSuchParty, $noSuchSmarts => nb ← Quit[nb, unexpected]; ENDCASE;
};
LookupServiceInterface.nb~$success
LookupServiceInterface.nb~$noSuchParty2
LookupServiceInterface.nb~$noSuchInterface
LookupServiceInterface.nb~$serverDown
LookupServiceInterface.nb~$notEnabled
RegisterKey: PUBLIC ENTRY PROC[
shh: SHHH,
credentials: Credentials,
key: Thrush.EncryptionKey,
reportNewKeys: BOOL
] RETURNS [ nb: NB, keyIndex: [0..17B] ] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
credentials.partyID ← myInfo.partyID;
credentials.smartsID ← myInfo.smartsID;
[nb, keyIndex] ← RealThParty.RegisterKey[shh, credentials, key, reportNewKeys];
SELECT nb FROM $noSuchParty, $noSuchSmarts => nb ← Quit[nb, unexpected]; ENDCASE;
};
RegisterKey.nb~$success
RegisterKey.nb~$newKeys
RegisterKey.Verify.nb~~$noSuchSmarts
RegisterKey.Verify.nb~~$noSuchParty
RegisterKey.Verify.nb~~$noSuchConv
RegisterKey.Verify.nb~~$notInConv
RegisterKey.Verify.nb~~$interfaceError
RegisterKey.nb~$serverDown
RegisterKey.nb~$notEnabled
GetKeyTable: PUBLIC ENTRY PROC [ shh: SHHH, credentials: Credentials ]
RETURNS [ nb: NB, keyTable: Thrush.KeyTable ] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
credentials.partyID ← myInfo.partyID;
credentials.smartsID ← myInfo.smartsID;
[nb, keyTable] ← RealThParty.GetKeyTable[shh, credentials];
SELECT nb FROM $noSuchParty, $noSuchSmarts => nb ← Quit[nb, unexpected]; ENDCASE;
};
GetKeyTable.nb~$success
GetKeyTable.Verify.nb~~$noSuchSmarts
GetKeyTable.Verify.nb~~$noSuchParty
GetKeyTable.Verify.nb~~$noSuchConv
GetKeyTable.Verify.nb~~$notInConv
GetKeyTable.Verify.nb~~$interfaceError
GetKeyTable.nb~$serverDown
GetKeyTable.nb~$notEnabled
UnregisterKey: PUBLIC ENTRY PROC[
shh: SHHH,
credentials: Credentials,
key: Thrush.EncryptionKey
] RETURNS [ nb: NB ] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
credentials.partyID ← myInfo.partyID;
credentials.smartsID ← myInfo.smartsID;
[nb] ← RealThParty.UnregisterKey[shh, credentials, key];
SELECT nb FROM $noSuchParty, $noSuchSmarts => nb ← Quit[nb, unexpected]; ENDCASE;
};
UnregisterKey.nb~$success
UnregisterKey.Verify.nb~~$noSuchSmarts
UnregisterKey.Verify.nb~~$noSuchParty
UnregisterKey.Verify.nb~~$noSuchConv
UnregisterKey.Verify.nb~~$notInConv
UnregisterKey.Verify.nb~~$interfaceError
UnregisterKey.nb~$serverDown
UnregisterKey.nb~$notEnabled
GetParty: PUBLIC ENTRY PROC[
shh: SHHH, partyID: PartyID, rName: ROPE,
type: Thrush.PartyType
] RETURNS [nb: NB, newPartyID: PartyID] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
partyID ← myInfo.partyID;
[nb, newPartyID] ← RealThParty.GetParty[shh, partyID, rName, type];
SELECT nb FROM $noSuchParty => nb ← Quit[nb, unexpected]; ENDCASE;
};
GetParty.nb~$success
GetParty.nb~$noIdentSupplied
GetParty.nb~$noSuchParty2
GetParty.nb~$noSuchParty
GetParty.GetRelatedParty.nb~~$voiceTerminalBusy
GetParty.GetRelatedParty.nb~~$convStillActive
GetParty.GetIdleParty/GetRnameFromParty.nb~~$noNameAvailable
GetParty.nb~$serverDown
GetParty.nb~$notEnabled
GetPartyFromNumber: PUBLIC ENTRY PROC[
shh: SHHH,
partyID: PartyID,
phoneNumber: Thrush.ROPE, description: ROPE
] RETURNS [nb: NB, newPartyID: PartyID] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
partyID ← myInfo.partyID;
[nb, newPartyID] ← RealThParty.GetPartyFromNumber[shh, partyID, phoneNumber];
SELECT nb FROM $noSuchParty => nb ← Quit[nb, unexpected]; ENDCASE;
};
GetPartyFromNumber.nb~$success
GetPartyFromNumber.nb~$noSuchParty
GetPartyFromNumber.GetRelatedParty.nb~~$voiceTerminalBusy
GetPartyFromNumber.GetRelatedParty.nb~~$noSuchParty2
GetPartyFromNumber.GetRelatedParty.nb~~$convStillActive
GetPartyFromNumber.GetRnameFromParty.nb~~$noNameAvailable
GetPartyFromNumber.nb~$serverDown
GetPartyFromNumber.nb~$notEnabled
GetPartyFromFeepNum: PUBLIC ENTRY PROC[
shh: SHHH,
partyID: PartyID,
feepNum: Thrush.ROPE
] RETURNS [nb: NB, newPartyID: PartyID] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
partyID ← myInfo.partyID;
[nb, newPartyID] ← RealThParty.GetPartyFromFeepNum[shh, partyID, feepNum];
SELECT nb FROM $noSuchParty => nb ← Quit[nb, unexpected]; ENDCASE;
};
GetPartyFromFeepNum.nb~$success
GetPartyFromFeepNum.nb~$noSuchParty2
GetPartyFromFeepNum.GetActiveParty.nb~~$noIdentSupplied
GetPartyFromFeepNum.GetActiveParty.nb~~$noSuchParty2
GetPartyFromFeepNum.GetActiveParty.nb~~$noSuchParty
GetPartyFromFeepNum.GetRelatedParty.nb~~$voiceTerminalBusy
GetPartyFromFeepNum.GetRelatedParty.nb~~$convStillActive
GetPartyFromFeepNum.GetIdleParty/GetRnameFromParty.nb~~$noNameAvailable
GetPartyFromFeepNum.nb~$serverDown
GetPartyFromFeepNum.nb~$notEnabled
GetCurrentParty: PUBLIC ENTRY PROC[shh: SHHH, smartsID: SmartsID]
RETURNS [nb: NB, partyID: Thrush.PartyID] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
smartsID ← myInfo.smartsID;
[nb, partyID] ← RealThParty.GetCurrentParty[shh, smartsID];
SELECT nb FROM $noSuchSmarts => nb ← Quit[nb, unexpected]; ENDCASE;
};
GetCurrentParty.nb~$success
GetCurrentParty.nb~$noSuchSmarts
GetCurrentParty.nb~$noSuchParty
GetCurrentParty.nb~$serverDown
GetCurrentParty.nb~$notEnabled
ReleaseParty: PUBLIC ENTRY PROC[shh: SHHH, partyID: PartyID, targetPartyID: PartyID]
RETURNS [nb: NB] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
partyID ← myInfo.partyID;
[nb] ← RealThParty.ReleaseParty[shh, partyID, targetPartyID];
};
ReleaseParty.nb~$success
ReleaseParty.nb~$serverDown
ReleaseParty.nb~$notEnabled
GetNumbersForRName: PUBLIC ENTRY PROC[shh: SHHH←none, rName: ROPE]
RETURNS [fullRName: ROPE←NIL, number: ROPE←NIL, homeNumber: ROPE←NIL] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF PostError[why]=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND PostError[$unbound]#$success THEN RETURN;
[fullRName, number, homeNumber] ← RealThParty.GetNumbersForRName[shh, rName];
};
Register: PUBLIC ENTRY PROC[
shh: SHHH,
rName: ROPE,
type: Thrush.PartyType,
clonePartyID: PartyID,
interface: SmartsInterfaceName,
properties: SmartsProperties
] RETURNS [ nb: NB, credentials: Credentials ] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
[nb, credentials] ← RealThParty.Register[shh, rName, type, clonePartyID, interface, properties];
};
Register.nb~$success
Register.nb~$noIdentSupplied
Register.nb~$couldntAuthenticate
Register.nb~$couldntConnect
Register.GetRnameFromParty.nb~~$noSuchParty -- $clone creation only
Register.GetRnameFromParty.nb~~$noSuchSmarts -- $clone creation only
Register.GetRnameFromParty.nb~~$noNameAvailable -- $clone creation only
Register.CreateParty.nb~~$noIdentSupplied
Register.nb~$serverDown
Register.nb~$notEnabled
CheckIn: PUBLIC ENTRY PROC[shh: SHHH, credentials: Credentials] RETURNS [nb: NB] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
credentials.partyID ← myInfo.partyID;
credentials.smartsID ← myInfo.smartsID;
nb ← RealThParty.CheckIn[shh, credentials];
SELECT nb FROM $noSuchSmarts, $noSuchParty => nb ← Quit[nb, unexpected]; ENDCASE;
};
CheckIn.nb~~$success
CheckIn.nb~~$noSuchParty
CheckIn.nb~~$noSuchSmarts
Deregister: PUBLIC ENTRY PROC[shh: SHHH, smartsID: SmartsID] RETURNS [nb: NB] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
smartsID ← myInfo.smartsID;
nb ← RealThParty.Deregister[shh, smartsID];
SELECT nb FROM $noSuchSmarts, $noSuchParty => nb ← Quit[nb, unexpected]; ENDCASE;
};
Deregister.nb~~$success
Deregister.nb~~$noSuchParty
Deregister.nb~~$noSuchSmarts
Functions called from FinchRegister and FinchDeregister should probably not be implemented here at all. Certainly not protected in this way. When they fail, kaboom!
Enable: PUBLIC ENTRY PROC[shh: SHHH, smartsID: SmartsID]
RETURNS [nb: Thrush.NB] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
smartsID ← myInfo.smartsID;
nb ← RealThParty.Enable[shh, smartsID];
SELECT nb FROM $noSuchParty, $noSuchSmarts => nb ← Quit[nb, unexpected]; ENDCASE;
};
Enable.nb~success
Enable.nb~noSuchSmarts
Enable.nb~noSuchParty
Enable.nb~$serverDown
Enable.nb~$notEnabled
Disable: PUBLIC ENTRY PROC[shh: SHHH, smartsID: SmartsID]
RETURNS [nb: Thrush.NB] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
smartsID ← myInfo.smartsID;
nb ← RealThParty.Disable[shh, smartsID];
SELECT nb FROM $noSuchParty, $noSuchSmarts => nb ← Quit[nb, unexpected]; ENDCASE;
};
Disable.nb~$ See Enable
Visit: PUBLIC ENTRY PROC[shh: SHHH, visitedParty: PartyID, visitingParty: PartyID,
visitingPassword: GVBasics.Password] RETURNS [nb: Thrush.NB] = {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
visitedParty ← myInfo.partyID;
nb ← RealThParty.Visit[shh, visitedParty, visitingParty, visitingPassword];
SELECT nb FROM $noSuchParty => nb ← Quit[nb, unexpected]; ENDCASE;
};
Visit.nb~$success
Visit.nb~$noSuchParty
Visit.nb~$noSuchParty2
Visit.nb~$narcissism
Visit.nb~$visitingIllegal
Visit.nb~$passwordNotValid
Visit.nb~$serverDown
Visit.nb~$notEnabled
Unvisit: PUBLIC ENTRY PROC[shh: SHHH, visitedParty: PartyID, visitingParty: PartyID,
visitingPassword: GVBasics.Password] RETURNS [nb: NB]
= {
ENABLE {
UNWIND => NULL;
RPC.CallFailed => IF (nb←PostError[why])=$success THEN RETRY ELSE CONTINUE;
};
IF (~pd.connected) AND (nb←PostError[$unbound])#$success THEN RETURN;
visitedParty ← myInfo.partyID;
nb ← RealThParty.Unvisit[shh, visitedParty, visitingParty, visitingPassword];
SELECT nb FROM $noSuchParty => nb ← Quit[nb, unexpected]; ENDCASE;
};
Unvisit.nb~$success
Unvisit.nb~$noSuchParty -- Visiting Party ID null or invalid
Unvisit.nb~$noSuchParty2 -- Visitee Party ID null or invalid
Unvisit.nb~$noSuchVisiting -- specified visiting relationship did not hold.
Unvisit.nb~$serverDown
Unvisit.nb~$notEnabled
Import/Unimport
We don't intercept errors here, in case clients want to be careful during initial importing. Later, we do intercept them, catch them, and render them relatively harmless, returning nb=$notRunning or nb=$callFailed if there is an nb arg.
Caller should know that either import might fail, or that NameDB call might fail. If the latter occurs, we won't be enabled.
FinchRegister: PUBLIC ENTRY PROC[
info: FinchSmarts.FinchInfo, interfaceName: RPC.InterfaceName]
RETURNS[nb: NB] = {
ENABLE UNWIND => NULL;
pd.enabled ← TRUE; -- Whether successful or not, a connection is now the desired thing.
myInfo ← info;
pd.connected ← FALSE;
pd.interfaceName ← interfaceName;
nb ← PostError[$unbound];
};
FinchDeregister: PUBLIC ENTRY PROC[info: FinchSmarts.FinchInfo, disable: BOOL] RETURNS [nb: NB←$success] = {
ENABLE UNWIND => NULL;
IF disable THEN pd.enabled ← FALSE;
IF pd.connected AND myInfo=info THEN
nb ← RealThParty.Deregister[myInfo.shh, myInfo.smartsID!RPC.CallFailed=>CONTINUE];
RealControl.UnimportInterface[];
IF ~disable THEN
[]←Quit[$serverDown];
};
PostError, other utilities
PostError: INTERNAL PROC[why: RPC.CallFailure] RETURNS [nb: NB←$success] = {
ENABLE {
RPC.ImportFailed => {
IF why=$wrongVersion THEN {
pd.enabled ← FALSE;
nb ← Quit[$serverDown, IO.PutFR["Finch version %d too old; import failed",
card[ThVersions.ThrushVersion]]];
}
ELSE nb ← Quit[$serverDown,
IO.PutFR["Could not import ThParty (%g)", rope[pd.interfaceName.instance]]];
CONTINUE;
};
RPC.CallFailed => {
nb ← Quit[$serverDown,
IO.PutFR["Could not import ThParty (%g)", rope[pd.interfaceName.instance]]];
CONTINUE;
};
NameDB.Error => {
nb ← Quit[$serverDown,
IO.PutFR["ThParty import db query failed (%g): %g", atom[ec], rope[explanation]]];
CONTINUE;
};
};
hostHint: RPCLupine.RPCHost;
credentials: Thrush.Credentials;
IF ~pd.enabled THEN RETURN[$notEnabled];
SELECT why FROM
$timeout, $busy =>
VoiceUtils.Problem[IO.PutFR["No response from ThParty (%g)", rope[pd.interfaceName.instance]], $Finch];
$runtimeProtocol, $stubProtocol => VoiceUtils.Problem[
"Protocol violation in communications with ThParty database", $Finch];
$unbound => NULL;
ENDCASE=>ERROR;
pd.connected ← FALSE;
hostHint ← VoiceUtils.NetAddressFromRope[
NameDB.GetAttribute[pd.interfaceName.instance, $connect]];
pd.interfaceName.version ← ThVersions.GetThrushVR;
RealControl.ImportInterface[interfaceName: pd.interfaceName, hostHint: hostHint];
[nb, credentials]←RealThParty.Register[
shh: myInfo.shh,
rName: myInfo.myRName,
type: $individual,
interface: myInfo.myName,
properties: [$controller, VoiceUtils.OwnNetAddress[]]
];
IF nb=$success THEN nb ← RealThParty.Enable[shh: myInfo.shh, smartsID: credentials.smartsID];
IF nb#$success THEN { nb ← Quit[nb, "Can't register with server"]; RETURN; };
myInfo.smartsID ← credentials.smartsID;
myInfo.partyID ← credentials.partyID;
pd.connected ← TRUE;
ReportSystemState[];
};
See FinchSmartsImpl.ReportConversationState for dicussion
ReportSystemState: INTERNAL PROC ~ {
IF myInfo=NIL THEN RETURN;
pd.requests.QueueClientAction[ReallyReportSystemState, myInfo];
};
ReallyReportSystemState: PROC [r: REF] ~ {
info: FinchSmarts.FinchInfo ← NARROW[r];
IF info=NIL THEN RETURN;
FOR l: LIST OF FinchSmarts.ReportSystemStateProc ← info.systemStateSubscribers, l.rest UNTIL l=NIL DO
l.first[pd.enabled, pd.connected];
ENDLOOP;
};
QUit: PUBLIC ENTRY PROC[proposedNB: NB, problem: Rope.ROPENIL] RETURNS[nb: NB] = {
RETURN[Quit[proposedNB, problem]];
};
Quit: INTERNAL PROC[proposedNB: NB, problem: Rope.ROPENIL] RETURNS[nb: NB] = {
pd.connected ← proposedNB=$success;
ReportSystemState[];
IF problem#NIL THEN FinchSmarts.Problem[problem, nb];
RETURN[proposedNB];
};
}.
Swinehart, July 14, 1987 4:20:37 pm PDT
Created in support of improved error and connection management.