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, SetupTimeouts, 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"; potentialServiceProvider: PROC[credentials: Thrush.Credentials, smartsInfo: SmartsInfo]; 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]; IF potentialServiceProvider#NIL THEN potentialServiceProvider[credentials, info]; 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; debugging: BOOL; SELECT info.larkInfo.larkState FROM $none, $failed => 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 info.otherSmartsID # nullID AND 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 debugging _ Rope.Equal[case: FALSE, s2: "D", s1: NamesGV.GVGetAttribute[ VoiceUtils.InstanceFromNetAddress[info.larkInfo.netAddress, larkRegistry], $mode, "O"]]; ThSmartsPrivate.SetupTimeouts[ info.larkInfo, debugging ]; -- Reset the Lark RETURN[TRUE]; EXITS Failed => RETURN[FALSE]; }; DeregisterIfRegistered: ENTRY PROC[ netAddress: Thrush.NetAddress, partyType: Thrush.PartyType] = { hostAtom: ATOM; smarts: REF; netAddress.socket _ Pup.nullSocket; hostAtom _ VoiceUtils.MakeAtom[VoiceUtils.InstanceFromNetAddress[netAddress, Atom.GetPName[partyType]]]; smarts_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 }; Login: PUBLIC PROC[shh: SHHH_, smartsID: SmartsID_, authenticated: BOOL_TRUE] = { NULL;}; 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]; }; RegisterServiceProvider: PUBLIC PROC[ serviceProvider: PROC[credentials: Thrush.Credentials, smartsInfo: SmartsInfo]] = { potentialServiceProvider _ serviceProvider; }; Commander.Register["LarkSmarts", LarkSmartsInit, "LarkSmarts \nInitialize and Export LarkSmarts"]; Commander.Register["KillLark", KillLark, "KillLark 110 -- deregisters lark 110"]; }. „LarkSmartsInitImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Last modified by D. Swinehart, November 25, 1986 3:58:12 pm PST Last Edited by: Pier, May 3, 1984 2:52:59 pm PDT Copies Limited registration for supporting service registration. This handles only one service that would like to register with LarkSmarts parties (intended for synthesizer). If multiple registrations became necessary, would have to extend this. See LarkSmartsInitImpl for the point of invocation, LarkSmartsSynthImpl for an example of use. Registration/Deregistration/Initialization Develop partyRname: the actual RName to be used to represent this party; and dbRname: the name under which database items are stored in Grapevine. The rName obtained from the conversation handle may have either form initially, since Finches will supply the former and Larks will supply the latter. Also, obtain the name of the service represented by this Rname, if any, from the database. Above converts from, say, Swinehart.pa.lark to Swinehart.pa. Also, from Swinehart.pa to Swinehart.pa. Strips one registry if there are two or more. The LarkSmarts interface definition suggests that a Lark could present enough information during registration to be simply re-validated (kind of like a hand stamp at a dance) without any great effort. That turns out not to be worth it. If a Lark registers when already registered, we get rid of any old information about it first. Don't assume that its type has not changed from $telephone to $service or vice/versa Get encryption taken care of Make sure we can talk to the Lark No further bad things are expected to happen. If the phone is on-hook, mark us ready to go, and set up any once-only Lark params. If anyone has registered, call them. They may want to register a service with our party. See LarkSmartsSynthImpl for an (the) example. We're debugging if the lark's mode field in the database has the value "D" or "d" If registered, undo everything at the smarts level and below, then deregister at the Party level Not implemented Other Utilities Initialization, export "LarkSmarts" Same as $Lark, except doesn't print at all if debugging viewer not found. See LarkSmartsSynthImpl for an (the) example. See Register (above) for invocation of potentialServiceProvider. Swinehart, May 22, 1985 5:03:50 pm PDT Cedar 6.0 New ways of defining service parties. autoAnswer (formerly hotLine), radio, and textToSpeech attributes obtained from data base. Text-To-Speech service contemplated. Deregistration works in the face of duplicate service names, etc. changes to: DIRECTORY, Register, DO changes to: DIRECTORY, Register, DO, DeregisterIfRegistered, ConsiderOne (local of DeregisterIfRegistered), Deregister Swinehart, October 28, 1985 9:55:38 am PST Names, Log => VoiceUtils, Handle => ID changes to: DIRECTORY, LarkSmartsInitImpl, ConversationID, Reseal, nullID, PartyID, SmartsID, Register, EnableSmarts, ConsiderOne (local of DeregisterIfRegistered), Deregister, SimpleDeregister, Login Swinehart, November 8, 1985 3:32:57 pm PST Accommodate new ThParty implementation changes to: DIRECTORY, Reseal, SHHH, Register, interfaceName, EnableSmarts, DeregisterIfRegistered, Deregister Swinehart, May 17, 1986 5:57:14 pm PDT Cedar 6.1 changes to: DIRECTORY, WhereIsSmartsLog, WhereIsLarkLog, KillLark Swinehart, May 25, 1986 10:09:37 pm PDT Lark => LarkOps changes to: DIRECTORY, LarkSmartsInitImpl, Register Κ ˜šœ™Icodešœ Οmœ7™BJšœ?™?J™0J˜—šΟk œ˜ Jšœžœ˜Jšœ žœ˜*Jšœ žœ˜#Jšœžœ˜Jšžœ˜Jšœžœ-žœ˜>Jšœžœ)˜@J˜ J˜Jšœžœ5˜OJ˜Jšœžœ˜ Jšœžœ˜!Jšœ žœ˜%Jšœžœ˜ Jšœžœ˜Jšœžœžœ˜#J˜JšžœžœN˜WJšœžœ˜Jšœžœ˜'Jšœ<˜J˜Jšœžœžœ˜Jšœžœ˜JšžœK˜RJ˜Jšœ žœ˜J˜+J˜Jšœ1žœ˜5Jšœžœ˜ Jšœ žœžœ˜%Jšœ žœ ˜Jšœ žœ˜Jšœ žœ˜J˜)Jšœžœ˜Jšœ žœ˜J˜ J˜LJ˜J™†šžœ)ž˜.Jšžœ)žœ˜MJ™J˜FJ˜Fšœ1˜1šœžœ ž˜Jšœ˜Jšžœ˜—J˜J˜Jšœ:˜:Jšœ˜—šžœžœ*žœ˜CJšœ;žœ˜?Jšœ(žœ ˜9—Jšœ-™-Jšœ ˜ Jšžœžœžœžœ˜šœžœ˜Jšœ˜J˜J˜+J˜,J˜šœ žœ!˜.J˜J˜ J˜J˜ Jšœ8žœ˜>J˜——J˜$Jšœžœ ˜=J˜(šžœž˜Jšœ œR˜Y—Jšœ[˜[šœ˜J™S—šžœžœžœ‘œ˜QJ™ˆ—šž˜Jšœ žœ˜—Jšœ˜—J˜šŸ œžœžœ˜/Jšœ˜—š Ÿ œžœžœžœžœ žœ˜OJšžœžœžœ˜8Jšœ žœ˜šžœž˜#Jšœžœ˜Jšžœžœžœ˜—Jš žœ6žœžœžœžœ˜Qšžœ5žœž˜=Jšœ7žœžœ˜H—šžœž˜"Jšœ9ž˜=Jšœ3žœ˜<—Jšœ7 ˜UJšœ7 ˜HJ™Qšœžœ ˜,šœ˜JšœX˜X——Jšœ; ˜LJšžœžœ˜ Jšžœ žœžœ˜J˜J˜—šŸœžœžœ˜#Jšœ?˜?J™`Jšœ žœ˜Jšœžœ˜ J˜#šœL˜LJšœ˜—Jšœ0  œ˜>Jšžœžœžœžœ˜J˜J˜—J˜šŸ œžœžœžœ˜8Jšœžœ˜%J˜!šœžœžœžœž˜)Jšžœžœ% œ˜D—šœ<˜˜>šœ$žœžœ!˜TJ˜——šœ#™#J˜šŸœ˜#˜J˜Q—J˜/J˜-J˜J˜—J˜+J˜"J˜šŸœ˜)šžœ˜JšžœLžœ ˜^J˜—šœ žœ+˜9JšœX˜X—šœA˜AJ˜;—˜ J˜Jšœ˜J˜J˜—JšœE˜Ešœy˜yJ™I—JšœI˜IJšœDžœ˜N˜%J˜J˜J˜J˜—Jšœ<žœ˜Xšž˜˜ JšœDžœ˜N——Jšœ˜J˜—šŸœžœžœ˜%Jšœžœ‘8œ˜TJšœo™oJšœ+˜+J˜—J˜—šœ’˜’J˜J˜—šœQ˜QJ˜J˜—J˜™&K™ K™§K™AKšœ Οr™#Kšœ £<œ"£ ™v—™*Kšœ$ž™&Kšœ £uœ"£%™Θ—™*K™&Kšœ £b™n—™&K™ Kšœ £5™A—™'K™Kšœ £'™3—K™—…—+šE1