diff options
14 files changed, 318 insertions, 756 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 58ece34..79e31c1 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs | |||
@@ -265,9 +265,9 @@ namespace OpenSim | |||
265 | LoadOar); | 265 | LoadOar); |
266 | 266 | ||
267 | m_console.Commands.AddCommand("region", false, "save oar", | 267 | m_console.Commands.AddCommand("region", false, "save oar", |
268 | "save oar [-v|version=N] [<OAR path>]", | 268 | "save oar [-v|--version=N] [<OAR path>]", |
269 | "Save a region's data to an OAR archive.", | 269 | "Save a region's data to an OAR archive.", |
270 | "-v|version=N generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine | 270 | "-v|--version=N generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine |
271 | + "The OAR path must be a filesystem path." | 271 | + "The OAR path must be a filesystem path." |
272 | + " If this is not given then the oar is saved to region.oar in the current directory.", | 272 | + " If this is not given then the oar is saved to region.oar in the current directory.", |
273 | SaveOar); | 273 | SaveOar); |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 1f85278..702eab9 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs | |||
@@ -56,7 +56,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
56 | /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version | 56 | /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version |
57 | /// bumps here should be compatible. | 57 | /// bumps here should be compatible. |
58 | /// </summary> | 58 | /// </summary> |
59 | public static int MAX_MAJOR_VERSION = 0; | 59 | public static int MAX_MAJOR_VERSION = 1; |
60 | 60 | ||
61 | protected Scene m_scene; | 61 | protected Scene m_scene; |
62 | protected Stream m_loadStream; | 62 | protected Stream m_loadStream; |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 0567a82..b987b5a 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs | |||
@@ -49,7 +49,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
49 | public class ArchiveWriteRequestPreparation | 49 | public class ArchiveWriteRequestPreparation |
50 | { | 50 | { |
51 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 51 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
52 | 52 | ||
53 | /// <summary> | ||
54 | /// The minimum major version of OAR that we can write. | ||
55 | /// </summary> | ||
56 | public static int MIN_MAJOR_VERSION = 0; | ||
57 | |||
58 | /// <summary> | ||
59 | /// The maximum major version of OAR that we can write. | ||
60 | /// </summary> | ||
61 | public static int MAX_MAJOR_VERSION = 1; | ||
62 | |||
53 | protected Scene m_scene; | 63 | protected Scene m_scene; |
54 | protected Stream m_saveStream; | 64 | protected Stream m_saveStream; |
55 | protected Guid m_requestId; | 65 | protected Guid m_requestId; |
@@ -101,110 +111,137 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
101 | /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> | 111 | /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> |
102 | public void ArchiveRegion(Dictionary<string, object> options) | 112 | public void ArchiveRegion(Dictionary<string, object> options) |
103 | { | 113 | { |
104 | Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>(); | 114 | try |
105 | 115 | { | |
106 | EntityBase[] entities = m_scene.GetEntities(); | 116 | Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>(); |
107 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); | 117 | |
108 | 118 | EntityBase[] entities = m_scene.GetEntities(); | |
109 | /* | 119 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); |
110 | foreach (ILandObject lo in m_scene.LandChannel.AllParcels()) | 120 | |
121 | /* | ||
122 | foreach (ILandObject lo in m_scene.LandChannel.AllParcels()) | ||
123 | { | ||
124 | if (name == lo.LandData.Name) | ||
125 | { | ||
126 | // This is the parcel we want | ||
127 | } | ||
128 | } | ||
129 | */ | ||
130 | |||
131 | // Filter entities so that we only have scene objects. | ||
132 | // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods | ||
133 | // end up having to do this | ||
134 | foreach (EntityBase entity in entities) | ||
111 | { | 135 | { |
112 | if (name == lo.LandData.Name) | 136 | if (entity is SceneObjectGroup) |
113 | { | 137 | { |
114 | // This is the parcel we want | 138 | SceneObjectGroup sceneObject = (SceneObjectGroup)entity; |
139 | |||
140 | if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) | ||
141 | sceneObjects.Add((SceneObjectGroup)entity); | ||
115 | } | 142 | } |
116 | } | 143 | } |
117 | */ | 144 | |
118 | 145 | UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); | |
119 | // Filter entities so that we only have scene objects. | 146 | |
120 | // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods | 147 | foreach (SceneObjectGroup sceneObject in sceneObjects) |
121 | // end up having to do this | ||
122 | foreach (EntityBase entity in entities) | ||
123 | { | ||
124 | if (entity is SceneObjectGroup) | ||
125 | { | 148 | { |
126 | SceneObjectGroup sceneObject = (SceneObjectGroup)entity; | 149 | assetGatherer.GatherAssetUuids(sceneObject, assetUuids); |
127 | |||
128 | if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) | ||
129 | sceneObjects.Add((SceneObjectGroup)entity); | ||
130 | } | 150 | } |
151 | |||
152 | m_log.DebugFormat( | ||
153 | "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", | ||
154 | sceneObjects.Count, assetUuids.Count); | ||
155 | |||
156 | // Make sure that we also request terrain texture assets | ||
157 | RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; | ||
158 | |||
159 | if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) | ||
160 | assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; | ||
161 | |||
162 | if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) | ||
163 | assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; | ||
164 | |||
165 | if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) | ||
166 | assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; | ||
167 | |||
168 | if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) | ||
169 | assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; | ||
170 | |||
171 | TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); | ||
172 | |||
173 | // Asynchronously request all the assets required to perform this archive operation | ||
174 | ArchiveWriteRequestExecution awre | ||
175 | = new ArchiveWriteRequestExecution( | ||
176 | sceneObjects, | ||
177 | m_scene.RequestModuleInterface<ITerrainModule>(), | ||
178 | m_scene.RequestModuleInterface<IRegionSerialiserModule>(), | ||
179 | m_scene, | ||
180 | archiveWriter, | ||
181 | m_requestId, | ||
182 | options); | ||
183 | |||
184 | m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); | ||
185 | |||
186 | // Write out control file. This has to be done first so that subsequent loaders will see this file first | ||
187 | // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this | ||
188 | archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options)); | ||
189 | m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); | ||
190 | |||
191 | new AssetsRequest( | ||
192 | new AssetsArchiver(archiveWriter), assetUuids, | ||
193 | m_scene.AssetService, awre.ReceivedAllAssets).Execute(); | ||
131 | } | 194 | } |
132 | 195 | catch (Exception) | |
133 | UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); | ||
134 | |||
135 | foreach (SceneObjectGroup sceneObject in sceneObjects) | ||
136 | { | 196 | { |
137 | assetGatherer.GatherAssetUuids(sceneObject, assetUuids); | 197 | m_saveStream.Close(); |
138 | } | 198 | throw; |
139 | 199 | } | |
140 | m_log.DebugFormat( | ||
141 | "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", | ||
142 | sceneObjects.Count, assetUuids.Count); | ||
143 | |||
144 | // Make sure that we also request terrain texture assets | ||
145 | RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; | ||
146 | |||
147 | if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) | ||
148 | assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; | ||
149 | |||
150 | if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) | ||
151 | assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; | ||
152 | |||
153 | if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) | ||
154 | assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; | ||
155 | |||
156 | if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) | ||
157 | assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; | ||
158 | |||
159 | TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); | ||
160 | |||
161 | // Asynchronously request all the assets required to perform this archive operation | ||
162 | ArchiveWriteRequestExecution awre | ||
163 | = new ArchiveWriteRequestExecution( | ||
164 | sceneObjects, | ||
165 | m_scene.RequestModuleInterface<ITerrainModule>(), | ||
166 | m_scene.RequestModuleInterface<IRegionSerialiserModule>(), | ||
167 | m_scene, | ||
168 | archiveWriter, | ||
169 | m_requestId, | ||
170 | options); | ||
171 | |||
172 | m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); | ||
173 | |||
174 | // Write out control file. This has to be done first so that subsequent loaders will see this file first | ||
175 | // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this | ||
176 | archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p2ControlFile(options)); | ||
177 | m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); | ||
178 | |||
179 | new AssetsRequest( | ||
180 | new AssetsArchiver(archiveWriter), assetUuids, | ||
181 | m_scene.AssetService, awre.ReceivedAllAssets).Execute(); | ||
182 | } | 200 | } |
183 | 201 | ||
184 | /// <summary> | 202 | /// <summary> |
185 | /// Create the control file for the most up to date archive | 203 | /// Create the control file for the most up to date archive |
186 | /// </summary> | 204 | /// </summary> |
187 | /// <returns></returns> | 205 | /// <returns></returns> |
188 | public static string Create0p2ControlFile(Dictionary<string, object> options) | 206 | public static string CreateControlFile(Dictionary<string, object> options) |
189 | { | 207 | { |
190 | int majorVersion = 0, minorVersion = 5; | 208 | int majorVersion = MAX_MAJOR_VERSION, minorVersion = 0; |
191 | 209 | ||
192 | if (options.ContainsKey("version")) | 210 | if (options.ContainsKey("version")) |
193 | { | 211 | { |
194 | minorVersion = 0; | ||
195 | string[] parts = options["version"].ToString().Split('.'); | 212 | string[] parts = options["version"].ToString().Split('.'); |
196 | if (parts.Length >= 1) | 213 | if (parts.Length >= 1) |
197 | majorVersion = Int32.Parse(parts[0]); | 214 | { |
198 | if (parts.Length >= 2) | 215 | majorVersion = Int32.Parse(parts[0]); |
199 | minorVersion = Int32.Parse(parts[1]); | 216 | |
217 | if (parts.Length >= 2) | ||
218 | minorVersion = Int32.Parse(parts[1]); | ||
219 | } | ||
200 | } | 220 | } |
201 | 221 | ||
202 | m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); | 222 | if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION) |
203 | // if (majorVersion == 1) | 223 | { |
204 | // { | 224 | throw new Exception( |
205 | // m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR"); | 225 | string.Format( |
206 | // } | 226 | "OAR version number for save must be between {0} and {1}", |
227 | MIN_MAJOR_VERSION, MAX_MAJOR_VERSION)); | ||
228 | } | ||
229 | else if (majorVersion == MAX_MAJOR_VERSION) | ||
230 | { | ||
231 | // Force 1.0 | ||
232 | minorVersion = 0; | ||
233 | } | ||
234 | else if (majorVersion == MIN_MAJOR_VERSION) | ||
235 | { | ||
236 | // Force 0.4 | ||
237 | minorVersion = 4; | ||
238 | } | ||
207 | 239 | ||
240 | m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); | ||
241 | if (majorVersion == 1) | ||
242 | { | ||
243 | m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR"); | ||
244 | } | ||
208 | 245 | ||
209 | StringWriter sw = new StringWriter(); | 246 | StringWriter sw = new StringWriter(); |
210 | XmlTextWriter xtw = new XmlTextWriter(sw); | 247 | XmlTextWriter xtw = new XmlTextWriter(sw); |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 04bdc4f..04b6e3d 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs | |||
@@ -122,13 +122,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
122 | } | 122 | } |
123 | 123 | ||
124 | /// <summary> | 124 | /// <summary> |
125 | /// Test saving a V0.2 OpenSim Region Archive. | 125 | /// Test saving an OpenSim Region Archive. |
126 | /// </summary> | 126 | /// </summary> |
127 | [Test] | 127 | [Test] |
128 | public void TestSaveOarV0_2() | 128 | public void TestSaveOar() |
129 | { | 129 | { |
130 | TestHelper.InMethod(); | 130 | TestHelper.InMethod(); |
131 | //log4net.Config.XmlConfigurator.Configure(); | 131 | // log4net.Config.XmlConfigurator.Configure(); |
132 | 132 | ||
133 | SceneObjectPart part1 = CreateSceneObjectPart1(); | 133 | SceneObjectPart part1 = CreateSceneObjectPart1(); |
134 | SceneObjectGroup sog1 = new SceneObjectGroup(part1); | 134 | SceneObjectGroup sog1 = new SceneObjectGroup(part1); |
@@ -212,10 +212,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
212 | } | 212 | } |
213 | 213 | ||
214 | /// <summary> | 214 | /// <summary> |
215 | /// Test loading a V0.2 OpenSim Region Archive. | 215 | /// Test loading an OpenSim Region Archive. |
216 | /// </summary> | 216 | /// </summary> |
217 | [Test] | 217 | [Test] |
218 | public void TestLoadOarV0_2() | 218 | public void TestLoadOar() |
219 | { | 219 | { |
220 | TestHelper.InMethod(); | 220 | TestHelper.InMethod(); |
221 | // log4net.Config.XmlConfigurator.Configure(); | 221 | // log4net.Config.XmlConfigurator.Configure(); |
@@ -230,7 +230,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
230 | // upset load | 230 | // upset load |
231 | tar.WriteDir(ArchiveConstants.TERRAINS_PATH); | 231 | tar.WriteDir(ArchiveConstants.TERRAINS_PATH); |
232 | 232 | ||
233 | tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestPreparation.Create0p2ControlFile(new Dictionary<string, Object>())); | 233 | tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestPreparation.CreateControlFile(new Dictionary<string, Object>())); |
234 | 234 | ||
235 | SceneObjectPart part1 = CreateSceneObjectPart1(); | 235 | SceneObjectPart part1 = CreateSceneObjectPart1(); |
236 | SceneObjectGroup object1 = new SceneObjectGroup(part1); | 236 | SceneObjectGroup object1 = new SceneObjectGroup(part1); |
@@ -317,10 +317,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
317 | } | 317 | } |
318 | 318 | ||
319 | /// <summary> | 319 | /// <summary> |
320 | /// Test loading the region settings of a V0.2 OpenSim Region Archive. | 320 | /// Test loading the region settings of an OpenSim Region Archive. |
321 | /// </summary> | 321 | /// </summary> |
322 | [Test] | 322 | [Test] |
323 | public void TestLoadOarV0_2RegionSettings() | 323 | public void TestLoadOarRegionSettings() |
324 | { | 324 | { |
325 | TestHelper.InMethod(); | 325 | TestHelper.InMethod(); |
326 | //log4net.Config.XmlConfigurator.Configure(); | 326 | //log4net.Config.XmlConfigurator.Configure(); |
@@ -329,7 +329,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
329 | TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); | 329 | TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); |
330 | 330 | ||
331 | tar.WriteDir(ArchiveConstants.TERRAINS_PATH); | 331 | tar.WriteDir(ArchiveConstants.TERRAINS_PATH); |
332 | tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestPreparation.Create0p2ControlFile(new Dictionary<string, Object>())); | 332 | tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestPreparation.CreateControlFile(new Dictionary<string, Object>())); |
333 | 333 | ||
334 | RegionSettings rs = new RegionSettings(); | 334 | RegionSettings rs = new RegionSettings(); |
335 | rs.AgentLimit = 17; | 335 | rs.AgentLimit = 17; |
@@ -409,10 +409,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
409 | } | 409 | } |
410 | 410 | ||
411 | /// <summary> | 411 | /// <summary> |
412 | /// Test merging a V0.2 OpenSim Region Archive into an existing scene | 412 | /// Test merging an OpenSim Region Archive into an existing scene |
413 | /// </summary> | 413 | /// </summary> |
414 | //[Test] | 414 | //[Test] |
415 | public void TestMergeOarV0_2() | 415 | public void TestMergeOar() |
416 | { | 416 | { |
417 | TestHelper.InMethod(); | 417 | TestHelper.InMethod(); |
418 | //XmlConfigurator.Configure(); | 418 | //XmlConfigurator.Configure(); |
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchDialplan.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchDialplan.cs deleted file mode 100644 index 46ad30f..0000000 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchDialplan.cs +++ /dev/null | |||
@@ -1,104 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using log4net; | ||
29 | using System; | ||
30 | using System.Reflection; | ||
31 | using System.Text; | ||
32 | using System.Collections; | ||
33 | |||
34 | namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | ||
35 | { | ||
36 | public class FreeSwitchDialplan | ||
37 | { | ||
38 | private static readonly ILog m_log = | ||
39 | LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
40 | |||
41 | |||
42 | public Hashtable HandleDialplanRequest(string Context, string Realm, Hashtable request) | ||
43 | { | ||
44 | m_log.DebugFormat("[FreeSwitchVoice] HandleDialplanRequest called with {0}",request.ToString()); | ||
45 | |||
46 | Hashtable response = new Hashtable(); | ||
47 | |||
48 | foreach (DictionaryEntry item in request) | ||
49 | { | ||
50 | m_log.InfoFormat("[FreeSwitchDirectory] requestBody item {0} {1}",item.Key, item.Value); | ||
51 | } | ||
52 | |||
53 | string requestcontext = (string) request["Hunt-Context"]; | ||
54 | response["content_type"] = "text/xml"; | ||
55 | response["keepalive"] = false; | ||
56 | response["int_response_code"] = 200; | ||
57 | if (Context != String.Empty && Context != requestcontext) | ||
58 | { | ||
59 | m_log.Debug("[FreeSwitchDirectory] returning empty as it's for another context"); | ||
60 | response["str_response_string"] = ""; | ||
61 | } else { | ||
62 | response["str_response_string"] = String.Format(@"<?xml version=""1.0"" encoding=""utf-8""?> | ||
63 | <document type=""freeswitch/xml""> | ||
64 | <section name=""dialplan""> | ||
65 | <context name=""{0}"">" + | ||
66 | |||
67 | /* <!-- dial via SIP uri --> | ||
68 | <extension name=""sip_uri""> | ||
69 | <condition field=""destination_number"" expression=""^sip:(.*)$""> | ||
70 | <action application=""bridge"" data=""sofia/${use_profile}/$1""/> | ||
71 | <!--<action application=""bridge"" data=""$1""/>--> | ||
72 | </condition> | ||
73 | </extension>*/ | ||
74 | |||
75 | @"<extension name=""opensim_conferences""> | ||
76 | <condition field=""destination_number"" expression=""^confctl-(.*)$""> | ||
77 | <action application=""answer""/> | ||
78 | <action application=""conference"" data=""$1-{1}@{0}""/> | ||
79 | </condition> | ||
80 | </extension> | ||
81 | |||
82 | <extension name=""opensim_conf""> | ||
83 | <condition field=""destination_number"" expression=""^conf-(.*)$""> | ||
84 | <action application=""answer""/> | ||
85 | <action application=""conference"" data=""$1-{1}@{0}""/> | ||
86 | </condition> | ||
87 | </extension> | ||
88 | |||
89 | <extension name=""avatar""> | ||
90 | <condition field=""destination_number"" expression=""^(x.*)$""> | ||
91 | <action application=""bridge"" data=""user/$1""/> | ||
92 | </condition> | ||
93 | </extension> | ||
94 | |||
95 | </context> | ||
96 | </section> | ||
97 | </document>", Context, Realm); | ||
98 | } | ||
99 | |||
100 | return response; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | } | ||
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchDirectory.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchDirectory.cs deleted file mode 100644 index 17cdf74..0000000 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchDirectory.cs +++ /dev/null | |||
@@ -1,348 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using log4net; | ||
29 | using System; | ||
30 | using System.Reflection; | ||
31 | using System.Text; | ||
32 | using System.Collections; | ||
33 | |||
34 | namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | ||
35 | { | ||
36 | public class FreeSwitchDirectory | ||
37 | { | ||
38 | private static readonly ILog m_log = | ||
39 | LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
40 | |||
41 | public Hashtable HandleDirectoryRequest(string Context, string Realm, Hashtable request) | ||
42 | { | ||
43 | Hashtable response = new Hashtable(); | ||
44 | string domain = (string) request["domain"]; | ||
45 | if (domain != Realm) { | ||
46 | response["content_type"] = "text/xml"; | ||
47 | response["keepalive"] = false; | ||
48 | response["int_response_code"] = 200; | ||
49 | response["str_response_string"] = ""; | ||
50 | } else { | ||
51 | m_log.DebugFormat("[FreeSwitchDirectory] HandleDirectoryRequest called with {0}",request.ToString()); | ||
52 | |||
53 | // information in the request we might be interested in | ||
54 | |||
55 | // Request 1 sip_auth for users account | ||
56 | |||
57 | //Event-Calling-Function=sofia_reg_parse_auth | ||
58 | //Event-Calling-Line-Number=1494 | ||
59 | //action=sip_auth | ||
60 | //sip_user_agent=Vivox-SDK-2.1.3010.6151-Mac%20(Feb-11-2009/16%3A42%3A41) | ||
61 | //sip_auth_username=xhZuXKmRpECyr2AARJYyGgg%3D%3D (==) | ||
62 | //sip_auth_realm=9.20.151.43 | ||
63 | //sip_contact_user=xhZuXKmRpECyr2AARJYyGgg%3D%3D (==) | ||
64 | //sip_contact_host=192.168.0.3 // this shouldnt really be a local IP, investigate STUN servers | ||
65 | //sip_to_user=xhZuXKmRpECyr2AARJYyGgg%3D%3D | ||
66 | //sip_to_host=9.20.151.43 | ||
67 | //sip_auth_method=REGISTER | ||
68 | //user=xhZuXKmRpECyr2AARJYyGgg%3D%3D | ||
69 | //domain=9.20.151.43 | ||
70 | //ip=9.167.220.137 // this is the correct IP rather than sip_contact_host above when through a vpn or NAT setup | ||
71 | |||
72 | foreach (DictionaryEntry item in request) | ||
73 | { | ||
74 | m_log.InfoFormat("[FreeSwitchDirectory] requestBody item {0} {1}", item.Key, item.Value); | ||
75 | } | ||
76 | |||
77 | string eventCallingFunction = (string) request["Event-Calling-Function"]; | ||
78 | if (eventCallingFunction == null) | ||
79 | { | ||
80 | eventCallingFunction = "sofia_reg_parse_auth"; | ||
81 | } | ||
82 | |||
83 | if (eventCallingFunction.Length == 0) | ||
84 | { | ||
85 | eventCallingFunction = "sofia_reg_parse_auth"; | ||
86 | } | ||
87 | |||
88 | if (eventCallingFunction == "sofia_reg_parse_auth") | ||
89 | { | ||
90 | string sipAuthMethod = (string)request["sip_auth_method"]; | ||
91 | |||
92 | if (sipAuthMethod == "REGISTER") | ||
93 | { | ||
94 | response = HandleRegister(Context, Realm, request); | ||
95 | } | ||
96 | else if (sipAuthMethod == "INVITE") | ||
97 | { | ||
98 | response = HandleInvite(Context, Realm, request); | ||
99 | } | ||
100 | else | ||
101 | { | ||
102 | m_log.ErrorFormat("[FreeSwitchVoice] HandleDirectoryRequest unknown sip_auth_method {0}",sipAuthMethod); | ||
103 | response["int_response_code"] = 404; | ||
104 | response["content_type"] = "text/xml"; | ||
105 | response["str_response_string"] = ""; | ||
106 | } | ||
107 | } | ||
108 | else if (eventCallingFunction == "switch_xml_locate_user") | ||
109 | { | ||
110 | response = HandleLocateUser(Realm, request); | ||
111 | } | ||
112 | else if (eventCallingFunction == "user_data_function") // gets called when an avatar to avatar call is made | ||
113 | { | ||
114 | response = HandleLocateUser(Realm, request); | ||
115 | } | ||
116 | else if (eventCallingFunction == "user_outgoing_channel") | ||
117 | { | ||
118 | response = HandleRegister(Context, Realm, request); | ||
119 | } | ||
120 | else if (eventCallingFunction == "config_sofia") // happens once on freeswitch startup | ||
121 | { | ||
122 | response = HandleConfigSofia(Context, Realm, request); | ||
123 | } | ||
124 | else if (eventCallingFunction == "switch_load_network_lists") | ||
125 | { | ||
126 | //response = HandleLoadNetworkLists(request); | ||
127 | response["int_response_code"] = 404; | ||
128 | response["keepalive"] = false; | ||
129 | response["content_type"] = "text/xml"; | ||
130 | response["str_response_string"] = ""; | ||
131 | } | ||
132 | else | ||
133 | { | ||
134 | m_log.ErrorFormat("[FreeSwitchVoice] HandleDirectoryRequest unknown Event-Calling-Function {0}",eventCallingFunction); | ||
135 | response["int_response_code"] = 404; | ||
136 | response["keepalive"] = false; | ||
137 | response["content_type"] = "text/xml"; | ||
138 | response["str_response_string"] = ""; | ||
139 | } | ||
140 | } | ||
141 | return response; | ||
142 | } | ||
143 | |||
144 | private Hashtable HandleRegister(string Context, string Realm, Hashtable request) | ||
145 | { | ||
146 | m_log.Info("[FreeSwitchDirectory] HandleRegister called"); | ||
147 | |||
148 | // TODO the password we return needs to match that sent in the request, this is hard coded for now | ||
149 | string password = "1234"; | ||
150 | string domain = (string) request["domain"]; | ||
151 | string user = (string) request["user"]; | ||
152 | |||
153 | Hashtable response = new Hashtable(); | ||
154 | response["content_type"] = "text/xml"; | ||
155 | response["keepalive"] = false; | ||
156 | response["int_response_code"] = 200; | ||
157 | |||
158 | response["str_response_string"] = String.Format( | ||
159 | "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" + | ||
160 | "<document type=\"freeswitch/xml\">\r\n" + | ||
161 | "<section name=\"directory\" description=\"User Directory\">\r\n" + | ||
162 | "<domain name=\"{0}\">\r\n" + | ||
163 | "<user id=\"{1}\">\r\n" + | ||
164 | "<params>\r\n" + | ||
165 | "<param name=\"password\" value=\"{2}\" />\r\n" + | ||
166 | "<param name=\"dial-string\" value=\"{{sip_contact_user={1}}}{{presence_id=${{dialed_user}}@${{dialed_domain}}}}${{sofia_contact(${{dialed_user}}@${{dialed_domain}})}}\"/>\r\n" + | ||
167 | "</params>\r\n" + | ||
168 | "<variables>\r\n" + | ||
169 | "<variable name=\"user_context\" value=\"{3}\" />\r\n" + | ||
170 | "<variable name=\"presence_id\" value=\"{1}@{0}\"/>"+ | ||
171 | "</variables>\r\n" + | ||
172 | "</user>\r\n" + | ||
173 | "</domain>\r\n" + | ||
174 | "</section>\r\n" + | ||
175 | "</document>\r\n", | ||
176 | domain , user, password, Context); | ||
177 | |||
178 | return response; | ||
179 | } | ||
180 | |||
181 | private Hashtable HandleInvite(string Context, string Realm, Hashtable request) | ||
182 | { | ||
183 | m_log.Info("[FreeSwitchDirectory] HandleInvite called"); | ||
184 | |||
185 | // TODO the password we return needs to match that sent in the request, this is hard coded for now | ||
186 | string password = "1234"; | ||
187 | string domain = (string) request["domain"]; | ||
188 | string user = (string) request["user"]; | ||
189 | string sipRequestUser = (string) request["sip_request_user"]; | ||
190 | |||
191 | Hashtable response = new Hashtable(); | ||
192 | response["content_type"] = "text/xml"; | ||
193 | response["keepalive"] = false; | ||
194 | response["int_response_code"] = 200; | ||
195 | response["str_response_string"] = String.Format( | ||
196 | "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" + | ||
197 | "<document type=\"freeswitch/xml\">\r\n" + | ||
198 | "<section name=\"directory\" description=\"User Directory\">\r\n" + | ||
199 | "<domain name=\"{0}\">\r\n" + | ||
200 | "<user id=\"{1}\">\r\n" + | ||
201 | "<params>\r\n" + | ||
202 | "<param name=\"password\" value=\"{2}\" />\r\n" + | ||
203 | "<param name=\"dial-string\" value=\"{{sip_contact_user={1}}}{{presence_id=${1}@${{dialed_domain}}}}${{sofia_contact(${1}@${{dialed_domain}})}}\"/>\r\n" + | ||
204 | "</params>\r\n" + | ||
205 | "<variables>\r\n" + | ||
206 | "<variable name=\"user_context\" value=\"{4}\" />\r\n" + | ||
207 | "<variable name=\"presence_id\" value=\"{1}@$${{domain}}\"/>"+ | ||
208 | "</variables>\r\n" + | ||
209 | "</user>\r\n" + | ||
210 | "<user id=\"{3}\">\r\n" + | ||
211 | "<params>\r\n" + | ||
212 | "<param name=\"password\" value=\"{2}\" />\r\n" + | ||
213 | "<param name=\"dial-string\" value=\"{{sip_contact_user={1}}}{{presence_id=${3}@${{dialed_domain}}}}${{sofia_contact(${3}@${{dialed_domain}})}}\"/>\r\n" + | ||
214 | "</params>\r\n" + | ||
215 | "<variables>\r\n" + | ||
216 | "<variable name=\"user_context\" value=\"{4}\" />\r\n" + | ||
217 | "<variable name=\"presence_id\" value=\"{3}@$${{domain}}\"/>"+ | ||
218 | "</variables>\r\n" + | ||
219 | "</user>\r\n" + | ||
220 | "</domain>\r\n" + | ||
221 | "</section>\r\n" + | ||
222 | "</document>\r\n", | ||
223 | domain , user, password,sipRequestUser, Context); | ||
224 | |||
225 | return response; | ||
226 | } | ||
227 | |||
228 | private Hashtable HandleLocateUser(String Realm, Hashtable request) | ||
229 | { | ||
230 | m_log.Info("[FreeSwitchDirectory] HandleLocateUser called"); | ||
231 | |||
232 | // TODO the password we return needs to match that sent in the request, this is hard coded for now | ||
233 | string domain = (string) request["domain"]; | ||
234 | string user = (string) request["user"]; | ||
235 | |||
236 | Hashtable response = new Hashtable(); | ||
237 | response["content_type"] = "text/xml"; | ||
238 | response["keepalive"] = false; | ||
239 | response["int_response_code"] = 200; | ||
240 | response["str_response_string"] = String.Format( | ||
241 | "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" + | ||
242 | "<document type=\"freeswitch/xml\">\r\n" + | ||
243 | "<section name=\"directory\" description=\"User Directory\">\r\n" + | ||
244 | "<domain name=\"{0}\">\r\n" + | ||
245 | "<params>\r\n" + | ||
246 | "<param name=\"dial-string\" value=\"{{sip_contact_user=${{dialed_user}}}}{{presence_id=${{dialed_user}}@${{dialed_domain}}}}${{sofia_contact(${{dialed_user}}@${{dialed_domain}})}}\"/>\r\n" + | ||
247 | "</params>\r\n" + | ||
248 | "<user id=\"{1}\">\r\n" + | ||
249 | "<variables>\r\n"+ | ||
250 | "<variable name=\"default_gateway\" value=\"$${{default_provider}}\"/>\r\n"+ | ||
251 | "<variable name=\"presence_id\" value=\"{1}@$${{domain}}\"/>"+ | ||
252 | "</variables>\r\n"+ | ||
253 | "</user>\r\n" + | ||
254 | "</domain>\r\n" + | ||
255 | "</section>\r\n" + | ||
256 | "</document>\r\n", | ||
257 | domain , user); | ||
258 | |||
259 | return response; | ||
260 | } | ||
261 | |||
262 | private Hashtable HandleConfigSofia(string Context, string Realm, Hashtable request) | ||
263 | { | ||
264 | m_log.Info("[FreeSwitchDirectory] HandleConfigSofia called"); | ||
265 | |||
266 | // TODO the password we return needs to match that sent in the request, this is hard coded for now | ||
267 | string domain = (string) request["domain"]; | ||
268 | |||
269 | Hashtable response = new Hashtable(); | ||
270 | response["content_type"] = "text/xml"; | ||
271 | response["keepalive"] = false; | ||
272 | response["int_response_code"] = 200; | ||
273 | response["str_response_string"] = String.Format( | ||
274 | "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" + | ||
275 | "<document type=\"freeswitch/xml\">\r\n" + | ||
276 | "<section name=\"directory\" description=\"User Directory\">\r\n" + | ||
277 | "<domain name=\"{0}\">\r\n" + | ||
278 | "<params>\r\n" + | ||
279 | "<param name=\"dial-string\" value=\"{{sip_contact_user=${{dialed_user}}}}{{presence_id=${{dialed_user}}@${{dialed_domain}}}}${{sofia_contact(${{dialed_user}}@${{dialed_domain}})}}\"/>\r\n" + | ||
280 | "</params>\r\n" + | ||
281 | "<groups name=\"default\">\r\n"+ | ||
282 | "<users>\r\n"+ | ||
283 | "<user id=\"$${{default_provider}}\">\r\n"+ | ||
284 | "<gateways>\r\n"+ | ||
285 | "<gateway name=\"$${{default_provider}}\">\r\n"+ | ||
286 | "<param name=\"username\" value=\"$${{default_provider_username}}\"/>\r\n"+ | ||
287 | "<param name=\"password\" value=\"$${{default_provider_password}}\"/>\r\n"+ | ||
288 | "<param name=\"from-user\" value=\"$${{default_provider_username}}\"/>\r\n"+ | ||
289 | "<param name=\"from-domain\" value=\"$${{default_provider_from_domain}}\"/>\r\n"+ | ||
290 | "<param name=\"expire-seconds\" value=\"600\"/>\r\n"+ | ||
291 | "<param name=\"register\" value=\"$${{default_provider_register}}\"/>\r\n"+ | ||
292 | "<param name=\"retry-seconds\" value=\"30\"/>\r\n"+ | ||
293 | "<param name=\"extension\" value=\"$${{default_provider_contact}}\"/>\r\n"+ | ||
294 | "<param name=\"contact-params\" value=\"domain_name=$${{domain}}\"/>\r\n"+ | ||
295 | "<param name=\"context\" value=\"{1}\"/>\r\n"+ | ||
296 | "</gateway>\r\n"+ | ||
297 | "</gateways>\r\n"+ | ||
298 | "<params>\r\n"+ | ||
299 | "<param name=\"password\" value=\"$${{default_provider_password}}\"/>\r\n"+ | ||
300 | "</params>\r\n"+ | ||
301 | "</user>\r\n"+ | ||
302 | "</users>"+ | ||
303 | "</groups>\r\n" + | ||
304 | "<variables>\r\n"+ | ||
305 | "<variable name=\"default_gateway\" value=\"$${{default_provider}}\"/>\r\n"+ | ||
306 | "</variables>\r\n"+ | ||
307 | "</domain>\r\n" + | ||
308 | "</section>\r\n" + | ||
309 | "</document>\r\n", | ||
310 | domain, Context); | ||
311 | |||
312 | return response; | ||
313 | } | ||
314 | |||
315 | |||
316 | // private Hashtable HandleLoadNetworkLists(Hashtable request) | ||
317 | // { | ||
318 | // m_log.Info("[FreeSwitchDirectory] HandleLoadNetworkLists called"); | ||
319 | // | ||
320 | // // TODO the password we return needs to match that sent in the request, this is hard coded for now | ||
321 | // string domain = (string) request["domain"]; | ||
322 | // | ||
323 | // Hashtable response = new Hashtable(); | ||
324 | // response["content_type"] = "text/xml"; | ||
325 | // response["keepalive"] = false; | ||
326 | // response["int_response_code"] = 200; | ||
327 | // response["str_response_string"] = String.Format( | ||
328 | // "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" + | ||
329 | // "<document type=\"freeswitch/xml\">\r\n" + | ||
330 | // "<section name=\"directory\" description=\"User Directory\">\r\n" + | ||
331 | // "<domain name=\"{0}\">\r\n" + | ||
332 | // "<params>\r\n" + | ||
333 | // "<param name=\"dial-string\" value=\"{{presence_id=${{dialed_user}}@${{dialed_domain}}}}${{sofia_contact(${{dialed_user}}@${{dialed_domain}})}}\"/>\r\n" + | ||
334 | // "</params>\r\n" + | ||
335 | // "<groups name=\"default\"><users/></groups>\r\n" + | ||
336 | // "<variables>\r\n"+ | ||
337 | // "<variable name=\"default_gateway\" value=\"$${{default_provider}}\"/>\r\n"+ | ||
338 | // "</variables>\r\n"+ | ||
339 | // "</domain>\r\n" + | ||
340 | // "</section>\r\n" + | ||
341 | // "</document>\r\n", | ||
342 | // domain); | ||
343 | // | ||
344 | // | ||
345 | // return response; | ||
346 | // } | ||
347 | } | ||
348 | } | ||
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index 242bc3f..a5e553c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | |||
@@ -37,10 +37,12 @@ using System.Collections; | |||
37 | using System.Collections.Generic; | 37 | using System.Collections.Generic; |
38 | using System.Reflection; | 38 | using System.Reflection; |
39 | using OpenMetaverse; | 39 | using OpenMetaverse; |
40 | using OpenMetaverse.StructuredData; | ||
40 | using log4net; | 41 | using log4net; |
41 | using Nini.Config; | 42 | using Nini.Config; |
42 | using Nwc.XmlRpc; | 43 | using Nwc.XmlRpc; |
43 | using OpenSim.Framework; | 44 | using OpenSim.Framework; |
45 | using Mono.Addins; | ||
44 | 46 | ||
45 | using OpenSim.Framework.Capabilities; | 47 | using OpenSim.Framework.Capabilities; |
46 | using OpenSim.Framework.Servers; | 48 | using OpenSim.Framework.Servers; |
@@ -49,28 +51,27 @@ using OpenSim.Region.Framework.Interfaces; | |||
49 | using OpenSim.Region.Framework.Scenes; | 51 | using OpenSim.Region.Framework.Scenes; |
50 | using Caps = OpenSim.Framework.Capabilities.Caps; | 52 | using Caps = OpenSim.Framework.Capabilities.Caps; |
51 | using System.Text.RegularExpressions; | 53 | using System.Text.RegularExpressions; |
54 | using OpenSim.Server.Base; | ||
55 | using OpenSim.Services.Interfaces; | ||
56 | using OSDMap = OpenMetaverse.StructuredData.OSDMap; | ||
52 | 57 | ||
53 | namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | 58 | namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice |
54 | { | 59 | { |
55 | public class FreeSwitchVoiceModule : IRegionModule, IVoiceModule | 60 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "FreeSwitchVoiceModule")] |
61 | public class FreeSwitchVoiceModule : INonSharedRegionModule, IVoiceModule | ||
56 | { | 62 | { |
57 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 63 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
58 | 64 | ||
59 | private bool UseProxy = false; | ||
60 | |||
61 | // Capability string prefixes | 65 | // Capability string prefixes |
62 | private static readonly string m_parcelVoiceInfoRequestPath = "0007/"; | 66 | private static readonly string m_parcelVoiceInfoRequestPath = "0007/"; |
63 | private static readonly string m_provisionVoiceAccountRequestPath = "0008/"; | 67 | private static readonly string m_provisionVoiceAccountRequestPath = "0008/"; |
64 | private static readonly string m_chatSessionRequestPath = "0009/"; | 68 | private static readonly string m_chatSessionRequestPath = "0009/"; |
65 | 69 | ||
66 | // Control info | 70 | // Control info |
67 | private static bool m_WOF = true; | 71 | private static bool m_Enabled = false; |
68 | private static bool m_pluginEnabled = false; | ||
69 | 72 | ||
70 | // FreeSwitch server is going to contact us and ask us all | 73 | // FreeSwitch server is going to contact us and ask us all |
71 | // sorts of things. | 74 | // sorts of things. |
72 | private static string m_freeSwitchServerUser; | ||
73 | private static string m_freeSwitchServerPass; | ||
74 | 75 | ||
75 | // SLVoice client will do a GET on this prefix | 76 | // SLVoice client will do a GET on this prefix |
76 | private static string m_freeSwitchAPIPrefix; | 77 | private static string m_freeSwitchAPIPrefix; |
@@ -84,143 +85,146 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
84 | private static string m_freeSwitchRealm; | 85 | private static string m_freeSwitchRealm; |
85 | private static string m_freeSwitchSIPProxy; | 86 | private static string m_freeSwitchSIPProxy; |
86 | private static bool m_freeSwitchAttemptUseSTUN; | 87 | private static bool m_freeSwitchAttemptUseSTUN; |
87 | // private static string m_freeSwitchSTUNServer; | ||
88 | private static string m_freeSwitchEchoServer; | 88 | private static string m_freeSwitchEchoServer; |
89 | private static int m_freeSwitchEchoPort; | 89 | private static int m_freeSwitchEchoPort; |
90 | private static string m_freeSwitchDefaultWellKnownIP; | 90 | private static string m_freeSwitchDefaultWellKnownIP; |
91 | private static int m_freeSwitchDefaultTimeout; | 91 | private static int m_freeSwitchDefaultTimeout; |
92 | // private static int m_freeSwitchSubscribeRetry; | ||
93 | private static string m_freeSwitchUrlResetPassword; | 92 | private static string m_freeSwitchUrlResetPassword; |
94 | // private static IPEndPoint m_FreeSwitchServiceIP; | 93 | private uint m_freeSwitchServicePort; |
95 | private int m_freeSwitchServicePort; | ||
96 | private string m_openSimWellKnownHTTPAddress; | 94 | private string m_openSimWellKnownHTTPAddress; |
97 | private string m_freeSwitchContext; | 95 | private string m_freeSwitchContext; |
98 | 96 | ||
99 | private FreeSwitchDirectory m_FreeSwitchDirectory; | ||
100 | private FreeSwitchDialplan m_FreeSwitchDialplan; | ||
101 | |||
102 | private readonly Dictionary<string, string> m_UUIDName = new Dictionary<string, string>(); | 97 | private readonly Dictionary<string, string> m_UUIDName = new Dictionary<string, string>(); |
103 | private Dictionary<string, string> m_ParcelAddress = new Dictionary<string, string>(); | 98 | private Dictionary<string, string> m_ParcelAddress = new Dictionary<string, string>(); |
104 | 99 | ||
105 | private Scene m_scene; | 100 | private Scene m_Scene; |
106 | 101 | ||
102 | private IConfig m_Config; | ||
107 | 103 | ||
108 | private IConfig m_config; | 104 | private IFreeswitchService m_FreeswitchService; |
109 | 105 | ||
110 | public void Initialise(Scene scene, IConfigSource config) | 106 | public void Initialise(IConfigSource config) |
111 | { | 107 | { |
112 | m_scene = scene; | 108 | m_Config = config.Configs["FreeSwitchVoice"]; |
113 | m_config = config.Configs["FreeSwitchVoice"]; | ||
114 | 109 | ||
115 | if (null == m_config) | 110 | if (m_Config == null) |
116 | { | 111 | { |
117 | m_log.Info("[FreeSwitchVoice] no config found, plugin disabled"); | 112 | m_log.Info("[FreeSwitchVoice] no config found, plugin disabled"); |
118 | return; | 113 | return; |
119 | } | 114 | } |
120 | 115 | ||
121 | if (!m_config.GetBoolean("enabled", false)) | 116 | if (!m_Config.GetBoolean("Enabled", false)) |
122 | { | 117 | { |
123 | m_log.Info("[FreeSwitchVoice] plugin disabled by configuration"); | 118 | m_log.Info("[FreeSwitchVoice] plugin disabled by configuration"); |
124 | return; | 119 | return; |
125 | } | 120 | } |
126 | 121 | ||
127 | // This is only done the FIRST time this method is invoked. | 122 | try |
128 | if (m_WOF) | ||
129 | { | 123 | { |
130 | m_pluginEnabled = true; | 124 | string serviceDll = m_Config.GetString("LocalServiceModule", |
131 | m_WOF = false; | 125 | String.Empty); |
132 | 126 | ||
133 | try | 127 | if (serviceDll == String.Empty) |
134 | { | 128 | { |
135 | m_freeSwitchServerUser = m_config.GetString("freeswitch_server_user", String.Empty); | 129 | m_log.Error("[FreeSwitchVoice]: No LocalServiceModule named in section FreeSwitchVoice"); |
136 | m_freeSwitchServerPass = m_config.GetString("freeswitch_server_pass", String.Empty); | 130 | return; |
137 | m_freeSwitchAPIPrefix = m_config.GetString("freeswitch_api_prefix", String.Empty); | 131 | } |
138 | |||
139 | // XXX: get IP address of HTTP server. (This can be this OpenSim server or another, or could be a dedicated grid service or may live on the freeswitch server) | ||
140 | |||
141 | string serviceIP = m_config.GetString("freeswitch_service_server", String.Empty); | ||
142 | int servicePort = m_config.GetInt("freeswitch_service_port", 80); | ||
143 | IPAddress serviceIPAddress = IPAddress.Parse(serviceIP); | ||
144 | // m_FreeSwitchServiceIP = new IPEndPoint(serviceIPAddress, servicePort); | ||
145 | m_freeSwitchServicePort = servicePort; | ||
146 | m_freeSwitchRealm = m_config.GetString("freeswitch_realm", String.Empty); | ||
147 | m_freeSwitchSIPProxy = m_config.GetString("freeswitch_sip_proxy", m_freeSwitchRealm); | ||
148 | m_freeSwitchAttemptUseSTUN = m_config.GetBoolean("freeswitch_attempt_stun", true); | ||
149 | // m_freeSwitchSTUNServer = m_config.GetString("freeswitch_stun_server", m_freeSwitchRealm); | ||
150 | m_freeSwitchEchoServer = m_config.GetString("freeswitch_echo_server", m_freeSwitchRealm); | ||
151 | m_freeSwitchEchoPort = m_config.GetInt("freeswitch_echo_port", 50505); | ||
152 | m_freeSwitchDefaultWellKnownIP = m_config.GetString("freeswitch_well_known_ip", m_freeSwitchRealm); | ||
153 | m_openSimWellKnownHTTPAddress = m_config.GetString("opensim_well_known_http_address", serviceIPAddress.ToString()); | ||
154 | m_freeSwitchDefaultTimeout = m_config.GetInt("freeswitch_default_timeout", 5000); | ||
155 | // m_freeSwitchSubscribeRetry = m_config.GetInt("freeswitch_subscribe_retry", 120); | ||
156 | m_freeSwitchUrlResetPassword = m_config.GetString("freeswitch_password_reset_url", String.Empty); | ||
157 | m_freeSwitchContext = m_config.GetString("freeswitch_context", "default"); | ||
158 | |||
159 | if (String.IsNullOrEmpty(m_freeSwitchServerUser) || | ||
160 | String.IsNullOrEmpty(m_freeSwitchServerPass) || | ||
161 | String.IsNullOrEmpty(m_freeSwitchRealm) || | ||
162 | String.IsNullOrEmpty(m_freeSwitchAPIPrefix)) | ||
163 | { | ||
164 | m_log.Error("[FreeSwitchVoice] plugin mis-configured"); | ||
165 | m_log.Info("[FreeSwitchVoice] plugin disabled: incomplete configuration"); | ||
166 | return; | ||
167 | } | ||
168 | 132 | ||
169 | // set up http request handlers for | 133 | Object[] args = new Object[] { config }; |
170 | // - prelogin: viv_get_prelogin.php | 134 | m_FreeswitchService = ServerUtils.LoadPlugin<IFreeswitchService>(serviceDll, args); |
171 | // - signin: viv_signin.php | 135 | |
172 | // - buddies: viv_buddy.php | 136 | string jsonConfig = m_FreeswitchService.GetJsonConfig(); |
173 | // - ???: viv_watcher.php | 137 | OSDMap map = (OSDMap)OSDParser.DeserializeJson(jsonConfig); |
174 | // - signout: viv_signout.php | 138 | |
175 | if (UseProxy) | 139 | m_freeSwitchAPIPrefix = map["APIPrefix"].AsString(); |
176 | { | 140 | m_freeSwitchRealm = map["Realm"].AsString(); |
177 | MainServer.Instance.AddHTTPHandler(String.Format("{0}/", m_freeSwitchAPIPrefix), | 141 | m_freeSwitchSIPProxy = map["SIPProxy"].AsString(); |
178 | ForwardProxyRequest); | 142 | m_freeSwitchAttemptUseSTUN = map["AttemptUseSTUN"].AsBoolean(); |
179 | } | 143 | m_freeSwitchEchoServer = map["EchoServer"].AsString(); |
180 | else | 144 | m_freeSwitchEchoPort = map["EchoPort"].AsInteger(); |
181 | { | 145 | m_freeSwitchDefaultWellKnownIP = map["DefaultWellKnownIP"].AsString(); |
182 | MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_get_prelogin.php", m_freeSwitchAPIPrefix), | 146 | m_freeSwitchDefaultTimeout = map["DefaultTimeout"].AsInteger(); |
183 | FreeSwitchSLVoiceGetPreloginHTTPHandler); | 147 | m_freeSwitchUrlResetPassword = String.Empty; |
148 | m_freeSwitchContext = map["Context"].AsString(); | ||
149 | |||
150 | if (String.IsNullOrEmpty(m_freeSwitchRealm) || | ||
151 | String.IsNullOrEmpty(m_freeSwitchAPIPrefix)) | ||
152 | { | ||
153 | m_log.Error("[FreeSwitchVoice] plugin mis-configured"); | ||
154 | m_log.Info("[FreeSwitchVoice] plugin disabled: incomplete configuration"); | ||
155 | return; | ||
156 | } | ||
184 | 157 | ||
185 | // RestStreamHandler h = new | 158 | // set up http request handlers for |
186 | // RestStreamHandler("GET", | 159 | // - prelogin: viv_get_prelogin.php |
187 | // String.Format("{0}/viv_get_prelogin.php", m_freeSwitchAPIPrefix), FreeSwitchSLVoiceGetPreloginHTTPHandler); | 160 | // - signin: viv_signin.php |
188 | // MainServer.Instance.AddStreamHandler(h); | 161 | // - buddies: viv_buddy.php |
162 | // - ???: viv_watcher.php | ||
163 | // - signout: viv_signout.php | ||
164 | MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_get_prelogin.php", m_freeSwitchAPIPrefix), | ||
165 | FreeSwitchSLVoiceGetPreloginHTTPHandler); | ||
189 | 166 | ||
167 | // RestStreamHandler h = new | ||
168 | // RestStreamHandler("GET", | ||
169 | // String.Format("{0}/viv_get_prelogin.php", m_freeSwitchAPIPrefix), FreeSwitchSLVoiceGetPreloginHTTPHandler); | ||
170 | // MainServer.Instance.AddStreamHandler(h); | ||
190 | 171 | ||
191 | 172 | ||
192 | MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_signin.php", m_freeSwitchAPIPrefix), | ||
193 | FreeSwitchSLVoiceSigninHTTPHandler); | ||
194 | 173 | ||
195 | // set up http request handlers to provide | 174 | MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_signin.php", m_freeSwitchAPIPrefix), |
196 | // on-demand FreeSwitch configuration to | 175 | FreeSwitchSLVoiceSigninHTTPHandler); |
197 | // FreeSwitch's mod_curl_xml | ||
198 | MainServer.Instance.AddHTTPHandler(String.Format("{0}/freeswitch-config", m_freeSwitchAPIPrefix), | ||
199 | FreeSwitchConfigHTTPHandler); | ||
200 | 176 | ||
201 | MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_buddy.php", m_freeSwitchAPIPrefix), | 177 | MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_buddy.php", m_freeSwitchAPIPrefix), |
202 | FreeSwitchSLVoiceBuddyHTTPHandler); | 178 | FreeSwitchSLVoiceBuddyHTTPHandler); |
203 | } | ||
204 | 179 | ||
205 | m_log.InfoFormat("[FreeSwitchVoice] using FreeSwitch server {0}", m_freeSwitchRealm); | 180 | m_log.InfoFormat("[FreeSwitchVoice] using FreeSwitch server {0}", m_freeSwitchRealm); |
206 | 181 | ||
207 | m_FreeSwitchDirectory = new FreeSwitchDirectory(); | 182 | m_Enabled = true; |
208 | m_FreeSwitchDialplan = new FreeSwitchDialplan(); | ||
209 | 183 | ||
210 | m_pluginEnabled = true; | 184 | m_log.Info("[FreeSwitchVoice] plugin enabled"); |
211 | m_WOF = false; | 185 | } |
186 | catch (Exception e) | ||
187 | { | ||
188 | m_log.ErrorFormat("[FreeSwitchVoice] plugin initialization failed: {0}", e.Message); | ||
189 | m_log.DebugFormat("[FreeSwitchVoice] plugin initialization failed: {0}", e.ToString()); | ||
190 | return; | ||
191 | } | ||
212 | 192 | ||
213 | m_log.Info("[FreeSwitchVoice] plugin enabled"); | 193 | // This here is a region module trying to make a global setting. |
194 | // Not really a good idea but it's Windows only, so I can't test. | ||
195 | try | ||
196 | { | ||
197 | ServicePointManager.ServerCertificateValidationCallback += CustomCertificateValidation; | ||
198 | } | ||
199 | catch (NotImplementedException) | ||
200 | { | ||
201 | try | ||
202 | { | ||
203 | #pragma warning disable 0612, 0618 | ||
204 | // Mono does not implement the ServicePointManager.ServerCertificateValidationCallback yet! Don't remove this! | ||
205 | ServicePointManager.CertificatePolicy = new MonoCert(); | ||
206 | #pragma warning restore 0612, 0618 | ||
214 | } | 207 | } |
215 | catch (Exception e) | 208 | catch (Exception) |
216 | { | 209 | { |
217 | m_log.ErrorFormat("[FreeSwitchVoice] plugin initialization failed: {0}", e.Message); | 210 | // COmmented multiline spam log message |
218 | m_log.DebugFormat("[FreeSwitchVoice] plugin initialization failed: {0}", e.ToString()); | 211 | //m_log.Error("[FreeSwitchVoice]: Certificate validation handler change not supported. You may get ssl certificate validation errors teleporting from your region to some SSL regions."); |
219 | return; | ||
220 | } | 212 | } |
221 | } | 213 | } |
214 | } | ||
222 | 215 | ||
223 | if (m_pluginEnabled) | 216 | public void AddRegion(Scene scene) |
217 | { | ||
218 | m_Scene = scene; | ||
219 | |||
220 | // We generate these like this: The region's external host name | ||
221 | // as defined in Regions.ini is a good address to use. It's a | ||
222 | // dotted quad (or should be!) and it can reach this host from | ||
223 | // a client. The port is grabbed from the region's HTTP server. | ||
224 | m_openSimWellKnownHTTPAddress = m_Scene.RegionInfo.ExternalHostName; | ||
225 | m_freeSwitchServicePort = MainServer.Instance.Port; | ||
226 | |||
227 | if (m_Enabled) | ||
224 | { | 228 | { |
225 | // we need to capture scene in an anonymous method | 229 | // we need to capture scene in an anonymous method |
226 | // here as we need it later in the callbacks | 230 | // here as we need it later in the callbacks |
@@ -228,36 +232,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
228 | { | 232 | { |
229 | OnRegisterCaps(scene, agentID, caps); | 233 | OnRegisterCaps(scene, agentID, caps); |
230 | }; | 234 | }; |
231 | |||
232 | try | ||
233 | { | ||
234 | ServicePointManager.ServerCertificateValidationCallback += CustomCertificateValidation; | ||
235 | } | ||
236 | catch (NotImplementedException) | ||
237 | { | ||
238 | try | ||
239 | { | ||
240 | #pragma warning disable 0612, 0618 | ||
241 | // Mono does not implement the ServicePointManager.ServerCertificateValidationCallback yet! Don't remove this! | ||
242 | ServicePointManager.CertificatePolicy = new MonoCert(); | ||
243 | #pragma warning restore 0612, 0618 | ||
244 | } | ||
245 | catch (Exception) | ||
246 | { | ||
247 | m_log.Error("[FreeSwitchVoice]: Certificate validation handler change not supported. You may get ssl certificate validation errors teleporting from your region to some SSL regions."); | ||
248 | } | ||
249 | } | ||
250 | } | 235 | } |
251 | } | 236 | } |
252 | 237 | ||
253 | public void PostInitialise() | 238 | public void RemoveRegion(Scene scene) |
254 | { | 239 | { |
255 | if (m_pluginEnabled) | 240 | } |
241 | |||
242 | public void RegionLoaded(Scene scene) | ||
243 | { | ||
244 | if (m_Enabled) | ||
256 | { | 245 | { |
257 | m_log.Info("[FreeSwitchVoice] registering IVoiceModule with the scene"); | 246 | m_log.Info("[FreeSwitchVoice] registering IVoiceModule with the scene"); |
258 | 247 | ||
259 | // register the voice interface for this module, so the script engine can call us | 248 | // register the voice interface for this module, so the script engine can call us |
260 | m_scene.RegisterModuleInterface<IVoiceModule>(this); | 249 | scene.RegisterModuleInterface<IVoiceModule>(this); |
261 | } | 250 | } |
262 | } | 251 | } |
263 | 252 | ||
@@ -270,9 +259,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
270 | get { return "FreeSwitchVoiceModule"; } | 259 | get { return "FreeSwitchVoiceModule"; } |
271 | } | 260 | } |
272 | 261 | ||
273 | public bool IsSharedModule | 262 | public Type ReplaceableInterface |
274 | { | 263 | { |
275 | get { return true; } | 264 | get { return null; } |
276 | } | 265 | } |
277 | 266 | ||
278 | // <summary> | 267 | // <summary> |
@@ -725,46 +714,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
725 | 714 | ||
726 | response["int_response_code"] = 200; | 715 | response["int_response_code"] = 200; |
727 | return response; | 716 | return response; |
728 | /* | ||
729 | <level0> | ||
730 | <status>OK</status><body><status>Ok</status><cookie_name>lib_session</cookie_name> | ||
731 | * <cookie>xMj1QJSc7TA-G7XqcW6QXAg==:1290551700:050d35c6fef96f132f780d8039ff7592::</cookie> | ||
732 | * <auth_token>xMj1QJSc7TA-G7XqcW6QXAg==:1290551700:050d35c6fef96f132f780d8039ff7592::</auth_token> | ||
733 | * <primary>1</primary> | ||
734 | * <account_id>7449</account_id> | ||
735 | * <displayname>Teravus Ousley</displayname></body></level0> | ||
736 | */ | ||
737 | } | ||
738 | |||
739 | public Hashtable FreeSwitchConfigHTTPHandler(Hashtable request) | ||
740 | { | ||
741 | m_log.DebugFormat("[FreeSwitchVoice] FreeSwitchConfigHTTPHandler called with {0}", (string)request["body"]); | ||
742 | |||
743 | Hashtable response = new Hashtable(); | ||
744 | response["str_response_string"] = string.Empty; | ||
745 | // all the params come as NVPs in the request body | ||
746 | Hashtable requestBody = parseRequestBody((string) request["body"]); | ||
747 | |||
748 | // is this a dialplan or directory request | ||
749 | string section = (string) requestBody["section"]; | ||
750 | |||
751 | if (section == "directory") | ||
752 | response = m_FreeSwitchDirectory.HandleDirectoryRequest(m_freeSwitchContext, m_freeSwitchRealm, requestBody); | ||
753 | else if (section == "dialplan") | ||
754 | response = m_FreeSwitchDialplan.HandleDialplanRequest(m_freeSwitchContext, m_freeSwitchRealm, requestBody); | ||
755 | else | ||
756 | m_log.WarnFormat("[FreeSwitchVoice]: section was {0}", section); | ||
757 | |||
758 | // XXX: re-generate dialplan: | ||
759 | // - conf == region UUID | ||
760 | // - conf number = region port | ||
761 | // -> TODO Initialise(): keep track of regions via events | ||
762 | // re-generate accounts for all avatars | ||
763 | // -> TODO Initialise(): keep track of avatars via events | ||
764 | Regex normalizeEndLines = new Regex(@"\r\n", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline); | ||
765 | |||
766 | m_log.DebugFormat("[FreeSwitchVoice] FreeSwitchConfigHTTPHandler return {0}",normalizeEndLines.Replace(((string)response["str_response_string"]), "")); | ||
767 | return response; | ||
768 | } | 717 | } |
769 | 718 | ||
770 | public Hashtable parseRequestBody(string body) | 719 | public Hashtable parseRequestBody(string body) |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 6d8e558..dee0d9a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -9283,7 +9283,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9283 | 9283 | ||
9284 | switch (data) | 9284 | switch (data) |
9285 | { | 9285 | { |
9286 | case 5: // DATA_SIM_POS | 9286 | case ScriptBaseClass.DATA_SIM_POS: |
9287 | if (info == null) | 9287 | if (info == null) |
9288 | { | 9288 | { |
9289 | ScriptSleep(1000); | 9289 | ScriptSleep(1000); |
@@ -9294,13 +9294,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9294 | info.RegionLocY, | 9294 | info.RegionLocY, |
9295 | 0).ToString(); | 9295 | 0).ToString(); |
9296 | break; | 9296 | break; |
9297 | case 6: // DATA_SIM_STATUS | 9297 | case ScriptBaseClass.DATA_SIM_STATUS: |
9298 | if (info != null) | 9298 | if (info != null) |
9299 | reply = "up"; // Duh! | 9299 | reply = "up"; // Duh! |
9300 | else | 9300 | else |
9301 | reply = "unknown"; | 9301 | reply = "unknown"; |
9302 | break; | 9302 | break; |
9303 | case 7: // DATA_SIM_RATING | 9303 | case ScriptBaseClass.DATA_SIM_RATING: |
9304 | if (info == null) | 9304 | if (info == null) |
9305 | { | 9305 | { |
9306 | ScriptSleep(1000); | 9306 | ScriptSleep(1000); |
@@ -9316,7 +9316,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9316 | else | 9316 | else |
9317 | reply = "UNKNOWN"; | 9317 | reply = "UNKNOWN"; |
9318 | break; | 9318 | break; |
9319 | case 128: | 9319 | case ScriptBaseClass.DATA_SIM_RELEASE: |
9320 | if (ossl != null) | 9320 | if (ossl != null) |
9321 | ossl.CheckThreatLevel(ThreatLevel.High, "llRequestSimulatorData"); | 9321 | ossl.CheckThreatLevel(ThreatLevel.High, "llRequestSimulatorData"); |
9322 | reply = "OpenSim"; | 9322 | reply = "OpenSim"; |
diff --git a/OpenSim/Server/Handlers/Freeswitch/FreeswitchServerConnector.cs b/OpenSim/Server/Handlers/Freeswitch/FreeswitchServerConnector.cs index 150df45..da56b87 100644 --- a/OpenSim/Server/Handlers/Freeswitch/FreeswitchServerConnector.cs +++ b/OpenSim/Server/Handlers/Freeswitch/FreeswitchServerConnector.cs | |||
@@ -35,6 +35,8 @@ using OpenSim.Services.Interfaces; | |||
35 | using OpenSim.Framework.Servers.HttpServer; | 35 | using OpenSim.Framework.Servers.HttpServer; |
36 | using OpenSim.Server.Handlers.Base; | 36 | using OpenSim.Server.Handlers.Base; |
37 | using log4net; | 37 | using log4net; |
38 | using OpenMetaverse; | ||
39 | using OpenMetaverse.StructuredData; | ||
38 | 40 | ||
39 | namespace OpenSim.Server.Handlers.Freeswitch | 41 | namespace OpenSim.Server.Handlers.Freeswitch |
40 | { | 42 | { |
@@ -67,12 +69,16 @@ namespace OpenSim.Server.Handlers.Freeswitch | |||
67 | ServerUtils.LoadPlugin<IFreeswitchService>(freeswitchService, args); | 69 | ServerUtils.LoadPlugin<IFreeswitchService>(freeswitchService, args); |
68 | 70 | ||
69 | server.AddHTTPHandler(String.Format("{0}/freeswitch-config", m_freeSwitchAPIPrefix), FreeSwitchConfigHTTPHandler); | 71 | server.AddHTTPHandler(String.Format("{0}/freeswitch-config", m_freeSwitchAPIPrefix), FreeSwitchConfigHTTPHandler); |
72 | server.AddHTTPHandler(String.Format("{0}/region-config", m_freeSwitchAPIPrefix), RegionConfigHTTPHandler); | ||
70 | } | 73 | } |
71 | 74 | ||
72 | public Hashtable FreeSwitchConfigHTTPHandler(Hashtable request) | 75 | public Hashtable FreeSwitchConfigHTTPHandler(Hashtable request) |
73 | { | 76 | { |
74 | Hashtable response = new Hashtable(); | 77 | Hashtable response = new Hashtable(); |
75 | response["str_response_string"] = string.Empty; | 78 | response["str_response_string"] = string.Empty; |
79 | response["content_type"] = "text/plain"; | ||
80 | response["keepalive"] = false; | ||
81 | response["int_response_code"] = 500; | ||
76 | 82 | ||
77 | Hashtable requestBody = ParseRequestBody((string) request["body"]); | 83 | Hashtable requestBody = ParseRequestBody((string) request["body"]); |
78 | 84 | ||
@@ -105,5 +111,18 @@ namespace OpenSim.Server.Handlers.Freeswitch | |||
105 | 111 | ||
106 | return bodyParams; | 112 | return bodyParams; |
107 | } | 113 | } |
114 | |||
115 | public Hashtable RegionConfigHTTPHandler(Hashtable request) | ||
116 | { | ||
117 | Hashtable response = new Hashtable(); | ||
118 | response["content_type"] = "text/json"; | ||
119 | response["keepalive"] = false; | ||
120 | response["int_response_code"] = 200; | ||
121 | |||
122 | response["str_response_string"] = m_FreeswitchService.GetJsonConfig(); | ||
123 | |||
124 | return response; | ||
125 | } | ||
126 | |||
108 | } | 127 | } |
109 | } | 128 | } |
diff --git a/OpenSim/Services/FreeswitchService/FreeswitchService.cs b/OpenSim/Services/FreeswitchService/FreeswitchService.cs index b62a65a..fe6f5cd 100644 --- a/OpenSim/Services/FreeswitchService/FreeswitchService.cs +++ b/OpenSim/Services/FreeswitchService/FreeswitchService.cs | |||
@@ -34,6 +34,7 @@ using OpenSim.Framework; | |||
34 | using OpenSim.Data; | 34 | using OpenSim.Data; |
35 | using OpenSim.Services.Interfaces; | 35 | using OpenSim.Services.Interfaces; |
36 | using OpenMetaverse; | 36 | using OpenMetaverse; |
37 | using OpenMetaverse.StructuredData; | ||
37 | using System.Collections; | 38 | using System.Collections; |
38 | 39 | ||
39 | namespace OpenSim.Services.FreeswitchService | 40 | namespace OpenSim.Services.FreeswitchService |
@@ -384,5 +385,22 @@ namespace OpenSim.Services.FreeswitchService | |||
384 | 385 | ||
385 | return response; | 386 | return response; |
386 | } | 387 | } |
388 | |||
389 | public string GetJsonConfig() | ||
390 | { | ||
391 | OSDMap map = new OSDMap(9); | ||
392 | |||
393 | map.Add("Realm", m_freeSwitchRealm); | ||
394 | map.Add("SIPProxy", m_freeSwitchSIPProxy); | ||
395 | map.Add("AttemptUseSTUN", m_freeSwitchAttemptUseSTUN); | ||
396 | map.Add("EchoServer", m_freeSwitchEchoServer); | ||
397 | map.Add("EchoPort", m_freeSwitchEchoPort); | ||
398 | map.Add("DefaultWellKnownIP", m_freeSwitchDefaultWellKnownIP); | ||
399 | map.Add("DefaultTimeout", m_freeSwitchDefaultTimeout); | ||
400 | map.Add("Context", m_freeSwitchContext); | ||
401 | map.Add("APIPrefix", m_freeSwitchAPIPrefix); | ||
402 | |||
403 | return OSDParser.SerializeJsonString(map); | ||
404 | } | ||
387 | } | 405 | } |
388 | } | 406 | } |
diff --git a/OpenSim/Services/Interfaces/IFreeswitchService.cs b/OpenSim/Services/Interfaces/IFreeswitchService.cs index 2b3ffeb..e7941d5 100644 --- a/OpenSim/Services/Interfaces/IFreeswitchService.cs +++ b/OpenSim/Services/Interfaces/IFreeswitchService.cs | |||
@@ -35,5 +35,6 @@ namespace OpenSim.Services.Interfaces | |||
35 | { | 35 | { |
36 | Hashtable HandleDirectoryRequest(Hashtable requestBody); | 36 | Hashtable HandleDirectoryRequest(Hashtable requestBody); |
37 | Hashtable HandleDialplanRequest(Hashtable requestBody); | 37 | Hashtable HandleDialplanRequest(Hashtable requestBody); |
38 | string GetJsonConfig(); | ||
38 | } | 39 | } |
39 | } | 40 | } |
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 9d34854..988831f 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example | |||
@@ -580,44 +580,33 @@ | |||
580 | [FreeSwitchVoice] | 580 | [FreeSwitchVoice] |
581 | ;; In order for this to work you need a functioning FreeSWITCH PBX set up. | 581 | ;; In order for this to work you need a functioning FreeSWITCH PBX set up. |
582 | ;; Configuration details at http://opensimulator.org/wiki/Freeswitch_Module | 582 | ;; Configuration details at http://opensimulator.org/wiki/Freeswitch_Module |
583 | ; enabled = false | 583 | ; Enabled = false |
584 | 584 | ||
585 | ;; FreeSWITCH server is going to contact us and ask us all sorts of things | 585 | ;; You need to load a local service for a standalone, and a remote service |
586 | ; freeswitch_server_user = freeswitch | 586 | ;; for a grid region. Use one of the lines below, as appropriate |
587 | ; freeswitch_server_pass = password | 587 | ; LocalServiceModule = OpenSim.Services.FreeswitchService.dll:FreeswitchService |
588 | ; freeswitch_api_prefix = /api | 588 | ; LocalServiceModule = OpenSim.Services.Connectors.dll:RemoteFreeswitchConnector |
589 | 589 | ||
590 | ;; external IP address of your OpenSim voice enabled region | 590 | ;; If using a remote module, specify the server URL |
591 | ;; note: all regions running on same OpenSim.exe will be enabled | 591 | ; FreeswitchServiceURL = http://my.grid.server:8003/fsapi |
592 | ; freeswitch_service_server = ip.address.of.your.sim | 592 | |
593 | 593 | [FreeswitchService] | |
594 | ;; this should be the same port the region listens on | 594 | ;; !!!!!!!!!!!!!!!!!!!!!!!!!!! |
595 | ; freeswitch_service_port = 9000 | 595 | ;; !!!!!!STANDALONE ONLY!!!!!! |
596 | ; freeswitch_realm = ip.address.of.freeswitch.server | 596 | ;; !!!!!!!!!!!!!!!!!!!!!!!!!!! |
597 | ; freeswitch_sip_proxy = ip.address.of.freeswitch.server:5060 | 597 | ;; IP of your FS server |
598 | 598 | ;ServerAddress = 85.25.142.92 | |
599 | ;; STUN = Simple Traversal of UDP through NATs | 599 | |
600 | ;; See http://wiki.freeswitch.org/wiki/NAT_Traversal | 600 | ;; All other options are - well - optional |
601 | ;; stun.freeswitch.org is not guaranteed to be running so use it in | 601 | ; Realm = "127.0.0.1" |
602 | ;; production at your own risk | 602 | ; SIPProxy = "127.0.0.1:5060" |
603 | ; freeswitch_attempt_stun = false | 603 | ; EchoServer = "127.0.0.1" |
604 | ; freeswitch_stun_server = ip.address.of.stun.server | 604 | ; EchoPort = 50505 |
605 | ; freeswitch_echo_server = ip.address.of.freeswitch.server | 605 | ; AttemptSTUN = "false" |
606 | ; freeswitch_echo_port = 50505 | 606 | ; DefaultTimeout = 5000 |
607 | ; freeswitch_well_known_ip = ip.address.of.freeswitch.server | 607 | ; Context = "default" |
608 | 608 | ; UserName = "freeswitch" | |
609 | ;; Type the address of your http server here, hostname is allowed. | 609 | ; Password = "password" |
610 | ;; This is provided so you can specify a hostname | ||
611 | ;; This is used by client for account verification. By default, it's the | ||
612 | ;; same as the freeswitch service server. | ||
613 | ; opensim_well_known_http_address = Address_Of_Your_SIM_HTTP_Server | ||
614 | |||
615 | ;; Timeouts | ||
616 | ; freeswitch_default_timeout = 5000 | ||
617 | ; freeswitch_subscribe_retry = 120 | ||
618 | |||
619 | ;; Misc | ||
620 | ; freeswitch_password_reset_url = | ||
621 | 610 | ||
622 | [Groups] | 611 | [Groups] |
623 | ;# {Enabled} {} {Enable groups?} {true false} false | 612 | ;# {Enabled} {} {Enable groups?} {true false} false |
diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example index 14998d4..b12e05b 100644 --- a/bin/Robust.ini.example +++ b/bin/Robust.ini.example | |||
@@ -70,11 +70,11 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 | |||
70 | [FreeswitchService] | 70 | [FreeswitchService] |
71 | LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService" | 71 | LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService" |
72 | ;; IP of your FS server | 72 | ;; IP of your FS server |
73 | ; FreeswitchService = 127.0.0.1 | 73 | ; ServerAddress = 127.0.0.1 |
74 | 74 | ||
75 | ;; All other options are - well - optional | 75 | ;; All other options are - well - optional |
76 | ; Realm = 1"27.0.0.1" | 76 | ; Realm = "127.0.0.1" |
77 | ; SIPProxy = 1"27.0.0.1:5060" | 77 | ; SIPProxy = "127.0.0.1:5060" |
78 | ; EchoServer = "127.0.0.1" | 78 | ; EchoServer = "127.0.0.1" |
79 | ; EchoPort = 50505 | 79 | ; EchoPort = 50505 |
80 | ; AttemptSTUN = "false" | 80 | ; AttemptSTUN = "false" |
diff --git a/prebuild.xml b/prebuild.xml index db9d502..85b31da 100644 --- a/prebuild.xml +++ b/prebuild.xml | |||
@@ -1053,6 +1053,7 @@ | |||
1053 | <ReferencePath>../../../bin/</ReferencePath> | 1053 | <ReferencePath>../../../bin/</ReferencePath> |
1054 | <Reference name="System"/> | 1054 | <Reference name="System"/> |
1055 | <Reference name="OpenMetaverseTypes" path="../../../bin/"/> | 1055 | <Reference name="OpenMetaverseTypes" path="../../../bin/"/> |
1056 | <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/> | ||
1056 | <Reference name="OpenMetaverse" path="../../../bin/"/> | 1057 | <Reference name="OpenMetaverse" path="../../../bin/"/> |
1057 | <Reference name="OpenSim.Framework"/> | 1058 | <Reference name="OpenSim.Framework"/> |
1058 | <Reference name="OpenSim.Framework.Console"/> | 1059 | <Reference name="OpenSim.Framework.Console"/> |