DIRECTORY IO USING [ atom, rope ], PhSmarts USING [ lock, PhoenixInfo, PhoenixInfoBody, phoenixInfo, pd, SHHH ], Process USING [ Detach, SecondsToTicks, SetTimeout ], Rope USING [ Equal, ROPE ], ThParty, ThPartySunRPControl USING [ ReportProblem, ReportState, ThrushConnect, ThrushDisconnect, ThrushReportState ], Thrush, ThSmartsSunExport USING [ ExportInterface ], UserProfile USING [ Token ], VoiceUtils USING [ CurrentRName, CurrentPasskey, OwnNetAddress, Problem, ProblemFR, Report, RopeFromSunAddr ] ; PhRegisterImpl: CEDAR MONITOR LOCKS PhSmarts.lock IMPORTS IO, PhSmarts, Process, Rope, ThParty, ThPartySunRPControl, ThSmartsSunExport, UserProfile, VoiceUtils EXPORTS PhSmarts ~ BEGIN OPEN PhSmarts; NB: TYPE = Thrush.NB; ROPE: TYPE = Rope.ROPE; uniqueSuffix: CARD ¬ 0; InitPhoenixSmarts: PUBLIC ENTRY PROC [ thrushInstance: Thrush.ROPE¬NIL ] = { ENABLE UNWIND => NULL; problem: ROPE¬NIL; nb: NB¬$serverDown; prevInfo: PhSmarts.PhoenixInfo ¬ PhSmarts.phoenixInfo; IF phoenixInfo#NIL AND phoenixInfo.connected THEN UnInitPhoenixSmartsInt[]; phoenixInfo ¬ NEW[PhSmarts.PhoenixInfoBody]; -- Dump any old one! IF prevInfo#NIL THEN NOTIFY prevInfo.pollCondition; phoenixInfo.conversations ¬ NIL; phoenixInfo.connected ¬ FALSE; thrushInstance ¬ SELECT TRUE FROM thrushInstance#NIL => thrushInstance, prevInfo#NIL AND prevInfo.prevThrushInstance#NIL => prevInfo.prevThrushInstance, ENDCASE=> UserProfile.Token["ThrushSunClientServerInstance", "Growler"]; phoenixInfo.prevThrushInstance ¬ thrushInstance; uniqueSuffix ¬ ThSmartsSunExport.ExportInterface[port: uniqueSuffix]; phoenixInfo.myName ¬ [ type: "ThSmarts.Lark", instance: VoiceUtils.RopeFromSunAddr[port: uniqueSuffix]]; phoenixInfo.myRName ¬ VoiceUtils.CurrentRName[]; phoenixInfo.myPassword ¬ VoiceUtils.CurrentPasskey[]; phoenixInfo.shh ¬ ThPartySunRPControl.ThrushConnect[ server: thrushInstance, rName: phoenixInfo.myRName, type: $telephone, interface: phoenixInfo.myName, properties: [role: $voiceTerminal, netAddress: VoiceUtils.OwnNetAddress[]], reportState: ReportStateFromThPartyRPC, reportProblem: ReportProblemFromThPartyRPC]; TRUSTED { Process.Detach[FORK PollWaiter[phoenixInfo]]; }; }; UnInitPhoenixSmarts: PUBLIC ENTRY PROC[disable: BOOL¬TRUE] = { ENABLE UNWIND=>NULL; UnInitPhoenixSmartsInt[disable]; }; UnInitPhoenixSmartsInt: INTERNAL PROC[disable: BOOL¬TRUE] = { shhh: PhSmarts.SHHH ¬ IF phoenixInfo#NIL THEN phoenixInfo.shh ELSE NIL; IF shhh=NIL THEN RETURN; ThPartySunRPControl.ThrushDisconnect[shhh, disable]; }; PhoenixIsRunning: PUBLIC PROC RETURNS [phoenixIsEnabled: BOOL¬FALSE, phoenixIsRunning: BOOL¬FALSE] = { IF phoenixInfo=NIL THEN RETURN; RETURN[phoenixInfo.enabled, phoenixInfo.connected]; }; RecordSystemStateFromSmartsReport: PUBLIC INTERNAL PROC[ nb: NB, remark: Rope.ROPE, connected: BOOL, enabled: BOOL, voicePath: BOOL, remoteRemark: Rope.ROPE ] RETURNS[echoNB: NB] -- A convenience for callers -- = { IF phoenixInfo.shh#NIL THEN ThPartySunRPControl.ThrushReportState[phoenixInfo.shh, enabled, connected]; RETURN[RecSS[nb, remark, connected, enabled, voicePath, remoteRemark]]; }; nextSched: INT ¬ pd.pollDefault; PollWaiter: ENTRY PROC[myInfo: PhSmarts.PhoenixInfo] = { ENABLE UNWIND => NULL; nextSched ¬ pd.pollDefault; WHILE myInfo = phoenixInfo DO nextSched ¬ MIN[nextSched, pd.pollDefault]; TRUSTED { Process.SetTimeout[@myInfo.pollCondition, Process.SecondsToTicks[nextSched]]; }; WAIT phoenixInfo.pollCondition; IF myInfo#phoenixInfo THEN RETURN; IF phoenixInfo.nextScheduledCheck#0 THEN { nextSched ¬ phoenixInfo.nextScheduledCheck; phoenixInfo.nextScheduledCheck ¬ 0; LOOP; } ELSE nextSched ¬ nextSched + 30; IF ~phoenixInfo.enabled OR ~pd.doPollingTimeouts THEN LOOP; [] ¬ ThParty.CheckIn[shh: phoenixInfo.shh, credentials: [ partyID: phoenixInfo.partyID, smartsID: phoenixInfo.smartsID, convID: Thrush.nullConvID]]; ENDLOOP; }; ReportProblemFromThPartyRPC: --already ENTRY-- ThPartySunRPControl.ReportProblem ~ { []¬RecSS[nb: ec, remark: expl]; }; ReportStateFromThPartyRPC: --already ENTRY-- ThPartySunRPControl.ReportState ~ { IF phoenixInfo#NIL THEN { phoenixInfo.partyID ¬ myPartyID; phoenixInfo.smartsID ¬ mySmartsID; }; []¬RecSS[connected: registered, enabled: enabled]; }; Poke: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; IF phoenixInfo#NIL THEN NOTIFY phoenixInfo.pollCondition; }; RecSS: --may be INTERNAL-- PROC[ nb: NB¬NIL, remark: Rope.ROPE¬NIL, connected: BOOL¬phoenixInfo.connected, enabled: BOOL¬phoenixInfo.enabled, voicePath: BOOL¬FALSE, remoteRemark: Rope.ROPE¬NIL ] RETURNS[echoNB: NB] -- A convenience for callers -- = { IF nb#NIL OR connected#phoenixInfo.connected OR enabled#phoenixInfo.enabled THEN { IF nb#NIL THEN NBProblem[remark, nb] ELSE IF remark#NIL THEN VoiceUtils.Report[remark, $Finch]; }; phoenixInfo.connected ¬ connected; phoenixInfo.enabled ¬ enabled; IF remoteRemark#NIL THEN { IF phoenixInfo=NIL OR ~remoteRemark.Equal[phoenixInfo.lastRemoteRemark] THEN VoiceUtils.Report[remoteRemark, $Finch]; IF phoenixInfo#NIL THEN phoenixInfo.lastRemoteRemark ¬ remoteRemark; }; RETURN[nb]; }; NBProblem: PROC[remark: ROPE¬NIL, nb: NB¬NIL] = { IF nb=NIL THEN VoiceUtils.Problem[remark, $Finch] ELSE VoiceUtils.ProblemFR["%g, reason: %g", $Finch, NIL, IO.rope[remark], IO.atom[nb]]; }; END. p PhRegisterImpl.mesa Copyright Σ 1990, 1992 by Xerox Corporation. All rights reserved. Vin, September 25, 1990 5:40 pm PDT Swinehar, October 1, 1992 4:09 pm PDT Now connect to server and register with Thrush IF disable THEN ThPartySunRPControl.ReleaseConversation[shhh]; That's just a cleanliness, and I'm worried about not adequately recording the last Progress and Substitution reports as they drag in. Before putting this back, analyze some typical traffic flow and see what's needed. Perhaps the previous stuff should be put on a timer, then destroyed. Worry, if ever we don't destroy phoenixInfo and create a new one, about the possibility that old reports will encounter strange credentials. DCS, September 13, 1990 11:57:37 am PDT Ordinary case: received another CheckIn report before timeout. Timeout occurred before next CheckIn report, and either we're disconnected or we've been told to worry if we haven't heard from the server (or it's been quite a while, we've been told not to worry, and we're paranoid. Calling any ThParty function will either succeed or the failure will trigger the best available recovery activities. Polling loop will awaken immediately and if necessary (and not inhibited) try to reconnect. Generalized reporting utility pd.requests.QueueClientAction[ReportSystemStateToFinchClients, NIL]; Relate each distinct remote remark exactly once. Κ:•NewlineDelimiter –"cedarcode" style™code™Kšœ Οeœ7™BK™#K™%K™—šΟk ˜ Kšžœžœ˜Kšœ žœ8žœ˜MKšœžœ(˜5Kšœžœ žœ˜K˜KšœžœT˜mKšœ˜Kšœžœ˜,Kšœ žœ ˜Kšœ žœ]˜mK˜—K˜K˜KšΠlnœžœžœžœ˜1Kšžœžœd˜nKšžœ ˜šœž˜Kšžœ ˜K˜Kšžœžœ žœ˜Kšžœžœžœ˜Kšœžœ˜K˜šΟnœžœžœžœ˜&KšΡbosœ žœž˜Kšœ˜Kšžœžœžœ˜Kšœ žœžœžœ ˜&K˜6K˜Kšžœ žœžœžœ˜KKšΠbo œžœΟc˜AKšžœ žœžœžœ˜3KšΟo œžœ˜ K˜Kšœ ’ œžœ˜š’œžœžœž˜!Kšœžœžœ˜%Kšœ žœžœžœ ˜PKšžœA˜H—Kšœ ’œ˜0K˜Ešœ ’œ˜K˜K˜:—Kšœ ’œ˜0Kšœ ’ œ˜5K˜™.šœ ’œ$˜4KšœE˜EKšœΏ˜Ώ——K˜Kšžœžœ˜:K˜—K˜š  œžœžœžœ žœžœ˜>Kšžœžœžœ˜Kšœ ˜ K˜—K˜š  œžœžœ žœžœ˜=Kš œžœžœ žœžœžœžœ˜GKšžœžœžœžœ˜Kšœ4˜4šΟtžœ žœ/™?Jšœ1₯¦™Χ—K˜—K˜š œžœž˜Kš žœžœžœžœžœ˜HKšžœ žœžœžœ˜Kšžœ-˜3Kšœ˜—K˜š !œžœžœžœ˜8Kš œžœžœ žœ žœ žœžœ˜eKšžœ žœ£œ˜7šžœžœž˜KšœK˜K—KšžœA˜GK˜K˜—šœ žœ˜ K˜—š  œžœžœ"˜8Kšžœžœžœ˜K˜šžœž˜Kšœ žœ˜+KšžœS˜ZKšžœ˜Kšžœžœžœ˜"šžœ"žœ˜*KšœPžœ˜W—šžœ˜ J™>—Kšžœžœžœžœ˜;J™Ο˜9KšœZ˜Z—Kšžœ˜—K˜—K˜š œžœ&˜TKš₯œ₯˜K˜—K˜š œžœ$˜Pšžœ žœžœ˜K˜ K˜"K˜—Kš₯œ₯/˜2K˜—K˜š œžœžœžœ˜Kšžœžœžœ˜Kšžœ žœžœžœ˜