/// <summary> /// Callback for a client request for ParcelVoiceInfo /// </summary> /// <param name="scene">current scene object of the client</param> /// <param name="request"></param> /// <param name="path"></param> /// <param name="param"></param> /// <param name="agentID"></param> /// <param name="caps"></param> /// <returns></returns> public string ParcelVoiceInfoRequest(Scene scene, string request, string path, string param, UUID agentID, Caps caps) { ScenePresence avatar = scene.GetScenePresence(agentID); string avatarName = avatar.Name; // - check whether we have a region channel in our cache // - if not: // create it and cache it // - send it to the client // - send channel_uri: as "sip:regionID@m_sipDomain" try { LLSDParcelVoiceInfoResponse parcelVoiceInfo; string channelUri; if (null == scene.LandChannel) { throw new Exception(String.Format("retion \"{0}\": avatar \"{1}\": land data not yet available", scene.RegionInfo.Regionname, avatarName)); } // get channel_uri: check first whether estate // settings allow voice, then whether parcel allows // voice, if all do retrieve or obtain the parcel // voice channel LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); m_log.DebugFormat("[Free Switch Voice][Parcel Voice]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); if ((land.Flags & (uint)Parcel.ParcelFlags.AllowVoiceChat) == 0) { m_log.DebugFormat("[Free Switch Voice][Parcel Voice]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel", scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName); channelUri = String.Empty; } else { channelUri = ChannelUri(scene, land); } // fill in our response to the client Hashtable creds = new Hashtable(); creds["channel_uri"] = channelUri; parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds); string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); m_log.DebugFormat("[Free Switch Voice][Parcel Voice]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}", scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r); return(r); } catch (Exception e) { m_log.ErrorFormat("[Free Switch Voice][Parcel Voice]: region \"{0}\": avatar \"{1}\": {2}, retry later", scene.RegionInfo.RegionName, avatarName, e.Message); m_log.DebugFormat("[Free Switch Voice][Parcel Voice]: region \"{0}\": avatar \"{1}\": {2} failed", scene.RegionInfo.RegionName, avatarName, e.ToString()); return("<llsd>undef</llsd>"); } }
/// Callback for a client request for ParcelVoiceInfo public string ParcelVoiceInfoRequest(Scene scene, string request, string path, string param, UUID agentID) { m_log.Debug("[MurmurVoice] Calling ParcelVoiceInfoRequest..."); try { ScenePresence avatar = scene.GetScenePresence(agentID); string channel_uri = String.Empty; if (null == scene.LandChannel) { throw new Exception(String.Format("region \"{0}\": avatar \"{1}\": land data not yet available", scene.RegionInfo.RegionName, avatar.Name)); } // get channel_uri: check first whether estate // settings allow voice, then whether parcel allows // voice, if all do retrieve or obtain the parcel // voice channel LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); if (null == land) { throw new Exception(String.Format("region \"{0}\": avatar \"{1}\": land data not yet available", scene.RegionInfo.RegionName, avatar.Name)); } m_log.DebugFormat("[MurmurVoice] region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", scene.RegionInfo.RegionName, land.Name, land.LocalID, avatar.Name, request, path, param); if (((land.Flags & (uint)ParcelFlags.AllowVoiceChat) > 0) && scene.RegionInfo.EstateSettings.AllowVoice) { ServerManager manager = GetServerManager(scene); Agent agent = manager.Agent.GetOrCreate(agentID, scene); if (agent == null) { m_log.ErrorFormat("[MurmurVoice] Agent not connected {0}", agentID); return("<llsd><undef /></llsd>"); } agent.channel = manager.Channel.GetOrCreate(ChannelName(scene, land)); // Wait for session connect int retry = 0; while (agent.session < 0) { if (++retry > 50) { m_log.ErrorFormat("[MurmurVoice] Connecting failed {0} (uid {1}) identified by {2}", agent.uuid.ToString(), agent.userid, agent.pass); return("<llsd><undef /></llsd>"); } Thread.Sleep(200); } // Host/port pair for voice server channel_uri = String.Format("{0}:{1}", m_murmurd_host, m_murmurd_port); Murmur.User state = manager.Server.getState(agent.session); GetServerCallback(scene).AddUserToChan(state, agent.channel); m_log.DebugFormat("[MurmurVoice] {0}", channel_uri); } else { m_log.DebugFormat("[MurmurVoice] Voice not enabled."); } Hashtable creds = new Hashtable(); creds["channel_uri"] = channel_uri; LLSDParcelVoiceInfoResponse parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds); string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); m_log.DebugFormat("[MurmurVoice] Parcel: {0}", r); return(r); } catch (Exception e) { m_log.ErrorFormat("[MurmurVoice] Exception: " + e.ToString()); return("<llsd><undef /></llsd>"); } }
public string ParcelVoiceInfoRequest(Scene scene, string request, string path, string param, UUID agentID, Caps caps) { m_log.DebugFormat( "[FreeSwitchVoice][PARCELVOICE]: ParcelVoiceInfoRequest() request: {0}, path: {1}, param: {2}", request, path, param); ScenePresence avatar = scene.GetScenePresence(agentID); if (avatar == null) // seen on the main grid, perhaps on user disconnect or viewer crash { return(EMPTY_RESPONSE); } string avatarName = avatar.Name; // - check whether we have a region channel in our cache // - if not: // create it and cache it // - send it to the client // - send channel_uri: as "sip:regionID@m_sipDomain" try { LLSDParcelVoiceInfoResponse parcelVoiceInfo; string channel_uri; if (null == scene.LandChannel) { throw new Exception(String.Format("region \"{0}\": avatar \"{1}\": land data not yet available", scene.RegionInfo.RegionName, avatarName)); } // If the avatar is in transit between regions, avatar.AbsolutePosition calls below can return undefined values. if (avatar.IsInTransit) { m_log.WarnFormat("[FreeSwitchVoice][PARCELVOICE]: Cannot process voice info request - avatar {0} is still in transit between regions.", avatarName); return(EMPTY_RESPONSE); } // get channel_uri: check first whether estate // settings allow voice, then whether parcel allows // voice, if all do retrieve or obtain the parcel // voice channel Vector3 pos = avatar.AbsolutePosition; // take a copy to avoid double recalc LandData land = scene.GetLandData(pos.X, pos.Y); if (land == null) { // m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": avatar\"{1}\" at ({2}): Land parcel not found.", // scene.RegionInfo.RegionName, avatarName, pos.ToString()); return(EMPTY_RESPONSE); } // TODO: EstateSettings don't seem to get propagated... if (!scene.RegionInfo.EstateSettings.AllowVoice) { m_log.InfoFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": voice not enabled in estate settings", scene.RegionInfo.RegionName); channel_uri = String.Empty; } if ((land.Flags & (uint)ParcelFlags.AllowVoiceChat) == 0) { m_log.InfoFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel", scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName); channel_uri = String.Empty; } else { channel_uri = RegionGetOrCreateChannel(scene, land); } // fill in our response to the client Hashtable creds = new Hashtable(); creds["channel_uri"] = channel_uri; parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds); string r = LLSDHelpers.SerializeLLSDReply(parcelVoiceInfo); return(r); } catch (Exception e) { m_log.ErrorFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": avatar \"{1}\": {2} failed", scene.RegionInfo.RegionName, avatarName, e.Message); m_log.ErrorFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": avatar \"{1}\": {2} exception", scene.RegionInfo.RegionName, avatarName, e.ToString()); return(EMPTY_RESPONSE); } }