aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework')
-rw-r--r--OpenSim/Framework/AgentCircuitData.cs2
-rw-r--r--OpenSim/Framework/Animation.cs5
-rw-r--r--OpenSim/Framework/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/AssetBase.cs13
-rw-r--r--OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/AvatarAppearance.cs6
-rw-r--r--OpenSim/Framework/BlockingQueue.cs18
-rw-r--r--OpenSim/Framework/ClientInfo.cs5
-rw-r--r--OpenSim/Framework/Communications/OutboundUrlFilter.cs256
-rw-r--r--OpenSim/Framework/Communications/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Communications/RestClient.cs148
-rw-r--r--OpenSim/Framework/Configuration/HTTP/HTTPConfiguration.cs123
-rw-r--r--OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Framework/Configuration/XML/XmlConfiguration.cs141
-rw-r--r--OpenSim/Framework/ConfigurationMember.cs530
-rw-r--r--OpenSim/Framework/Console/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Console/CommandConsole.cs46
-rw-r--r--OpenSim/Framework/Console/ConsoleDisplayUtil.cs48
-rw-r--r--OpenSim/Framework/Console/ConsoleUtil.cs124
-rw-r--r--OpenSim/Framework/Console/LocalConsole.cs70
-rw-r--r--OpenSim/Framework/Console/MockConsole.cs3
-rw-r--r--OpenSim/Framework/EstateBan.cs49
-rw-r--r--OpenSim/Framework/EstateSettings.cs115
-rw-r--r--OpenSim/Framework/ICommandConsole.cs11
-rw-r--r--OpenSim/Framework/ILandObject.cs1
-rw-r--r--OpenSim/Framework/IPeople.cs2
-rw-r--r--OpenSim/Framework/ISceneAgent.cs7
-rw-r--r--OpenSim/Framework/ISceneObject.cs2
-rw-r--r--OpenSim/Framework/InventoryCollection.cs4
-rw-r--r--OpenSim/Framework/InventoryFolderBase.cs3
-rw-r--r--OpenSim/Framework/InventoryItemBase.cs7
-rw-r--r--OpenSim/Framework/MapItemReplyStruct.cs33
-rw-r--r--OpenSim/Framework/MetricsCollector.cs223
-rw-r--r--OpenSim/Framework/Monitoring/JobEngine.cs341
-rw-r--r--OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Monitoring/ServerStatsCollector.cs23
-rwxr-xr-x[-rw-r--r--]OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs52
-rw-r--r--OpenSim/Framework/Monitoring/Stats/Stat.cs3
-rw-r--r--OpenSim/Framework/Monitoring/StatsLogger.cs63
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs38
-rw-r--r--OpenSim/Framework/Monitoring/Watchdog.cs105
-rw-r--r--OpenSim/Framework/Monitoring/WorkManager.cs290
-rw-r--r--OpenSim/Framework/PluginLoader.cs18
-rw-r--r--OpenSim/Framework/RegionInfo.cs77
-rw-r--r--OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs27
-rw-r--r--OpenSim/Framework/SLUtil.cs396
-rw-r--r--OpenSim/Framework/Serialization/ArchiveConstants.cs10
-rw-r--r--OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs267
-rw-r--r--OpenSim/Framework/Serialization/External/LandDataSerializer.cs28
-rw-r--r--OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs47
-rw-r--r--OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs3
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs27
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs170
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs19
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs24
-rw-r--r--OpenSim/Framework/Servers/HttpServer/JsonRpcRequestManager.cs190
-rw-r--r--OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs13
-rw-r--r--OpenSim/Framework/Servers/HttpServer/OSHttpRequestPump.cs4
-rw-r--r--OpenSim/Framework/Servers/HttpServer/OSHttpServer.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs4
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs219
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestObjectPoster.cs28
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestObjectPosterResponse.cs29
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestSessionService.cs61
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs102
-rw-r--r--OpenSim/Framework/Servers/Tests/OSHttpTests.cs4
-rw-r--r--OpenSim/Framework/ServiceAuth/BasicHttpAuthentication.cs113
-rw-r--r--OpenSim/Framework/ServiceAuth/CompoundAuthentication.cs82
-rw-r--r--OpenSim/Framework/ServiceAuth/DisallowLlHttpRequest.cs (renamed from OpenSim/Framework/Configuration/HTTP/RemoteConfigSettings.cs)36
-rw-r--r--OpenSim/Framework/ServiceAuth/IServiceAuth.cs48
-rw-r--r--OpenSim/Framework/ServiceAuth/ServiceAuth.cs68
-rw-r--r--OpenSim/Framework/Tests/AnimationTests.cs1
-rw-r--r--OpenSim/Framework/Tests/AssetBaseTest.cs4
-rw-r--r--OpenSim/Framework/Tests/UtilTest.cs21
-rw-r--r--OpenSim/Framework/ThreadSafeRandom.cs72
-rw-r--r--OpenSim/Framework/UntrustedWebRequest.cs230
-rw-r--r--OpenSim/Framework/UserProfileData.cs4
-rw-r--r--OpenSim/Framework/UserProfiles.cs3
-rw-r--r--OpenSim/Framework/Util.cs970
-rw-r--r--OpenSim/Framework/VersionInfo.cs (renamed from OpenSim/Framework/Servers/VersionInfo.cs)7
-rw-r--r--OpenSim/Framework/WebUtil.cs860
86 files changed, 5308 insertions, 1974 deletions
diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs
index f2fe494..0d053e4 100644
--- a/OpenSim/Framework/AgentCircuitData.cs
+++ b/OpenSim/Framework/AgentCircuitData.cs
@@ -321,6 +321,8 @@ namespace OpenSim.Framework
321 Mac = args["mac"].AsString(); 321 Mac = args["mac"].AsString();
322 if (args["id0"] != null) 322 if (args["id0"] != null)
323 Id0 = args["id0"].AsString(); 323 Id0 = args["id0"].AsString();
324 if (args["teleport_flags"] != null)
325 teleportFlags = args["teleport_flags"].AsUInteger();
324 326
325 if (args["start_pos"] != null) 327 if (args["start_pos"] != null)
326 Vector3.TryParse(args["start_pos"].AsString(), out startpos); 328 Vector3.TryParse(args["start_pos"].AsString(), out startpos);
diff --git a/OpenSim/Framework/Animation.cs b/OpenSim/Framework/Animation.cs
index 3425505..e958b75 100644
--- a/OpenSim/Framework/Animation.cs
+++ b/OpenSim/Framework/Animation.cs
@@ -132,6 +132,11 @@ namespace OpenSim.Framework
132 return base.Equals(obj); 132 return base.Equals(obj);
133 } 133 }
134 134
135 public override int GetHashCode()
136 {
137 return base.GetHashCode();
138 }
139
135 public override string ToString() 140 public override string ToString()
136 { 141 {
137 return "AnimID=" + AnimID.ToString() 142 return "AnimID=" + AnimID.ToString()
diff --git a/OpenSim/Framework/AssemblyInfo.cs b/OpenSim/Framework/AssemblyInfo.cs
index 287b988..a797424 100644
--- a/OpenSim/Framework/AssemblyInfo.cs
+++ b/OpenSim/Framework/AssemblyInfo.cs
@@ -59,4 +59,4 @@ using System.Runtime.InteropServices;
59// Revision 59// Revision
60// 60//
61 61
62[assembly : AssemblyVersion("0.8.0.*")] 62[assembly : AssemblyVersion("0.8.2.*")]
diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs
index 5da8e11..3937d9c 100644
--- a/OpenSim/Framework/AssetBase.cs
+++ b/OpenSim/Framework/AssetBase.cs
@@ -50,6 +50,9 @@ namespace OpenSim.Framework
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 public static readonly int MAX_ASSET_NAME = 64;
54 public static readonly int MAX_ASSET_DESC = 64;
55
53 /// <summary> 56 /// <summary>
54 /// Data of the Asset 57 /// Data of the Asset
55 /// </summary> 58 /// </summary>
@@ -135,7 +138,7 @@ namespace OpenSim.Framework
135 get 138 get
136 { 139 {
137 return 140 return
138 (Type == (sbyte) AssetType.Animation || 141 (Type == (sbyte)AssetType.Animation ||
139 Type == (sbyte)AssetType.Gesture || 142 Type == (sbyte)AssetType.Gesture ||
140 Type == (sbyte)AssetType.Simstate || 143 Type == (sbyte)AssetType.Simstate ||
141 Type == (sbyte)AssetType.Unknown || 144 Type == (sbyte)AssetType.Unknown ||
@@ -145,14 +148,14 @@ namespace OpenSim.Framework
145 Type == (sbyte)AssetType.Texture || 148 Type == (sbyte)AssetType.Texture ||
146 Type == (sbyte)AssetType.TextureTGA || 149 Type == (sbyte)AssetType.TextureTGA ||
147 Type == (sbyte)AssetType.Folder || 150 Type == (sbyte)AssetType.Folder ||
148 Type == (sbyte)AssetType.RootFolder ||
149 Type == (sbyte)AssetType.LostAndFoundFolder ||
150 Type == (sbyte)AssetType.SnapshotFolder ||
151 Type == (sbyte)AssetType.TrashFolder ||
152 Type == (sbyte)AssetType.ImageJPEG || 151 Type == (sbyte)AssetType.ImageJPEG ||
153 Type == (sbyte)AssetType.ImageTGA || 152 Type == (sbyte)AssetType.ImageTGA ||
153<<<<<<< HEAD
154 Type == (sbyte)AssetType.LSLBytecode);
155=======
154 Type == (sbyte)AssetType.Mesh || 156 Type == (sbyte)AssetType.Mesh ||
155 Type == (sbyte) AssetType.LSLBytecode); 157 Type == (sbyte) AssetType.LSLBytecode);
158>>>>>>> avn/ubitvar
156 } 159 }
157 } 160 }
158 161
diff --git a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
index 11fece3..cd182d6 100644
--- a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.0.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs
index 3874c47..72c6bfc 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -536,6 +536,12 @@ namespace OpenSim.Framework
536 if (!m_attachments.ContainsKey(attach.AttachPoint)) 536 if (!m_attachments.ContainsKey(attach.AttachPoint))
537 m_attachments[attach.AttachPoint] = new List<AvatarAttachment>(); 537 m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
538 538
539 foreach (AvatarAttachment prev in m_attachments[attach.AttachPoint])
540 {
541 if (prev.ItemID == attach.ItemID)
542 return;
543 }
544
539 m_attachments[attach.AttachPoint].Add(attach); 545 m_attachments[attach.AttachPoint].Add(attach);
540 } 546 }
541 } 547 }
diff --git a/OpenSim/Framework/BlockingQueue.cs b/OpenSim/Framework/BlockingQueue.cs
index aef1192..daf99a8 100644
--- a/OpenSim/Framework/BlockingQueue.cs
+++ b/OpenSim/Framework/BlockingQueue.cs
@@ -97,11 +97,11 @@ namespace OpenSim.Framework
97 /// </remarks> 97 /// </remarks>
98 public bool Contains(T item) 98 public bool Contains(T item)
99 { 99 {
100 if (m_queue.Count < 1 && m_pqueue.Count < 1)
101 return false;
102
103 lock (m_queueSync) 100 lock (m_queueSync)
104 { 101 {
102 if (m_queue.Count < 1 && m_pqueue.Count < 1)
103 return false;
104
105 if (m_pqueue.Contains(item)) 105 if (m_pqueue.Contains(item))
106 return true; 106 return true;
107 return m_queue.Contains(item); 107 return m_queue.Contains(item);
@@ -111,12 +111,10 @@ namespace OpenSim.Framework
111 /// <summary> 111 /// <summary>
112 /// Return a count of the number of requests on this queue. 112 /// Return a count of the number of requests on this queue.
113 /// </summary> 113 /// </summary>
114 /// <remarks>
115 /// This method is not thread-safe. Do not rely on the result without consistent external locking.
116 /// </remarks>
117 public int Count() 114 public int Count()
118 { 115 {
119 return m_queue.Count + m_pqueue.Count; 116 lock (m_queueSync)
117 return m_queue.Count + m_pqueue.Count;
120 } 118 }
121 119
122 /// <summary> 120 /// <summary>
@@ -127,11 +125,11 @@ namespace OpenSim.Framework
127 /// </remarks> 125 /// </remarks>
128 public T[] GetQueueArray() 126 public T[] GetQueueArray()
129 { 127 {
130 if (m_queue.Count < 1 && m_pqueue.Count < 1)
131 return new T[0];
132
133 lock (m_queueSync) 128 lock (m_queueSync)
134 { 129 {
130 if (m_queue.Count < 1 && m_pqueue.Count < 1)
131 return new T[0];
132
135 return m_queue.ToArray(); 133 return m_queue.ToArray();
136 } 134 }
137 } 135 }
diff --git a/OpenSim/Framework/ClientInfo.cs b/OpenSim/Framework/ClientInfo.cs
index 9021315..98e4465 100644
--- a/OpenSim/Framework/ClientInfo.cs
+++ b/OpenSim/Framework/ClientInfo.cs
@@ -55,6 +55,11 @@ namespace OpenSim.Framework
55 public int textureThrottle; 55 public int textureThrottle;
56 public int totalThrottle; 56 public int totalThrottle;
57 57
58 // Used by adaptive only
59 public int targetThrottle;
60
61 public int maxThrottle;
62
58 public Dictionary<string, int> SyncRequests = new Dictionary<string,int>(); 63 public Dictionary<string, int> SyncRequests = new Dictionary<string,int>();
59 public Dictionary<string, int> AsyncRequests = new Dictionary<string,int>(); 64 public Dictionary<string, int> AsyncRequests = new Dictionary<string,int>();
60 public Dictionary<string, int> GenericRequests = new Dictionary<string,int>(); 65 public Dictionary<string, int> GenericRequests = new Dictionary<string,int>();
diff --git a/OpenSim/Framework/Communications/OutboundUrlFilter.cs b/OpenSim/Framework/Communications/OutboundUrlFilter.cs
new file mode 100644
index 0000000..8b572d1
--- /dev/null
+++ b/OpenSim/Framework/Communications/OutboundUrlFilter.cs
@@ -0,0 +1,256 @@
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
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Net;
32using System.Reflection;
33using log4net;
34using LukeSkywalker.IPNetwork;
35using Nini.Config;
36
37namespace OpenSim.Framework.Communications
38{
39 public class OutboundUrlFilter
40 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42
43 public string Name { get; private set; }
44
45 private List<IPNetwork> m_blacklistNetworks;
46 private List<IPEndPoint> m_blacklistEndPoints;
47
48 private List<IPNetwork> m_blacklistExceptionNetworks;
49 private List<IPEndPoint> m_blacklistExceptionEndPoints;
50
51 public OutboundUrlFilter(
52 string name,
53 List<IPNetwork> blacklistNetworks, List<IPEndPoint> blacklistEndPoints,
54 List<IPNetwork> blacklistExceptionNetworks, List<IPEndPoint> blacklistExceptionEndPoints)
55 {
56 Name = name;
57
58 m_blacklistNetworks = blacklistNetworks;
59 m_blacklistEndPoints = blacklistEndPoints;
60 m_blacklistExceptionNetworks = blacklistExceptionNetworks;
61 m_blacklistExceptionEndPoints = blacklistExceptionEndPoints;
62 }
63
64 /// <summary>
65 /// Initializes a new instance of the <see cref="OpenSim.Framework.Communications.OutboundUrlFilter"/> class.
66 /// </summary>
67 /// <param name="name">Name of the filter for logging purposes.</param>
68 /// <param name="config">Filter configuration</param>
69 public OutboundUrlFilter(string name, IConfigSource config)
70 {
71 Name = name;
72
73 string configBlacklist
74 = "0.0.0.0/8|10.0.0.0/8|100.64.0.0/10|127.0.0.0/8|169.254.0.0/16|172.16.0.0/12|192.0.0.0/24|192.0.2.0/24|192.88.99.0/24|192.168.0.0/16|198.18.0.0/15|198.51.100.0/24|203.0.113.0/24|224.0.0.0/4|240.0.0.0/4|255.255.255.255/32";
75 string configBlacklistExceptions = "";
76
77 IConfig networkConfig = config.Configs["Network"];
78
79 if (networkConfig != null)
80 {
81 configBlacklist = networkConfig.GetString("OutboundDisallowForUserScripts", configBlacklist);
82 configBlacklistExceptions
83 = networkConfig.GetString("OutboundDisallowForUserScriptsExcept", configBlacklistExceptions);
84 }
85
86 m_log.DebugFormat(
87 "[OUTBOUND URL FILTER]: OutboundDisallowForUserScripts for {0} is [{1}]", Name, configBlacklist);
88 m_log.DebugFormat(
89 "[OUTBOUND URL FILTER]: OutboundDisallowForUserScriptsExcept for {0} is [{1}]", Name, configBlacklistExceptions);
90
91 OutboundUrlFilter.ParseConfigList(
92 configBlacklist, Name, out m_blacklistNetworks, out m_blacklistEndPoints);
93 OutboundUrlFilter.ParseConfigList(
94 configBlacklistExceptions, Name, out m_blacklistExceptionNetworks, out m_blacklistExceptionEndPoints);
95 }
96
97 private static void ParseConfigList(
98 string fullConfigEntry, string filterName, out List<IPNetwork> networks, out List<IPEndPoint> endPoints)
99 {
100 // Parse blacklist
101 string[] configBlacklistEntries
102 = fullConfigEntry.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
103
104 configBlacklistEntries = configBlacklistEntries.Select(e => e.Trim()).ToArray();
105
106 networks = new List<IPNetwork>();
107 endPoints = new List<IPEndPoint>();
108
109 foreach (string configEntry in configBlacklistEntries)
110 {
111 if (configEntry.Contains("/"))
112 {
113 IPNetwork network;
114
115 if (!IPNetwork.TryParse(configEntry, out network))
116 {
117 m_log.ErrorFormat(
118 "[OUTBOUND URL FILTER]: Entry [{0}] is invalid network for {1}", configEntry, filterName);
119
120 continue;
121 }
122
123 networks.Add(network);
124 }
125 else
126 {
127 Uri configEntryUri;
128
129 if (!Uri.TryCreate("http://" + configEntry, UriKind.Absolute, out configEntryUri))
130 {
131 m_log.ErrorFormat(
132 "[OUTBOUND URL FILTER]: EndPoint entry [{0}] is invalid endpoint for {1}",
133 configEntry, filterName);
134
135 continue;
136 }
137
138 IPAddress[] addresses = Dns.GetHostAddresses(configEntryUri.Host);
139
140 foreach (IPAddress addr in addresses)
141 {
142 if (addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
143 {
144 // m_log.DebugFormat("[OUTBOUND URL FILTER]: Found address [{0}] in config", addr);
145
146 IPEndPoint configEntryEp = new IPEndPoint(addr, configEntryUri.Port);
147 endPoints.Add(configEntryEp);
148
149 // m_log.DebugFormat("[OUTBOUND URL FILTER]: Added blacklist exception [{0}]", configEntryEp);
150 }
151 }
152 }
153 }
154 }
155
156 /// <summary>
157 /// Determines if an url is in a list of networks and endpoints.
158 /// </summary>
159 /// <returns></returns>
160 /// <param name="url">IP address</param>
161 /// <param name="port"></param>
162 /// <param name="networks">Networks.</param>
163 /// <param name="endPoints">End points.</param>
164 /// <param name="filterName">Filter name.</param>
165 private static bool IsInNetwork(
166 IPAddress addr, int port, List<IPNetwork> networks, List<IPEndPoint> endPoints, string filterName)
167 {
168 foreach (IPNetwork ipn in networks)
169 {
170// m_log.DebugFormat(
171// "[OUTBOUND URL FILTER]: Checking [{0}] against network [{1}]", addr, ipn);
172
173 if (IPNetwork.Contains(ipn, addr))
174 {
175// m_log.DebugFormat(
176// "[OUTBOUND URL FILTER]: Found [{0}] in network [{1}]", addr, ipn);
177
178 return true;
179 }
180 }
181
182 // m_log.DebugFormat("[OUTBOUND URL FILTER]: Found address [{0}]", addr);
183
184 foreach (IPEndPoint ep in endPoints)
185 {
186// m_log.DebugFormat(
187// "[OUTBOUND URL FILTER]: Checking [{0}:{1}] against endpoint [{2}]",
188// addr, port, ep);
189
190 if (addr.Equals(ep.Address) && port == ep.Port)
191 {
192// m_log.DebugFormat(
193// "[OUTBOUND URL FILTER]: Found [{0}:{1}] in endpoint [{2}]", addr, port, ep);
194
195 return true;
196 }
197 }
198
199// m_log.DebugFormat("[OUTBOUND URL FILTER]: Did not find [{0}:{1}] in list", addr, port);
200
201 return false;
202 }
203
204 /// <summary>
205 /// Checks whether the given url is allowed by the filter.
206 /// </summary>
207 /// <returns></returns>
208 public bool CheckAllowed(Uri url)
209 {
210 bool allowed = true;
211
212 // Check that we are permitted to make calls to this endpoint.
213 bool foundIpv4Address = false;
214
215 IPAddress[] addresses = Dns.GetHostAddresses(url.Host);
216
217 foreach (IPAddress addr in addresses)
218 {
219 if (addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
220 {
221// m_log.DebugFormat("[OUTBOUND URL FILTER]: Found address [{0}]", addr);
222
223 foundIpv4Address = true;
224
225 // Check blacklist
226 if (OutboundUrlFilter.IsInNetwork(addr, url.Port, m_blacklistNetworks, m_blacklistEndPoints, Name))
227 {
228// m_log.DebugFormat("[OUTBOUND URL FILTER]: Found [{0}] in blacklist for {1}", url, Name);
229
230 // Check blacklist exceptions
231 allowed
232 = OutboundUrlFilter.IsInNetwork(
233 addr, url.Port, m_blacklistExceptionNetworks, m_blacklistExceptionEndPoints, Name);
234
235// if (allowed)
236// m_log.DebugFormat("[OUTBOUND URL FILTER]: Found [{0}] in whitelist for {1}", url, Name);
237 }
238 }
239
240 // Found at least one address in a blacklist and not a blacklist exception
241 if (!allowed)
242 return false;
243// else
244// m_log.DebugFormat("[OUTBOUND URL FILTER]: URL [{0}] not in blacklist for {1}", url, Name);
245 }
246
247 // We do not know how to handle IPv6 securely yet.
248 if (!foundIpv4Address)
249 return false;
250
251// m_log.DebugFormat("[OUTBOUND URL FILTER]: Allowing request [{0}]", url);
252
253 return allowed;
254 }
255 }
256} \ No newline at end of file
diff --git a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
index 09611fa..b398167 100644
--- a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.8.0.*")] 64[assembly : AssemblyVersion("0.8.2.*")]
65 65
diff --git a/OpenSim/Framework/Communications/RestClient.cs b/OpenSim/Framework/Communications/RestClient.cs
index ce36fbf..4403f40 100644
--- a/OpenSim/Framework/Communications/RestClient.cs
+++ b/OpenSim/Framework/Communications/RestClient.cs
@@ -35,6 +35,8 @@ using System.Threading;
35using System.Web; 35using System.Web;
36using log4net; 36using log4net;
37 37
38using OpenSim.Framework.ServiceAuth;
39
38namespace OpenSim.Framework.Communications 40namespace OpenSim.Framework.Communications
39{ 41{
40 /// <summary> 42 /// <summary>
@@ -54,7 +56,7 @@ namespace OpenSim.Framework.Communications
54 /// other threads to execute, while it waits for a response from the web-service. RestClient itself can be 56 /// other threads to execute, while it waits for a response from the web-service. RestClient itself can be
55 /// invoked by the caller in either synchronous mode or asynchronous modes. 57 /// invoked by the caller in either synchronous mode or asynchronous modes.
56 /// </remarks> 58 /// </remarks>
57 public class RestClient 59 public class RestClient : IDisposable
58 { 60 {
59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60 62
@@ -88,7 +90,7 @@ namespace OpenSim.Framework.Communications
88 private byte[] _readbuf; 90 private byte[] _readbuf;
89 91
90 /// <summary> 92 /// <summary>
91 /// MemoryStream representing the resultiong resource 93 /// MemoryStream representing the resulting resource
92 /// </summary> 94 /// </summary>
93 private Stream _resource; 95 private Stream _resource;
94 96
@@ -146,6 +148,33 @@ namespace OpenSim.Framework.Communications
146 148
147 #endregion constructors 149 #endregion constructors
148 150
151
152 #region Dispose
153
154 private bool disposed = false;
155
156 public void Dispose()
157 {
158 Dispose(true);
159 GC.SuppressFinalize(this);
160 }
161
162 protected virtual void Dispose(bool disposing)
163 {
164 if (disposed)
165 return;
166
167 if (disposing)
168 {
169 _resource.Dispose();
170 }
171
172 disposed = true;
173 }
174
175 #endregion Dispose
176
177
149 /// <summary> 178 /// <summary>
150 /// Add a path element to the query, e.g. assets 179 /// Add a path element to the query, e.g. assets
151 /// </summary> 180 /// </summary>
@@ -299,6 +328,14 @@ namespace OpenSim.Framework.Communications
299 /// </summary> 328 /// </summary>
300 public Stream Request() 329 public Stream Request()
301 { 330 {
331 return Request(null);
332 }
333
334 /// <summary>
335 /// Perform a synchronous request
336 /// </summary>
337 public Stream Request(IServiceAuth auth)
338 {
302 lock (_lock) 339 lock (_lock)
303 { 340 {
304 _request = (HttpWebRequest) WebRequest.Create(buildUri()); 341 _request = (HttpWebRequest) WebRequest.Create(buildUri());
@@ -307,23 +344,49 @@ namespace OpenSim.Framework.Communications
307 _request.Timeout = 200000; 344 _request.Timeout = 200000;
308 _request.Method = RequestMethod; 345 _request.Method = RequestMethod;
309 _asyncException = null; 346 _asyncException = null;
347 if (auth != null)
348 auth.AddAuthorization(_request.Headers);
349
350 int reqnum = WebUtil.RequestNumber++;
351 if (WebUtil.DebugLevel >= 3)
352 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} REST {1} to {2}", reqnum, _request.Method, _request.RequestUri);
310 353
311// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); 354// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request);
355
312 try 356 try
313 { 357 {
314 _response = (HttpWebResponse) _request.GetResponse(); 358 using (_response = (HttpWebResponse) _request.GetResponse())
359 {
360 using (Stream src = _response.GetResponseStream())
361 {
362 int length = src.Read(_readbuf, 0, BufferSize);
363 while (length > 0)
364 {
365 _resource.Write(_readbuf, 0, length);
366 length = src.Read(_readbuf, 0, BufferSize);
367 }
368
369 // TODO! Implement timeout, without killing the server
370 // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
371 //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true);
372
373 // _allDone.WaitOne();
374 }
375 }
315 } 376 }
316 catch (WebException e) 377 catch (WebException e)
317 { 378 {
318 HttpWebResponse errorResponse = e.Response as HttpWebResponse; 379 using (HttpWebResponse errorResponse = e.Response as HttpWebResponse)
319 if (null != errorResponse && HttpStatusCode.NotFound == errorResponse.StatusCode)
320 {
321 m_log.Warn("[REST CLIENT] Resource not found (404)");
322 }
323 else
324 { 380 {
325 m_log.Error("[REST CLIENT] Error fetching resource from server " + _request.Address.ToString()); 381 if (null != errorResponse && HttpStatusCode.NotFound == errorResponse.StatusCode)
326 m_log.Debug(e.ToString()); 382 {
383 // This is often benign. E.g., requesting a missing asset will return 404.
384 m_log.DebugFormat("[REST CLIENT] Resource not found (404): {0}", _request.Address.ToString());
385 }
386 else
387 {
388 m_log.Error(string.Format("[REST CLIENT] Error fetching resource from server: {0} ", _request.Address.ToString()), e);
389 }
327 } 390 }
328 391
329 if (_response != null) 392 if (_response != null)
@@ -332,6 +395,8 @@ namespace OpenSim.Framework.Communications
332 return null; 395 return null;
333 } 396 }
334 397
398<<<<<<< HEAD
399=======
335 using (Stream src = _response.GetResponseStream()) 400 using (Stream src = _response.GetResponseStream())
336 { 401 {
337 int length = src.Read(_readbuf, 0, BufferSize); 402 int length = src.Read(_readbuf, 0, BufferSize);
@@ -349,6 +414,7 @@ namespace OpenSim.Framework.Communications
349// _allDone.WaitOne(); 414// _allDone.WaitOne();
350 if (_response != null) 415 if (_response != null)
351 _response.Close(); 416 _response.Close();
417>>>>>>> avn/ubitvar
352 if (_asyncException != null) 418 if (_asyncException != null)
353 throw _asyncException; 419 throw _asyncException;
354 420
@@ -358,11 +424,14 @@ namespace OpenSim.Framework.Communications
358 _resource.Seek(0, SeekOrigin.Begin); 424 _resource.Seek(0, SeekOrigin.Begin);
359 } 425 }
360 426
427 if (WebUtil.DebugLevel >= 5)
428 WebUtil.LogResponseDetail(reqnum, _resource);
429
361 return _resource; 430 return _resource;
362 } 431 }
363 } 432 }
364 433
365 public Stream Request(Stream src) 434 public Stream Request(Stream src, IServiceAuth auth)
366 { 435 {
367 _request = (HttpWebRequest) WebRequest.Create(buildUri()); 436 _request = (HttpWebRequest) WebRequest.Create(buildUri());
368 _request.KeepAlive = false; 437 _request.KeepAlive = false;
@@ -371,13 +440,28 @@ namespace OpenSim.Framework.Communications
371 _request.Method = RequestMethod; 440 _request.Method = RequestMethod;
372 _asyncException = null; 441 _asyncException = null;
373 _request.ContentLength = src.Length; 442 _request.ContentLength = src.Length;
443 if (auth != null)
444 auth.AddAuthorization(_request.Headers);
374 445
375 m_log.InfoFormat("[REST]: Request Length {0}", _request.ContentLength);
376 m_log.InfoFormat("[REST]: Sending Web Request {0}", buildUri());
377 src.Seek(0, SeekOrigin.Begin); 446 src.Seek(0, SeekOrigin.Begin);
447<<<<<<< HEAD
448
449 int reqnum = WebUtil.RequestNumber++;
450 if (WebUtil.DebugLevel >= 3)
451 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} REST {1} to {2}", reqnum, _request.Method, _request.RequestUri);
452 if (WebUtil.DebugLevel >= 5)
453 WebUtil.LogOutgoingDetail(string.Format("SEND {0}: ", reqnum), src);
454
455 Stream dst = _request.GetRequestStream();
456
457 byte[] buf = new byte[1024];
458 int length = src.Read(buf, 0, 1024);
459 while (length > 0)
460=======
378 m_log.Info("[REST]: Seek is ok"); 461 m_log.Info("[REST]: Seek is ok");
379 462
380 using (Stream dst = _request.GetRequestStream()) 463 using (Stream dst = _request.GetRequestStream())
464>>>>>>> avn/ubitvar
381 { 465 {
382 m_log.Info("[REST]: GetRequestStream is ok"); 466 m_log.Info("[REST]: GetRequestStream is ok");
383 467
@@ -391,7 +475,37 @@ namespace OpenSim.Framework.Communications
391 } 475 }
392 } 476 }
393 477
394 _response = (HttpWebResponse) _request.GetResponse(); 478 try
479 {
480 _response = (HttpWebResponse)_request.GetResponse();
481 }
482 catch (WebException e)
483 {
484 m_log.WarnFormat("[REST]: Request {0} {1} failed with status {2} and message {3}",
485 RequestMethod, _request.RequestUri, e.Status, e.Message);
486 return null;
487 }
488 catch (Exception e)
489 {
490 m_log.WarnFormat(
491 "[REST]: Request {0} {1} failed with exception {2} {3}",
492 RequestMethod, _request.RequestUri, e.Message, e.StackTrace);
493 return null;
494 }
495
496 if (WebUtil.DebugLevel >= 5)
497 {
498 using (Stream responseStream = _response.GetResponseStream())
499 {
500 using (StreamReader reader = new StreamReader(responseStream))
501 {
502 string responseStr = reader.ReadToEnd();
503 WebUtil.LogResponseDetail(reqnum, responseStr);
504 }
505 }
506 }
507
508 _response.Close();
395 509
396 if (_response != null) 510 if (_response != null)
397 _response.Close(); 511 _response.Close();
@@ -413,7 +527,7 @@ namespace OpenSim.Framework.Communications
413 /// In case, we are invoked asynchroneously this object will keep track of the state 527 /// In case, we are invoked asynchroneously this object will keep track of the state
414 /// </summary> 528 /// </summary>
415 AsyncResult<Stream> ar = new AsyncResult<Stream>(callback, state); 529 AsyncResult<Stream> ar = new AsyncResult<Stream>(callback, state);
416 Util.FireAndForget(RequestHelper, ar); 530 Util.FireAndForget(RequestHelper, ar, "RestClient.BeginRequest");
417 return ar; 531 return ar;
418 } 532 }
419 533
@@ -433,7 +547,7 @@ namespace OpenSim.Framework.Communications
433 try 547 try
434 { 548 {
435 // Perform the operation; if sucessful set the result 549 // Perform the operation; if sucessful set the result
436 Stream s = Request(); 550 Stream s = Request(null);
437 ar.SetAsCompleted(s, false); 551 ar.SetAsCompleted(s, false);
438 } 552 }
439 catch (Exception e) 553 catch (Exception e)
diff --git a/OpenSim/Framework/Configuration/HTTP/HTTPConfiguration.cs b/OpenSim/Framework/Configuration/HTTP/HTTPConfiguration.cs
deleted file mode 100644
index 6681c37..0000000
--- a/OpenSim/Framework/Configuration/HTTP/HTTPConfiguration.cs
+++ /dev/null
@@ -1,123 +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
28using System;
29using System.IO;
30using System.Net;
31using System.Reflection;
32using System.Text;
33using log4net;
34using OpenSim.Framework.Configuration.XML;
35
36namespace OpenSim.Framework.Configuration.HTTP
37{
38 public class HTTPConfiguration : IGenericConfig
39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
42 private RemoteConfigSettings remoteConfigSettings;
43
44 private XmlConfiguration xmlConfig;
45
46 private string configFileName = String.Empty;
47
48 public HTTPConfiguration()
49 {
50 remoteConfigSettings = new RemoteConfigSettings("remoteconfig.xml");
51 xmlConfig = new XmlConfiguration();
52 }
53
54 public void SetFileName(string fileName)
55 {
56 configFileName = fileName;
57 }
58
59 public void LoadData()
60 {
61 try
62 {
63 StringBuilder sb = new StringBuilder();
64
65 byte[] buf = new byte[8192];
66 HttpWebRequest request =
67 (HttpWebRequest) WebRequest.Create(remoteConfigSettings.baseConfigURL + configFileName);
68 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
69 {
70 using (Stream resStream = response.GetResponseStream())
71 {
72 string tempString = null;
73 int count = 0;
74
75 do
76 {
77 count = resStream.Read(buf, 0, buf.Length);
78 if (count != 0)
79 {
80 tempString = Util.UTF8.GetString(buf, 0, count);
81 sb.Append(tempString);
82 }
83 }
84 while (count > 0);
85
86 LoadDataFromString(sb.ToString());
87 }
88 }
89 }
90 catch (WebException)
91 {
92 m_log.Warn("Unable to connect to remote configuration file (" +
93 remoteConfigSettings.baseConfigURL + configFileName +
94 "). Creating local file instead.");
95 xmlConfig.SetFileName(configFileName);
96 xmlConfig.LoadData();
97 }
98 }
99
100 public void LoadDataFromString(string data)
101 {
102 xmlConfig.LoadDataFromString(data);
103 }
104
105 public string GetAttribute(string attributeName)
106 {
107 return xmlConfig.GetAttribute(attributeName);
108 }
109
110 public bool SetAttribute(string attributeName, string attributeValue)
111 {
112 return true;
113 }
114
115 public void Commit()
116 {
117 }
118
119 public void Close()
120 {
121 }
122 }
123}
diff --git a/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs b/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
deleted file mode 100644
index 05a2e0e..0000000
--- a/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,33 +0,0 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Framework.Configuration.HTTP")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator develoeprs")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("cb78b672-d000-4f93-88f9-dae151cc0061")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.8.0.*")]
33
diff --git a/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs b/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
deleted file mode 100644
index d928a94..0000000
--- a/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,33 +0,0 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Framework.Configuration.XML")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("eeb880df-0112-4c3d-87ed-b2108d614c55")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.8.0.*")]
33
diff --git a/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs b/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs
deleted file mode 100644
index 3152a7d..0000000
--- a/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs
+++ /dev/null
@@ -1,141 +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
28using System;
29using System.IO;
30using System.Xml;
31
32namespace OpenSim.Framework.Configuration.XML
33{
34 public class XmlConfiguration : IGenericConfig
35 {
36 private XmlDocument doc;
37 private XmlNode rootNode;
38 private XmlNode configNode;
39 private string fileName;
40 private bool createdFile = false;
41
42 public void SetFileName(string file)
43 {
44 fileName = file;
45 }
46
47 private void LoadDataToClass()
48 {
49 rootNode = doc.SelectSingleNode("Root");
50 if (null == rootNode)
51 throw new Exception("Error: Invalid .xml File. Missing <Root>");
52
53 configNode = rootNode.SelectSingleNode("Config");
54 if (null == configNode)
55 throw new Exception("Error: Invalid .xml File. <Root> should contain a <Config>");
56 }
57
58 public void LoadData()
59 {
60 lock (this)
61 {
62 doc = new XmlDocument();
63 if (File.Exists(fileName))
64 {
65 XmlTextReader reader = new XmlTextReader(fileName);
66 reader.WhitespaceHandling = WhitespaceHandling.None;
67 doc.Load(reader);
68 reader.Close();
69 }
70 else
71 {
72 createdFile = true;
73 rootNode = doc.CreateNode(XmlNodeType.Element, "Root", String.Empty);
74 doc.AppendChild(rootNode);
75 configNode = doc.CreateNode(XmlNodeType.Element, "Config", String.Empty);
76 rootNode.AppendChild(configNode);
77 }
78
79 LoadDataToClass();
80
81 if (createdFile)
82 {
83 Commit();
84 }
85 }
86 }
87
88 public void LoadDataFromString(string data)
89 {
90 doc = new XmlDocument();
91 doc.LoadXml(data);
92
93 LoadDataToClass();
94 }
95
96 public string GetAttribute(string attributeName)
97 {
98 string result = null;
99 if (configNode.Attributes[attributeName] != null)
100 {
101 result = ((XmlAttribute) configNode.Attributes.GetNamedItem(attributeName)).Value;
102 }
103 return result;
104 }
105
106 public bool SetAttribute(string attributeName, string attributeValue)
107 {
108 if (configNode.Attributes[attributeName] != null)
109 {
110 ((XmlAttribute) configNode.Attributes.GetNamedItem(attributeName)).Value = attributeValue;
111 }
112 else
113 {
114 XmlAttribute attri;
115 attri = doc.CreateAttribute(attributeName);
116 attri.Value = attributeValue;
117 configNode.Attributes.Append(attri);
118 }
119 return true;
120 }
121
122 public void Commit()
123 {
124 if (string.IsNullOrEmpty(fileName))
125 return;
126
127 if (!Directory.Exists(Util.configDir()))
128 {
129 Directory.CreateDirectory(Util.configDir());
130 }
131 doc.Save(fileName);
132 }
133
134 public void Close()
135 {
136 configNode = null;
137 rootNode = null;
138 doc = null;
139 }
140 }
141}
diff --git a/OpenSim/Framework/ConfigurationMember.cs b/OpenSim/Framework/ConfigurationMember.cs
deleted file mode 100644
index 7afa68a..0000000
--- a/OpenSim/Framework/ConfigurationMember.cs
+++ /dev/null
@@ -1,530 +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
28using System;
29using System.Collections.Generic;
30using System.Globalization;
31using System.Net;
32using System.Reflection;
33using System.Xml;
34using log4net;
35using OpenMetaverse;
36//using OpenSim.Framework.Console;
37
38namespace OpenSim.Framework
39{
40 public class ConfigurationMember
41 {
42 #region Delegates
43
44 public delegate bool ConfigurationOptionResult(string configuration_key, object configuration_result);
45
46 public delegate void ConfigurationOptionsLoad();
47
48 #endregion
49
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 private int cE = 0;
52
53 private string configurationDescription = String.Empty;
54 private string configurationFilename = String.Empty;
55 private XmlNode configurationFromXMLNode = null;
56 private List<ConfigurationOption> configurationOptions = new List<ConfigurationOption>();
57 private IGenericConfig configurationPlugin = null;
58
59 /// <summary>
60 /// This is the default configuration DLL loaded
61 /// </summary>
62 private string configurationPluginFilename = "OpenSim.Framework.Configuration.XML.dll";
63
64 private ConfigurationOptionsLoad loadFunction;
65 private ConfigurationOptionResult resultFunction;
66
67 private bool useConsoleToPromptOnError = true;
68
69 public ConfigurationMember(string configuration_filename, string configuration_description,
70 ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error)
71 {
72 configurationFilename = configuration_filename;
73 configurationDescription = configuration_description;
74 loadFunction = load_function;
75 resultFunction = result_function;
76 useConsoleToPromptOnError = use_console_to_prompt_on_error;
77 }
78
79 public ConfigurationMember(XmlNode configuration_xml, string configuration_description,
80 ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error)
81 {
82 configurationFilename = String.Empty;
83 configurationFromXMLNode = configuration_xml;
84 configurationDescription = configuration_description;
85 loadFunction = load_function;
86 resultFunction = result_function;
87 useConsoleToPromptOnError = use_console_to_prompt_on_error;
88 }
89
90 public void setConfigurationFilename(string filename)
91 {
92 configurationFilename = filename;
93 }
94
95 public void setConfigurationDescription(string desc)
96 {
97 configurationDescription = desc;
98 }
99
100 public void setConfigurationResultFunction(ConfigurationOptionResult result)
101 {
102 resultFunction = result;
103 }
104
105 public void forceConfigurationPluginLibrary(string dll_filename)
106 {
107 configurationPluginFilename = dll_filename;
108 }
109
110 private void checkAndAddConfigOption(ConfigurationOption option)
111 {
112 if ((option.configurationKey != String.Empty && option.configurationQuestion != String.Empty) ||
113 (option.configurationKey != String.Empty && option.configurationUseDefaultNoPrompt))
114 {
115 if (!configurationOptions.Contains(option))
116 {
117 configurationOptions.Add(option);
118 }
119 }
120 else
121 {
122 m_log.Info(
123 "Required fields for adding a configuration option is invalid. Will not add this option (" +
124 option.configurationKey + ")");
125 }
126 }
127
128 public void addConfigurationOption(string configuration_key,
129 ConfigurationOption.ConfigurationTypes configuration_type,
130 string configuration_question, string configuration_default,
131 bool use_default_no_prompt)
132 {
133 ConfigurationOption configOption = new ConfigurationOption();
134 configOption.configurationKey = configuration_key;
135 configOption.configurationQuestion = configuration_question;
136 configOption.configurationDefault = configuration_default;
137 configOption.configurationType = configuration_type;
138 configOption.configurationUseDefaultNoPrompt = use_default_no_prompt;
139 configOption.shouldIBeAsked = null; //Assumes true, I can ask whenever
140 checkAndAddConfigOption(configOption);
141 }
142
143 public void addConfigurationOption(string configuration_key,
144 ConfigurationOption.ConfigurationTypes configuration_type,
145 string configuration_question, string configuration_default,
146 bool use_default_no_prompt,
147 ConfigurationOption.ConfigurationOptionShouldBeAsked shouldIBeAskedDelegate)
148 {
149 ConfigurationOption configOption = new ConfigurationOption();
150 configOption.configurationKey = configuration_key;
151 configOption.configurationQuestion = configuration_question;
152 configOption.configurationDefault = configuration_default;
153 configOption.configurationType = configuration_type;
154 configOption.configurationUseDefaultNoPrompt = use_default_no_prompt;
155 configOption.shouldIBeAsked = shouldIBeAskedDelegate;
156 checkAndAddConfigOption(configOption);
157 }
158
159 // TEMP - REMOVE
160 public void performConfigurationRetrieve()
161 {
162 if (cE > 1)
163 m_log.Error("READING CONFIGURATION COUT: " + cE.ToString());
164
165
166 configurationPlugin = LoadConfigDll(configurationPluginFilename);
167 configurationOptions.Clear();
168 if (loadFunction == null)
169 {
170 m_log.Error("Load Function for '" + configurationDescription +
171 "' is null. Refusing to run configuration.");
172 return;
173 }
174
175 if (resultFunction == null)
176 {
177 m_log.Error("Result Function for '" + configurationDescription +
178 "' is null. Refusing to run configuration.");
179 return;
180 }
181
182 //m_log.Debug("[CONFIG]: Calling Configuration Load Function...");
183 loadFunction();
184
185 if (configurationOptions.Count <= 0)
186 {
187 m_log.Error("[CONFIG]: No configuration options were specified for '" + configurationOptions +
188 "'. Refusing to continue configuration.");
189 return;
190 }
191
192 bool useFile = true;
193 if (configurationPlugin == null)
194 {
195 m_log.Error("[CONFIG]: Configuration Plugin NOT LOADED!");
196 return;
197 }
198
199 if (configurationFilename.Trim() != String.Empty)
200 {
201 configurationPlugin.SetFileName(configurationFilename);
202 try
203 {
204 configurationPlugin.LoadData();
205 useFile = true;
206 }
207 catch (XmlException e)
208 {
209 m_log.WarnFormat("[CONFIG] Not using {0}: {1}",
210 configurationFilename,
211 e.Message.ToString());
212 //m_log.Error("Error loading " + configurationFilename + ": " + e.ToString());
213 useFile = false;
214 }
215 }
216 else
217 {
218 if (configurationFromXMLNode != null)
219 {
220 m_log.Info("Loading from XML Node, will not save to the file");
221 configurationPlugin.LoadDataFromString(configurationFromXMLNode.OuterXml);
222 }
223
224 m_log.Info("XML Configuration Filename is not valid; will not save to the file.");
225 useFile = false;
226 }
227
228 foreach (ConfigurationOption configOption in configurationOptions)
229 {
230 bool convertSuccess = false;
231 object return_result = null;
232 string errorMessage = String.Empty;
233 bool ignoreNextFromConfig = false;
234 while (convertSuccess == false)
235 {
236 string console_result = String.Empty;
237 string attribute = null;
238 if (useFile || configurationFromXMLNode != null)
239 {
240 if (!ignoreNextFromConfig)
241 {
242 attribute = configurationPlugin.GetAttribute(configOption.configurationKey);
243 }
244 else
245 {
246 ignoreNextFromConfig = false;
247 }
248 }
249
250 if (attribute == null)
251 {
252 if (configOption.configurationUseDefaultNoPrompt || useConsoleToPromptOnError == false)
253 {
254 console_result = configOption.configurationDefault;
255 }
256 else
257 {
258 if ((configOption.shouldIBeAsked != null &&
259 configOption.shouldIBeAsked(configOption.configurationKey)) ||
260 configOption.shouldIBeAsked == null)
261 {
262 if (configurationDescription.Trim() != String.Empty)
263 {
264 console_result =
265 MainConsole.Instance.CmdPrompt(
266 configurationDescription + ": " + configOption.configurationQuestion,
267 configOption.configurationDefault);
268 }
269 else
270 {
271 console_result =
272 MainConsole.Instance.CmdPrompt(configOption.configurationQuestion,
273 configOption.configurationDefault);
274 }
275 }
276 else
277 {
278 //Dont Ask! Just use default
279 console_result = configOption.configurationDefault;
280 }
281 }
282 }
283 else
284 {
285 console_result = attribute;
286 }
287
288 // if the first character is a "$", assume it's the name
289 // of an environment variable and substitute with the value of that variable
290 if (console_result.StartsWith("$"))
291 console_result = Environment.GetEnvironmentVariable(console_result.Substring(1));
292
293 switch (configOption.configurationType)
294 {
295 case ConfigurationOption.ConfigurationTypes.TYPE_STRING:
296 return_result = console_result;
297 convertSuccess = true;
298 break;
299 case ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY:
300 if (console_result.Length > 0)
301 {
302 return_result = console_result;
303 convertSuccess = true;
304 }
305 errorMessage = "a string that is not empty";
306 break;
307 case ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN:
308 bool boolResult;
309 if (Boolean.TryParse(console_result, out boolResult))
310 {
311 convertSuccess = true;
312 return_result = boolResult;
313 }
314 errorMessage = "'true' or 'false' (Boolean)";
315 break;
316 case ConfigurationOption.ConfigurationTypes.TYPE_BYTE:
317 byte byteResult;
318 if (Byte.TryParse(console_result, out byteResult))
319 {
320 convertSuccess = true;
321 return_result = byteResult;
322 }
323 errorMessage = "a byte (Byte)";
324 break;
325 case ConfigurationOption.ConfigurationTypes.TYPE_CHARACTER:
326 char charResult;
327 if (Char.TryParse(console_result, out charResult))
328 {
329 convertSuccess = true;
330 return_result = charResult;
331 }
332 errorMessage = "a character (Char)";
333 break;
334 case ConfigurationOption.ConfigurationTypes.TYPE_INT16:
335 short shortResult;
336 if (Int16.TryParse(console_result, out shortResult))
337 {
338 convertSuccess = true;
339 return_result = shortResult;
340 }
341 errorMessage = "a signed 32 bit integer (short)";
342 break;
343 case ConfigurationOption.ConfigurationTypes.TYPE_INT32:
344 int intResult;
345 if (Int32.TryParse(console_result, out intResult))
346 {
347 convertSuccess = true;
348 return_result = intResult;
349 }
350 errorMessage = "a signed 32 bit integer (int)";
351 break;
352 case ConfigurationOption.ConfigurationTypes.TYPE_INT64:
353 long longResult;
354 if (Int64.TryParse(console_result, out longResult))
355 {
356 convertSuccess = true;
357 return_result = longResult;
358 }
359 errorMessage = "a signed 32 bit integer (long)";
360 break;
361 case ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS:
362 IPAddress ipAddressResult;
363 if (IPAddress.TryParse(console_result, out ipAddressResult))
364 {
365 convertSuccess = true;
366 return_result = ipAddressResult;
367 }
368 errorMessage = "an IP Address (IPAddress)";
369 break;
370 case ConfigurationOption.ConfigurationTypes.TYPE_UUID:
371 UUID uuidResult;
372 if (UUID.TryParse(console_result, out uuidResult))
373 {
374 convertSuccess = true;
375 return_result = uuidResult;
376 }
377 errorMessage = "a UUID (UUID)";
378 break;
379 case ConfigurationOption.ConfigurationTypes.TYPE_UUID_NULL_FREE:
380 UUID uuidResult2;
381 if (UUID.TryParse(console_result, out uuidResult2))
382 {
383 convertSuccess = true;
384
385 if (uuidResult2 == UUID.Zero)
386 uuidResult2 = UUID.Random();
387
388 return_result = uuidResult2;
389 }
390 errorMessage = "a non-null UUID (UUID)";
391 break;
392 case ConfigurationOption.ConfigurationTypes.TYPE_Vector3:
393 Vector3 vectorResult;
394 if (Vector3.TryParse(console_result, out vectorResult))
395 {
396 convertSuccess = true;
397 return_result = vectorResult;
398 }
399 errorMessage = "a vector (Vector3)";
400 break;
401 case ConfigurationOption.ConfigurationTypes.TYPE_UINT16:
402 ushort ushortResult;
403 if (UInt16.TryParse(console_result, out ushortResult))
404 {
405 convertSuccess = true;
406 return_result = ushortResult;
407 }
408 errorMessage = "an unsigned 16 bit integer (ushort)";
409 break;
410 case ConfigurationOption.ConfigurationTypes.TYPE_UINT32:
411 uint uintResult;
412 if (UInt32.TryParse(console_result, out uintResult))
413 {
414 convertSuccess = true;
415 return_result = uintResult;
416 }
417 errorMessage = "an unsigned 32 bit integer (uint)";
418 break;
419 case ConfigurationOption.ConfigurationTypes.TYPE_UINT64:
420 ulong ulongResult;
421 if (UInt64.TryParse(console_result, out ulongResult))
422 {
423 convertSuccess = true;
424 return_result = ulongResult;
425 }
426 errorMessage = "an unsigned 64 bit integer (ulong)";
427 break;
428 case ConfigurationOption.ConfigurationTypes.TYPE_FLOAT:
429 float floatResult;
430 if (
431 float.TryParse(console_result, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, Culture.NumberFormatInfo,
432 out floatResult))
433 {
434 convertSuccess = true;
435 return_result = floatResult;
436 }
437 errorMessage = "a single-precision floating point number (float)";
438 break;
439 case ConfigurationOption.ConfigurationTypes.TYPE_DOUBLE:
440 double doubleResult;
441 if (
442 Double.TryParse(console_result, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, Culture.NumberFormatInfo,
443 out doubleResult))
444 {
445 convertSuccess = true;
446 return_result = doubleResult;
447 }
448 errorMessage = "an double-precision floating point number (double)";
449 break;
450 }
451
452 if (convertSuccess)
453 {
454 if (useFile)
455 {
456 configurationPlugin.SetAttribute(configOption.configurationKey, console_result);
457 }
458
459 if (!resultFunction(configOption.configurationKey, return_result))
460 {
461 m_log.Info(
462 "The handler for the last configuration option denied that input, please try again.");
463 convertSuccess = false;
464 ignoreNextFromConfig = true;
465 }
466 }
467 else
468 {
469 if (configOption.configurationUseDefaultNoPrompt)
470 {
471 m_log.Error(string.Format(
472 "[CONFIG]: [{3}]:[{1}] is not valid default for parameter [{0}].\nThe configuration result must be parsable to {2}.\n",
473 configOption.configurationKey, console_result, errorMessage,
474 configurationFilename));
475 convertSuccess = true;
476 }
477 else
478 {
479 m_log.Warn(string.Format(
480 "[CONFIG]: [{3}]:[{1}] is not a valid value [{0}].\nThe configuration result must be parsable to {2}.\n",
481 configOption.configurationKey, console_result, errorMessage,
482 configurationFilename));
483 ignoreNextFromConfig = true;
484 }
485 }
486 }
487 }
488
489 if (useFile)
490 {
491 configurationPlugin.Commit();
492 configurationPlugin.Close();
493 }
494 }
495
496 private static IGenericConfig LoadConfigDll(string dllName)
497 {
498 Assembly pluginAssembly = Assembly.LoadFrom(dllName);
499 IGenericConfig plug = null;
500
501 foreach (Type pluginType in pluginAssembly.GetTypes())
502 {
503 if (pluginType.IsPublic)
504 {
505 if (!pluginType.IsAbstract)
506 {
507 Type typeInterface = pluginType.GetInterface("IGenericConfig", true);
508
509 if (typeInterface != null)
510 {
511 plug =
512 (IGenericConfig) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
513 }
514 }
515 }
516 }
517
518 pluginAssembly = null;
519 return plug;
520 }
521
522 public void forceSetConfigurationOption(string configuration_key, string configuration_value)
523 {
524 configurationPlugin.LoadData();
525 configurationPlugin.SetAttribute(configuration_key, configuration_value);
526 configurationPlugin.Commit();
527 configurationPlugin.Close();
528 }
529 }
530}
diff --git a/OpenSim/Framework/Console/AssemblyInfo.cs b/OpenSim/Framework/Console/AssemblyInfo.cs
index ba59025..67af471 100644
--- a/OpenSim/Framework/Console/AssemblyInfo.cs
+++ b/OpenSim/Framework/Console/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.8.0.*")] 58[assembly : AssemblyVersion("0.8.2.*")]
diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs
index 9490013..851fbed 100644
--- a/OpenSim/Framework/Console/CommandConsole.cs
+++ b/OpenSim/Framework/Console/CommandConsole.cs
@@ -429,9 +429,9 @@ namespace OpenSim.Framework.Console
429 return new string[] { new List<string>(current.Keys)[0] }; 429 return new string[] { new List<string>(current.Keys)[0] };
430 } 430 }
431 431
432 public string[] Resolve(string[] cmd) 432 private CommandInfo ResolveCommand(string[] cmd, out string[] result)
433 { 433 {
434 string[] result = cmd; 434 result = cmd;
435 int index = -1; 435 int index = -1;
436 436
437 Dictionary<string, object> current = tree; 437 Dictionary<string, object> current = tree;
@@ -463,7 +463,7 @@ namespace OpenSim.Framework.Console
463 } 463 }
464 else if (found.Count > 0) 464 else if (found.Count > 0)
465 { 465 {
466 return new string[0]; 466 return null;
467 } 467 }
468 else 468 else
469 { 469 {
@@ -472,21 +472,37 @@ namespace OpenSim.Framework.Console
472 } 472 }
473 473
474 if (current.ContainsKey(String.Empty)) 474 if (current.ContainsKey(String.Empty))
475 return (CommandInfo)current[String.Empty];
476
477 return null;
478 }
479
480 public bool HasCommand(string command)
481 {
482 string[] result;
483 return ResolveCommand(Parser.Parse(command), out result) != null;
484 }
485
486 public string[] Resolve(string[] cmd)
487 {
488 string[] result;
489 CommandInfo ci = ResolveCommand(cmd, out result);
490
491 if (ci == null)
492 return new string[0];
493
494 if (ci.fn.Count == 0)
495 return new string[0];
496
497 foreach (CommandDelegate fn in ci.fn)
475 { 498 {
476 CommandInfo ci = (CommandInfo)current[String.Empty]; 499 if (fn != null)
477 if (ci.fn.Count == 0) 500 fn(ci.module, result);
501 else
478 return new string[0]; 502 return new string[0];
479 foreach (CommandDelegate fn in ci.fn)
480 {
481 if (fn != null)
482 fn(ci.module, result);
483 else
484 return new string[0];
485 }
486 return result;
487 } 503 }
488 504
489 return new string[0]; 505 return result;
490 } 506 }
491 507
492 public XmlElement GetXml(XmlDocument doc) 508 public XmlElement GetXml(XmlDocument doc)
diff --git a/OpenSim/Framework/Console/ConsoleDisplayUtil.cs b/OpenSim/Framework/Console/ConsoleDisplayUtil.cs
new file mode 100644
index 0000000..6417663
--- /dev/null
+++ b/OpenSim/Framework/Console/ConsoleDisplayUtil.cs
@@ -0,0 +1,48 @@
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
28using System;
29
30namespace OpenSim.Framework.Console
31{
32 /// <summary>
33 /// This will be a set of typical column sizes to allow greater consistency between console commands.
34 /// </summary>
35 public static class ConsoleDisplayUtil
36 {
37 public const int CoordTupleSize = 11;
38 public const int PortSize = 5;
39
40 public const int EstateNameSize = 20;
41 public const int ParcelNameSize = 40;
42 public const int RegionNameSize = 20;
43 public const int UserNameSize = 35;
44
45 public const int UuidSize = 36;
46 public const int VectorSize = 15;
47 }
48} \ No newline at end of file
diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs
index 794bfaf..44f6dc1 100644
--- a/OpenSim/Framework/Console/ConsoleUtil.cs
+++ b/OpenSim/Framework/Console/ConsoleUtil.cs
@@ -156,7 +156,7 @@ namespace OpenSim.Framework.Console
156 } 156 }
157 157
158 /// <summary> 158 /// <summary>
159 /// Convert a console integer to an int, automatically complaining if a console is given. 159 /// Convert a console input to a bool, automatically complaining if a console is given.
160 /// </summary> 160 /// </summary>
161 /// <param name='console'>Can be null if no console is available.</param> 161 /// <param name='console'>Can be null if no console is available.</param>
162 /// <param name='rawConsoleVector'>/param> 162 /// <param name='rawConsoleVector'>/param>
@@ -176,7 +176,7 @@ namespace OpenSim.Framework.Console
176 } 176 }
177 177
178 /// <summary> 178 /// <summary>
179 /// Convert a console integer to an int, automatically complaining if a console is given. 179 /// Convert a console input to an int, automatically complaining if a console is given.
180 /// </summary> 180 /// </summary>
181 /// <param name='console'>Can be null if no console is available.</param> 181 /// <param name='console'>Can be null if no console is available.</param>
182 /// <param name='rawConsoleInt'>/param> 182 /// <param name='rawConsoleInt'>/param>
@@ -196,6 +196,46 @@ namespace OpenSim.Framework.Console
196 } 196 }
197 197
198 /// <summary> 198 /// <summary>
199 /// Convert a console input to a float, automatically complaining if a console is given.
200 /// </summary>
201 /// <param name='console'>Can be null if no console is available.</param>
202 /// <param name='rawConsoleInput'>/param>
203 /// <param name='i'></param>
204 /// <returns></returns>
205 public static bool TryParseConsoleFloat(ICommandConsole console, string rawConsoleInput, out float i)
206 {
207 if (!float.TryParse(rawConsoleInput, out i))
208 {
209 if (console != null)
210 console.OutputFormat("ERROR: {0} is not a valid float", rawConsoleInput);
211
212 return false;
213 }
214
215 return true;
216 }
217
218 /// <summary>
219 /// Convert a console input to a double, automatically complaining if a console is given.
220 /// </summary>
221 /// <param name='console'>Can be null if no console is available.</param>
222 /// <param name='rawConsoleInput'>/param>
223 /// <param name='i'></param>
224 /// <returns></returns>
225 public static bool TryParseConsoleDouble(ICommandConsole console, string rawConsoleInput, out double i)
226 {
227 if (!double.TryParse(rawConsoleInput, out i))
228 {
229 if (console != null)
230 console.OutputFormat("ERROR: {0} is not a valid double", rawConsoleInput);
231
232 return false;
233 }
234
235 return true;
236 }
237
238 /// <summary>
199 /// Convert a console integer to a natural int, automatically complaining if a console is given. 239 /// Convert a console integer to a natural int, automatically complaining if a console is given.
200 /// </summary> 240 /// </summary>
201 /// <param name='console'>Can be null if no console is available.</param> 241 /// <param name='console'>Can be null if no console is available.</param>
@@ -252,24 +292,82 @@ namespace OpenSim.Framework.Console
252 /// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue 292 /// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue
253 /// Other than that, component values must be numeric. 293 /// Other than that, component values must be numeric.
254 /// </param> 294 /// </param>
255 /// <param name='blankComponentFunc'></param> 295 /// <param name='blankComponentFunc'>
296 /// Behaviour if component is blank. If null then conversion fails on a blank component.
297 /// </param>
256 /// <param name='vector'></param> 298 /// <param name='vector'></param>
257 /// <returns></returns> 299 /// <returns></returns>
258 public static bool TryParseConsoleVector( 300 public static bool TryParseConsoleVector(
259 string rawConsoleVector, Func<string, string> blankComponentFunc, out Vector3 vector) 301 string rawConsoleVector, Func<string, string> blankComponentFunc, out Vector3 vector)
260 { 302 {
261 List<string> components = rawConsoleVector.Split(VectorSeparatorChars).ToList(); 303 return Vector3.TryParse(CookVector(rawConsoleVector, 3, blankComponentFunc), out vector);
262 304 }
263 if (components.Count < 1 || components.Count > 3) 305
306 /// <summary>
307 /// Convert a vector input from the console to an OpenMetaverse.Vector2
308 /// </summary>
309 /// <param name='rawConsoleVector'>
310 /// A string in the form <x>,<y> where there is no space between values.
311 /// Any component can be missing (e.g. ,40). blankComponentFunc is invoked to replace the blank with a suitable value
312 /// Also, if the blank component is at the end, then the comma can be missed off entirely (e.g. 40)
313 /// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue
314 /// Other than that, component values must be numeric.
315 /// </param>
316 /// <param name='blankComponentFunc'>
317 /// Behaviour if component is blank. If null then conversion fails on a blank component.
318 /// </param>
319 /// <param name='vector'></param>
320 /// <returns></returns>
321 public static bool TryParseConsole2DVector(
322 string rawConsoleVector, Func<string, string> blankComponentFunc, out Vector2 vector)
323 {
324 // We don't use Vector2.TryParse() for now because for some reason it expects an input with 3 components
325 // rather than 2.
326 string cookedVector = CookVector(rawConsoleVector, 2, blankComponentFunc);
327
328 if (cookedVector == null)
264 { 329 {
265 vector = Vector3.Zero; 330 vector = Vector2.Zero;
331
266 return false; 332 return false;
267 } 333 }
334 else
335 {
336 string[] cookedComponents = cookedVector.Split(VectorSeparatorChars);
337
338 vector = new Vector2(float.Parse(cookedComponents[0]), float.Parse(cookedComponents[1]));
339
340 return true;
341 }
342
343 //return Vector2.TryParse(CookVector(rawConsoleVector, 2, blankComponentFunc), out vector);
344 }
345
346 /// <summary>
347 /// Convert a raw console vector into a vector that can be be parsed by the relevant OpenMetaverse.TryParse()
348 /// </summary>
349 /// <param name='rawConsoleVector'></param>
350 /// <param name='dimensions'></param>
351 /// <param name='blankComponentFunc'></param>
352 /// <returns>null if conversion was not possible</returns>
353 private static string CookVector(
354 string rawConsoleVector, int dimensions, Func<string, string> blankComponentFunc)
355 {
356 List<string> components = rawConsoleVector.Split(VectorSeparatorChars).ToList();
268 357
269 for (int i = components.Count; i < 3; i++) 358 if (components.Count < 1 || components.Count > dimensions)
270 components.Add(""); 359 return null;
271 360
272 List<string> semiDigestedComponents 361 if (components.Count < dimensions)
362 {
363 if (blankComponentFunc == null)
364 return null;
365 else
366 for (int i = components.Count; i < dimensions; i++)
367 components.Add("");
368 }
369
370 List<string> cookedComponents
273 = components.ConvertAll<string>( 371 = components.ConvertAll<string>(
274 c => 372 c =>
275 { 373 {
@@ -283,11 +381,7 @@ namespace OpenSim.Framework.Console
283 return c; 381 return c;
284 }); 382 });
285 383
286 string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray()); 384 return string.Join(VectorSeparator, cookedComponents.ToArray());
287
288 // m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector);
289
290 return Vector3.TryParse(semiDigestedConsoleVector, out vector);
291 } 385 }
292 } 386 }
293} \ No newline at end of file 387} \ No newline at end of file
diff --git a/OpenSim/Framework/Console/LocalConsole.cs b/OpenSim/Framework/Console/LocalConsole.cs
index a967db6..28293c0 100644
--- a/OpenSim/Framework/Console/LocalConsole.cs
+++ b/OpenSim/Framework/Console/LocalConsole.cs
@@ -32,6 +32,8 @@ using System.Reflection;
32using System.Text; 32using System.Text;
33using System.Text.RegularExpressions; 33using System.Text.RegularExpressions;
34using System.Threading; 34using System.Threading;
35using System.IO;
36using Nini.Config;
35using log4net; 37using log4net;
36 38
37namespace OpenSim.Framework.Console 39namespace OpenSim.Framework.Console
@@ -41,11 +43,18 @@ namespace OpenSim.Framework.Console
41 /// </summary> 43 /// </summary>
42 public class LocalConsole : CommandConsole 44 public class LocalConsole : CommandConsole
43 { 45 {
44// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 private string m_historyPath;
48 private bool m_historyEnable;
45 49
46 // private readonly object m_syncRoot = new object(); 50 // private readonly object m_syncRoot = new object();
47 private const string LOGLEVEL_NONE = "(none)"; 51 private const string LOGLEVEL_NONE = "(none)";
48 52
53 // Used to extract categories for colourization.
54 private Regex m_categoryRegex
55 = new Regex(
56 @"^(?<Front>.*?)\[(?<Category>[^\]]+)\]:?(?<End>.*)", RegexOptions.Singleline | RegexOptions.Compiled);
57
49 private int m_cursorYPosition = -1; 58 private int m_cursorYPosition = -1;
50 private int m_cursorXPosition = 0; 59 private int m_cursorXPosition = 0;
51 private StringBuilder m_commandLine = new StringBuilder(); 60 private StringBuilder m_commandLine = new StringBuilder();
@@ -74,8 +83,54 @@ namespace OpenSim.Framework.Console
74 return Colors[(Math.Abs(input.ToUpper().GetHashCode()) % Colors.Length)]; 83 return Colors[(Math.Abs(input.ToUpper().GetHashCode()) % Colors.Length)];
75 } 84 }
76 85
77 public LocalConsole(string defaultPrompt) : base(defaultPrompt) 86 public LocalConsole(string defaultPrompt, IConfig startupConfig = null) : base(defaultPrompt)
78 { 87 {
88
89 if (startupConfig == null) return;
90
91 m_historyEnable = startupConfig.GetBoolean("ConsoleHistoryFileEnabled", false);
92 if (!m_historyEnable)
93 {
94 m_log.Info("[LOCAL CONSOLE]: Persistent command line history from file is Disabled");
95 return;
96 }
97
98 string m_historyFile = startupConfig.GetString("ConsoleHistoryFile", "OpenSimConsoleHistory.txt");
99 int m_historySize = startupConfig.GetInt("ConsoleHistoryFileLines", 100);
100 m_historyPath = Path.GetFullPath(Path.Combine(Util.configDir(), m_historyFile));
101 m_log.InfoFormat("[LOCAL CONSOLE]: Persistent command line history is Enabled, up to {0} lines from file {1}", m_historySize, m_historyPath);
102
103 if (File.Exists(m_historyPath))
104 {
105 using (StreamReader history_file = new StreamReader(m_historyPath))
106 {
107 string line;
108 while ((line = history_file.ReadLine()) != null)
109 {
110 m_history.Add(line);
111 }
112 }
113
114 if (m_history.Count > m_historySize)
115 {
116 while (m_history.Count > m_historySize)
117 m_history.RemoveAt(0);
118
119 using (StreamWriter history_file = new StreamWriter(m_historyPath))
120 {
121 foreach (string line in m_history)
122 {
123 history_file.WriteLine(line);
124 }
125 }
126 }
127 m_log.InfoFormat("[LOCAL CONSOLE]: Read {0} lines of command line history from file {1}", m_history.Count, m_historyPath);
128 }
129 else
130 {
131 m_log.InfoFormat("[LOCAL CONSOLE]: Creating new empty command line history file {0}", m_historyPath);
132 File.Create(m_historyPath).Dispose();
133 }
79 } 134 }
80 135
81 private void AddToHistory(string text) 136 private void AddToHistory(string text)
@@ -84,6 +139,10 @@ namespace OpenSim.Framework.Console
84 m_history.RemoveAt(0); 139 m_history.RemoveAt(0);
85 140
86 m_history.Add(text); 141 m_history.Add(text);
142 if (m_historyEnable)
143 {
144 File.AppendAllText(m_historyPath, text + Environment.NewLine);
145 }
87 } 146 }
88 147
89 /// <summary> 148 /// <summary>
@@ -280,11 +339,8 @@ namespace OpenSim.Framework.Console
280 string outText = text; 339 string outText = text;
281 340
282 if (level != LOGLEVEL_NONE) 341 if (level != LOGLEVEL_NONE)
283 { 342 {
284 string regex = @"^(?<Front>.*?)\[(?<Category>[^\]]+)\]:?(?<End>.*)"; 343 MatchCollection matches = m_categoryRegex.Matches(text);
285
286 Regex RE = new Regex(regex, RegexOptions.Multiline);
287 MatchCollection matches = RE.Matches(text);
288 344
289 if (matches.Count == 1) 345 if (matches.Count == 1)
290 { 346 {
diff --git a/OpenSim/Framework/Console/MockConsole.cs b/OpenSim/Framework/Console/MockConsole.cs
index 8ba58e4..1a142df 100644
--- a/OpenSim/Framework/Console/MockConsole.cs
+++ b/OpenSim/Framework/Console/MockConsole.cs
@@ -40,7 +40,9 @@ namespace OpenSim.Framework.Console
40 /// </summary> 40 /// </summary>
41 public class MockConsole : ICommandConsole 41 public class MockConsole : ICommandConsole
42 { 42 {
43#pragma warning disable 0067
43 public event OnOutputDelegate OnOutput; 44 public event OnOutputDelegate OnOutput;
45#pragma warning restore 0067
44 46
45 private MockCommands m_commands = new MockCommands(); 47 private MockCommands m_commands = new MockCommands();
46 48
@@ -80,6 +82,7 @@ namespace OpenSim.Framework.Console
80 public void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn) {} 82 public void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn) {}
81 public void AddCommand(string module, bool shared, string command, string help, string longhelp, string descriptivehelp, CommandDelegate fn) {} 83 public void AddCommand(string module, bool shared, string command, string help, string longhelp, string descriptivehelp, CommandDelegate fn) {}
82 public string[] FindNextOption(string[] cmd, bool term) { return null; } 84 public string[] FindNextOption(string[] cmd, bool term) { return null; }
85 public bool HasCommand(string cmd) { return false; }
83 public string[] Resolve(string[] cmd) { return null; } 86 public string[] Resolve(string[] cmd) { return null; }
84 public XmlElement GetXml(XmlDocument doc) { return null; } 87 public XmlElement GetXml(XmlDocument doc) { return null; }
85 } 88 }
diff --git a/OpenSim/Framework/EstateBan.cs b/OpenSim/Framework/EstateBan.cs
index de9ebf6..ebed794 100644
--- a/OpenSim/Framework/EstateBan.cs
+++ b/OpenSim/Framework/EstateBan.cs
@@ -25,6 +25,10 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31
28using OpenMetaverse; 32using OpenMetaverse;
29 33
30namespace OpenSim.Framework 34namespace OpenSim.Framework
@@ -111,5 +115,50 @@ namespace OpenSim.Framework
111 } 115 }
112 } 116 }
113 117
118 public EstateBan() { }
119
120 public Dictionary<string, object> ToMap()
121 {
122 Dictionary<string, object> map = new Dictionary<string, object>();
123 PropertyInfo[] properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
124 foreach (PropertyInfo p in properties)
125 map[p.Name] = p.GetValue(this, null);
126
127 return map;
128 }
129
130 public EstateBan(Dictionary<string, object> map)
131 {
132 foreach (KeyValuePair<string, object> kvp in map)
133 {
134 PropertyInfo p = this.GetType().GetProperty(kvp.Key, BindingFlags.Public | BindingFlags.Instance);
135 if (p == null)
136 continue;
137 object value = p.GetValue(this, null);
138 if (value is String)
139 p.SetValue(this, map[p.Name], null);
140 else if (value is UInt32)
141 p.SetValue(this, UInt32.Parse((string)map[p.Name]), null);
142 else if (value is Boolean)
143 p.SetValue(this, Boolean.Parse((string)map[p.Name]), null);
144 else if (value is UUID)
145 p.SetValue(this, UUID.Parse((string)map[p.Name]), null);
146 }
147 }
148
149
150 /// <summary>
151 /// For debugging
152 /// </summary>
153 /// <returns></returns>
154 public override string ToString()
155 {
156 Dictionary<string, object> map = ToMap();
157 string result = string.Empty;
158 foreach (KeyValuePair<string, object> kvp in map)
159 result += string.Format("{0}: {1} {2}", kvp.Key, kvp.Value, Environment.NewLine);
160
161 return result;
162 }
114 } 163 }
115} 164}
diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs
index 5ddbd61..3aec437 100644
--- a/OpenSim/Framework/EstateSettings.cs
+++ b/OpenSim/Framework/EstateSettings.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Reflection;
31using OpenMetaverse; 32using OpenMetaverse;
32 33
33namespace OpenSim.Framework 34namespace OpenSim.Framework
@@ -430,5 +431,119 @@ namespace OpenSim.Framework
430 { 431 {
431 return l_EstateGroups.Contains(groupID); 432 return l_EstateGroups.Contains(groupID);
432 } 433 }
434
435 public Dictionary<string, object> ToMap()
436 {
437 Dictionary<string, object> map = new Dictionary<string, object>();
438 PropertyInfo[] properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
439 foreach (PropertyInfo p in properties)
440 {
441 // EstateBans is a complex type, let's treat it as special
442 if (p.Name == "EstateBans")
443 continue;
444
445 object value = p.GetValue(this, null);
446 if (value != null)
447 {
448 if (p.PropertyType.IsArray) // of UUIDs
449 {
450 if (((Array)value).Length > 0)
451 {
452 string[] args = new string[((Array)value).Length];
453 int index = 0;
454 foreach (object o in (Array)value)
455 args[index++] = o.ToString();
456 map[p.Name] = String.Join(",", args);
457 }
458 }
459 else // simple types
460 map[p.Name] = value;
461 }
462 }
463
464 // EstateBans are special
465 if (EstateBans.Length > 0)
466 {
467 Dictionary<string, object> bans = new Dictionary<string, object>();
468 int i = 0;
469 foreach (EstateBan ban in EstateBans)
470 bans["ban" + i++] = ban.ToMap();
471 map["EstateBans"] = bans;
472 }
473
474 return map;
475 }
476
477 /// <summary>
478 /// For debugging
479 /// </summary>
480 /// <returns></returns>
481 public override string ToString()
482 {
483 Dictionary<string, object> map = ToMap();
484 String result = String.Empty;
485
486 foreach (KeyValuePair<string, object> kvp in map)
487 {
488 if (kvp.Key == "EstateBans")
489 {
490 result += "EstateBans:" + Environment.NewLine;
491 foreach (KeyValuePair<string, object> ban in (Dictionary<string, object>)kvp.Value)
492 result += ban.Value.ToString();
493 }
494 else
495 result += string.Format("{0}: {1} {2}", kvp.Key, kvp.Value.ToString(), Environment.NewLine);
496 }
497
498 return result;
499 }
500
501 public EstateSettings(Dictionary<string, object> map)
502 {
503 foreach (KeyValuePair<string, object> kvp in map)
504 {
505 PropertyInfo p = this.GetType().GetProperty(kvp.Key, BindingFlags.Public | BindingFlags.Instance);
506 if (p == null)
507 continue;
508
509 // EstateBans is a complex type, let's treat it as special
510 if (p.Name == "EstateBans")
511 continue;
512
513 if (p.PropertyType.IsArray)
514 {
515 string[] elements = ((string)map[p.Name]).Split(new char[] { ',' });
516 UUID[] uuids = new UUID[elements.Length];
517 int i = 0;
518 foreach (string e in elements)
519 uuids[i++] = new UUID(e);
520 p.SetValue(this, uuids, null);
521 }
522 else
523 {
524 object value = p.GetValue(this, null);
525 if (value is String)
526 p.SetValue(this, map[p.Name], null);
527 else if (value is UInt32)
528 p.SetValue(this, UInt32.Parse((string)map[p.Name]), null);
529 else if (value is Boolean)
530 p.SetValue(this, Boolean.Parse((string)map[p.Name]), null);
531 else if (value is UUID)
532 p.SetValue(this, UUID.Parse((string)map[p.Name]), null);
533 }
534 }
535
536 // EstateBans are special
537 if (map.ContainsKey("EstateBans"))
538 {
539 var banData = ((Dictionary<string, object>)map["EstateBans"]).Values;
540 EstateBan[] bans = new EstateBan[banData.Count];
541 int b = 0;
542 foreach (Dictionary<string, object> ban in banData)
543 bans[b++] = new EstateBan(ban);
544 PropertyInfo bansProperty = this.GetType().GetProperty("EstateBans", BindingFlags.Public | BindingFlags.Instance);
545 bansProperty.SetValue(this, bans, null);
546 }
547 }
433 } 548 }
434} 549}
diff --git a/OpenSim/Framework/ICommandConsole.cs b/OpenSim/Framework/ICommandConsole.cs
index a6573f8..3db2765 100644
--- a/OpenSim/Framework/ICommandConsole.cs
+++ b/OpenSim/Framework/ICommandConsole.cs
@@ -67,9 +67,16 @@ namespace OpenSim.Framework
67 string help, string longhelp, string descriptivehelp, 67 string help, string longhelp, string descriptivehelp,
68 CommandDelegate fn); 68 CommandDelegate fn);
69 69
70 string[] FindNextOption(string[] cmd, bool term); 70 /// <summary>
71 /// Has the given command already been registered?
72 /// </summary>
73 /// <returns></returns>
74 /// <param name="command">Command.</param>
75 bool HasCommand(string command);
76
77 string[] FindNextOption(string[] command, bool term);
71 78
72 string[] Resolve(string[] cmd); 79 string[] Resolve(string[] command);
73 80
74 XmlElement GetXml(XmlDocument doc); 81 XmlElement GetXml(XmlDocument doc);
75 } 82 }
diff --git a/OpenSim/Framework/ILandObject.cs b/OpenSim/Framework/ILandObject.cs
index 8d15119..db1496c 100644
--- a/OpenSim/Framework/ILandObject.cs
+++ b/OpenSim/Framework/ILandObject.cs
@@ -38,6 +38,7 @@ namespace OpenSim.Framework
38 int GetParcelMaxPrimCount(); 38 int GetParcelMaxPrimCount();
39 int GetSimulatorMaxPrimCount(); 39 int GetSimulatorMaxPrimCount();
40 int GetPrimsFree(); 40 int GetPrimsFree();
41 Dictionary<UUID, int> GetLandObjectOwners();
41 42
42 LandData LandData { get; set; } 43 LandData LandData { get; set; }
43 bool[,] LandBitmap { get; set; } 44 bool[,] LandBitmap { get; set; }
diff --git a/OpenSim/Framework/IPeople.cs b/OpenSim/Framework/IPeople.cs
index b88e103..8d274d0 100644
--- a/OpenSim/Framework/IPeople.cs
+++ b/OpenSim/Framework/IPeople.cs
@@ -38,6 +38,8 @@ namespace OpenSim.Framework
38 public string LastName { get; set; } 38 public string LastName { get; set; }
39 public string HomeURL { get; set; } 39 public string HomeURL { get; set; }
40 public Dictionary<string, object> ServerURLs { get; set; } 40 public Dictionary<string, object> ServerURLs { get; set; }
41 public bool IsUnknownUser { get; set; }
42 public bool HasGridUserTried { get; set; }
41 } 43 }
42 44
43 public interface IPeople 45 public interface IPeople
diff --git a/OpenSim/Framework/ISceneAgent.cs b/OpenSim/Framework/ISceneAgent.cs
index 563d906..ca1399c 100644
--- a/OpenSim/Framework/ISceneAgent.cs
+++ b/OpenSim/Framework/ISceneAgent.cs
@@ -66,12 +66,17 @@ namespace OpenSim.Framework
66 AvatarAppearance Appearance { get; set; } 66 AvatarAppearance Appearance { get; set; }
67 67
68 /// <summary> 68 /// <summary>
69 /// Set if initial data about the scene (avatars, objects) has been sent to the client.
70 /// </summary>
71 bool SentInitialDataToClient { get; }
72
73 /// <summary>
69 /// Send initial scene data to the client controlling this agent 74 /// Send initial scene data to the client controlling this agent
70 /// </summary> 75 /// </summary>
71 /// <remarks> 76 /// <remarks>
72 /// This includes scene object data and the appearance data of other avatars. 77 /// This includes scene object data and the appearance data of other avatars.
73 /// </remarks> 78 /// </remarks>
74 void SendInitialDataToMe(); 79 void SendInitialDataToClient();
75 80
76 /// <summary> 81 /// <summary>
77 /// Direction in which the scene presence is looking. 82 /// Direction in which the scene presence is looking.
diff --git a/OpenSim/Framework/ISceneObject.cs b/OpenSim/Framework/ISceneObject.cs
index afac9b8..754b77b 100644
--- a/OpenSim/Framework/ISceneObject.cs
+++ b/OpenSim/Framework/ISceneObject.cs
@@ -32,6 +32,8 @@ namespace OpenSim.Framework
32{ 32{
33 public interface ISceneObject 33 public interface ISceneObject
34 { 34 {
35 string Name { get; }
36
35 UUID UUID { get; } 37 UUID UUID { get; }
36 38
37 /// <summary> 39 /// <summary>
diff --git a/OpenSim/Framework/InventoryCollection.cs b/OpenSim/Framework/InventoryCollection.cs
index 7049902..59655eb 100644
--- a/OpenSim/Framework/InventoryCollection.cs
+++ b/OpenSim/Framework/InventoryCollection.cs
@@ -37,6 +37,8 @@ namespace OpenSim.Framework
37 { 37 {
38 public List<InventoryFolderBase> Folders; 38 public List<InventoryFolderBase> Folders;
39 public List<InventoryItemBase> Items; 39 public List<InventoryItemBase> Items;
40 public UUID UserID; 40 public UUID OwnerID;
41 public UUID FolderID;
42 public int Version;
41 } 43 }
42} 44}
diff --git a/OpenSim/Framework/InventoryFolderBase.cs b/OpenSim/Framework/InventoryFolderBase.cs
index b3457a6..fb66056 100644
--- a/OpenSim/Framework/InventoryFolderBase.cs
+++ b/OpenSim/Framework/InventoryFolderBase.cs
@@ -34,6 +34,9 @@ namespace OpenSim.Framework
34 /// </summary> 34 /// </summary>
35 public class InventoryFolderBase : InventoryNodeBase 35 public class InventoryFolderBase : InventoryNodeBase
36 { 36 {
37 public static readonly string ROOT_FOLDER_NAME = "My Inventory";
38 public static readonly string SUITCASE_FOLDER_NAME = "My Suitcase";
39
37 /// <summary> 40 /// <summary>
38 /// The folder this folder is contained in 41 /// The folder this folder is contained in
39 /// </summary> 42 /// </summary>
diff --git a/OpenSim/Framework/InventoryItemBase.cs b/OpenSim/Framework/InventoryItemBase.cs
index 558dfd0..f9fd752 100644
--- a/OpenSim/Framework/InventoryItemBase.cs
+++ b/OpenSim/Framework/InventoryItemBase.cs
@@ -34,7 +34,7 @@ namespace OpenSim.Framework
34 /// Inventory Item - contains all the properties associated with an individual inventory piece. 34 /// Inventory Item - contains all the properties associated with an individual inventory piece.
35 /// </summary> 35 /// </summary>
36 public class InventoryItemBase : InventoryNodeBase, ICloneable 36 public class InventoryItemBase : InventoryNodeBase, ICloneable
37 { 37 {
38 /// <value> 38 /// <value>
39 /// The inventory type of the item. This is slightly different from the asset type in some situations. 39 /// The inventory type of the item. This is slightly different from the asset type in some situations.
40 /// </value> 40 /// </value>
@@ -82,12 +82,15 @@ namespace OpenSim.Framework
82 set 82 set
83 { 83 {
84 m_creatorId = value; 84 m_creatorId = value;
85
86 if ((m_creatorId == null) || !UUID.TryParse(m_creatorId, out m_creatorIdAsUuid))
87 m_creatorIdAsUuid = UUID.Zero;
85 } 88 }
86 } 89 }
87 protected string m_creatorId; 90 protected string m_creatorId;
88 91
89 /// <value> 92 /// <value>
90 /// The CreatorId expressed as a UUID.tely 93 /// The CreatorId expressed as a UUID.
91 /// </value> 94 /// </value>
92 public UUID CreatorIdAsUuid 95 public UUID CreatorIdAsUuid
93 { 96 {
diff --git a/OpenSim/Framework/MapItemReplyStruct.cs b/OpenSim/Framework/MapItemReplyStruct.cs
index 58011bd..c8693ae 100644
--- a/OpenSim/Framework/MapItemReplyStruct.cs
+++ b/OpenSim/Framework/MapItemReplyStruct.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using OpenMetaverse; 28using OpenMetaverse;
29using OpenMetaverse.StructuredData;
29 30
30namespace OpenSim.Framework 31namespace OpenSim.Framework
31{ 32{
@@ -37,5 +38,37 @@ namespace OpenSim.Framework
37 public int Extra; 38 public int Extra;
38 public int Extra2; 39 public int Extra2;
39 public string name; 40 public string name;
41
42 public mapItemReply(uint pX, uint pY, UUID pId, string pName, int pExt1, int pExt2)
43 {
44 x = pX;
45 y = pY;
46 id = pId;
47 name = pName;
48 Extra = pExt1;
49 Extra2 = pExt2;
50 }
51
52 public OSDMap ToOSD()
53 {
54 OSDMap map = new OSDMap();
55 map["X"] = OSD.FromInteger((int)x);
56 map["Y"] = OSD.FromInteger((int)y);
57 map["ID"] = OSD.FromUUID(id);
58 map["Name"] = OSD.FromString(name);
59 map["Extra"] = OSD.FromInteger(Extra);
60 map["Extra2"] = OSD.FromInteger(Extra2);
61 return map;
62 }
63
64 public void FromOSD(OSDMap map)
65 {
66 x = (uint) map["X"].AsInteger();
67 y = (uint) map["Y"].AsInteger();
68 id = map["ID"].AsUUID();
69 Extra = map["Extra"].AsInteger();
70 Extra2 = map["Extra2"].AsInteger();
71 name = map["Name"].AsString();
72 }
40 } 73 }
41} 74}
diff --git a/OpenSim/Framework/MetricsCollector.cs b/OpenSim/Framework/MetricsCollector.cs
new file mode 100644
index 0000000..c8f4a33
--- /dev/null
+++ b/OpenSim/Framework/MetricsCollector.cs
@@ -0,0 +1,223 @@
1using System;
2using System.Diagnostics;
3
4namespace OpenSim.Framework
5{
6 /// <summary>
7 /// A MetricsCollector for 'long' values.
8 /// </summary>
9 public class MetricsCollectorLong : MetricsCollector<long>
10 {
11 public MetricsCollectorLong(int windowSize, int numBuckets)
12 : base(windowSize, numBuckets)
13 {
14 }
15
16 protected override long GetZero() { return 0; }
17
18 protected override long Add(long a, long b) { return a + b; }
19 }
20
21
22 /// <summary>
23 /// A MetricsCollector for time spans.
24 /// </summary>
25 public class MetricsCollectorTime : MetricsCollectorLong
26 {
27 public MetricsCollectorTime(int windowSize, int numBuckets)
28 : base(windowSize, numBuckets)
29 {
30 }
31
32 public void AddSample(Stopwatch timer)
33 {
34 long ticks = timer.ElapsedTicks;
35 if (ticks > 0)
36 AddSample(ticks);
37 }
38
39 public TimeSpan GetSumTime()
40 {
41 return TimeSpan.FromMilliseconds((GetSum() * 1000) / Stopwatch.Frequency);
42 }
43 }
44
45
46 struct MetricsBucket<T>
47 {
48 public T value;
49 public int count;
50 }
51
52
53 /// <summary>
54 /// Collects metrics in a sliding window.
55 /// </summary>
56 /// <remarks>
57 /// MetricsCollector provides the current Sum of the metrics that it collects. It can easily be extended
58 /// to provide the Average, too. It uses a sliding window to keep these values current.
59 ///
60 /// This class is not thread-safe.
61 ///
62 /// Subclass MetricsCollector to have it use a concrete value type. Override the abstract methods.
63 /// </remarks>
64 public abstract class MetricsCollector<T>
65 {
66 private int bucketSize; // e.g. 3,000 ms
67
68 private MetricsBucket<T>[] buckets;
69
70 private int NumBuckets { get { return buckets.Length; } }
71
72
73 // The number of the current bucket, if we had an infinite number of buckets and didn't have to wrap around
74 long curBucketGlobal;
75
76 // The total of all the buckets
77 T totalSum;
78 int totalCount;
79
80
81 /// <summary>
82 /// Returns the default (zero) value.
83 /// </summary>
84 /// <returns></returns>
85 protected abstract T GetZero();
86
87 /// <summary>
88 /// Adds two values.
89 /// </summary>
90 protected abstract T Add(T a, T b);
91
92
93 /// <summary>
94 /// Creates a MetricsCollector.
95 /// </summary>
96 /// <param name="windowSize">The period of time over which to collect the metrics, in ms. E.g.: 30,000.</param>
97 /// <param name="numBuckets">The number of buckets to divide the samples into. E.g.: 10. Using more buckets
98 /// smooths the jarring that occurs whenever we drop an old bucket, but uses more memory.</param>
99 public MetricsCollector(int windowSize, int numBuckets)
100 {
101 bucketSize = windowSize / numBuckets;
102 buckets = new MetricsBucket<T>[numBuckets];
103 Reset();
104 }
105
106 public void Reset()
107 {
108 ZeroBuckets(0, NumBuckets);
109 curBucketGlobal = GetNow() / bucketSize;
110 totalSum = GetZero();
111 totalCount = 0;
112 }
113
114 public void AddSample(T sample)
115 {
116 MoveWindow();
117
118 int curBucket = (int)(curBucketGlobal % NumBuckets);
119 buckets[curBucket].value = Add(buckets[curBucket].value, sample);
120 buckets[curBucket].count++;
121
122 totalSum = Add(totalSum, sample);
123 totalCount++;
124 }
125
126 /// <summary>
127 /// Returns the total values in the collection window.
128 /// </summary>
129 public T GetSum()
130 {
131 // It might have been a while since we last added a sample, so we may need to adjust the window
132 MoveWindow();
133
134 return totalSum;
135 }
136
137 /// <summary>
138 /// Returns the current time in ms.
139 /// </summary>
140 private long GetNow()
141 {
142 return DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
143 }
144
145 /// <summary>
146 /// Clears the values in buckets [offset, offset+num)
147 /// </summary>
148 private void ZeroBuckets(int offset, int num)
149 {
150 for (int i = 0; i < num; i++)
151 {
152 buckets[offset + i].value = GetZero();
153 buckets[offset + i].count = 0;
154 }
155 }
156
157 /// <summary>
158 /// Adjusts the buckets so that the "current bucket" corresponds to the current time.
159 /// This may require dropping old buckets.
160 /// </summary>
161 /// <remarks>
162 /// This method allows for the possibility that we don't get new samples for each bucket, so the
163 /// new bucket may be some distance away from the last used bucket.
164 /// </remarks>
165 private void MoveWindow()
166 {
167 long newBucketGlobal = GetNow() / bucketSize;
168 long bucketsDistance = newBucketGlobal - curBucketGlobal;
169
170 if (bucketsDistance == 0)
171 {
172 // We're still on the same bucket as before
173 return;
174 }
175
176 if (bucketsDistance >= NumBuckets)
177 {
178 // Discard everything
179 Reset();
180 return;
181 }
182
183 int curBucket = (int)(curBucketGlobal % NumBuckets);
184 int newBucket = (int)(newBucketGlobal % NumBuckets);
185
186
187 // Clear all the buckets in this range: (cur, new]
188 int numToClear = (int)bucketsDistance;
189
190 if (curBucket < NumBuckets - 1)
191 {
192 // Clear buckets at the end of the window
193 int num = Math.Min((int)bucketsDistance, NumBuckets - (curBucket + 1));
194 ZeroBuckets(curBucket + 1, num);
195 numToClear -= num;
196 }
197
198 if (numToClear > 0)
199 {
200 // Clear buckets at the beginning of the window
201 ZeroBuckets(0, numToClear);
202 }
203
204 // Move the "current bucket" pointer
205 curBucketGlobal = newBucketGlobal;
206
207 RecalcTotal();
208 }
209
210 private void RecalcTotal()
211 {
212 totalSum = GetZero();
213 totalCount = 0;
214
215 for (int i = 0; i < NumBuckets; i++)
216 {
217 totalSum = Add(totalSum, buckets[i].value);
218 totalCount += buckets[i].count;
219 }
220 }
221
222 }
223}
diff --git a/OpenSim/Framework/Monitoring/JobEngine.cs b/OpenSim/Framework/Monitoring/JobEngine.cs
new file mode 100644
index 0000000..6db9a67
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/JobEngine.cs
@@ -0,0 +1,341 @@
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
28using System;
29using System.Collections.Concurrent;
30using System.Reflection;
31using System.Threading;
32using log4net;
33using OpenSim.Framework;
34
35namespace OpenSim.Framework.Monitoring
36{
37 public class JobEngine
38 {
39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40
41 public int LogLevel { get; set; }
42
43 public string Name { get; private set; }
44
45 public string LoggingName { get; private set; }
46
47 /// <summary>
48 /// Is this engine running?
49 /// </summary>
50 public bool IsRunning { get; private set; }
51
52 /// <summary>
53 /// The current job that the engine is running.
54 /// </summary>
55 /// <remarks>
56 /// Will be null if no job is currently running.
57 /// </remarks>
58 public Job CurrentJob { get; private set; }
59
60 /// <summary>
61 /// Number of jobs waiting to be processed.
62 /// </summary>
63 public int JobsWaiting { get { return m_jobQueue.Count; } }
64
65 /// <summary>
66 /// The timeout in milliseconds to wait for at least one event to be written when the recorder is stopping.
67 /// </summary>
68 public int RequestProcessTimeoutOnStop { get; set; }
69
70 /// <summary>
71 /// Controls whether we need to warn in the log about exceeding the max queue size.
72 /// </summary>
73 /// <remarks>
74 /// This is flipped to false once queue max has been exceeded and back to true when it falls below max, in
75 /// order to avoid spamming the log with lots of warnings.
76 /// </remarks>
77 private bool m_warnOverMaxQueue = true;
78
79 private BlockingCollection<Job> m_jobQueue;
80
81 private CancellationTokenSource m_cancelSource;
82
83 /// <summary>
84 /// Used to signal that we are ready to complete stop.
85 /// </summary>
86 private ManualResetEvent m_finishedProcessingAfterStop = new ManualResetEvent(false);
87
88 public JobEngine(string name, string loggingName)
89 {
90 Name = name;
91 LoggingName = loggingName;
92
93 RequestProcessTimeoutOnStop = 5000;
94 }
95
96 public void Start()
97 {
98 lock (this)
99 {
100 if (IsRunning)
101 return;
102
103 IsRunning = true;
104
105 m_finishedProcessingAfterStop.Reset();
106
107 m_jobQueue = new BlockingCollection<Job>(new ConcurrentQueue<Job>(), 5000);
108 m_cancelSource = new CancellationTokenSource();
109
110 WorkManager.StartThread(
111 ProcessRequests,
112 Name,
113 ThreadPriority.Normal,
114 false,
115 true,
116 null,
117 int.MaxValue);
118 }
119 }
120
121 public void Stop()
122 {
123 lock (this)
124 {
125 try
126 {
127 if (!IsRunning)
128 return;
129
130 IsRunning = false;
131
132 int requestsLeft = m_jobQueue.Count;
133
134 if (requestsLeft <= 0)
135 {
136 m_cancelSource.Cancel();
137 }
138 else
139 {
140 m_log.InfoFormat("[{0}]: Waiting to write {1} events after stop.", LoggingName, requestsLeft);
141
142 while (requestsLeft > 0)
143 {
144 if (!m_finishedProcessingAfterStop.WaitOne(RequestProcessTimeoutOnStop))
145 {
146 // After timeout no events have been written
147 if (requestsLeft == m_jobQueue.Count)
148 {
149 m_log.WarnFormat(
150 "[{0}]: No requests processed after {1} ms wait. Discarding remaining {2} requests",
151 LoggingName, RequestProcessTimeoutOnStop, requestsLeft);
152
153 break;
154 }
155 }
156
157 requestsLeft = m_jobQueue.Count;
158 }
159 }
160 }
161 finally
162 {
163 m_cancelSource.Dispose();
164 }
165 }
166 }
167
168 /// <summary>
169 /// Make a job.
170 /// </summary>
171 /// <remarks>
172 /// We provide this method to replace the constructor so that we can later pool job objects if necessary to
173 /// reduce memory churn. Normally one would directly call QueueJob() with parameters anyway.
174 /// </remarks>
175 /// <returns></returns>
176 /// <param name="name">Name.</param>
177 /// <param name="action">Action.</param>
178 /// <param name="commonId">Common identifier.</param>
179 public static Job MakeJob(string name, Action action, string commonId = null)
180 {
181 return Job.MakeJob(name, action, commonId);
182 }
183
184 /// <summary>
185 /// Remove the next job queued for processing.
186 /// </summary>
187 /// <remarks>
188 /// Returns null if there is no next job.
189 /// Will not remove a job currently being performed.
190 /// </remarks>
191 public Job RemoveNextJob()
192 {
193 Job nextJob;
194 m_jobQueue.TryTake(out nextJob);
195
196 return nextJob;
197 }
198
199 /// <summary>
200 /// Queue the job for processing.
201 /// </summary>
202 /// <returns><c>true</c>, if job was queued, <c>false</c> otherwise.</returns>
203 /// <param name="name">Name of job. This appears on the console and in logging.</param>
204 /// <param name="action">Action to perform.</param>
205 /// <param name="commonId">
206 /// Common identifier for a set of jobs. This is allows a set of jobs to be removed
207 /// if required (e.g. all jobs for a given agent. Optional.
208 /// </param>
209 public bool QueueJob(string name, Action action, string commonId = null)
210 {
211 return QueueJob(MakeJob(name, action, commonId));
212 }
213
214 /// <summary>
215 /// Queue the job for processing.
216 /// </summary>
217 /// <returns><c>true</c>, if job was queued, <c>false</c> otherwise.</returns>
218 /// <param name="job">The job</param>
219 /// </param>
220 public bool QueueJob(Job job)
221 {
222 if (m_jobQueue.Count < m_jobQueue.BoundedCapacity)
223 {
224 m_jobQueue.Add(job);
225
226 if (!m_warnOverMaxQueue)
227 m_warnOverMaxQueue = true;
228
229 return true;
230 }
231 else
232 {
233 if (m_warnOverMaxQueue)
234 {
235 m_log.WarnFormat(
236 "[{0}]: Job queue at maximum capacity, not recording job from {1} in {2}",
237 LoggingName, job.Name, Name);
238
239 m_warnOverMaxQueue = false;
240 }
241
242 return false;
243 }
244 }
245
246 private void ProcessRequests()
247 {
248 try
249 {
250 while (IsRunning || m_jobQueue.Count > 0)
251 {
252 try
253 {
254 CurrentJob = m_jobQueue.Take(m_cancelSource.Token);
255 }
256 catch (ObjectDisposedException e)
257 {
258 // If we see this whilst not running then it may be due to a race where this thread checks
259 // IsRunning after the stopping thread sets it to false and disposes of the cancellation source.
260 if (IsRunning)
261 throw e;
262 else
263 break;
264 }
265
266 if (LogLevel >= 1)
267 m_log.DebugFormat("[{0}]: Processing job {1}", LoggingName, CurrentJob.Name);
268
269 try
270 {
271 CurrentJob.Action();
272 }
273 catch (Exception e)
274 {
275 m_log.Error(
276 string.Format(
277 "[{0}]: Job {1} failed, continuing. Exception ", LoggingName, CurrentJob.Name), e);
278 }
279
280 if (LogLevel >= 1)
281 m_log.DebugFormat("[{0}]: Processed job {1}", LoggingName, CurrentJob.Name);
282
283 CurrentJob = null;
284 }
285 }
286 catch (OperationCanceledException)
287 {
288 }
289
290 m_finishedProcessingAfterStop.Set();
291 }
292
293 public class Job
294 {
295 /// <summary>
296 /// Name of the job.
297 /// </summary>
298 /// <remarks>
299 /// This appears on console and debug output.
300 /// </remarks>
301 public string Name { get; private set; }
302
303 /// <summary>
304 /// Common ID for this job.
305 /// </summary>
306 /// <remarks>
307 /// This allows all jobs with a certain common ID (e.g. a client UUID) to be removed en-masse if required.
308 /// Can be null if this is not required.
309 /// </remarks>
310 public string CommonId { get; private set; }
311
312 /// <summary>
313 /// Action to perform when this job is processed.
314 /// </summary>
315 public Action Action { get; private set; }
316
317 private Job(string name, string commonId, Action action)
318 {
319 Name = name;
320 CommonId = commonId;
321 Action = action;
322 }
323
324 /// <summary>
325 /// Make a job. It needs to be separately queued.
326 /// </summary>
327 /// <remarks>
328 /// We provide this method to replace the constructor so that we can pool job objects if necessary to
329 /// to reduce memory churn. Normally one would directly call JobEngine.QueueJob() with parameters anyway.
330 /// </remarks>
331 /// <returns></returns>
332 /// <param name="name">Name.</param>
333 /// <param name="action">Action.</param>
334 /// <param name="commonId">Common identifier.</param>
335 public static Job MakeJob(string name, Action action, string commonId = null)
336 {
337 return new Job(name, commonId, action);
338 }
339 }
340 }
341} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
index 07971bf..b08e4f7 100644
--- a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.0.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
index e6c73d3..be4a8b4 100644
--- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
@@ -82,6 +82,9 @@ namespace OpenSim.Framework.Monitoring
82 // IRegionModuleBase.Initialize 82 // IRegionModuleBase.Initialize
83 public void Initialise(IConfigSource source) 83 public void Initialise(IConfigSource source)
84 { 84 {
85 if (source == null)
86 return;
87
85 IConfig cfg = source.Configs["Monitoring"]; 88 IConfig cfg = source.Configs["Monitoring"];
86 89
87 if (cfg != null) 90 if (cfg != null)
@@ -141,19 +144,19 @@ namespace OpenSim.Framework.Monitoring
141 processorPercentPerfCounter = new PerfCounterControl(tempPC); 144 processorPercentPerfCounter = new PerfCounterControl(tempPC);
142 // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy. 145 // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
143 tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor, 146 tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
144 StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); }, 147 StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter); },
145 StatVerbosity.Info); 148 StatVerbosity.Info);
146 StatsManager.RegisterStat(tempStat); 149 StatsManager.RegisterStat(tempStat);
147 RegisteredStats.Add(tempName, tempStat); 150 RegisteredStats.Add(tempName, tempStat);
148 151
149 MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor, 152 MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,
150 (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; }); 153 (s) => { s.Value = Math.Round(Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds, 3); });
151 154
152 MakeStat("UserProcessorTime", null, "sec", ContainerProcessor, 155 MakeStat("UserProcessorTime", null, "sec", ContainerProcessor,
153 (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; }); 156 (s) => { s.Value = Math.Round(Process.GetCurrentProcess().UserProcessorTime.TotalSeconds, 3); });
154 157
155 MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor, 158 MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor,
156 (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; }); 159 (s) => { s.Value = Math.Round(Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds, 3); });
157 160
158 MakeStat("Threads", null, "threads", ContainerProcessor, 161 MakeStat("Threads", null, "threads", ContainerProcessor,
159 (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; }); 162 (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
@@ -296,28 +299,22 @@ namespace OpenSim.Framework.Monitoring
296 // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c 299 // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
297 // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters 300 // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
298 private delegate double PerfCounterNextValue(); 301 private delegate double PerfCounterNextValue();
302
299 private void GetNextValue(Stat stat, PerfCounterControl perfControl) 303 private void GetNextValue(Stat stat, PerfCounterControl perfControl)
300 { 304 {
301 GetNextValue(stat, perfControl, 1.0);
302 }
303 private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
304 {
305 if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval) 305 if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
306 { 306 {
307 if (perfControl != null && perfControl.perfCounter != null) 307 if (perfControl != null && perfControl.perfCounter != null)
308 { 308 {
309 try 309 try
310 { 310 {
311 // Kludge for factor to run double duty. If -1, subtract the value from one 311 stat.Value = Math.Round(perfControl.perfCounter.NextValue(), 3);
312 if (factor == -1)
313 stat.Value = 1 - perfControl.perfCounter.NextValue();
314 else
315 stat.Value = perfControl.perfCounter.NextValue() / factor;
316 } 312 }
317 catch (Exception e) 313 catch (Exception e)
318 { 314 {
319 m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e); 315 m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
320 } 316 }
317
321 perfControl.lastFetch = Util.EnvironmentTickCount(); 318 perfControl.lastFetch = Util.EnvironmentTickCount();
322 } 319 }
323 } 320 }
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
index f6f458d..e4df7ee 100644..100755
--- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics;
30using System.Linq; 31using System.Linq;
31using System.Text; 32using System.Text;
32using OpenMetaverse; 33using OpenMetaverse;
@@ -71,6 +72,11 @@ namespace OpenSim.Framework.Monitoring
71 private volatile float pendingUploads; 72 private volatile float pendingUploads;
72 private volatile float activeScripts; 73 private volatile float activeScripts;
73 private volatile float scriptLinesPerSecond; 74 private volatile float scriptLinesPerSecond;
75 private volatile float m_frameDilation;
76 private volatile float m_usersLoggingIn;
77 private volatile float m_totalGeoPrims;
78 private volatile float m_totalMeshes;
79 private volatile float m_inUseThreads;
74 80
75// /// <summary> 81// /// <summary>
76// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the 82// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the
@@ -249,6 +255,10 @@ namespace OpenSim.Framework.Monitoring
249 { 255 {
250 // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original 256 // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original
251 // SimStatsPacket that was being used). 257 // SimStatsPacket that was being used).
258
259 // For an unknown reason the original designers decided not to
260 // include the spare MS statistic inside of this class, this is
261 // located inside the StatsBlock at location 21, thus it is skipped
252 timeDilation = stats.StatsBlock[0].StatValue; 262 timeDilation = stats.StatsBlock[0].StatValue;
253 simFps = stats.StatsBlock[1].StatValue; 263 simFps = stats.StatsBlock[1].StatValue;
254 physicsFps = stats.StatsBlock[2].StatValue; 264 physicsFps = stats.StatsBlock[2].StatValue;
@@ -270,6 +280,11 @@ namespace OpenSim.Framework.Monitoring
270 pendingUploads = stats.StatsBlock[18].StatValue; 280 pendingUploads = stats.StatsBlock[18].StatValue;
271 activeScripts = stats.StatsBlock[19].StatValue; 281 activeScripts = stats.StatsBlock[19].StatValue;
272 scriptLinesPerSecond = stats.StatsBlock[20].StatValue; 282 scriptLinesPerSecond = stats.StatsBlock[20].StatValue;
283 m_frameDilation = stats.StatsBlock[22].StatValue;
284 m_usersLoggingIn = stats.StatsBlock[23].StatValue;
285 m_totalGeoPrims = stats.StatsBlock[24].StatValue;
286 m_totalMeshes = stats.StatsBlock[25].StatValue;
287 m_inUseThreads = stats.StatsBlock[26].StatValue;
273 } 288 }
274 289
275 /// <summary> 290 /// <summary>
@@ -407,6 +422,27 @@ Asset service request failures: {3}" + Environment.NewLine,
407 /// <returns></returns> 422 /// <returns></returns>
408 public override OSDMap OReport(string uptime, string version) 423 public override OSDMap OReport(string uptime, string version)
409 { 424 {
425 // Get the amount of physical memory, allocated with the instance of this program, in kilobytes;
426 // the working set is the set of memory pages currently visible to this program in physical RAM
427 // memory and includes both shared (e.g. system libraries) and private data
428 double memUsage = Process.GetCurrentProcess().WorkingSet64 / 1024.0;
429
430 // Get the number of threads from the system that are currently
431 // running
432 int numberThreadsRunning = 0;
433 foreach (ProcessThread currentThread in
434 Process.GetCurrentProcess().Threads)
435 {
436 // A known issue with the current process .Threads property is
437 // that it can return null threads, thus don't count those as
438 // running threads and prevent the program function from failing
439 if (currentThread != null &&
440 currentThread.ThreadState == ThreadState.Running)
441 {
442 numberThreadsRunning++;
443 }
444 }
445
410 OSDMap args = new OSDMap(30); 446 OSDMap args = new OSDMap(30);
411// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache)); 447// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache));
412// args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}", 448// args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}",
@@ -443,6 +479,22 @@ Asset service request failures: {3}" + Environment.NewLine,
443 args["Memory"] = OSD.FromString (base.XReport (uptime, version)); 479 args["Memory"] = OSD.FromString (base.XReport (uptime, version));
444 args["Uptime"] = OSD.FromString (uptime); 480 args["Uptime"] = OSD.FromString (uptime);
445 args["Version"] = OSD.FromString (version); 481 args["Version"] = OSD.FromString (version);
482
483 args["FrameDilatn"] = OSD.FromString(String.Format("{0:0.##}", m_frameDilation));
484 args["Logging in Users"] = OSD.FromString(String.Format("{0:0.##}",
485 m_usersLoggingIn));
486 args["GeoPrims"] = OSD.FromString(String.Format("{0:0.##}",
487 m_totalGeoPrims));
488 args["Mesh Objects"] = OSD.FromString(String.Format("{0:0.##}",
489 m_totalMeshes));
490 args["XEngine Thread Count"] = OSD.FromString(String.Format("{0:0.##}",
491 m_inUseThreads));
492 args["Util Thread Count"] = OSD.FromString(String.Format("{0:0.##}",
493 Util.GetSmartThreadPoolInfo().InUseThreads));
494 args["System Thread Count"] = OSD.FromString(String.Format(
495 "{0:0.##}", numberThreadsRunning));
496 args["ProcMem"] = OSD.FromString(String.Format("{0:#,###,###.##}",
497 memUsage));
446 498
447 return args; 499 return args;
448 } 500 }
diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs
index bd757d0..916fa53 100644
--- a/OpenSim/Framework/Monitoring/Stats/Stat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs
@@ -171,7 +171,8 @@ namespace OpenSim.Framework.Monitoring
171 foreach (char c in DisallowedShortNameCharacters) 171 foreach (char c in DisallowedShortNameCharacters)
172 { 172 {
173 if (shortName.IndexOf(c) != -1) 173 if (shortName.IndexOf(c) != -1)
174 throw new Exception(string.Format("Stat name {0} cannot contain character {1}", shortName, c)); 174 shortName = shortName.Replace(c, '#');
175// throw new Exception(string.Format("Stat name {0} cannot contain character {1}", shortName, c));
175 } 176 }
176 177
177 ShortName = shortName; 178 ShortName = shortName;
diff --git a/OpenSim/Framework/Monitoring/StatsLogger.cs b/OpenSim/Framework/Monitoring/StatsLogger.cs
index 1e4fa11..15a37aa 100644
--- a/OpenSim/Framework/Monitoring/StatsLogger.cs
+++ b/OpenSim/Framework/Monitoring/StatsLogger.cs
@@ -26,7 +26,10 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
30using System.IO;
29using System.Reflection; 31using System.Reflection;
32using System.Text;
30using System.Timers; 33using System.Timers;
31using log4net; 34using log4net;
32 35
@@ -45,37 +48,67 @@ namespace OpenSim.Framework.Monitoring
45 public static void RegisterConsoleCommands(ICommandConsole console) 48 public static void RegisterConsoleCommands(ICommandConsole console)
46 { 49 {
47 console.Commands.AddCommand( 50 console.Commands.AddCommand(
48 "Debug", 51 "General",
49 false, 52 false,
50 "debug stats record", 53 "stats record",
51 "debug stats record start|stop", 54 "stats record start|stop",
52 "Control whether stats are being regularly recorded to a separate file.", 55 "Control whether stats are being regularly recorded to a separate file.",
53 "For debug purposes. Experimental.", 56 "For debug purposes. Experimental.",
54 HandleStatsRecordCommand); 57 HandleStatsRecordCommand);
58
59 console.Commands.AddCommand(
60 "General",
61 false,
62 "stats save",
63 "stats save <path>",
64 "Save stats snapshot to a file. If the file already exists, then the report is appended.",
65 "For debug purposes. Experimental.",
66 HandleStatsSaveCommand);
55 } 67 }
56 68
57 public static void HandleStatsRecordCommand(string module, string[] cmd) 69 public static void HandleStatsRecordCommand(string module, string[] cmd)
58 { 70 {
59 ICommandConsole con = MainConsole.Instance; 71 ICommandConsole con = MainConsole.Instance;
60 72
61 if (cmd.Length != 4) 73 if (cmd.Length != 3)
62 { 74 {
63 con.Output("Usage: debug stats record start|stop"); 75 con.Output("Usage: stats record start|stop");
64 return; 76 return;
65 } 77 }
66 78
67 if (cmd[3] == "start") 79 if (cmd[2] == "start")
68 { 80 {
69 Start(); 81 Start();
70 con.OutputFormat("Now recording all stats to file every {0}ms", m_statsLogIntervalMs); 82 con.OutputFormat("Now recording all stats to file every {0}ms", m_statsLogIntervalMs);
71 } 83 }
72 else if (cmd[3] == "stop") 84 else if (cmd[2] == "stop")
73 { 85 {
74 Stop(); 86 Stop();
75 con.Output("Stopped recording stats to file."); 87 con.Output("Stopped recording stats to file.");
76 } 88 }
77 } 89 }
78 90
91 public static void HandleStatsSaveCommand(string module, string[] cmd)
92 {
93 ICommandConsole con = MainConsole.Instance;
94
95 if (cmd.Length != 3)
96 {
97 con.Output("Usage: stats save <path>");
98 return;
99 }
100
101 string path = cmd[2];
102
103 using (StreamWriter sw = new StreamWriter(path, true))
104 {
105 foreach (string line in GetReport())
106 sw.WriteLine(line);
107 }
108
109 MainConsole.Instance.OutputFormat("Stats saved to file {0}", path);
110 }
111
79 public static void Start() 112 public static void Start()
80 { 113 {
81 if (m_loggingTimer != null) 114 if (m_loggingTimer != null)
@@ -97,12 +130,22 @@ namespace OpenSim.Framework.Monitoring
97 130
98 private static void Log(object sender, ElapsedEventArgs e) 131 private static void Log(object sender, ElapsedEventArgs e)
99 { 132 {
100 m_statsLog.InfoFormat("*** STATS REPORT AT {0} ***", DateTime.Now); 133 foreach (string line in GetReport())
134 m_statsLog.Info(line);
135
136 m_loggingTimer.Start();
137 }
138
139 private static List<string> GetReport()
140 {
141 List<string> lines = new List<string>();
142
143 lines.Add(string.Format("*** STATS REPORT AT {0} ***", DateTime.Now));
101 144
102 foreach (string report in StatsManager.GetAllStatsReports()) 145 foreach (string report in StatsManager.GetAllStatsReports())
103 m_statsLog.Info(report); 146 lines.Add(report);
104 147
105 m_loggingTimer.Start(); 148 return lines;
106 } 149 }
107 } 150 }
108} \ No newline at end of file 151} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 249cef6..a167b55 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -72,8 +72,8 @@ namespace OpenSim.Framework.Monitoring
72 console.Commands.AddCommand( 72 console.Commands.AddCommand(
73 "General", 73 "General",
74 false, 74 false,
75 "show stats", 75 "stats show",
76 "show stats [list|all|(<category>[.<container>])+", 76 "stats show [list|all|(<category>[.<container>])+",
77 "Show statistical information for this server", 77 "Show statistical information for this server",
78 "If no final argument is specified then legacy statistics information is currently shown.\n" 78 "If no final argument is specified then legacy statistics information is currently shown.\n"
79 + "'list' argument will show statistic categories.\n" 79 + "'list' argument will show statistic categories.\n"
@@ -84,6 +84,14 @@ namespace OpenSim.Framework.Monitoring
84 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", 84 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
85 HandleShowStatsCommand); 85 HandleShowStatsCommand);
86 86
87 console.Commands.AddCommand(
88 "General",
89 false,
90 "show stats",
91 "show stats [list|all|(<category>[.<container>])+",
92 "Alias for 'stats show' command",
93 HandleShowStatsCommand);
94
87 StatsLogger.RegisterConsoleCommands(console); 95 StatsLogger.RegisterConsoleCommands(console);
88 } 96 }
89 97
@@ -99,6 +107,7 @@ namespace OpenSim.Framework.Monitoring
99 107
100 string categoryName = components[0]; 108 string categoryName = components[0];
101 string containerName = components.Length > 1 ? components[1] : null; 109 string containerName = components.Length > 1 ? components[1] : null;
110 string statName = components.Length > 2 ? components[2] : null;
102 111
103 if (categoryName == AllSubCommand) 112 if (categoryName == AllSubCommand)
104 { 113 {
@@ -128,7 +137,23 @@ namespace OpenSim.Framework.Monitoring
128 SortedDictionary<string, Stat> container; 137 SortedDictionary<string, Stat> container;
129 if (category.TryGetValue(containerName, out container)) 138 if (category.TryGetValue(containerName, out container))
130 { 139 {
131 OutputContainerStatsToConsole(con, container); 140 if (String.IsNullOrEmpty(statName))
141 {
142 OutputContainerStatsToConsole(con, container);
143 }
144 else
145 {
146 Stat stat;
147 if (container.TryGetValue(statName, out stat))
148 {
149 OutputStatToConsole(con, stat);
150 }
151 else
152 {
153 con.OutputFormat(
154 "No such stat {0} in {1}.{2}", statName, categoryName, containerName);
155 }
156 }
132 } 157 }
133 else 158 else
134 { 159 {
@@ -200,6 +225,11 @@ namespace OpenSim.Framework.Monitoring
200 con.Output(report); 225 con.Output(report);
201 } 226 }
202 227
228 private static void OutputStatToConsole(ICommandConsole con, Stat stat)
229 {
230 con.Output(stat.ToConsoleString());
231 }
232
203 // Creates an OSDMap of the format: 233 // Creates an OSDMap of the format:
204 // { categoryName: { 234 // { categoryName: {
205 // containerName: { 235 // containerName: {
@@ -288,7 +318,7 @@ namespace OpenSim.Framework.Monitoring
288 318
289 if (request.ContainsKey("cat")) pCategoryName = request["cat"].ToString(); 319 if (request.ContainsKey("cat")) pCategoryName = request["cat"].ToString();
290 if (request.ContainsKey("cont")) pContainerName = request["cat"].ToString(); 320 if (request.ContainsKey("cont")) pContainerName = request["cat"].ToString();
291 if (request.ContainsKey("stat")) pStatName = request["cat"].ToString(); 321 if (request.ContainsKey("stat")) pStatName = request["stat"].ToString();
292 322
293 string strOut = StatsManager.GetStatsAsOSDMap(pCategoryName, pContainerName, pStatName).ToString(); 323 string strOut = StatsManager.GetStatsAsOSDMap(pCategoryName, pContainerName, pStatName).ToString();
294 324
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index 32724ec..0cab427 100644
--- a/OpenSim/Framework/Monitoring/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -38,6 +38,8 @@ namespace OpenSim.Framework.Monitoring
38 /// </summary> 38 /// </summary>
39 public static class Watchdog 39 public static class Watchdog
40 { 40 {
41 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
42
41 /// <summary>Timer interval in milliseconds for the watchdog timer</summary> 43 /// <summary>Timer interval in milliseconds for the watchdog timer</summary>
42 public const double WATCHDOG_INTERVAL_MS = 2500.0d; 44 public const double WATCHDOG_INTERVAL_MS = 2500.0d;
43 45
@@ -82,12 +84,32 @@ namespace OpenSim.Framework.Monitoring
82 /// </summary> 84 /// </summary>
83 public Func<string> AlarmMethod { get; set; } 85 public Func<string> AlarmMethod { get; set; }
84 86
85 public ThreadWatchdogInfo(Thread thread, int timeout) 87 /// <summary>
88 /// Stat structure associated with this thread.
89 /// </summary>
90 public Stat Stat { get; set; }
91
92 public ThreadWatchdogInfo(Thread thread, int timeout, string name)
86 { 93 {
87 Thread = thread; 94 Thread = thread;
88 Timeout = timeout; 95 Timeout = timeout;
89 FirstTick = Environment.TickCount & Int32.MaxValue; 96 FirstTick = Environment.TickCount & Int32.MaxValue;
90 LastTick = FirstTick; 97 LastTick = FirstTick;
98
99 Stat
100 = new Stat(
101 name,
102 string.Format("Last update of thread {0}", name),
103 "",
104 "ms",
105 "server",
106 "thread",
107 StatType.Pull,
108 MeasuresOfInterest.None,
109 stat => stat.Value = Environment.TickCount & Int32.MaxValue - LastTick,
110 StatVerbosity.Debug);
111
112 StatsManager.RegisterStat(Stat);
91 } 113 }
92 114
93 public ThreadWatchdogInfo(ThreadWatchdogInfo previousTwi) 115 public ThreadWatchdogInfo(ThreadWatchdogInfo previousTwi)
@@ -100,6 +122,11 @@ namespace OpenSim.Framework.Monitoring
100 AlarmIfTimeout = previousTwi.AlarmIfTimeout; 122 AlarmIfTimeout = previousTwi.AlarmIfTimeout;
101 AlarmMethod = previousTwi.AlarmMethod; 123 AlarmMethod = previousTwi.AlarmMethod;
102 } 124 }
125
126 public void Cleanup()
127 {
128 StatsManager.DeregisterStat(Stat);
129 }
103 } 130 }
104 131
105 /// <summary> 132 /// <summary>
@@ -116,7 +143,7 @@ namespace OpenSim.Framework.Monitoring
116 get { return m_enabled; } 143 get { return m_enabled; }
117 set 144 set
118 { 145 {
119// m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value); 146 // m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value);
120 147
121 if (value == m_enabled) 148 if (value == m_enabled)
122 return; 149 return;
@@ -132,9 +159,8 @@ namespace OpenSim.Framework.Monitoring
132 m_watchdogTimer.Enabled = m_enabled; 159 m_watchdogTimer.Enabled = m_enabled;
133 } 160 }
134 } 161 }
135 private static bool m_enabled;
136 162
137 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 163 private static bool m_enabled;
138 private static Dictionary<int, ThreadWatchdogInfo> m_threads; 164 private static Dictionary<int, ThreadWatchdogInfo> m_threads;
139 private static System.Timers.Timer m_watchdogTimer; 165 private static System.Timers.Timer m_watchdogTimer;
140 166
@@ -155,57 +181,19 @@ namespace OpenSim.Framework.Monitoring
155 } 181 }
156 182
157 /// <summary> 183 /// <summary>
158 /// Start a new thread that is tracked by the watchdog timer. 184 /// Add a thread to the watchdog tracker.
159 /// </summary>
160 /// <param name="start">The method that will be executed in a new thread</param>
161 /// <param name="name">A name to give to the new thread</param>
162 /// <param name="priority">Priority to run the thread at</param>
163 /// <param name="isBackground">True to run this thread as a background thread, otherwise false</param>
164 /// <param name="alarmIfTimeout">Trigger an alarm function is we have timed out</param>
165 /// <returns>The newly created Thread object</returns>
166 public static Thread StartThread(
167 ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout)
168 {
169 return StartThread(start, name, priority, isBackground, alarmIfTimeout, null, DEFAULT_WATCHDOG_TIMEOUT_MS);
170 }
171
172 /// <summary>
173 /// Start a new thread that is tracked by the watchdog timer
174 /// </summary> 185 /// </summary>
175 /// <param name="start">The method that will be executed in a new thread</param> 186 /// <param name="info">Information about the thread.</info>
176 /// <param name="name">A name to give to the new thread</param> 187 /// <param name="info">Name of the thread.</info>
177 /// <param name="priority">Priority to run the thread at</param> 188 /// <param name="log">If true then creation of thread is logged.</param>
178 /// <param name="isBackground">True to run this thread as a background 189 public static void AddThread(ThreadWatchdogInfo info, string name, bool log = true)
179 /// thread, otherwise false</param>
180 /// <param name="alarmIfTimeout">Trigger an alarm function is we have timed out</param>
181 /// <param name="alarmMethod">
182 /// Alarm method to call if alarmIfTimeout is true and there is a timeout.
183 /// Normally, this will just return some useful debugging information.
184 /// </param>
185 /// <param name="timeout">Number of milliseconds to wait until we issue a warning about timeout.</param>
186 /// <returns>The newly created Thread object</returns>
187 public static Thread StartThread(
188 ThreadStart start, string name, ThreadPriority priority, bool isBackground,
189 bool alarmIfTimeout, Func<string> alarmMethod, int timeout)
190 { 190 {
191 Thread thread = new Thread(start); 191 if (log)
192 thread.Name = name; 192 m_log.DebugFormat(
193 thread.Priority = priority; 193 "[WATCHDOG]: Started tracking thread {0}, ID {1}", name, info.Thread.ManagedThreadId);
194 thread.IsBackground = isBackground;
195
196 ThreadWatchdogInfo twi
197 = new ThreadWatchdogInfo(thread, timeout)
198 { AlarmIfTimeout = alarmIfTimeout, AlarmMethod = alarmMethod };
199
200 m_log.DebugFormat(
201 "[WATCHDOG]: Started tracking thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
202 194
203 lock (m_threads) 195 lock (m_threads)
204 m_threads.Add(twi.Thread.ManagedThreadId, twi); 196 m_threads.Add(info.Thread.ManagedThreadId, info);
205
206 thread.Start();
207
208 return thread;
209 } 197 }
210 198
211 /// <summary> 199 /// <summary>
@@ -219,25 +207,28 @@ namespace OpenSim.Framework.Monitoring
219 /// <summary> 207 /// <summary>
220 /// Stops watchdog tracking on the current thread 208 /// Stops watchdog tracking on the current thread
221 /// </summary> 209 /// </summary>
210 /// <param name="log">If true then normal events in thread removal are not logged.</param>
222 /// <returns> 211 /// <returns>
223 /// True if the thread was removed from the list of tracked 212 /// True if the thread was removed from the list of tracked
224 /// threads, otherwise false 213 /// threads, otherwise false
225 /// </returns> 214 /// </returns>
226 public static bool RemoveThread() 215 public static bool RemoveThread(bool log = true)
227 { 216 {
228 return RemoveThread(Thread.CurrentThread.ManagedThreadId); 217 return RemoveThread(Thread.CurrentThread.ManagedThreadId, log);
229 } 218 }
230 219
231 private static bool RemoveThread(int threadID) 220 private static bool RemoveThread(int threadID, bool log = true)
232 { 221 {
233 lock (m_threads) 222 lock (m_threads)
234 { 223 {
235 ThreadWatchdogInfo twi; 224 ThreadWatchdogInfo twi;
236 if (m_threads.TryGetValue(threadID, out twi)) 225 if (m_threads.TryGetValue(threadID, out twi))
237 { 226 {
238 m_log.DebugFormat( 227 if (log)
239 "[WATCHDOG]: Removing thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId); 228 m_log.DebugFormat(
229 "[WATCHDOG]: Removing thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
240 230
231 twi.Cleanup();
241 m_threads.Remove(threadID); 232 m_threads.Remove(threadID);
242 233
243 return true; 234 return true;
@@ -293,7 +284,7 @@ namespace OpenSim.Framework.Monitoring
293 } 284 }
294 catch { } 285 catch { }
295 } 286 }
296 287
297 /// <summary> 288 /// <summary>
298 /// Get currently watched threads for diagnostic purposes 289 /// Get currently watched threads for diagnostic purposes
299 /// </summary> 290 /// </summary>
diff --git a/OpenSim/Framework/Monitoring/WorkManager.cs b/OpenSim/Framework/Monitoring/WorkManager.cs
new file mode 100644
index 0000000..d1a74ce
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/WorkManager.cs
@@ -0,0 +1,290 @@
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
28using System;
29using System.Reflection;
30using System.Threading;
31using log4net;
32
33namespace OpenSim.Framework.Monitoring
34{
35 /// <summary>
36 /// Manages various work items in the simulator.
37 /// </summary>
38 /// <remarks>
39 /// Currently, here work can be started
40 /// * As a long-running and monitored thread.
41 /// * In a thread that will never timeout but where the job is expected to eventually complete.
42 /// * In a threadpool thread that will timeout if it takes a very long time to complete (> 10 mins).
43 /// * As a job which will be run in a single-threaded job engine. Such jobs must not incorporate delays (sleeps,
44 /// network waits, etc.).
45 ///
46 /// This is an evolving approach to better manage the work that OpenSimulator is asked to do from a very diverse
47 /// range of sources (client actions, incoming network, outgoing network calls, etc.).
48 ///
49 /// Util.FireAndForget is still available to insert jobs in the threadpool, though this is equivalent to
50 /// WorkManager.RunInThreadPool().
51 /// </remarks>
52 public static class WorkManager
53 {
54 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
55
56 public static JobEngine JobEngine { get; private set; }
57
58 static WorkManager()
59 {
60 JobEngine = new JobEngine("Non-blocking non-critical job engine", "JOB ENGINE");
61
62 StatsManager.RegisterStat(
63 new Stat(
64 "JobsWaiting",
65 "Number of jobs waiting for processing.",
66 "",
67 "",
68 "server",
69 "jobengine",
70 StatType.Pull,
71 MeasuresOfInterest.None,
72 stat => stat.Value = JobEngine.JobsWaiting,
73 StatVerbosity.Debug));
74
75 MainConsole.Instance.Commands.AddCommand(
76 "Debug",
77 false,
78 "debug jobengine",
79 "debug jobengine <start|stop|status|log>",
80 "Start, stop, get status or set logging level of the job engine.",
81 "If stopped then all outstanding jobs are processed immediately.",
82 HandleControlCommand);
83 }
84
85 /// <summary>
86 /// Start a new long-lived thread.
87 /// </summary>
88 /// <param name="start">The method that will be executed in a new thread</param>
89 /// <param name="name">A name to give to the new thread</param>
90 /// <param name="priority">Priority to run the thread at</param>
91 /// <param name="isBackground">True to run this thread as a background thread, otherwise false</param>
92 /// <param name="alarmIfTimeout">Trigger an alarm function is we have timed out</param>
93 /// <param name="log">If true then creation of thread is logged.</param>
94 /// <returns>The newly created Thread object</returns>
95 public static Thread StartThread(
96 ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout, bool log = true)
97 {
98 return StartThread(start, name, priority, isBackground, alarmIfTimeout, null, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS, log);
99 }
100
101 /// <summary>
102 /// Start a new thread that is tracked by the watchdog
103 /// </summary>
104 /// <param name="start">The method that will be executed in a new thread</param>
105 /// <param name="name">A name to give to the new thread</param>
106 /// <param name="priority">Priority to run the thread at</param>
107 /// <param name="isBackground">True to run this thread as a background
108 /// thread, otherwise false</param>
109 /// <param name="alarmIfTimeout">Trigger an alarm function is we have timed out</param>
110 /// <param name="alarmMethod">
111 /// Alarm method to call if alarmIfTimeout is true and there is a timeout.
112 /// Normally, this will just return some useful debugging information.
113 /// </param>
114 /// <param name="timeout">Number of milliseconds to wait until we issue a warning about timeout.</param>
115 /// <param name="log">If true then creation of thread is logged.</param>
116 /// <returns>The newly created Thread object</returns>
117 public static Thread StartThread(
118 ThreadStart start, string name, ThreadPriority priority, bool isBackground,
119 bool alarmIfTimeout, Func<string> alarmMethod, int timeout, bool log = true)
120 {
121 Thread thread = new Thread(start);
122 thread.Priority = priority;
123 thread.IsBackground = isBackground;
124
125 Watchdog.ThreadWatchdogInfo twi
126 = new Watchdog.ThreadWatchdogInfo(thread, timeout, name)
127 { AlarmIfTimeout = alarmIfTimeout, AlarmMethod = alarmMethod };
128
129 Watchdog.AddThread(twi, name, log:log);
130
131 thread.Start();
132 thread.Name = name;
133
134 return thread;
135 }
136
137 /// <summary>
138 /// Run the callback in a new thread immediately. If the thread exits with an exception log it but do
139 /// not propogate it.
140 /// </summary>
141 /// <param name="callback">Code for the thread to execute.</param>
142 /// <param name="obj">Object to pass to the thread.</param>
143 /// <param name="name">Name of the thread</param>
144 public static void RunInThread(WaitCallback callback, object obj, string name, bool log = false)
145 {
146 if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
147 {
148 Culture.SetCurrentCulture();
149 callback(obj);
150 return;
151 }
152
153 ThreadStart ts = new ThreadStart(delegate()
154 {
155 try
156 {
157 Culture.SetCurrentCulture();
158 callback(obj);
159 Watchdog.RemoveThread(log:false);
160 }
161 catch (Exception e)
162 {
163 m_log.Error(string.Format("[WATCHDOG]: Exception in thread {0}.", name), e);
164 }
165 });
166
167 StartThread(ts, name, ThreadPriority.Normal, true, false, log:log);
168 }
169
170 /// <summary>
171 /// Run the callback via a threadpool thread.
172 /// </summary>
173 /// <remarks>
174 /// Such jobs may run after some delay but must always complete.
175 /// </remarks>
176 /// <param name="callback"></param>
177 /// <param name="obj"></param>
178 /// <param name="name">The name of the job. This is used in monitoring and debugging.</param>
179 public static void RunInThreadPool(System.Threading.WaitCallback callback, object obj, string name)
180 {
181 Util.FireAndForget(callback, obj, name);
182 }
183
184 /// <summary>
185 /// Run a job.
186 /// </summary>
187 /// <remarks>
188 /// This differs from direct scheduling (e.g. Util.FireAndForget) in that a job can be run in the job
189 /// engine if it is running, where all jobs are currently performed in sequence on a single thread. This is
190 /// to prevent observed overload and server freeze problems when there are hundreds of connections which all attempt to
191 /// perform work at once (e.g. in conference situations). With lower numbers of connections, the small
192 /// delay in performing jobs in sequence rather than concurrently has not been notiecable in testing, though a future more
193 /// sophisticated implementation could perform jobs concurrently when the server is under low load.
194 ///
195 /// However, be advised that some callers of this function rely on all jobs being performed in sequence if any
196 /// jobs are performed in sequence (i.e. if jobengine is active or not). Therefore, expanding the jobengine
197 /// beyond a single thread will require considerable thought.
198 ///
199 /// Also, any jobs submitted must be guaranteed to complete within a reasonable timeframe (e.g. they cannot
200 /// incorporate a network delay with a long timeout). At the moment, work that could suffer such issues
201 /// should still be run directly with RunInThread(), Util.FireAndForget(), etc. This is another area where
202 /// the job engine could be improved and so CPU utilization improved by better management of concurrency within
203 /// OpenSimulator.
204 /// </remarks>
205 /// <param name="jobType">General classification for the job (e.g. "RezAttachments").</param>
206 /// <param name="callback">Callback for job.</param>
207 /// <param name="obj">Object to pass to callback when run</param>
208 /// <param name="name">Specific name of job (e.g. "RezAttachments for Joe Bloggs"</param>
209 /// <param name="canRunInThisThread">If set to true then the job may be run in ths calling thread.</param>
210 /// <param name="mustNotTimeout">If the true then the job must never timeout.</param>
211 /// <param name="log">If set to true then extra logging is performed.</param>
212 public static void RunJob(
213 string jobType, WaitCallback callback, object obj, string name,
214 bool canRunInThisThread = false, bool mustNotTimeout = false,
215 bool log = false)
216 {
217 if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
218 {
219 Culture.SetCurrentCulture();
220 callback(obj);
221 return;
222 }
223
224 if (JobEngine.IsRunning)
225 JobEngine.QueueJob(name, () => callback(obj));
226 else if (canRunInThisThread)
227 callback(obj);
228 else if (mustNotTimeout)
229 RunInThread(callback, obj, name, log);
230 else
231 Util.FireAndForget(callback, obj, name);
232 }
233
234 private static void HandleControlCommand(string module, string[] args)
235 {
236 // if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
237 // return;
238
239 if (args.Length < 3)
240 {
241 MainConsole.Instance.Output("Usage: debug jobengine <stop|start|status|log>");
242 return;
243 }
244
245 string subCommand = args[2];
246
247 if (subCommand == "stop")
248 {
249 JobEngine.Stop();
250 MainConsole.Instance.OutputFormat("Stopped job engine.");
251 }
252 else if (subCommand == "start")
253 {
254 JobEngine.Start();
255 MainConsole.Instance.OutputFormat("Started job engine.");
256 }
257 else if (subCommand == "status")
258 {
259 MainConsole.Instance.OutputFormat("Job engine running: {0}", JobEngine.IsRunning);
260
261 JobEngine.Job job = JobEngine.CurrentJob;
262 MainConsole.Instance.OutputFormat("Current job {0}", job != null ? job.Name : "none");
263
264 MainConsole.Instance.OutputFormat(
265 "Jobs waiting: {0}", JobEngine.IsRunning ? JobEngine.JobsWaiting.ToString() : "n/a");
266 MainConsole.Instance.OutputFormat("Log Level: {0}", JobEngine.LogLevel);
267 }
268 else if (subCommand == "log")
269 {
270 if (args.Length < 4)
271 {
272 MainConsole.Instance.Output("Usage: debug jobengine log <level>");
273 return;
274 }
275
276 // int logLevel;
277 int logLevel = int.Parse(args[3]);
278 // if (ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out logLevel))
279 // {
280 JobEngine.LogLevel = logLevel;
281 MainConsole.Instance.OutputFormat("Set debug log level to {0}", JobEngine.LogLevel);
282 // }
283 }
284 else
285 {
286 MainConsole.Instance.OutputFormat("Unrecognized job engine subcommand {0}", subCommand);
287 }
288 }
289 }
290} \ No newline at end of file
diff --git a/OpenSim/Framework/PluginLoader.cs b/OpenSim/Framework/PluginLoader.cs
index cc80943..5fa27d6 100644
--- a/OpenSim/Framework/PluginLoader.cs
+++ b/OpenSim/Framework/PluginLoader.cs
@@ -215,12 +215,12 @@ namespace OpenSim.Framework
215 AddinManager.AddinLoadError += on_addinloaderror_; 215 AddinManager.AddinLoadError += on_addinloaderror_;
216 AddinManager.AddinLoaded += on_addinloaded_; 216 AddinManager.AddinLoaded += on_addinloaded_;
217 217
218 clear_registry_(); 218 //clear_registry_(dir);
219 219
220 suppress_console_output_(true); 220 //suppress_console_output_(true);
221 AddinManager.Initialize(dir); 221 AddinManager.Initialize(dir);
222 AddinManager.Registry.Update(null); 222 AddinManager.Registry.Update(null);
223 suppress_console_output_(false); 223 //suppress_console_output_(false);
224 } 224 }
225 225
226 private void on_addinloaded_(object sender, AddinEventArgs args) 226 private void on_addinloaded_(object sender, AddinEventArgs args)
@@ -239,12 +239,21 @@ namespace OpenSim.Framework
239 + args.Exception.StackTrace); 239 + args.Exception.StackTrace);
240 } 240 }
241 241
242 private void clear_registry_() 242 private void clear_registry_(string dir)
243 { 243 {
244 // The Mono addin manager (in Mono.Addins.dll version 0.2.0.0) 244 // The Mono addin manager (in Mono.Addins.dll version 0.2.0.0)
245 // occasionally seems to corrupt its addin cache 245 // occasionally seems to corrupt its addin cache
246 // Hence, as a temporary solution we'll remove it before each startup 246 // Hence, as a temporary solution we'll remove it before each startup
247 247
248<<<<<<< HEAD
249 try
250 {
251 if (Directory.Exists(dir + "/addin-db-000"))
252 Directory.Delete(dir + "/addin-db-000", true);
253
254 if (Directory.Exists(dir + "/addin-db-001"))
255 Directory.Delete(dir + "/addin-db-001", true);
256=======
248 string customDir = Environment.GetEnvironmentVariable ("MONO_ADDINS_REGISTRY"); 257 string customDir = Environment.GetEnvironmentVariable ("MONO_ADDINS_REGISTRY");
249 string v0 = "addin-db-000"; 258 string v0 = "addin-db-000";
250 string v1 = "addin-db-001"; 259 string v1 = "addin-db-001";
@@ -260,6 +269,7 @@ namespace OpenSim.Framework
260 269
261 if (Directory.Exists(v1)) 270 if (Directory.Exists(v1))
262 Directory.Delete(v1, true); 271 Directory.Delete(v1, true);
272>>>>>>> avn/ubitvar
263 } 273 }
264 catch (IOException) 274 catch (IOException)
265 { 275 {
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index 019fffc..d75a6cf 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -102,9 +102,12 @@ namespace OpenSim.Framework
102 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 102 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
103 private static readonly string LogHeader = "[REGION INFO]"; 103 private static readonly string LogHeader = "[REGION INFO]";
104 104
105<<<<<<< HEAD
106=======
105 public bool commFailTF = false; 107 public bool commFailTF = false;
106 public ConfigurationMember configMember; 108 public ConfigurationMember configMember;
107 public string DataStore = String.Empty; 109 public string DataStore = String.Empty;
110>>>>>>> avn/ubitvar
108 public string RegionFile = String.Empty; 111 public string RegionFile = String.Empty;
109 public bool isSandbox = false; 112 public bool isSandbox = false;
110 public bool Persistent = true; 113 public bool Persistent = true;
@@ -129,8 +132,8 @@ namespace OpenSim.Framework
129 private int m_physPrimMax = 0; 132 private int m_physPrimMax = 0;
130 private bool m_clampPrimSize = false; 133 private bool m_clampPrimSize = false;
131 private int m_objectCapacity = 0; 134 private int m_objectCapacity = 0;
135 private int m_maxPrimsPerUser = -1;
132 private int m_linksetCapacity = 0; 136 private int m_linksetCapacity = 0;
133 private int m_agentCapacity = 0;
134 private string m_regionType = String.Empty; 137 private string m_regionType = String.Empty;
135 private RegionLightShareData m_windlight = new RegionLightShareData(); 138 private RegionLightShareData m_windlight = new RegionLightShareData();
136 protected uint m_httpPort; 139 protected uint m_httpPort;
@@ -226,7 +229,6 @@ namespace OpenSim.Framework
226 try 229 try
227 { 230 {
228 // This will throw if it's not legal Nini XML format 231 // This will throw if it's not legal Nini XML format
229 // and thereby toss it to the legacy loader
230 // 232 //
231 IConfigSource xmlsource = new XmlConfigSource(filename); 233 IConfigSource xmlsource = new XmlConfigSource(filename);
232 234
@@ -239,11 +241,6 @@ namespace OpenSim.Framework
239 catch (Exception) 241 catch (Exception)
240 { 242 {
241 } 243 }
242
243 configMember =
244 new ConfigurationMember(filename, description, loadConfigurationOptions, handleIncomingConfiguration, !skipConsoleConfig);
245 configMember.performConfigurationRetrieve();
246 RegionFile = filename;
247 } 244 }
248 245
249 // The web loader uses this 246 // The web loader uses this
@@ -350,16 +347,18 @@ namespace OpenSim.Framework
350 get { return m_objectCapacity; } 347 get { return m_objectCapacity; }
351 } 348 }
352 349
353 public int LinksetCapacity 350 public int MaxPrimsPerUser
354 { 351 {
355 get { return m_linksetCapacity; } 352 get { return m_maxPrimsPerUser; }
356 } 353 }
357 354
358 public int AgentCapacity 355 public int LinksetCapacity
359 { 356 {
360 get { return m_agentCapacity; } 357 get { return m_linksetCapacity; }
361 } 358 }
362 359
360 public int AgentCapacity { get; set; }
361
363 public byte AccessLevel 362 public byte AccessLevel
364 { 363 {
365 get { return (byte)Util.ConvertMaturityToAccessLevel((uint)RegionSettings.Maturity); } 364 get { return (byte)Util.ConvertMaturityToAccessLevel((uint)RegionSettings.Maturity); }
@@ -374,6 +373,8 @@ namespace OpenSim.Framework
374 { 373 {
375 get { return m_maptileStaticUUID; } 374 get { return m_maptileStaticUUID; }
376 } 375 }
376
377 public string MaptileStaticFile { get; private set; }
377 378
378 /// <summary> 379 /// <summary>
379 /// The port by which http communication occurs with the region (most noticeably, CAPS communication) 380 /// The port by which http communication occurs with the region (most noticeably, CAPS communication)
@@ -523,7 +524,7 @@ namespace OpenSim.Framework
523 m_internalEndPoint = tmpEPE; 524 m_internalEndPoint = tmpEPE;
524 } 525 }
525 526
526 public string GetOtherSetting(string key) 527 public string GetSetting(string key)
527 { 528 {
528 string val; 529 string val;
529 string keylower = key.ToLower(); 530 string keylower = key.ToLower();
@@ -533,7 +534,11 @@ namespace OpenSim.Framework
533 return null; 534 return null;
534 } 535 }
535 536
537<<<<<<< HEAD
538 private void SetExtraSetting(string key, string value)
539=======
536 public void SetExtraSetting(string key, string value) 540 public void SetExtraSetting(string key, string value)
541>>>>>>> avn/ubitvar
537 { 542 {
538 string keylower = key.ToLower(); 543 string keylower = key.ToLower();
539 m_extraSettings[keylower] = value; 544 m_extraSettings[keylower] = value;
@@ -732,6 +737,9 @@ namespace OpenSim.Framework
732 m_objectCapacity = config.GetInt("MaxPrims", 15000); 737 m_objectCapacity = config.GetInt("MaxPrims", 15000);
733 allKeys.Remove("MaxPrims"); 738 allKeys.Remove("MaxPrims");
734 739
740 m_maxPrimsPerUser = config.GetInt("MaxPrimsPerUser", -1);
741 allKeys.Remove("MaxPrimsPerUser");
742
735 m_linksetCapacity = config.GetInt("LinksetPrims", 0); 743 m_linksetCapacity = config.GetInt("LinksetPrims", 0);
736 allKeys.Remove("LinksetPrims"); 744 allKeys.Remove("LinksetPrims");
737 745
@@ -741,10 +749,13 @@ namespace OpenSim.Framework
741 { 749 {
742 config.Set("MaptileStaticUUID", m_maptileStaticUUID.ToString()); 750 config.Set("MaptileStaticUUID", m_maptileStaticUUID.ToString());
743 } 751 }
752
753 MaptileStaticFile = config.GetString("MaptileStaticFile", String.Empty);
754 allKeys.Remove("MaptileStaticFile");
744 755
745 #endregion 756 #endregion
746 757
747 m_agentCapacity = config.GetInt("MaxAgents", 100); 758 AgentCapacity = config.GetInt("MaxAgents", 100);
748 allKeys.Remove("MaxAgents"); 759 allKeys.Remove("MaxAgents");
749 760
750 // Multi-tenancy 761 // Multi-tenancy
@@ -823,15 +834,22 @@ namespace OpenSim.Framework
823 string location = String.Format("{0},{1}", RegionLocX, RegionLocY); 834 string location = String.Format("{0},{1}", RegionLocX, RegionLocY);
824 config.Set("Location", location); 835 config.Set("Location", location);
825 836
837<<<<<<< HEAD
838 if (RegionSizeX > 0)
839=======
826 if (DataStore != String.Empty) 840 if (DataStore != String.Empty)
827 config.Set("Datastore", DataStore); 841 config.Set("Datastore", DataStore);
828 842
829 if (RegionSizeX != Constants.RegionSize || RegionSizeY != Constants.RegionSize) 843 if (RegionSizeX != Constants.RegionSize || RegionSizeY != Constants.RegionSize)
830 { 844 {
845>>>>>>> avn/ubitvar
831 config.Set("SizeX", RegionSizeX); 846 config.Set("SizeX", RegionSizeX);
847
848 if (RegionSizeY > 0)
832 config.Set("SizeY", RegionSizeY); 849 config.Set("SizeY", RegionSizeY);
833 config.Set("SizeZ", RegionSizeZ); 850
834 } 851// if (RegionSizeZ > 0)
852// config.Set("SizeZ", RegionSizeZ);
835 853
836 config.Set("InternalAddress", m_internalEndPoint.Address.ToString()); 854 config.Set("InternalAddress", m_internalEndPoint.Address.ToString());
837 config.Set("InternalPort", m_internalEndPoint.Port); 855 config.Set("InternalPort", m_internalEndPoint.Port);
@@ -857,11 +875,14 @@ namespace OpenSim.Framework
857 if (m_objectCapacity > 0) 875 if (m_objectCapacity > 0)
858 config.Set("MaxPrims", m_objectCapacity); 876 config.Set("MaxPrims", m_objectCapacity);
859 877
878 if (m_maxPrimsPerUser > -1)
879 config.Set("MaxPrimsPerUser", m_maxPrimsPerUser);
880
860 if (m_linksetCapacity > 0) 881 if (m_linksetCapacity > 0)
861 config.Set("LinksetPrims", m_linksetCapacity); 882 config.Set("LinksetPrims", m_linksetCapacity);
862 883
863 if (m_agentCapacity > 0) 884 if (AgentCapacity > 0)
864 config.Set("MaxAgents", m_agentCapacity); 885 config.Set("MaxAgents", AgentCapacity);
865 886
866 if (ScopeID != UUID.Zero) 887 if (ScopeID != UUID.Zero)
867 config.Set("ScopeID", ScopeID.ToString()); 888 config.Set("ScopeID", ScopeID.ToString());
@@ -871,11 +892,9 @@ namespace OpenSim.Framework
871 892
872 if (m_maptileStaticUUID != UUID.Zero) 893 if (m_maptileStaticUUID != UUID.Zero)
873 config.Set("MaptileStaticUUID", m_maptileStaticUUID.ToString()); 894 config.Set("MaptileStaticUUID", m_maptileStaticUUID.ToString());
874 }
875 895
876 public bool ignoreIncomingConfiguration(string configuration_key, object configuration_result) 896 if (MaptileStaticFile != null && MaptileStaticFile != String.Empty)
877 { 897 config.Set("MaptileStaticFile", MaptileStaticFile);
878 return true;
879 } 898 }
880 899
881 public void SaveRegionToFile(string description, string filename) 900 public void SaveRegionToFile(string description, string filename)
@@ -897,17 +916,12 @@ namespace OpenSim.Framework
897 916
898 return; 917 return;
899 } 918 }
900 else if (filename.ToLower().EndsWith(".xml"))
901 {
902 configMember = new ConfigurationMember(filename, description, loadConfigurationOptionsFromMe,
903 ignoreIncomingConfiguration, false);
904 configMember.performConfigurationRetrieve();
905 RegionFile = filename;
906 }
907 else 919 else
908 throw new Exception("Invalid file type for region persistence."); 920 throw new Exception("Invalid file type for region persistence.");
909 } 921 }
910 922
923<<<<<<< HEAD
924=======
911 public void loadConfigurationOptionsFromMe() 925 public void loadConfigurationOptionsFromMe()
912 { 926 {
913 configMember.addConfigurationOption("sim_UUID", ConfigurationOption.ConfigurationTypes.TYPE_UUID_NULL_FREE, 927 configMember.addConfigurationOption("sim_UUID", ConfigurationOption.ConfigurationTypes.TYPE_UUID_NULL_FREE,
@@ -1133,16 +1147,11 @@ namespace OpenSim.Framework
1133 return true; 1147 return true;
1134 } 1148 }
1135 1149
1150>>>>>>> avn/ubitvar
1136 public void SaveLastMapUUID(UUID mapUUID) 1151 public void SaveLastMapUUID(UUID mapUUID)
1137 { 1152 {
1138 lastMapUUID = mapUUID; 1153 lastMapUUID = mapUUID;
1139 lastMapRefresh = Util.UnixTimeSinceEpoch().ToString(); 1154 lastMapRefresh = Util.UnixTimeSinceEpoch().ToString();
1140
1141 if (configMember == null)
1142 return;
1143
1144 configMember.forceSetConfigurationOption("lastmap_uuid", mapUUID.ToString());
1145 configMember.forceSetConfigurationOption("lastmap_refresh", lastMapRefresh);
1146 } 1155 }
1147 1156
1148 public OSDMap PackRegionInfoData() 1157 public OSDMap PackRegionInfoData()
diff --git a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
index 563bcb9..3bcbe2f 100644
--- a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.0.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
index ab36f10..1b2519c 100644
--- a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.0.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs b/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs
index 65de563..487c087 100644
--- a/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs
+++ b/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs
@@ -121,12 +121,39 @@ namespace OpenSim.Framework.RegionLoader.Web
121 throw ex; 121 throw ex;
122 } 122 }
123 123
124<<<<<<< HEAD
125 m_log.Debug("[WEBLOADER]: Done downloading region information from server. Total Bytes: " +
126 xmlSource.Length);
127 XmlDocument xmlDoc = new XmlDocument();
128 xmlDoc.LoadXml(xmlSource);
129 if (xmlDoc.FirstChild.Name == "Nini")
130 {
131 regionCount = xmlDoc.FirstChild.ChildNodes.Count;
132
133 if (regionCount > 0)
134 {
135 regionInfos = new RegionInfo[regionCount];
136 int i;
137 for (i = 0; i < xmlDoc.FirstChild.ChildNodes.Count; i++)
138 {
139 m_log.Debug(xmlDoc.FirstChild.ChildNodes[i].OuterXml);
140 regionInfos[i] =
141 new RegionInfo("REGION CONFIG #" + (i + 1), xmlDoc.FirstChild.ChildNodes[i],false,m_configSource);
142 }
143 }
144 }
145 }
146 catch (WebException ex)
147 {
148 using (HttpWebResponse response = (HttpWebResponse)ex.Response)
149=======
124 if (regionCount > 0 | allowRegionless) 150 if (regionCount > 0 | allowRegionless)
125 return regionInfos; 151 return regionInfos;
126 152
127 m_log.Debug("[WEBLOADER]: Request yielded no regions."); 153 m_log.Debug("[WEBLOADER]: Request yielded no regions.");
128 tries--; 154 tries--;
129 if (tries > 0) 155 if (tries > 0)
156>>>>>>> avn/ubitvar
130 { 157 {
131 m_log.Debug("[WEBLOADER]: Retrying"); 158 m_log.Debug("[WEBLOADER]: Retrying");
132 System.Threading.Thread.Sleep(wait); 159 System.Threading.Thread.Sleep(wait);
diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs
index 9249105..e66d5be 100644
--- a/OpenSim/Framework/SLUtil.cs
+++ b/OpenSim/Framework/SLUtil.cs
@@ -25,13 +25,9 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using OpenMetaverse;
28using System; 29using System;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Xml;
33using log4net;
34using OpenMetaverse;
35 31
36namespace OpenSim.Framework 32namespace OpenSim.Framework
37{ 33{
@@ -68,7 +64,7 @@ namespace OpenSim.Framework
68 private class TypeMapping 64 private class TypeMapping
69 { 65 {
70 private sbyte assetType; 66 private sbyte assetType;
71 private InventoryType inventoryType; 67 private sbyte inventoryType;
72 private string contentType; 68 private string contentType;
73 private string contentType2; 69 private string contentType2;
74 private string extension; 70 private string extension;
@@ -83,7 +79,7 @@ namespace OpenSim.Framework
83 get { return AssetTypeFromCode(assetType); } 79 get { return AssetTypeFromCode(assetType); }
84 } 80 }
85 81
86 public InventoryType InventoryType 82 public sbyte InventoryType
87 { 83 {
88 get { return inventoryType; } 84 get { return inventoryType; }
89 } 85 }
@@ -103,7 +99,7 @@ namespace OpenSim.Framework
103 get { return extension; } 99 get { return extension; }
104 } 100 }
105 101
106 private TypeMapping(sbyte assetType, InventoryType inventoryType, string contentType, string contentType2, string extension) 102 private TypeMapping(sbyte assetType, sbyte inventoryType, string contentType, string contentType2, string extension)
107 { 103 {
108 this.assetType = assetType; 104 this.assetType = assetType;
109 this.inventoryType = inventoryType; 105 this.inventoryType = inventoryType;
@@ -112,18 +108,28 @@ namespace OpenSim.Framework
112 this.extension = extension; 108 this.extension = extension;
113 } 109 }
114 110
115 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string contentType2, string extension) 111 public TypeMapping(AssetType assetType, sbyte inventoryType, string contentType, string contentType2, string extension)
116 : this((sbyte)assetType, inventoryType, contentType, contentType2, extension) 112 : this((sbyte)assetType, inventoryType, contentType, contentType2, extension)
117 { 113 {
118 } 114 }
119 115
116 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string contentType2, string extension)
117 : this((sbyte)assetType, (sbyte)inventoryType, contentType, contentType2, extension)
118 {
119 }
120
120 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string extension) 121 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string extension)
121 : this((sbyte)assetType, inventoryType, contentType, null, extension) 122 : this((sbyte)assetType, (sbyte)inventoryType, contentType, null, extension)
123 {
124 }
125
126 public TypeMapping(AssetType assetType, FolderType inventoryType, string contentType, string extension)
127 : this((sbyte)assetType, (sbyte)inventoryType, contentType, null, extension)
122 { 128 {
123 } 129 }
124 130
125 public TypeMapping(OpenSimAssetType assetType, InventoryType inventoryType, string contentType, string extension) 131 public TypeMapping(OpenSimAssetType assetType, InventoryType inventoryType, string contentType, string extension)
126 : this((sbyte)assetType, inventoryType, contentType, null, extension) 132 : this((sbyte)assetType, (sbyte)inventoryType, contentType, null, extension)
127 { 133 {
128 } 134 }
129 } 135 }
@@ -149,53 +155,65 @@ namespace OpenSim.Framework
149 new TypeMapping(AssetType.Object, InventoryType.Object, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"), 155 new TypeMapping(AssetType.Object, InventoryType.Object, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"),
150 new TypeMapping(AssetType.Object, InventoryType.Attachment, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"), 156 new TypeMapping(AssetType.Object, InventoryType.Attachment, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"),
151 new TypeMapping(AssetType.Notecard, InventoryType.Notecard, "application/vnd.ll.notecard", "application/x-metaverse-notecard", "notecard"), 157 new TypeMapping(AssetType.Notecard, InventoryType.Notecard, "application/vnd.ll.notecard", "application/x-metaverse-notecard", "notecard"),
152 new TypeMapping(AssetType.Folder, InventoryType.Folder, "application/vnd.ll.folder", "folder"),
153 new TypeMapping(AssetType.RootFolder, InventoryType.RootCategory, "application/vnd.ll.rootfolder", "rootfolder"),
154 new TypeMapping(AssetType.LSLText, InventoryType.LSL, "application/vnd.ll.lsltext", "application/x-metaverse-lsl", "lsl"), 158 new TypeMapping(AssetType.LSLText, InventoryType.LSL, "application/vnd.ll.lsltext", "application/x-metaverse-lsl", "lsl"),
155 new TypeMapping(AssetType.LSLBytecode, InventoryType.LSL, "application/vnd.ll.lslbyte", "application/x-metaverse-lso", "lso"), 159 new TypeMapping(AssetType.LSLBytecode, InventoryType.LSL, "application/vnd.ll.lslbyte", "application/x-metaverse-lso", "lso"),
156 new TypeMapping(AssetType.Bodypart, InventoryType.Wearable, "application/vnd.ll.bodypart", "application/x-metaverse-bodypart", "bodypart"), 160 new TypeMapping(AssetType.Bodypart, InventoryType.Wearable, "application/vnd.ll.bodypart", "application/x-metaverse-bodypart", "bodypart"),
157 new TypeMapping(AssetType.TrashFolder, InventoryType.Folder, "application/vnd.ll.trashfolder", "trashfolder"),
158 new TypeMapping(AssetType.SnapshotFolder, InventoryType.Folder, "application/vnd.ll.snapshotfolder", "snapshotfolder"),
159 new TypeMapping(AssetType.LostAndFoundFolder, InventoryType.Folder, "application/vnd.ll.lostandfoundfolder", "lostandfoundfolder"),
160 new TypeMapping(AssetType.Animation, InventoryType.Animation, "application/vnd.ll.animation", "application/x-metaverse-animation", "animation"), 161 new TypeMapping(AssetType.Animation, InventoryType.Animation, "application/vnd.ll.animation", "application/x-metaverse-animation", "animation"),
161 new TypeMapping(AssetType.Gesture, InventoryType.Gesture, "application/vnd.ll.gesture", "application/x-metaverse-gesture", "gesture"), 162 new TypeMapping(AssetType.Gesture, InventoryType.Gesture, "application/vnd.ll.gesture", "application/x-metaverse-gesture", "gesture"),
162 new TypeMapping(AssetType.Simstate, InventoryType.Snapshot, "application/x-metaverse-simstate", "simstate"), 163 new TypeMapping(AssetType.Simstate, InventoryType.Snapshot, "application/x-metaverse-simstate", "simstate"),
163 new TypeMapping(AssetType.FavoriteFolder, InventoryType.Unknown, "application/vnd.ll.favoritefolder", "favoritefolder"),
164 new TypeMapping(AssetType.Link, InventoryType.Unknown, "application/vnd.ll.link", "link"), 164 new TypeMapping(AssetType.Link, InventoryType.Unknown, "application/vnd.ll.link", "link"),
165 new TypeMapping(AssetType.LinkFolder, InventoryType.Unknown, "application/vnd.ll.linkfolder", "linkfolder"), 165 new TypeMapping(AssetType.LinkFolder, InventoryType.Unknown, "application/vnd.ll.linkfolder", "linkfolder"),
166 new TypeMapping(AssetType.CurrentOutfitFolder, InventoryType.Unknown, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"),
167 new TypeMapping(AssetType.OutfitFolder, InventoryType.Unknown, "application/vnd.ll.outfitfolder", "outfitfolder"),
168 new TypeMapping(AssetType.MyOutfitsFolder, InventoryType.Unknown, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"),
169 new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm"), 166 new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm"),
167
168 // The next few items are about inventory folders
169 new TypeMapping(AssetType.Folder, FolderType.None, "application/vnd.ll.folder", "folder"),
170 new TypeMapping(AssetType.Folder, FolderType.Root, "application/vnd.ll.rootfolder", "rootfolder"),
171 new TypeMapping(AssetType.Folder, FolderType.Trash, "application/vnd.ll.trashfolder", "trashfolder"),
172 new TypeMapping(AssetType.Folder, FolderType.Snapshot, "application/vnd.ll.snapshotfolder", "snapshotfolder"),
173 new TypeMapping(AssetType.Folder, FolderType.LostAndFound, "application/vnd.ll.lostandfoundfolder", "lostandfoundfolder"),
174 new TypeMapping(AssetType.Folder, FolderType.Favorites, "application/vnd.ll.favoritefolder", "favoritefolder"),
175 new TypeMapping(AssetType.Folder, FolderType.CurrentOutfit, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"),
176 new TypeMapping(AssetType.Folder, FolderType.Outfit, "application/vnd.ll.outfitfolder", "outfitfolder"),
177 new TypeMapping(AssetType.Folder, FolderType.MyOutfits, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"),
170 178
179 // This next mappping is an asset to inventory item mapping.
180 // Note: LL stores folders as assets of type Folder = 8, and it has a corresponding InventoryType = 8
181 // OpenSim doesn't store folders as assets, so this mapping should only be used when parsing things from the viewer to the server
182 new TypeMapping(AssetType.Folder, InventoryType.Folder, "application/vnd.ll.folder", "folder"),
183
184 // OpenSim specific
171 new TypeMapping(OpenSimAssetType.Material, InventoryType.Unknown, "application/llsd+xml", "material") 185 new TypeMapping(OpenSimAssetType.Material, InventoryType.Unknown, "application/llsd+xml", "material")
172 }; 186 };
173 187
174 private static Dictionary<sbyte, string> asset2Content; 188 private static Dictionary<sbyte, string> asset2Content;
175 private static Dictionary<sbyte, string> asset2Extension; 189 private static Dictionary<sbyte, string> asset2Extension;
176 private static Dictionary<InventoryType, string> inventory2Content; 190 private static Dictionary<sbyte, string> inventory2Content;
177 private static Dictionary<string, sbyte> content2Asset; 191 private static Dictionary<string, sbyte> content2Asset;
178 private static Dictionary<string, InventoryType> content2Inventory; 192 private static Dictionary<string, sbyte> content2Inventory;
179 193
180 static SLUtil() 194 static SLUtil()
181 { 195 {
182 asset2Content = new Dictionary<sbyte, string>(); 196 asset2Content = new Dictionary<sbyte, string>();
183 asset2Extension = new Dictionary<sbyte, string>(); 197 asset2Extension = new Dictionary<sbyte, string>();
184 inventory2Content = new Dictionary<InventoryType, string>(); 198 inventory2Content = new Dictionary<sbyte, string>();
185 content2Asset = new Dictionary<string, sbyte>(); 199 content2Asset = new Dictionary<string, sbyte>();
186 content2Inventory = new Dictionary<string, InventoryType>(); 200 content2Inventory = new Dictionary<string, sbyte>();
187 201
188 foreach (TypeMapping mapping in MAPPINGS) 202 foreach (TypeMapping mapping in MAPPINGS)
189 { 203 {
190 sbyte assetType = mapping.AssetTypeCode; 204 sbyte assetType = mapping.AssetTypeCode;
191 if (!asset2Content.ContainsKey(assetType)) 205 if (!asset2Content.ContainsKey(assetType))
192 asset2Content.Add(assetType, mapping.ContentType); 206 asset2Content.Add(assetType, mapping.ContentType);
207
193 if (!asset2Extension.ContainsKey(assetType)) 208 if (!asset2Extension.ContainsKey(assetType))
194 asset2Extension.Add(assetType, mapping.Extension); 209 asset2Extension.Add(assetType, mapping.Extension);
210
195 if (!inventory2Content.ContainsKey(mapping.InventoryType)) 211 if (!inventory2Content.ContainsKey(mapping.InventoryType))
196 inventory2Content.Add(mapping.InventoryType, mapping.ContentType); 212 inventory2Content.Add(mapping.InventoryType, mapping.ContentType);
213
197 if (!content2Asset.ContainsKey(mapping.ContentType)) 214 if (!content2Asset.ContainsKey(mapping.ContentType))
198 content2Asset.Add(mapping.ContentType, assetType); 215 content2Asset.Add(mapping.ContentType, assetType);
216
199 if (!content2Inventory.ContainsKey(mapping.ContentType)) 217 if (!content2Inventory.ContainsKey(mapping.ContentType))
200 content2Inventory.Add(mapping.ContentType, mapping.InventoryType); 218 content2Inventory.Add(mapping.ContentType, mapping.InventoryType);
201 219
@@ -220,8 +238,8 @@ namespace OpenSim.Framework
220 public static string SLInvTypeToContentType(int invType) 238 public static string SLInvTypeToContentType(int invType)
221 { 239 {
222 string contentType; 240 string contentType;
223 if (!inventory2Content.TryGetValue((InventoryType)invType, out contentType)) 241 if (!inventory2Content.TryGetValue((sbyte)invType, out contentType))
224 contentType = inventory2Content[InventoryType.Unknown]; 242 contentType = inventory2Content[(sbyte)InventoryType.Unknown];
225 return contentType; 243 return contentType;
226 } 244 }
227 245
@@ -235,9 +253,9 @@ namespace OpenSim.Framework
235 253
236 public static sbyte ContentTypeToSLInvType(string contentType) 254 public static sbyte ContentTypeToSLInvType(string contentType)
237 { 255 {
238 InventoryType invType; 256 sbyte invType;
239 if (!content2Inventory.TryGetValue(contentType, out invType)) 257 if (!content2Inventory.TryGetValue(contentType, out invType))
240 invType = InventoryType.Unknown; 258 invType = (sbyte)InventoryType.Unknown;
241 return (sbyte)invType; 259 return (sbyte)invType;
242 } 260 }
243 261
@@ -251,106 +269,270 @@ namespace OpenSim.Framework
251 269
252 #endregion SL / file extension / content-type conversions 270 #endregion SL / file extension / content-type conversions
253 271
254 /// <summary> 272 private class NotecardReader
255 /// Parse a notecard in Linden format to a string of ordinary text.
256 /// </summary>
257 /// <param name="rawInput"></param>
258 /// <returns></returns>
259 public static string ParseNotecardToString(string rawInput)
260 { 273 {
261 string[] output = ParseNotecardToList(rawInput).ToArray(); 274 private string rawInput;
275 private int lineNumber;
262 276
263// foreach (string line in output) 277 public int LineNumber
264// m_log.DebugFormat("[PARSE NOTECARD]: ParseNotecardToString got line {0}", line); 278 {
265 279 get
266 return string.Join("\n", output); 280 {
281 return lineNumber;
282 }
283 }
284
285 public NotecardReader(string _rawInput)
286 {
287 rawInput = (string)_rawInput.Clone();
288 lineNumber = 0;
289 }
290
291 public string getLine()
292 {
293 if(rawInput.Length == 0)
294 {
295 throw new NotANotecardFormatException(lineNumber + 1);
296 }
297
298 int pos = rawInput.IndexOf('\n');
299 if(pos < 0)
300 {
301 pos = rawInput.Length;
302 }
303
304 /* cut line from rest */
305 ++lineNumber;
306 string line = rawInput.Substring(0, pos);
307 if (pos + 1 >= rawInput.Length)
308 {
309 rawInput = string.Empty;
310 }
311 else
312 {
313 rawInput = rawInput.Substring(pos + 1);
314 }
315 /* clean up line from double spaces and tabs */
316 line = line.Replace("\t", " ");
317 while(line.IndexOf(" ") >= 0)
318 {
319 line = line.Replace(" ", " ");
320 }
321 return line.Replace("\r", "").Trim();
322 }
323
324 public string getBlock(int length)
325 {
326 /* cut line from rest */
327 if(length > rawInput.Length)
328 {
329 throw new NotANotecardFormatException(lineNumber);
330 }
331 string line = rawInput.Substring(0, length);
332 rawInput = rawInput.Substring(length);
333 return line;
334 }
267 } 335 }
268 336
269 /// <summary> 337 public class NotANotecardFormatException : Exception
270 /// Parse a notecard in Linden format to a list of ordinary lines. 338 {
271 /// </summary> 339 public int lineNumber;
272 /// <param name="rawInput"></param> 340 public NotANotecardFormatException(int _lineNumber)
273 /// <returns></returns> 341 : base()
274 public static List<string> ParseNotecardToList(string rawInput) 342 {
343 lineNumber = _lineNumber;
344 }
345 }
346
347 private static void skipSection(NotecardReader reader)
348 {
349 if (reader.getLine() != "{")
350 throw new NotANotecardFormatException(reader.LineNumber);
351
352 string line;
353 while ((line = reader.getLine()) != "}")
354 {
355 if(line.IndexOf('{')>=0)
356 {
357 throw new NotANotecardFormatException(reader.LineNumber);
358 }
359 }
360 }
361
362 private static void skipInventoryItem(NotecardReader reader)
275 { 363 {
276 string[] input; 364 if (reader.getLine() != "{")
277 int idx = 0; 365 throw new NotANotecardFormatException(reader.LineNumber);
278 int level = 0; 366
279 List<string> output = new List<string>(); 367 string line;
280 string[] words; 368 while((line = reader.getLine()) != "}")
281
282 //The Linden format always ends with a } after the input data.
283 //Strip off trailing } so there is nothing after the input data.
284 int i = rawInput.LastIndexOf("}");
285 rawInput = rawInput.Remove(i, rawInput.Length-i);
286 input = rawInput.Replace("\r", "").Split('\n');
287
288 while (idx < input.Length)
289 { 369 {
290 if (input[idx] == "{") 370 string[] data = line.Split(' ');
371 if(data.Length == 0)
291 { 372 {
292 level++;
293 idx++;
294 continue; 373 continue;
295 } 374 }
375 if(data[0] == "permissions")
376 {
377 skipSection(reader);
378 }
379 else if(data[0] == "sale_info")
380 {
381 skipSection(reader);
382 }
383 else if (line.IndexOf('{') >= 0)
384 {
385 throw new NotANotecardFormatException(reader.LineNumber);
386 }
387 }
388 }
296 389
297 if (input[idx]== "}") 390 private static void skipInventoryItems(NotecardReader reader)
391 {
392 if(reader.getLine() != "{")
393 {
394 throw new NotANotecardFormatException(reader.LineNumber);
395 }
396
397 string line;
398 while((line = reader.getLine()) != "}")
399 {
400 string[] data = line.Split(' ');
401 if(data.Length == 0)
298 { 402 {
299 level--;
300 idx++;
301 continue; 403 continue;
302 } 404 }
303 405
304 switch (level) 406 if(data[0] == "inv_item")
305 { 407 {
306 case 0: 408 skipInventoryItem(reader);
307 words = input[idx].Split(' '); // Linden text ver 409 }
308 // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard) 410 else if (line.IndexOf('{') >= 0)
309 if (words.Length < 3) 411 {
310 return output; 412 throw new NotANotecardFormatException(reader.LineNumber);
311 413 }
312 int version = int.Parse(words[3]);
313 if (version != 2)
314 return output;
315 break;
316 case 1:
317 words = input[idx].Split(' ');
318 if (words[0] == "LLEmbeddedItems")
319 break;
320 if (words[0] == "Text")
321 {
322 idx++; //Now points to first line of notecard text
323 414
324 //Number of lines in notecard. 415 }
325 int lines = input.Length - idx; 416 }
326 int line = 0;
327 417
328 while (line < lines) 418 private static void skipInventory(NotecardReader reader)
329 { 419 {
330// m_log.DebugFormat("[PARSE NOTECARD]: Adding line {0}", input[idx]); 420 if (reader.getLine() != "{")
331 output.Add(input[idx]); 421 throw new NotANotecardFormatException(reader.LineNumber);
332 idx++;
333 line++;
334 }
335 422
336 return output; 423 string line;
337 } 424 while((line = reader.getLine()) != "}")
338 break; 425 {
339 case 2: 426 string[] data = line.Split(' ');
340 words = input[idx].Split(' '); // count 427 if(data[0] == "count")
341 if (words[0] == "count") 428 {
429 int count = Int32.Parse(data[1]);
430 for(int i = 0; i < count; ++i)
342 { 431 {
343 int c = int.Parse(words[1]); 432 skipInventoryItems(reader);
344 if (c > 0)
345 return output;
346 break;
347 } 433 }
348 break;
349 } 434 }
350 idx++; 435 else if (line.IndexOf('{') >= 0)
436 {
437 throw new NotANotecardFormatException(reader.LineNumber);
438 }
351 } 439 }
352 440 }
353 return output; 441
442 private static string readNotecardText(NotecardReader reader)
443 {
444 if (reader.getLine() != "{")
445 throw new NotANotecardFormatException(reader.LineNumber);
446
447 string notecardString = string.Empty;
448 string line;
449 while((line = reader.getLine()) != "}")
450 {
451 string[] data = line.Split(' ');
452 if (data.Length == 0)
453 {
454 continue;
455 }
456
457 if (data[0] == "LLEmbeddedItems")
458 {
459 skipInventory(reader);
460 }
461 else if(data[0] == "Text" && data.Length == 3)
462 {
463 int length = Int32.Parse(data[2]);
464 notecardString = reader.getBlock(length);
465 }
466 else if (line.IndexOf('{') >= 0)
467 {
468 throw new NotANotecardFormatException(reader.LineNumber);
469 }
470
471 }
472 return notecardString;
473 }
474
475 private static string readNotecard(byte[] rawInput)
476 {
477 string rawIntermedInput = string.Empty;
478
479 /* make up a Raw Encoding here */
480 foreach(byte c in rawInput)
481 {
482 char d = (char)c;
483 rawIntermedInput += d;
484 }
485
486 NotecardReader reader = new NotecardReader(rawIntermedInput);
487 string line;
488 try
489 {
490 line = reader.getLine();
491 }
492 catch(Exception)
493 {
494 return System.Text.Encoding.UTF8.GetString(rawInput);
495 }
496 string[] versioninfo = line.Split(' ');
497 if(versioninfo.Length < 3)
498 {
499 return System.Text.Encoding.UTF8.GetString(rawInput);
500 }
501 else if(versioninfo[0] != "Linden" || versioninfo[1] != "text")
502 {
503 return System.Text.Encoding.UTF8.GetString(rawInput);
504 }
505 else
506 {
507 /* now we actually decode the Encoding, before we needed it in raw */
508 string o = readNotecardText(reader);
509 byte[] a = new byte[o.Length];
510 for(int i = 0; i < o.Length; ++i)
511 {
512 a[i] = (byte)o[i];
513 }
514 return System.Text.Encoding.UTF8.GetString(a);
515 }
516 }
517
518 /// <summary>
519 /// Parse a notecard in Linden format to a string of ordinary text.
520 /// </summary>
521 /// <param name="rawInput"></param>
522 /// <returns></returns>
523 public static string ParseNotecardToString(byte[] rawInput)
524 {
525 return readNotecard(rawInput);
526 }
527
528 /// <summary>
529 /// Parse a notecard in Linden format to a list of ordinary lines.
530 /// </summary>
531 /// <param name="rawInput"></param>
532 /// <returns></returns>
533 public static string[] ParseNotecardToArray(byte[] rawInput)
534 {
535 return readNotecard(rawInput).Replace("\r", "").Split('\n');
354 } 536 }
355 } 537 }
356} 538}
diff --git a/OpenSim/Framework/Serialization/ArchiveConstants.cs b/OpenSim/Framework/Serialization/ArchiveConstants.cs
index 73ebfae..ab3c285 100644
--- a/OpenSim/Framework/Serialization/ArchiveConstants.cs
+++ b/OpenSim/Framework/Serialization/ArchiveConstants.cs
@@ -115,20 +115,16 @@ namespace OpenSim.Framework.Serialization
115 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.ImageJPEG] = ASSET_EXTENSION_SEPARATOR + "image.jpg"; 115 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.ImageJPEG] = ASSET_EXTENSION_SEPARATOR + "image.jpg";
116 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.ImageTGA] = ASSET_EXTENSION_SEPARATOR + "image.tga"; 116 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.ImageTGA] = ASSET_EXTENSION_SEPARATOR + "image.tga";
117 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Landmark] = ASSET_EXTENSION_SEPARATOR + "landmark.txt"; 117 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Landmark] = ASSET_EXTENSION_SEPARATOR + "landmark.txt";
118 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LostAndFoundFolder] = ASSET_EXTENSION_SEPARATOR + "lostandfoundfolder.txt"; // Not sure if we'll ever see this
119 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLBytecode] = ASSET_EXTENSION_SEPARATOR + "bytecode.lso"; 118 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLBytecode] = ASSET_EXTENSION_SEPARATOR + "bytecode.lso";
120 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLText] = ASSET_EXTENSION_SEPARATOR + "script.lsl"; 119 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLText] = ASSET_EXTENSION_SEPARATOR + "script.lsl";
121 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Mesh] = ASSET_EXTENSION_SEPARATOR + "mesh.llmesh"; 120 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Mesh] = ASSET_EXTENSION_SEPARATOR + "mesh.llmesh";
122 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Notecard] = ASSET_EXTENSION_SEPARATOR + "notecard.txt"; 121 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Notecard] = ASSET_EXTENSION_SEPARATOR + "notecard.txt";
123 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Object] = ASSET_EXTENSION_SEPARATOR + "object.xml"; 122 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Object] = ASSET_EXTENSION_SEPARATOR + "object.xml";
124 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.RootFolder] = ASSET_EXTENSION_SEPARATOR + "rootfolder.txt"; // Not sure if we'll ever see this
125 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Simstate] = ASSET_EXTENSION_SEPARATOR + "simstate.bin"; // Not sure if we'll ever see this 123 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Simstate] = ASSET_EXTENSION_SEPARATOR + "simstate.bin"; // Not sure if we'll ever see this
126 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SnapshotFolder] = ASSET_EXTENSION_SEPARATOR + "snapshotfolder.txt"; // Not sure if we'll ever see this
127 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Sound] = ASSET_EXTENSION_SEPARATOR + "sound.ogg"; 124 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Sound] = ASSET_EXTENSION_SEPARATOR + "sound.ogg";
128 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV] = ASSET_EXTENSION_SEPARATOR + "sound.wav"; 125 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV] = ASSET_EXTENSION_SEPARATOR + "sound.wav";
129 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Texture] = ASSET_EXTENSION_SEPARATOR + "texture.jp2"; 126 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Texture] = ASSET_EXTENSION_SEPARATOR + "texture.jp2";
130 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TextureTGA] = ASSET_EXTENSION_SEPARATOR + "texture.tga"; 127 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TextureTGA] = ASSET_EXTENSION_SEPARATOR + "texture.tga";
131 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TrashFolder] = ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"; // Not sure if we'll ever see this
132 ASSET_TYPE_TO_EXTENSION[(sbyte)OpenSimAssetType.Material] = ASSET_EXTENSION_SEPARATOR + "material.xml"; // Not sure if we'll ever see this 128 ASSET_TYPE_TO_EXTENSION[(sbyte)OpenSimAssetType.Material] = ASSET_EXTENSION_SEPARATOR + "material.xml"; // Not sure if we'll ever see this
133 129
134 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "animation.bvh"] = (sbyte)AssetType.Animation; 130 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "animation.bvh"] = (sbyte)AssetType.Animation;
@@ -140,21 +136,17 @@ namespace OpenSim.Framework.Serialization
140 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "image.jpg"] = (sbyte)AssetType.ImageJPEG; 136 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "image.jpg"] = (sbyte)AssetType.ImageJPEG;
141 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "image.tga"] = (sbyte)AssetType.ImageTGA; 137 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "image.tga"] = (sbyte)AssetType.ImageTGA;
142 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "landmark.txt"] = (sbyte)AssetType.Landmark; 138 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "landmark.txt"] = (sbyte)AssetType.Landmark;
143 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "lostandfoundfolder.txt"] = (sbyte)AssetType.LostAndFoundFolder;
144 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bytecode.lso"] = (sbyte)AssetType.LSLBytecode; 139 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bytecode.lso"] = (sbyte)AssetType.LSLBytecode;
145 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "script.lsl"] = (sbyte)AssetType.LSLText; 140 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "script.lsl"] = (sbyte)AssetType.LSLText;
146 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "mesh.llmesh"] = (sbyte)AssetType.Mesh; 141 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "mesh.llmesh"] = (sbyte)AssetType.Mesh;
147 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "notecard.txt"] = (sbyte)AssetType.Notecard; 142 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "notecard.txt"] = (sbyte)AssetType.Notecard;
148 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "object.xml"] = (sbyte)AssetType.Object; 143 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "object.xml"] = (sbyte)AssetType.Object;
149 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "rootfolder.txt"] = (sbyte)AssetType.RootFolder;
150 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "simstate.bin"] = (sbyte)AssetType.Simstate; 144 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "simstate.bin"] = (sbyte)AssetType.Simstate;
151 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "snapshotfolder.txt"] = (sbyte)AssetType.SnapshotFolder;
152 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "sound.ogg"] = (sbyte)AssetType.Sound; 145 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "sound.ogg"] = (sbyte)AssetType.Sound;
153 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "sound.wav"] = (sbyte)AssetType.SoundWAV; 146 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "sound.wav"] = (sbyte)AssetType.SoundWAV;
154 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.jp2"] = (sbyte)AssetType.Texture; 147 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.jp2"] = (sbyte)AssetType.Texture;
155 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.tga"] = (sbyte)AssetType.TextureTGA; 148 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.tga"] = (sbyte)AssetType.TextureTGA;
156 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder; 149 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "material.xml"] = (sbyte)OpenSimAssetType.Material;
157 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "material.xml"] = (sbyte)OpenSimAssetType.Material;
158 } 150 }
159 151
160 public static string CreateOarLandDataPath(LandData ld) 152 public static string CreateOarLandDataPath(LandData ld)
diff --git a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs
index c56f213..55640ac 100644
--- a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs
+++ b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics;
30using System.IO; 31using System.IO;
31using System.Reflection; 32using System.Reflection;
32using System.Xml; 33using System.Xml;
@@ -47,20 +48,20 @@ namespace OpenSim.Framework.Serialization.External
47 /// Populate a node with data read from xml using a dictinoary of processors 48 /// Populate a node with data read from xml using a dictinoary of processors
48 /// </summary> 49 /// </summary>
49 /// <param name="nodeToFill"></param> 50 /// <param name="nodeToFill"></param>
50 /// <param name="processors">/param> 51 /// <param name="processors"></param>
51 /// <param name="xtr"></param> 52 /// <param name="xtr"></param>
52 /// <returns>true on successful, false if there were any processing failures</returns> 53 /// <returns>true on successful, false if there were any processing failures</returns>
53 public static bool ExecuteReadProcessors<NodeType>( 54 public static bool ExecuteReadProcessors<NodeType>(
54 NodeType nodeToFill, Dictionary<string, Action<NodeType, XmlTextReader>> processors, XmlTextReader xtr) 55 NodeType nodeToFill, Dictionary<string, Action<NodeType, XmlReader>> processors, XmlReader xtr)
55 { 56 {
56 return ExecuteReadProcessors( 57 return ExecuteReadProcessors(
57 nodeToFill, 58 nodeToFill,
58 processors, 59 processors,
59 xtr, 60 xtr,
60 (o, name, e) 61 (o, nodeName, e) => {
61 => m_log.DebugFormat( 62 m_log.Debug(string.Format("[ExternalRepresentationUtils]: Error while parsing element {0} ",
62 "[ExternalRepresentationUtils]: Exception while parsing element {0}, continuing. Exception {1}{2}", 63 nodeName), e);
63 name, e.Message, e.StackTrace)); 64 });
64 } 65 }
65 66
66 /// <summary> 67 /// <summary>
@@ -75,23 +76,27 @@ namespace OpenSim.Framework.Serialization.External
75 /// <returns>true on successful, false if there were any processing failures</returns> 76 /// <returns>true on successful, false if there were any processing failures</returns>
76 public static bool ExecuteReadProcessors<NodeType>( 77 public static bool ExecuteReadProcessors<NodeType>(
77 NodeType nodeToFill, 78 NodeType nodeToFill,
78 Dictionary<string, Action<NodeType, XmlTextReader>> processors, 79 Dictionary<string, Action<NodeType, XmlReader>> processors,
79 XmlTextReader xtr, 80 XmlReader xtr,
80 Action<NodeType, string, Exception> parseExceptionAction) 81 Action<NodeType, string, Exception> parseExceptionAction)
81 { 82 {
82 bool errors = false; 83 bool errors = false;
84 int numErrors = 0;
85
86 Stopwatch timer = new Stopwatch();
87 timer.Start();
83 88
84 string nodeName = string.Empty; 89 string nodeName = string.Empty;
85 while (xtr.NodeType != XmlNodeType.EndElement) 90 while (xtr.NodeType != XmlNodeType.EndElement)
86 { 91 {
87 nodeName = xtr.Name; 92 nodeName = xtr.Name;
88 93
89// m_log.DebugFormat("[ExternalRepresentationUtils]: Processing: {0}", nodeName); 94 // m_log.DebugFormat("[ExternalRepresentationUtils]: Processing node: {0}", nodeName);
90 95
91 Action<NodeType, XmlTextReader> p = null; 96 Action<NodeType, XmlReader> p = null;
92 if (processors.TryGetValue(xtr.Name, out p)) 97 if (processors.TryGetValue(xtr.Name, out p))
93 { 98 {
94// m_log.DebugFormat("[ExternalRepresentationUtils]: Found {0} processor, nodeName); 99 // m_log.DebugFormat("[ExternalRepresentationUtils]: Found processor for {0}", nodeName);
95 100
96 try 101 try
97 { 102 {
@@ -101,6 +106,18 @@ namespace OpenSim.Framework.Serialization.External
101 { 106 {
102 errors = true; 107 errors = true;
103 parseExceptionAction(nodeToFill, nodeName, e); 108 parseExceptionAction(nodeToFill, nodeName, e);
109
110 if (xtr.EOF)
111 {
112 m_log.Debug("[ExternalRepresentationUtils]: Aborting ExecuteReadProcessors due to unexpected end of XML");
113 break;
114 }
115
116 if (++numErrors == 10)
117 {
118 m_log.Debug("[ExternalRepresentationUtils]: Aborting ExecuteReadProcessors due to too many parsing errors");
119 break;
120 }
104 121
105 if (xtr.NodeType == XmlNodeType.EndElement) 122 if (xtr.NodeType == XmlNodeType.EndElement)
106 xtr.Read(); 123 xtr.Read();
@@ -108,9 +125,16 @@ namespace OpenSim.Framework.Serialization.External
108 } 125 }
109 else 126 else
110 { 127 {
111 // m_log.DebugFormat("[LandDataSerializer]: caught unknown element {0}", nodeName); 128 // m_log.DebugFormat("[ExternalRepresentationUtils]: found unknown element \"{0}\"", nodeName);
112 xtr.ReadOuterXml(); // ignore 129 xtr.ReadOuterXml(); // ignore
113 } 130 }
131
132 if (timer.Elapsed.TotalSeconds >= 60)
133 {
134 m_log.Debug("[ExternalRepresentationUtils]: Aborting ExecuteReadProcessors due to timeout");
135 errors = true;
136 break;
137 }
114 } 138 }
115 139
116 return errors; 140 return errors;
@@ -125,7 +149,8 @@ namespace OpenSim.Framework.Serialization.External
125 /// <param name="userService">The service for retrieving user account information</param> 149 /// <param name="userService">The service for retrieving user account information</param>
126 /// <param name="scopeID">The scope of the user account information (Grid ID)</param> 150 /// <param name="scopeID">The scope of the user account information (Grid ID)</param>
127 /// <returns>The SceneObjectPart represented in XML2</returns> 151 /// <returns>The SceneObjectPart represented in XML2</returns>
128 public static string RewriteSOP(string xml, string homeURL, IUserAccountService userService, UUID scopeID) 152 [Obsolete("This method is deprecated. Use RewriteSOP instead.")]
153 public static string RewriteSOP_Old(string xml, string homeURL, IUserAccountService userService, UUID scopeID)
129 { 154 {
130 if (xml == string.Empty || homeURL == string.Empty || userService == null) 155 if (xml == string.Empty || homeURL == string.Empty || userService == null)
131 return xml; 156 return xml;
@@ -161,7 +186,7 @@ namespace OpenSim.Framework.Serialization.External
161 if (!hasCreatorData && creator != null) 186 if (!hasCreatorData && creator != null)
162 { 187 {
163 XmlElement creatorData = doc.CreateElement("CreatorData"); 188 XmlElement creatorData = doc.CreateElement("CreatorData");
164 creatorData.InnerText = homeURL + ";" + creator.FirstName + " " + creator.LastName; 189 creatorData.InnerText = CalcCreatorData(homeURL, creator.FirstName + " " + creator.LastName);
165 sop.AppendChild(creatorData); 190 sop.AppendChild(creatorData);
166 } 191 }
167 } 192 }
@@ -172,5 +197,215 @@ namespace OpenSim.Framework.Serialization.External
172 return wr.ToString(); 197 return wr.ToString();
173 } 198 }
174 } 199 }
200
201 /// <summary>
202 /// Takes a XML representation of a SceneObjectPart and returns another XML representation
203 /// with creator data added to it.
204 /// </summary>
205 /// <param name="xml">The SceneObjectPart represented in XML2</param>
206 /// <param name="sceneName">An identifier for the component that's calling this function</param>
207 /// <param name="homeURL">The URL of the user agents service (home) for the creator</param>
208 /// <param name="userService">The service for retrieving user account information</param>
209 /// <param name="scopeID">The scope of the user account information (Grid ID)</param>
210 /// <returns>The SceneObjectPart represented in XML2</returns>
211 public static string RewriteSOP(string xmlData, string sceneName, string homeURL, IUserAccountService userService, UUID scopeID)
212 {
213 // Console.WriteLine("Input XML [{0}]", xmlData);
214 if (xmlData == string.Empty || homeURL == string.Empty || userService == null)
215 return xmlData;
216
217 // Deal with bug
218 xmlData = ExternalRepresentationUtils.SanitizeXml(xmlData);
219
220 using (StringWriter sw = new StringWriter())
221 using (XmlTextWriter writer = new XmlTextWriter(sw))
222 using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null))
223 using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment }))
224 {
225 TransformXml(reader, writer, sceneName, homeURL, userService, scopeID);
226
227 // Console.WriteLine("Output: [{0}]", sw.ToString());
228
229 return sw.ToString();
230 }
231 }
232
233 protected static void TransformXml(XmlReader reader, XmlWriter writer, string sceneName, string homeURI, IUserAccountService userAccountService, UUID scopeID)
234 {
235 // m_log.DebugFormat("[HG ASSET MAPPER]: Transforming XML");
236
237 int sopDepth = -1;
238 UserAccount creator = null;
239 bool hasCreatorData = false;
240
241 while (reader.Read())
242 {
243 // Console.WriteLine("Depth: {0}, name {1}", reader.Depth, reader.Name);
244
245 switch (reader.NodeType)
246 {
247 case XmlNodeType.Attribute:
248 // Console.WriteLine("FOUND ATTRIBUTE {0}", reader.Name);
249 writer.WriteAttributeString(reader.Name, reader.Value);
250 break;
251
252 case XmlNodeType.CDATA:
253 writer.WriteCData(reader.Value);
254 break;
255
256 case XmlNodeType.Comment:
257 writer.WriteComment(reader.Value);
258 break;
259
260 case XmlNodeType.DocumentType:
261 writer.WriteDocType(reader.Name, reader.Value, null, null);
262 break;
263
264 case XmlNodeType.Element:
265 // m_log.DebugFormat("Depth {0} at element {1}", reader.Depth, reader.Name);
266
267 writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
268
269 if (reader.HasAttributes)
270 {
271 while (reader.MoveToNextAttribute())
272 writer.WriteAttributeString(reader.Name, reader.Value);
273
274 reader.MoveToElement();
275 }
276
277 if (reader.LocalName == "SceneObjectPart")
278 {
279 if (sopDepth < 0)
280 {
281 sopDepth = reader.Depth;
282 // m_log.DebugFormat("[HG ASSET MAPPER]: Set sopDepth to {0}", sopDepth);
283 }
284 }
285 else
286 {
287 if (sopDepth >= 0 && reader.Depth == sopDepth + 1)
288 {
289 if (reader.Name == "CreatorID")
290 {
291 reader.Read();
292 if (reader.NodeType == XmlNodeType.Element && reader.Name == "Guid" || reader.Name == "UUID")
293 {
294 reader.Read();
295
296 if (reader.NodeType == XmlNodeType.Text)
297 {
298 UUID uuid = UUID.Zero;
299 UUID.TryParse(reader.Value, out uuid);
300 creator = userAccountService.GetUserAccount(scopeID, uuid);
301 writer.WriteElementString("UUID", reader.Value);
302 reader.Read();
303 }
304 else
305 {
306 // If we unexpected run across mixed content in this node, still carry on
307 // transforming the subtree (this replicates earlier behaviour).
308 TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID);
309 }
310 }
311 else
312 {
313 // If we unexpected run across mixed content in this node, still carry on
314 // transforming the subtree (this replicates earlier behaviour).
315 TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID);
316 }
317 }
318 else if (reader.Name == "CreatorData")
319 {
320 reader.Read();
321 if (reader.NodeType == XmlNodeType.Text)
322 {
323 hasCreatorData = true;
324 writer.WriteString(reader.Value);
325 }
326 else
327 {
328 // If we unexpected run across mixed content in this node, still carry on
329 // transforming the subtree (this replicates earlier behaviour).
330 TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID);
331 }
332 }
333 }
334 }
335
336 if (reader.IsEmptyElement)
337 {
338 // m_log.DebugFormat("[HG ASSET MAPPER]: Writing end for empty element {0}", reader.Name);
339 writer.WriteEndElement();
340 }
341
342 break;
343
344 case XmlNodeType.EndElement:
345 // m_log.DebugFormat("Depth {0} at EndElement", reader.Depth);
346 if (sopDepth == reader.Depth)
347 {
348 if (!hasCreatorData && creator != null)
349 writer.WriteElementString(reader.Prefix, "CreatorData", reader.NamespaceURI, string.Format("{0};{1} {2}", homeURI, creator.FirstName, creator.LastName));
350
351 // m_log.DebugFormat("[HG ASSET MAPPER]: Reset sopDepth");
352 sopDepth = -1;
353 creator = null;
354 hasCreatorData = false;
355 }
356 writer.WriteEndElement();
357 break;
358
359 case XmlNodeType.EntityReference:
360 writer.WriteEntityRef(reader.Name);
361 break;
362
363 case XmlNodeType.ProcessingInstruction:
364 writer.WriteProcessingInstruction(reader.Name, reader.Value);
365 break;
366
367 case XmlNodeType.Text:
368 writer.WriteString(reader.Value);
369 break;
370
371 case XmlNodeType.XmlDeclaration:
372 // For various reasons, not all serializations have xml declarations (or consistent ones)
373 // and as it's embedded inside a byte stream we don't need it anyway, so ignore.
374 break;
375
376 default:
377 m_log.WarnFormat(
378 "[HG ASSET MAPPER]: Unrecognized node {0} in asset XML transform in {1}",
379 reader.NodeType, sceneName);
380 break;
381 }
382 }
383 }
384
385 public static string CalcCreatorData(string homeURL, string name)
386 {
387 return homeURL + ";" + name;
388 }
389
390 internal static string CalcCreatorData(string homeURL, UUID uuid, string name)
391 {
392 return homeURL + "/" + uuid + ";" + name;
393 }
394
395 /// <summary>
396 /// Sanitation for bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8)
397 /// </summary>
398 /// <param name="xmlData"></param>
399 /// <returns></returns>
400 public static string SanitizeXml(string xmlData)
401 {
402 string fixedData = xmlData;
403 if (fixedData != null)
404 // Loop, because it may contain multiple
405 while (fixedData.Contains("xmlns:xmlns:"))
406 fixedData = fixedData.Replace("xmlns:xmlns:", "xmlns:");
407 return fixedData;
408 }
409
175 } 410 }
176} \ No newline at end of file 411}
diff --git a/OpenSim/Framework/Serialization/External/LandDataSerializer.cs b/OpenSim/Framework/Serialization/External/LandDataSerializer.cs
index 709b516..e42d56f 100644
--- a/OpenSim/Framework/Serialization/External/LandDataSerializer.cs
+++ b/OpenSim/Framework/Serialization/External/LandDataSerializer.cs
@@ -44,11 +44,11 @@ namespace OpenSim.Framework.Serialization.External
44 { 44 {
45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 private static Dictionary<string, Action<LandData, XmlTextReader>> m_ldProcessors 47 private static Dictionary<string, Action<LandData, XmlReader>> m_ldProcessors
48 = new Dictionary<string, Action<LandData, XmlTextReader>>(); 48 = new Dictionary<string, Action<LandData, XmlReader>>();
49 49
50 private static Dictionary<string, Action<LandAccessEntry, XmlTextReader>> m_laeProcessors 50 private static Dictionary<string, Action<LandAccessEntry, XmlReader>> m_laeProcessors
51 = new Dictionary<string, Action<LandAccessEntry, XmlTextReader>>(); 51 = new Dictionary<string, Action<LandAccessEntry, XmlReader>>();
52 52
53 static LandDataSerializer() 53 static LandDataSerializer()
54 { 54 {
@@ -134,7 +134,7 @@ namespace OpenSim.Framework.Serialization.External
134 "AccessList", (lae, xtr) => lae.Flags = (AccessList)Convert.ToUInt32(xtr.ReadElementString("AccessList"))); 134 "AccessList", (lae, xtr) => lae.Flags = (AccessList)Convert.ToUInt32(xtr.ReadElementString("AccessList")));
135 } 135 }
136 136
137 public static void ProcessParcelAccessList(LandData ld, XmlTextReader xtr) 137 public static void ProcessParcelAccessList(LandData ld, XmlReader xtr)
138 { 138 {
139 if (!xtr.IsEmptyElement) 139 if (!xtr.IsEmptyElement)
140 { 140 {
@@ -213,8 +213,13 @@ namespace OpenSim.Framework.Serialization.External
213 xtw.WriteElementString("ClaimDate", Convert.ToString(landData.ClaimDate)); 213 xtw.WriteElementString("ClaimDate", Convert.ToString(landData.ClaimDate));
214 xtw.WriteElementString("ClaimPrice", Convert.ToString(landData.ClaimPrice)); 214 xtw.WriteElementString("ClaimPrice", Convert.ToString(landData.ClaimPrice));
215 xtw.WriteElementString("GlobalID", landData.GlobalID.ToString()); 215 xtw.WriteElementString("GlobalID", landData.GlobalID.ToString());
216 xtw.WriteElementString("GroupID", landData.GroupID.ToString()); 216
217 xtw.WriteElementString("IsGroupOwned", Convert.ToString(landData.IsGroupOwned)); 217 UUID groupID = options.ContainsKey("wipe-owners") ? UUID.Zero : landData.GroupID;
218 xtw.WriteElementString("GroupID", groupID.ToString());
219
220 bool isGroupOwned = options.ContainsKey("wipe-owners") ? false : landData.IsGroupOwned;
221 xtw.WriteElementString("IsGroupOwned", Convert.ToString(isGroupOwned));
222
218 xtw.WriteElementString("Bitmap", Convert.ToBase64String(landData.Bitmap)); 223 xtw.WriteElementString("Bitmap", Convert.ToBase64String(landData.Bitmap));
219 xtw.WriteElementString("Description", landData.Description); 224 xtw.WriteElementString("Description", landData.Description);
220 xtw.WriteElementString("Flags", Convert.ToString((uint)landData.Flags)); 225 xtw.WriteElementString("Flags", Convert.ToString((uint)landData.Flags));
@@ -227,13 +232,8 @@ namespace OpenSim.Framework.Serialization.External
227 xtw.WriteElementString("MediaURL", landData.MediaURL); 232 xtw.WriteElementString("MediaURL", landData.MediaURL);
228 xtw.WriteElementString("MusicURL", landData.MusicURL); 233 xtw.WriteElementString("MusicURL", landData.MusicURL);
229 234
230 UUID ownerIdToWrite; 235 UUID ownerID = options.ContainsKey("wipe-owners") ? UUID.Zero : landData.OwnerID;
231 if (options != null && options.ContainsKey("wipe-owners")) 236 xtw.WriteElementString("OwnerID", ownerID.ToString());
232 ownerIdToWrite = UUID.Zero;
233 else
234 ownerIdToWrite = landData.OwnerID;
235
236 xtw.WriteElementString("OwnerID", ownerIdToWrite.ToString());
237 237
238 xtw.WriteStartElement("ParcelAccessList"); 238 xtw.WriteStartElement("ParcelAccessList");
239 foreach (LandAccessEntry pal in landData.ParcelAccessList) 239 foreach (LandAccessEntry pal in landData.ParcelAccessList)
diff --git a/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs b/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs
index f2a6b8b..994cede 100644
--- a/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs
+++ b/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs
@@ -46,8 +46,8 @@ namespace OpenSim.Framework.Serialization.External
46 { 46 {
47// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private static Dictionary<string, Action<InventoryItemBase, XmlTextReader>> m_InventoryItemXmlProcessors 49 private static Dictionary<string, Action<InventoryItemBase, XmlReader>> m_InventoryItemXmlProcessors
50 = new Dictionary<string, Action<InventoryItemBase, XmlTextReader>>(); 50 = new Dictionary<string, Action<InventoryItemBase, XmlReader>>();
51 51
52 #region InventoryItemBase Processor initialization 52 #region InventoryItemBase Processor initialization
53 static UserInventoryItemSerializer() 53 static UserInventoryItemSerializer()
@@ -76,103 +76,103 @@ namespace OpenSim.Framework.Serialization.External
76 #endregion 76 #endregion
77 77
78 #region InventoryItemBase Processors 78 #region InventoryItemBase Processors
79 private static void ProcessName(InventoryItemBase item, XmlTextReader reader) 79 private static void ProcessName(InventoryItemBase item, XmlReader reader)
80 { 80 {
81 item.Name = reader.ReadElementContentAsString("Name", String.Empty); 81 item.Name = reader.ReadElementContentAsString("Name", String.Empty);
82 } 82 }
83 83
84 private static void ProcessID(InventoryItemBase item, XmlTextReader reader) 84 private static void ProcessID(InventoryItemBase item, XmlReader reader)
85 { 85 {
86 item.ID = Util.ReadUUID(reader, "ID"); 86 item.ID = Util.ReadUUID(reader, "ID");
87 } 87 }
88 88
89 private static void ProcessInvType(InventoryItemBase item, XmlTextReader reader) 89 private static void ProcessInvType(InventoryItemBase item, XmlReader reader)
90 { 90 {
91 item.InvType = reader.ReadElementContentAsInt("InvType", String.Empty); 91 item.InvType = reader.ReadElementContentAsInt("InvType", String.Empty);
92 } 92 }
93 93
94 private static void ProcessCreatorUUID(InventoryItemBase item, XmlTextReader reader) 94 private static void ProcessCreatorUUID(InventoryItemBase item, XmlReader reader)
95 { 95 {
96 item.CreatorId = reader.ReadElementContentAsString("CreatorUUID", String.Empty); 96 item.CreatorId = reader.ReadElementContentAsString("CreatorUUID", String.Empty);
97 } 97 }
98 98
99 private static void ProcessCreatorID(InventoryItemBase item, XmlTextReader reader) 99 private static void ProcessCreatorID(InventoryItemBase item, XmlReader reader)
100 { 100 {
101 // when it exists, this overrides the previous 101 // when it exists, this overrides the previous
102 item.CreatorId = reader.ReadElementContentAsString("CreatorID", String.Empty); 102 item.CreatorId = reader.ReadElementContentAsString("CreatorID", String.Empty);
103 } 103 }
104 104
105 private static void ProcessCreationDate(InventoryItemBase item, XmlTextReader reader) 105 private static void ProcessCreationDate(InventoryItemBase item, XmlReader reader)
106 { 106 {
107 item.CreationDate = reader.ReadElementContentAsInt("CreationDate", String.Empty); 107 item.CreationDate = reader.ReadElementContentAsInt("CreationDate", String.Empty);
108 } 108 }
109 109
110 private static void ProcessOwner(InventoryItemBase item, XmlTextReader reader) 110 private static void ProcessOwner(InventoryItemBase item, XmlReader reader)
111 { 111 {
112 item.Owner = Util.ReadUUID(reader, "Owner"); 112 item.Owner = Util.ReadUUID(reader, "Owner");
113 } 113 }
114 114
115 private static void ProcessDescription(InventoryItemBase item, XmlTextReader reader) 115 private static void ProcessDescription(InventoryItemBase item, XmlReader reader)
116 { 116 {
117 item.Description = reader.ReadElementContentAsString("Description", String.Empty); 117 item.Description = reader.ReadElementContentAsString("Description", String.Empty);
118 } 118 }
119 119
120 private static void ProcessAssetType(InventoryItemBase item, XmlTextReader reader) 120 private static void ProcessAssetType(InventoryItemBase item, XmlReader reader)
121 { 121 {
122 item.AssetType = reader.ReadElementContentAsInt("AssetType", String.Empty); 122 item.AssetType = reader.ReadElementContentAsInt("AssetType", String.Empty);
123 } 123 }
124 124
125 private static void ProcessAssetID(InventoryItemBase item, XmlTextReader reader) 125 private static void ProcessAssetID(InventoryItemBase item, XmlReader reader)
126 { 126 {
127 item.AssetID = Util.ReadUUID(reader, "AssetID"); 127 item.AssetID = Util.ReadUUID(reader, "AssetID");
128 } 128 }
129 129
130 private static void ProcessSaleType(InventoryItemBase item, XmlTextReader reader) 130 private static void ProcessSaleType(InventoryItemBase item, XmlReader reader)
131 { 131 {
132 item.SaleType = (byte)reader.ReadElementContentAsInt("SaleType", String.Empty); 132 item.SaleType = (byte)reader.ReadElementContentAsInt("SaleType", String.Empty);
133 } 133 }
134 134
135 private static void ProcessSalePrice(InventoryItemBase item, XmlTextReader reader) 135 private static void ProcessSalePrice(InventoryItemBase item, XmlReader reader)
136 { 136 {
137 item.SalePrice = reader.ReadElementContentAsInt("SalePrice", String.Empty); 137 item.SalePrice = reader.ReadElementContentAsInt("SalePrice", String.Empty);
138 } 138 }
139 139
140 private static void ProcessBasePermissions(InventoryItemBase item, XmlTextReader reader) 140 private static void ProcessBasePermissions(InventoryItemBase item, XmlReader reader)
141 { 141 {
142 item.BasePermissions = (uint)reader.ReadElementContentAsInt("BasePermissions", String.Empty); 142 item.BasePermissions = (uint)reader.ReadElementContentAsInt("BasePermissions", String.Empty);
143 } 143 }
144 144
145 private static void ProcessCurrentPermissions(InventoryItemBase item, XmlTextReader reader) 145 private static void ProcessCurrentPermissions(InventoryItemBase item, XmlReader reader)
146 { 146 {
147 item.CurrentPermissions = (uint)reader.ReadElementContentAsInt("CurrentPermissions", String.Empty); 147 item.CurrentPermissions = (uint)reader.ReadElementContentAsInt("CurrentPermissions", String.Empty);
148 } 148 }
149 149
150 private static void ProcessEveryOnePermissions(InventoryItemBase item, XmlTextReader reader) 150 private static void ProcessEveryOnePermissions(InventoryItemBase item, XmlReader reader)
151 { 151 {
152 item.EveryOnePermissions = (uint)reader.ReadElementContentAsInt("EveryOnePermissions", String.Empty); 152 item.EveryOnePermissions = (uint)reader.ReadElementContentAsInt("EveryOnePermissions", String.Empty);
153 } 153 }
154 154
155 private static void ProcessNextPermissions(InventoryItemBase item, XmlTextReader reader) 155 private static void ProcessNextPermissions(InventoryItemBase item, XmlReader reader)
156 { 156 {
157 item.NextPermissions = (uint)reader.ReadElementContentAsInt("NextPermissions", String.Empty); 157 item.NextPermissions = (uint)reader.ReadElementContentAsInt("NextPermissions", String.Empty);
158 } 158 }
159 159
160 private static void ProcessFlags(InventoryItemBase item, XmlTextReader reader) 160 private static void ProcessFlags(InventoryItemBase item, XmlReader reader)
161 { 161 {
162 item.Flags = (uint)reader.ReadElementContentAsInt("Flags", String.Empty); 162 item.Flags = (uint)reader.ReadElementContentAsInt("Flags", String.Empty);
163 } 163 }
164 164
165 private static void ProcessGroupID(InventoryItemBase item, XmlTextReader reader) 165 private static void ProcessGroupID(InventoryItemBase item, XmlReader reader)
166 { 166 {
167 item.GroupID = Util.ReadUUID(reader, "GroupID"); 167 item.GroupID = Util.ReadUUID(reader, "GroupID");
168 } 168 }
169 169
170 private static void ProcessGroupOwned(InventoryItemBase item, XmlTextReader reader) 170 private static void ProcessGroupOwned(InventoryItemBase item, XmlReader reader)
171 { 171 {
172 item.GroupOwned = Util.ReadBoolean(reader); 172 item.GroupOwned = Util.ReadBoolean(reader);
173 } 173 }
174 174
175 private static void ProcessCreatorData(InventoryItemBase item, XmlTextReader reader) 175 private static void ProcessCreatorData(InventoryItemBase item, XmlReader reader)
176 { 176 {
177 item.CreatorData = reader.ReadElementContentAsString("CreatorData", String.Empty); 177 item.CreatorData = reader.ReadElementContentAsString("CreatorData", String.Empty);
178 } 178 }
@@ -286,7 +286,8 @@ namespace OpenSim.Framework.Serialization.External
286 UserAccount account = userAccountService.GetUserAccount(UUID.Zero, inventoryItem.CreatorIdAsUuid); 286 UserAccount account = userAccountService.GetUserAccount(UUID.Zero, inventoryItem.CreatorIdAsUuid);
287 if (account != null) 287 if (account != null)
288 { 288 {
289 writer.WriteElementString("CreatorData", (string)options["home"] + "/" + inventoryItem.CreatorIdAsUuid + ";" + account.FirstName + " " + account.LastName); 289 string creatorData = ExternalRepresentationUtils.CalcCreatorData((string)options["home"], inventoryItem.CreatorIdAsUuid, account.FirstName + " " + account.LastName);
290 writer.WriteElementString("CreatorData", creatorData);
290 } 291 }
291 writer.WriteElementString("CreatorID", inventoryItem.CreatorId); 292 writer.WriteElementString("CreatorID", inventoryItem.CreatorId);
292 } 293 }
diff --git a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
index 3f04148..0cce722 100644
--- a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.0.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs b/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs
index ea100ee..e81cb78 100644
--- a/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs
+++ b/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs
@@ -121,7 +121,8 @@ namespace OpenSim.Framework.Serialization.Tests
121 TestHelpers.InMethod(); 121 TestHelpers.InMethod();
122// log4net.Config.XmlConfigurator.Configure(); 122// log4net.Config.XmlConfigurator.Configure();
123 123
124 LandData ld = LandDataSerializer.Deserialize(LandDataSerializer.Serialize(this.land, null)); 124 Dictionary<string, object> options = new Dictionary<string, object>();
125 LandData ld = LandDataSerializer.Deserialize(LandDataSerializer.Serialize(this.land, options));
125 Assert.That(ld, Is.Not.Null, "Deserialize(string) returned null"); 126 Assert.That(ld, Is.Not.Null, "Deserialize(string) returned null");
126// Assert.That(ld.AABBMax, Is.EqualTo(land.AABBMax)); 127// Assert.That(ld.AABBMax, Is.EqualTo(land.AABBMax));
127// Assert.That(ld.AABBMin, Is.EqualTo(land.AABBMin)); 128// Assert.That(ld.AABBMin, Is.EqualTo(land.AABBMin));
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 3055865..60702d4 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -45,6 +45,7 @@ using OpenSim.Framework.Monitoring;
45using OpenSim.Framework.Servers; 45using OpenSim.Framework.Servers;
46using OpenSim.Framework.Servers.HttpServer; 46using OpenSim.Framework.Servers.HttpServer;
47using Timer=System.Timers.Timer; 47using Timer=System.Timers.Timer;
48using Nini.Config;
48 49
49namespace OpenSim.Framework.Servers 50namespace OpenSim.Framework.Servers
50{ 51{
@@ -56,10 +57,20 @@ namespace OpenSim.Framework.Servers
56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 57 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57 58
58 /// <summary> 59 /// <summary>
60 /// Used by tests to suppress Environment.Exit(0) so that post-run operations are possible.
61 /// </summary>
62 public bool SuppressExit { get; set; }
63
64 /// <summary>
59 /// This will control a periodic log printout of the current 'show stats' (if they are active) for this 65 /// This will control a periodic log printout of the current 'show stats' (if they are active) for this
60 /// server. 66 /// server.
61 /// </summary> 67 /// </summary>
68<<<<<<< HEAD
69 private int m_periodDiagnosticTimerMS = 60 * 60 * 1000;
70 private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000);
71=======
62// private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000); 72// private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000);
73>>>>>>> avn/ubitvar
63 74
64 /// <summary> 75 /// <summary>
65 /// Random uuid for private data 76 /// Random uuid for private data
@@ -77,8 +88,11 @@ namespace OpenSim.Framework.Servers
77 // Random uuid for private data 88 // Random uuid for private data
78 m_osSecret = UUID.Random().ToString(); 89 m_osSecret = UUID.Random().ToString();
79 90
91<<<<<<< HEAD
92=======
80// m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics); 93// m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics);
81// m_periodicDiagnosticsTimer.Enabled = true; 94// m_periodicDiagnosticsTimer.Enabled = true;
95>>>>>>> avn/ubitvar
82 } 96 }
83 97
84 /// <summary> 98 /// <summary>
@@ -89,6 +103,16 @@ namespace OpenSim.Framework.Servers
89 StatsManager.SimExtraStats = new SimExtraStatsCollector(); 103 StatsManager.SimExtraStats = new SimExtraStatsCollector();
90 RegisterCommonCommands(); 104 RegisterCommonCommands();
91 RegisterCommonComponents(Config); 105 RegisterCommonComponents(Config);
106
107 IConfig startupConfig = Config.Configs["Startup"];
108 int logShowStatsSeconds = startupConfig.GetInt("LogShowStatsSeconds", m_periodDiagnosticTimerMS / 1000);
109 m_periodDiagnosticTimerMS = logShowStatsSeconds * 1000;
110 m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics);
111 if (m_periodDiagnosticTimerMS != 0)
112 {
113 m_periodicDiagnosticsTimer.Interval = m_periodDiagnosticTimerMS;
114 m_periodicDiagnosticsTimer.Enabled = true;
115 }
92 } 116 }
93 117
94 protected override void ShutdownSpecific() 118 protected override void ShutdownSpecific()
@@ -99,7 +123,8 @@ namespace OpenSim.Framework.Servers
99 123
100 base.ShutdownSpecific(); 124 base.ShutdownSpecific();
101 125
102 Environment.Exit(0); 126 if (!SuppressExit)
127 Environment.Exit(0);
103 } 128 }
104 129
105 /// <summary> 130 /// <summary>
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 1363eab..616c673 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -46,6 +46,7 @@ using CoolHTTPListener = HttpServer.HttpListener;
46using HttpListener=System.Net.HttpListener; 46using HttpListener=System.Net.HttpListener;
47using LogPrio=HttpServer.LogPrio; 47using LogPrio=HttpServer.LogPrio;
48using OpenSim.Framework.Monitoring; 48using OpenSim.Framework.Monitoring;
49using System.IO.Compression;
49 50
50namespace OpenSim.Framework.Servers.HttpServer 51namespace OpenSim.Framework.Servers.HttpServer
51{ 52{
@@ -53,6 +54,7 @@ namespace OpenSim.Framework.Servers.HttpServer
53 { 54 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); 56 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
57 private static Encoding UTF8NoBOM = new System.Text.UTF8Encoding(false);
56 58
57 /// <summary> 59 /// <summary>
58 /// This is a pending websocket request before it got an sucessful upgrade response. 60 /// This is a pending websocket request before it got an sucessful upgrade response.
@@ -113,7 +115,7 @@ namespace OpenSim.Framework.Servers.HttpServer
113 115
114 protected IPAddress m_listenIPAddress = IPAddress.Any; 116 protected IPAddress m_listenIPAddress = IPAddress.Any;
115 117
116 private PollServiceRequestManager m_PollServiceManager; 118 public PollServiceRequestManager PollServiceRequestManager { get; private set; }
117 119
118 public uint SSLPort 120 public uint SSLPort
119 { 121 {
@@ -374,7 +376,7 @@ namespace OpenSim.Framework.Servers.HttpServer
374 return true; 376 return true;
375 } 377 }
376 378
377 private void OnRequest(object source, RequestEventArgs args) 379 public void OnRequest(object source, RequestEventArgs args)
378 { 380 {
379 RequestNumber++; 381 RequestNumber++;
380 382
@@ -430,7 +432,7 @@ namespace OpenSim.Framework.Servers.HttpServer
430 psEvArgs.Request(psreq.RequestID, keysvals); 432 psEvArgs.Request(psreq.RequestID, keysvals);
431 } 433 }
432 434
433 m_PollServiceManager.Enqueue(psreq); 435 PollServiceRequestManager.Enqueue(psreq);
434 } 436 }
435 else 437 else
436 { 438 {
@@ -492,8 +494,8 @@ namespace OpenSim.Framework.Servers.HttpServer
492 try 494 try
493 { 495 {
494 byte[] buffer500 = SendHTML500(response); 496 byte[] buffer500 = SendHTML500(response);
495 response.Body.Write(buffer500,0,buffer500.Length); 497 response.OutputStream.Write(buffer500, 0, buffer500.Length);
496 response.Body.Close(); 498 response.Send();
497 } 499 }
498 catch 500 catch
499 { 501 {
@@ -691,6 +693,23 @@ namespace OpenSim.Framework.Servers.HttpServer
691 693
692 if (buffer != null) 694 if (buffer != null)
693 { 695 {
696 if (WebUtil.DebugLevel >= 5)
697 {
698 string output = System.Text.Encoding.UTF8.GetString(buffer);
699
700 if (WebUtil.DebugLevel >= 6)
701 {
702 // Always truncate binary blobs. We don't have a ContentType, so detect them using the request name.
703 if ((requestHandler != null && requestHandler.Name == "GetMesh"))
704 {
705 if (output.Length > WebUtil.MaxRequestDiagLength)
706 output = output.Substring(0, WebUtil.MaxRequestDiagLength) + "...";
707 }
708 }
709
710 WebUtil.LogResponseDetail(RequestNumber, output);
711 }
712
694 if (!response.SendChunked && response.ContentLength64 <= 0) 713 if (!response.SendChunked && response.ContentLength64 <= 0)
695 response.ContentLength64 = buffer.LongLength; 714 response.ContentLength64 = buffer.LongLength;
696 715
@@ -721,16 +740,16 @@ namespace OpenSim.Framework.Servers.HttpServer
721 } 740 }
722 catch (IOException e) 741 catch (IOException e)
723 { 742 {
724 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); 743 m_log.Error("[BASE HTTP SERVER]: HandleRequest() threw exception ", e);
725 } 744 }
726 catch (Exception e) 745 catch (Exception e)
727 { 746 {
728 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); 747 m_log.Error("[BASE HTTP SERVER]: HandleRequest() threw exception ", e);
729 try 748 try
730 { 749 {
731 byte[] buffer500 = SendHTML500(response); 750 byte[] buffer500 = SendHTML500(response);
732 response.Body.Write(buffer500, 0, buffer500.Length); 751 response.OutputStream.Write(buffer500, 0, buffer500.Length);
733 response.Body.Close(); 752 response.Send();
734 } 753 }
735 catch 754 catch
736 { 755 {
@@ -744,7 +763,7 @@ namespace OpenSim.Framework.Servers.HttpServer
744 if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture")) 763 if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture"))
745 { 764 {
746 m_log.InfoFormat( 765 m_log.InfoFormat(
747 "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms", 766 "[LOGHTTP] Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms",
748 RequestNumber, 767 RequestNumber,
749 requestMethod, 768 requestMethod,
750 uriString, 769 uriString,
@@ -756,7 +775,7 @@ namespace OpenSim.Framework.Servers.HttpServer
756 else if (DebugLevel >= 4) 775 else if (DebugLevel >= 4)
757 { 776 {
758 m_log.DebugFormat( 777 m_log.DebugFormat(
759 "[BASE HTTP SERVER]: HTTP IN {0} :{1} took {2}ms", 778 "[LOGHTTP] HTTP IN {0} :{1} took {2}ms",
760 RequestNumber, 779 RequestNumber,
761 Port, 780 Port,
762 tickdiff); 781 tickdiff);
@@ -767,7 +786,7 @@ namespace OpenSim.Framework.Servers.HttpServer
767 private void LogIncomingToStreamHandler(OSHttpRequest request, IRequestHandler requestHandler) 786 private void LogIncomingToStreamHandler(OSHttpRequest request, IRequestHandler requestHandler)
768 { 787 {
769 m_log.DebugFormat( 788 m_log.DebugFormat(
770 "[BASE HTTP SERVER]: HTTP IN {0} :{1} stream handler {2} {3} {4} {5} from {6}", 789 "[LOGHTTP] HTTP IN {0} :{1} stream handler {2} {3} {4} {5} from {6}",
771 RequestNumber, 790 RequestNumber,
772 Port, 791 Port,
773 request.HttpMethod, 792 request.HttpMethod,
@@ -783,7 +802,7 @@ namespace OpenSim.Framework.Servers.HttpServer
783 private void LogIncomingToContentTypeHandler(OSHttpRequest request) 802 private void LogIncomingToContentTypeHandler(OSHttpRequest request)
784 { 803 {
785 m_log.DebugFormat( 804 m_log.DebugFormat(
786 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}", 805 "[LOGHTTP] HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
787 RequestNumber, 806 RequestNumber,
788 Port, 807 Port,
789 string.IsNullOrEmpty(request.ContentType) ? "not set" : request.ContentType, 808 string.IsNullOrEmpty(request.ContentType) ? "not set" : request.ContentType,
@@ -798,7 +817,7 @@ namespace OpenSim.Framework.Servers.HttpServer
798 private void LogIncomingToXmlRpcHandler(OSHttpRequest request) 817 private void LogIncomingToXmlRpcHandler(OSHttpRequest request)
799 { 818 {
800 m_log.DebugFormat( 819 m_log.DebugFormat(
801 "[BASE HTTP SERVER]: HTTP IN {0} :{1} assumed generic XMLRPC request {2} {3} from {4}", 820 "[LOGHTTP] HTTP IN {0} :{1} assumed generic XMLRPC request {2} {3} from {4}",
802 RequestNumber, 821 RequestNumber,
803 Port, 822 Port,
804 request.HttpMethod, 823 request.HttpMethod,
@@ -811,29 +830,49 @@ namespace OpenSim.Framework.Servers.HttpServer
811 830
812 private void LogIncomingInDetail(OSHttpRequest request) 831 private void LogIncomingInDetail(OSHttpRequest request)
813 { 832 {
814 using (StreamReader reader = new StreamReader(Util.Copy(request.InputStream), Encoding.UTF8)) 833 if (request.ContentType == "application/octet-stream")
815 { 834 return; // never log these; they're just binary data
816 string output;
817 835
818 if (DebugLevel == 5) 836 Stream inputStream = Util.Copy(request.InputStream);
837 Stream innerStream = null;
838 try
839 {
840 if ((request.Headers["Content-Encoding"] == "gzip") || (request.Headers["X-Content-Encoding"] == "gzip"))
819 { 841 {
820 const int sampleLength = 80; 842 innerStream = inputStream;
821 char[] sampleChars = new char[sampleLength + 3]; 843 inputStream = new GZipStream(innerStream, System.IO.Compression.CompressionMode.Decompress);
822 reader.Read(sampleChars, 0, sampleLength);
823 sampleChars[80] = '.';
824 sampleChars[81] = '.';
825 sampleChars[82] = '.';
826 output = new string(sampleChars);
827 } 844 }
828 else 845
846 using (StreamReader reader = new StreamReader(inputStream, Encoding.UTF8))
829 { 847 {
830 output = reader.ReadToEnd(); 848 string output;
831 } 849
850 if (DebugLevel == 5)
851 {
852 char[] chars = new char[WebUtil.MaxRequestDiagLength + 1]; // +1 so we know to add "..." only if needed
853 int len = reader.Read(chars, 0, WebUtil.MaxRequestDiagLength + 1);
854 output = new string(chars, 0, Math.Min(len, WebUtil.MaxRequestDiagLength));
855 if (len > WebUtil.MaxRequestDiagLength)
856 output += "...";
857 }
858 else
859 {
860 output = reader.ReadToEnd();
861 }
832 862
833 m_log.DebugFormat("[BASE HTTP SERVER]: {0}", output.Replace("\n", @"\n")); 863 m_log.DebugFormat("[LOGHTTP] {0}", Util.BinaryToASCII(output));
864 }
865 }
866 finally
867 {
868 if (innerStream != null)
869 innerStream.Dispose();
870 inputStream.Dispose();
834 } 871 }
835 } 872 }
836 873
874 private readonly string HANDLER_SEPARATORS = "/?&#-";
875
837 private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler) 876 private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler)
838 { 877 {
839 string bestMatch = null; 878 string bestMatch = null;
@@ -842,7 +881,8 @@ namespace OpenSim.Framework.Servers.HttpServer
842 { 881 {
843 foreach (string pattern in m_streamHandlers.Keys) 882 foreach (string pattern in m_streamHandlers.Keys)
844 { 883 {
845 if (handlerKey.StartsWith(pattern)) 884 if ((handlerKey == pattern)
885 || (handlerKey.StartsWith(pattern) && (HANDLER_SEPARATORS.IndexOf(handlerKey[pattern.Length]) >= 0)))
846 { 886 {
847 if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length) 887 if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length)
848 { 888 {
@@ -872,7 +912,8 @@ namespace OpenSim.Framework.Servers.HttpServer
872 { 912 {
873 foreach (string pattern in m_pollHandlers.Keys) 913 foreach (string pattern in m_pollHandlers.Keys)
874 { 914 {
875 if (handlerKey.StartsWith(pattern)) 915 if ((handlerKey == pattern)
916 || (handlerKey.StartsWith(pattern) && (HANDLER_SEPARATORS.IndexOf(handlerKey[pattern.Length]) >= 0)))
876 { 917 {
877 if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length) 918 if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length)
878 { 919 {
@@ -904,7 +945,8 @@ namespace OpenSim.Framework.Servers.HttpServer
904 { 945 {
905 foreach (string pattern in m_HTTPHandlers.Keys) 946 foreach (string pattern in m_HTTPHandlers.Keys)
906 { 947 {
907 if (handlerKey.StartsWith(pattern)) 948 if ((handlerKey == pattern)
949 || (handlerKey.StartsWith(pattern) && (HANDLER_SEPARATORS.IndexOf(handlerKey[pattern.Length]) >= 0)))
908 { 950 {
909 if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length) 951 if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length)
910 { 952 {
@@ -953,16 +995,33 @@ namespace OpenSim.Framework.Servers.HttpServer
953 /// <param name="response"></param> 995 /// <param name="response"></param>
954 private byte[] HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response) 996 private byte[] HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response)
955 { 997 {
998 String requestBody;
999
956 Stream requestStream = request.InputStream; 1000 Stream requestStream = request.InputStream;
1001 Stream innerStream = null;
1002 try
1003 {
1004 if ((request.Headers["Content-Encoding"] == "gzip") || (request.Headers["X-Content-Encoding"] == "gzip"))
1005 {
1006 innerStream = requestStream;
1007 requestStream = new GZipStream(innerStream, System.IO.Compression.CompressionMode.Decompress);
1008 }
957 1009
958 Encoding encoding = Encoding.UTF8; 1010 using (StreamReader reader = new StreamReader(requestStream, Encoding.UTF8))
959 StreamReader reader = new StreamReader(requestStream, encoding); 1011 {
1012 requestBody = reader.ReadToEnd();
1013 }
1014 }
1015 finally
1016 {
1017 if (innerStream != null)
1018 innerStream.Dispose();
1019 requestStream.Dispose();
1020 }
960 1021
961 string requestBody = reader.ReadToEnd();
962 reader.Close();
963 requestStream.Close();
964 //m_log.Debug(requestBody); 1022 //m_log.Debug(requestBody);
965 requestBody = requestBody.Replace("<base64></base64>", ""); 1023 requestBody = requestBody.Replace("<base64></base64>", "");
1024
966 string responseString = String.Empty; 1025 string responseString = String.Empty;
967 XmlRpcRequest xmlRprcRequest = null; 1026 XmlRpcRequest xmlRprcRequest = null;
968 1027
@@ -1073,18 +1132,16 @@ namespace OpenSim.Framework.Servers.HttpServer
1073 1132
1074 response.ContentType = "text/xml"; 1133 response.ContentType = "text/xml";
1075 using (MemoryStream outs = new MemoryStream()) 1134 using (MemoryStream outs = new MemoryStream())
1135 using (XmlTextWriter writer = new XmlTextWriter(outs, UTF8NoBOM))
1076 { 1136 {
1077 using (XmlTextWriter writer = new XmlTextWriter(outs, Encoding.UTF8)) 1137 writer.Formatting = Formatting.None;
1138 XmlRpcResponseSerializer.Singleton.Serialize(writer, xmlRpcResponse);
1139 writer.Flush();
1140 outs.Flush();
1141 outs.Position = 0;
1142 using (StreamReader sr = new StreamReader(outs))
1078 { 1143 {
1079 writer.Formatting = Formatting.None; 1144 responseString = sr.ReadToEnd();
1080 XmlRpcResponseSerializer.Singleton.Serialize(writer, xmlRpcResponse);
1081 writer.Flush();
1082 outs.Flush();
1083 outs.Position = 0;
1084 using (StreamReader sr = new StreamReader(outs))
1085 {
1086 responseString = sr.ReadToEnd();
1087 }
1088 } 1145 }
1089 } 1146 }
1090 } 1147 }
@@ -1842,10 +1899,17 @@ namespace OpenSim.Framework.Servers.HttpServer
1842 1899
1843 public void Start() 1900 public void Start()
1844 { 1901 {
1845 StartHTTP(); 1902 Start(true);
1846 } 1903 }
1847 1904
1848 private void StartHTTP() 1905 /// <summary>
1906 /// Start the http server
1907 /// </summary>
1908 /// <param name='processPollRequestsAsync'>
1909 /// If true then poll responses are performed asynchronsly.
1910 /// Option exists to allow regression tests to perform processing synchronously.
1911 /// </param>
1912 public void Start(bool performPollResponsesAsync)
1849 { 1913 {
1850 m_log.InfoFormat( 1914 m_log.InfoFormat(
1851 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port); 1915 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port);
@@ -1883,8 +1947,14 @@ namespace OpenSim.Framework.Servers.HttpServer
1883 m_httpListener2.Start(64); 1947 m_httpListener2.Start(64);
1884 1948
1885 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events 1949 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
1950<<<<<<< HEAD
1951 PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 3, 25000);
1952 PollServiceRequestManager.Start();
1953
1954=======
1886 m_PollServiceManager = new PollServiceRequestManager(this, 4, 25000); 1955 m_PollServiceManager = new PollServiceRequestManager(this, 4, 25000);
1887 m_PollServiceManager.Start(); 1956 m_PollServiceManager.Start();
1957>>>>>>> avn/ubitvar
1888 HTTPDRunning = true; 1958 HTTPDRunning = true;
1889 1959
1890 //HttpListenerContext context; 1960 //HttpListenerContext context;
@@ -1955,7 +2025,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1955 2025
1956 try 2026 try
1957 { 2027 {
1958 m_PollServiceManager.Stop(); 2028 PollServiceRequestManager.Stop();
1959 2029
1960 m_httpListener2.ExceptionThrown -= httpServerException; 2030 m_httpListener2.ExceptionThrown -= httpServerException;
1961 //m_httpListener2.DisconnectHandler = null; 2031 //m_httpListener2.DisconnectHandler = null;
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
index bbac699..d4a1ec3 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using OpenSim.Framework.Monitoring;
29 30
30namespace OpenSim.Framework.Servers.HttpServer 31namespace OpenSim.Framework.Servers.HttpServer
31{ 32{
@@ -61,6 +62,24 @@ namespace OpenSim.Framework.Servers.HttpServer
61 Description = description; 62 Description = description;
62 m_httpMethod = httpMethod; 63 m_httpMethod = httpMethod;
63 m_path = path; 64 m_path = path;
65
66 // FIXME: A very temporary measure to stop the simulator stats being overwhelmed with user CAPS info.
67 // Needs to be fixed properly in stats display
68 if (!path.StartsWith("/CAPS/"))
69 {
70 StatsManager.RegisterStat(
71 new Stat(
72 "requests",
73 "requests",
74 "Number of requests received by this service endpoint",
75 "requests",
76 "service",
77 string.Format("{0}:{1}", httpMethod, path),
78 StatType.Pull,
79 MeasuresOfInterest.AverageChangeOverTime,
80 s => s.Value = RequestsReceived,
81 StatVerbosity.Debug));
82 }
64 } 83 }
65 84
66 public virtual string Path 85 public virtual string Path
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
index 252cc2a..41aa19b 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
@@ -26,6 +26,8 @@
26 */ 26 */
27 27
28using System.IO; 28using System.IO;
29using System.Net;
30using OpenSim.Framework.ServiceAuth;
29 31
30namespace OpenSim.Framework.Servers.HttpServer 32namespace OpenSim.Framework.Servers.HttpServer
31{ 33{
@@ -37,16 +39,36 @@ namespace OpenSim.Framework.Servers.HttpServer
37 /// </remarks> 39 /// </remarks>
38 public abstract class BaseStreamHandler : BaseRequestHandler, IStreamedRequestHandler 40 public abstract class BaseStreamHandler : BaseRequestHandler, IStreamedRequestHandler
39 { 41 {
40 protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {} 42 protected IServiceAuth m_Auth;
43
44 protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) { }
41 45
42 protected BaseStreamHandler(string httpMethod, string path, string name, string description) 46 protected BaseStreamHandler(string httpMethod, string path, string name, string description)
43 : base(httpMethod, path, name, description) {} 47 : base(httpMethod, path, name, description) {}
44 48
49 protected BaseStreamHandler(string httpMethod, string path, IServiceAuth auth)
50 : base(httpMethod, path, null, null)
51 {
52 m_Auth = auth;
53 }
54
45 public virtual byte[] Handle( 55 public virtual byte[] Handle(
46 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 56 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
47 { 57 {
48 RequestsReceived++; 58 RequestsReceived++;
49 59
60 if (m_Auth != null)
61 {
62 HttpStatusCode statusCode;
63
64 if (!m_Auth.Authenticate(httpRequest.Headers, httpResponse.AddHeader, out statusCode))
65 {
66 httpResponse.StatusCode = (int)statusCode;
67 httpResponse.ContentType = "text/plain";
68 return new byte[0];
69 }
70 }
71
50 byte[] result = ProcessRequest(path, request, httpRequest, httpResponse); 72 byte[] result = ProcessRequest(path, request, httpRequest, httpResponse);
51 73
52 RequestsHandled++; 74 RequestsHandled++;
diff --git a/OpenSim/Framework/Servers/HttpServer/JsonRpcRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/JsonRpcRequestManager.cs
new file mode 100644
index 0000000..2fe1a7d
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/JsonRpcRequestManager.cs
@@ -0,0 +1,190 @@
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
28using System;
29using System.Net;
30using System.Net.Sockets;
31using System.Reflection;
32using System.Text;
33using System.IO;
34using OpenMetaverse.StructuredData;
35using OpenMetaverse;
36using log4net;
37
38namespace OpenSim.Framework.Servers.HttpServer
39{
40 /// <summary>
41 /// Json rpc request manager.
42 /// </summary>
43 public class JsonRpcRequestManager
44 {
45 static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 public JsonRpcRequestManager()
48 {
49 }
50
51 /// <summary>
52 /// Sends json-rpc request with a serializable type.
53 /// </summary>
54 /// <returns>
55 /// OSD Map.
56 /// </returns>
57 /// <param name='parameters'>
58 /// Serializable type .
59 /// </param>
60 /// <param name='method'>
61 /// Json-rpc method to call.
62 /// </param>
63 /// <param name='uri'>
64 /// URI of json-rpc service.
65 /// </param>
66 /// <param name='jsonId'>
67 /// Id for our call.
68 /// </param>
69 public bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
70 {
71 if (jsonId == null)
72 throw new ArgumentNullException("jsonId");
73 if (uri == null)
74 throw new ArgumentNullException("uri");
75 if (method == null)
76 throw new ArgumentNullException("method");
77 if (parameters == null)
78 throw new ArgumentNullException("parameters");
79
80 OSDMap request = new OSDMap();
81 request.Add("jsonrpc", OSD.FromString("2.0"));
82 request.Add("id", OSD.FromString(jsonId));
83 request.Add("method", OSD.FromString(method));
84 request.Add("params", OSD.SerializeMembers(parameters));
85
86 OSDMap response;
87 try
88 {
89 response = WebUtil.PostToService(uri, request, 10000, true);
90 }
91 catch (Exception e)
92 {
93 m_log.Debug(string.Format("JsonRpc request '{0}' to {1} failed", method, uri), e);
94 return false;
95 }
96
97 if (!response.ContainsKey("_Result"))
98 {
99 m_log.DebugFormat("JsonRpc request '{0}' to {1} returned an invalid response: {2}",
100 method, uri, OSDParser.SerializeJsonString(response));
101 return false;
102 }
103 response = (OSDMap)response["_Result"];
104
105 OSD data;
106
107 if (response.ContainsKey("error"))
108 {
109 data = response["error"];
110 m_log.DebugFormat("JsonRpc request '{0}' to {1} returned an error: {2}",
111 method, uri, OSDParser.SerializeJsonString(data));
112 return false;
113 }
114
115 if (!response.ContainsKey("result"))
116 {
117 m_log.DebugFormat("JsonRpc request '{0}' to {1} returned an invalid response: {2}",
118 method, uri, OSDParser.SerializeJsonString(response));
119 return false;
120 }
121
122 data = response["result"];
123 OSD.DeserializeMembers(ref parameters, (OSDMap)data);
124
125 return true;
126 }
127
128 /// <summary>
129 /// Sends json-rpc request with OSD parameter.
130 /// </summary>
131 /// <returns>
132 /// The rpc request.
133 /// </returns>
134 /// <param name='data'>
135 /// data - incoming as parameters, outgoing as result/error
136 /// </param>
137 /// <param name='method'>
138 /// Json-rpc method to call.
139 /// </param>
140 /// <param name='uri'>
141 /// URI of json-rpc service.
142 /// </param>
143 /// <param name='jsonId'>
144 /// If set to <c>true</c> json identifier.
145 /// </param>
146 public bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
147 {
148 if (string.IsNullOrEmpty(jsonId))
149 jsonId = UUID.Random().ToString();
150
151 OSDMap request = new OSDMap();
152 request.Add("jsonrpc", OSD.FromString("2.0"));
153 request.Add("id", OSD.FromString(jsonId));
154 request.Add("method", OSD.FromString(method));
155 request.Add("params", data);
156
157 OSDMap response;
158 try
159 {
160 response = WebUtil.PostToService(uri, request, 10000, true);
161 }
162 catch (Exception e)
163 {
164 m_log.Debug(string.Format("JsonRpc request '{0}' to {1} failed", method, uri), e);
165 return false;
166 }
167
168 if (!response.ContainsKey("_Result"))
169 {
170 m_log.DebugFormat("JsonRpc request '{0}' to {1} returned an invalid response: {2}",
171 method, uri, OSDParser.SerializeJsonString(response));
172 return false;
173 }
174 response = (OSDMap)response["_Result"];
175
176 if (response.ContainsKey("error"))
177 {
178 data = response["error"];
179 m_log.DebugFormat("JsonRpc request '{0}' to {1} returned an error: {2}",
180 method, uri, OSDParser.SerializeJsonString(data));
181 return false;
182 }
183
184 data = response;
185
186 return true;
187 }
188
189 }
190}
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs
index 3171759..05ec6dc 100644
--- a/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs
@@ -182,11 +182,22 @@ namespace OpenSim.Framework.Servers.HttpServer
182 _context = context; 182 _context = context;
183 183
184 if (null != req.Headers["content-encoding"]) 184 if (null != req.Headers["content-encoding"])
185 _contentEncoding = Encoding.GetEncoding(_request.Headers["content-encoding"]); 185 {
186 try
187 {
188 _contentEncoding = Encoding.GetEncoding(_request.Headers["content-encoding"]);
189 }
190 catch (Exception)
191 {
192 // ignore
193 }
194 }
195
186 if (null != req.Headers["content-type"]) 196 if (null != req.Headers["content-type"])
187 _contentType = _request.Headers["content-type"]; 197 _contentType = _request.Headers["content-type"];
188 if (null != req.Headers["user-agent"]) 198 if (null != req.Headers["user-agent"])
189 _userAgent = req.Headers["user-agent"]; 199 _userAgent = req.Headers["user-agent"];
200
190 if (null != req.Headers["remote_addr"]) 201 if (null != req.Headers["remote_addr"])
191 { 202 {
192 try 203 try
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpRequestPump.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpRequestPump.cs
index 77cfb7e..bdea278 100644
--- a/OpenSim/Framework/Servers/HttpServer/OSHttpRequestPump.cs
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpRequestPump.cs
@@ -70,9 +70,9 @@ namespace OpenSim.Framework.Servers.HttpServer
70 _id = id; 70 _id = id;
71 71
72 _engine = new Thread(new ThreadStart(Engine)); 72 _engine = new Thread(new ThreadStart(Engine));
73 _engine.Name = EngineID;
74 _engine.IsBackground = true; 73 _engine.IsBackground = true;
75 _engine.Start(); 74 _engine.Start();
75 _engine.Name = string.Format ("Engine:{0}",EngineID);
76 76
77 ThreadTracker.Add(_engine); 77 ThreadTracker.Add(_engine);
78 } 78 }
@@ -91,9 +91,9 @@ namespace OpenSim.Framework.Servers.HttpServer
91 public void Start() 91 public void Start()
92 { 92 {
93 _engine = new Thread(new ThreadStart(Engine)); 93 _engine = new Thread(new ThreadStart(Engine));
94 _engine.Name = EngineID;
95 _engine.IsBackground = true; 94 _engine.IsBackground = true;
96 _engine.Start(); 95 _engine.Start();
96 _engine.Name = string.Format ("Engine:{0}",EngineID);
97 97
98 ThreadTracker.Add(_engine); 98 ThreadTracker.Add(_engine);
99 } 99 }
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer.cs
index 84aa31b..cd62842 100644
--- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer.cs
@@ -150,9 +150,9 @@ namespace OpenSim.Framework.Servers.HttpServer
150 public void Start() 150 public void Start()
151 { 151 {
152 _engine = new Thread(new ThreadStart(Engine)); 152 _engine = new Thread(new ThreadStart(Engine));
153 _engine.Name = _engineId;
154 _engine.IsBackground = true; 153 _engine.IsBackground = true;
155 _engine.Start(); 154 _engine.Start();
155 _engine.Name = string.Format ("Engine:{0}",_engineId);
156 156
157 ThreadTracker.Add(_engine); 157 ThreadTracker.Add(_engine);
158 158
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
index 5bd63a6..49cd110 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
@@ -93,7 +93,7 @@ namespace OpenSim.Framework.Servers.HttpServer
93 } 93 }
94 catch (Exception ex) 94 catch (Exception ex)
95 { 95 {
96 m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex)); 96 m_log.Warn("[POLL SERVICE WORKER THREAD]: Error ", ex);
97 } 97 }
98 finally 98 finally
99 { 99 {
@@ -108,7 +108,7 @@ namespace OpenSim.Framework.Servers.HttpServer
108 } 108 }
109 catch (Exception e) 109 catch (Exception e)
110 { 110 {
111 m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e)); 111 m_log.Warn("[POLL SERVICE WORKER THREAD]: Error ", e);
112 } 112 }
113 113
114 PollServiceArgs.RequestsHandled++; 114 PollServiceArgs.RequestsHandled++;
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index b56ade8..4ffe6e5 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -44,6 +44,25 @@ namespace OpenSim.Framework.Servers.HttpServer
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 /// <summary>
48 /// Is the poll service request manager running?
49 /// </summary>
50 /// <remarks>
51 /// Can be running either synchronously or asynchronously
52 /// </remarks>
53 public bool IsRunning { get; private set; }
54
55 /// <summary>
56 /// Is the poll service performing responses asynchronously (with its own threads) or synchronously (via
57 /// external calls)?
58 /// </summary>
59 public bool PerformResponsesAsync { get; private set; }
60
61 /// <summary>
62 /// Number of responses actually processed and sent to viewer (or aborted due to error).
63 /// </summary>
64 public int ResponsesProcessed { get; private set; }
65
47 private readonly BaseHttpServer m_server; 66 private readonly BaseHttpServer m_server;
48 67
49 private Dictionary<PollServiceHttpRequest, Queue<PollServiceHttpRequest>> m_bycontext; 68 private Dictionary<PollServiceHttpRequest, Queue<PollServiceHttpRequest>> m_bycontext;
@@ -55,17 +74,52 @@ namespace OpenSim.Framework.Servers.HttpServer
55 private Thread[] m_workerThreads; 74 private Thread[] m_workerThreads;
56 private Thread m_retrysThread; 75 private Thread m_retrysThread;
57 76
77<<<<<<< HEAD
78 private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2);
79
80// private int m_timeout = 1000; // increase timeout 250; now use the event one
81=======
58 private bool m_running = true; 82 private bool m_running = true;
59 private int slowCount = 0; 83 private int slowCount = 0;
60 84
61 private SmartThreadPool m_threadPool; 85 private SmartThreadPool m_threadPool;
86>>>>>>> avn/ubitvar
62 87
63 public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout) 88 public PollServiceRequestManager(
89 BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout)
64 { 90 {
65 m_server = pSrv; 91 m_server = pSrv;
92 PerformResponsesAsync = performResponsesAsync;
66 m_WorkerThreadCount = pWorkerThreadCount; 93 m_WorkerThreadCount = pWorkerThreadCount;
67 m_workerThreads = new Thread[m_WorkerThreadCount]; 94 m_workerThreads = new Thread[m_WorkerThreadCount];
68 95
96<<<<<<< HEAD
97 StatsManager.RegisterStat(
98 new Stat(
99 "QueuedPollResponses",
100 "Number of poll responses queued for processing.",
101 "",
102 "",
103 "httpserver",
104 m_server.Port.ToString(),
105 StatType.Pull,
106 MeasuresOfInterest.AverageChangeOverTime,
107 stat => stat.Value = m_requests.Count(),
108 StatVerbosity.Debug));
109
110 StatsManager.RegisterStat(
111 new Stat(
112 "ProcessedPollResponses",
113 "Number of poll responses processed.",
114 "",
115 "",
116 "httpserver",
117 m_server.Port.ToString(),
118 StatType.Pull,
119 MeasuresOfInterest.AverageChangeOverTime,
120 stat => stat.Value = ResponsesProcessed,
121 StatVerbosity.Debug));
122=======
69 PollServiceHttpRequestComparer preqCp = new PollServiceHttpRequestComparer(); 123 PollServiceHttpRequestComparer preqCp = new PollServiceHttpRequestComparer();
70 m_bycontext = new Dictionary<PollServiceHttpRequest, Queue<PollServiceHttpRequest>>(preqCp); 124 m_bycontext = new Dictionary<PollServiceHttpRequest, Queue<PollServiceHttpRequest>>(preqCp);
71 125
@@ -78,10 +132,40 @@ namespace OpenSim.Framework.Servers.HttpServer
78 startInfo.ThreadPoolName = "PoolService"; 132 startInfo.ThreadPoolName = "PoolService";
79 133
80 m_threadPool = new SmartThreadPool(startInfo); 134 m_threadPool = new SmartThreadPool(startInfo);
135>>>>>>> avn/ubitvar
81 } 136 }
82 137
83 public void Start() 138 public void Start()
84 { 139 {
140<<<<<<< HEAD
141 IsRunning = true;
142
143 if (PerformResponsesAsync)
144 {
145 //startup worker threads
146 for (uint i = 0; i < m_WorkerThreadCount; i++)
147 {
148 m_workerThreads[i]
149 = WorkManager.StartThread(
150 PoolWorkerJob,
151 string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port),
152 ThreadPriority.Normal,
153 false,
154 false,
155 null,
156 int.MaxValue);
157 }
158
159 WorkManager.StartThread(
160 this.CheckLongPollThreads,
161 string.Format("LongPollServiceWatcherThread:{0}", m_server.Port),
162 ThreadPriority.Normal,
163 false,
164 true,
165 null,
166 1000 * 60 * 10);
167 }
168=======
85 m_threadPool.Start(); 169 m_threadPool.Start();
86 //startup worker threads 170 //startup worker threads
87 for (uint i = 0; i < m_WorkerThreadCount; i++) 171 for (uint i = 0; i < m_WorkerThreadCount; i++)
@@ -105,11 +189,12 @@ namespace OpenSim.Framework.Servers.HttpServer
105 true, 189 true,
106 null, 190 null,
107 1000 * 60 * 10); 191 1000 * 60 * 10);
192>>>>>>> avn/ubitvar
108 } 193 }
109 194
110 private void ReQueueEvent(PollServiceHttpRequest req) 195 private void ReQueueEvent(PollServiceHttpRequest req)
111 { 196 {
112 if (m_running) 197 if (IsRunning)
113 { 198 {
114 lock (m_retryRequests) 199 lock (m_retryRequests)
115 m_retryRequests.Enqueue(req); 200 m_retryRequests.Enqueue(req);
@@ -157,7 +242,7 @@ namespace OpenSim.Framework.Servers.HttpServer
157 242
158 public void EnqueueInt(PollServiceHttpRequest req) 243 public void EnqueueInt(PollServiceHttpRequest req)
159 { 244 {
160 if (m_running) 245 if (IsRunning)
161 { 246 {
162 if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.LongPoll) 247 if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.LongPoll)
163 { 248 {
@@ -173,12 +258,36 @@ namespace OpenSim.Framework.Servers.HttpServer
173 258
174 private void CheckRetries() 259 private void CheckRetries()
175 { 260 {
261<<<<<<< HEAD
262 // The only purpose of this thread is to check the EQs for events.
263 // If there are events, that thread will be placed in the "ready-to-serve" queue, m_requests.
264 // If there are no events, that thread will be back to its "waiting" queue, m_longPollRequests.
265 // All other types of tasks (Inventory handlers, http-in, etc) don't have the long-poll nature,
266 // so if they aren't ready to be served by a worker thread (no events), they are placed
267 // directly back in the "ready-to-serve" queue by the worker thread.
268 while (IsRunning)
269=======
176 while (m_running) 270 while (m_running)
271>>>>>>> avn/ubitvar
177 { 272 {
178 Thread.Sleep(100); // let the world move .. back to faster rate 273 Thread.Sleep(100); // let the world move .. back to faster rate
179 Watchdog.UpdateThread(); 274 Watchdog.UpdateThread();
180 lock (m_retryRequests) 275 lock (m_retryRequests)
181 { 276 {
277<<<<<<< HEAD
278 if (m_longPollRequests.Count > 0 && IsRunning)
279 {
280 List<PollServiceHttpRequest> ready = m_longPollRequests.FindAll(req =>
281 (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id) || // there are events in this EQ
282 (Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) // no events, but timeout
283 );
284
285 ready.ForEach(req =>
286 {
287 m_requests.Enqueue(req);
288 m_longPollRequests.Remove(req);
289 });
290=======
182 while (m_retryRequests.Count > 0 && m_running) 291 while (m_retryRequests.Count > 0 && m_running)
183 m_requests.Enqueue(m_retryRequests.Dequeue()); 292 m_requests.Enqueue(m_retryRequests.Dequeue());
184 } 293 }
@@ -186,6 +295,7 @@ namespace OpenSim.Framework.Servers.HttpServer
186 if (slowCount >= 10) 295 if (slowCount >= 10)
187 { 296 {
188 slowCount = 0; 297 slowCount = 0;
298>>>>>>> avn/ubitvar
189 299
190 lock (m_slowRequests) 300 lock (m_slowRequests)
191 { 301 {
@@ -198,7 +308,12 @@ namespace OpenSim.Framework.Servers.HttpServer
198 308
199 public void Stop() 309 public void Stop()
200 { 310 {
311<<<<<<< HEAD
312 IsRunning = false;
313// m_timeout = -10000; // cause all to expire
314=======
201 m_running = false; 315 m_running = false;
316>>>>>>> avn/ubitvar
202 Thread.Sleep(1000); // let the world move 317 Thread.Sleep(1000); // let the world move
203 318
204 foreach (Thread t in m_workerThreads) 319 foreach (Thread t in m_workerThreads)
@@ -226,8 +341,13 @@ namespace OpenSim.Framework.Servers.HttpServer
226 341
227 lock (m_slowRequests) 342 lock (m_slowRequests)
228 { 343 {
344<<<<<<< HEAD
345 if (m_longPollRequests.Count > 0 && IsRunning)
346 m_longPollRequests.ForEach(req => m_requests.Enqueue(req));
347=======
229 while (m_slowRequests.Count > 0) 348 while (m_slowRequests.Count > 0)
230 m_requests.Enqueue(m_slowRequests.Dequeue()); 349 m_requests.Enqueue(m_slowRequests.Dequeue());
350>>>>>>> avn/ubitvar
231 } 351 }
232 352
233 while (m_requests.Count() > 0) 353 while (m_requests.Count() > 0)
@@ -235,7 +355,13 @@ namespace OpenSim.Framework.Servers.HttpServer
235 try 355 try
236 { 356 {
237 wreq = m_requests.Dequeue(0); 357 wreq = m_requests.Dequeue(0);
358<<<<<<< HEAD
359 ResponsesProcessed++;
360 wreq.DoHTTPGruntWork(
361 m_server, wreq.PollServiceArgs.NoEvents(wreq.RequestID, wreq.PollServiceArgs.Id));
362=======
238 wreq.DoHTTPstop(m_server); 363 wreq.DoHTTPstop(m_server);
364>>>>>>> avn/ubitvar
239 } 365 }
240 catch 366 catch
241 { 367 {
@@ -249,35 +375,91 @@ namespace OpenSim.Framework.Servers.HttpServer
249 375
250 private void PoolWorkerJob() 376 private void PoolWorkerJob()
251 { 377 {
252 while (m_running) 378 while (IsRunning)
253 { 379 {
380<<<<<<< HEAD
381=======
254 PollServiceHttpRequest req = m_requests.Dequeue(5000); 382 PollServiceHttpRequest req = m_requests.Dequeue(5000);
255 383
384>>>>>>> avn/ubitvar
256 Watchdog.UpdateThread(); 385 Watchdog.UpdateThread();
257 if (req != null) 386 WaitPerformResponse();
387 }
388 }
389
390 public void WaitPerformResponse()
391 {
392 PollServiceHttpRequest req = m_requests.Dequeue(5000);
393// m_log.DebugFormat("[YYY]: Dequeued {0}", (req == null ? "null" : req.PollServiceArgs.Type.ToString()));
394
395 if (req != null)
396 {
397 try
258 { 398 {
259 try 399 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
260 { 400 {
261 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) 401 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
262 { 402
263 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id); 403<<<<<<< HEAD
404 if (responsedata == null)
405 return;
264 406
407 // This is the event queue.
408 // Even if we're not running we can still perform responses by explicit request.
409 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll
410 || !PerformResponsesAsync)
411 {
412 try
413 {
414 ResponsesProcessed++;
415 req.DoHTTPGruntWork(m_server, responsedata);
416 }
417 catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream
418 {
419 // Ignore it, no need to reply
420 m_log.Error(e);
421 }
422 }
423 else
424 {
425 m_threadPool.QueueWorkItem(x =>
426=======
265 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) // This is the event queue 427 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) // This is the event queue
428>>>>>>> avn/ubitvar
266 { 429 {
267 try 430 try
268 { 431 {
432 ResponsesProcessed++;
269 req.DoHTTPGruntWork(m_server, responsedata); 433 req.DoHTTPGruntWork(m_server, responsedata);
270 byContextDequeue(req); 434 byContextDequeue(req);
271 } 435 }
272 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream 436 catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream
273 { 437 {
274 // Ignore it, no need to reply 438 // Ignore it, no need to reply
439 m_log.Error(e);
275 } 440 }
276 } 441 catch (Exception e)
277 else
278 {
279 m_threadPool.QueueWorkItem(x =>
280 { 442 {
443<<<<<<< HEAD
444 m_log.Error(e);
445 }
446
447 return null;
448 }, null);
449 }
450 }
451 else
452 {
453 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
454 {
455 ResponsesProcessed++;
456 req.DoHTTPGruntWork(
457 m_server, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
458 }
459 else
460 {
461 ReQueueEvent(req);
462=======
281 try 463 try
282 { 464 {
283 req.DoHTTPGruntWork(m_server, responsedata); 465 req.DoHTTPGruntWork(m_server, responsedata);
@@ -304,12 +486,13 @@ namespace OpenSim.Framework.Servers.HttpServer
304 { 486 {
305 ReQueueEvent(req); 487 ReQueueEvent(req);
306 } 488 }
489>>>>>>> avn/ubitvar
307 } 490 }
308 } 491 }
309 catch (Exception e) 492 }
310 { 493 catch (Exception e)
311 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString()); 494 {
312 } 495 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
313 } 496 }
314 } 497 }
315 } 498 }
diff --git a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
index f409667..63335bd 100644
--- a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.0.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Framework/Servers/HttpServer/RestObjectPoster.cs b/OpenSim/Framework/Servers/HttpServer/RestObjectPoster.cs
index 48ced19..afe052f 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestObjectPoster.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestObjectPoster.cs
@@ -52,23 +52,25 @@ namespace OpenSim.Framework.Servers.HttpServer
52 request.Method = verb; 52 request.Method = verb;
53 request.ContentType = "text/xml"; 53 request.ContentType = "text/xml";
54 54
55 MemoryStream buffer = new MemoryStream(); 55 using (MemoryStream buffer = new MemoryStream())
56 {
57 XmlWriterSettings settings = new XmlWriterSettings();
58 settings.Encoding = Encoding.UTF8;
56 59
57 XmlWriterSettings settings = new XmlWriterSettings(); 60 using (XmlWriter writer = XmlWriter.Create(buffer, settings))
58 settings.Encoding = Encoding.UTF8; 61 {
62 XmlSerializer serializer = new XmlSerializer(type);
63 serializer.Serialize(writer, obj);
64 writer.Flush();
65 }
59 66
60 using (XmlWriter writer = XmlWriter.Create(buffer, settings)) 67 int length = (int)buffer.Length;
61 { 68 request.ContentLength = length;
62 XmlSerializer serializer = new XmlSerializer(type);
63 serializer.Serialize(writer, obj);
64 writer.Flush();
65 }
66 69
67 int length = (int) buffer.Length; 70 using (Stream requestStream = request.GetRequestStream())
68 request.ContentLength = length; 71 requestStream.Write(buffer.ToArray(), 0, length);
72 }
69 73
70 Stream requestStream = request.GetRequestStream();
71 requestStream.Write(buffer.ToArray(), 0, length);
72 // IAsyncResult result = request.BeginGetResponse(AsyncCallback, request); 74 // IAsyncResult result = request.BeginGetResponse(AsyncCallback, request);
73 request.BeginGetResponse(AsyncCallback, request); 75 request.BeginGetResponse(AsyncCallback, request);
74 } 76 }
diff --git a/OpenSim/Framework/Servers/HttpServer/RestObjectPosterResponse.cs b/OpenSim/Framework/Servers/HttpServer/RestObjectPosterResponse.cs
index 451745c..a911b9f 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestObjectPosterResponse.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestObjectPosterResponse.cs
@@ -60,24 +60,25 @@ namespace OpenSim.Framework.Servers.HttpServer
60 request.ContentType = "text/xml"; 60 request.ContentType = "text/xml";
61 request.Timeout = 10000; 61 request.Timeout = 10000;
62 62
63 MemoryStream buffer = new MemoryStream(); 63 using (MemoryStream buffer = new MemoryStream())
64 {
65 XmlWriterSettings settings = new XmlWriterSettings();
66 settings.Encoding = Encoding.UTF8;
67
68 using (XmlWriter writer = XmlWriter.Create(buffer, settings))
69 {
70 XmlSerializer serializer = new XmlSerializer(type);
71 serializer.Serialize(writer, obj);
72 writer.Flush();
73 }
64 74
65 XmlWriterSettings settings = new XmlWriterSettings(); 75 int length = (int)buffer.Length;
66 settings.Encoding = Encoding.UTF8; 76 request.ContentLength = length;
67 77
68 using (XmlWriter writer = XmlWriter.Create(buffer, settings)) 78 using (Stream requestStream = request.GetRequestStream())
69 { 79 requestStream.Write(buffer.ToArray(), 0, length);
70 XmlSerializer serializer = new XmlSerializer(type);
71 serializer.Serialize(writer, obj);
72 writer.Flush();
73 } 80 }
74 81
75 int length = (int) buffer.Length;
76 request.ContentLength = length;
77
78 Stream requestStream = request.GetRequestStream();
79 requestStream.Write(buffer.ToArray(), 0, length);
80 requestStream.Close();
81 // IAsyncResult result = request.BeginGetResponse(AsyncCallback, request); 82 // IAsyncResult result = request.BeginGetResponse(AsyncCallback, request);
82 request.BeginGetResponse(AsyncCallback, request); 83 request.BeginGetResponse(AsyncCallback, request);
83 } 84 }
diff --git a/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs b/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
index 83c9848..ad69cd2 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
@@ -77,25 +77,24 @@ namespace OpenSim.Framework.Servers.HttpServer
77 request.ContentType = "text/xml"; 77 request.ContentType = "text/xml";
78 request.Timeout = 20000; 78 request.Timeout = 20000;
79 79
80 MemoryStream buffer = new MemoryStream(); 80 using (MemoryStream buffer = new MemoryStream())
81
82 XmlWriterSettings settings = new XmlWriterSettings();
83 settings.Encoding = Encoding.UTF8;
84
85 using (XmlWriter writer = XmlWriter.Create(buffer, settings))
86 { 81 {
87 XmlSerializer serializer = new XmlSerializer(type); 82 XmlWriterSettings settings = new XmlWriterSettings();
88 serializer.Serialize(writer, sobj); 83 settings.Encoding = Encoding.UTF8;
89 writer.Flush();
90 }
91 84
92 int length = (int)buffer.Length; 85 using (XmlWriter writer = XmlWriter.Create(buffer, settings))
93 request.ContentLength = length; 86 {
87 XmlSerializer serializer = new XmlSerializer(type);
88 serializer.Serialize(writer, sobj);
89 writer.Flush();
90 }
91
92 int length = (int)buffer.Length;
93 request.ContentLength = length;
94 94
95 Stream requestStream = request.GetRequestStream(); 95 using (Stream requestStream = request.GetRequestStream())
96 requestStream.Write(buffer.ToArray(), 0, length); 96 requestStream.Write(buffer.ToArray(), 0, length);
97 buffer.Close(); 97 }
98 requestStream.Close();
99 98
100 TResponse deserial = default(TResponse); 99 TResponse deserial = default(TResponse);
101 using (WebResponse resp = request.GetResponse()) 100 using (WebResponse resp = request.GetResponse())
@@ -133,25 +132,25 @@ namespace OpenSim.Framework.Servers.HttpServer
133 request.ContentType = "text/xml"; 132 request.ContentType = "text/xml";
134 request.Timeout = 10000; 133 request.Timeout = 10000;
135 134
136 MemoryStream buffer = new MemoryStream(); 135 using (MemoryStream buffer = new MemoryStream())
136 {
137 XmlWriterSettings settings = new XmlWriterSettings();
138 settings.Encoding = Encoding.UTF8;
139
140 using (XmlWriter writer = XmlWriter.Create(buffer, settings))
141 {
142 XmlSerializer serializer = new XmlSerializer(type);
143 serializer.Serialize(writer, sobj);
144 writer.Flush();
145 }
137 146
138 XmlWriterSettings settings = new XmlWriterSettings(); 147 int length = (int)buffer.Length;
139 settings.Encoding = Encoding.UTF8; 148 request.ContentLength = length;
140 149
141 using (XmlWriter writer = XmlWriter.Create(buffer, settings)) 150 using (Stream requestStream = request.GetRequestStream())
142 { 151 requestStream.Write(buffer.ToArray(), 0, length);
143 XmlSerializer serializer = new XmlSerializer(type);
144 serializer.Serialize(writer, sobj);
145 writer.Flush();
146 } 152 }
147 buffer.Close();
148
149 int length = (int)buffer.Length;
150 request.ContentLength = length;
151 153
152 Stream requestStream = request.GetRequestStream();
153 requestStream.Write(buffer.ToArray(), 0, length);
154 requestStream.Close();
155 // IAsyncResult result = request.BeginGetResponse(AsyncCallback, request); 154 // IAsyncResult result = request.BeginGetResponse(AsyncCallback, request);
156 request.BeginGetResponse(AsyncCallback, request); 155 request.BeginGetResponse(AsyncCallback, request);
157 } 156 }
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
index 7108314..35177f4 100644
--- a/OpenSim/Framework/Servers/ServerBase.cs
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; 30using System.Diagnostics;
31using System.IO; 31using System.IO;
32using System.Linq;
32using System.Reflection; 33using System.Reflection;
33using System.Text; 34using System.Text;
34using System.Text.RegularExpressions; 35using System.Text.RegularExpressions;
@@ -279,6 +280,29 @@ namespace OpenSim.Framework.Servers
279 "debug threadpool status", 280 "debug threadpool status",
280 "Show current debug threadpool parameters.", 281 "Show current debug threadpool parameters.",
281 HandleDebugThreadpoolStatus); 282 HandleDebugThreadpoolStatus);
283
284 m_console.Commands.AddCommand(
285 "Debug", false, "debug threadpool level",
286 "debug threadpool level 0.." + Util.MAX_THREADPOOL_LEVEL,
287 "Turn on logging of activity in the main thread pool.",
288 "Log levels:\n"
289 + " 0 = no logging\n"
290 + " 1 = only first line of stack trace; don't log common threads\n"
291 + " 2 = full stack trace; don't log common threads\n"
292 + " 3 = full stack trace, including common threads\n",
293 HandleDebugThreadpoolLevel);
294
295// m_console.Commands.AddCommand(
296// "Debug", false, "show threadpool calls active",
297// "show threadpool calls active",
298// "Show details about threadpool calls that are still active (currently waiting or in progress)",
299// HandleShowThreadpoolCallsActive);
300
301 m_console.Commands.AddCommand(
302 "Debug", false, "show threadpool calls complete",
303 "show threadpool calls complete",
304 "Show details about threadpool calls that have been completed.",
305 HandleShowThreadpoolCallsComplete);
282 306
283 m_console.Commands.AddCommand( 307 m_console.Commands.AddCommand(
284 "Debug", false, "force gc", 308 "Debug", false, "force gc",
@@ -343,6 +367,57 @@ namespace OpenSim.Framework.Servers
343 Notice("serialosdreq is now {0}", setSerializeOsdRequests); 367 Notice("serialosdreq is now {0}", setSerializeOsdRequests);
344 } 368 }
345 369
370 private void HandleShowThreadpoolCallsActive(string module, string[] args)
371 {
372 List<KeyValuePair<string, int>> calls = Util.GetFireAndForgetCallsInProgress().ToList();
373 calls.Sort((kvp1, kvp2) => kvp2.Value.CompareTo(kvp1.Value));
374 int namedCalls = 0;
375
376 ConsoleDisplayList cdl = new ConsoleDisplayList();
377 foreach (KeyValuePair<string, int> kvp in calls)
378 {
379 if (kvp.Value > 0)
380 {
381 cdl.AddRow(kvp.Key, kvp.Value);
382 namedCalls += kvp.Value;
383 }
384 }
385
386 cdl.AddRow("TOTAL NAMED", namedCalls);
387
388 long allQueuedCalls = Util.TotalQueuedFireAndForgetCalls;
389 long allRunningCalls = Util.TotalRunningFireAndForgetCalls;
390
391 cdl.AddRow("TOTAL QUEUED", allQueuedCalls);
392 cdl.AddRow("TOTAL RUNNING", allRunningCalls);
393 cdl.AddRow("TOTAL ANONYMOUS", allQueuedCalls + allRunningCalls - namedCalls);
394 cdl.AddRow("TOTAL ALL", allQueuedCalls + allRunningCalls);
395
396 MainConsole.Instance.Output(cdl.ToString());
397 }
398
399 private void HandleShowThreadpoolCallsComplete(string module, string[] args)
400 {
401 List<KeyValuePair<string, int>> calls = Util.GetFireAndForgetCallsMade().ToList();
402 calls.Sort((kvp1, kvp2) => kvp2.Value.CompareTo(kvp1.Value));
403 int namedCallsMade = 0;
404
405 ConsoleDisplayList cdl = new ConsoleDisplayList();
406 foreach (KeyValuePair<string, int> kvp in calls)
407 {
408 cdl.AddRow(kvp.Key, kvp.Value);
409 namedCallsMade += kvp.Value;
410 }
411
412 cdl.AddRow("TOTAL NAMED", namedCallsMade);
413
414 long allCallsMade = Util.TotalFireAndForgetCallsMade;
415 cdl.AddRow("TOTAL ANONYMOUS", allCallsMade - namedCallsMade);
416 cdl.AddRow("TOTAL ALL", allCallsMade);
417
418 MainConsole.Instance.Output(cdl.ToString());
419 }
420
346 private void HandleDebugThreadpoolStatus(string module, string[] args) 421 private void HandleDebugThreadpoolStatus(string module, string[] args)
347 { 422 {
348 int workerThreads, iocpThreads; 423 int workerThreads, iocpThreads;
@@ -432,6 +507,33 @@ namespace OpenSim.Framework.Servers
432 } 507 }
433 } 508 }
434 509
510 private static void HandleDebugThreadpoolLevel(string module, string[] cmdparams)
511 {
512 if (cmdparams.Length < 4)
513 {
514 MainConsole.Instance.Output("Usage: debug threadpool level 0.." + Util.MAX_THREADPOOL_LEVEL);
515 return;
516 }
517
518 string rawLevel = cmdparams[3];
519 int newLevel;
520
521 if (!int.TryParse(rawLevel, out newLevel))
522 {
523 MainConsole.Instance.OutputFormat("{0} is not a valid debug level", rawLevel);
524 return;
525 }
526
527 if (newLevel < 0 || newLevel > Util.MAX_THREADPOOL_LEVEL)
528 {
529 MainConsole.Instance.OutputFormat("{0} is outside the valid debug level range of 0.." + Util.MAX_THREADPOOL_LEVEL, newLevel);
530 return;
531 }
532
533 Util.LogThreadPool = newLevel;
534 MainConsole.Instance.OutputFormat("LogThreadPool set to {0}", newLevel);
535 }
536
435 private void HandleForceGc(string module, string[] args) 537 private void HandleForceGc(string module, string[] args)
436 { 538 {
437 Notice("Manually invoking runtime garbage collection"); 539 Notice("Manually invoking runtime garbage collection");
diff --git a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
index deae45c..e13551c 100644
--- a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
+++ b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
@@ -41,6 +41,9 @@ namespace OpenSim.Framework.Servers.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class OSHttpTests : OpenSimTestCase 43 public class OSHttpTests : OpenSimTestCase
44<<<<<<< HEAD
45 {
46=======
44 { 47 {
45 // we need an IHttpClientContext for our tests 48 // we need an IHttpClientContext for our tests
46 public class TestHttpClientContext: IHttpClientContext 49 public class TestHttpClientContext: IHttpClientContext
@@ -362,6 +365,7 @@ namespace OpenSim.Framework.Servers.Tests
362 } 365 }
363 366
364 367
368>>>>>>> avn/ubitvar
365 public OSHttpRequest req0; 369 public OSHttpRequest req0;
366 public OSHttpRequest req1; 370 public OSHttpRequest req1;
367 371
diff --git a/OpenSim/Framework/ServiceAuth/BasicHttpAuthentication.cs b/OpenSim/Framework/ServiceAuth/BasicHttpAuthentication.cs
new file mode 100644
index 0000000..512ac4f
--- /dev/null
+++ b/OpenSim/Framework/ServiceAuth/BasicHttpAuthentication.cs
@@ -0,0 +1,113 @@
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
28using System;
29using System.Collections.Generic;
30using System.Collections.Specialized;
31using System.Net;
32using System.Reflection;
33
34using Nini.Config;
35using log4net;
36
37namespace OpenSim.Framework.ServiceAuth
38{
39 public class BasicHttpAuthentication : IServiceAuth
40 {
41// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42
43 public string Name { get { return "BasicHttp"; } }
44
45 private string m_Username, m_Password;
46 private string m_CredentialsB64;
47
48// private string remove_me;
49
50 public string Credentials
51 {
52 get { return m_CredentialsB64; }
53 }
54
55 public BasicHttpAuthentication(IConfigSource config, string section)
56 {
57// remove_me = section;
58 m_Username = Util.GetConfigVarFromSections<string>(config, "HttpAuthUsername", new string[] { "Network", section }, string.Empty);
59 m_Password = Util.GetConfigVarFromSections<string>(config, "HttpAuthPassword", new string[] { "Network", section }, string.Empty);
60 string str = m_Username + ":" + m_Password;
61 byte[] encData_byte = Util.UTF8.GetBytes(str);
62
63 m_CredentialsB64 = Convert.ToBase64String(encData_byte);
64// m_log.DebugFormat("[HTTP BASIC AUTH]: {0} {1} [{2}]", m_Username, m_Password, section);
65 }
66
67 public void AddAuthorization(NameValueCollection headers)
68 {
69 //m_log.DebugFormat("[HTTP BASIC AUTH]: Adding authorization for {0}", remove_me);
70 headers["Authorization"] = "Basic " + m_CredentialsB64;
71 }
72
73 public bool Authenticate(string data)
74 {
75 string recovered = Util.Base64ToString(data);
76 if (!String.IsNullOrEmpty(recovered))
77 {
78 string[] parts = recovered.Split(new char[] { ':' });
79 if (parts.Length >= 2)
80 {
81 return m_Username.Equals(parts[0]) && m_Password.Equals(parts[1]);
82 }
83 }
84
85 return false;
86 }
87
88 public bool Authenticate(NameValueCollection requestHeaders, AddHeaderDelegate d, out HttpStatusCode statusCode)
89 {
90// m_log.DebugFormat("[HTTP BASIC AUTH]: Authenticate in {0}", "BasicHttpAuthentication");
91
92 string value = requestHeaders.Get("Authorization");
93 if (value != null)
94 {
95 value = value.Trim();
96 if (value.StartsWith("Basic "))
97 {
98 value = value.Replace("Basic ", string.Empty);
99 if (Authenticate(value))
100 {
101 statusCode = HttpStatusCode.OK;
102 return true;
103 }
104 }
105 }
106
107 d("WWW-Authenticate", "Basic realm = \"Asset Server\"");
108
109 statusCode = HttpStatusCode.Unauthorized;
110 return false;
111 }
112 }
113}
diff --git a/OpenSim/Framework/ServiceAuth/CompoundAuthentication.cs b/OpenSim/Framework/ServiceAuth/CompoundAuthentication.cs
new file mode 100644
index 0000000..a49952c
--- /dev/null
+++ b/OpenSim/Framework/ServiceAuth/CompoundAuthentication.cs
@@ -0,0 +1,82 @@
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
28using System;
29using System.Collections.Generic;
30using System.Collections.Specialized;
31using System.Linq;
32using System.Net;
33
34namespace OpenSim.Framework.ServiceAuth
35{
36 public class CompoundAuthentication : IServiceAuth
37 {
38 public string Name { get { return "Compound"; } }
39
40 private List<IServiceAuth> m_authentications = new List<IServiceAuth>();
41
42 public int Count { get { return m_authentications.Count; } }
43
44 public List<IServiceAuth> GetAuthentors()
45 {
46 return new List<IServiceAuth>(m_authentications);
47 }
48
49 public void AddAuthenticator(IServiceAuth auth)
50 {
51 m_authentications.Add(auth);
52 }
53
54 public void RemoveAuthenticator(IServiceAuth auth)
55 {
56 m_authentications.Remove(auth);
57 }
58
59 public void AddAuthorization(NameValueCollection headers)
60 {
61 foreach (IServiceAuth auth in m_authentications)
62 auth.AddAuthorization(headers);
63 }
64
65 public bool Authenticate(string data)
66 {
67 return m_authentications.TrueForAll(a => a.Authenticate(data));
68 }
69
70 public bool Authenticate(NameValueCollection requestHeaders, AddHeaderDelegate d, out HttpStatusCode statusCode)
71 {
72 foreach (IServiceAuth auth in m_authentications)
73 {
74 if (!auth.Authenticate(requestHeaders, d, out statusCode))
75 return false;
76 }
77
78 statusCode = HttpStatusCode.OK;
79 return true;
80 }
81 }
82} \ No newline at end of file
diff --git a/OpenSim/Framework/Configuration/HTTP/RemoteConfigSettings.cs b/OpenSim/Framework/ServiceAuth/DisallowLlHttpRequest.cs
index 10bc88a..e0c413b 100644
--- a/OpenSim/Framework/Configuration/HTTP/RemoteConfigSettings.cs
+++ b/OpenSim/Framework/ServiceAuth/DisallowLlHttpRequest.cs
@@ -26,38 +26,34 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Specialized;
30using System.Net;
29 31
30namespace OpenSim.Framework.Configuration.HTTP 32namespace OpenSim.Framework.ServiceAuth
31{ 33{
32 public class RemoteConfigSettings 34 public class DisallowLlHttpRequest : IServiceAuth
33 { 35 {
34 private ConfigurationMember configMember; 36 public string Name { get { return "DisallowllHTTPRequest"; } }
35 37
36 public string baseConfigURL = String.Empty; 38 public void AddAuthorization(NameValueCollection headers) {}
37 39
38 public RemoteConfigSettings(string filename) 40 public bool Authenticate(string data)
39 { 41 {
40 configMember = 42 return false;
41 new ConfigurationMember(filename, "REMOTE CONFIG SETTINGS", loadConfigurationOptions,
42 handleIncomingConfiguration,true);
43 configMember.forceConfigurationPluginLibrary("OpenSim.Framework.Configuration.XML.dll");
44 configMember.performConfigurationRetrieve();
45 } 43 }
46 44
47 public void loadConfigurationOptions() 45 public bool Authenticate(NameValueCollection requestHeaders, AddHeaderDelegate d, out HttpStatusCode statusCode)
48 { 46 {
49 configMember.addConfigurationOption("base_config_url", 47// Console.WriteLine("DisallowLlHttpRequest");
50 ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
51 "URL Containing Configuration Files", "http://localhost/", false);
52 }
53 48
54 public bool handleIncomingConfiguration(string configuration_key, object configuration_result) 49 if (requestHeaders["X-SecondLife-Shard"] != null)
55 {
56 if (configuration_key == "base_config_url")
57 { 50 {
58 baseConfigURL = (string) configuration_result; 51 statusCode = HttpStatusCode.Forbidden;
52 return false;
59 } 53 }
54
55 statusCode = HttpStatusCode.OK;
60 return true; 56 return true;
61 } 57 }
62 } 58 }
63} 59} \ No newline at end of file
diff --git a/OpenSim/Framework/ServiceAuth/IServiceAuth.cs b/OpenSim/Framework/ServiceAuth/IServiceAuth.cs
new file mode 100644
index 0000000..5f744cb
--- /dev/null
+++ b/OpenSim/Framework/ServiceAuth/IServiceAuth.cs
@@ -0,0 +1,48 @@
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
28using System;
29using System.Net;
30using System.Collections.Generic;
31using System.Collections.Specialized;
32
33namespace OpenSim.Framework.ServiceAuth
34{
35 public delegate void AddHeaderDelegate(string key, string value);
36
37 public interface IServiceAuth
38 {
39 /// <summary>
40 /// Name of this authenticator.
41 /// </summary>
42 string Name { get; }
43
44 bool Authenticate(string data);
45 bool Authenticate(NameValueCollection headers, AddHeaderDelegate d, out HttpStatusCode statusCode);
46 void AddAuthorization(NameValueCollection headers);
47 }
48}
diff --git a/OpenSim/Framework/ServiceAuth/ServiceAuth.cs b/OpenSim/Framework/ServiceAuth/ServiceAuth.cs
new file mode 100644
index 0000000..51012e3
--- /dev/null
+++ b/OpenSim/Framework/ServiceAuth/ServiceAuth.cs
@@ -0,0 +1,68 @@
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
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
32using Nini.Config;
33
34namespace OpenSim.Framework.ServiceAuth
35{
36 public class ServiceAuth
37 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39
40 public static IServiceAuth Create(IConfigSource config, string section)
41 {
42 CompoundAuthentication compoundAuth = new CompoundAuthentication();
43
44 bool allowLlHttpRequestIn
45 = Util.GetConfigVarFromSections<bool>(config, "AllowllHTTPRequestIn", new string[] { "Network", section }, false);
46
47 if (!allowLlHttpRequestIn)
48 compoundAuth.AddAuthenticator(new DisallowLlHttpRequest());
49
50 string authType = Util.GetConfigVarFromSections<string>(config, "AuthType", new string[] { "Network", section }, "None");
51
52 switch (authType)
53 {
54 case "BasicHttpAuthentication":
55 compoundAuth.AddAuthenticator(new BasicHttpAuthentication(config, section));
56 break;
57 }
58
59// foreach (IServiceAuth auth in compoundAuth.GetAuthentors())
60// m_log.DebugFormat("[SERVICE AUTH]: Configured authenticator {0}", auth.Name);
61
62 if (compoundAuth.Count > 0)
63 return compoundAuth;
64 else
65 return null;
66 }
67 }
68} \ No newline at end of file
diff --git a/OpenSim/Framework/Tests/AnimationTests.cs b/OpenSim/Framework/Tests/AnimationTests.cs
index f3be81b..d8f17d0 100644
--- a/OpenSim/Framework/Tests/AnimationTests.cs
+++ b/OpenSim/Framework/Tests/AnimationTests.cs
@@ -32,7 +32,6 @@ using OpenMetaverse;
32using OpenMetaverse.StructuredData; 32using OpenMetaverse.StructuredData;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Tests.Common; 34using OpenSim.Tests.Common;
35using OpenSim.Tests.Common.Mock;
36using Animation = OpenSim.Framework.Animation; 35using Animation = OpenSim.Framework.Animation;
37 36
38namespace OpenSim.Framework.Tests 37namespace OpenSim.Framework.Tests
diff --git a/OpenSim/Framework/Tests/AssetBaseTest.cs b/OpenSim/Framework/Tests/AssetBaseTest.cs
index 25d2393..1975a4d 100644
--- a/OpenSim/Framework/Tests/AssetBaseTest.cs
+++ b/OpenSim/Framework/Tests/AssetBaseTest.cs
@@ -50,19 +50,15 @@ namespace OpenSim.Framework.Tests
50 CheckContainsReferences(AssetType.ImageJPEG , false); 50 CheckContainsReferences(AssetType.ImageJPEG , false);
51 CheckContainsReferences(AssetType.ImageTGA , false); 51 CheckContainsReferences(AssetType.ImageTGA , false);
52 CheckContainsReferences(AssetType.Landmark , false); 52 CheckContainsReferences(AssetType.Landmark , false);
53 CheckContainsReferences(AssetType.LostAndFoundFolder, false);
54 CheckContainsReferences(AssetType.LSLBytecode, false); 53 CheckContainsReferences(AssetType.LSLBytecode, false);
55 CheckContainsReferences(AssetType.LSLText, false); 54 CheckContainsReferences(AssetType.LSLText, false);
56 CheckContainsReferences(AssetType.Notecard, false); 55 CheckContainsReferences(AssetType.Notecard, false);
57 CheckContainsReferences(AssetType.Object, false); 56 CheckContainsReferences(AssetType.Object, false);
58 CheckContainsReferences(AssetType.RootFolder, false);
59 CheckContainsReferences(AssetType.Simstate, false); 57 CheckContainsReferences(AssetType.Simstate, false);
60 CheckContainsReferences(AssetType.SnapshotFolder, false);
61 CheckContainsReferences(AssetType.Sound, false); 58 CheckContainsReferences(AssetType.Sound, false);
62 CheckContainsReferences(AssetType.SoundWAV, false); 59 CheckContainsReferences(AssetType.SoundWAV, false);
63 CheckContainsReferences(AssetType.Texture, false); 60 CheckContainsReferences(AssetType.Texture, false);
64 CheckContainsReferences(AssetType.TextureTGA, false); 61 CheckContainsReferences(AssetType.TextureTGA, false);
65 CheckContainsReferences(AssetType.TrashFolder, false);
66 CheckContainsReferences(AssetType.Unknown, false); 62 CheckContainsReferences(AssetType.Unknown, false);
67 } 63 }
68 64
diff --git a/OpenSim/Framework/Tests/UtilTest.cs b/OpenSim/Framework/Tests/UtilTest.cs
index 3b7f252..cfe3139 100644
--- a/OpenSim/Framework/Tests/UtilTest.cs
+++ b/OpenSim/Framework/Tests/UtilTest.cs
@@ -173,8 +173,8 @@ namespace OpenSim.Framework.Tests
173 [Test] 173 [Test]
174 public void SLUtilTypeConvertTests() 174 public void SLUtilTypeConvertTests()
175 { 175 {
176 int[] assettypes = new int[]{-1,0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 176 int[] assettypes = new int[]{-1,0,1,2,3,5,6,7,8,10,11,12,13,17,18,19,20,21,22
177 ,23,24,25,46,47,48}; 177 ,24,25};
178 string[] contenttypes = new string[] 178 string[] contenttypes = new string[]
179 { 179 {
180 "application/octet-stream", 180 "application/octet-stream",
@@ -186,26 +186,18 @@ namespace OpenSim.Framework.Tests
186 "application/vnd.ll.primitive", 186 "application/vnd.ll.primitive",
187 "application/vnd.ll.notecard", 187 "application/vnd.ll.notecard",
188 "application/vnd.ll.folder", 188 "application/vnd.ll.folder",
189 "application/vnd.ll.rootfolder",
190 "application/vnd.ll.lsltext", 189 "application/vnd.ll.lsltext",
191 "application/vnd.ll.lslbyte", 190 "application/vnd.ll.lslbyte",
192 "image/tga", 191 "image/tga",
193 "application/vnd.ll.bodypart", 192 "application/vnd.ll.bodypart",
194 "application/vnd.ll.trashfolder",
195 "application/vnd.ll.snapshotfolder",
196 "application/vnd.ll.lostandfoundfolder",
197 "audio/x-wav", 193 "audio/x-wav",
198 "image/tga", 194 "image/tga",
199 "image/jpeg", 195 "image/jpeg",
200 "application/vnd.ll.animation", 196 "application/vnd.ll.animation",
201 "application/vnd.ll.gesture", 197 "application/vnd.ll.gesture",
202 "application/x-metaverse-simstate", 198 "application/x-metaverse-simstate",
203 "application/vnd.ll.favoritefolder",
204 "application/vnd.ll.link", 199 "application/vnd.ll.link",
205 "application/vnd.ll.linkfolder", 200 "application/vnd.ll.linkfolder",
206 "application/vnd.ll.currentoutfitfolder",
207 "application/vnd.ll.outfitfolder",
208 "application/vnd.ll.myoutfitsfolder"
209 }; 201 };
210 for (int i=0;i<assettypes.Length;i++) 202 for (int i=0;i<assettypes.Length;i++)
211 { 203 {
@@ -223,7 +215,7 @@ namespace OpenSim.Framework.Tests
223 String.Format("Incorrect AssetType mapped from Content-Type {0}", contenttypes[i])); 215 String.Format("Incorrect AssetType mapped from Content-Type {0}", contenttypes[i]));
224 } 216 }
225 217
226 int[] inventorytypes = new int[] {-1,0,1,2,3,6,7,8,9,10,15,17,18,20}; 218 int[] inventorytypes = new int[] {-1,0,1,2,3,6,7,8,10,15,17,18,20};
227 string[] invcontenttypes = new string[] 219 string[] invcontenttypes = new string[]
228 { 220 {
229 "application/octet-stream", 221 "application/octet-stream",
@@ -233,7 +225,6 @@ namespace OpenSim.Framework.Tests
233 "application/vnd.ll.landmark", 225 "application/vnd.ll.landmark",
234 "application/vnd.ll.primitive", 226 "application/vnd.ll.primitive",
235 "application/vnd.ll.notecard", 227 "application/vnd.ll.notecard",
236 "application/vnd.ll.folder",
237 "application/vnd.ll.rootfolder", 228 "application/vnd.ll.rootfolder",
238 "application/vnd.ll.lsltext", 229 "application/vnd.ll.lsltext",
239 "image/x-j2c", 230 "image/x-j2c",
@@ -272,8 +263,8 @@ namespace OpenSim.Framework.Tests
272 }; 263 };
273 sbyte[] invtypes = new sbyte[] 264 sbyte[] invtypes = new sbyte[]
274 { 265 {
275 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 18, 18, 18, 18, 6, 6, 7, 7, 8, 9, 10, 10, 10, 10 266 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 18, 18, 18, 18, 6, 6, 7, 7, -1, 8, 10, 10, 10, 10
276 , 8, 8, 8, 19, 19, 20, 20, 15, -1 267 , 14, 15, 16, 19, 19, 20, 20, 15, -1
277 }; 268 };
278 269
279 for (int i = 0; i < invtypes.Length; i++) 270 for (int i = 0; i < invtypes.Length; i++)
@@ -299,7 +290,7 @@ namespace OpenSim.Framework.Tests
299 uint z1 = 22; 290 uint z1 = 22;
300 ulong regionHandle2; 291 ulong regionHandle2;
301 uint x2, y2, z2; 292 uint x2, y2, z2;
302 UUID fakeParcelID1, fakeParcelID2, uuid; 293 UUID fakeParcelID1, uuid;
303 294
304 ulong bigInt64 = Util.BytesToUInt64Big(hexBytes8); 295 ulong bigInt64 = Util.BytesToUInt64Big(hexBytes8);
305 Assert.AreEqual(var64Bit, bigInt64, 296 Assert.AreEqual(var64Bit, bigInt64,
diff --git a/OpenSim/Framework/ThreadSafeRandom.cs b/OpenSim/Framework/ThreadSafeRandom.cs
new file mode 100644
index 0000000..58853e6
--- /dev/null
+++ b/OpenSim/Framework/ThreadSafeRandom.cs
@@ -0,0 +1,72 @@
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
28using System;
29
30namespace OpenSim.Framework
31{
32 /// <summary>
33 /// A thread-safe Random since the .NET version is not.
34 /// See http://msdn.microsoft.com/en-us/library/system.random%28v=vs.100%29.aspx
35 /// </summary>
36 public class ThreadSafeRandom : Random
37 {
38 public ThreadSafeRandom() : base() {}
39
40 public ThreadSafeRandom(int seed): base (seed) {}
41
42 public override int Next()
43 {
44 lock (this)
45 return base.Next();
46 }
47
48 public override int Next(int maxValue)
49 {
50 lock (this)
51 return base.Next(maxValue);
52 }
53
54 public override int Next(int minValue, int maxValue)
55 {
56 lock (this)
57 return base.Next(minValue, maxValue);
58 }
59
60 public override void NextBytes(byte[] buffer)
61 {
62 lock (this)
63 base.NextBytes(buffer);
64 }
65
66 public override double NextDouble()
67 {
68 lock (this)
69 return base.NextDouble();
70 }
71 }
72} \ No newline at end of file
diff --git a/OpenSim/Framework/UntrustedWebRequest.cs b/OpenSim/Framework/UntrustedWebRequest.cs
deleted file mode 100644
index e6411cc..0000000
--- a/OpenSim/Framework/UntrustedWebRequest.cs
+++ /dev/null
@@ -1,230 +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
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Net;
32using System.Net.Security;
33using System.Text;
34using log4net;
35
36namespace OpenSim.Framework
37{
38 /// <summary>
39 /// Used for requests to untrusted endpoints that may potentially be
40 /// malicious
41 /// </summary>
42 public static class UntrustedHttpWebRequest
43 {
44 /// <summary>Setting this to true will allow HTTP connections to localhost</summary>
45 private const bool DEBUG = true;
46
47 private static readonly ILog m_log =
48 LogManager.GetLogger(
49 System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
50
51 private static readonly ICollection<string> allowableSchemes = new List<string> { "http", "https" };
52
53 /// <summary>
54 /// Creates an HttpWebRequest that is hardened against malicious
55 /// endpoints after ensuring the given Uri is safe to retrieve
56 /// </summary>
57 /// <param name="uri">Web location to request</param>
58 /// <returns>A hardened HttpWebRequest if the uri was determined to be safe</returns>
59 /// <exception cref="ArgumentNullException">If uri is null</exception>
60 /// <exception cref="ArgumentException">If uri is unsafe</exception>
61 public static HttpWebRequest Create(Uri uri)
62 {
63 return Create(uri, DEBUG, 1000 * 5, 1000 * 20, 10);
64 }
65
66 /// <summary>
67 /// Creates an HttpWebRequest that is hardened against malicious
68 /// endpoints after ensuring the given Uri is safe to retrieve
69 /// </summary>
70 /// <param name="uri">Web location to request</param>
71 /// <param name="allowLoopback">True to allow connections to localhost, otherwise false</param>
72 /// <param name="readWriteTimeoutMS">Read write timeout, in milliseconds</param>
73 /// <param name="timeoutMS">Connection timeout, in milliseconds</param>
74 /// <param name="maximumRedirects">Maximum number of allowed redirects</param>
75 /// <returns>A hardened HttpWebRequest if the uri was determined to be safe</returns>
76 /// <exception cref="ArgumentNullException">If uri is null</exception>
77 /// <exception cref="ArgumentException">If uri is unsafe</exception>
78 public static HttpWebRequest Create(Uri uri, bool allowLoopback, int readWriteTimeoutMS, int timeoutMS, int maximumRedirects)
79 {
80 if (uri == null)
81 throw new ArgumentNullException("uri");
82
83 if (!IsUriAllowable(uri, allowLoopback))
84 throw new ArgumentException("Uri " + uri + " was rejected");
85
86 HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(uri);
87 httpWebRequest.MaximumAutomaticRedirections = maximumRedirects;
88 httpWebRequest.ReadWriteTimeout = readWriteTimeoutMS;
89 httpWebRequest.Timeout = timeoutMS;
90 httpWebRequest.KeepAlive = false;
91
92 return httpWebRequest;
93 }
94
95 public static string PostToUntrustedUrl(Uri url, string data)
96 {
97 try
98 {
99 byte[] requestData = System.Text.Encoding.UTF8.GetBytes(data);
100
101 HttpWebRequest request = Create(url);
102 request.Method = "POST";
103 request.ContentLength = requestData.Length;
104 request.ContentType = "application/x-www-form-urlencoded";
105
106 using (Stream requestStream = request.GetRequestStream())
107 requestStream.Write(requestData, 0, requestData.Length);
108
109 using (WebResponse response = request.GetResponse())
110 {
111 using (Stream responseStream = response.GetResponseStream())
112 return responseStream.GetStreamString();
113 }
114 }
115 catch (Exception ex)
116 {
117 m_log.Warn("POST to untrusted URL " + url + " failed: " + ex.Message);
118 return null;
119 }
120 }
121
122 public static string GetUntrustedUrl(Uri url)
123 {
124 try
125 {
126 HttpWebRequest request = Create(url);
127
128 using (WebResponse response = request.GetResponse())
129 {
130 using (Stream responseStream = response.GetResponseStream())
131 return responseStream.GetStreamString();
132 }
133 }
134 catch (Exception ex)
135 {
136 m_log.Warn("GET from untrusted URL " + url + " failed: " + ex.Message);
137 return null;
138 }
139 }
140
141 /// <summary>
142 /// Determines whether a URI is allowed based on scheme and host name.
143 /// No requireSSL check is done here
144 /// </summary>
145 /// <param name="allowLoopback">True to allow loopback addresses to be used</param>
146 /// <param name="uri">The URI to test for whether it should be allowed.</param>
147 /// <returns>
148 /// <c>true</c> if [is URI allowable] [the specified URI]; otherwise, <c>false</c>.
149 /// </returns>
150 private static bool IsUriAllowable(Uri uri, bool allowLoopback)
151 {
152 if (!allowableSchemes.Contains(uri.Scheme))
153 {
154 m_log.WarnFormat("Rejecting URL {0} because it uses a disallowed scheme.", uri);
155 return false;
156 }
157
158 // Try to interpret the hostname as an IP address so we can test for internal
159 // IP address ranges. Note that IP addresses can appear in many forms
160 // (e.g. http://127.0.0.1, http://2130706433, http://0x0100007f, http://::1
161 // So we convert them to a canonical IPAddress instance, and test for all
162 // non-routable IP ranges: 10.*.*.*, 127.*.*.*, ::1
163 // Note that Uri.IsLoopback is very unreliable, not catching many of these variants.
164 IPAddress hostIPAddress;
165 if (IPAddress.TryParse(uri.DnsSafeHost, out hostIPAddress))
166 {
167 byte[] addressBytes = hostIPAddress.GetAddressBytes();
168
169 // The host is actually an IP address.
170 switch (hostIPAddress.AddressFamily)
171 {
172 case System.Net.Sockets.AddressFamily.InterNetwork:
173 if (!allowLoopback && (addressBytes[0] == 127 || addressBytes[0] == 10))
174 {
175 m_log.WarnFormat("Rejecting URL {0} because it is a loopback address.", uri);
176 return false;
177 }
178 break;
179 case System.Net.Sockets.AddressFamily.InterNetworkV6:
180 if (!allowLoopback && IsIPv6Loopback(hostIPAddress))
181 {
182 m_log.WarnFormat("Rejecting URL {0} because it is a loopback address.", uri);
183 return false;
184 }
185 break;
186 default:
187 m_log.WarnFormat("Rejecting URL {0} because it does not use an IPv4 or IPv6 address.", uri);
188 return false;
189 }
190 }
191 else
192 {
193 // The host is given by name. We require names to contain periods to
194 // help make sure it's not an internal address.
195 if (!allowLoopback && !uri.Host.Contains("."))
196 {
197 m_log.WarnFormat("Rejecting URL {0} because it does not contain a period in the host name.", uri);
198 return false;
199 }
200 }
201
202 return true;
203 }
204
205 /// <summary>
206 /// Determines whether an IP address is the IPv6 equivalent of "localhost/127.0.0.1".
207 /// </summary>
208 /// <param name="ip">The ip address to check.</param>
209 /// <returns>
210 /// <c>true</c> if this is a loopback IP address; <c>false</c> otherwise.
211 /// </returns>
212 private static bool IsIPv6Loopback(IPAddress ip)
213 {
214 if (ip == null)
215 throw new ArgumentNullException("ip");
216
217 byte[] addressBytes = ip.GetAddressBytes();
218 for (int i = 0; i < addressBytes.Length - 1; i++)
219 {
220 if (addressBytes[i] != 0)
221 return false;
222 }
223
224 if (addressBytes[addressBytes.Length - 1] != 1)
225 return false;
226
227 return true;
228 }
229 }
230}
diff --git a/OpenSim/Framework/UserProfileData.cs b/OpenSim/Framework/UserProfileData.cs
index f7069a5..61d8fe5 100644
--- a/OpenSim/Framework/UserProfileData.cs
+++ b/OpenSim/Framework/UserProfileData.cs
@@ -160,7 +160,11 @@ namespace OpenSim.Framework
160 public virtual ulong HomeRegion 160 public virtual ulong HomeRegion
161 { 161 {
162 get 162 get
163<<<<<<< HEAD
164 {
165=======
163 { 166 {
167>>>>>>> avn/ubitvar
164 return Util.RegionWorldLocToHandle(Util.RegionToWorldLoc(m_homeRegionX), Util.RegionToWorldLoc(m_homeRegionY)); 168 return Util.RegionWorldLocToHandle(Util.RegionToWorldLoc(m_homeRegionX), Util.RegionToWorldLoc(m_homeRegionY));
165 // return Utils.UIntsToLong( m_homeRegionX * (uint)Constants.RegionSize, m_homeRegionY * (uint)Constants.RegionSize); 169 // return Utils.UIntsToLong( m_homeRegionX * (uint)Constants.RegionSize, m_homeRegionY * (uint)Constants.RegionSize);
166 } 170 }
diff --git a/OpenSim/Framework/UserProfiles.cs b/OpenSim/Framework/UserProfiles.cs
index 6133591..944a492 100644
--- a/OpenSim/Framework/UserProfiles.cs
+++ b/OpenSim/Framework/UserProfiles.cs
@@ -77,9 +77,10 @@ namespace OpenSim.Framework
77 public string Desc = string.Empty; 77 public string Desc = string.Empty;
78 public UUID ParcelId = UUID.Zero; 78 public UUID ParcelId = UUID.Zero;
79 public UUID SnapshotId = UUID.Zero; 79 public UUID SnapshotId = UUID.Zero;
80 public string User = string.Empty; 80 public string ParcelName = string.Empty;
81 public string SimName = string.Empty; 81 public string SimName = string.Empty;
82 public string GlobalPos = "<0,0,0>"; 82 public string GlobalPos = "<0,0,0>";
83 public string Gatekeeper = string.Empty;
83 public int SortOrder = 0; 84 public int SortOrder = 0;
84 public bool Enabled = false; 85 public bool Enabled = false;
85 } 86 }
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 5f4ab06..eb3526a 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -51,6 +51,9 @@ using Nwc.XmlRpc;
51using OpenMetaverse; 51using OpenMetaverse;
52using OpenMetaverse.StructuredData; 52using OpenMetaverse.StructuredData;
53using Amib.Threading; 53using Amib.Threading;
54using System.Collections.Concurrent;
55using System.Collections.Specialized;
56using System.Web;
54 57
55namespace OpenSim.Framework 58namespace OpenSim.Framework
56{ 59{
@@ -76,7 +79,7 @@ namespace OpenSim.Framework
76 // All does not contain Export, which is special and must be 79 // All does not contain Export, which is special and must be
77 // explicitly given 80 // explicitly given
78 All = (1 << 13) | (1 << 14) | (1 << 15) | (1 << 19) 81 All = (1 << 13) | (1 << 14) | (1 << 15) | (1 << 19)
79 } 82 }
80 83
81 /// <summary> 84 /// <summary>
82 /// The method used by Util.FireAndForget for asynchronously firing events 85 /// The method used by Util.FireAndForget for asynchronously firing events
@@ -125,8 +128,26 @@ namespace OpenSim.Framework
125 { 128 {
126 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 129 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
127 130
131 /// <summary>
132 /// Log-level for the thread pool:
133 /// 0 = no logging
134 /// 1 = only first line of stack trace; don't log common threads
135 /// 2 = full stack trace; don't log common threads
136 /// 3 = full stack trace, including common threads
137 /// </summary>
138 public static int LogThreadPool { get; set; }
139 public static bool LogOverloads { get; set; }
140
141 public static readonly int MAX_THREADPOOL_LEVEL = 3;
142
143 static Util()
144 {
145 LogThreadPool = 0;
146 LogOverloads = true;
147 }
148
128 private static uint nextXferID = 5000; 149 private static uint nextXferID = 5000;
129 private static Random randomClass = new Random(); 150 private static Random randomClass = new ThreadSafeRandom();
130 151
131 // Get a list of invalid file characters (OS dependent) 152 // Get a list of invalid file characters (OS dependent)
132 private static string regexInvalidFileChars = "[" + new String(Path.GetInvalidFileNameChars()) + "]"; 153 private static string regexInvalidFileChars = "[" + new String(Path.GetInvalidFileNameChars()) + "]";
@@ -138,6 +159,9 @@ namespace OpenSim.Framework
138 /// </summary> 159 /// </summary>
139 private static SmartThreadPool m_ThreadPool; 160 private static SmartThreadPool m_ThreadPool;
140 161
162 // Watchdog timer that aborts threads that have timed-out
163 private static Timer m_threadPoolWatchdog;
164
141 // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC. 165 // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC.
142 public static readonly DateTime UnixEpoch = 166 public static readonly DateTime UnixEpoch =
143 DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime(); 167 DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime();
@@ -403,6 +427,22 @@ namespace OpenSim.Framework
403 return x; 427 return x;
404 } 428 }
405 429
430 /// <summary>
431 /// Check if any of the values in a Vector3 are NaN or Infinity
432 /// </summary>
433 /// <param name="v">Vector3 to check</param>
434 /// <returns></returns>
435 public static bool IsNanOrInfinity(Vector3 v)
436 {
437 if (float.IsNaN(v.X) || float.IsNaN(v.Y) || float.IsNaN(v.Z))
438 return true;
439
440 if (float.IsInfinity(v.X) || float.IsInfinity(v.Y) || float.IsNaN(v.Z))
441 return true;
442
443 return false;
444 }
445
406 // Inclusive, within range test (true if equal to the endpoints) 446 // Inclusive, within range test (true if equal to the endpoints)
407 public static bool InRange<T>(T x, T min, T max) 447 public static bool InRange<T>(T x, T min, T max)
408 where T : IComparable<T> 448 where T : IComparable<T>
@@ -492,6 +532,19 @@ namespace OpenSim.Framework
492 return sb.ToString(); 532 return sb.ToString();
493 } 533 }
494 534
535 public static byte[] DocToBytes(XmlDocument doc)
536 {
537 using (MemoryStream ms = new MemoryStream())
538 using (XmlTextWriter xw = new XmlTextWriter(ms, null))
539 {
540 xw.Formatting = Formatting.Indented;
541 doc.WriteTo(xw);
542 xw.Flush();
543
544 return ms.ToArray();
545 }
546 }
547
495 /// <summary> 548 /// <summary>
496 /// Is the platform Windows? 549 /// Is the platform Windows?
497 /// </summary> 550 /// </summary>
@@ -508,6 +561,11 @@ namespace OpenSim.Framework
508 561
509 public static bool LoadArchSpecificWindowsDll(string libraryName) 562 public static bool LoadArchSpecificWindowsDll(string libraryName)
510 { 563 {
564 return LoadArchSpecificWindowsDll(libraryName, string.Empty);
565 }
566
567 public static bool LoadArchSpecificWindowsDll(string libraryName, string path)
568 {
511 // We do this so that OpenSimulator on Windows loads the correct native library depending on whether 569 // We do this so that OpenSimulator on Windows loads the correct native library depending on whether
512 // it's running as a 32-bit process or a 64-bit one. By invoking LoadLibary here, later DLLImports 570 // it's running as a 32-bit process or a 64-bit one. By invoking LoadLibary here, later DLLImports
513 // will find it already loaded later on. 571 // will find it already loaded later on.
@@ -517,9 +575,9 @@ namespace OpenSim.Framework
517 string nativeLibraryPath; 575 string nativeLibraryPath;
518 576
519 if (Util.Is64BitProcess()) 577 if (Util.Is64BitProcess())
520 nativeLibraryPath = "lib64/" + libraryName; 578 nativeLibraryPath = Path.Combine(Path.Combine(path, "lib64"), libraryName);
521 else 579 else
522 nativeLibraryPath = "lib32/" + libraryName; 580 nativeLibraryPath = Path.Combine(Path.Combine(path, "lib32"), libraryName);
523 581
524 m_log.DebugFormat("[UTIL]: Loading native Windows library at {0}", nativeLibraryPath); 582 m_log.DebugFormat("[UTIL]: Loading native Windows library at {0}", nativeLibraryPath);
525 583
@@ -874,6 +932,54 @@ namespace OpenSim.Framework
874 } 932 }
875 933
876 /// <summary> 934 /// <summary>
935 /// Parses a foreign asset ID.
936 /// </summary>
937 /// <param name="id">A possibly-foreign asset ID: http://grid.example.com:8002/00000000-0000-0000-0000-000000000000 </param>
938 /// <param name="url">The URL: http://grid.example.com:8002</param>
939 /// <param name="assetID">The asset ID: 00000000-0000-0000-0000-000000000000. Returned even if 'id' isn't foreign.</param>
940 /// <returns>True: this is a foreign asset ID; False: it isn't</returns>
941 public static bool ParseForeignAssetID(string id, out string url, out string assetID)
942 {
943 url = String.Empty;
944 assetID = String.Empty;
945
946 UUID uuid;
947 if (UUID.TryParse(id, out uuid))
948 {
949 assetID = uuid.ToString();
950 return false;
951 }
952
953 if ((id.Length == 0) || (id[0] != 'h' && id[0] != 'H'))
954 return false;
955
956 Uri assetUri;
957 if (!Uri.TryCreate(id, UriKind.Absolute, out assetUri) || assetUri.Scheme != Uri.UriSchemeHttp)
958 return false;
959
960 // Simian
961 if (assetUri.Query != string.Empty)
962 {
963 NameValueCollection qscoll = HttpUtility.ParseQueryString(assetUri.Query);
964 assetID = qscoll["id"];
965 if (assetID != null)
966 url = id.Replace(assetID, ""); // Malformed again, as simian expects
967 else
968 url = id; // !!! best effort
969 }
970 else // robust
971 {
972 url = "http://" + assetUri.Authority;
973 assetID = assetUri.LocalPath.Trim(new char[] { '/' });
974 }
975
976 if (!UUID.TryParse(assetID, out uuid))
977 return false;
978
979 return true;
980 }
981
982 /// <summary>
877 /// Removes all invalid path chars (OS dependent) 983 /// Removes all invalid path chars (OS dependent)
878 /// </summary> 984 /// </summary>
879 /// <param name="path">path</param> 985 /// <param name="path">path</param>
@@ -974,11 +1080,12 @@ namespace OpenSim.Framework
974 } 1080 }
975 1081
976 #region Nini (config) related Methods 1082 #region Nini (config) related Methods
1083
977 public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName) 1084 public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName)
978 { 1085 {
979 if (!File.Exists(fileName)) 1086 if (!File.Exists(fileName))
980 { 1087 {
981 //create new file 1088 // create new file
982 } 1089 }
983 XmlConfigSource config = new XmlConfigSource(fileName); 1090 XmlConfigSource config = new XmlConfigSource(fileName);
984 AddDataRowToConfig(config, row); 1091 AddDataRowToConfig(config, row);
@@ -1067,6 +1174,148 @@ namespace OpenSim.Framework
1067 return (T)val; 1174 return (T)val;
1068 } 1175 }
1069 1176
1177 public static void MergeEnvironmentToConfig(IConfigSource ConfigSource)
1178 {
1179 IConfig enVars = ConfigSource.Configs["Environment"];
1180 // if section does not exist then user isn't expecting them, so don't bother.
1181 if( enVars != null )
1182 {
1183 // load the values from the environment
1184 EnvConfigSource envConfigSource = new EnvConfigSource();
1185 // add the requested keys
1186 string[] env_keys = enVars.GetKeys();
1187 foreach ( string key in env_keys )
1188 {
1189 envConfigSource.AddEnv(key, string.Empty);
1190 }
1191 // load the values from environment
1192 envConfigSource.LoadEnv();
1193 // add them in to the master
1194 ConfigSource.Merge(envConfigSource);
1195 ConfigSource.ExpandKeyValues();
1196 }
1197 }
1198
1199 public static T ReadSettingsFromIniFile<T>(IConfig config, T settingsClass)
1200 {
1201 Type settingsType = settingsClass.GetType();
1202
1203 FieldInfo[] fieldInfos = settingsType.GetFields();
1204 foreach (FieldInfo fieldInfo in fieldInfos)
1205 {
1206 if (!fieldInfo.IsStatic)
1207 {
1208 if (fieldInfo.FieldType == typeof(System.String))
1209 {
1210 fieldInfo.SetValue(settingsClass, config.Get(fieldInfo.Name, (string)fieldInfo.GetValue(settingsClass)));
1211 }
1212 else if (fieldInfo.FieldType == typeof(System.Boolean))
1213 {
1214 fieldInfo.SetValue(settingsClass, config.GetBoolean(fieldInfo.Name, (bool)fieldInfo.GetValue(settingsClass)));
1215 }
1216 else if (fieldInfo.FieldType == typeof(System.Int32))
1217 {
1218 fieldInfo.SetValue(settingsClass, config.GetInt(fieldInfo.Name, (int)fieldInfo.GetValue(settingsClass)));
1219 }
1220 else if (fieldInfo.FieldType == typeof(System.Single))
1221 {
1222 fieldInfo.SetValue(settingsClass, config.GetFloat(fieldInfo.Name, (float)fieldInfo.GetValue(settingsClass)));
1223 }
1224 else if (fieldInfo.FieldType == typeof(System.UInt32))
1225 {
1226 fieldInfo.SetValue(settingsClass, Convert.ToUInt32(config.Get(fieldInfo.Name, ((uint)fieldInfo.GetValue(settingsClass)).ToString())));
1227 }
1228 }
1229 }
1230
1231 PropertyInfo[] propertyInfos = settingsType.GetProperties();
1232 foreach (PropertyInfo propInfo in propertyInfos)
1233 {
1234 if ((propInfo.CanRead) && (propInfo.CanWrite))
1235 {
1236 if (propInfo.PropertyType == typeof(System.String))
1237 {
1238 propInfo.SetValue(settingsClass, config.Get(propInfo.Name, (string)propInfo.GetValue(settingsClass, null)), null);
1239 }
1240 else if (propInfo.PropertyType == typeof(System.Boolean))
1241 {
1242 propInfo.SetValue(settingsClass, config.GetBoolean(propInfo.Name, (bool)propInfo.GetValue(settingsClass, null)), null);
1243 }
1244 else if (propInfo.PropertyType == typeof(System.Int32))
1245 {
1246 propInfo.SetValue(settingsClass, config.GetInt(propInfo.Name, (int)propInfo.GetValue(settingsClass, null)), null);
1247 }
1248 else if (propInfo.PropertyType == typeof(System.Single))
1249 {
1250 propInfo.SetValue(settingsClass, config.GetFloat(propInfo.Name, (float)propInfo.GetValue(settingsClass, null)), null);
1251 }
1252 if (propInfo.PropertyType == typeof(System.UInt32))
1253 {
1254 propInfo.SetValue(settingsClass, Convert.ToUInt32(config.Get(propInfo.Name, ((uint)propInfo.GetValue(settingsClass, null)).ToString())), null);
1255 }
1256 }
1257 }
1258
1259 return settingsClass;
1260 }
1261
1262 /// <summary>
1263 /// Reads a configuration file, configFile, merging it with the main configuration, config.
1264 /// If the file doesn't exist, it copies a given exampleConfigFile onto configFile, and then
1265 /// merges it.
1266 /// </summary>
1267 /// <param name="config">The main configuration data</param>
1268 /// <param name="configFileName">The name of a configuration file in ConfigDirectory variable, no path</param>
1269 /// <param name="exampleConfigFile">Full path to an example configuration file</param>
1270 /// <param name="configFilePath">Full path ConfigDirectory/configFileName</param>
1271 /// <param name="created">True if the file was created in ConfigDirectory, false if it existed</param>
1272 /// <returns>True if success</returns>
1273 public static bool MergeConfigurationFile(IConfigSource config, string configFileName, string exampleConfigFile, out string configFilePath, out bool created)
1274 {
1275 created = false;
1276 configFilePath = string.Empty;
1277
1278 IConfig cnf = config.Configs["Startup"];
1279 if (cnf == null)
1280 {
1281 m_log.WarnFormat("[UTILS]: Startup section doesn't exist");
1282 return false;
1283 }
1284
1285 string configDirectory = cnf.GetString("ConfigDirectory", ".");
1286 string configFile = Path.Combine(configDirectory, configFileName);
1287
1288 if (!File.Exists(configFile) && !string.IsNullOrEmpty(exampleConfigFile))
1289 {
1290 // We need to copy the example onto it
1291
1292 if (!Directory.Exists(configDirectory))
1293 Directory.CreateDirectory(configDirectory);
1294
1295 try
1296 {
1297 File.Copy(exampleConfigFile, configFile);
1298 created = true;
1299 }
1300 catch (Exception e)
1301 {
1302 m_log.WarnFormat("[UTILS]: Exception copying configuration file {0} to {1}: {2}", configFile, exampleConfigFile, e.Message);
1303 return false;
1304 }
1305 }
1306
1307 if (File.Exists(configFile))
1308 {
1309 // Merge
1310 config.Merge(new IniConfigSource(configFile));
1311 config.ExpandKeyValues();
1312 configFilePath = configFile;
1313 return true;
1314 }
1315 else
1316 return false;
1317 }
1318
1070 #endregion 1319 #endregion
1071 1320
1072 public static float Clip(float x, float min, float max) 1321 public static float Clip(float x, float min, float max)
@@ -1514,6 +1763,46 @@ namespace OpenSim.Framework
1514 return result; 1763 return result;
1515 } 1764 }
1516 1765
1766 public static void BinaryToASCII(char[] chars)
1767 {
1768 for (int i = 0; i < chars.Length; i++)
1769 {
1770 char ch = chars[i];
1771 if (ch < 32 || ch > 127)
1772 chars[i] = '.';
1773 }
1774 }
1775
1776 public static string BinaryToASCII(string src)
1777 {
1778 char[] chars = src.ToCharArray();
1779 BinaryToASCII(chars);
1780 return new String(chars);
1781 }
1782
1783 /// <summary>
1784 /// Reads a known number of bytes from a stream.
1785 /// Throws EndOfStreamException if the stream doesn't contain enough data.
1786 /// </summary>
1787 /// <param name="stream">The stream to read data from</param>
1788 /// <param name="data">The array to write bytes into. The array
1789 /// will be completely filled from the stream, so an appropriate
1790 /// size must be given.</param>
1791 public static void ReadStream(Stream stream, byte[] data)
1792 {
1793 int offset = 0;
1794 int remaining = data.Length;
1795
1796 while (remaining > 0)
1797 {
1798 int read = stream.Read(data, offset, remaining);
1799 if (read <= 0)
1800 throw new EndOfStreamException(String.Format("End of stream reached with {0} bytes left to read", remaining));
1801 remaining -= read;
1802 offset += read;
1803 }
1804 }
1805
1517 public static Guid GetHashGuid(string data, string salt) 1806 public static Guid GetHashGuid(string data, string salt)
1518 { 1807 {
1519 byte[] hash = ComputeMD5Hash(data + salt, Encoding.Default); 1808 byte[] hash = ComputeMD5Hash(data + salt, Encoding.Default);
@@ -1774,6 +2063,30 @@ namespace OpenSim.Framework
1774 } 2063 }
1775 2064
1776 /// <summary> 2065 /// <summary>
2066 /// Pretty format the hashtable contents to a single line.
2067 /// </summary>
2068 /// <remarks>
2069 /// Used for debugging output.
2070 /// </remarks>
2071 /// <param name='ht'></param>
2072 public static string PrettyFormatToSingleLine(Hashtable ht)
2073 {
2074 StringBuilder sb = new StringBuilder();
2075
2076 int i = 0;
2077
2078 foreach (string key in ht.Keys)
2079 {
2080 sb.AppendFormat("{0}:{1}", key, ht[key]);
2081
2082 if (++i < ht.Count)
2083 sb.AppendFormat(", ");
2084 }
2085
2086 return sb.ToString();
2087 }
2088
2089 /// <summary>
1777 /// Used to trigger an early library load on Windows systems. 2090 /// Used to trigger an early library load on Windows systems.
1778 /// </summary> 2091 /// </summary>
1779 /// <remarks> 2092 /// <remarks>
@@ -1852,10 +2165,15 @@ namespace OpenSim.Framework
1852 { 2165 {
1853 if (maxThreads < 2) 2166 if (maxThreads < 2)
1854 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2"); 2167 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2");
2168
1855 if (minThreads > maxThreads || minThreads < 2) 2169 if (minThreads > maxThreads || minThreads < 2)
1856 throw new ArgumentOutOfRangeException("minThreads", "minThreads must be greater than 2 and less than or equal to maxThreads"); 2170 throw new ArgumentOutOfRangeException("minThreads", "minThreads must be greater than 2 and less than or equal to maxThreads");
2171
1857 if (m_ThreadPool != null) 2172 if (m_ThreadPool != null)
1858 throw new InvalidOperationException("SmartThreadPool is already initialized"); 2173 {
2174 m_log.Warn("SmartThreadPool is already initialized. Ignoring request.");
2175 return;
2176 }
1859 2177
1860 STPStartInfo startInfo = new STPStartInfo(); 2178 STPStartInfo startInfo = new STPStartInfo();
1861 startInfo.ThreadPoolName = "Util"; 2179 startInfo.ThreadPoolName = "Util";
@@ -1864,6 +2182,7 @@ namespace OpenSim.Framework
1864 startInfo.MinWorkerThreads = minThreads; 2182 startInfo.MinWorkerThreads = minThreads;
1865 2183
1866 m_ThreadPool = new SmartThreadPool(startInfo); 2184 m_ThreadPool = new SmartThreadPool(startInfo);
2185 m_threadPoolWatchdog = new Timer(ThreadPoolWatchdog, null, 0, 1000);
1867 } 2186 }
1868 2187
1869 public static int FireAndForgetCount() 2188 public static int FireAndForgetCount()
@@ -1886,15 +2205,179 @@ namespace OpenSim.Framework
1886 throw new NotImplementedException(); 2205 throw new NotImplementedException();
1887 } 2206 }
1888 } 2207 }
2208
2209 /// <summary>
2210 /// Additional information about threads in the main thread pool. Used to time how long the
2211 /// thread has been running, and abort it if it has timed-out.
2212 /// </summary>
2213 private class ThreadInfo
2214 {
2215 public long ThreadFuncNum { get; set; }
2216 public string StackTrace { get; set; }
2217 private string context;
2218 public bool LogThread { get; set; }
2219
2220 public IWorkItemResult WorkItem { get; set; }
2221 public Thread Thread { get; set; }
2222 public bool Running { get; set; }
2223 public bool Aborted { get; set; }
2224 private int started;
2225
2226 public ThreadInfo(long threadFuncNum, string context)
2227 {
2228 ThreadFuncNum = threadFuncNum;
2229 this.context = context;
2230 LogThread = false;
2231 Thread = null;
2232 Running = false;
2233 Aborted = false;
2234 }
2235
2236 public void Started()
2237 {
2238 Thread = Thread.CurrentThread;
2239 started = EnvironmentTickCount();
2240 Running = true;
2241 }
2242
2243 public void Ended()
2244 {
2245 Running = false;
2246 }
2247
2248 public int Elapsed()
2249 {
2250 return EnvironmentTickCountSubtract(started);
2251 }
2252
2253 public void Abort()
2254 {
2255 Aborted = true;
2256 WorkItem.Cancel(true);
2257 }
2258
2259 /// <summary>
2260 /// Returns the thread's stack trace.
2261 /// </summary>
2262 /// <remarks>
2263 /// May return one of two stack traces. First, tries to get the thread's active stack
2264 /// trace. But this can fail, so as a fallback this method will return the stack
2265 /// trace that was active when the task was queued.
2266 /// </remarks>
2267 public string GetStackTrace()
2268 {
2269 string ret = (context == null) ? "" : ("(" + context + ") ");
2270
2271 StackTrace activeStackTrace = Util.GetStackTrace(Thread);
2272 if (activeStackTrace != null)
2273 ret += activeStackTrace.ToString();
2274 else if (StackTrace != null)
2275 ret += "(Stack trace when queued) " + StackTrace;
2276 // else, no stack trace available
2277
2278 return ret;
2279 }
2280 }
2281
2282 private static long nextThreadFuncNum = 0;
2283 private static long numQueuedThreadFuncs = 0;
2284 private static long numRunningThreadFuncs = 0;
2285 private static long numTotalThreadFuncsCalled = 0;
2286 private static Int32 threadFuncOverloadMode = 0;
2287
2288 public static long TotalQueuedFireAndForgetCalls { get { return numQueuedThreadFuncs; } }
2289 public static long TotalRunningFireAndForgetCalls { get { return numRunningThreadFuncs; } }
2290
2291 // Maps (ThreadFunc number -> Thread)
2292 private static ConcurrentDictionary<long, ThreadInfo> activeThreads = new ConcurrentDictionary<long, ThreadInfo>();
2293
2294 private static readonly int THREAD_TIMEOUT = 10 * 60 * 1000; // 10 minutes
2295
2296 /// <summary>
2297 /// Finds threads in the main thread pool that have timed-out, and aborts them.
2298 /// </summary>
2299 private static void ThreadPoolWatchdog(object state)
2300 {
2301 foreach (KeyValuePair<long, ThreadInfo> entry in activeThreads)
2302 {
2303 ThreadInfo t = entry.Value;
2304 if (t.Running && !t.Aborted && (t.Elapsed() >= THREAD_TIMEOUT))
2305 {
2306 m_log.WarnFormat("Timeout in threadfunc {0} ({1}) {2}", t.ThreadFuncNum, t.Thread.Name, t.GetStackTrace());
2307 t.Abort();
2308
2309 ThreadInfo dummy;
2310 activeThreads.TryRemove(entry.Key, out dummy);
2311
2312 // It's possible that the thread won't abort. To make sure the thread pool isn't
2313 // depleted, increase the pool size.
2314 m_ThreadPool.MaxThreads++;
2315 }
2316 }
2317 }
2318
2319 public static long TotalFireAndForgetCallsMade { get { return numTotalThreadFuncsCalled; } }
2320
2321 public static Dictionary<string, int> GetFireAndForgetCallsMade()
2322 {
2323 return new Dictionary<string, int>(m_fireAndForgetCallsMade);
2324 }
2325
2326 private static Dictionary<string, int> m_fireAndForgetCallsMade = new Dictionary<string, int>();
2327
2328 public static Dictionary<string, int> GetFireAndForgetCallsInProgress()
2329 {
2330 return new Dictionary<string, int>(m_fireAndForgetCallsInProgress);
2331 }
2332
2333 private static Dictionary<string, int> m_fireAndForgetCallsInProgress = new Dictionary<string, int>();
2334
2335 public static void FireAndForget(System.Threading.WaitCallback callback)
2336 {
2337 FireAndForget(callback, null, null);
2338 }
1889 2339
1890 public static void FireAndForget(System.Threading.WaitCallback callback, object obj) 2340 public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
1891 { 2341 {
2342 FireAndForget(callback, obj, null);
2343 }
2344
2345 public static void FireAndForget(System.Threading.WaitCallback callback, object obj, string context)
2346 {
2347 Interlocked.Increment(ref numTotalThreadFuncsCalled);
2348
2349 if (context != null)
2350 {
2351 if (!m_fireAndForgetCallsMade.ContainsKey(context))
2352 m_fireAndForgetCallsMade[context] = 1;
2353 else
2354 m_fireAndForgetCallsMade[context]++;
2355
2356 if (!m_fireAndForgetCallsInProgress.ContainsKey(context))
2357 m_fireAndForgetCallsInProgress[context] = 1;
2358 else
2359 m_fireAndForgetCallsInProgress[context]++;
2360 }
2361
1892 WaitCallback realCallback; 2362 WaitCallback realCallback;
1893 2363
2364 bool loggingEnabled = LogThreadPool > 0;
2365
2366 long threadFuncNum = Interlocked.Increment(ref nextThreadFuncNum);
2367 ThreadInfo threadInfo = new ThreadInfo(threadFuncNum, context);
2368
1894 if (FireAndForgetMethod == FireAndForgetMethod.RegressionTest) 2369 if (FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
1895 { 2370 {
1896 // If we're running regression tests, then we want any exceptions to rise up to the test code. 2371 // If we're running regression tests, then we want any exceptions to rise up to the test code.
1897 realCallback = o => { Culture.SetCurrentCulture(); callback(o); }; 2372 realCallback =
2373 o =>
2374 {
2375 Culture.SetCurrentCulture();
2376 callback(o);
2377
2378 if (context != null)
2379 m_fireAndForgetCallsInProgress[context]--;
2380 };
1898 } 2381 }
1899 else 2382 else
1900 { 2383 {
@@ -1903,51 +2386,267 @@ namespace OpenSim.Framework
1903 // for decimals places but is read by a culture that treats commas as number seperators. 2386 // for decimals places but is read by a culture that treats commas as number seperators.
1904 realCallback = o => 2387 realCallback = o =>
1905 { 2388 {
1906 Culture.SetCurrentCulture(); 2389 long numQueued1 = Interlocked.Decrement(ref numQueuedThreadFuncs);
2390 long numRunning1 = Interlocked.Increment(ref numRunningThreadFuncs);
2391 threadInfo.Started();
2392 activeThreads[threadFuncNum] = threadInfo;
1907 2393
1908 try 2394 try
1909 { 2395 {
2396 if ((loggingEnabled || (threadFuncOverloadMode == 1)) && threadInfo.LogThread)
2397 m_log.DebugFormat("Run threadfunc {0} (Queued {1}, Running {2})", threadFuncNum, numQueued1, numRunning1);
2398
2399 Culture.SetCurrentCulture();
2400
1910 callback(o); 2401 callback(o);
1911 } 2402 }
2403 catch (ThreadAbortException e)
2404 {
2405 m_log.Error(string.Format("Aborted threadfunc {0} ", threadFuncNum), e);
2406 }
1912 catch (Exception e) 2407 catch (Exception e)
1913 { 2408 {
1914 m_log.ErrorFormat( 2409 m_log.Error(string.Format("[UTIL]: Util STP threadfunc {0} terminated with error ", threadFuncNum), e);
1915 "[UTIL]: Continuing after async_call_method thread terminated with exception {0}{1}", 2410 }
1916 e.Message, e.StackTrace); 2411 finally
2412 {
2413 Interlocked.Decrement(ref numRunningThreadFuncs);
2414 threadInfo.Ended();
2415 ThreadInfo dummy;
2416 activeThreads.TryRemove(threadFuncNum, out dummy);
2417 if ((loggingEnabled || (threadFuncOverloadMode == 1)) && threadInfo.LogThread)
2418 m_log.DebugFormat("Exit threadfunc {0} ({1})", threadFuncNum, FormatDuration(threadInfo.Elapsed()));
2419
2420 if (context != null)
2421 m_fireAndForgetCallsInProgress[context]--;
1917 } 2422 }
1918 }; 2423 };
1919 } 2424 }
1920 2425
1921 switch (FireAndForgetMethod) 2426 long numQueued = Interlocked.Increment(ref numQueuedThreadFuncs);
2427 try
1922 { 2428 {
1923 case FireAndForgetMethod.RegressionTest: 2429 long numRunning = numRunningThreadFuncs;
1924 case FireAndForgetMethod.None: 2430
1925 realCallback.Invoke(obj); 2431 if (m_ThreadPool != null && LogOverloads)
1926 break; 2432 {
1927 case FireAndForgetMethod.UnsafeQueueUserWorkItem: 2433 if ((threadFuncOverloadMode == 0) && (numRunning >= m_ThreadPool.MaxThreads))
1928 ThreadPool.UnsafeQueueUserWorkItem(realCallback, obj); 2434 {
1929 break; 2435 if (Interlocked.CompareExchange(ref threadFuncOverloadMode, 1, 0) == 0)
1930 case FireAndForgetMethod.QueueUserWorkItem: 2436 m_log.DebugFormat("Threadfunc: enable overload mode (Queued {0}, Running {1})", numQueued, numRunning);
1931 ThreadPool.QueueUserWorkItem(realCallback, obj); 2437 }
1932 break; 2438 else if ((threadFuncOverloadMode == 1) && (numRunning <= (m_ThreadPool.MaxThreads * 2) / 3))
1933 case FireAndForgetMethod.BeginInvoke: 2439 {
1934 FireAndForgetWrapper wrapper = FireAndForgetWrapper.Instance; 2440 if (Interlocked.CompareExchange(ref threadFuncOverloadMode, 0, 1) == 1)
1935 wrapper.FireAndForget(realCallback, obj); 2441 m_log.DebugFormat("Threadfunc: disable overload mode (Queued {0}, Running {1})", numQueued, numRunning);
1936 break; 2442 }
1937 case FireAndForgetMethod.SmartThreadPool: 2443 }
1938 if (m_ThreadPool == null) 2444
1939 InitThreadPool(2, 15); 2445 if (loggingEnabled || (threadFuncOverloadMode == 1))
1940 m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj); 2446 {
1941 break; 2447 string full, partial;
1942 case FireAndForgetMethod.Thread: 2448 GetFireAndForgetStackTrace(out full, out partial);
1943 Thread thread = new Thread(delegate(object o) { realCallback(o); }); 2449 threadInfo.StackTrace = full;
1944 thread.Start(obj); 2450 threadInfo.LogThread = ShouldLogThread(partial);
1945 break; 2451
1946 default: 2452 if (threadInfo.LogThread)
1947 throw new NotImplementedException(); 2453 {
2454 m_log.DebugFormat("Queue threadfunc {0} (Queued {1}, Running {2}) {3}{4}",
2455 threadFuncNum, numQueued, numRunningThreadFuncs,
2456 (context == null) ? "" : ("(" + context + ") "),
2457 (LogThreadPool >= 2) ? full : partial);
2458 }
2459 }
2460 else
2461 {
2462 // Since we didn't log "Queue threadfunc", don't log "Run threadfunc" or "End threadfunc" either.
2463 // Those log lines aren't useful when we don't know which function is running in the thread.
2464 threadInfo.LogThread = false;
2465 }
2466
2467 switch (FireAndForgetMethod)
2468 {
2469 case FireAndForgetMethod.RegressionTest:
2470 case FireAndForgetMethod.None:
2471 realCallback.Invoke(obj);
2472 break;
2473 case FireAndForgetMethod.UnsafeQueueUserWorkItem:
2474 ThreadPool.UnsafeQueueUserWorkItem(realCallback, obj);
2475 break;
2476 case FireAndForgetMethod.QueueUserWorkItem:
2477 ThreadPool.QueueUserWorkItem(realCallback, obj);
2478 break;
2479 case FireAndForgetMethod.BeginInvoke:
2480 FireAndForgetWrapper wrapper = FireAndForgetWrapper.Instance;
2481 wrapper.FireAndForget(realCallback, obj);
2482 break;
2483 case FireAndForgetMethod.SmartThreadPool:
2484 if (m_ThreadPool == null)
2485 InitThreadPool(2, 15);
2486 threadInfo.WorkItem = m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj);
2487 break;
2488 case FireAndForgetMethod.Thread:
2489 Thread thread = new Thread(delegate(object o) { realCallback(o); });
2490 thread.Start(obj);
2491 break;
2492 default:
2493 throw new NotImplementedException();
2494 }
2495 }
2496 catch (Exception)
2497 {
2498 Interlocked.Decrement(ref numQueuedThreadFuncs);
2499 ThreadInfo dummy;
2500 activeThreads.TryRemove(threadFuncNum, out dummy);
2501 throw;
2502 }
2503 }
2504
2505 /// <summary>
2506 /// Returns whether the thread should be logged. Some very common threads aren't logged,
2507 /// to avoid filling up the log.
2508 /// </summary>
2509 /// <param name="stackTrace">A partial stack trace of where the thread was queued</param>
2510 /// <returns>Whether to log this thread</returns>
2511 private static bool ShouldLogThread(string stackTrace)
2512 {
2513 if (LogThreadPool < 3)
2514 {
2515 if (stackTrace.Contains("BeginFireQueueEmpty"))
2516 return false;
2517 }
2518
2519 return true;
2520 }
2521
2522 /// <summary>
2523 /// Returns a stack trace for a thread added using FireAndForget().
2524 /// </summary>
2525 /// <param name="full">Will contain the full stack trace</param>
2526 /// <param name="partial">Will contain only the first frame of the stack trace</param>
2527 private static void GetFireAndForgetStackTrace(out string full, out string partial)
2528 {
2529 string src = Environment.StackTrace;
2530 string[] lines = src.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
2531
2532 StringBuilder dest = new StringBuilder(src.Length);
2533
2534 bool started = false;
2535 bool first = true;
2536 partial = "";
2537
2538 for (int i = 0; i < lines.Length; i++)
2539 {
2540 string line = lines[i];
2541
2542 if (!started)
2543 {
2544 // Skip the initial stack frames, because they're of no interest for debugging
2545 if (line.Contains("StackTrace") || line.Contains("FireAndForget"))
2546 continue;
2547 started = true;
2548 }
2549
2550 if (first)
2551 {
2552 line = line.TrimStart();
2553 first = false;
2554 partial = line;
2555 }
2556
2557 bool last = (i == lines.Length - 1);
2558 if (last)
2559 dest.Append(line);
2560 else
2561 dest.AppendLine(line);
1948 } 2562 }
2563
2564 full = dest.ToString();
1949 } 2565 }
1950 2566
2567#pragma warning disable 0618
2568 /// <summary>
2569 /// Return the stack trace of a different thread.
2570 /// </summary>
2571 /// <remarks>
2572 /// This is complicated because the thread needs to be paused in order to get its stack
2573 /// trace. And pausing another thread can cause a deadlock. This method attempts to
2574 /// avoid deadlock by using a short timeout (200ms), after which it gives up and
2575 /// returns 'null' instead of the stack trace.
2576 ///
2577 /// Take from: http://stackoverflow.com/a/14935378
2578 ///
2579 /// WARNING: this doesn't work in Mono. See https://bugzilla.novell.com/show_bug.cgi?id=571691
2580 ///
2581 /// </remarks>
2582 /// <returns>The stack trace, or null if failed to get it</returns>
2583 private static StackTrace GetStackTrace(Thread targetThread)
2584 {
2585 if (IsPlatformMono)
2586 {
2587 // This doesn't work in Mono
2588 return null;
2589 }
2590
2591 ManualResetEventSlim fallbackThreadReady = new ManualResetEventSlim();
2592 ManualResetEventSlim exitedSafely = new ManualResetEventSlim();
2593
2594 try
2595 {
2596 new Thread(delegate()
2597 {
2598 fallbackThreadReady.Set();
2599 while (!exitedSafely.Wait(200))
2600 {
2601 try
2602 {
2603 targetThread.Resume();
2604 }
2605 catch (Exception)
2606 {
2607 // Whatever happens, do never stop to resume the main-thread regularly until the main-thread has exited safely.
2608 }
2609 }
2610 }).Start();
2611
2612 fallbackThreadReady.Wait();
2613 // From here, you have about 200ms to get the stack-trace
2614
2615 targetThread.Suspend();
2616
2617 StackTrace trace = null;
2618 try
2619 {
2620 trace = new StackTrace(targetThread, true);
2621 }
2622 catch (ThreadStateException)
2623 {
2624 //failed to get stack trace, since the fallback-thread resumed the thread
2625 //possible reasons:
2626 //1.) This thread was just too slow
2627 //2.) A deadlock ocurred
2628 //Automatic retry seems too risky here, so just return null.
2629 }
2630
2631 try
2632 {
2633 targetThread.Resume();
2634 }
2635 catch (ThreadStateException)
2636 {
2637 // Thread is running again already
2638 }
2639
2640 return trace;
2641 }
2642 finally
2643 {
2644 // Signal the fallack-thread to stop
2645 exitedSafely.Set();
2646 }
2647 }
2648#pragma warning restore 0618
2649
1951 /// <summary> 2650 /// <summary>
1952 /// Get information about the current state of the smart thread pool. 2651 /// Get information about the current state of the smart thread pool.
1953 /// </summary> 2652 /// </summary>
@@ -2032,6 +2731,60 @@ namespace OpenSim.Framework
2032 } 2731 }
2033 2732
2034 /// <summary> 2733 /// <summary>
2734 /// Formats a duration (given in milliseconds).
2735 /// </summary>
2736 public static string FormatDuration(int ms)
2737 {
2738 TimeSpan span = new TimeSpan(ms * TimeSpan.TicksPerMillisecond);
2739
2740 string str = "";
2741 string suffix = null;
2742
2743 int hours = (int)span.TotalHours;
2744 if (hours > 0)
2745 {
2746 str += hours.ToString(str.Length == 0 ? "0" : "00");
2747 suffix = "hours";
2748 }
2749
2750 if ((hours > 0) || (span.Minutes > 0))
2751 {
2752 if (str.Length > 0)
2753 str += ":";
2754 str += span.Minutes.ToString(str.Length == 0 ? "0" : "00");
2755 if (suffix == null)
2756 suffix = "min";
2757 }
2758
2759 if ((hours > 0) || (span.Minutes > 0) || (span.Seconds > 0))
2760 {
2761 if (str.Length > 0)
2762 str += ":";
2763 str += span.Seconds.ToString(str.Length == 0 ? "0" : "00");
2764 if (suffix == null)
2765 suffix = "sec";
2766 }
2767
2768 if (suffix == null)
2769 suffix = "ms";
2770
2771 if (span.TotalMinutes < 1)
2772 {
2773 int ms1 = span.Milliseconds;
2774 if (str.Length > 0)
2775 {
2776 ms1 /= 100;
2777 str += ".";
2778 }
2779 str += ms1.ToString("0");
2780 }
2781
2782 str += " " + suffix;
2783
2784 return str;
2785 }
2786
2787 /// <summary>
2035 /// Prints the call stack at any given point. Useful for debugging. 2788 /// Prints the call stack at any given point. Useful for debugging.
2036 /// </summary> 2789 /// </summary>
2037 public static void PrintCallStack() 2790 public static void PrintCallStack()
@@ -2098,7 +2851,7 @@ namespace OpenSim.Framework
2098 } 2851 }
2099 2852
2100 #region Xml Serialization Utilities 2853 #region Xml Serialization Utilities
2101 public static bool ReadBoolean(XmlTextReader reader) 2854 public static bool ReadBoolean(XmlReader reader)
2102 { 2855 {
2103 // AuroraSim uses "int" for some fields that are boolean in OpenSim, e.g. "PassCollisions". Don't fail because of this. 2856 // AuroraSim uses "int" for some fields that are boolean in OpenSim, e.g. "PassCollisions". Don't fail because of this.
2104 reader.ReadStartElement(); 2857 reader.ReadStartElement();
@@ -2109,7 +2862,7 @@ namespace OpenSim.Framework
2109 return result; 2862 return result;
2110 } 2863 }
2111 2864
2112 public static UUID ReadUUID(XmlTextReader reader, string name) 2865 public static UUID ReadUUID(XmlReader reader, string name)
2113 { 2866 {
2114 UUID id; 2867 UUID id;
2115 string idStr; 2868 string idStr;
@@ -2128,7 +2881,7 @@ namespace OpenSim.Framework
2128 return id; 2881 return id;
2129 } 2882 }
2130 2883
2131 public static Vector3 ReadVector(XmlTextReader reader, string name) 2884 public static Vector3 ReadVector(XmlReader reader, string name)
2132 { 2885 {
2133 Vector3 vec; 2886 Vector3 vec;
2134 2887
@@ -2141,7 +2894,7 @@ namespace OpenSim.Framework
2141 return vec; 2894 return vec;
2142 } 2895 }
2143 2896
2144 public static Quaternion ReadQuaternion(XmlTextReader reader, string name) 2897 public static Quaternion ReadQuaternion(XmlReader reader, string name)
2145 { 2898 {
2146 Quaternion quat = new Quaternion(); 2899 Quaternion quat = new Quaternion();
2147 2900
@@ -2170,7 +2923,7 @@ namespace OpenSim.Framework
2170 return quat; 2923 return quat;
2171 } 2924 }
2172 2925
2173 public static T ReadEnum<T>(XmlTextReader reader, string name) 2926 public static T ReadEnum<T>(XmlReader reader, string name)
2174 { 2927 {
2175 string value = reader.ReadElementContentAsString(name, String.Empty); 2928 string value = reader.ReadElementContentAsString(name, String.Empty);
2176 // !!!!! to deal with flags without commas 2929 // !!!!! to deal with flags without commas
@@ -2182,7 +2935,9 @@ namespace OpenSim.Framework
2182 #endregion 2935 #endregion
2183 2936
2184 #region Universal User Identifiers 2937 #region Universal User Identifiers
2185 /// <summary> 2938
2939 /// <summary>
2940 /// Attempts to parse a UUI into its components: UUID, name and URL.
2186 /// </summary> 2941 /// </summary>
2187 /// <param name="value">uuid[;endpoint[;first last[;secret]]]</param> 2942 /// <param name="value">uuid[;endpoint[;first last[;secret]]]</param>
2188 /// <param name="uuid">the uuid part</param> 2943 /// <param name="uuid">the uuid part</param>
@@ -2218,6 +2973,27 @@ namespace OpenSim.Framework
2218 } 2973 }
2219 2974
2220 /// <summary> 2975 /// <summary>
2976 /// For foreign avatars, extracts their original name and Server URL from their First Name and Last Name.
2977 /// </summary>
2978 public static bool ParseForeignAvatarName(string firstname, string lastname,
2979 out string realFirstName, out string realLastName, out string serverURI)
2980 {
2981 realFirstName = realLastName = serverURI = string.Empty;
2982
2983 if (!lastname.Contains("@"))
2984 return false;
2985
2986 if (!firstname.Contains("."))
2987 return false;
2988
2989 realFirstName = firstname.Split('.')[0];
2990 realLastName = firstname.Split('.')[1];
2991 serverURI = new Uri("http://" + lastname.Replace("@", "")).ToString();
2992
2993 return true;
2994 }
2995
2996 /// <summary>
2221 /// Produces a universal (HG) system-facing identifier given the information 2997 /// Produces a universal (HG) system-facing identifier given the information
2222 /// </summary> 2998 /// </summary>
2223 /// <param name="acircuit"></param> 2999 /// <param name="acircuit"></param>
@@ -2250,10 +3026,15 @@ namespace OpenSim.Framework
2250 { 3026 {
2251 string[] parts = firstName.Split(new char[] { '.' }); 3027 string[] parts = firstName.Split(new char[] { '.' });
2252 if (parts.Length == 2) 3028 if (parts.Length == 2)
2253 return id.ToString() + ";" + agentsURI + ";" + parts[0] + " " + parts[1]; 3029 return CalcUniversalIdentifier(id, agentsURI, parts[0] + " " + parts[1]);
2254 } 3030 }
2255 return id.ToString() + ";" + agentsURI + ";" + firstName + " " + lastName; 3031
3032 return CalcUniversalIdentifier(id, agentsURI, firstName + " " + lastName);
3033 }
2256 3034
3035 private static string CalcUniversalIdentifier(UUID id, string agentsURI, string name)
3036 {
3037 return id.ToString() + ";" + agentsURI + ";" + name;
2257 } 3038 }
2258 3039
2259 /// <summary> 3040 /// <summary>
@@ -2288,6 +3069,48 @@ namespace OpenSim.Framework
2288 { 3069 {
2289 return str.Replace("_", "\\_").Replace("%", "\\%"); 3070 return str.Replace("_", "\\_").Replace("%", "\\%");
2290 } 3071 }
3072
3073 /// <summary>
3074 /// Returns the name of the user's viewer.
3075 /// </summary>
3076 /// <remarks>
3077 /// This method handles two ways that viewers specify their name:
3078 /// 1. Viewer = "Firestorm-Release 4.4.2.34167", Channel = "(don't care)" -> "Firestorm-Release 4.4.2.34167"
3079 /// 2. Viewer = "4.5.1.38838", Channel = "Firestorm-Beta" -> "Firestorm-Beta 4.5.1.38838"
3080 /// </remarks>
3081 public static string GetViewerName(AgentCircuitData agent)
3082 {
3083 string name = agent.Viewer;
3084 if (name == null)
3085 name = "";
3086 else
3087 name = name.Trim();
3088
3089 // Check if 'Viewer' is just a version number. If it's *not*, then we
3090 // assume that it contains the real viewer name, and we return it.
3091 foreach (char c in name)
3092 {
3093 if (Char.IsLetter(c))
3094 return name;
3095 }
3096
3097 // The 'Viewer' string contains just a version number. If there's anything in
3098 // 'Channel' then assume that it's the viewer name.
3099 if ((agent.Channel != null) && (agent.Channel.Length > 0))
3100 name = agent.Channel.Trim() + " " + name;
3101
3102 return name;
3103 }
3104
3105 public static void LogFailedXML(string message, string xml)
3106 {
3107 int length = xml.Length;
3108 if (length > 2000)
3109 xml = xml.Substring(0, 2000) + "...";
3110
3111 m_log.ErrorFormat("{0} Failed XML ({1} bytes) = {2}", message, length, xml);
3112 }
3113
2291 } 3114 }
2292 3115
2293 public class DoubleQueue<T> where T:class 3116 public class DoubleQueue<T> where T:class
@@ -2304,7 +3127,11 @@ namespace OpenSim.Framework
2304 3127
2305 public virtual int Count 3128 public virtual int Count
2306 { 3129 {
2307 get { return m_highQueue.Count + m_lowQueue.Count; } 3130 get
3131 {
3132 lock (m_syncRoot)
3133 return m_highQueue.Count + m_lowQueue.Count;
3134 }
2308 } 3135 }
2309 3136
2310 public virtual void Enqueue(T data) 3137 public virtual void Enqueue(T data)
@@ -2397,4 +3224,55 @@ namespace OpenSim.Framework
2397 } 3224 }
2398 } 3225 }
2399 } 3226 }
3227
3228 public class BetterRandom
3229 {
3230 private const int BufferSize = 1024; // must be a multiple of 4
3231 private byte[] RandomBuffer;
3232 private int BufferOffset;
3233 private RNGCryptoServiceProvider rng;
3234 public BetterRandom()
3235 {
3236 RandomBuffer = new byte[BufferSize];
3237 rng = new RNGCryptoServiceProvider();
3238 BufferOffset = RandomBuffer.Length;
3239 }
3240 private void FillBuffer()
3241 {
3242 rng.GetBytes(RandomBuffer);
3243 BufferOffset = 0;
3244 }
3245 public int Next()
3246 {
3247 if (BufferOffset >= RandomBuffer.Length)
3248 {
3249 FillBuffer();
3250 }
3251 int val = BitConverter.ToInt32(RandomBuffer, BufferOffset) & 0x7fffffff;
3252 BufferOffset += sizeof(int);
3253 return val;
3254 }
3255 public int Next(int maxValue)
3256 {
3257 return Next() % maxValue;
3258 }
3259 public int Next(int minValue, int maxValue)
3260 {
3261 if (maxValue < minValue)
3262 {
3263 throw new ArgumentOutOfRangeException("maxValue must be greater than or equal to minValue");
3264 }
3265 int range = maxValue - minValue;
3266 return minValue + Next(range);
3267 }
3268 public double NextDouble()
3269 {
3270 int val = Next();
3271 return (double)val / int.MaxValue;
3272 }
3273 public void GetBytes(byte[] buff)
3274 {
3275 rng.GetBytes(buff);
3276 }
3277 }
2400} 3278}
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/VersionInfo.cs
index 33b1366..ea99444 100644
--- a/OpenSim/Framework/Servers/VersionInfo.cs
+++ b/OpenSim/Framework/VersionInfo.cs
@@ -29,7 +29,11 @@ namespace OpenSim
29{ 29{
30 public class VersionInfo 30 public class VersionInfo
31 { 31 {
32<<<<<<< HEAD:OpenSim/Framework/VersionInfo.cs
33 public const string VersionNumber = "0.8.2.0";
34=======
32 private const string VERSION_NUMBER = "0.8.0CM"; 35 private const string VERSION_NUMBER = "0.8.0CM";
36>>>>>>> avn/ubitvar:OpenSim/Framework/Servers/VersionInfo.cs
33 private const Flavour VERSION_FLAVOUR = Flavour.Dev; 37 private const Flavour VERSION_FLAVOUR = Flavour.Dev;
34 38
35 public enum Flavour 39 public enum Flavour
@@ -38,6 +42,7 @@ namespace OpenSim
38 Dev, 42 Dev,
39 RC1, 43 RC1,
40 RC2, 44 RC2,
45 RC3,
41 Release, 46 Release,
42 Post_Fixes, 47 Post_Fixes,
43 Extended 48 Extended
@@ -45,7 +50,7 @@ namespace OpenSim
45 50
46 public static string Version 51 public static string Version
47 { 52 {
48 get { return GetVersionString(VERSION_NUMBER, VERSION_FLAVOUR); } 53 get { return GetVersionString(VersionNumber, VERSION_FLAVOUR); }
49 } 54 }
50 55
51 public static string GetVersionString(string versionNumber, Flavour flavour) 56 public static string GetVersionString(string versionNumber, Flavour flavour)
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index 3625a1f..94b5230 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -39,8 +39,13 @@ using System.Text;
39using System.Web; 39using System.Web;
40using System.Xml; 40using System.Xml;
41using System.Xml.Serialization; 41using System.Xml.Serialization;
42using System.Xml.Linq;
42using log4net; 43using log4net;
44using Nwc.XmlRpc;
43using OpenMetaverse.StructuredData; 45using OpenMetaverse.StructuredData;
46using XMLResponseHelper = OpenSim.Framework.SynchronousRestObjectRequester.XMLResponseHelper;
47
48using OpenSim.Framework.ServiceAuth;
44 49
45namespace OpenSim.Framework 50namespace OpenSim.Framework
46{ 51{
@@ -64,7 +69,7 @@ namespace OpenSim.Framework
64 /// <summary> 69 /// <summary>
65 /// Request number for diagnostic purposes. 70 /// Request number for diagnostic purposes.
66 /// </summary> 71 /// </summary>
67 public static int RequestNumber { get; internal set; } 72 public static int RequestNumber { get; set; }
68 73
69 /// <summary> 74 /// <summary>
70 /// Control where OSD requests should be serialized per endpoint. 75 /// Control where OSD requests should be serialized per endpoint.
@@ -89,8 +94,9 @@ namespace OpenSim.Framework
89 /// <remarks> 94 /// <remarks>
90 /// This is to truncate any really large post data, such as an asset. In theory, the first section should 95 /// This is to truncate any really large post data, such as an asset. In theory, the first section should
91 /// give us useful information about the call (which agent it relates to if applicable, etc.). 96 /// give us useful information about the call (which agent it relates to if applicable, etc.).
97 /// This is also used to truncate messages when using DebugLevel 5.
92 /// </remarks> 98 /// </remarks>
93 public const int MaxRequestDiagLength = 100; 99 public const int MaxRequestDiagLength = 200;
94 100
95 /// <summary> 101 /// <summary>
96 /// Dictionary of end points 102 /// Dictionary of end points
@@ -125,88 +131,112 @@ namespace OpenSim.Framework
125 /// </summary> 131 /// </summary>
126 public static OSDMap PutToServiceCompressed(string url, OSDMap data, int timeout) 132 public static OSDMap PutToServiceCompressed(string url, OSDMap data, int timeout)
127 { 133 {
128 return ServiceOSDRequest(url,data, "PUT", timeout, true); 134 return ServiceOSDRequest(url,data, "PUT", timeout, true, false);
129 } 135 }
130 136
131 public static OSDMap PutToService(string url, OSDMap data, int timeout) 137 public static OSDMap PutToService(string url, OSDMap data, int timeout)
132 { 138 {
133 return ServiceOSDRequest(url,data, "PUT", timeout, false); 139 return ServiceOSDRequest(url,data, "PUT", timeout, false, false);
134 } 140 }
135 141
136 public static OSDMap PostToService(string url, OSDMap data, int timeout) 142 public static OSDMap PostToService(string url, OSDMap data, int timeout, bool rpc)
137 { 143 {
138 return ServiceOSDRequest(url, data, "POST", timeout, false); 144 return ServiceOSDRequest(url, data, "POST", timeout, false, rpc);
139 } 145 }
140 146
141 public static OSDMap PostToServiceCompressed(string url, OSDMap data, int timeout) 147 public static OSDMap PostToServiceCompressed(string url, OSDMap data, int timeout)
142 { 148 {
143 return ServiceOSDRequest(url, data, "POST", timeout, true); 149 return ServiceOSDRequest(url, data, "POST", timeout, true, false);
144 } 150 }
145 151
146 public static OSDMap GetFromService(string url, int timeout) 152 public static OSDMap GetFromService(string url, int timeout)
147 { 153 {
148 return ServiceOSDRequest(url, null, "GET", timeout, false); 154 return ServiceOSDRequest(url, null, "GET", timeout, false, false);
149 } 155 }
150 156
151 public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed) 157 public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed, bool rpc)
152 { 158 {
153 if (SerializeOSDRequestsPerEndpoint) 159 if (SerializeOSDRequestsPerEndpoint)
154 { 160 {
155 lock (EndPointLock(url)) 161 lock (EndPointLock(url))
156 { 162 {
157 return ServiceOSDRequestWorker(url, data, method, timeout, compressed); 163 return ServiceOSDRequestWorker(url, data, method, timeout, compressed, rpc);
158 } 164 }
159 } 165 }
160 else 166 else
161 { 167 {
162 return ServiceOSDRequestWorker(url, data, method, timeout, compressed); 168 return ServiceOSDRequestWorker(url, data, method, timeout, compressed, rpc);
163 } 169 }
164 } 170 }
165 171
166 public static void LogOutgoingDetail(Stream outputStream) 172 public static void LogOutgoingDetail(Stream outputStream)
167 { 173 {
168 using (StreamReader reader = new StreamReader(Util.Copy(outputStream), Encoding.UTF8)) 174 LogOutgoingDetail("", outputStream);
175 }
176
177 public static void LogOutgoingDetail(string context, Stream outputStream)
178 {
179 using (Stream stream = Util.Copy(outputStream))
180 using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
169 { 181 {
170 string output; 182 string output;
171 183
172 if (DebugLevel == 5) 184 if (DebugLevel == 5)
173 { 185 {
174 const int sampleLength = 80; 186 char[] chars = new char[WebUtil.MaxRequestDiagLength + 1]; // +1 so we know to add "..." only if needed
175 char[] sampleChars = new char[sampleLength]; 187 int len = reader.Read(chars, 0, WebUtil.MaxRequestDiagLength + 1);
176 reader.Read(sampleChars, 0, sampleLength); 188 output = new string(chars, 0, len);
177 output = new string(sampleChars);
178 } 189 }
179 else 190 else
180 { 191 {
181 output = reader.ReadToEnd(); 192 output = reader.ReadToEnd();
182 } 193 }
183 194
184 LogOutgoingDetail(output); 195 LogOutgoingDetail(context, output);
185 } 196 }
186 } 197 }
187 198
188 public static void LogOutgoingDetail(string output) 199 public static void LogOutgoingDetail(string type, int reqnum, string output)
200 {
201 LogOutgoingDetail(string.Format("{0} {1}: ", type, reqnum), output);
202 }
203
204 public static void LogOutgoingDetail(string context, string output)
189 { 205 {
190 if (DebugLevel == 5) 206 if (DebugLevel == 5)
191 { 207 {
208<<<<<<< HEAD
209 if (output.Length > MaxRequestDiagLength)
210 output = output.Substring(0, MaxRequestDiagLength) + "...";
211=======
192 int len = output.Length; 212 int len = output.Length;
193 if(len > 80) 213 if(len > 80)
194 len = 80; 214 len = 80;
195 output = output.Substring(0, len); 215 output = output.Substring(0, len);
196 output = output + "..."; 216 output = output + "...";
217>>>>>>> avn/ubitvar
197 } 218 }
198 219
199 m_log.DebugFormat("[WEB UTIL]: {0}", output.Replace("\n", @"\n")); 220 m_log.DebugFormat("[LOGHTTP]: {0}{1}", context, Util.BinaryToASCII(output));
221 }
222
223 public static void LogResponseDetail(int reqnum, Stream inputStream)
224 {
225 LogOutgoingDetail(string.Format("RESPONSE {0}: ", reqnum), inputStream);
200 } 226 }
201 227
202 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed) 228 public static void LogResponseDetail(int reqnum, string input)
229 {
230 LogOutgoingDetail(string.Format("RESPONSE {0}: ", reqnum), input);
231 }
232
233 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed, bool rpc)
203 { 234 {
204 int reqnum = RequestNumber++; 235 int reqnum = RequestNumber++;
205 236
206 if (DebugLevel >= 3) 237 if (DebugLevel >= 3)
207 m_log.DebugFormat( 238 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} JSON-RPC {1} to {2}",
208 "[WEB UTIL]: HTTP OUT {0} ServiceOSD {1} {2} (timeout {3}, compressed {4})", 239 reqnum, method, url);
209 reqnum, method, url, timeout, compressed);
210 240
211 string errorMessage = "unknown error"; 241 string errorMessage = "unknown error";
212 int tickstart = Util.EnvironmentTickCount(); 242 int tickstart = Util.EnvironmentTickCount();
@@ -234,21 +264,24 @@ namespace OpenSim.Framework
234 tickJsondata = Util.EnvironmentTickCountSubtract(tickstart); 264 tickJsondata = Util.EnvironmentTickCountSubtract(tickstart);
235 265
236 if (DebugLevel >= 5) 266 if (DebugLevel >= 5)
237 LogOutgoingDetail(strBuffer); 267 LogOutgoingDetail("SEND", reqnum, strBuffer);
238 268
239 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer); 269 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer);
240 270
271 request.ContentType = rpc ? "application/json-rpc" : "application/json";
272
241 if (compressed) 273 if (compressed)
242 { 274 {
243 request.ContentType = "application/x-gzip"; 275 request.Headers["X-Content-Encoding"] = "gzip"; // can't set "Content-Encoding" because old OpenSims fail if they get an unrecognized Content-Encoding
276
244 using (MemoryStream ms = new MemoryStream()) 277 using (MemoryStream ms = new MemoryStream())
245 { 278 {
246 using (GZipStream comp = new GZipStream(ms, CompressionMode.Compress)) 279 using (GZipStream comp = new GZipStream(ms, CompressionMode.Compress, true))
247 { 280 {
248 comp.Write(buffer, 0, buffer.Length); 281 comp.Write(buffer, 0, buffer.Length);
249 // We need to close the gzip stream before we write it anywhere 282 // We need to close the gzip stream before we write it anywhere
250 // because apparently something important related to gzip compression 283 // because apparently something important related to gzip compression
251 // gets written on the strteam upon Dispose() 284 // gets written on the stream upon Dispose()
252 } 285 }
253 byte[] buf = ms.ToArray(); 286 byte[] buf = ms.ToArray();
254 287
@@ -262,12 +295,15 @@ namespace OpenSim.Framework
262 } 295 }
263 else 296 else
264 { 297 {
298<<<<<<< HEAD
299=======
265 tickcompressdata = tickJsondata; 300 tickcompressdata = tickJsondata;
266 compsize = buffer.Length; 301 compsize = buffer.Length;
267 request.ContentType = "application/json"; 302 request.ContentType = "application/json";
303>>>>>>> avn/ubitvar
268 request.ContentLength = buffer.Length; //Count bytes to send 304 request.ContentLength = buffer.Length; //Count bytes to send
269 using (Stream requestStream = request.GetRequestStream()) 305 using (Stream requestStream = request.GetRequestStream())
270 requestStream.Write(buffer, 0, buffer.Length); //Send it 306 requestStream.Write(buffer, 0, buffer.Length); //Send it
271 } 307 }
272 } 308 }
273 309
@@ -279,10 +315,20 @@ namespace OpenSim.Framework
279 { 315 {
280 using (Stream responseStream = response.GetResponseStream()) 316 using (Stream responseStream = response.GetResponseStream())
281 { 317 {
318<<<<<<< HEAD
319 using (StreamReader reader = new StreamReader(responseStream))
320 {
321 string responseStr = reader.ReadToEnd();
322 if (WebUtil.DebugLevel >= 5)
323 WebUtil.LogResponseDetail(reqnum, responseStr);
324 return CanonicalizeResults(responseStr);
325 }
326=======
282 string responseStr = null; 327 string responseStr = null;
283 responseStr = responseStream.GetStreamString(); 328 responseStr = responseStream.GetStreamString();
284 //m_log.DebugFormat("[WEB UTIL]: <{0}> response is <{1}>",reqnum,responseStr); 329 //m_log.DebugFormat("[WEB UTIL]: <{0}> response is <{1}>",reqnum,responseStr);
285 return CanonicalizeResults(responseStr); 330 return CanonicalizeResults(responseStr);
331>>>>>>> avn/ubitvar
286 } 332 }
287 } 333 }
288 } 334 }
@@ -304,7 +350,12 @@ namespace OpenSim.Framework
304 { 350 {
305 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 351 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
306 if (tickdiff > LongCallTime) 352 if (tickdiff > LongCallTime)
353 {
307 m_log.InfoFormat( 354 m_log.InfoFormat(
355<<<<<<< HEAD
356 "[LOGHTTP]: Slow JSON-RPC request {0} {1} to {2} took {3}ms, {4}ms writing, {5}",
357 reqnum, method, url, tickdiff, tickdata,
358=======
308 "[WEB UTIL]: Slow ServiceOSD request {0} {1} {2} took {3}ms, {4}ms writing({5} at Json; {6} at comp), {7} bytes ({8} uncomp): {9}", 359 "[WEB UTIL]: Slow ServiceOSD request {0} {1} {2} took {3}ms, {4}ms writing({5} at Json; {6} at comp), {7} bytes ({8} uncomp): {9}",
309 reqnum, 360 reqnum,
310 method, 361 method,
@@ -315,17 +366,20 @@ namespace OpenSim.Framework
315 tickcompressdata, 366 tickcompressdata,
316 compsize, 367 compsize,
317 strBuffer != null ? strBuffer.Length : 0, 368 strBuffer != null ? strBuffer.Length : 0,
369>>>>>>> avn/ubitvar
318 strBuffer != null 370 strBuffer != null
319 ? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer) 371 ? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer)
320 : ""); 372 : "");
373 }
321 else if (DebugLevel >= 4) 374 else if (DebugLevel >= 4)
322 m_log.DebugFormat( 375 {
323 "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing", 376 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} took {1}ms, {2}ms writing",
324 reqnum, tickdiff, tickdata); 377 reqnum, tickdiff, tickdata);
378 }
325 } 379 }
326 380
327 m_log.DebugFormat( 381 m_log.DebugFormat(
328 "[WEB UTIL]: ServiceOSD request {0} {1} {2} FAILED: {3}", reqnum, url, method, errorMessage); 382 "[LOGHTTP]: JSON-RPC request {0} {1} to {2} FAILED: {3}", reqnum, method, url, errorMessage);
329 383
330 return ErrorResponseMap(errorMessage); 384 return ErrorResponseMap(errorMessage);
331 } 385 }
@@ -403,9 +457,8 @@ namespace OpenSim.Framework
403 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown"; 457 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown";
404 458
405 if (DebugLevel >= 3) 459 if (DebugLevel >= 3)
406 m_log.DebugFormat( 460 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} ServiceForm '{1}' to {2}",
407 "[WEB UTIL]: HTTP OUT {0} ServiceForm {1} {2} (timeout {3})", 461 reqnum, method, url);
408 reqnum, method, url, timeout);
409 462
410 string errorMessage = "unknown error"; 463 string errorMessage = "unknown error";
411 int tickstart = Util.EnvironmentTickCount(); 464 int tickstart = Util.EnvironmentTickCount();
@@ -427,7 +480,7 @@ namespace OpenSim.Framework
427 queryString = BuildQueryString(data); 480 queryString = BuildQueryString(data);
428 481
429 if (DebugLevel >= 5) 482 if (DebugLevel >= 5)
430 LogOutgoingDetail(queryString); 483 LogOutgoingDetail("SEND", reqnum, queryString);
431 484
432 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString); 485 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString);
433 486
@@ -445,12 +498,16 @@ namespace OpenSim.Framework
445 { 498 {
446 using (Stream responseStream = response.GetResponseStream()) 499 using (Stream responseStream = response.GetResponseStream())
447 { 500 {
448 string responseStr = null; 501 using (StreamReader reader = new StreamReader(responseStream))
502 {
503 string responseStr = reader.ReadToEnd();
504 if (WebUtil.DebugLevel >= 5)
505 WebUtil.LogResponseDetail(reqnum, responseStr);
506 OSD responseOSD = OSDParser.Deserialize(responseStr);
449 507
450 responseStr = responseStream.GetStreamString(); 508 if (responseOSD.Type == OSDType.Map)
451 OSD responseOSD = OSDParser.Deserialize(responseStr); 509 return (OSDMap)responseOSD;
452 if (responseOSD.Type == OSDType.Map) 510 }
453 return (OSDMap)responseOSD;
454 } 511 }
455 } 512 }
456 } 513 }
@@ -471,23 +528,22 @@ namespace OpenSim.Framework
471 { 528 {
472 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 529 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
473 if (tickdiff > LongCallTime) 530 if (tickdiff > LongCallTime)
531 {
474 m_log.InfoFormat( 532 m_log.InfoFormat(
475 "[WEB UTIL]: Slow ServiceForm request {0} {1} {2} took {3}ms, {4}ms writing, {5}", 533 "[LOGHTTP]: Slow ServiceForm request {0} '{1}' to {2} took {3}ms, {4}ms writing, {5}",
476 reqnum, 534 reqnum, method, url, tickdiff, tickdata,
477 method,
478 url,
479 tickdiff,
480 tickdata,
481 queryString != null 535 queryString != null
482 ? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString 536 ? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString
483 : ""); 537 : "");
538 }
484 else if (DebugLevel >= 4) 539 else if (DebugLevel >= 4)
485 m_log.DebugFormat( 540 {
486 "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing", 541 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} took {1}ms, {2}ms writing",
487 reqnum, tickdiff, tickdata); 542 reqnum, tickdiff, tickdata);
543 }
488 } 544 }
489 545
490 m_log.WarnFormat("[WEB UTIL]: ServiceForm request {0} {1} {2} failed: {2}", reqnum, method, url, errorMessage); 546 m_log.WarnFormat("[LOGHTTP]: ServiceForm request {0} '{1}' to {2} failed: {3}", reqnum, method, url, errorMessage);
491 547
492 return ErrorResponseMap(errorMessage); 548 return ErrorResponseMap(errorMessage);
493 } 549 }
@@ -664,38 +720,6 @@ namespace OpenSim.Framework
664 return totalCopiedBytes; 720 return totalCopiedBytes;
665 } 721 }
666 722
667 /// <summary>
668 /// Converts an entire stream to a string, regardless of current stream
669 /// position
670 /// </summary>
671 /// <param name="stream">The stream to convert to a string</param>
672 /// <returns></returns>
673 /// <remarks>When this method is done, the stream position will be
674 /// reset to its previous position before this method was called</remarks>
675 public static string GetStreamString(this Stream stream)
676 {
677 string value = null;
678
679 if (stream != null && stream.CanRead)
680 {
681 long rewindPos = -1;
682
683 if (stream.CanSeek)
684 {
685 rewindPos = stream.Position;
686 stream.Seek(0, SeekOrigin.Begin);
687 }
688
689 StreamReader reader = new StreamReader(stream);
690 value = reader.ReadToEnd();
691
692 if (rewindPos >= 0)
693 stream.Seek(rewindPos, SeekOrigin.Begin);
694 }
695
696 return value;
697 }
698
699 #endregion Stream 723 #endregion Stream
700 724
701 public class QBasedComparer : IComparer 725 public class QBasedComparer : IComparer
@@ -796,11 +820,17 @@ namespace OpenSim.Framework
796 string requestUrl, TRequest obj, Action<TResponse> action, 820 string requestUrl, TRequest obj, Action<TResponse> action,
797 int maxConnections) 821 int maxConnections)
798 { 822 {
823 MakeRequest<TRequest, TResponse>(verb, requestUrl, obj, action, maxConnections, null);
824 }
825
826 public static void MakeRequest<TRequest, TResponse>(string verb,
827 string requestUrl, TRequest obj, Action<TResponse> action,
828 int maxConnections, IServiceAuth auth)
829 {
799 int reqnum = WebUtil.RequestNumber++; 830 int reqnum = WebUtil.RequestNumber++;
800 831
801 if (WebUtil.DebugLevel >= 3) 832 if (WebUtil.DebugLevel >= 3)
802 m_log.DebugFormat( 833 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} AsynchronousRequestObject {1} to {2}",
803 "[WEB UTIL]: HTTP OUT {0} AsynchronousRequestObject {1} {2}",
804 reqnum, verb, requestUrl); 834 reqnum, verb, requestUrl);
805 835
806 int tickstart = Util.EnvironmentTickCount(); 836 int tickstart = Util.EnvironmentTickCount();
@@ -811,125 +841,170 @@ namespace OpenSim.Framework
811 841
812 WebRequest request = WebRequest.Create(requestUrl); 842 WebRequest request = WebRequest.Create(requestUrl);
813 HttpWebRequest ht = (HttpWebRequest)request; 843 HttpWebRequest ht = (HttpWebRequest)request;
844
845 if (auth != null)
846 auth.AddAuthorization(ht.Headers);
847
814 if (maxConnections > 0 && ht.ServicePoint.ConnectionLimit < maxConnections) 848 if (maxConnections > 0 && ht.ServicePoint.ConnectionLimit < maxConnections)
815 ht.ServicePoint.ConnectionLimit = maxConnections; 849 ht.ServicePoint.ConnectionLimit = maxConnections;
816 850
817 WebResponse response = null;
818 TResponse deserial = default(TResponse); 851 TResponse deserial = default(TResponse);
819 XmlSerializer deserializer = new XmlSerializer(typeof(TResponse));
820 852
821 request.Method = verb; 853 request.Method = verb;
854
822 MemoryStream buffer = null; 855 MemoryStream buffer = null;
823 856
824 if (verb == "POST") 857 try
825 { 858 {
826 request.ContentType = "text/xml"; 859 if (verb == "POST")
827
828 buffer = new MemoryStream();
829
830 XmlWriterSettings settings = new XmlWriterSettings();
831 settings.Encoding = Encoding.UTF8;
832
833 using (XmlWriter writer = XmlWriter.Create(buffer, settings))
834 { 860 {
835 XmlSerializer serializer = new XmlSerializer(type); 861 request.ContentType = "text/xml";
836 serializer.Serialize(writer, obj);
837 writer.Flush();
838 }
839 862
840 int length = (int)buffer.Length; 863 buffer = new MemoryStream();
841 request.ContentLength = length;
842 864
843 if (WebUtil.DebugLevel >= 5) 865 XmlWriterSettings settings = new XmlWriterSettings();
844 WebUtil.LogOutgoingDetail(buffer); 866 settings.Encoding = Encoding.UTF8;
845 867
846 request.BeginGetRequestStream(delegate(IAsyncResult res) 868 using (XmlWriter writer = XmlWriter.Create(buffer, settings))
847 { 869 {
848 Stream requestStream = request.EndGetRequestStream(res); 870 XmlSerializer serializer = new XmlSerializer(type);
871 serializer.Serialize(writer, obj);
872 writer.Flush();
873 }
874
875 int length = (int)buffer.Length;
876 request.ContentLength = length;
877 byte[] data = buffer.ToArray();
849 878
850 requestStream.Write(buffer.ToArray(), 0, length); 879<<<<<<< HEAD
851 requestStream.Close(); 880 if (WebUtil.DebugLevel >= 5)
881 WebUtil.LogOutgoingDetail("SEND", reqnum, System.Text.Encoding.UTF8.GetString(data));
852 882
883 request.BeginGetRequestStream(delegate(IAsyncResult res)
884=======
853 // capture how much time was spent writing 885 // capture how much time was spent writing
854 // useless in this async 886 // useless in this async
855// tickdata = Util.EnvironmentTickCountSubtract(tickstart); 887// tickdata = Util.EnvironmentTickCountSubtract(tickstart);
856 request.BeginGetResponse(delegate(IAsyncResult ar) 888 request.BeginGetResponse(delegate(IAsyncResult ar)
889>>>>>>> avn/ubitvar
857 { 890 {
858 response = request.EndGetResponse(ar); 891 using (Stream requestStream = request.EndGetRequestStream(res))
859 Stream respStream = null; 892 requestStream.Write(data, 0, length);
860 try 893
861 { 894 // capture how much time was spent writing
862 respStream = response.GetResponseStream(); 895 tickdata = Util.EnvironmentTickCountSubtract(tickstart);
863 deserial = (TResponse)deserializer.Deserialize( 896
864 respStream); 897 request.BeginGetResponse(delegate(IAsyncResult ar)
865 }
866 catch (System.InvalidOperationException)
867 {
868 }
869 finally
870 { 898 {
899<<<<<<< HEAD
900 using (WebResponse response = request.EndGetResponse(ar))
901 {
902 try
903 {
904 using (Stream respStream = response.GetResponseStream())
905 {
906 deserial = XMLResponseHelper.LogAndDeserialize<TRequest, TResponse>(
907 reqnum, respStream, response.ContentLength);
908 }
909 }
910 catch (System.InvalidOperationException)
911 {
912 }
913 }
914=======
871 // Let's not close this 915 // Let's not close this
872 // yes do close it 916 // yes do close it
873 buffer.Close(); 917 buffer.Close();
874 respStream.Close(); 918 respStream.Close();
875 response.Close(); 919 response.Close();
876 } 920 }
921>>>>>>> avn/ubitvar
877 922
878 action(deserial); 923 action(deserial);
879 924
925 }, null);
880 }, null); 926 }, null);
881 }, null); 927 }
882 } 928 else
883 else
884 {
885 request.BeginGetResponse(delegate(IAsyncResult res2)
886 { 929 {
887 try 930 request.BeginGetResponse(delegate(IAsyncResult res2)
888 { 931 {
889 // If the server returns a 404, this appears to trigger a System.Net.WebException even though that isn't
890 // documented in MSDN
891 response = request.EndGetResponse(res2);
892
893 Stream respStream = null;
894 try 932 try
895 { 933 {
896 respStream = response.GetResponseStream(); 934 // If the server returns a 404, this appears to trigger a System.Net.WebException even though that isn't
897 deserial = (TResponse)deserializer.Deserialize(respStream); 935 // documented in MSDN
898 } 936 using (WebResponse response = request.EndGetResponse(res2))
899 catch (System.InvalidOperationException) 937 {
900 { 938 try
901 } 939 {
902 finally 940 using (Stream respStream = response.GetResponseStream())
903 { 941 {
904 respStream.Close(); 942 deserial = XMLResponseHelper.LogAndDeserialize<TRequest, TResponse>(
905 response.Close(); 943 reqnum, respStream, response.ContentLength);
944 }
945 }
946 catch (System.InvalidOperationException)
947 {
948 }
949 }
906 } 950 }
907 } 951 catch (WebException e)
908 catch (WebException e)
909 {
910 if (e.Status == WebExceptionStatus.ProtocolError)
911 { 952 {
912 if (e.Response is HttpWebResponse) 953 if (e.Status == WebExceptionStatus.ProtocolError)
913 { 954 {
914 using (HttpWebResponse httpResponse = (HttpWebResponse)e.Response) 955 if (e.Response is HttpWebResponse)
915 { 956 {
916 if (httpResponse.StatusCode != HttpStatusCode.NotFound) 957 using (HttpWebResponse httpResponse = (HttpWebResponse)e.Response)
917 { 958 {
918 // We don't appear to be handling any other status codes, so log these feailures to that 959 if (httpResponse.StatusCode != HttpStatusCode.NotFound)
919 // people don't spend unnecessary hours hunting phantom bugs. 960 {
920 m_log.DebugFormat( 961 // We don't appear to be handling any other status codes, so log these feailures to that
921 "[ASYNC REQUEST]: Request {0} {1} failed with unexpected status code {2}", 962 // people don't spend unnecessary hours hunting phantom bugs.
922 verb, requestUrl, httpResponse.StatusCode); 963 m_log.DebugFormat(
964 "[ASYNC REQUEST]: Request {0} {1} failed with unexpected status code {2}",
965 verb, requestUrl, httpResponse.StatusCode);
966 }
923 } 967 }
924 } 968 }
925 } 969 }
970 else
971 {
972 m_log.ErrorFormat(
973 "[ASYNC REQUEST]: Request {0} {1} failed with status {2} and message {3}",
974 verb, requestUrl, e.Status, e.Message);
975 }
926 } 976 }
927 else 977 catch (Exception e)
978 {
979 m_log.ErrorFormat(
980 "[ASYNC REQUEST]: Request {0} {1} failed with exception {2}{3}",
981 verb, requestUrl, e.Message, e.StackTrace);
982 }
983<<<<<<< HEAD
984
985 // m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString());
986
987 try
988 {
989 action(deserial);
990 }
991 catch (Exception e)
928 { 992 {
929 m_log.ErrorFormat( 993 m_log.ErrorFormat(
930 "[ASYNC REQUEST]: Request {0} {1} failed with status {2} and message {3}", 994 "[ASYNC REQUEST]: Request {0} {1} callback failed with exception {2}{3}",
931 verb, requestUrl, e.Status, e.Message); 995 verb, requestUrl, e.Message, e.StackTrace);
932 } 996 }
997
998 }, null);
999 }
1000
1001 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
1002 if (tickdiff > WebUtil.LongCallTime)
1003 {
1004 string originalRequest = null;
1005
1006 if (buffer != null)
1007=======
933 } 1008 }
934 catch (Exception e) 1009 catch (Exception e)
935 { 1010 {
@@ -944,28 +1019,39 @@ namespace OpenSim.Framework
944 action(deserial); 1019 action(deserial);
945 } 1020 }
946 catch (Exception e) 1021 catch (Exception e)
1022>>>>>>> avn/ubitvar
947 { 1023 {
948 m_log.ErrorFormat( 1024 originalRequest = Encoding.UTF8.GetString(buffer.ToArray());
949 "[ASYNC REQUEST]: Request {0} {1} callback failed with exception {2}{3}",
950 verb, requestUrl, e.Message, e.StackTrace);
951 }
952
953 }, null);
954 }
955 1025
1026<<<<<<< HEAD
1027 if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
1028 originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
1029 }
1030=======
956 tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 1031 tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
957 if (tickdiff > WebUtil.LongCallTime) 1032 if (tickdiff > WebUtil.LongCallTime)
958 { 1033 {
959/* 1034/*
960 string originalRequest = null; 1035 string originalRequest = null;
1036>>>>>>> avn/ubitvar
961 1037
962 if (buffer != null) 1038 m_log.InfoFormat(
1039 "[LOGHTTP]: Slow AsynchronousRequestObject request {0} {1} to {2} took {3}ms, {4}ms writing, {5}",
1040 reqnum, verb, requestUrl, tickdiff, tickdata,
1041 originalRequest);
1042 }
1043 else if (WebUtil.DebugLevel >= 4)
963 { 1044 {
964 originalRequest = Encoding.UTF8.GetString(buffer.ToArray()); 1045 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} took {1}ms, {2}ms writing",
965 1046 reqnum, tickdiff, tickdata);
966 if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
967 originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
968 } 1047 }
1048<<<<<<< HEAD
1049 }
1050 finally
1051 {
1052 if (buffer != null)
1053 buffer.Dispose();
1054=======
969 1055
970 m_log.InfoFormat( 1056 m_log.InfoFormat(
971 "[ASYNC REQUEST]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}", 1057 "[ASYNC REQUEST]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
@@ -988,6 +1074,7 @@ namespace OpenSim.Framework
988 m_log.DebugFormat( 1074 m_log.DebugFormat(
989 "[WEB UTIL]: HTTP OUT {0} took {1}ms", 1075 "[WEB UTIL]: HTTP OUT {0} took {1}ms",
990 reqnum, tickdiff); 1076 reqnum, tickdiff);
1077>>>>>>> avn/ubitvar
991 } 1078 }
992 } 1079 }
993 } 1080 }
@@ -1007,13 +1094,12 @@ namespace OpenSim.Framework
1007 /// 1094 ///
1008 /// <exception cref="System.Net.WebException">Thrown if we encounter a network issue while posting 1095 /// <exception cref="System.Net.WebException">Thrown if we encounter a network issue while posting
1009 /// the request. You'll want to make sure you deal with this as they're not uncommon</exception> 1096 /// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
1010 public static string MakeRequest(string verb, string requestUrl, string obj, int timeoutsecs) 1097 public static string MakeRequest(string verb, string requestUrl, string obj, int timeoutsecs, IServiceAuth auth)
1011 { 1098 {
1012 int reqnum = WebUtil.RequestNumber++; 1099 int reqnum = WebUtil.RequestNumber++;
1013 1100
1014 if (WebUtil.DebugLevel >= 3) 1101 if (WebUtil.DebugLevel >= 3)
1015 m_log.DebugFormat( 1102 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} SynchronousRestForms {1} to {2}",
1016 "[WEB UTIL]: HTTP OUT {0} SynchronousRestForms {1} {2}",
1017 reqnum, verb, requestUrl); 1103 reqnum, verb, requestUrl);
1018 1104
1019 int tickstart = Util.EnvironmentTickCount(); 1105 int tickstart = Util.EnvironmentTickCount();
@@ -1023,6 +1109,10 @@ namespace OpenSim.Framework
1023 request.Method = verb; 1109 request.Method = verb;
1024 if (timeoutsecs > 0) 1110 if (timeoutsecs > 0)
1025 request.Timeout = timeoutsecs * 1000; 1111 request.Timeout = timeoutsecs * 1000;
1112
1113 if (auth != null)
1114 auth.AddAuthorization(request.Headers);
1115
1026 string respstring = String.Empty; 1116 string respstring = String.Empty;
1027 1117
1028 int tickset = Util.EnvironmentTickCountSubtract(tickstart); 1118 int tickset = Util.EnvironmentTickCountSubtract(tickstart);
@@ -1044,23 +1134,30 @@ namespace OpenSim.Framework
1044 1134
1045 length = (int)obj.Length; 1135 length = (int)obj.Length;
1046 request.ContentLength = length; 1136 request.ContentLength = length;
1137 byte[] data = buffer.ToArray();
1047 1138
1139<<<<<<< HEAD
1140 if (WebUtil.DebugLevel >= 5)
1141 WebUtil.LogOutgoingDetail("SEND", reqnum, System.Text.Encoding.UTF8.GetString(data));
1142=======
1143>>>>>>> avn/ubitvar
1048 1144
1049 Stream requestStream = null; 1145 Stream requestStream = null;
1050 try 1146 try
1051 { 1147 {
1052 requestStream = request.GetRequestStream(); 1148 requestStream = request.GetRequestStream();
1053 requestStream.Write(buffer.ToArray(), 0, length); 1149 requestStream.Write(data, 0, length);
1054 } 1150 }
1055 catch (Exception e) 1151 catch (Exception e)
1056 { 1152 {
1057 m_log.DebugFormat( 1153 m_log.InfoFormat("[FORMS]: Error sending request to {0}: {1}. Request: {2}", requestUrl, e.Message,
1058 "[FORMS]: exception occured {0} {1}: {2}{3}", verb, requestUrl, e.Message, e.StackTrace); 1154 obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
1155 throw e;
1059 } 1156 }
1060 finally 1157 finally
1061 { 1158 {
1062 if (requestStream != null) 1159 if (requestStream != null)
1063 requestStream.Close(); 1160 requestStream.Dispose();
1064 1161
1065 // capture how much time was spent writing 1162 // capture how much time was spent writing
1066 tickdata = Util.EnvironmentTickCountSubtract(tickstart); 1163 tickdata = Util.EnvironmentTickCountSubtract(tickstart);
@@ -1073,37 +1170,28 @@ namespace OpenSim.Framework
1073 { 1170 {
1074 if (resp.ContentLength != 0) 1171 if (resp.ContentLength != 0)
1075 { 1172 {
1076 Stream respStream = null; 1173 using (Stream respStream = resp.GetResponseStream())
1077 try 1174 using (StreamReader reader = new StreamReader(respStream))
1078 { 1175 respstring = reader.ReadToEnd();
1079 using (respStream = resp.GetResponseStream())
1080 using (StreamReader reader = new StreamReader(respStream))
1081 respstring = reader.ReadToEnd();
1082 }
1083 catch (Exception e)
1084 {
1085 m_log.DebugFormat(
1086 "[FORMS]: Exception occured on receiving {0} {1}: {2}{3}",
1087 verb, requestUrl, e.Message, e.StackTrace);
1088 }
1089 finally
1090 {
1091 if (respStream != null)
1092 respStream.Close();
1093 }
1094 } 1176 }
1095 } 1177 }
1096 } 1178 }
1097 catch (System.InvalidOperationException) 1179 catch (Exception e)
1098 { 1180 {
1099 // This is what happens when there is invalid XML 1181 m_log.InfoFormat("[FORMS]: Error receiving response from {0}: {1}. Request: {2}", requestUrl, e.Message,
1100 m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving {0} {1}", verb, requestUrl); 1182 obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
1183 throw e;
1101 } 1184 }
1102 } 1185 }
1103 1186
1104 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 1187 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
1105 if (tickdiff > WebUtil.LongCallTime) 1188 if (tickdiff > WebUtil.LongCallTime)
1189 {
1106 m_log.InfoFormat( 1190 m_log.InfoFormat(
1191<<<<<<< HEAD
1192 "[LOGHTTP]: Slow SynchronousRestForms request {0} {1} to {2} took {3}ms, {4}ms writing, {5}",
1193 reqnum, verb, requestUrl, tickdiff, tickdata,
1194=======
1107 "[FORMS]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}", 1195 "[FORMS]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
1108 reqnum, 1196 reqnum,
1109 verb, 1197 verb,
@@ -1111,19 +1199,35 @@ namespace OpenSim.Framework
1111 tickdiff, 1199 tickdiff,
1112 tickset, 1200 tickset,
1113 tickdata, 1201 tickdata,
1202>>>>>>> avn/ubitvar
1114 obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj); 1203 obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
1204 }
1115 else if (WebUtil.DebugLevel >= 4) 1205 else if (WebUtil.DebugLevel >= 4)
1116 m_log.DebugFormat( 1206 {
1117 "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing", 1207 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} took {1}ms, {2}ms writing",
1118 reqnum, tickdiff, tickdata); 1208 reqnum, tickdiff, tickdata);
1209 }
1210
1211 if (WebUtil.DebugLevel >= 5)
1212 WebUtil.LogResponseDetail(reqnum, respstring);
1119 1213
1120 return respstring; 1214 return respstring;
1121 } 1215 }
1122 1216
1217 public static string MakeRequest(string verb, string requestUrl, string obj, int timeoutsecs)
1218 {
1219 return MakeRequest(verb, requestUrl, obj, timeoutsecs, null);
1220 }
1221
1123 public static string MakeRequest(string verb, string requestUrl, string obj) 1222 public static string MakeRequest(string verb, string requestUrl, string obj)
1124 { 1223 {
1125 return MakeRequest(verb, requestUrl, obj, -1); 1224 return MakeRequest(verb, requestUrl, obj, -1);
1126 } 1225 }
1226
1227 public static string MakeRequest(string verb, string requestUrl, string obj, IServiceAuth auth)
1228 {
1229 return MakeRequest(verb, requestUrl, obj, -1, auth);
1230 }
1127 } 1231 }
1128 1232
1129 public class SynchronousRestObjectRequester 1233 public class SynchronousRestObjectRequester
@@ -1137,28 +1241,80 @@ namespace OpenSim.Framework
1137 /// </summary> 1241 /// </summary>
1138 /// <param name="verb"></param> 1242 /// <param name="verb"></param>
1139 /// <param name="requestUrl"></param> 1243 /// <param name="requestUrl"></param>
1140 /// <param name="obj"> </param> 1244 /// <param name="obj"></param>
1141 /// <returns></returns> 1245 /// <returns>
1142 /// 1246 /// The response. If there was an internal exception, then the default(TResponse) is returned.
1143 /// <exception cref="System.Net.WebException">Thrown if we encounter a network issue while posting 1247 /// </returns>
1144 /// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
1145 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj) 1248 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj)
1146 { 1249 {
1147 return MakeRequest<TRequest, TResponse>(verb, requestUrl, obj, 0); 1250 return MakeRequest<TRequest, TResponse>(verb, requestUrl, obj, 0);
1148 } 1251 }
1149 1252
1253 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, IServiceAuth auth)
1254 {
1255 return MakeRequest<TRequest, TResponse>(verb, requestUrl, obj, 0, auth);
1256 }
1257 /// <summary>
1258 /// Perform a synchronous REST request.
1259 /// </summary>
1260 /// <param name="verb"></param>
1261 /// <param name="requestUrl"></param>
1262 /// <param name="obj"></param>
1263 /// <param name="pTimeout">
1264 /// Request timeout in milliseconds. Timeout.Infinite indicates no timeout. If 0 is passed then the default HttpWebRequest timeout is used (100 seconds)
1265 /// </param>
1266 /// <returns>
1267 /// The response. If there was an internal exception or the request timed out,
1268 /// then the default(TResponse) is returned.
1269 /// </returns>
1150 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout) 1270 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout)
1151 { 1271 {
1152 return MakeRequest<TRequest, TResponse>(verb, requestUrl, obj, pTimeout, 0); 1272 return MakeRequest<TRequest, TResponse>(verb, requestUrl, obj, pTimeout, 0);
1153 } 1273 }
1154 1274
1275 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout, IServiceAuth auth)
1276 {
1277 return MakeRequest<TRequest, TResponse>(verb, requestUrl, obj, pTimeout, 0, auth);
1278 }
1279
1280 /// Perform a synchronous REST request.
1281 /// </summary>
1282 /// <param name="verb"></param>
1283 /// <param name="requestUrl"></param>
1284 /// <param name="obj"></param>
1285 /// <param name="pTimeout">
1286 /// Request timeout in milliseconds. Timeout.Infinite indicates no timeout. If 0 is passed then the default HttpWebRequest timeout is used (100 seconds)
1287 /// </param>
1288 /// <param name="maxConnections"></param>
1289 /// <returns>
1290 /// The response. If there was an internal exception or the request timed out,
1291 /// then the default(TResponse) is returned.
1292 /// </returns>
1155 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout, int maxConnections) 1293 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout, int maxConnections)
1156 { 1294 {
1295 return MakeRequest<TRequest, TResponse>(verb, requestUrl, obj, pTimeout, maxConnections, null);
1296 }
1297
1298 /// <summary>
1299 /// Perform a synchronous REST request.
1300 /// </summary>
1301 /// <param name="verb"></param>
1302 /// <param name="requestUrl"></param>
1303 /// <param name="obj"></param>
1304 /// <param name="pTimeout">
1305 /// Request timeout in milliseconds. Timeout.Infinite indicates no timeout. If 0 is passed then the default HttpWebRequest timeout is used (100 seconds)
1306 /// </param>
1307 /// <param name="maxConnections"></param>
1308 /// <returns>
1309 /// The response. If there was an internal exception or the request timed out,
1310 /// then the default(TResponse) is returned.
1311 /// </returns>
1312 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout, int maxConnections, IServiceAuth auth)
1313 {
1157 int reqnum = WebUtil.RequestNumber++; 1314 int reqnum = WebUtil.RequestNumber++;
1158 1315
1159 if (WebUtil.DebugLevel >= 3) 1316 if (WebUtil.DebugLevel >= 3)
1160 m_log.DebugFormat( 1317 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} SynchronousRestObject {1} to {2}",
1161 "[WEB UTIL]: HTTP OUT {0} SynchronousRestObject {1} {2}",
1162 reqnum, verb, requestUrl); 1318 reqnum, verb, requestUrl);
1163 1319
1164 int tickstart = Util.EnvironmentTickCount(); 1320 int tickstart = Util.EnvironmentTickCount();
@@ -1169,6 +1325,13 @@ namespace OpenSim.Framework
1169 1325
1170 WebRequest request = WebRequest.Create(requestUrl); 1326 WebRequest request = WebRequest.Create(requestUrl);
1171 HttpWebRequest ht = (HttpWebRequest)request; 1327 HttpWebRequest ht = (HttpWebRequest)request;
1328
1329 if (auth != null)
1330 auth.AddAuthorization(ht.Headers);
1331
1332 if (pTimeout != 0)
1333 ht.Timeout = pTimeout;
1334
1172 if (maxConnections > 0 && ht.ServicePoint.ConnectionLimit < maxConnections) 1335 if (maxConnections > 0 && ht.ServicePoint.ConnectionLimit < maxConnections)
1173 ht.ServicePoint.ConnectionLimit = maxConnections; 1336 ht.ServicePoint.ConnectionLimit = maxConnections;
1174 1337
@@ -1177,15 +1340,25 @@ namespace OpenSim.Framework
1177 request.Timeout = pTimeout * 1000; 1340 request.Timeout = pTimeout * 1000;
1178 MemoryStream buffer = null; 1341 MemoryStream buffer = null;
1179 1342
1180 if ((verb == "POST") || (verb == "PUT")) 1343 try
1181 { 1344 {
1182 request.ContentType = "text/xml"; 1345 if ((verb == "POST") || (verb == "PUT"))
1346 {
1347 request.ContentType = "text/xml";
1183 1348
1184 buffer = new MemoryStream(); 1349 buffer = new MemoryStream();
1185 1350
1186 XmlWriterSettings settings = new XmlWriterSettings(); 1351 XmlWriterSettings settings = new XmlWriterSettings();
1187 settings.Encoding = Encoding.UTF8; 1352 settings.Encoding = Encoding.UTF8;
1188 1353
1354<<<<<<< HEAD
1355 using (XmlWriter writer = XmlWriter.Create(buffer, settings))
1356 {
1357 XmlSerializer serializer = new XmlSerializer(type);
1358 serializer.Serialize(writer, obj);
1359 writer.Flush();
1360 }
1361=======
1189 using (XmlWriter writer = XmlWriter.Create(buffer, settings)) 1362 using (XmlWriter writer = XmlWriter.Create(buffer, settings))
1190 { 1363 {
1191 XmlSerializer serializer = new XmlSerializer(type); 1364 XmlSerializer serializer = new XmlSerializer(type);
@@ -1194,110 +1367,227 @@ namespace OpenSim.Framework
1194 if (WebUtil.DebugLevel >= 5) 1367 if (WebUtil.DebugLevel >= 5)
1195 WebUtil.LogOutgoingDetail(buffer); 1368 WebUtil.LogOutgoingDetail(buffer);
1196 } 1369 }
1370>>>>>>> avn/ubitvar
1371
1372 int length = (int)buffer.Length;
1373 request.ContentLength = length;
1374 byte[] data = buffer.ToArray();
1375
1376<<<<<<< HEAD
1377 if (WebUtil.DebugLevel >= 5)
1378 WebUtil.LogOutgoingDetail("SEND", reqnum, System.Text.Encoding.UTF8.GetString(data));
1379
1380 try
1381 {
1382 using (Stream requestStream = request.GetRequestStream())
1383 requestStream.Write(data, 0, length);
1384 }
1385 catch (Exception e)
1386 {
1387 m_log.DebugFormat(
1388 "[SynchronousRestObjectRequester]: Exception in making request {0} {1}: {2}{3}",
1389 verb, requestUrl, e.Message, e.StackTrace);
1197 1390
1198 int length = (int)buffer.Length; 1391 return deserial;
1199 request.ContentLength = length; 1392 }
1393 finally
1394 {
1395 // capture how much time was spent writing
1396 tickdata = Util.EnvironmentTickCountSubtract(tickstart);
1397 }
1398 }
1200 1399
1400=======
1201 Stream requestStream = null; 1401 Stream requestStream = null;
1402>>>>>>> avn/ubitvar
1202 try 1403 try
1203 { 1404 {
1204 requestStream = request.GetRequestStream(); 1405 using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
1205 requestStream.Write(buffer.ToArray(), 0, length); 1406 {
1407 if (resp.ContentLength != 0)
1408 {
1409 using (Stream respStream = resp.GetResponseStream())
1410 {
1411 deserial = XMLResponseHelper.LogAndDeserialize<TRequest, TResponse>(
1412 reqnum, respStream, resp.ContentLength);
1413 }
1414 }
1415 else
1416 {
1417 m_log.DebugFormat(
1418 "[SynchronousRestObjectRequester]: Oops! no content found in response stream from {0} {1}",
1419 verb, requestUrl);
1420 }
1421 }
1206 } 1422 }
1207 catch (Exception e) 1423 catch (WebException e)
1424 {
1425 using (HttpWebResponse hwr = (HttpWebResponse)e.Response)
1426 {
1427 if (hwr != null)
1428 {
1429 if (hwr.StatusCode == HttpStatusCode.NotFound)
1430 return deserial;
1431 if (hwr.StatusCode == HttpStatusCode.Unauthorized)
1432 {
1433 m_log.Error(string.Format(
1434 "[SynchronousRestObjectRequester]: Web request {0} requires authentication ",
1435 requestUrl));
1436 return deserial;
1437 }
1438 }
1439 else
1440 m_log.Error(string.Format(
1441 "[SynchronousRestObjectRequester]: WebException for {0} {1} {2} ",
1442 verb, requestUrl, typeof(TResponse).ToString()), e);
1443 }
1444 }
1445 catch (System.InvalidOperationException)
1208 { 1446 {
1447 // This is what happens when there is invalid XML
1209 m_log.DebugFormat( 1448 m_log.DebugFormat(
1210 "[SynchronousRestObjectRequester]: Exception in making request {0} {1}: {2}{3}", 1449 "[SynchronousRestObjectRequester]: Invalid XML from {0} {1} {2}",
1211 verb, requestUrl, e.Message, e.StackTrace); 1450 verb, requestUrl, typeof(TResponse).ToString());
1212
1213 return deserial;
1214 } 1451 }
1215 finally 1452 catch (Exception e)
1216 { 1453 {
1217 if (requestStream != null) 1454 m_log.Debug(string.Format(
1218 requestStream.Close(); 1455 "[SynchronousRestObjectRequester]: Exception on response from {0} {1} ",
1219 1456 verb, requestUrl), e);
1220 // capture how much time was spent writing
1221 tickdata = Util.EnvironmentTickCountSubtract(tickstart);
1222 } 1457 }
1223 }
1224 1458
1225 try 1459 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
1226 { 1460 if (tickdiff > WebUtil.LongCallTime)
1227 using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
1228 { 1461 {
1229 if (resp.ContentLength != 0) 1462 string originalRequest = null;
1230 { 1463
1231 using (Stream respStream = resp.GetResponseStream()) 1464 if (buffer != null)
1232 {
1233 XmlSerializer deserializer = new XmlSerializer(typeof(TResponse));
1234 deserial = (TResponse)deserializer.Deserialize(respStream);
1235 }
1236 }
1237 else
1238 { 1465 {
1239 m_log.DebugFormat( 1466 originalRequest = Encoding.UTF8.GetString(buffer.ToArray());
1240 "[SynchronousRestObjectRequester]: Oops! no content found in response stream from {0} {1}", 1467
1241 verb, requestUrl); 1468 if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
1469 originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
1242 } 1470 }
1471
1472 m_log.InfoFormat(
1473 "[LOGHTTP]: Slow SynchronousRestObject request {0} {1} to {2} took {3}ms, {4}ms writing, {5}",
1474 reqnum, verb, requestUrl, tickdiff, tickdata,
1475 originalRequest);
1243 } 1476 }
1244 } 1477 else if (WebUtil.DebugLevel >= 4)
1245 catch (WebException e)
1246 {
1247 using (HttpWebResponse hwr = (HttpWebResponse)e.Response)
1248 { 1478 {
1249 if (hwr != null && hwr.StatusCode == HttpStatusCode.NotFound) 1479 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} took {1}ms, {2}ms writing",
1250 return deserial; 1480 reqnum, tickdiff, tickdata);
1251 else
1252 m_log.ErrorFormat(
1253 "[SynchronousRestObjectRequester]: WebException for {0} {1} {2}: {3} {4}",
1254 verb, requestUrl, typeof(TResponse).ToString(), e.Message, e.StackTrace);
1255 } 1481 }
1256 } 1482 }
1257 catch (System.InvalidOperationException) 1483 finally
1258 { 1484 {
1259 // This is what happens when there is invalid XML 1485 if (buffer != null)
1260 m_log.DebugFormat( 1486 buffer.Dispose();
1261 "[SynchronousRestObjectRequester]: Invalid XML from {0} {1} {2}",
1262 verb, requestUrl, typeof(TResponse).ToString());
1263 } 1487 }
1264 catch (Exception e) 1488
1489 return deserial;
1490 }
1491
1492
1493 public static class XMLResponseHelper
1494 {
1495 public static TResponse LogAndDeserialize<TRequest, TResponse>(int reqnum, Stream respStream, long contentLength)
1265 { 1496 {
1266 m_log.DebugFormat( 1497 XmlSerializer deserializer = new XmlSerializer(typeof(TResponse));
1267 "[SynchronousRestObjectRequester]: Exception on response from {0} {1}: {2}{3}", 1498
1268 verb, requestUrl, e.Message, e.StackTrace); 1499 if (WebUtil.DebugLevel >= 5)
1500 {
1501 byte[] data = new byte[contentLength];
1502 Util.ReadStream(respStream, data);
1503
1504 WebUtil.LogResponseDetail(reqnum, System.Text.Encoding.UTF8.GetString(data));
1505
1506 using (MemoryStream temp = new MemoryStream(data))
1507 return (TResponse)deserializer.Deserialize(temp);
1508 }
1509 else
1510 {
1511 return (TResponse)deserializer.Deserialize(respStream);
1512 }
1269 } 1513 }
1514 }
1515 }
1270 1516
1271 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 1517
1272 if (tickdiff > WebUtil.LongCallTime) 1518 public static class XMLRPCRequester
1519 {
1520 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
1521
1522 public static Hashtable SendRequest(Hashtable ReqParams, string method, string url)
1523 {
1524 int reqnum = WebUtil.RequestNumber++;
1525
1526 if (WebUtil.DebugLevel >= 3)
1527 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} XML-RPC '{1}' to {2}",
1528 reqnum, method, url);
1529
1530 int tickstart = Util.EnvironmentTickCount();
1531 string responseStr = null;
1532
1533 try
1273 { 1534 {
1274 string originalRequest = null; 1535 ArrayList SendParams = new ArrayList();
1536 SendParams.Add(ReqParams);
1275 1537
1276 if (buffer != null) 1538 XmlRpcRequest Req = new XmlRpcRequest(method, SendParams);
1539
1540 if (WebUtil.DebugLevel >= 5)
1277 { 1541 {
1278 originalRequest = Encoding.UTF8.GetString(buffer.ToArray()); 1542 string str = Req.ToString();
1543 str = XElement.Parse(str).ToString(SaveOptions.DisableFormatting);
1544 WebUtil.LogOutgoingDetail("SEND", reqnum, str);
1545 }
1279 1546
1280 if (originalRequest.Length > WebUtil.MaxRequestDiagLength) 1547 XmlRpcResponse Resp = Req.Send(url, 30000);
1281 originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength); 1548
1549 try
1550 {
1551 responseStr = Resp.ToString();
1552 responseStr = XElement.Parse(responseStr).ToString(SaveOptions.DisableFormatting);
1553
1554 if (WebUtil.DebugLevel >= 5)
1555 WebUtil.LogResponseDetail(reqnum, responseStr);
1556 }
1557 catch (Exception e)
1558 {
1559 m_log.Error("Error parsing XML-RPC response", e);
1560 }
1561
1562 if (Resp.IsFault)
1563 {
1564 m_log.DebugFormat(
1565 "[LOGHTTP]: XML-RPC request {0} '{1}' to {2} FAILED: FaultCode={3}, FaultMessage={4}",
1566 reqnum, method, url, Resp.FaultCode, Resp.FaultString);
1567 return null;
1282 } 1568 }
1283 1569
1284 m_log.InfoFormat( 1570 Hashtable RespData = (Hashtable)Resp.Value;
1285 "[SynchronousRestObjectRequester]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}", 1571 return RespData;
1286 reqnum,
1287 verb,
1288 requestUrl,
1289 tickdiff,
1290 tickdata,
1291 originalRequest);
1292 } 1572 }
1293 else if (WebUtil.DebugLevel >= 4) 1573 finally
1294 { 1574 {
1295 m_log.DebugFormat( 1575 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
1296 "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing", 1576 if (tickdiff > WebUtil.LongCallTime)
1297 reqnum, tickdiff, tickdata); 1577 {
1578 m_log.InfoFormat(
1579 "[LOGHTTP]: Slow XML-RPC request {0} '{1}' to {2} took {3}ms, {4}",
1580 reqnum, method, url, tickdiff,
1581 responseStr != null
1582 ? (responseStr.Length > WebUtil.MaxRequestDiagLength ? responseStr.Remove(WebUtil.MaxRequestDiagLength) : responseStr)
1583 : "");
1584 }
1585 else if (WebUtil.DebugLevel >= 4)
1586 {
1587 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} took {1}ms", reqnum, tickdiff);
1588 }
1298 } 1589 }
1299
1300 return deserial;
1301 } 1590 }
1591
1302 } 1592 }
1303} \ No newline at end of file 1593}