diff --git a/README b/README deleted file mode 100644 index a290336..0000000 --- a/README +++ /dev/null @@ -1,22 +0,0 @@ -Whisper OpenSim Voice Module -============================ - -For a detailed documentation, please check doc/Whisper_Murmur_Config.pdf - -Many thanks to Snoopy Pfeffer, Justin Clark-Casey, and Brian Becker for making this release possible. - -Release Notes -============= -0.2.0 ------ -- updated to compile for OpenSim 0.7.1+ (thanks to Justin) -- grid support (thanks Snoopy) -- glacier2 support (thanks Brian) - -0.1.0 ------ -- initial version -- for OpenSim standalone configuration - ---------------------------------- -Contact: volker.gaessler@vcomm.ch \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b46aee1 --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +#Whisper OpenSim Voice Module# + +For detailed documentation please check [CONFIG]. + +#Building# + +To use Whisper, one has to + +1. Build and/or install the OpenSimulator module. +2. Build and/or install the Murmur viewer executable (which currently replaces SLVoice.exe in the viewer) +3. Run a murmur server to route voice data between viewers after channels have been established via the +OpenSimulator module. + +For detailed instructions on 2 and 3, please see [CONFIG]. Here, we will describe the process of building and +configuring the OpenSimulator module in a bit more detail. + +##Building the OpenSimulator module## + +1. Copy this directory to $OPENSIM_BASE/addon-modules/Whisper +2. Follow the instructions at [MODULE BUILD] to build the module. This will copy the generated DLL automatically +into your $OPENSIM_BASE/bin directory. + +##Installing the OpenSimulator module## + +Alternatively, you can install the prebuilt bin/Whisper.dll into $OPENSIM_BASE/bin. This was built under +Mono but should work on other systems. You will also need to copy over bin/Ice.dll and bin/Glacier2.dll if you +are going to use the Glacier option. + +## Configuring the module## + +1. Copy the contents of the OpenSim.ini.include file into your OpenSim.ini + +#References# + +[CONFIG] - doc/Whisper_Murmur_Config.pdf +[MODULE BUILD] - http://opensimulator.org/wiki/IRegionModule#Building_Region_Modules + +#Release Notes# + +##Development## +- updated to compile from OpenSim 0.7.3 to 0.8 and current OpenSimulator dev code. + +##0.2.0## +- updated to compile for OpenSim 0.7.1+ (thanks to Justin) +- grid support (thanks Snoopy) +- glacier2 support (thanks Brian) + +##0.1.0## +- initial version +- for OpenSim standalone configuration + +#Credits# +* Volker Gaessler (vcomm.ch) +* Snoopy Pfeffer (dreamlandmetaverse.com) +* Justin Clark-Casey (justincc.org) +* Brian Becker diff --git a/Whisper/Modules/Murmur.cs b/Whisper/Modules/Murmur.cs index dd5be15..2d5d2f3 100644 --- a/Whisper/Modules/Murmur.cs +++ b/Whisper/Modules/Murmur.cs @@ -10,8 +10,6 @@ // Ice version 3.3.1 // Generated from file `Murmur.ice' -/// Original source at https://github.com/vgaessler/whisper_server - #if __MonoCS__ using _System = System; diff --git a/Whisper/Modules/MurmurVoiceModule.cs b/Whisper/Modules/MurmurVoiceModule.cs index 58de7ed..14aca4c 100644 --- a/Whisper/Modules/MurmurVoiceModule.cs +++ b/Whisper/Modules/MurmurVoiceModule.cs @@ -18,7 +18,6 @@ * along with this program. If not, see . */ -/// Original source at https://github.com/vgaessler/whisper_server using Mono.Addins; using System; using System.IO; @@ -27,6 +26,7 @@ using System.Threading; using System.Collections.Generic; using System.Reflection; +using System.Xml; using log4net; using Nini.Config; using OpenMetaverse; @@ -366,13 +366,17 @@ public Agent GetOrCreate(UUID uuid, Scene scene) { string name = Agent.Name(uuid); lock (name_to_agent) + { if (name_to_agent.ContainsKey(name)) + { return (name_to_agent[name].session < 0 ? null : name_to_agent[name]); + } else { Agent a = Add(uuid, scene); return a; } + } } public void RemoveAgent(UUID uuid) @@ -382,8 +386,7 @@ public void RemoveAgent(UUID uuid) m_log.DebugFormat("[MurmurVoice] Removing registered user {0}", user.name); lock (name_to_agent) - if (name_to_agent.ContainsKey(user.name)) - name_to_agent.Remove(user.name); + name_to_agent.Remove(user.name); } private Agent Add(UUID uuid, Scene scene) @@ -398,12 +401,16 @@ private Agent Add(UUID uuid, Scene scene) if (user.name == agent.name) { - m_log.DebugFormat("[MurmurVoice] Found previously registered user {0} {1} {2} {3}", user.name, user.userid, user.session, user.channel); + m_log.DebugFormat( + "[MurmurVoice] Found previously registered user {0} {1} {2} {3}", + user.name, user.userid, user.session, user.channel); if ((user.userid >= 0) && (user.session >= 0)) { // Reuse Murmur User - m_log.DebugFormat("[MurmurVoice] Reusing previously registered user {0} {1} {2} {3}", user.name, user.userid, user.session, user.channel); + m_log.DebugFormat( + "[MurmurVoice] Reusing previously registered user {0} {1} {2} {3}", + user.name, user.userid, user.session, user.channel); agent.userid = user.userid; agent.session = user.session; @@ -441,15 +448,26 @@ private Agent Add(UUID uuid, Scene scene) try { + m_log.DebugFormat( + "[MurmurVoice]: Registering user {0} {1} password {2} with Murmur server", + agent.name, agent.uuid, agent.pass); + int r = m_server.registerUser(agent.user_info); - if (r >= 0) agent.userid = r; + if (r >= 0) + agent.userid = r; } - catch (Murmur.InvalidUserException) + catch (Murmur.InvalidUserException e) { - m_log.Warn("[MurmurVoice] InvalidUserException; continuing to recover later"); + m_log.WarnFormat( + "[MurmurVoice] InvalidUserException; {0}{1}", + e.Message, e.StackTrace); + + return null; } - m_log.DebugFormat("[MurmurVoice] Registered {0} (uid {1}) identified by {2}", agent.uuid.ToString(), agent.userid, agent.pass); + m_log.DebugFormat( + "[MurmurVoice] Registered {0} {1} (Murmur uid {2}) identified by {3}", + agent.name, agent.uuid, agent.userid, agent.pass); return agent; } @@ -542,7 +560,7 @@ public class MurmurVoiceModule : ISharedRegionModule private static string m_glacier_user; private static string m_glacier_pass; private static string m_murmur_ice_cb; - private static string m_channel_name; + private static string m_parent_channel_name; private static Dictionary m_managers = new Dictionary(); private static Dictionary m_servercallbacks = new Dictionary(); private static bool m_enabled = false; @@ -584,13 +602,13 @@ public void Initialise(IConfigSource config) if (null == m_config) { - m_log.Info("[MurmurVoice] no config found, plugin disabled"); + m_log.Info("[MurmurVoice] No config found, plugin disabled"); return; } if (!m_config.GetBoolean("enabled", false)) { - m_log.Info("[MurmurVoice] plugin disabled by configuration"); + m_log.Info("[MurmurVoice] Plugin disabled by configuration"); return; } @@ -600,7 +618,7 @@ public void Initialise(IConfigSource config) m_murmurd_ice = "Meta:" + m_config.GetString("murmur_ice", String.Empty); m_murmur_ice_cb = m_config.GetString("murmur_ice_cb", "tcp -h 127.0.0.1"); - m_channel_name = m_config.GetString("channel_name", "Channel").Replace(" ","_"); + m_parent_channel_name = m_config.GetString("channel_name", "Channel").Replace(" ","_"); m_glacier_enabled = m_config.GetBoolean("glacier", false); m_glacier_ice = m_config.GetString("glacier_ice", String.Empty); @@ -611,11 +629,11 @@ public void Initialise(IConfigSource config) if (String.IsNullOrEmpty(m_murmurd_ice) || String.IsNullOrEmpty(m_murmurd_host) ) { - m_log.Error("[MurmurVoice] plugin disabled: incomplete configuration"); + m_log.Error("[MurmurVoice] Plugin disabled: incomplete configuration"); return; } - m_log.Info("[MurmurVoice] enabled"); + m_log.Info("[MurmurVoice] Enabled"); m_enabled = true; } @@ -629,13 +647,13 @@ public void Initialize(Scene scene) { m_started = true; - scene.AddCommand(this, "mumble report", "mumble report", + scene.AddCommand("Mumble", this, "mumble report", "mumble report", "Returns mumble report", MumbleReport); - scene.AddCommand(this, "mumble unregister", "mumble unregister ", + scene.AddCommand("Mumble", this, "mumble unregister", "mumble unregister ", "Unregister User by userid", UnregisterUser); - scene.AddCommand(this, "mumble remove", "mumble remove ", + scene.AddCommand("Mumble", this, "mumble remove", "mumble remove ", "Remove Agent by UUID", RemoveAgent); Ice.Communicator comm = Ice.Util.initialize(); @@ -647,14 +665,23 @@ public void Initialize(Scene scene) m_router.createSession(m_glacier_user, m_glacier_pass); } + m_log.DebugFormat("[MurmurVoice] Setting up connection to mumble server at {0}", m_murmurd_ice); + MetaPrx meta = MetaPrxHelper.checkedCast(comm.stringToProxy(m_murmurd_ice)); // Create the adapter comm.getProperties().setProperty("Ice.PrintAdapterReady", "0"); if (m_glacier_enabled) - m_adapter = comm.createObjectAdapterWithRouter("Callback.Client", comm.getDefaultRouter() ); + { + m_log.DebugFormat("[MurmurVoice] Setting up Glacier callback"); + m_adapter = comm.createObjectAdapterWithRouter("Callback.Client", comm.getDefaultRouter()); + } else + { + m_log.DebugFormat("[MurmurVoice] Setting up non-Glacier callback listener {0}", m_murmur_ice_cb); m_adapter = comm.createObjectAdapterWithEndpoints("Callback.Client", m_murmur_ice_cb); + } + m_adapter.activate(); // Create identity and callback for Metaserver @@ -662,10 +689,11 @@ public void Initialize(Scene scene) metaCallbackIdent.name = "metaCallback"; if (m_router != null) metaCallbackIdent.category = m_router.getCategoryForClient(); - MetaCallbackPrx meta_callback = MetaCallbackPrxHelper.checkedCast(m_adapter.add(new MetaCallbackImpl(), metaCallbackIdent)); + MetaCallbackPrx meta_callback + = MetaCallbackPrxHelper.checkedCast(m_adapter.add(new MetaCallbackImpl(), metaCallbackIdent)); meta.addCallback(meta_callback); - m_log.InfoFormat("[MurmurVoice] using murmur server ice '{0}'", m_murmurd_ice); + m_log.InfoFormat("[MurmurVoice] Using murmur server ice '{0}'", m_murmurd_ice); // create a server and figure out the port name Dictionary defaults = meta.getDefaultConf(); @@ -692,11 +720,11 @@ public void Initialize(Scene scene) { } - m_log.Info("[MurmurVoice] started"); + m_log.Info("[MurmurVoice] Started"); } // starts the server and gets a callback - ServerManager manager = new ServerManager(m_server, m_channel_name); + ServerManager manager = new ServerManager(m_server, m_parent_channel_name); // Create identity and callback for this current server AddServerCallback(scene, new ServerCallbackImpl(manager)); @@ -707,16 +735,23 @@ public void Initialize(Scene scene) if (m_router != null) serverCallbackIdent.category = m_router.getCategoryForClient(); - m_server.addCallback(ServerCallbackPrxHelper.checkedCast(m_adapter.add(GetServerCallback(scene), serverCallbackIdent))); + m_log.DebugFormat( + "[MurmurVoice] Adding murmur ICE ServerCallback {0} at listener {1}", + serverCallbackIdent.name, m_murmur_ice_cb); + m_server.addCallback( + ServerCallbackPrxHelper.checkedCast(m_adapter.add(GetServerCallback(scene), serverCallbackIdent))); // Show information on console for debugging purposes - m_log.InfoFormat("[MurmurVoice] using murmur server '{0}:{1}', sid '{2}'", m_murmurd_host, m_murmurd_port, m_server_id); - m_log.Info("[MurmurVoice] plugin enabled"); + m_log.InfoFormat( + "[MurmurVoice] Murmur server address for clients is '{0}:{1}', sid '{2}'", + m_murmurd_host, m_murmurd_port, m_server_id); + + m_log.Info("[MurmurVoice] Plugin enabled"); m_enabled = true; } catch (Exception e) { - m_log.ErrorFormat("[MurmurVoice] plugin initialization failed: {0}", e.ToString()); + m_log.Error("[MurmurVoice] Plugin initialization failed, ", e); return; } } @@ -758,11 +793,12 @@ public void RemovePresence(UUID agentID) public void ClientClosed(UUID agentID, Scene scene) { - m_log.DebugFormat("[MurmurVoice]: ClientClosed {0}", agentID); + m_log.DebugFormat("[MurmurVoice]: ClientClosed {0} on {1}", agentID, scene.RegionInfo.RegionName); ScenePresence avatar = scene.GetScenePresence(agentID); - if ((avatar == null) || (avatar.IsChildAgent)) return; + if ((avatar == null) || (avatar.IsChildAgent)) + return; GetServerManager(scene).Agent.RemoveAgent(agentID); } @@ -824,19 +860,18 @@ private string ChannelName(Scene scene, LandData land) { // Create parcel voice channel. If no parcel exists, then the voice channel ID is the same // as the directory ID. Otherwise, it reflects the parcel's ID. + string channelName; if (land.LocalID != 1 && (land.Flags & (uint)ParcelFlags.UseEstateVoiceChan) == 0) - { - m_log.DebugFormat("[MurmurVoice]: Region: parcel \"{0}:{1}\": parcel id {2} {3}", - scene.RegionInfo.RegionName, land.Name, land.LocalID, land.GlobalID.ToString().Replace("-","")); - return land.GlobalID.ToString().Replace("-",""); - } + channelName = land.GlobalID.ToString().Replace("-",""); else - { - m_log.DebugFormat("[MurmurVoice]: Region: parcel \"{0}:{1}\": parcel id {2} {3}", - scene.RegionInfo.RegionName, scene.RegionInfo.RegionName, land.LocalID, scene.RegionInfo.RegionID.ToString().Replace("-","")); - return scene.RegionInfo.RegionID.ToString().Replace("-",""); - } + channelName = scene.RegionInfo.RegionID.ToString().Replace("-",""); + + m_log.DebugFormat( + "[MurmurVoice]: Channel name {0} for region:parcel \"{1}:{2}\": parcel id {3}", + scene.RegionInfo.RegionName, land.Name, land.LocalID, channelName); + + return channelName; } // OnRegisterCaps is invoked via the scene.EventManager @@ -863,7 +898,7 @@ public void OnRegisterCaps(Scene scene, UUID agentID, Caps caps) caps.RegisterHandler("ProvisionVoiceAccountRequest", new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath, delegate(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { return ProvisionVoiceAccountRequest(scene, request, path, param, agentID); @@ -871,7 +906,7 @@ public void OnRegisterCaps(Scene scene, UUID agentID, Caps caps) caps.RegisterHandler("ParcelVoiceInfoRequest", new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath, delegate(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { return ParcelVoiceInfoRequest(scene, request, path, param, agentID); @@ -879,7 +914,7 @@ public void OnRegisterCaps(Scene scene, UUID agentID, Caps caps) caps.RegisterHandler("ChatSessionRequest", new RestStreamHandler("POST", capsBase + m_chatSessionRequestPath, delegate(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { return ChatSessionRequest(scene, request, path, param, agentID); @@ -889,13 +924,21 @@ public void OnRegisterCaps(Scene scene, UUID agentID, Caps caps) caps.RegisterHandler("mumble_server_info", new RestStreamHandler("GET", capsBase + m_chatSessionRequestPath, delegate(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { return RestGetMumbleServerInfo(scene, request, path, param, httpRequest, httpResponse); })); } + /// /// Callback for a client request for Voice Account Details. + /// + /// + /// + /// + /// + /// + /// public string ProvisionVoiceAccountRequest(Scene scene, string request, string path, string param, UUID agentID) { @@ -931,12 +974,20 @@ public string ProvisionVoiceAccountRequest(Scene scene, string request, string p } catch (Exception e) { - m_log.DebugFormat("[MurmurVoice] {0} failed", e.ToString()); + m_log.DebugFormat("[MurmurVoice] Exception {0}{1}", e.Message, e.StackTrace); return ""; } } - /// Callback for a client request for ParcelVoiceInfo + /// + /// Handle the client request to the ParcelVoiceInfoRequest capability. + /// + /// + /// + /// + /// + /// + /// public string ParcelVoiceInfoRequest(Scene scene, string request, string path, string param, UUID agentID) { @@ -970,7 +1021,9 @@ public string ParcelVoiceInfoRequest(Scene scene, string request, string path, s if (agent == null) { - m_log.ErrorFormat("[MurmurVoice] Agent not connected {0}", agentID); + m_log.WarnFormat( + "[MurmurVoice] Agent {0} not registered with Murmur server. Waiting for retry by viewer.", + agentID); return ""; } @@ -983,7 +1036,8 @@ public string ParcelVoiceInfoRequest(Scene scene, string request, string path, s { if (++retry > 50) { - m_log.ErrorFormat("[MurmurVoice] Connecting failed {0} (uid {1}) identified by {2}", agent.uuid.ToString(), agent.userid, agent.pass); + m_log.ErrorFormat("[MurmurVoice] Connecting failed {0} (uid {1}) identified by {2}", + agent.uuid, agent.userid, agent.pass); return ""; } @@ -997,7 +1051,7 @@ public string ParcelVoiceInfoRequest(Scene scene, string request, string path, s Murmur.User state = manager.Server.getState(agent.session); GetServerCallback(scene).AddUserToChan(state, agent.channel); - m_log.DebugFormat("[MurmurVoice] {0}", channel_uri); +// m_log.DebugFormat("[MurmurVoice] {0}", channel_uri); } else { @@ -1007,7 +1061,8 @@ public string ParcelVoiceInfoRequest(Scene scene, string request, string path, s Hashtable creds = new Hashtable(); creds["channel_uri"] = channel_uri; - LLSDParcelVoiceInfoResponse parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds); + LLSDParcelVoiceInfoResponse parcelVoiceInfo + = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds); string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); m_log.DebugFormat("[MurmurVoice] Parcel: {0}", r); @@ -1015,7 +1070,7 @@ public string ParcelVoiceInfoRequest(Scene scene, string request, string path, s } catch (Exception e) { - m_log.ErrorFormat("[MurmurVoice] Exception: " + e.ToString()); + m_log.Error("[MurmurVoice] Exception, ", e); return ""; } } @@ -1042,7 +1097,7 @@ public string ChatSessionRequest(Scene scene, string request, string path, strin /// HTTP response header object /// Information about the mumble server in http response headers public string RestGetMumbleServerInfo(Scene scene, string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { if (m_murmurd_host == null) { @@ -1053,6 +1108,7 @@ public string RestGetMumbleServerInfo(Scene scene, string request, string path, m_log.Warn(message); return "Mumble server info is not available."; } + if (httpRequest.Headers.GetValues("avatar_uuid") == null) { httpResponse.StatusCode = 400; @@ -1102,7 +1158,7 @@ public string RestGetMumbleServerInfo(Scene scene, string request, string path, GetServerCallback(scene).AddUserToChan(state, agent.channel); } - m_log.InfoFormat("[MurmurVoice] {0}", channel_uri); + m_log.InfoFormat("[MurmurVoice] channel_uri {0}", channel_uri); } else { @@ -1158,6 +1214,8 @@ private void MumbleReport(string module, string[] args) Dictionary users = m_server.getUsers(); + m_log.InfoFormat("Users Connected: {0}", users.Count); + foreach (var v in users) { User user = v.Value; @@ -1207,4 +1265,4 @@ private void RemoveAgent(string module, string[] args) } #endregion -} +} \ No newline at end of file diff --git a/bin/Whisper.dll b/bin/Whisper.dll index b01abac..cc6663f 100644 Binary files a/bin/Whisper.dll and b/bin/Whisper.dll differ diff --git a/Whisper/prebuild.xml b/prebuild.xml similarity index 61% rename from Whisper/prebuild.xml rename to prebuild.xml index efd6611..55c7a43 100644 --- a/Whisper/prebuild.xml +++ b/prebuild.xml @@ -1,37 +1,37 @@ - + - ../../../bin/ + ../../../../bin/ - ../../../bin/ + ../../../../bin/ - ../../../bin/ + ../../../../bin/ - ../../../bin/ + ../../../../bin/ - ../../../bin/ + ../../../../bin/ - ../../../bin/ + ../../../../bin/ - ../../../bin/ + ../../../../bin/ @@ -40,9 +40,9 @@ - - - + + + @@ -51,11 +51,11 @@ - - - - - + + + + +