<> <> <> <> DIRECTORY Atom USING [ GetPName ], Commander USING [ CommandProc, Register ], CommandTool USING [ NextArgument ], Convert USING [ IntFromRope ], IO, Lark USING [ CommandEventSequence, LarkModel, Machine, SHHH ], LarkOpsRpcControl USING [ ImportNewInterface, InterfaceRecord ], LarkSmarts, LarkSmartsMonitorImpl, LarkSmartsRpcControl USING [ExportInterface, InterfaceName, UnexportInterface], LupineRuntime, MBQueue USING [ Create, Flush ], NamesGV USING [ GVGetAttribute ], NamesRPC USING [ StartConversation ], Nice USING [ LarkConLogStream ], Pup USING [ nullSocket ], RefID USING [ ID, Reseal, Unseal ], Rope USING [Concat, Equal], RPC USING [ AuthenticateFailed, EncryptionKey, ExportFailed, GetCaller, ImportFailed ], ThNet USING [ pd ], ThPartyPrivate USING [ RegisterLocal ], ThParty USING [ Deregister, Enable, SmartsInterfaceRecord ], Thrush USING [ Credentials, epoch, Epoch, NB, NetAddress, noAddress, nullID, PartyID, PartyType, ROPE, SmartsID, unencrypted ], ThSmartsPrivate USING [ CheckHookState, EnterLarkState, LarkFailed, LarkInfo, LarkInfoBody, LarkParseEvent, LarkProgress, LarkReportAction, LarkSubstitution, NoteNewState, RegisterTrunk, SmartsInfo, SmartsInfoBody ], ThSmartsRpcControl, ThVersions, Triples USING [ Any, Make, Select ], TU, VoiceUtils USING [ CmdOrToken, CurrentPasskey, DNFProc, InstanceFromNetAddress, MakeAtom, MakeRName, Problem, ProblemFR, RegisterWhereToReport, ReportFR, RnameToRspec, Rspec, WhereProc ] ; LarkSmartsInitImpl: CEDAR MONITOR LOCKS root IMPORTS IO, Atom, Commander, CommandTool, Convert, LarkOpsRpcControl, LarkSmartsRpcControl, NamesGV, NamesRPC, root: LarkSmartsMonitorImpl, LupineRuntime, MBQueue, Nice, RefID, Rope, RPC, ThNet, ThPartyPrivate, ThParty, Thrush, ThSmartsPrivate, ThSmartsRpcControl, ThVersions, Triples, TU, VoiceUtils EXPORTS LarkSmarts, ThSmartsPrivate SHARES LarkSmartsMonitorImpl = { OPEN IO; <> Reseal: PROC[r: REF] RETURNS[RefID.ID] = INLINE {RETURN[RefID.Reseal[r]]; }; nullID: RefID.ID = Thrush.nullID; PartyID: TYPE = Thrush.PartyID; ROPE: TYPE = Thrush.ROPE; SHHH: TYPE = Lark.SHHH; -- Encrypts conv. if first arg to RPC PROC SmartsID: TYPE = Thrush.SmartsID; SmartsInfo: TYPE = ThSmartsPrivate.SmartsInfo; SmartsInfoBody: TYPE = ThSmartsPrivate.SmartsInfoBody; larkRegistry: ROPE_".lark"; <> Register: PUBLIC PROC[ shh: SHHH, -- encrypts connection oldSmartsID: Thrush.SmartsID, oldEpoch: Thrush.Epoch, machine: Lark.Machine, -- machine name for registering Lark -- model: Lark.LarkModel, authenticated: BOOL_FALSE, clientInstance: ROPE ] RETURNS [ smartsID: Thrush.SmartsID_nullID, epoch: Thrush.Epoch_Thrush.epoch ] = { larkSh: Lark.SHHH; localSmarts: ThParty.SmartsInterfaceRecord; info: SmartsInfo; larkInterface: LarkOpsRpcControl.InterfaceRecord_NIL; smarts: REF; fullRname: ROPE = RPC.GetCaller[shh]; partyRname: ROPE _ fullRname; dbRname: ROPE; serviceName: ROPE; partyType: Thrush.PartyType _ $telephone; s: VoiceUtils.Rspec _ NIL; nb: Thrush.NB; credentials: Thrush.Credentials; netAddress: Thrush.NetAddress = [machine.net, machine.host, Pup.nullSocket]; <> IF (s_VoiceUtils.RnameToRspec[partyRname])#NIL AND VoiceUtils.RnameToRspec[s.simpleName] # NIL THEN partyRname_s.simpleName; <> <> dbRname _ partyRname.Concat[larkRegistry]; serviceName _ NamesGV.GVGetAttribute[dbRname, $service, NIL]; IF serviceName#NIL THEN partyType _ $service; <<>> <> DeregisterIfRegistered[netAddress, $telephone]; DeregisterIfRegistered[netAddress, $service]; <> larkSh _ IF NOT ThNet.pd.encryptionRequested THEN Thrush.unencrypted ELSE NamesRPC.StartConversation [ caller: myName.instance, callee: fullRname, key: serverPassword, level: --<>--CBCCheck ! RPC.AuthenticateFailed=> { VoiceUtils.ProblemFR["Can't authenticate %g to %g", $System, NIL, rope[myName.instance], rope[fullRname]]; GOTO NotSmart; }]; <> larkInterface _ LarkOpsRpcControl.ImportNewInterface[ interfaceName: [type: "Lark.Lark", instance: clientInstance] ! RPC.ImportFailed=> { VoiceUtils.ProblemFR["Can't import Lark interface from %g", $System, NIL, rope[clientInstance]]; GOTO NotSmart; }]; localSmarts _ ThSmartsRpcControl.NewInterfaceRecord[]; localSmarts.clientStubProgress _ ThSmartsPrivate.LarkProgress; localSmarts.clientStubSubstitution _ ThSmartsPrivate.LarkSubstitution; localSmarts.clientStubReportAction _ ThSmartsPrivate.LarkReportAction; [nb, credentials] _ ThPartyPrivate.RegisterLocal[ rName: (SELECT partyType FROM $telephone => partyRname, ENDCASE=> serviceName), type: partyType, interfaceRecord: localSmarts, properties: [role: $voiceTerminal, netAddress: netAddress] ]; IF nb # $success OR (smartsID_credentials.smartsID) = nullID THEN { VoiceUtils.ProblemFR["Can't register Lark: %g, %g",$System,NIL, rope[fullRname], rope[clientInstance]]; GOTO NotSmart; }; <> smarts _ RefID.Unseal[smartsID]; IF smarts=NIL THEN ERROR; info _ NEW[SmartsInfoBody_ [ smartsID: smartsID, partyType: partyType, ParseEvent: ThSmartsPrivate.LarkParseEvent, NoteNewStateP: ThSmartsPrivate.NoteNewState, requests: MBQueue.Create[], larkInfo: NEW[ThSmartsPrivate.LarkInfoBody _ [ interface: larkInterface, shh: larkSh, netAddress: netAddress, model: model, textToSpeech: Rope.Equal[serviceName, "Text-to-Speech", FALSE] ]] ]]; info.larkInfo.larkSmartsInfo _ info; info.larkInfo.scratchEv _ NEW[Lark.CommandEventSequence[15]]; Triples.Make[$SmartsData, smarts, info]; IF partyType # $service THEN [--nb--, info.otherSmartsID]_ThSmartsPrivate.RegisterTrunk[ smartsID, info, partyRname ]; VoiceUtils.ReportFR[" (%g = %g)", $Smarts, info, rope[clientInstance], TU.RefAddr[smarts]]; EnableSmartsE[info]; -- Ready to go, as long as phone is on hook EXITS NotSmart => RETURN; }; EnableSmartsE: ENTRY PROC[info: SmartsInfo] = { []_EnableSmarts[info]; }; EnableSmarts: PUBLIC INTERNAL PROC[info: SmartsInfo] RETURNS[enabled: BOOL] = { ENABLE UNWIND, ThSmartsPrivate.LarkFailed =>GOTO Failed; SELECT info.larkInfo.larkState FROM $none, $failed, $recovering => NULL; ENDCASE=> RETURN[TRUE]; IF ThSmartsPrivate.CheckHookState[info.larkInfo].onHook=FALSE THEN RETURN[FALSE]; IF ThParty.Enable[ smartsID: info.smartsID] # $success THEN { VoiceUtils.Problem["Could not enable", $Smarts, info]; RETURN[FALSE]; }; IF ThParty.Enable[ smartsID: info.otherSmartsID] # $success THEN { VoiceUtils.Problem["Impossible", $Smarts, info]; ERROR; }; ThSmartsPrivate.EnterLarkState[ info.larkInfo, none ]; -- Clear any previous failure. ThSmartsPrivate.EnterLarkState[ info.larkInfo, idle ]; -- Reset the Lark RETURN[TRUE]; EXITS Failed => RETURN[FALSE]; }; DeregisterIfRegistered: ENTRY PROC[ netAddress: Thrush.NetAddress, partyType: Thrush.PartyType] = { <> hostAtom: ATOM = VoiceUtils.MakeAtom[VoiceUtils.InstanceFromNetAddress[netAddress, Atom.GetPName[partyType]]]; smarts: REF_Triples.Select[$SmartsForHost, hostAtom, -- smarts --]; IF smarts=NIL THEN RETURN; Deregister[Reseal[smarts]]; }; Deregister: PUBLIC INTERNAL PROC[smartsID: SmartsID] = { smarts: REF _ RefID.Unseal[smartsID]; otherSmartsID: SmartsID _ nullID; info: SmartsInfo _ IF smarts=NIL THEN NIL ELSE NARROW[Triples.Select[$SmartsData, smarts, -- smartsInfo -- ]]; VoiceUtils.ReportFR["Smarts %d (%g) is dead", $Smarts, info, card[Reseal[smarts]], TU.RefAddr[smarts]]; IF info#NIL THEN { otherSmartsID _ info.otherSmartsID; IF info.larkInfo#NIL THEN { ThSmartsPrivate.EnterLarkState[ info.larkInfo, failed ]; -- prevent further action. info.larkInfo.larkSmartsInfo _ NIL; IF info.larkInfo.larkTrunkSmartsInfo#NIL THEN info.larkInfo.larkTrunkSmartsInfo.larkInfo _ NIL; info.larkInfo.larkTrunkSmartsInfo _ NIL; info.larkInfo _ NIL; }; } ELSE VoiceUtils.ProblemFR["Smarts %d (%g) has no SmartsInfo", $System, NIL, card[Reseal[smarts]], TU.RefAddr[smarts]]; IF otherSmartsID # nullID THEN [--nb--]_ThParty.Deregister[smartsID: otherSmartsID]; [--nb--]_ThParty.Deregister[smartsID: smartsID]; IF info#NIL THEN info.requests.Flush[]; -- Abandon progress-notification queue }; <> WhereIsSmartsLog: VoiceUtils.WhereProc -- [fixedWhereData: REF ANY, whereData: REF ANY] RETURNS [s: STREAM _ NIL] -- = CHECKED { info: SmartsInfo=NARROW[whereData]; IF info#NIL THEN s_Nice.LarkConLogStream[info.larkInfo.netAddress]; IF s#NIL AND s=Nice.LarkConLogStream[Thrush.noAddress] THEN s_NIL; -- use default stream unless debug viewer stream open. }; WhereIsLarkLog: VoiceUtils.WhereProc -- [fixedWhereData: REF ANY, whereData: REF ANY] RETURNS [s: STREAM _ NIL] -- = CHECKED { info: ThSmartsPrivate.LarkInfo=NARROW[whereData]; IF info#NIL THEN s_Nice.LarkConLogStream[info.netAddress]; IF s#NIL AND s=Nice.LarkConLogStream[Thrush.noAddress] THEN s_NIL; -- only want the debug viewer stream }; WhereIsLarkLogFerSherr: VoiceUtils.WhereProc _ WhereIsLarkLog; FerSherrDefault: VoiceUtils.DNFProc=TRUSTED{ RETURN[ThNet.pd.defaultLarkReports]; }; <> KillLark: Commander.CommandProc = { netAddress: Thrush.NetAddress = [[173B],[Convert.IntFromRope[CommandTool.NextArgument[cmd], 8]], Pup.nullSocket]; DeregisterIfRegistered[netAddress, $telephone]; DeregisterIfRegistered[netAddress, $service]; }; myName: LarkSmartsRpcControl.InterfaceName; serverPassword: RPC.EncryptionKey; LarkSmartsInit: Commander.CommandProc = { ENABLE { RPC.ExportFailed => { VoiceUtils.Problem["LarkSmarts export failed", $System]; GOTO Failed; }; }; instance: ROPE = VoiceUtils.MakeRName[style: rName, name: VoiceUtils.CmdOrToken[cmd: cmd, key: "ThrushServerInstance", default: "Strowger.Lark"]]; serverPassword _ VoiceUtils.CurrentPasskey[VoiceUtils.CmdOrToken[ cmd: cmd, key: "ThrushServerPassword", default: "MFLFLX"]]; myName _ [ type: "LarkSmarts.Lark", instance: instance, version: ThVersions.ThrushVR ]; VoiceUtils.RegisterWhereToReport[proc: WhereIsLarkLog, where: $Lark]; VoiceUtils.RegisterWhereToReport[proc: WhereIsLarkLogFerSherr, where: $LarkDetailed, defaultIfNotFound: FerSherrDefault]; <> VoiceUtils.RegisterWhereToReport[proc: WhereIsSmartsLog, where: $Smarts]; LarkSmartsRpcControl.UnexportInterface[!LupineRuntime.BindingError=>CONTINUE]; LarkSmartsRpcControl.ExportInterface[ interfaceName: myName, user: instance, password: serverPassword ]; VoiceUtils.ReportFR["Export[LarkSmarts.Lark, %s]", $System, NIL, rope[myName.instance]]; EXITS Failed => LarkSmartsRpcControl.UnexportInterface[!LupineRuntime.BindingError=>CONTINUE]; }; Commander.Register["LarkSmarts", LarkSmartsInit, "LarkSmarts \nInitialize and Export LarkSmarts"]; Commander.Register["KillLark", KillLark, "KillLark 110 -- deregisters lark 110"]; }. <> <> <> <> <> <> <> < VoiceUtils, Handle => ID>> <> <> <> <> <> <> <> <> < LarkOps>> <> <<>>