<> <> DIRECTORY Atom USING [ GetPName, MakeAtom ], GVBasics USING [ RName ], GVNames USING [ Expand, RListHandle ], IO, Log USING [ FindWhere, Problem, ProblemHandle, RegisterWhereToReport, Report, ReportFR, WhereProc ], LupineRuntime USING [ BindingError ], Names USING [ CurrentRName, CurrentPasskey, MakeAtom, Registrize ], NamesGV USING [ GVGetAttribute ], NamesRPC USING [ StartConversation ], Nice, Rope USING [ Concat, Fetch, Length, Substr ], RPC USING [ AuthenticateFailed, EncryptionKey, ExportFailed, ImportFailed ], SafeStorage USING [ GetCanonicalType, Type ], Thrush USING [ AlertKind, CallUrgency, ConversationHandle, Enhandle, HandleFault, KillHandle, NB, PartyHandle, PartyType, H, nullHandle, Machine, MakeUnique, pERROR, PhoneNumber, Priorities, Rname, ROPE, SHHH, SmartsHandle, TBD, ThHandle, unencrypted ], ThNet USING [ HowToDial, InitWhitePagesDatabase, WhitePagesEntry, WPListing, WPState ], ThParty, ThPartyPrivate USING [ CFRef, DehandleParty, DehandleSmarts, DoAdvance, PartyBody, PartyData, SmartsBody, SmartsData, Supervise ], ThPartyRpcControl, ThPartyMonitorImpl, ThSmarts USING [ SmartsInterface, SmartsProperties ], ThSmartsRpcControl USING [ ImportNewInterface, InterfaceRecord ], ThVersions USING [ ThrushVR ], Triples USING [ Any, Erase, Foreach, ForeachProc, Select ], TU USING [ RefAddr ], UserProfile USING [ Token ] ; ThPartyInitImpl: CEDAR MONITOR LOCKS root IMPORTS Atom, GVNames, IO, Log, LupineRuntime, Names, NamesGV, NamesRPC, Nice, root: ThPartyMonitorImpl, Rope, RPC, SafeStorage, SmartsRpc: ThSmartsRpcControl, Thrush, ThNet, ThPartyPrivate, ThPartyRpcControl, ThVersions, Triples, TU, UserProfile EXPORTS ThParty, ThPartyPrivate SHARES ThPartyMonitorImpl = { OPEN IO; <> AlertKind: TYPE = Thrush.AlertKind; CallUrgency: TYPE = Thrush.CallUrgency; CFRef: TYPE = ThPartyPrivate.CFRef; ConversationHandle: TYPE = Thrush.ConversationHandle; PartyBody: TYPE = ThPartyPrivate.PartyBody; -- Concrete RTPartyType: SafeStorage.Type = SafeStorage.GetCanonicalType[CODE[PartyBody]]; PartyData: TYPE = ThPartyPrivate.PartyData; -- REF Concrete PartyHandle: TYPE = Thrush.PartyHandle; -- Handle ROPE: TYPE = Thrush.ROPE; SmartsBody: TYPE = ThPartyPrivate.SmartsBody; -- Concrete SmartsData: TYPE = ThPartyPrivate.SmartsData; -- REF Concrete RTSmartsType: SafeStorage.Type =SafeStorage.GetCanonicalType[CODE[SmartsBody]]; SmartsHandle: TYPE = Thrush.SmartsHandle; -- Handle SmartsInterface: TYPE = ThSmarts.SmartsInterface; LocalSmartsInterface: TYPE = SmartsRpc.InterfaceRecord; nullHandle: Thrush.PartyHandle = Thrush.nullHandle; SHHH: TYPE = Thrush.SHHH; none: SHHH = Thrush.unencrypted; TBD: TYPE = Thrush.TBD; pERROR: ERROR = Thrush.pERROR; H: PROC[r: REF] RETURNS[Thrush.ThHandle] = INLINE {RETURN[Thrush.H[r]]; }; larkRegistry: ROPE=".Lark"; recordingRname: Thrush.Rname = "idle.jay.lark"; recordingRAtom: PUBLIC ATOM _ Atom.MakeAtom[recordingRname]; <> standardPriorities: Thrush.Priorities = LIST [ LIST [$Supervisor], LIST [$Manager], LIST[$LocatedTerminal], LIST [$AdjacentTerminal], LIST [$VoiceTerminal, $LabPhone], LIST [$Secretary], LIST [$Receptionist] ]; GetParty: PUBLIC ENTRY PROC[shh: SHHH_NIL, partyID: PartyHandle, rName: Thrush.Rname] RETURNS [newPartyID: PartyHandle] = { ENABLE UNWIND=>NULL; <<|Need an NB return on failure|>> RETURN[H[GetActiveParty[rName]]]; }; GetActiveParty: INTERNAL PROC[rName: Thrush.Rname] RETURNS [newParty: PartyData] = { rAtom: ATOM; IF rName=NIL THEN RETURN[NIL]; rName _ Names.Registrize[rName]; rAtom _ Names.MakeAtom[rName]; RETURN[NARROW[Triples.Select[$RnameForParty, --party--, rAtom]]]; }; GetJayParty: PUBLIC ENTRY PROC[shh: SHHH_none, partyID: PartyHandle] RETURNS [newPartyID: PartyHandle_nullHandle] = { ENABLE UNWIND=>NULL; party: PartyData_ ThPartyPrivate.DehandleParty[partyID]; rAtom: ATOM; IF party = NIL THEN RETURN; rAtom _ NARROW[Triples.Select[$RnameForParty, party, -- rAtom --]]; rAtom _ Names.MakeAtom[Atom.GetPName[rAtom].Concat[".Jay"]]; party _ NARROW[Triples.Select[$RnameForParty, --party--, recordingRAtom]]; IF party = NIL OR party.numEnabled = 0 THEN RETURN; Thrush.MakeUnique[$RnameForParty, party, rAtom]; RETURN[H[party]]; }; GetPartyFromFeepNum: PUBLIC ENTRY PROC[ shh: SHHH_none, partyID: PartyHandle, feepNum: Thrush.ROPE_NIL] RETURNS [newPartyID: PartyHandle_nullHandle] = { ENABLE UNWIND=>NULL; party: PartyData _ NIL; rName, officeNumber: ROPE; listing: ThNet.WPListing; [rName, officeNumber, listing] _ ThNet.WhitePagesEntry [ wpState: wpState, name: feepNum, feep: TRUE, key: $officeNumber]; IF rName=NIL THEN RETURN; party _ GetActiveParty[rName]; IF party#NIL THEN RETURN[H[party]]; IF officeNumber=NIL THEN RETURN; RETURN[GetPartyFromNumberInt[partyID, officeNumber, rName, TRUE]]; }; GetPartyFromNumber: PUBLIC ENTRY PROC[ shh: SHHH, partyID: PartyHandle, phoneNumber: Thrush.ROPE, description: ROPE, trunkOK: BOOL] RETURNS [newPartyID: PartyHandle] = { ENABLE UNWIND => NULL; RETURN[GetPartyFromNumberInt[partyID, phoneNumber, description, trunkOK]]; }; GetPartyFromNumberInt: INTERNAL PROC[ partyID: PartyHandle, phoneNumber: Thrush.ROPE, description: ROPE, trunkOK: BOOL] RETURNS [newPartyID: PartyHandle] = { ENABLE ANY => { newPartyID _ Log.ProblemHandle[,$System]; CONTINUE; }; isExt: BOOLEAN _ FALSE; num: ROPE _ NIL; party: PartyData = ThPartyPrivate.DehandleParty[partyID]; <> myExtAtom: ATOM = IF party=NIL THEN NIL ELSE NARROW[Triples.Select[$Extension, party,]]; myExt: ROPE = IF myExtAtom=NIL THEN NIL ELSE Atom.GetPName[myExtAtom]; IF phoneNumber#NIL THEN [num, isExt] _ ThNet.HowToDial[phoneNumber, myExt]; IF isExt THEN { extAtom: ATOM=Atom.MakeAtom[num]; newPartyID _ H[NARROW[Triples.Select[$Extension, --party--, extAtom]]]; IF newPartyID#nullHandle THEN RETURN[newPartyID]; }; IF ~trunkOK THEN RETURN[nullHandle]; RETURN[H[GetTrunkParty[partyID: partyID, description: description, address: num]]]; }; GetTrunkParty: INTERNAL PROC[ partyID: PartyHandle, description: Thrush.ROPE, address: Thrush.ROPE] RETURNS[trunkParty: PartyData_NIL] = { party: PartyData = ThPartyPrivate.DehandleParty[partyID]; IF party#NIL THEN trunkParty _ NARROW[Triples.Select[$TrunkParty, party, Triples.Any]]; IF trunkParty = NIL THEN RETURN; TRUSTED { WITH tp: trunkParty SELECT FROM trunk => { IF tp.outgoing#NIL OR GetRnameFromParty[trunkParty] # NIL THEN RETURN[NIL]; tp.outgoing _ address; IF description#NIL THEN Thrush.MakeUnique[$RnameForTrunk, trunkParty, Atom.MakeAtom[description]]; }; ENDCASE => { Log.Problem["Wrong party type", $System]; RETURN[NIL]; }; }; }; GetNumbersForRName: PUBLIC PROC[shh: SHHH_none, rName: Thrush.Rname] RETURNS [fullRName: ROPE, number: ROPE, homeNumber: ROPE] = { listing: ThNet.WPListing; [fullRName, number, listing] _ ThNet.WhitePagesEntry[ wpState: wpState, name: rName, key: $officeNumber]; IF listing#NIL THEN homeNumber _ ThNet.WhitePagesEntry[ wpState: wpState, key: $outsideNumber, listing: listing].entry; }; <<>> <> GetRname: PUBLIC PROC[shh: SHHH_none, partyID: PartyHandle] RETURNS [rName: Thrush.Rname] = { RETURN[GetRnameFromParty[ThPartyPrivate.DehandleParty[partyID]]]; }; CreateParty: PUBLIC PROC[shh: SHHH_NIL, rName: Thrush.Rname, type: Thrush.PartyType] RETURNS [partyID: PartyHandle_nullHandle] = { <<|Need NB indicating why null handle returned.|>> ENABLE ANY => { partyID _ Log.ProblemHandle[, $System]; CONTINUE; }; party: PartyData_NIL; rn: Thrush.Rname = IF type#recording THEN rName ELSE recordingRname; larkName: ROPE=rn.Concat[larkRegistry]; nameAttr: ATOM=$RnameForParty; rAtom: ATOM=Names.MakeAtom[rn]; extension: ATOM_NIL; ExistingParty: ENTRY PROC = -- INLINE -- { ENABLE UNWIND=>NULL; party_IF type=recording THEN NIL ELSE NARROW[Triples.Select[nameAttr, --party--, rAtom]]; IF party#NIL AND ~party.partyFailed AND party.type#type THEN { Log.Problem[remark: "Same party name, new type", where: $System]; party_NIL; }; }; NewParty: ENTRY PROC = -- INLINE -- { <> SELECT type FROM individual => { party_NEW[PartyBody _ [v: individual []]]; IF extension#NIL THEN Thrush.MakeUnique[$Extension, party, extension]; }; recording => party_NEW[PartyBody _ [v: recording []]]; trunk => party _ NEW [ PartyBody _ [ v: trunk [ NIL, NIL ] ] ]; ENDCASE => { Log.Problem["Unknown party type", $System]; RETURN; }; party.supervisor _ NIL; IF rName#NIL THEN Thrush.MakeUnique[nameAttr, party, rAtom]; Thrush.MakeUnique[$Priorities, party, standardPriorities]; partyID _ Thrush.Enhandle[party]; }; rName_rn; IF rName=NIL AND type#trunk THEN RETURN; ExistingParty[]; IF party#NIL THEN RETURN[H[party]]; <> SELECT type FROM individual => TRUSTED { <> <> WITH GVNames.Expand[larkName] SELECT FROM group => { FOR entries: GVNames.RListHandle _ members, members.rest WHILE entries#NIL DO entry: GVBasics.RName=entries.first; IF entry.Length[]>2 AND entry.Fetch[0]='X AND entry.Fetch[1]='. THEN { extension _ Names.MakeAtom[entry.Substr[start: 2, len: 4]]; EXIT; }; ENDLOOP; }; ENDCASE; IF extension=NIL THEN { ext: ROPE _ GetNumbersForRName[rName: rName].number; IF ext#NIL AND ([ext,]_ThNet.HowToDial[ext]).isLocalExtension THEN extension_Names.MakeAtom[ext]; }; }; ENDCASE; <> NewParty[]; Log.Report[IO.PutFR["CreateParty[%s, %s] -> [ %g, %g ]", rope[rName], rope[SELECT type FROM individual => "individual", trunk=>"trunk", recording=>"recording", ENDCASE=>NIL], card[partyID], IF party=NIL THEN atom[$Unknown] ELSE TU.RefAddr[party]], $Party, party]; }; ReleaseTrunkParty: PUBLIC ENTRY PROC[shh: SHHH, partyID: PartyHandle] = TRUSTED { party: PartyData = ThPartyPrivate.DehandleParty[partyID]; IF party=NIL THEN RETURN; IF party.numConvs#0 THEN RETURN; -- ONLY do if didn't make it into a conversation WITH tp: party SELECT FROM trunk => { IF party.numConvs#0 THEN RETURN; tp.outgoing _ NIL; Triples.Erase[$RnameForTrunk, party, Triples.Any]; }; ENDCASE; }; Register: PUBLIC PROC[shh: SHHH, partyID: PartyHandle, interface: SmartsInterface, properties: ThSmarts.SmartsProperties, oldSmartsID: SmartsHandle] RETURNS [smartsID: SmartsHandle] = { <> RETURN[DoRegister[ThPartyPrivate.DehandleParty[partyID], NIL, interface, properties]]; }; <> RegisterLocal: PUBLIC PROC[partyID: PartyHandle, interface: LocalSmartsInterface, properties: ThSmarts.SmartsProperties, oldSmartsID: SmartsHandle] RETURNS [smartsID: SmartsHandle] = { <<|Need NB why failed|>> <> RETURN[DoRegister[ThPartyPrivate.DehandleParty[partyID], interface, NIL, properties]]; }; DoRegister: PROC[party: PartyData, localInterface: LocalSmartsInterface, remoteInterface: SmartsInterface, properties: ThSmarts.SmartsProperties] RETURNS [smartsID: Thrush.SmartsHandle_nullHandle] ={ <<|Need NB why failed|>> ENABLE ANY => { smartsID _ Log.ProblemHandle[,$System]; CONTINUE; }; rName: ROPE; smarts: SmartsData; shh: SHHH; interface: SmartsRpc.InterfaceRecord; IF party=NIL THEN RETURN[nullHandle]; IF properties.role = manager THEN { <> smarts _ NARROW[Triples.Select[$Manager, party, Triples.Any]]; IF smarts#NIL THEN Deregister[shh: none, smartsID: H[smarts]]; }; rName_GetRnameFromParty[IF party.type#trunk THEN party ELSE GetHostParty[party]]; IF rName=NIL THEN RETURN[Log.ProblemHandle["No RName for own party", $System]]; <> shh _ NamesRPC.StartConversation[caller: Names.CurrentRName[], callee: rName, key: Names.CurrentPasskey[], level: --<>--CBCCheck ! RPC.AuthenticateFailed => { smartsID _ Log.ProblemHandle["Authenticate failed", $System]; GOTO Failed}]; interface _ IF remoteInterface=NIL THEN localInterface ELSE SmartsRpc.ImportNewInterface[interfaceName: remoteInterface^ ! RPC.ImportFailed => { smartsID _ Log.ProblemHandle["Import failed", $System]; GOTO Failed}]; <> smarts_NEW[ThPartyPrivate.SmartsBody_[interface: interface, properties: properties, type: party.type, shh: shh, authenticated: FALSE--, remote: remoteInterface#NIL--]]; smartsID _ EnterSmarts[party, smarts]; Log.Report[IO.PutFR["RegisterSmarts[%g, %s] -> [%g, %g]", TU.RefAddr[party], rope[SELECT properties.role FROM voiceTerminal=>"voice", manager=>"mgr", ENDCASE=>"NIY"], card[smartsID], TU.RefAddr[smarts]], $Party, party]; EXITS Failed => smartsID_nullHandle; }; GetHostParty: PROC[party: PartyData] RETURNS [hostParty: PartyData ] = { RETURN[NARROW[Triples.Select[$TrunkParty, Triples.Any, party]]]; }; RegisterClone: PUBLIC PROC[ shh: SHHH_none, partyID: PartyHandle, clonePartyID: PartyHandle, oldSmartsID: SmartsHandle_nullHandle ] RETURNS [smartsID: SmartsHandle] = { cloneParty: PartyData_ThPartyPrivate.DehandleParty[clonePartyID]; party: PartyData _ ThPartyPrivate.DehandleParty[partyID]; cloneSmarts: SmartsData; smData: SmartsData; IF party=NIL OR cloneParty=NIL THEN RETURN[nullHandle]; cloneSmarts _ NARROW[Triples.Select[$VoiceTerminal, cloneParty, -- Smarts --]]; IF cloneSmarts=NIL THEN RETURN[nullHandle]; smData_NEW[ ThPartyPrivate.SmartsBody _ [ interface: cloneSmarts.interface, properties: cloneSmarts.properties, shh: cloneSmarts.shh, authenticated: cloneSmarts.authenticated--, remote: cloneSmarts.remote--]]; smartsID _ EnterSmarts[party, smData]; Log.Report[IO.PutFR["RegisterClone[%g, %g] -> [%g, %g]", TU.RefAddr[party], TU.RefAddr[cloneParty], card[smartsID], TU.RefAddr[smData]], $Party, party]; }; Deregister: PUBLIC ENTRY PROC[shh: SHHH, smartsID: SmartsHandle] = { OPEN Triples; ENABLE { UNWIND => NULL; ANY => { Log.Problem[, $System]; CONTINUE; }; }; party: PartyData; cfRef: CFRef; smarts: SmartsData; CleanupParty: INTERNAL ForeachProc -- [trip: Triples.TripleRec] -- RETURNS [continue: BOOLEAN _ TRUE] -- = { WITH trip.att SELECT FROM r: CFRef => IF (party.numEnabled=0 OR r.voiceSmartsID = smartsID) AND r.event.state#idle THEN { cfRef _ r; [] _ ThPartyPrivate.DoAdvance[ smartsID: smartsID, party: party, conv: NARROW[trip.obj], cfRef: cfRef, state: idle, reason: terminating]; -- Idle party in conversation!! RETURN[FALSE]; }; ENDCASE; }; DeregisterOneParty: INTERNAL ForeachProc -- [trip: TripleRec] -- RETURNS [continue: BOOLEAN _ TRUE] -- = { WITH trip.obj SELECT FROM p: PartyData => party _ p; ENDCASE => RETURN; -- not a party to smarts connection Erase[trip.att, party, smarts -- (trip.val) --]; party.numSmarts _ party.numSmarts - 1; IF smarts.enablesParty THEN party.numEnabled _ party.numEnabled - 1; SELECT NARROW[trip.att, ATOM] FROM $Manager => { adjSmarts: SmartsData=NARROW[Select[$AdjacentTerminal, party, Any]]; Erase[$ManagerOwner, trip.val, Any]; IF adjSmarts#NIL THEN { Erase[$AdjacentTerminal, party, Any]; party.numSmarts _ party.numSmarts - 1; IF adjSmarts.enablesParty THEN party.numEnabled _ party.numEnabled - 1; }; }; ENDCASE; DO <> cfRef_NIL; Foreach[Any, Any, party, CleanupParty]; IF cfRef = NIL THEN EXIT; ENDLOOP; IF party.numSmarts = 0 THEN { <> party.partyFailed_TRUE; ThPartyPrivate.Supervise[party]; Log.ReportFR["DeleteParty[%g, %g]", $System, NIL, card[H[party]], TU.RefAddr[party]]; }; RETURN[FALSE]; }; smarts _ ThPartyPrivate.DehandleSmarts[smartsID]; IF smarts=NIL THEN RETURN; DO -- Outside loop avoids conflict when Deregister erases things. party_NIL; Foreach[Any, Any, smarts, DeregisterOneParty]; IF party = NIL THEN EXIT; ENDLOOP; Log.ReportFR["UnregisterSmarts[%g, %g]", $System, NIL, card[smartsID], TU.RefAddr[smarts]]; Thrush.KillHandle[smartsID, RTSmartsType! Thrush.HandleFault=>{Log.Problem["Problem killing smarts handle", $System]; CONTINUE}]; }; <<>> EnterSmarts: PROC[party: PartyData, smarts: SmartsData] RETURNS[smartsID: SmartsHandle] = { <> <> <> managerOwnerRAtom: ATOM_NIL; EnterSmartsE: ENTRY PROC RETURNS[smartsID: SmartsHandle] = -- INLINE -- { <> attr: ATOM=WITH props: smarts.properties SELECT FROM backstop=> $BackStop, manager=> $Manager, supervisor=> $Supervisor, voiceTerminal=> $VoiceTerminal, ENDCASE=>ERROR pERROR; smartsID _ Thrush.Enhandle[smarts]; Thrush.MakeUnique[attr, party, smarts]; party.numSmarts _ party.numSmarts + 1; IF smarts.enablesParty THEN party.numEnabled _ party.numEnabled + 1; WITH props: smarts.properties SELECT FROM <> manager => { OPEN Triples; Thrush.MakeUnique[$ManagerOwner, smarts, managerOwnerRAtom]; WITH Select[$RnameForParty, --party--, managerOwnerRAtom] SELECT FROM managerOwnerParty: PartyData => { mgrOwnSmarts: SmartsData _ NARROW[Select[$VoiceTerminal, managerOwnerParty, --smarts--]]; IF mgrOwnSmarts#NIL THEN { Thrush.MakeUnique[$AdjacentTerminal, party, mgrOwnSmarts]; party.numSmarts _ party.numSmarts + 1; IF mgrOwnSmarts.enablesParty THEN party.numEnabled _ party.numEnabled + 1; }; }; ENDCASE; }; <> voiceTerminal => IF party.type=individual THEN { OPEN Triples; managerOwnerSmarts: REF; managerOwnerParty: PartyData; managerOwnerRAtom _ NARROW[Select[$RnameForParty, party, -- rAtom --]]; IF managerOwnerRAtom=NIL THEN RETURN; -- This is really an Error, though. managerOwnerSmarts _ Select[$ManagerOwner, --smarts--, managerOwnerRAtom]; IF managerOwnerSmarts=NIL THEN RETURN; managerOwnerParty _ NARROW[Select[$Manager, -- party--, managerOwnerSmarts]]; IF managerOwnerParty=NIL THEN RETURN; Thrush.MakeUnique[$AdjacentTerminal, managerOwnerParty, smarts]; managerOwnerParty.numSmarts _ managerOwnerParty.numSmarts + 1; IF smarts.enablesParty THEN managerOwnerParty.numEnabled _ managerOwnerParty.numEnabled + 1; }; ENDCASE; }; WITH props: smarts.properties SELECT FROM <> manager => { managerOwner: _ NamesGV.GVGetAttribute[ rName: Names.InstanceFromNetAddress[props.machine, larkRegistry], attribute: $connect, default: NIL]; IF managerOwner#NIL THEN managerOwnerRAtom _ Names.MakeAtom[managerOwner]; }; ENDCASE; RETURN[EnterSmartsE[]]; }; Enable: PUBLIC ENTRY PROC[shh: SHHH_none, smartsID: SmartsHandle] RETURNS [nb: Thrush.NB] = { smarts: SmartsData=ThPartyPrivate.DehandleSmarts[smartsID]; IF smarts=NIL THEN RETURN[noSuchSmarts]; IF smarts.enablesParty THEN RETURN[success]; smarts.enablesParty_TRUE; RETURN[Able[smarts, 1]]; }; <<>> Disable: PUBLIC ENTRY PROC[shh: SHHH_none, smartsID: SmartsHandle] RETURNS [nb: Thrush.NB] = { smarts: SmartsData=ThPartyPrivate.DehandleSmarts[smartsID]; IF smarts=NIL THEN RETURN[noSuchSmarts]; IF ~smarts.enablesParty THEN RETURN[success]; smarts.enablesParty_FALSE; RETURN[Able[smarts, -1]]; }; Able: INTERNAL PROC[smarts: SmartsData, direction: INT] RETURNS[nb: Thrush.NB_success] = { AbleOne: Triples.ForeachProc -- [trip: TripleRec] -- RETURNS [continue: BOOLEAN _ TRUE] -- ={ WITH trip.obj SELECT FROM party: PartyData => { res: INT=party.numEnabled+direction; IF res<0 THEN nb_invalidTransition ELSE party.numEnabled _ res; }; ENDCASE; }; Triples.Foreach[Triples.Any, Triples.Any, smarts, AbleOne]; }; DescribeParty: PUBLIC ENTRY PROC[shh: SHHH_none, partyID: PartyHandle] RETURNS[ description: Thrush.ROPE] = { ENABLE UNWIND=>NULL; RETURN[DoDescribeParty[partyID]]; }; DoDescribeParty: PUBLIC INTERNAL PROC[ partyID: PartyHandle ] RETURNS[ description: Thrush.ROPE] = TRUSTED { party: PartyData = ThPartyPrivate.DehandleParty[partyID]; IF party=NIL THEN RETURN[NIL]; description _ GetRnameFromParty[party]; WITH p: party SELECT FROM individual => RETURN[description]; trunk => { more: ROPE=IF p.outgoing#NIL THEN p.outgoing ELSE "outside line"; IF description=NIL THEN description _ more ELSE description _ IO.PutFR["%s (%s)", IO.rope[description], IO.rope[more]]; RETURN[description]; }; recording => RETURN["Recording service"]; ENDCASE; }; <<>> GetRnameFromParty: PROC[party: PartyData] RETURNS [rName: Thrush.Rname] = { rRef: REF ANY; IF party=NIL THEN RETURN[NIL]; rRef _ Triples.Select[$RnameForParty, party, --rRef--]; IF rRef=NIL THEN rRef_Triples.Select[$RnameForTrunk, party, --rRef--]; IF rRef=NIL THEN RETURN[NIL]; RETURN[Atom.GetPName[NARROW[rRef]]]; }; <> GetCurrentParty: PUBLIC ENTRY PROC[shh: Thrush.SHHH_none, smartsID: Thrush.SmartsHandle] RETURNS [partyID: Thrush.PartyHandle_Thrush.nullHandle] = { <<| Should have an NB |>> ENABLE UNWIND=>NULL; smarts: REF _ ThPartyPrivate.DehandleSmarts[smartsID]; IF smarts=NIL THEN RETURN; FOR p: Thrush.Priorities _ standardPriorities, p.rest WHILE p#NIL DO FOR s: Thrush.Priorities _ NARROW[p.first], s.rest WHILE s#NIL DO att: ATOM_NARROW[s.first]; party: REF_Triples.Select[att, Triples.Any, smarts]; IF party#NIL THEN RETURN[H[party]]; ENDLOOP; ENDLOOP; }; GetPartySmarts: PUBLIC ENTRY PROC[partyID: Thrush.PartyHandle, kind: ATOM ] RETURNS [smartsID: Thrush.SmartsHandle]={ ENABLE UNWIND=>NULL; party: PartyData_ThPartyPrivate.DehandleParty[partyID]; IF party=NIL THEN RETURN [Thrush.nullHandle]; RETURN[H[Triples.Select[kind, party, --smarts--]]]; }; ReportSystem: Log.WhereProc = CHECKED { s_Nice.LarkConLogStream[[[0],[0]]]; }; ReportParty: Log.WhereProc = TRUSTED { party: PartyData = NARROW[whereData]; IF party#NIL THEN { smarts: SmartsData = NARROW[Triples.Select[$VoiceTerminal, party, Triples.Any]]; IF smarts#NIL THEN WITH props: smarts.properties SELECT FROM voiceTerminal => s_Nice.LarkConLogStream[props.machine]; ENDCASE; }; IF s=NIL THEN s _ Log.FindWhere[$System, NIL]; }; myName: ThPartyRpcControl.InterfaceName_ [ type: "ThParty.Lark", instance: UserProfile.Token[key: "ThrushServerInstance", default: "Morley.Lark"], version: ThVersions.ThrushVR]; serverPassword: RPC.EncryptionKey = Names.CurrentPasskey[UserProfile.Token[ key: "ThrushServerPassword", default: "MFLFLX"]]; wpState: ThNet.WPState; ThPartyInit: PROC = { ENABLE RPC.ExportFailed => { Log.Problem["ThParty export failed", $System]; GOTO Failed; }; Log.RegisterWhereToReport[ReportSystem, $System]; Log.RegisterWhereToReport[ReportParty, $Party]; wpState _ ThNet.InitWhitePagesDatabase[ UserProfile.Token[key: "ThrushWPTreeName", default: "///Strowger/WPTree"]]; ThPartyRpcControl.ExportInterface[ interfaceName: myName, user: myName.instance, password: serverPassword]; Log.ReportFR["Export[ThParty.Lark, %s", $System, NIL, rope[myName.instance]]; EXITS Failed => ThPartyRpcControl.UnexportInterface[!LupineRuntime.BindingError=>CONTINUE]; }; ThPartyInit[]; }.