aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/AgentCircuitData.cs5
-rw-r--r--OpenSim/Framework/Console/CommandConsole.cs10
-rw-r--r--OpenSim/Framework/Console/ConsoleDisplayList.cs112
-rw-r--r--OpenSim/Framework/Console/ConsoleDisplayTable.cs154
-rw-r--r--OpenSim/Framework/Console/LocalConsole.cs4
-rw-r--r--OpenSim/Framework/EstateSettings.cs6
-rw-r--r--OpenSim/Framework/IClientAPI.cs22
-rw-r--r--OpenSim/Framework/IScene.cs5
-rw-r--r--OpenSim/Framework/ISceneAgent.cs7
-rw-r--r--OpenSim/Framework/PrimitiveBaseShape.cs12
-rw-r--r--OpenSim/Framework/RegionSettings.cs29
-rw-r--r--OpenSim/Framework/SLUtil.cs382
-rw-r--r--OpenSim/Framework/Serialization/External/LandDataSerializer.cs6
-rw-r--r--OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs41
-rw-r--r--OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs2
-rw-r--r--OpenSim/Framework/Serialization/TarArchiveReader.cs8
-rw-r--r--OpenSim/Framework/Serialization/TarArchiveWriter.cs27
-rw-r--r--OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs8
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs8
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHTTPHandler.cs10
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs474
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs10
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs9
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs17
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Interfaces/IOSHttpResponse.cs8
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs21
-rw-r--r--OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs3
-rw-r--r--OpenSim/Framework/Servers/HttpServer/OSHttpStatusCodes.cs379
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs6
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs7
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs15
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs49
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs6
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestHTTPHandler.cs20
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs14
-rw-r--r--OpenSim/Framework/Servers/MainServer.cs184
-rw-r--r--OpenSim/Framework/Statistics/StatsManager.cs17
-rw-r--r--OpenSim/Framework/TaskInventoryDictionary.cs89
-rw-r--r--OpenSim/Framework/TaskInventoryItem.cs16
-rw-r--r--OpenSim/Framework/Tests/MundaneFrameworkTests.cs4
-rw-r--r--OpenSim/Framework/Tests/UtilTest.cs23
-rw-r--r--OpenSim/Framework/Util.cs4
-rw-r--r--OpenSim/Framework/Watchdog.cs66
-rw-r--r--OpenSim/Framework/WebUtil.cs312
45 files changed, 1649 insertions, 964 deletions
diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs
index 57fb808..ffcc584 100644
--- a/OpenSim/Framework/AgentCircuitData.cs
+++ b/OpenSim/Framework/AgentCircuitData.cs
@@ -99,6 +99,11 @@ namespace OpenSim.Framework
99 public string lastname; 99 public string lastname;
100 100
101 /// <summary> 101 /// <summary>
102 /// Agent's full name.
103 /// </summary>
104 public string Name { get { return string.Format("{0} {1}", firstname, lastname); } }
105
106 /// <summary>
102 /// Random Unique GUID for this session. Client gets this at login and it's 107 /// Random Unique GUID for this session. Client gets this at login and it's
103 /// only supposed to be disclosed over secure channels 108 /// only supposed to be disclosed over secure channels
104 /// </summary> 109 /// </summary>
diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs
index c5d6b78..87bdacd 100644
--- a/OpenSim/Framework/Console/CommandConsole.cs
+++ b/OpenSim/Framework/Console/CommandConsole.cs
@@ -79,7 +79,11 @@ namespace OpenSim.Framework.Console
79 public List<CommandDelegate> fn; 79 public List<CommandDelegate> fn;
80 } 80 }
81 81
82 public const string GeneralHelpText = "For more information, type 'help <item>' where <item> is one of the following categories:"; 82 public const string GeneralHelpText
83 = "To enter an argument that contains spaces, surround the argument with double quotes.\nFor example, show object name \"My long object name\"\n";
84
85 public const string ItemHelpText
86 = "For more information, type 'help <item>' where <item> is one of the following:";
83 87
84 /// <value> 88 /// <value>
85 /// Commands organized by keyword in a tree 89 /// Commands organized by keyword in a tree
@@ -108,7 +112,9 @@ namespace OpenSim.Framework.Console
108 // General help 112 // General help
109 if (helpParts.Count == 0) 113 if (helpParts.Count == 0)
110 { 114 {
115 help.Add(""); // Will become a newline.
111 help.Add(GeneralHelpText); 116 help.Add(GeneralHelpText);
117 help.Add(ItemHelpText);
112 help.AddRange(CollectModulesHelp(tree)); 118 help.AddRange(CollectModulesHelp(tree));
113 } 119 }
114 else 120 else
@@ -132,7 +138,7 @@ namespace OpenSim.Framework.Console
132 // Check modules first to see if we just need to display a list of those commands 138 // Check modules first to see if we just need to display a list of those commands
133 if (TryCollectModuleHelp(originalHelpRequest, help)) 139 if (TryCollectModuleHelp(originalHelpRequest, help))
134 { 140 {
135 help.Insert(0, GeneralHelpText); 141 help.Insert(0, ItemHelpText);
136 return help; 142 return help;
137 } 143 }
138 144
diff --git a/OpenSim/Framework/Console/ConsoleDisplayList.cs b/OpenSim/Framework/Console/ConsoleDisplayList.cs
new file mode 100644
index 0000000..6885509
--- /dev/null
+++ b/OpenSim/Framework/Console/ConsoleDisplayList.cs
@@ -0,0 +1,112 @@
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.Text;
32
33namespace OpenSim.Framework.Console
34{
35 /// <summary>
36 /// Used to generated a formatted table for the console.
37 /// </summary>
38 /// <remarks>
39 /// Currently subject to change. If you use this, be prepared to change your code when this class changes.
40 /// </remarks>
41 public class ConsoleDisplayList
42 {
43 /// <summary>
44 /// The default divider between key and value for a list item.
45 /// </summary>
46 public const string DefaultKeyValueDivider = " : ";
47
48 /// <summary>
49 /// The divider used between key and value for a list item.
50 /// </summary>
51 public string KeyValueDivider { get; set; }
52
53 /// <summary>
54 /// Table rows
55 /// </summary>
56 public List<KeyValuePair<string, string>> Rows { get; private set; }
57
58 /// <summary>
59 /// Number of spaces to indent the list.
60 /// </summary>
61 public int Indent { get; set; }
62
63 public ConsoleDisplayList()
64 {
65 Rows = new List<KeyValuePair<string, string>>();
66 KeyValueDivider = DefaultKeyValueDivider;
67 }
68
69 public override string ToString()
70 {
71 StringBuilder sb = new StringBuilder();
72 AddToStringBuilder(sb);
73 return sb.ToString();
74 }
75
76 public void AddToStringBuilder(StringBuilder sb)
77 {
78 string formatString = GetFormatString();
79// System.Console.WriteLine("FORMAT STRING [{0}]", formatString);
80
81 // rows
82 foreach (KeyValuePair<string, string> row in Rows)
83 sb.AppendFormat(formatString, row.Key, row.Value);
84 }
85
86 /// <summary>
87 /// Gets the format string for the table.
88 /// </summary>
89 private string GetFormatString()
90 {
91 StringBuilder formatSb = new StringBuilder();
92
93 int longestKey = -1;
94
95 foreach (KeyValuePair<string, string> row in Rows)
96 if (row.Key.Length > longestKey)
97 longestKey = row.Key.Length;
98
99 formatSb.Append(' ', Indent);
100
101 // Can only do left formatting for now
102 formatSb.AppendFormat("{{0,-{0}}}{1}{{1}}\n", longestKey, KeyValueDivider);
103
104 return formatSb.ToString();
105 }
106
107 public void AddRow(object key, object value)
108 {
109 Rows.Add(new KeyValuePair<string, string>(key.ToString(), value.ToString()));
110 }
111 }
112} \ No newline at end of file
diff --git a/OpenSim/Framework/Console/ConsoleDisplayTable.cs b/OpenSim/Framework/Console/ConsoleDisplayTable.cs
new file mode 100644
index 0000000..c620dfe
--- /dev/null
+++ b/OpenSim/Framework/Console/ConsoleDisplayTable.cs
@@ -0,0 +1,154 @@
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.Text;
32
33namespace OpenSim.Framework.Console
34{
35 /// <summary>
36 /// Used to generated a formatted table for the console.
37 /// </summary>
38 /// <remarks>
39 /// Currently subject to change. If you use this, be prepared to change your code when this class changes.
40 /// </remarks>
41 public class ConsoleDisplayTable
42 {
43 /// <summary>
44 /// Default number of spaces between table columns.
45 /// </summary>
46 public const int DefaultTableSpacing = 2;
47
48 /// <summary>
49 /// Table columns.
50 /// </summary>
51 public List<ConsoleDisplayTableColumn> Columns { get; private set; }
52
53 /// <summary>
54 /// Table rows
55 /// </summary>
56 public List<ConsoleDisplayTableRow> Rows { get; private set; }
57
58 /// <summary>
59 /// Number of spaces to indent the table.
60 /// </summary>
61 public int Indent { get; set; }
62
63 /// <summary>
64 /// Spacing between table columns
65 /// </summary>
66 public int TableSpacing { get; set; }
67
68 public ConsoleDisplayTable()
69 {
70 TableSpacing = DefaultTableSpacing;
71 Columns = new List<ConsoleDisplayTableColumn>();
72 Rows = new List<ConsoleDisplayTableRow>();
73 }
74
75 public override string ToString()
76 {
77 StringBuilder sb = new StringBuilder();
78 AddToStringBuilder(sb);
79 return sb.ToString();
80 }
81
82 public void AddColumn(string name, int width)
83 {
84 Columns.Add(new ConsoleDisplayTableColumn(name, width));
85 }
86
87 public void AddRow(params string[] cells)
88 {
89 Rows.Add(new ConsoleDisplayTableRow(cells));
90 }
91
92 public void AddToStringBuilder(StringBuilder sb)
93 {
94 string formatString = GetFormatString();
95// System.Console.WriteLine("FORMAT STRING [{0}]", formatString);
96
97 // columns
98 sb.AppendFormat(formatString, Columns.ConvertAll(c => c.Header).ToArray());
99
100 // rows
101 foreach (ConsoleDisplayTableRow row in Rows)
102 sb.AppendFormat(formatString, row.Cells.ToArray());
103 }
104
105 /// <summary>
106 /// Gets the format string for the table.
107 /// </summary>
108 private string GetFormatString()
109 {
110 StringBuilder formatSb = new StringBuilder();
111
112 formatSb.Append(' ', Indent);
113
114 for (int i = 0; i < Columns.Count; i++)
115 {
116 formatSb.Append(' ', TableSpacing);
117
118 // Can only do left formatting for now
119 formatSb.AppendFormat("{{{0},-{1}}}", i, Columns[i].Width);
120 }
121
122 formatSb.Append('\n');
123
124 return formatSb.ToString();
125 }
126 }
127
128 public struct ConsoleDisplayTableColumn
129 {
130 public string Header { get; set; }
131 public int Width { get; set; }
132
133 public ConsoleDisplayTableColumn(string header, int width) : this()
134 {
135 Header = header;
136 Width = width;
137 }
138 }
139
140 public struct ConsoleDisplayTableRow
141 {
142 public List<string> Cells { get; private set; }
143
144 public ConsoleDisplayTableRow(List<string> cells) : this()
145 {
146 Cells = cells;
147 }
148
149 public ConsoleDisplayTableRow(params string[] cells) : this()
150 {
151 Cells = new List<string>(cells);
152 }
153 }
154} \ No newline at end of file
diff --git a/OpenSim/Framework/Console/LocalConsole.cs b/OpenSim/Framework/Console/LocalConsole.cs
index 7c8626d..f65813b 100644
--- a/OpenSim/Framework/Console/LocalConsole.cs
+++ b/OpenSim/Framework/Console/LocalConsole.cs
@@ -296,6 +296,10 @@ namespace OpenSim.Framework.Console
296 matches[0].Groups["Category"].Value); 296 matches[0].Groups["Category"].Value);
297 System.Console.Write("]:"); 297 System.Console.Write("]:");
298 } 298 }
299 else
300 {
301 outText = outText.Trim();
302 }
299 } 303 }
300 304
301 if (level == "error") 305 if (level == "error")
diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs
index 142b783..9020761 100644
--- a/OpenSim/Framework/EstateSettings.cs
+++ b/OpenSim/Framework/EstateSettings.cs
@@ -346,7 +346,7 @@ namespace OpenSim.Framework
346 l_EstateManagers.Remove(avatarID); 346 l_EstateManagers.Remove(avatarID);
347 } 347 }
348 348
349 public bool IsEstateManager(UUID avatarID) 349 public bool IsEstateManagerOrOwner(UUID avatarID)
350 { 350 {
351 if (IsEstateOwner(avatarID)) 351 if (IsEstateOwner(avatarID))
352 return true; 352 return true;
@@ -368,7 +368,7 @@ namespace OpenSim.Framework
368 if (ban.BannedUserID == avatarID) 368 if (ban.BannedUserID == avatarID)
369 return true; 369 return true;
370 370
371 if (!IsEstateManager(avatarID) && !HasAccess(avatarID)) 371 if (!IsEstateManagerOrOwner(avatarID) && !HasAccess(avatarID))
372 { 372 {
373 if (DenyMinors) 373 if (DenyMinors)
374 { 374 {
@@ -411,7 +411,7 @@ namespace OpenSim.Framework
411 411
412 public bool HasAccess(UUID user) 412 public bool HasAccess(UUID user)
413 { 413 {
414 if (IsEstateManager(user)) 414 if (IsEstateManagerOrOwner(user))
415 return true; 415 return true;
416 416
417 return l_EstateAccess.Contains(user); 417 return l_EstateAccess.Contains(user);
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index c1bd078..58a65de 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -749,14 +749,21 @@ namespace OpenSim.Framework
749 /// </summary> 749 /// </summary>
750 string Name { get; } 750 string Name { get; }
751 751
752 /// <value> 752 /// <summary>
753 /// Determines whether the client thread is doing anything or not. 753 /// True if the client is active (sending and receiving new UDP messages). False if the client is being closed.
754 /// </value> 754 /// </summary>
755 bool IsActive { get; set; } 755 bool IsActive { get; set; }
756 756
757 /// <value> 757 /// <summary>
758 /// Determines whether the client is or has been removed from a given scene 758 /// Set if the client is closing due to a logout request
759 /// </value> 759 /// </summary>
760 /// <remarks>
761 /// Do not use this flag if you want to know if the client is closing, since it will not be set in other
762 /// circumstances (e.g. if a child agent is closed or the agent is kicked off the simulator). Use IsActive
763 /// instead with a IClientAPI.SceneAgent.IsChildAgent check if necessary.
764 ///
765 /// Only set for root agents.
766 /// </remarks>
760 bool IsLoggingOut { get; set; } 767 bool IsLoggingOut { get; set; }
761 768
762 bool SendLogoutPacketWhenClosing { set; } 769 bool SendLogoutPacketWhenClosing { set; }
@@ -1362,7 +1369,6 @@ namespace OpenSim.Framework
1362 void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message); 1369 void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message);
1363 1370
1364 void SendLogoutPacket(); 1371 void SendLogoutPacket();
1365 EndPoint GetClientEP();
1366 1372
1367 // WARNING WARNING WARNING 1373 // WARNING WARNING WARNING
1368 // 1374 //
@@ -1423,8 +1429,6 @@ namespace OpenSim.Framework
1423 1429
1424 void SendGroupVoteHistory(UUID groupID, UUID transactionID, GroupVoteHistory[] Votes); 1430 void SendGroupVoteHistory(UUID groupID, UUID transactionID, GroupVoteHistory[] Votes);
1425 1431
1426 void KillEndDone();
1427
1428 bool AddGenericPacketHandler(string MethodName, GenericMessage handler); 1432 bool AddGenericPacketHandler(string MethodName, GenericMessage handler);
1429 1433
1430 void SendRebakeAvatarTextures(UUID textureID); 1434 void SendRebakeAvatarTextures(UUID textureID);
diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs
index b2604f4..a9432c2 100644
--- a/OpenSim/Framework/IScene.cs
+++ b/OpenSim/Framework/IScene.cs
@@ -56,6 +56,11 @@ namespace OpenSim.Framework
56 56
57 public interface IScene 57 public interface IScene
58 { 58 {
59 /// <summary>
60 /// The name of this scene.
61 /// </summary>
62 string Name { get; }
63
59 RegionInfo RegionInfo { get; } 64 RegionInfo RegionInfo { get; }
60 RegionStatus RegionStatus { get; set; } 65 RegionStatus RegionStatus { get; set; }
61 66
diff --git a/OpenSim/Framework/ISceneAgent.cs b/OpenSim/Framework/ISceneAgent.cs
index 824172d..563d906 100644
--- a/OpenSim/Framework/ISceneAgent.cs
+++ b/OpenSim/Framework/ISceneAgent.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using OpenMetaverse;
29 30
30namespace OpenSim.Framework 31namespace OpenSim.Framework
31{ 32{
@@ -71,5 +72,11 @@ namespace OpenSim.Framework
71 /// This includes scene object data and the appearance data of other avatars. 72 /// This includes scene object data and the appearance data of other avatars.
72 /// </remarks> 73 /// </remarks>
73 void SendInitialDataToMe(); 74 void SendInitialDataToMe();
75
76 /// <summary>
77 /// Direction in which the scene presence is looking.
78 /// </summary>
79 /// <remarks>Will be Vector3.Zero for a child agent.</remarks>
80 Vector3 Lookat { get; }
74 } 81 }
75} \ No newline at end of file 82} \ No newline at end of file
diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs
index c6ccc9e..fcc9873 100644
--- a/OpenSim/Framework/PrimitiveBaseShape.cs
+++ b/OpenSim/Framework/PrimitiveBaseShape.cs
@@ -241,10 +241,14 @@ namespace OpenSim.Framework
241 241
242 m_textureEntry = prim.Textures.GetBytes(); 242 m_textureEntry = prim.Textures.GetBytes();
243 243
244 SculptEntry = (prim.Sculpt.Type != OpenMetaverse.SculptType.None); 244 if (prim.Sculpt != null)
245 SculptData = prim.Sculpt.GetBytes(); 245 {
246 SculptTexture = prim.Sculpt.SculptTexture; 246 SculptEntry = (prim.Sculpt.Type != OpenMetaverse.SculptType.None);
247 SculptType = (byte)prim.Sculpt.Type; 247 SculptData = prim.Sculpt.GetBytes();
248 SculptTexture = prim.Sculpt.SculptTexture;
249 SculptType = (byte)prim.Sculpt.Type;
250 }
251 else SculptType = (byte)OpenMetaverse.SculptType.None;
248 } 252 }
249 253
250 [XmlIgnore] 254 [XmlIgnore]
diff --git a/OpenSim/Framework/RegionSettings.cs b/OpenSim/Framework/RegionSettings.cs
index c142bd9..47a2780 100644
--- a/OpenSim/Framework/RegionSettings.cs
+++ b/OpenSim/Framework/RegionSettings.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using OpenMetaverse; 31using OpenMetaverse;
32using System.Runtime.Serialization;
32 33
33namespace OpenSim.Framework 34namespace OpenSim.Framework
34{ 35{
@@ -71,6 +72,32 @@ namespace OpenSim.Framework
71 72
72 return pos + offset; 73 return pos + offset;
73 } 74 }
75
76 /// <summary>
77 /// Returns a string representation of this SpawnPoint.
78 /// </summary>
79 /// <returns></returns>
80 public override string ToString()
81 {
82 return string.Format("{0},{1},{2}", Yaw, Pitch, Distance);
83 }
84
85 /// <summary>
86 /// Generate a SpawnPoint from a string
87 /// </summary>
88 /// <param name="str"></param>
89 public static SpawnPoint Parse(string str)
90 {
91 string[] parts = str.Split(',');
92 if (parts.Length != 3)
93 throw new ArgumentException("Invalid string: " + str);
94
95 SpawnPoint sp = new SpawnPoint();
96 sp.Yaw = float.Parse(parts[0]);
97 sp.Pitch = float.Parse(parts[1]);
98 sp.Distance = float.Parse(parts[2]);
99 return sp;
100 }
74 } 101 }
75 102
76 public class RegionSettings 103 public class RegionSettings
@@ -478,7 +505,7 @@ namespace OpenSim.Framework
478 } 505 }
479 506
480 // Connected Telehub object 507 // Connected Telehub object
481 private UUID m_TelehubObject; 508 private UUID m_TelehubObject = UUID.Zero;
482 public UUID TelehubObject 509 public UUID TelehubObject
483 { 510 {
484 get 511 get
diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs
index db4541e..537de7a 100644
--- a/OpenSim/Framework/SLUtil.cs
+++ b/OpenSim/Framework/SLUtil.cs
@@ -38,239 +38,189 @@ namespace OpenSim.Framework
38 public static class SLUtil 38 public static class SLUtil
39 { 39 {
40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41 41
42 #region SL / file extension / content-type conversions 42 #region SL / file extension / content-type conversions
43 43
44 public static string SLAssetTypeToContentType(int assetType) 44 private class TypeMapping
45 { 45 {
46 switch ((AssetType)assetType) 46 private sbyte assetType;
47 private InventoryType inventoryType;
48 private string contentType;
49 private string contentType2;
50 private string extension;
51
52 public sbyte AssetTypeCode
53 {
54 get { return assetType; }
55 }
56
57 public object AssetType
58 {
59 get {
60 if (Enum.IsDefined(typeof(OpenMetaverse.AssetType), assetType))
61 return (OpenMetaverse.AssetType)assetType;
62 else
63 return OpenMetaverse.AssetType.Unknown;
64 }
65 }
66
67 public InventoryType InventoryType
68 {
69 get { return inventoryType; }
70 }
71
72 public string ContentType
73 {
74 get { return contentType; }
75 }
76
77 public string ContentType2
78 {
79 get { return contentType2; }
80 }
81
82 public string Extension
83 {
84 get { return extension; }
85 }
86
87 private TypeMapping(sbyte assetType, InventoryType inventoryType, string contentType, string contentType2, string extension)
88 {
89 this.assetType = assetType;
90 this.inventoryType = inventoryType;
91 this.contentType = contentType;
92 this.contentType2 = contentType2;
93 this.extension = extension;
94 }
95
96 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string contentType2, string extension)
97 : this((sbyte)assetType, inventoryType, contentType, contentType2, extension)
98 {
99 }
100
101 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string extension)
102 : this((sbyte)assetType, inventoryType, contentType, null, extension)
47 { 103 {
48 case AssetType.Texture:
49 return "image/x-j2c";
50 case AssetType.Sound:
51 return "audio/ogg";
52 case AssetType.CallingCard:
53 return "application/vnd.ll.callingcard";
54 case AssetType.Landmark:
55 return "application/vnd.ll.landmark";
56 case AssetType.Clothing:
57 return "application/vnd.ll.clothing";
58 case AssetType.Object:
59 return "application/vnd.ll.primitive";
60 case AssetType.Notecard:
61 return "application/vnd.ll.notecard";
62 case AssetType.Folder:
63 return "application/vnd.ll.folder";
64 case AssetType.RootFolder:
65 return "application/vnd.ll.rootfolder";
66 case AssetType.LSLText:
67 return "application/vnd.ll.lsltext";
68 case AssetType.LSLBytecode:
69 return "application/vnd.ll.lslbyte";
70 case AssetType.TextureTGA:
71 case AssetType.ImageTGA:
72 return "image/tga";
73 case AssetType.Bodypart:
74 return "application/vnd.ll.bodypart";
75 case AssetType.TrashFolder:
76 return "application/vnd.ll.trashfolder";
77 case AssetType.SnapshotFolder:
78 return "application/vnd.ll.snapshotfolder";
79 case AssetType.LostAndFoundFolder:
80 return "application/vnd.ll.lostandfoundfolder";
81 case AssetType.SoundWAV:
82 return "audio/x-wav";
83 case AssetType.ImageJPEG:
84 return "image/jpeg";
85 case AssetType.Animation:
86 return "application/vnd.ll.animation";
87 case AssetType.Gesture:
88 return "application/vnd.ll.gesture";
89 case AssetType.Simstate:
90 return "application/x-metaverse-simstate";
91 case AssetType.FavoriteFolder:
92 return "application/vnd.ll.favoritefolder";
93 case AssetType.Link:
94 return "application/vnd.ll.link";
95 case AssetType.LinkFolder:
96 return "application/vnd.ll.linkfolder";
97 case AssetType.CurrentOutfitFolder:
98 return "application/vnd.ll.currentoutfitfolder";
99 case AssetType.OutfitFolder:
100 return "application/vnd.ll.outfitfolder";
101 case AssetType.MyOutfitsFolder:
102 return "application/vnd.ll.myoutfitsfolder";
103 case AssetType.Unknown:
104 default:
105 return "application/octet-stream";
106 } 104 }
107 } 105 }
108 106
109 public static string SLInvTypeToContentType(int invType) 107 /// <summary>
108 /// Maps between AssetType, InventoryType and Content-Type.
109 /// Where more than one possibility exists, the first one takes precedence. E.g.:
110 /// AssetType "AssetType.Texture" -> Content-Type "image-xj2c"
111 /// Content-Type "image/x-j2c" -> InventoryType "InventoryType.Texture"
112 /// </summary>
113 private static TypeMapping[] MAPPINGS = new TypeMapping[] {
114 new TypeMapping(AssetType.Unknown, InventoryType.Unknown, "application/octet-stream", "bin"),
115 new TypeMapping(AssetType.Texture, InventoryType.Texture, "image/x-j2c", "image/jp2", "j2c"),
116 new TypeMapping(AssetType.Texture, InventoryType.Snapshot, "image/x-j2c", "image/jp2", "j2c"),
117 new TypeMapping(AssetType.TextureTGA, InventoryType.Texture, "image/tga", "tga"),
118 new TypeMapping(AssetType.ImageTGA, InventoryType.Texture, "image/tga", "tga"),
119 new TypeMapping(AssetType.ImageJPEG, InventoryType.Texture, "image/jpeg", "jpg"),
120 new TypeMapping(AssetType.Sound, InventoryType.Sound, "audio/ogg", "application/ogg", "ogg"),
121 new TypeMapping(AssetType.SoundWAV, InventoryType.Sound, "audio/x-wav", "wav"),
122 new TypeMapping(AssetType.CallingCard, InventoryType.CallingCard, "application/vnd.ll.callingcard", "application/x-metaverse-callingcard", "callingcard"),
123 new TypeMapping(AssetType.Landmark, InventoryType.Landmark, "application/vnd.ll.landmark", "application/x-metaverse-landmark", "landmark"),
124 new TypeMapping(AssetType.Clothing, InventoryType.Wearable, "application/vnd.ll.clothing", "application/x-metaverse-clothing", "clothing"),
125 new TypeMapping(AssetType.Object, InventoryType.Object, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"),
126 new TypeMapping(AssetType.Object, InventoryType.Attachment, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"),
127 new TypeMapping(AssetType.Notecard, InventoryType.Notecard, "application/vnd.ll.notecard", "application/x-metaverse-notecard", "notecard"),
128 new TypeMapping(AssetType.Folder, InventoryType.Folder, "application/vnd.ll.folder", "folder"),
129 new TypeMapping(AssetType.RootFolder, InventoryType.RootCategory, "application/vnd.ll.rootfolder", "rootfolder"),
130 new TypeMapping(AssetType.LSLText, InventoryType.LSL, "application/vnd.ll.lsltext", "application/x-metaverse-lsl", "lsl"),
131 new TypeMapping(AssetType.LSLBytecode, InventoryType.LSL, "application/vnd.ll.lslbyte", "application/x-metaverse-lso", "lso"),
132 new TypeMapping(AssetType.Bodypart, InventoryType.Wearable, "application/vnd.ll.bodypart", "application/x-metaverse-bodypart", "bodypart"),
133 new TypeMapping(AssetType.TrashFolder, InventoryType.Folder, "application/vnd.ll.trashfolder", "trashfolder"),
134 new TypeMapping(AssetType.SnapshotFolder, InventoryType.Folder, "application/vnd.ll.snapshotfolder", "snapshotfolder"),
135 new TypeMapping(AssetType.LostAndFoundFolder, InventoryType.Folder, "application/vnd.ll.lostandfoundfolder", "lostandfoundfolder"),
136 new TypeMapping(AssetType.Animation, InventoryType.Animation, "application/vnd.ll.animation", "application/x-metaverse-animation", "animation"),
137 new TypeMapping(AssetType.Gesture, InventoryType.Gesture, "application/vnd.ll.gesture", "application/x-metaverse-gesture", "gesture"),
138 new TypeMapping(AssetType.Simstate, InventoryType.Snapshot, "application/x-metaverse-simstate", "simstate"),
139 new TypeMapping(AssetType.FavoriteFolder, InventoryType.Unknown, "application/vnd.ll.favoritefolder", "favoritefolder"),
140 new TypeMapping(AssetType.Link, InventoryType.Unknown, "application/vnd.ll.link", "link"),
141 new TypeMapping(AssetType.LinkFolder, InventoryType.Unknown, "application/vnd.ll.linkfolder", "linkfolder"),
142 new TypeMapping(AssetType.CurrentOutfitFolder, InventoryType.Unknown, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"),
143 new TypeMapping(AssetType.OutfitFolder, InventoryType.Unknown, "application/vnd.ll.outfitfolder", "outfitfolder"),
144 new TypeMapping(AssetType.MyOutfitsFolder, InventoryType.Unknown, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"),
145 new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm")
146 };
147
148 private static Dictionary<sbyte, string> asset2Content;
149 private static Dictionary<sbyte, string> asset2Extension;
150 private static Dictionary<InventoryType, string> inventory2Content;
151 private static Dictionary<string, sbyte> content2Asset;
152 private static Dictionary<string, InventoryType> content2Inventory;
153
154 static SLUtil()
110 { 155 {
111 switch ((InventoryType)invType) 156 asset2Content = new Dictionary<sbyte, string>();
157 asset2Extension = new Dictionary<sbyte, string>();
158 inventory2Content = new Dictionary<InventoryType, string>();
159 content2Asset = new Dictionary<string, sbyte>();
160 content2Inventory = new Dictionary<string, InventoryType>();
161
162 foreach (TypeMapping mapping in MAPPINGS)
112 { 163 {
113 case InventoryType.Animation: 164 sbyte assetType = mapping.AssetTypeCode;
114 return "application/vnd.ll.animation"; 165 if (!asset2Content.ContainsKey(assetType))
115 case InventoryType.CallingCard: 166 asset2Content.Add(assetType, mapping.ContentType);
116 return "application/vnd.ll.callingcard"; 167 if (!asset2Extension.ContainsKey(assetType))
117 case InventoryType.Folder: 168 asset2Extension.Add(assetType, mapping.Extension);
118 return "application/vnd.ll.folder"; 169 if (!inventory2Content.ContainsKey(mapping.InventoryType))
119 case InventoryType.Gesture: 170 inventory2Content.Add(mapping.InventoryType, mapping.ContentType);
120 return "application/vnd.ll.gesture"; 171 if (!content2Asset.ContainsKey(mapping.ContentType))
121 case InventoryType.Landmark: 172 content2Asset.Add(mapping.ContentType, assetType);
122 return "application/vnd.ll.landmark"; 173 if (!content2Inventory.ContainsKey(mapping.ContentType))
123 case InventoryType.LSL: 174 content2Inventory.Add(mapping.ContentType, mapping.InventoryType);
124 return "application/vnd.ll.lsltext"; 175
125 case InventoryType.Notecard: 176 if (mapping.ContentType2 != null)
126 return "application/vnd.ll.notecard"; 177 {
127 case InventoryType.Attachment: 178 if (!content2Asset.ContainsKey(mapping.ContentType2))
128 case InventoryType.Object: 179 content2Asset.Add(mapping.ContentType2, assetType);
129 return "application/vnd.ll.primitive"; 180 if (!content2Inventory.ContainsKey(mapping.ContentType2))
130 case InventoryType.Sound: 181 content2Inventory.Add(mapping.ContentType2, mapping.InventoryType);
131 return "audio/ogg"; 182 }
132 case InventoryType.Snapshot:
133 case InventoryType.Texture:
134 return "image/x-j2c";
135 case InventoryType.Wearable:
136 return "application/vnd.ll.clothing";
137 default:
138 return "application/octet-stream";
139 } 183 }
140 } 184 }
185
186 public static string SLAssetTypeToContentType(int assetType)
187 {
188 string contentType;
189 if (!asset2Content.TryGetValue((sbyte)assetType, out contentType))
190 contentType = asset2Content[(sbyte)AssetType.Unknown];
191 return contentType;
192 }
193
194 public static string SLInvTypeToContentType(int invType)
195 {
196 string contentType;
197 if (!inventory2Content.TryGetValue((InventoryType)invType, out contentType))
198 contentType = inventory2Content[InventoryType.Unknown];
199 return contentType;
200 }
141 201
142 public static sbyte ContentTypeToSLAssetType(string contentType) 202 public static sbyte ContentTypeToSLAssetType(string contentType)
143 { 203 {
144 switch (contentType) 204 sbyte assetType;
145 { 205 if (!content2Asset.TryGetValue(contentType, out assetType))
146 case "image/x-j2c": 206 assetType = (sbyte)AssetType.Unknown;
147 case "image/jp2": 207 return (sbyte)assetType;
148 return (sbyte)AssetType.Texture;
149 case "application/ogg":
150 case "audio/ogg":
151 return (sbyte)AssetType.Sound;
152 case "application/vnd.ll.callingcard":
153 case "application/x-metaverse-callingcard":
154 return (sbyte)AssetType.CallingCard;
155 case "application/vnd.ll.landmark":
156 case "application/x-metaverse-landmark":
157 return (sbyte)AssetType.Landmark;
158 case "application/vnd.ll.clothing":
159 case "application/x-metaverse-clothing":
160 return (sbyte)AssetType.Clothing;
161 case "application/vnd.ll.primitive":
162 case "application/x-metaverse-primitive":
163 return (sbyte)AssetType.Object;
164 case "application/vnd.ll.notecard":
165 case "application/x-metaverse-notecard":
166 return (sbyte)AssetType.Notecard;
167 case "application/vnd.ll.folder":
168 return (sbyte)AssetType.Folder;
169 case "application/vnd.ll.rootfolder":
170 return (sbyte)AssetType.RootFolder;
171 case "application/vnd.ll.lsltext":
172 case "application/x-metaverse-lsl":
173 return (sbyte)AssetType.LSLText;
174 case "application/vnd.ll.lslbyte":
175 case "application/x-metaverse-lso":
176 return (sbyte)AssetType.LSLBytecode;
177 case "image/tga":
178 // Note that AssetType.TextureTGA will be converted to AssetType.ImageTGA
179 return (sbyte)AssetType.ImageTGA;
180 case "application/vnd.ll.bodypart":
181 case "application/x-metaverse-bodypart":
182 return (sbyte)AssetType.Bodypart;
183 case "application/vnd.ll.trashfolder":
184 return (sbyte)AssetType.TrashFolder;
185 case "application/vnd.ll.snapshotfolder":
186 return (sbyte)AssetType.SnapshotFolder;
187 case "application/vnd.ll.lostandfoundfolder":
188 return (sbyte)AssetType.LostAndFoundFolder;
189 case "audio/x-wav":
190 return (sbyte)AssetType.SoundWAV;
191 case "image/jpeg":
192 return (sbyte)AssetType.ImageJPEG;
193 case "application/vnd.ll.animation":
194 case "application/x-metaverse-animation":
195 return (sbyte)AssetType.Animation;
196 case "application/vnd.ll.gesture":
197 case "application/x-metaverse-gesture":
198 return (sbyte)AssetType.Gesture;
199 case "application/x-metaverse-simstate":
200 return (sbyte)AssetType.Simstate;
201 case "application/vnd.ll.favoritefolder":
202 return (sbyte)AssetType.FavoriteFolder;
203 case "application/vnd.ll.link":
204 return (sbyte)AssetType.Link;
205 case "application/vnd.ll.linkfolder":
206 return (sbyte)AssetType.LinkFolder;
207 case "application/vnd.ll.currentoutfitfolder":
208 return (sbyte)AssetType.CurrentOutfitFolder;
209 case "application/vnd.ll.outfitfolder":
210 return (sbyte)AssetType.OutfitFolder;
211 case "application/vnd.ll.myoutfitsfolder":
212 return (sbyte)AssetType.MyOutfitsFolder;
213 case "application/octet-stream":
214 default:
215 return (sbyte)AssetType.Unknown;
216 }
217 } 208 }
218 209
219 public static sbyte ContentTypeToSLInvType(string contentType) 210 public static sbyte ContentTypeToSLInvType(string contentType)
220 { 211 {
221 switch (contentType) 212 InventoryType invType;
222 { 213 if (!content2Inventory.TryGetValue(contentType, out invType))
223 case "image/x-j2c": 214 invType = InventoryType.Unknown;
224 case "image/jp2": 215 return (sbyte)invType;
225 case "image/tga": 216 }
226 case "image/jpeg": 217
227 return (sbyte)InventoryType.Texture; 218 public static string SLAssetTypeToExtension(int assetType)
228 case "application/ogg": 219 {
229 case "audio/ogg": 220 string extension;
230 case "audio/x-wav": 221 if (!asset2Extension.TryGetValue((sbyte)assetType, out extension))
231 return (sbyte)InventoryType.Sound; 222 extension = asset2Extension[(sbyte)AssetType.Unknown];
232 case "application/vnd.ll.callingcard": 223 return extension;
233 case "application/x-metaverse-callingcard":
234 return (sbyte)InventoryType.CallingCard;
235 case "application/vnd.ll.landmark":
236 case "application/x-metaverse-landmark":
237 return (sbyte)InventoryType.Landmark;
238 case "application/vnd.ll.clothing":
239 case "application/x-metaverse-clothing":
240 case "application/vnd.ll.bodypart":
241 case "application/x-metaverse-bodypart":
242 return (sbyte)InventoryType.Wearable;
243 case "application/vnd.ll.primitive":
244 case "application/x-metaverse-primitive":
245 return (sbyte)InventoryType.Object;
246 case "application/vnd.ll.notecard":
247 case "application/x-metaverse-notecard":
248 return (sbyte)InventoryType.Notecard;
249 case "application/vnd.ll.folder":
250 return (sbyte)InventoryType.Folder;
251 case "application/vnd.ll.rootfolder":
252 return (sbyte)InventoryType.RootCategory;
253 case "application/vnd.ll.lsltext":
254 case "application/x-metaverse-lsl":
255 case "application/vnd.ll.lslbyte":
256 case "application/x-metaverse-lso":
257 return (sbyte)InventoryType.LSL;
258 case "application/vnd.ll.trashfolder":
259 case "application/vnd.ll.snapshotfolder":
260 case "application/vnd.ll.lostandfoundfolder":
261 return (sbyte)InventoryType.Folder;
262 case "application/vnd.ll.animation":
263 case "application/x-metaverse-animation":
264 return (sbyte)InventoryType.Animation;
265 case "application/vnd.ll.gesture":
266 case "application/x-metaverse-gesture":
267 return (sbyte)InventoryType.Gesture;
268 case "application/x-metaverse-simstate":
269 return (sbyte)InventoryType.Snapshot;
270 case "application/octet-stream":
271 default:
272 return (sbyte)InventoryType.Unknown;
273 }
274 } 224 }
275 225
276 #endregion SL / file extension / content-type conversions 226 #endregion SL / file extension / content-type conversions
@@ -377,4 +327,4 @@ namespace OpenSim.Framework
377 return output; 327 return output;
378 } 328 }
379 } 329 }
380} \ No newline at end of file 330}
diff --git a/OpenSim/Framework/Serialization/External/LandDataSerializer.cs b/OpenSim/Framework/Serialization/External/LandDataSerializer.cs
index a12877a..a64f01c 100644
--- a/OpenSim/Framework/Serialization/External/LandDataSerializer.cs
+++ b/OpenSim/Framework/Serialization/External/LandDataSerializer.cs
@@ -42,9 +42,7 @@ namespace OpenSim.Framework.Serialization.External
42 /// </summary> 42 /// </summary>
43 public class LandDataSerializer 43 public class LandDataSerializer
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
47 protected static UTF8Encoding m_utf8Encoding = new UTF8Encoding();
48 46
49 private static Dictionary<string, Action<LandData, XmlTextReader>> m_ldProcessors 47 private static Dictionary<string, Action<LandData, XmlTextReader>> m_ldProcessors
50 = new Dictionary<string, Action<LandData, XmlTextReader>>(); 48 = new Dictionary<string, Action<LandData, XmlTextReader>>();
@@ -163,7 +161,7 @@ namespace OpenSim.Framework.Serialization.External
163 /// <exception cref="System.Xml.XmlException"></exception> 161 /// <exception cref="System.Xml.XmlException"></exception>
164 public static LandData Deserialize(byte[] serializedLandData) 162 public static LandData Deserialize(byte[] serializedLandData)
165 { 163 {
166 return Deserialize(m_utf8Encoding.GetString(serializedLandData, 0, serializedLandData.Length)); 164 return Deserialize(Encoding.UTF8.GetString(serializedLandData, 0, serializedLandData.Length));
167 } 165 }
168 166
169 /// <summary> 167 /// <summary>
diff --git a/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs b/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs
index 931898c..19468c3 100644
--- a/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs
+++ b/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs
@@ -30,6 +30,8 @@ using System.Text;
30using System.Xml; 30using System.Xml;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using log4net;
34using System.Reflection;
33 35
34namespace OpenSim.Framework.Serialization.External 36namespace OpenSim.Framework.Serialization.External
35{ 37{
@@ -38,8 +40,6 @@ namespace OpenSim.Framework.Serialization.External
38 /// </summary> 40 /// </summary>
39 public class RegionSettingsSerializer 41 public class RegionSettingsSerializer
40 { 42 {
41 protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
42
43 /// <summary> 43 /// <summary>
44 /// Deserialize settings 44 /// Deserialize settings
45 /// </summary> 45 /// </summary>
@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Serialization.External
48 /// <exception cref="System.Xml.XmlException"></exception> 48 /// <exception cref="System.Xml.XmlException"></exception>
49 public static RegionSettings Deserialize(byte[] serializedSettings) 49 public static RegionSettings Deserialize(byte[] serializedSettings)
50 { 50 {
51 return Deserialize(m_asciiEncoding.GetString(serializedSettings, 0, serializedSettings.Length)); 51 return Deserialize(Encoding.ASCII.GetString(serializedSettings, 0, serializedSettings.Length));
52 } 52 }
53 53
54 /// <summary> 54 /// <summary>
@@ -187,7 +187,29 @@ namespace OpenSim.Framework.Serialization.External
187 break; 187 break;
188 } 188 }
189 } 189 }
190 190
191 xtr.ReadEndElement();
192
193 if (xtr.IsStartElement("Telehub"))
194 {
195 xtr.ReadStartElement("Telehub");
196
197 while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement)
198 {
199 switch (xtr.Name)
200 {
201 case "TelehubObject":
202 settings.TelehubObject = UUID.Parse(xtr.ReadElementContentAsString());
203 break;
204 case "SpawnPoint":
205 string str = xtr.ReadElementContentAsString();
206 SpawnPoint sp = SpawnPoint.Parse(str);
207 settings.AddSpawnPoint(sp);
208 break;
209 }
210 }
211 }
212
191 xtr.Close(); 213 xtr.Close();
192 sr.Close(); 214 sr.Close();
193 215
@@ -243,7 +265,16 @@ namespace OpenSim.Framework.Serialization.External
243 xtw.WriteElementString("SunPosition", settings.SunPosition.ToString()); 265 xtw.WriteElementString("SunPosition", settings.SunPosition.ToString());
244 // Note: 'SunVector' isn't saved because this value is owned by the Sun Module, which 266 // Note: 'SunVector' isn't saved because this value is owned by the Sun Module, which
245 // calculates it automatically according to the date and other factors. 267 // calculates it automatically according to the date and other factors.
246 xtw.WriteEndElement(); 268 xtw.WriteEndElement();
269
270 xtw.WriteStartElement("Telehub");
271 if (settings.TelehubObject != UUID.Zero)
272 {
273 xtw.WriteElementString("TelehubObject", settings.TelehubObject.ToString());
274 foreach (SpawnPoint sp in settings.SpawnPoints())
275 xtw.WriteElementString("SpawnPoint", sp.ToString());
276 }
277 xtw.WriteEndElement();
247 278
248 xtw.WriteEndElement(); 279 xtw.WriteEndElement();
249 280
diff --git a/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs b/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs
index 57da7ca..88f9581 100644
--- a/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs
+++ b/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Framework.Serialization.External
44 /// </summary> 44 /// </summary>
45 public class UserInventoryItemSerializer 45 public class UserInventoryItemSerializer
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, XmlTextReader>> m_InventoryItemXmlProcessors
50 = new Dictionary<string, Action<InventoryItemBase, XmlTextReader>>(); 50 = new Dictionary<string, Action<InventoryItemBase, XmlTextReader>>();
diff --git a/OpenSim/Framework/Serialization/TarArchiveReader.cs b/OpenSim/Framework/Serialization/TarArchiveReader.cs
index 77c29f8..339a37a 100644
--- a/OpenSim/Framework/Serialization/TarArchiveReader.cs
+++ b/OpenSim/Framework/Serialization/TarArchiveReader.cs
@@ -53,8 +53,6 @@ namespace OpenSim.Framework.Serialization
53 TYPE_CONTIGUOUS_FILE = 8, 53 TYPE_CONTIGUOUS_FILE = 8,
54 } 54 }
55 55
56 protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
57
58 /// <summary> 56 /// <summary>
59 /// Binary reader for the underlying stream 57 /// Binary reader for the underlying stream
60 /// </summary> 58 /// </summary>
@@ -120,13 +118,13 @@ namespace OpenSim.Framework.Serialization
120 if (header[156] == (byte)'L') 118 if (header[156] == (byte)'L')
121 { 119 {
122 int longNameLength = ConvertOctalBytesToDecimal(header, 124, 11); 120 int longNameLength = ConvertOctalBytesToDecimal(header, 124, 11);
123 tarHeader.FilePath = m_asciiEncoding.GetString(ReadData(longNameLength)); 121 tarHeader.FilePath = Encoding.ASCII.GetString(ReadData(longNameLength));
124 //m_log.DebugFormat("[TAR ARCHIVE READER]: Got long file name {0}", tarHeader.FilePath); 122 //m_log.DebugFormat("[TAR ARCHIVE READER]: Got long file name {0}", tarHeader.FilePath);
125 header = m_br.ReadBytes(512); 123 header = m_br.ReadBytes(512);
126 } 124 }
127 else 125 else
128 { 126 {
129 tarHeader.FilePath = m_asciiEncoding.GetString(header, 0, 100); 127 tarHeader.FilePath = Encoding.ASCII.GetString(header, 0, 100);
130 tarHeader.FilePath = tarHeader.FilePath.Trim(m_nullCharArray); 128 tarHeader.FilePath = tarHeader.FilePath.Trim(m_nullCharArray);
131 //m_log.DebugFormat("[TAR ARCHIVE READER]: Got short file name {0}", tarHeader.FilePath); 129 //m_log.DebugFormat("[TAR ARCHIVE READER]: Got short file name {0}", tarHeader.FilePath);
132 } 130 }
@@ -205,7 +203,7 @@ namespace OpenSim.Framework.Serialization
205 { 203 {
206 // Trim leading white space: ancient tars do that instead 204 // Trim leading white space: ancient tars do that instead
207 // of leading 0s :-( don't ask. really. 205 // of leading 0s :-( don't ask. really.
208 string oString = m_asciiEncoding.GetString(bytes, startIndex, count).TrimStart(m_spaceCharArray); 206 string oString = Encoding.ASCII.GetString(bytes, startIndex, count).TrimStart(m_spaceCharArray);
209 207
210 int d = 0; 208 int d = 0;
211 209
diff --git a/OpenSim/Framework/Serialization/TarArchiveWriter.cs b/OpenSim/Framework/Serialization/TarArchiveWriter.cs
index fca909f..2a3bc48 100644
--- a/OpenSim/Framework/Serialization/TarArchiveWriter.cs
+++ b/OpenSim/Framework/Serialization/TarArchiveWriter.cs
@@ -41,9 +41,6 @@ namespace OpenSim.Framework.Serialization
41 { 41 {
42// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 43
44 protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
45 protected static UTF8Encoding m_utf8Encoding = new UTF8Encoding();
46
47 /// <summary> 44 /// <summary>
48 /// Binary writer for the underlying stream 45 /// Binary writer for the underlying stream
49 /// </summary> 46 /// </summary>
@@ -74,7 +71,7 @@ namespace OpenSim.Framework.Serialization
74 /// <param name="data"></param> 71 /// <param name="data"></param>
75 public void WriteFile(string filePath, string data) 72 public void WriteFile(string filePath, string data)
76 { 73 {
77 WriteFile(filePath, m_utf8Encoding.GetBytes(data)); 74 WriteFile(filePath, Util.UTF8NoBomEncoding.GetBytes(data));
78 } 75 }
79 76
80 /// <summary> 77 /// <summary>
@@ -85,7 +82,7 @@ namespace OpenSim.Framework.Serialization
85 public void WriteFile(string filePath, byte[] data) 82 public void WriteFile(string filePath, byte[] data)
86 { 83 {
87 if (filePath.Length > 100) 84 if (filePath.Length > 100)
88 WriteEntry("././@LongLink", m_asciiEncoding.GetBytes(filePath), 'L'); 85 WriteEntry("././@LongLink", Encoding.ASCII.GetBytes(filePath), 'L');
89 86
90 char fileType; 87 char fileType;
91 88
@@ -137,7 +134,7 @@ namespace OpenSim.Framework.Serialization
137 oString = "0" + oString; 134 oString = "0" + oString;
138 } 135 }
139 136
140 byte[] oBytes = m_asciiEncoding.GetBytes(oString); 137 byte[] oBytes = Encoding.ASCII.GetBytes(oString);
141 138
142 return oBytes; 139 return oBytes;
143 } 140 }
@@ -156,20 +153,20 @@ namespace OpenSim.Framework.Serialization
156 byte[] header = new byte[512]; 153 byte[] header = new byte[512];
157 154
158 // file path field (100) 155 // file path field (100)
159 byte[] nameBytes = m_asciiEncoding.GetBytes(filePath); 156 byte[] nameBytes = Encoding.ASCII.GetBytes(filePath);
160 int nameSize = (nameBytes.Length >= 100) ? 100 : nameBytes.Length; 157 int nameSize = (nameBytes.Length >= 100) ? 100 : nameBytes.Length;
161 Array.Copy(nameBytes, header, nameSize); 158 Array.Copy(nameBytes, header, nameSize);
162 159
163 // file mode (8) 160 // file mode (8)
164 byte[] modeBytes = m_asciiEncoding.GetBytes("0000777"); 161 byte[] modeBytes = Encoding.ASCII.GetBytes("0000777");
165 Array.Copy(modeBytes, 0, header, 100, 7); 162 Array.Copy(modeBytes, 0, header, 100, 7);
166 163
167 // owner user id (8) 164 // owner user id (8)
168 byte[] ownerIdBytes = m_asciiEncoding.GetBytes("0000764"); 165 byte[] ownerIdBytes = Encoding.ASCII.GetBytes("0000764");
169 Array.Copy(ownerIdBytes, 0, header, 108, 7); 166 Array.Copy(ownerIdBytes, 0, header, 108, 7);
170 167
171 // group user id (8) 168 // group user id (8)
172 byte[] groupIdBytes = m_asciiEncoding.GetBytes("0000764"); 169 byte[] groupIdBytes = Encoding.ASCII.GetBytes("0000764");
173 Array.Copy(groupIdBytes, 0, header, 116, 7); 170 Array.Copy(groupIdBytes, 0, header, 116, 7);
174 171
175 // file size in bytes (12) 172 // file size in bytes (12)
@@ -181,17 +178,17 @@ namespace OpenSim.Framework.Serialization
181 Array.Copy(fileSizeBytes, 0, header, 124, 11); 178 Array.Copy(fileSizeBytes, 0, header, 124, 11);
182 179
183 // last modification time (12) 180 // last modification time (12)
184 byte[] lastModTimeBytes = m_asciiEncoding.GetBytes("11017037332"); 181 byte[] lastModTimeBytes = Encoding.ASCII.GetBytes("11017037332");
185 Array.Copy(lastModTimeBytes, 0, header, 136, 11); 182 Array.Copy(lastModTimeBytes, 0, header, 136, 11);
186 183
187 // entry type indicator (1) 184 // entry type indicator (1)
188 header[156] = m_asciiEncoding.GetBytes(new char[] { fileType })[0]; 185 header[156] = Encoding.ASCII.GetBytes(new char[] { fileType })[0];
189 186
190 Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 329, 7); 187 Array.Copy(Encoding.ASCII.GetBytes("0000000"), 0, header, 329, 7);
191 Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 337, 7); 188 Array.Copy(Encoding.ASCII.GetBytes("0000000"), 0, header, 337, 7);
192 189
193 // check sum for header block (8) [calculated last] 190 // check sum for header block (8) [calculated last]
194 Array.Copy(m_asciiEncoding.GetBytes(" "), 0, header, 148, 8); 191 Array.Copy(Encoding.ASCII.GetBytes(" "), 0, header, 148, 8);
195 192
196 int checksum = 0; 193 int checksum = 0;
197 foreach (byte b in header) 194 foreach (byte b in header)
diff --git a/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs b/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs
index a61e4af..09b6f6d 100644
--- a/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs
+++ b/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs
@@ -78,6 +78,10 @@ namespace OpenSim.Framework.Serialization.Tests
78 <FixedSun>true</FixedSun> 78 <FixedSun>true</FixedSun>
79 <SunPosition>12</SunPosition> 79 <SunPosition>12</SunPosition>
80 </Terrain> 80 </Terrain>
81 <Telehub>
82 <TelehubObject>00000000-0000-0000-0000-111111111111</TelehubObject>
83 <SpawnPoint>1,-2,0.33</SpawnPoint>
84 </Telehub>
81</RegionSettings>"; 85</RegionSettings>";
82 86
83 private RegionSettings m_rs; 87 private RegionSettings m_rs;
@@ -116,6 +120,8 @@ namespace OpenSim.Framework.Serialization.Tests
116 m_rs.TerrainTexture4 = UUID.Parse("00000000-0000-0000-0000-000000000080"); 120 m_rs.TerrainTexture4 = UUID.Parse("00000000-0000-0000-0000-000000000080");
117 m_rs.UseEstateSun = true; 121 m_rs.UseEstateSun = true;
118 m_rs.WaterHeight = 23; 122 m_rs.WaterHeight = 23;
123 m_rs.TelehubObject = UUID.Parse("00000000-0000-0000-0000-111111111111");
124 m_rs.AddSpawnPoint(SpawnPoint.Parse("1,-2,0.33"));
119 } 125 }
120 126
121 [Test] 127 [Test]
@@ -129,6 +135,8 @@ namespace OpenSim.Framework.Serialization.Tests
129 Assert.That(deserRs.TerrainTexture2, Is.EqualTo(m_rs.TerrainTexture2)); 135 Assert.That(deserRs.TerrainTexture2, Is.EqualTo(m_rs.TerrainTexture2));
130 Assert.That(deserRs.DisablePhysics, Is.EqualTo(m_rs.DisablePhysics)); 136 Assert.That(deserRs.DisablePhysics, Is.EqualTo(m_rs.DisablePhysics));
131 Assert.That(deserRs.TerrainLowerLimit, Is.EqualTo(m_rs.TerrainLowerLimit)); 137 Assert.That(deserRs.TerrainLowerLimit, Is.EqualTo(m_rs.TerrainLowerLimit));
138 Assert.That(deserRs.TelehubObject, Is.EqualTo(m_rs.TelehubObject));
139 Assert.That(deserRs.SpawnPoints()[0].ToString(), Is.EqualTo(m_rs.SpawnPoints()[0].ToString()));
132 } 140 }
133 } 141 }
134} 142}
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 87d04f8..9a2cd0e 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -320,7 +320,9 @@ namespace OpenSim.Framework.Servers
320 320
321 TimeSpan timeTaken = DateTime.Now - m_startuptime; 321 TimeSpan timeTaken = DateTime.Now - m_startuptime;
322 322
323 m_log.InfoFormat("[STARTUP]: Startup took {0}m {1}s", timeTaken.Minutes, timeTaken.Seconds); 323 m_log.InfoFormat(
324 "[STARTUP]: Non-script portion of startup took {0}m {1}s. PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED.",
325 timeTaken.Minutes, timeTaken.Seconds);
324 } 326 }
325 327
326 /// <summary> 328 /// <summary>
@@ -589,8 +591,8 @@ namespace OpenSim.Framework.Servers
589 { 591 {
590 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString(); 592 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
591 FileStream fs = File.Create(path); 593 FileStream fs = File.Create(path);
592 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); 594
593 Byte[] buf = enc.GetBytes(pidstring); 595 Byte[] buf = Encoding.ASCII.GetBytes(pidstring);
594 fs.Write(buf, 0, buf.Length); 596 fs.Write(buf, 0, buf.Length);
595 fs.Close(); 597 fs.Close();
596 m_pidFile = path; 598 m_pidFile = path;
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHTTPHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseHTTPHandler.cs
index 2fe9769..9f8f4a8 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHTTPHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHTTPHandler.cs
@@ -33,9 +33,9 @@ namespace OpenSim.Framework.Servers.HttpServer
33 { 33 {
34 public abstract Hashtable Handle(string path, Hashtable Request); 34 public abstract Hashtable Handle(string path, Hashtable Request);
35 35
36 protected BaseHTTPHandler(string httpMethod, string path) 36 protected BaseHTTPHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
37 : base(httpMethod, path) 37
38 { 38 protected BaseHTTPHandler(string httpMethod, string path, string name, string description)
39 } 39 : base(httpMethod, path, name, description) {}
40 } 40 }
41} 41} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index a3a5029..24f986a 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -53,6 +53,8 @@ namespace OpenSim.Framework.Servers.HttpServer
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); 54 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
55 55
56 public int DebugLevel { get; set; }
57
56 private volatile int NotSocketErrors = 0; 58 private volatile int NotSocketErrors = 0;
57 public volatile bool HTTPDRunning = false; 59 public volatile bool HTTPDRunning = false;
58 60
@@ -79,11 +81,6 @@ namespace OpenSim.Framework.Servers.HttpServer
79 81
80 private PollServiceRequestManager m_PollServiceManager; 82 private PollServiceRequestManager m_PollServiceManager;
81 83
82 /// <summary>
83 /// Control the printing of certain debug messages.
84 /// </summary>
85 public int DebugLevel { get; set; }
86
87 public uint SSLPort 84 public uint SSLPort
88 { 85 {
89 get { return m_sslport; } 86 get { return m_sslport; }
@@ -156,7 +153,7 @@ namespace OpenSim.Framework.Servers.HttpServer
156 } 153 }
157 } 154 }
158 155
159 public List<string> GetStreamHandlerKeys() 156 public List<string> GetStreamHandlerKeys()
160 { 157 {
161 lock (m_streamHandlers) 158 lock (m_streamHandlers)
162 return new List<string>(m_streamHandlers.Keys); 159 return new List<string>(m_streamHandlers.Keys);
@@ -356,7 +353,7 @@ namespace OpenSim.Framework.Servers.HttpServer
356 } 353 }
357 catch (Exception e) 354 catch (Exception e)
358 { 355 {
359 m_log.ErrorFormat("[BASE HTTP SERVER]: OnRequest() failed with {0}{1}", e.Message, e.StackTrace); 356 m_log.Error(String.Format("[BASE HTTP SERVER]: OnRequest() failed: {0} ", e.Message), e);
360 } 357 }
361 } 358 }
362 359
@@ -408,7 +405,12 @@ namespace OpenSim.Framework.Servers.HttpServer
408 string uriString = request.RawUrl; 405 string uriString = request.RawUrl;
409 406
410// string reqnum = "unknown"; 407// string reqnum = "unknown";
411 int tickstart = Environment.TickCount; 408 int requestStartTick = Environment.TickCount;
409
410 // Will be adjusted later on.
411 int requestEndTick = requestStartTick;
412
413 IRequestHandler requestHandler = null;
412 414
413 try 415 try
414 { 416 {
@@ -431,6 +433,7 @@ namespace OpenSim.Framework.Servers.HttpServer
431 { 433 {
432 if (HandleAgentRequest(agentHandler, request, response)) 434 if (HandleAgentRequest(agentHandler, request, response))
433 { 435 {
436 requestEndTick = Environment.TickCount;
434 return; 437 return;
435 } 438 }
436 } 439 }
@@ -438,20 +441,16 @@ namespace OpenSim.Framework.Servers.HttpServer
438 //response.KeepAlive = true; 441 //response.KeepAlive = true;
439 response.SendChunked = false; 442 response.SendChunked = false;
440 443
441 IRequestHandler requestHandler;
442
443 string path = request.RawUrl; 444 string path = request.RawUrl;
444 string handlerKey = GetHandlerKey(request.HttpMethod, path); 445 string handlerKey = GetHandlerKey(request.HttpMethod, path);
446 byte[] buffer = null;
445 447
446 if (TryGetStreamHandler(handlerKey, out requestHandler)) 448 if (TryGetStreamHandler(handlerKey, out requestHandler))
447 { 449 {
448 if (DebugLevel >= 1) 450 if (DebugLevel >= 3)
449 m_log.DebugFormat( 451 m_log.DebugFormat(
450 "[BASE HTTP SERVER]: Found stream handler for {0} {1}", 452 "[BASE HTTP SERVER]: Found stream handler for {0} {1} {2} {3}",
451 request.HttpMethod, request.Url.PathAndQuery); 453 request.HttpMethod, request.Url.PathAndQuery, requestHandler.Name, requestHandler.Description);
452
453 // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler.
454 byte[] buffer = null;
455 454
456 response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. 455 response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
457 456
@@ -507,8 +506,8 @@ namespace OpenSim.Framework.Servers.HttpServer
507 //m_log.Warn("[HTTP]: " + requestBody); 506 //m_log.Warn("[HTTP]: " + requestBody);
508 507
509 } 508 }
510 DoHTTPGruntWork(HTTPRequestHandler.Handle(path, keysvals), response); 509
511 return; 510 buffer = DoHTTPGruntWork(HTTPRequestHandler.Handle(path, keysvals), response);
512 } 511 }
513 else 512 else
514 { 513 {
@@ -521,133 +520,99 @@ namespace OpenSim.Framework.Servers.HttpServer
521 buffer = memoryStream.ToArray(); 520 buffer = memoryStream.ToArray();
522 } 521 }
523 } 522 }
524
525 request.InputStream.Close();
526
527 // HTTP IN support. The script engine takes it from here
528 // Nothing to worry about for us.
529 //
530 if (buffer == null)
531 return;
532
533 if (!response.SendChunked)
534 response.ContentLength64 = buffer.LongLength;
535
536 try
537 {
538 response.OutputStream.Write(buffer, 0, buffer.Length);
539 //response.OutputStream.Close();
540 }
541 catch (HttpListenerException)
542 {
543 m_log.WarnFormat("[BASE HTTP SERVER]: HTTP request abnormally terminated.");
544 }
545 //response.OutputStream.Close();
546 try
547 {
548 response.Send();
549 //response.FreeContext();
550 }
551 catch (SocketException e)
552 {
553 // This has to be here to prevent a Linux/Mono crash
554 m_log.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
555 }
556 catch (IOException e)
557 {
558 m_log.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e.Message);
559 }
560
561 return;
562 } 523 }
563 524 else
564 if (request.AcceptTypes != null && request.AcceptTypes.Length > 0)
565 { 525 {
566 foreach (string strAccept in request.AcceptTypes) 526 switch (request.ContentType)
567 { 527 {
568 if (strAccept.Contains("application/llsd+xml") || 528 case null:
569 strAccept.Contains("application/llsd+json")) 529 case "text/html":
570 { 530
571 if (DebugLevel >= 1) 531 if (DebugLevel >= 3)
572 m_log.DebugFormat(
573 "[BASE HTTP SERVER]: Found application/llsd+xml accept header handler for {0} {1}",
574 request.HttpMethod, request.Url.PathAndQuery);
575
576 HandleLLSDRequests(request, response);
577 return;
578 }
579 }
580 }
581
582 switch (request.ContentType)
583 {
584 case null:
585 case "text/html":
586
587 if (DebugLevel >= 1)
588 m_log.DebugFormat(
589 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
590 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
591
592 HandleHTTPRequest(request, response);
593 return;
594
595 case "application/llsd+xml":
596 case "application/xml+llsd":
597 case "application/llsd+json":
598
599 if (DebugLevel >= 1)
600 m_log.DebugFormat(
601 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
602 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
603
604 HandleLLSDRequests(request, response);
605 return;
606
607 case "text/xml":
608 case "application/xml":
609 case "application/json":
610 default:
611 //m_log.Info("[Debug BASE HTTP SERVER]: in default handler");
612 // Point of note.. the DoWeHaveA methods check for an EXACT path
613 // if (request.RawUrl.Contains("/CAPS/EQG"))
614 // {
615 // int i = 1;
616 // }
617 //m_log.Info("[Debug BASE HTTP SERVER]: Checking for LLSD Handler");
618 if (DoWeHaveALLSDHandler(request.RawUrl))
619 {
620 if (DebugLevel >= 1)
621 m_log.DebugFormat( 532 m_log.DebugFormat(
622 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}", 533 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
623 request.ContentType, request.HttpMethod, request.Url.PathAndQuery); 534 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
624 535
625 HandleLLSDRequests(request, response); 536 buffer = HandleHTTPRequest(request, response);
626 return; 537 break;
627 } 538
628 539 case "application/llsd+xml":
629// m_log.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl); 540 case "application/xml+llsd":
630 if (DoWeHaveAHTTPHandler(request.RawUrl)) 541 case "application/llsd+json":
631 { 542
632 if (DebugLevel >= 1) 543 if (DebugLevel >= 3)
633 m_log.DebugFormat( 544 m_log.DebugFormat(
634 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}", 545 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
635 request.ContentType, request.HttpMethod, request.Url.PathAndQuery); 546 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
547
548 buffer = HandleLLSDRequests(request, response);
549 break;
550
551 case "text/xml":
552 case "application/xml":
553 case "application/json":
554 default:
555 //m_log.Info("[Debug BASE HTTP SERVER]: in default handler");
556 // Point of note.. the DoWeHaveA methods check for an EXACT path
557 // if (request.RawUrl.Contains("/CAPS/EQG"))
558 // {
559 // int i = 1;
560 // }
561 //m_log.Info("[Debug BASE HTTP SERVER]: Checking for LLSD Handler");
562 if (DoWeHaveALLSDHandler(request.RawUrl))
563 {
564 if (DebugLevel >= 3)
565 m_log.DebugFormat(
566 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
567 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
568
569 buffer = HandleLLSDRequests(request, response);
570 }
571 // m_log.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl);
572 else if (DoWeHaveAHTTPHandler(request.RawUrl))
573 {
574 if (DebugLevel >= 3)
575 m_log.DebugFormat(
576 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
577 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
578
579 buffer = HandleHTTPRequest(request, response);
580 }
581 else
582 {
583 if (DebugLevel >= 3)
584 m_log.DebugFormat(
585 "[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
586 request.HttpMethod, request.Url.PathAndQuery);
587
588 // generic login request.
589 buffer = HandleXmlRpcRequests(request, response);
590 }
591
592 break;
593 }
594 }
636 595
637 HandleHTTPRequest(request, response); 596 request.InputStream.Close();
638 return;
639 }
640
641 if (DebugLevel >= 1)
642 m_log.DebugFormat(
643 "[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
644 request.HttpMethod, request.Url.PathAndQuery);
645 597
646 // generic login request. 598 if (buffer != null)
647 HandleXmlRpcRequests(request, response); 599 {
600 if (!response.SendChunked)
601 response.ContentLength64 = buffer.LongLength;
648 602
649 return; 603 response.OutputStream.Write(buffer, 0, buffer.Length);
650 } 604 }
605
606 // Do not include the time taken to actually send the response to the caller in the measurement
607 // time. This is to avoid logging when it's the client that is slow to process rather than the
608 // server
609 requestEndTick = Environment.TickCount;
610
611 response.Send();
612
613 //response.OutputStream.Close();
614
615 //response.FreeContext();
651 } 616 }
652 catch (SocketException e) 617 catch (SocketException e)
653 { 618 {
@@ -658,25 +623,33 @@ namespace OpenSim.Framework.Servers.HttpServer
658 // 623 //
659 // An alternative may be to turn off all response write exceptions on the HttpListener, but let's go 624 // An alternative may be to turn off all response write exceptions on the HttpListener, but let's go
660 // with the minimum first 625 // with the minimum first
661 m_log.WarnFormat("[BASE HTTP SERVER]: HandleRequest threw {0}.\nNOTE: this may be spurious on Linux", e); 626 m_log.Warn(String.Format("[BASE HTTP SERVER]: HandleRequest threw {0}.\nNOTE: this may be spurious on Linux ", e.Message), e);
662 } 627 }
663 catch (IOException e) 628 catch (IOException e)
664 { 629 {
665 m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e); 630 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e);
666 } 631 }
667 catch (Exception e) 632 catch (Exception e)
668 { 633 {
669 m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e.StackTrace); 634 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e);
670 SendHTML500(response); 635 SendHTML500(response);
671 } 636 }
672 finally 637 finally
673 { 638 {
674 // Every month or so this will wrap and give bad numbers, not really a problem 639 // Every month or so this will wrap and give bad numbers, not really a problem
675 // since its just for reporting, tickdiff limit can be adjusted 640 // since its just for reporting
676 int tickdiff = Environment.TickCount - tickstart; 641 int tickdiff = requestEndTick - requestStartTick;
677 if (tickdiff > 3000) 642 if (tickdiff > 3000)
643 {
678 m_log.InfoFormat( 644 m_log.InfoFormat(
679 "[BASE HTTP SERVER]: slow {0} request for {1} from {2} took {3} ms", requestMethod, uriString, request.RemoteIPEndPoint.ToString(), tickdiff); 645 "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} from {4} took {5}ms",
646 requestMethod,
647 uriString,
648 requestHandler != null ? requestHandler.Name : "",
649 requestHandler != null ? requestHandler.Description : "",
650 request.RemoteIPEndPoint.ToString(),
651 tickdiff);
652 }
680 } 653 }
681 } 654 }
682 655
@@ -797,7 +770,7 @@ namespace OpenSim.Framework.Servers.HttpServer
797 /// </summary> 770 /// </summary>
798 /// <param name="request"></param> 771 /// <param name="request"></param>
799 /// <param name="response"></param> 772 /// <param name="response"></param>
800 private void HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response) 773 private byte[] HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response)
801 { 774 {
802 Stream requestStream = request.InputStream; 775 Stream requestStream = request.InputStream;
803 776
@@ -816,8 +789,23 @@ namespace OpenSim.Framework.Servers.HttpServer
816 { 789 {
817 xmlRprcRequest = (XmlRpcRequest) (new XmlRpcRequestDeserializer()).Deserialize(requestBody); 790 xmlRprcRequest = (XmlRpcRequest) (new XmlRpcRequestDeserializer()).Deserialize(requestBody);
818 } 791 }
819 catch (XmlException) 792 catch (XmlException e)
820 { 793 {
794 if (DebugLevel >= 1)
795 {
796 if (DebugLevel >= 2)
797 m_log.Warn(
798 string.Format(
799 "[BASE HTTP SERVER]: Got XMLRPC request with invalid XML from {0}. XML was '{1}'. Sending blank response. Exception ",
800 request.RemoteIPEndPoint, requestBody),
801 e);
802 else
803 {
804 m_log.WarnFormat(
805 "[BASE HTTP SERVER]: Got XMLRPC request with invalid XML from {0}, length {1}. Sending blank response.",
806 request.RemoteIPEndPoint, requestBody.Length);
807 }
808 }
821 } 809 }
822 810
823 if (xmlRprcRequest != null) 811 if (xmlRprcRequest != null)
@@ -887,6 +875,7 @@ namespace OpenSim.Framework.Servers.HttpServer
887 String.Format("Requested method [{0}] not found", methodName)); 875 String.Format("Requested method [{0}] not found", methodName));
888 } 876 }
889 877
878 response.ContentType = "text/xml";
890 responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse); 879 responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse);
891 } 880 }
892 else 881 else
@@ -896,82 +885,25 @@ namespace OpenSim.Framework.Servers.HttpServer
896 response.StatusCode = 404; 885 response.StatusCode = 404;
897 response.StatusDescription = "Not Found"; 886 response.StatusDescription = "Not Found";
898 response.ProtocolVersion = "HTTP/1.0"; 887 response.ProtocolVersion = "HTTP/1.0";
899 byte[] buf = Encoding.UTF8.GetBytes("Not found"); 888 responseString = "Not found";
900 response.KeepAlive = false; 889 response.KeepAlive = false;
901 890
902 m_log.ErrorFormat( 891 m_log.ErrorFormat(
903 "[BASE HTTP SERVER]: Handler not found for http request {0} {1}", 892 "[BASE HTTP SERVER]: Handler not found for http request {0} {1}",
904 request.HttpMethod, request.Url.PathAndQuery); 893 request.HttpMethod, request.Url.PathAndQuery);
905
906 response.SendChunked = false;
907 response.ContentLength64 = buf.Length;
908 response.ContentEncoding = Encoding.UTF8;
909
910 try
911 {
912 response.OutputStream.Write(buf, 0, buf.Length);
913 }
914 catch (Exception ex)
915 {
916 m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
917 }
918 finally
919 {
920 try
921 {
922 response.Send();
923 //response.FreeContext();
924 }
925 catch (SocketException e)
926 {
927 // This has to be here to prevent a Linux/Mono crash
928 m_log.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
929 }
930 catch (IOException e)
931 {
932 m_log.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e.Message);
933 }
934 }
935 return;
936 //responseString = "Error";
937 } 894 }
938 } 895 }
939 896
940 response.ContentType = "text/xml";
941
942 byte[] buffer = Encoding.UTF8.GetBytes(responseString); 897 byte[] buffer = Encoding.UTF8.GetBytes(responseString);
943 898
944 response.SendChunked = false; 899 response.SendChunked = false;
945 response.ContentLength64 = buffer.Length; 900 response.ContentLength64 = buffer.Length;
946 response.ContentEncoding = Encoding.UTF8; 901 response.ContentEncoding = Encoding.UTF8;
947 try 902
948 { 903 return buffer;
949 response.OutputStream.Write(buffer, 0, buffer.Length);
950 }
951 catch (Exception ex)
952 {
953 m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
954 }
955 finally
956 {
957 try
958 {
959 response.Send();
960 //response.FreeContext();
961 }
962 catch (SocketException e)
963 {
964 // This has to be here to prevent a Linux/Mono crash
965 m_log.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
966 }
967 catch (IOException e)
968 {
969 m_log.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e.Message);
970 }
971 }
972 } 904 }
973 905
974 private void HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response) 906 private byte[] HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response)
975 { 907 {
976 //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request"); 908 //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request");
977 Stream requestStream = request.InputStream; 909 Stream requestStream = request.InputStream;
@@ -1057,34 +989,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1057 response.ContentEncoding = Encoding.UTF8; 989 response.ContentEncoding = Encoding.UTF8;
1058 response.KeepAlive = true; 990 response.KeepAlive = true;
1059 991
1060 try 992 return buffer;
1061 {
1062 response.OutputStream.Write(buffer, 0, buffer.Length);
1063 }
1064 catch (Exception ex)
1065 {
1066 m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
1067 }
1068 finally
1069 {
1070 //response.OutputStream.Close();
1071 try
1072 {
1073 response.Send();
1074 response.OutputStream.Flush();
1075 //response.FreeContext();
1076 //response.OutputStream.Close();
1077 }
1078 catch (IOException e)
1079 {
1080 m_log.WarnFormat("[BASE HTTP SERVER]: LLSD IOException {0}.", e);
1081 }
1082 catch (SocketException e)
1083 {
1084 // This has to be here to prevent a Linux/Mono crash
1085 m_log.WarnFormat("[BASE HTTP SERVER]: LLSD issue {0}.\nNOTE: this may be spurious on Linux.", e);
1086 }
1087 }
1088 } 993 }
1089 994
1090 private byte[] BuildLLSDResponse(OSHttpRequest request, OSHttpResponse response, OSD llsdResponse) 995 private byte[] BuildLLSDResponse(OSHttpRequest request, OSHttpResponse response, OSD llsdResponse)
@@ -1334,8 +1239,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1334 catch (SocketException f) 1239 catch (SocketException f)
1335 { 1240 {
1336 // This has to be here to prevent a Linux/Mono crash 1241 // This has to be here to prevent a Linux/Mono crash
1337 m_log.WarnFormat( 1242 m_log.Warn(
1338 "[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", f); 1243 String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", f.Message), f);
1339 } 1244 }
1340 } 1245 }
1341 catch(Exception) 1246 catch(Exception)
@@ -1349,7 +1254,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1349 1254
1350 } 1255 }
1351 1256
1352 public void HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response) 1257 public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
1353 { 1258 {
1354// m_log.DebugFormat( 1259// m_log.DebugFormat(
1355// "[BASE HTTP SERVER]: HandleHTTPRequest for request to {0}, method {1}", 1260// "[BASE HTTP SERVER]: HandleHTTPRequest for request to {0}, method {1}",
@@ -1359,15 +1264,14 @@ namespace OpenSim.Framework.Servers.HttpServer
1359 { 1264 {
1360 case "OPTIONS": 1265 case "OPTIONS":
1361 response.StatusCode = (int)OSHttpStatusCode.SuccessOk; 1266 response.StatusCode = (int)OSHttpStatusCode.SuccessOk;
1362 return; 1267 return null;
1363 1268
1364 default: 1269 default:
1365 HandleContentVerbs(request, response); 1270 return HandleContentVerbs(request, response);
1366 return;
1367 } 1271 }
1368 } 1272 }
1369 1273
1370 private void HandleContentVerbs(OSHttpRequest request, OSHttpResponse response) 1274 private byte[] HandleContentVerbs(OSHttpRequest request, OSHttpResponse response)
1371 { 1275 {
1372// m_log.DebugFormat("[BASE HTTP SERVER]: HandleContentVerbs for request to {0}", request.RawUrl); 1276// m_log.DebugFormat("[BASE HTTP SERVER]: HandleContentVerbs for request to {0}", request.RawUrl);
1373 1277
@@ -1383,6 +1287,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1383 // to display the form, or process it. 1287 // to display the form, or process it.
1384 // a better way would be nifty. 1288 // a better way would be nifty.
1385 1289
1290 byte[] buffer;
1291
1386 Stream requestStream = request.InputStream; 1292 Stream requestStream = request.InputStream;
1387 1293
1388 Encoding encoding = Encoding.UTF8; 1294 Encoding encoding = Encoding.UTF8;
@@ -1443,14 +1349,14 @@ namespace OpenSim.Framework.Servers.HttpServer
1443 if (foundHandler) 1349 if (foundHandler)
1444 { 1350 {
1445 Hashtable responsedata1 = requestprocessor(keysvals); 1351 Hashtable responsedata1 = requestprocessor(keysvals);
1446 DoHTTPGruntWork(responsedata1,response); 1352 buffer = DoHTTPGruntWork(responsedata1,response);
1447 1353
1448 //SendHTML500(response); 1354 //SendHTML500(response);
1449 } 1355 }
1450 else 1356 else
1451 { 1357 {
1452// m_log.Warn("[BASE HTTP SERVER]: Handler Not Found"); 1358// m_log.Warn("[BASE HTTP SERVER]: Handler Not Found");
1453 SendHTML404(response, host); 1359 buffer = SendHTML404(response, host);
1454 } 1360 }
1455 } 1361 }
1456 else 1362 else
@@ -1460,16 +1366,18 @@ namespace OpenSim.Framework.Servers.HttpServer
1460 if (foundHandler) 1366 if (foundHandler)
1461 { 1367 {
1462 Hashtable responsedata2 = requestprocessor(keysvals); 1368 Hashtable responsedata2 = requestprocessor(keysvals);
1463 DoHTTPGruntWork(responsedata2, response); 1369 buffer = DoHTTPGruntWork(responsedata2, response);
1464 1370
1465 //SendHTML500(response); 1371 //SendHTML500(response);
1466 } 1372 }
1467 else 1373 else
1468 { 1374 {
1469// m_log.Warn("[BASE HTTP SERVER]: Handler Not Found2"); 1375// m_log.Warn("[BASE HTTP SERVER]: Handler Not Found2");
1470 SendHTML404(response, host); 1376 buffer = SendHTML404(response, host);
1471 } 1377 }
1472 } 1378 }
1379
1380 return buffer;
1473 } 1381 }
1474 1382
1475 private bool TryGetHTTPHandlerPathBased(string path, out GenericHTTPMethod httpHandler) 1383 private bool TryGetHTTPHandlerPathBased(string path, out GenericHTTPMethod httpHandler)
@@ -1537,7 +1445,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1537 } 1445 }
1538 } 1446 }
1539 1447
1540 internal void DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response) 1448 internal byte[] DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response)
1541 { 1449 {
1542 int responsecode; 1450 int responsecode;
1543 string responseString; 1451 string responseString;
@@ -1631,38 +1539,10 @@ namespace OpenSim.Framework.Servers.HttpServer
1631 response.ContentLength64 = buffer.Length; 1539 response.ContentLength64 = buffer.Length;
1632 response.ContentEncoding = Encoding.UTF8; 1540 response.ContentEncoding = Encoding.UTF8;
1633 1541
1634 try 1542 return buffer;
1635 {
1636 response.OutputStream.Write(buffer, 0, buffer.Length);
1637 }
1638 catch (Exception ex)
1639 {
1640 m_log.Warn("[HTTPD]: Error - " + ex.Message);
1641 }
1642 finally
1643 {
1644 //response.OutputStream.Close();
1645 try
1646 {
1647 response.OutputStream.Flush();
1648 response.Send();
1649
1650 //if (!response.KeepAlive && response.ReuseContext)
1651 // response.FreeContext();
1652 }
1653 catch (SocketException e)
1654 {
1655 // This has to be here to prevent a Linux/Mono crash
1656 m_log.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
1657 }
1658 catch (IOException e)
1659 {
1660 m_log.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e.Message);
1661 }
1662 }
1663 } 1543 }
1664 1544
1665 public void SendHTML404(OSHttpResponse response, string host) 1545 public byte[] SendHTML404(OSHttpResponse response, string host)
1666 { 1546 {
1667 // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s 1547 // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s
1668 response.StatusCode = 404; 1548 response.StatusCode = 404;
@@ -1675,31 +1555,10 @@ namespace OpenSim.Framework.Servers.HttpServer
1675 response.ContentLength64 = buffer.Length; 1555 response.ContentLength64 = buffer.Length;
1676 response.ContentEncoding = Encoding.UTF8; 1556 response.ContentEncoding = Encoding.UTF8;
1677 1557
1678 try 1558 return buffer;
1679 {
1680 response.OutputStream.Write(buffer, 0, buffer.Length);
1681 }
1682 catch (Exception ex)
1683 {
1684 m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
1685 }
1686 finally
1687 {
1688 //response.OutputStream.Close();
1689 try
1690 {
1691 response.Send();
1692 //response.FreeContext();
1693 }
1694 catch (SocketException e)
1695 {
1696 // This has to be here to prevent a Linux/Mono crash
1697 m_log.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
1698 }
1699 }
1700 } 1559 }
1701 1560
1702 public void SendHTML500(OSHttpResponse response) 1561 public byte[] SendHTML500(OSHttpResponse response)
1703 { 1562 {
1704 // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s 1563 // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s
1705 response.StatusCode = (int)OSHttpStatusCode.SuccessOk; 1564 response.StatusCode = (int)OSHttpStatusCode.SuccessOk;
@@ -1711,28 +1570,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1711 response.SendChunked = false; 1570 response.SendChunked = false;
1712 response.ContentLength64 = buffer.Length; 1571 response.ContentLength64 = buffer.Length;
1713 response.ContentEncoding = Encoding.UTF8; 1572 response.ContentEncoding = Encoding.UTF8;
1714 try 1573
1715 { 1574 return buffer;
1716 response.OutputStream.Write(buffer, 0, buffer.Length);
1717 }
1718 catch (Exception ex)
1719 {
1720 m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
1721 }
1722 finally
1723 {
1724 //response.OutputStream.Close();
1725 try
1726 {
1727 response.Send();
1728 //response.FreeContext();
1729 }
1730 catch (SocketException e)
1731 {
1732 // This has to be here to prevent a Linux/Mono crash
1733 m_log.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
1734 }
1735 }
1736 } 1575 }
1737 1576
1738 public void Start() 1577 public void Start()
@@ -1742,6 +1581,9 @@ namespace OpenSim.Framework.Servers.HttpServer
1742 1581
1743 private void StartHTTP() 1582 private void StartHTTP()
1744 { 1583 {
1584 m_log.InfoFormat(
1585 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port);
1586
1745 try 1587 try
1746 { 1588 {
1747 //m_httpListener = new HttpListener(); 1589 //m_httpListener = new HttpListener();
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
index a2135a3..ae7aaf2 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
@@ -45,8 +45,16 @@ namespace OpenSim.Framework.Servers.HttpServer
45 45
46 private readonly string m_path; 46 private readonly string m_path;
47 47
48 protected BaseRequestHandler(string httpMethod, string path) 48 public string Name { get; private set; }
49
50 public string Description { get; private set; }
51
52 protected BaseRequestHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
53
54 protected BaseRequestHandler(string httpMethod, string path, string name, string description)
49 { 55 {
56 Name = name;
57 Description = description;
50 m_httpMethod = httpMethod; 58 m_httpMethod = httpMethod;
51 m_path = path; 59 m_path = path;
52 } 60 }
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
index f1cde74..6342983 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
@@ -34,8 +34,9 @@ namespace OpenSim.Framework.Servers.HttpServer
34 public abstract byte[] Handle(string path, Stream request, 34 public abstract byte[] Handle(string path, Stream request,
35 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse); 35 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse);
36 36
37 protected BaseStreamHandler(string httpMethod, string path) : base(httpMethod, path) 37 protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
38 { 38
39 } 39 protected BaseStreamHandler(string httpMethod, string path, string name, string description)
40 : base(httpMethod, path, name, description) {}
40 } 41 }
41} 42} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
index 1699233..b94bfb4 100644
--- a/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
@@ -36,6 +36,15 @@ namespace OpenSim.Framework.Servers.HttpServer
36 { 36 {
37 private BinaryMethod m_method; 37 private BinaryMethod m_method;
38 38
39 public BinaryStreamHandler(string httpMethod, string path, BinaryMethod binaryMethod)
40 : this(httpMethod, path, binaryMethod, null, null) {}
41
42 public BinaryStreamHandler(string httpMethod, string path, BinaryMethod binaryMethod, string name, string description)
43 : base(httpMethod, path, name, description)
44 {
45 m_method = binaryMethod;
46 }
47
39 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 48 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
40 { 49 {
41 byte[] data = ReadFully(request); 50 byte[] data = ReadFully(request);
@@ -45,12 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer
45 return Encoding.UTF8.GetBytes(responseString); 54 return Encoding.UTF8.GetBytes(responseString);
46 } 55 }
47 56
48 public BinaryStreamHandler(string httpMethod, string path, BinaryMethod binaryMethod)
49 : base(httpMethod, path)
50 {
51 m_method = binaryMethod;
52 }
53
54 private static byte[] ReadFully(Stream stream) 57 private static byte[] ReadFully(Stream stream)
55 { 58 {
56 byte[] buffer = new byte[1024]; 59 byte[] buffer = new byte[1024];
@@ -70,4 +73,4 @@ namespace OpenSim.Framework.Servers.HttpServer
70 } 73 }
71 } 74 }
72 } 75 }
73} 76} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IOSHttpResponse.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IOSHttpResponse.cs
index 33a1663..f61b090 100644
--- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IOSHttpResponse.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IOSHttpResponse.cs
@@ -128,11 +128,5 @@ namespace OpenSim.Framework.Servers.HttpServer
128 /// <param name="value">string containing the header field 128 /// <param name="value">string containing the header field
129 /// value</param> 129 /// value</param>
130 void AddHeader(string key, string value); 130 void AddHeader(string key, string value);
131
132 /// <summary>
133 /// Send the response back to the remote client
134 /// </summary>
135 void Send();
136 } 131 }
137} 132} \ No newline at end of file
138
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
index a449c2d..cb5cce5 100644
--- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
@@ -32,6 +32,25 @@ namespace OpenSim.Framework.Servers.HttpServer
32{ 32{
33 public interface IRequestHandler 33 public interface IRequestHandler
34 { 34 {
35
36 /// <summary>
37 /// Name for this handler.
38 /// </summary>
39 /// <remarks>
40 /// Used for diagnostics. The path doesn't always describe what the handler does. Can be null if none
41 /// specified.
42 /// </remarks>
43 string Name { get; }
44
45 /// <summary>
46 /// Description for this handler.
47 /// </summary>
48 /// <remarks>
49 /// Used for diagnostics. The path doesn't always describe what the handler does. Can be null if none
50 /// specified.
51 /// </remarks>
52 string Description { get; }
53
35 // Return response content type 54 // Return response content type
36 string ContentType { get; } 55 string ContentType { get; }
37 56
@@ -58,4 +77,4 @@ namespace OpenSim.Framework.Servers.HttpServer
58 { 77 {
59 Hashtable Handle(string path, Hashtable request); 78 Hashtable Handle(string path, Hashtable request);
60 } 79 }
61} 80} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs
index fc8daf3..3171759 100644
--- a/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs
@@ -107,7 +107,7 @@ namespace OpenSim.Framework.Servers.HttpServer
107 107
108 public bool IsSecured 108 public bool IsSecured
109 { 109 {
110 get { return _context.Secured; } 110 get { return _context.IsSecured; }
111 } 111 }
112 112
113 public bool KeepAlive 113 public bool KeepAlive
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs
index f9227ac..89fb5d4 100644
--- a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs
@@ -321,13 +321,12 @@ namespace OpenSim.Framework.Servers.HttpServer
321 { 321 {
322 _httpResponse.Body.Flush(); 322 _httpResponse.Body.Flush();
323 _httpResponse.Send(); 323 _httpResponse.Send();
324
325 } 324 }
325
326 public void FreeContext() 326 public void FreeContext()
327 { 327 {
328 if (_httpClientContext != null) 328 if (_httpClientContext != null)
329 _httpClientContext.Close(); 329 _httpClientContext.Close();
330 } 330 }
331
332 } 331 }
333} \ No newline at end of file 332} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpStatusCodes.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpStatusCodes.cs
index 5625227..a736c8b 100644
--- a/OpenSim/Framework/Servers/HttpServer/OSHttpStatusCodes.cs
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpStatusCodes.cs
@@ -28,143 +28,252 @@
28namespace OpenSim.Framework.Servers.HttpServer 28namespace OpenSim.Framework.Servers.HttpServer
29{ 29{
30 /// <summary> 30 /// <summary>
31 /// HTTP status codes (almost) as defined by W3C in 31 /// HTTP status codes (almost) as defined by W3C in http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html and IETF in http://tools.ietf.org/html/rfc6585
32 /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
33 /// </summary> 32 /// </summary>
34 public enum OSHttpStatusCode: int 33 public enum OSHttpStatusCode : int
35 { 34 {
36 // 1xx Informational status codes providing a provisional 35 #region 1xx Informational status codes providing a provisional response.
37 // response. 36
38 // 100 Tells client that to keep on going sending its request 37 /// <summary>
39 InfoContinue = 100, 38 /// 100 Tells client that to keep on going sending its request
40 // 101 Server understands request, proposes to switch to different 39 /// </summary>
41 // application level protocol 40 InfoContinue = 100,
42 InfoSwitchingProtocols = 101, 41
43 42 /// <summary>
44 43 /// 101 Server understands request, proposes to switch to different application level protocol
45 // 2xx Success codes 44 /// </summary>
46 // 200 Request successful 45 InfoSwitchingProtocols = 101,
47 SuccessOk = 200, 46
48 // 201 Request successful, new resource created 47 #endregion
49 SuccessOkCreated = 201, 48
50 // 202 Request accepted, processing still on-going 49 #region 2xx Success codes
51 SuccessOkAccepted = 202, 50
52 // 203 Request successful, meta information not authoritative 51 /// <summary>
53 SuccessOkNonAuthoritativeInformation = 203, 52 /// 200 Request successful
54 // 204 Request successful, nothing to return in the body 53 /// </summary>
55 SuccessOkNoContent = 204, 54 SuccessOk = 200,
56 // 205 Request successful, reset displayed content 55
57 SuccessOkResetContent = 205, 56 /// <summary>
58 // 206 Request successful, partial content returned 57 /// 201 Request successful, new resource created
59 SuccessOkPartialContent = 206, 58 /// </summary>
60 59 SuccessOkCreated = 201,
61 // 3xx Redirect code: user agent needs to go somewhere else 60
62 // 300 Redirect: different presentation forms available, take 61 /// <summary>
63 // a pick 62 /// 202 Request accepted, processing still on-going
64 RedirectMultipleChoices = 300, 63 /// </summary>
65 // 301 Redirect: requested resource has moved and now lives 64 SuccessOkAccepted = 202,
66 // somewhere else 65
67 RedirectMovedPermanently = 301, 66 /// <summary>
68 // 302 Redirect: Resource temporarily somewhere else, location 67 /// 203 Request successful, meta information not authoritative
69 // might change 68 /// </summary>
70 RedirectFound = 302, 69 SuccessOkNonAuthoritativeInformation = 203,
71 // 303 Redirect: See other as result of a POST 70
72 RedirectSeeOther = 303, 71 /// <summary>
73 // 304 Redirect: Resource still the same as before 72 /// 204 Request successful, nothing to return in the body
74 RedirectNotModified = 304, 73 /// </summary>
75 // 305 Redirect: Resource must be accessed via proxy provided 74 SuccessOkNoContent = 204,
76 // in location field 75
77 RedirectUseProxy = 305, 76 /// <summary>
78 // 307 Redirect: Resource temporarily somewhere else, location 77 /// 205 Request successful, reset displayed content
79 // might change 78 /// </summary>
80 RedirectMovedTemporarily = 307, 79 SuccessOkResetContent = 205,
81 80
82 // 4xx Client error: the client borked the request 81 /// <summary>
83 // 400 Client error: bad request, server does not grok what 82 /// 206 Request successful, partial content returned
84 // the client wants 83 /// </summary>
85 ClientErrorBadRequest = 400, 84 SuccessOkPartialContent = 206,
86 // 401 Client error: the client is not authorized, response 85
87 // provides WWW-Authenticate header field with a challenge 86 #endregion
88 ClientErrorUnauthorized = 401, 87
89 // 402 Client error: Payment required (reserved for future use) 88 #region 3xx Redirect code: user agent needs to go somewhere else
90 ClientErrorPaymentRequired = 402, 89
91 // 403 Client error: Server understood request, will not 90 /// <summary>
92 // deliver, do not try again. 91 /// 300 Redirect: different presentation forms available, take a pick
93 ClientErrorForbidden = 403, 92 /// </summary>
94 // 404 Client error: Server cannot find anything matching the 93 RedirectMultipleChoices = 300,
95 // client request. 94
96 ClientErrorNotFound = 404, 95 /// <summary>
97 // 405 Client error: The method specified by the client in the 96 /// 301 Redirect: requested resource has moved and now lives somewhere else
98 // request is not allowed for the resource requested 97 /// </summary>
99 ClientErrorMethodNotAllowed = 405, 98 RedirectMovedPermanently = 301,
100 // 406 Client error: Server cannot generate suitable response 99
101 // for the resource and content characteristics requested by 100 /// <summary>
102 // the client 101 /// 302 Redirect: Resource temporarily somewhere else, location might change
103 ClientErrorNotAcceptable = 406, 102 /// </summary>
104 // 407 Client error: Similar to 401, Server requests that 103 RedirectFound = 302,
105 // client authenticate itself with the proxy first 104
106 ClientErrorProxyAuthRequired = 407, 105 /// <summary>
107 // 408 Client error: Server got impatient with client and 106 /// 303 Redirect: See other as result of a POST
108 // decided to give up waiting for the client's request to 107 /// </summary>
109 // arrive 108 RedirectSeeOther = 303,
110 ClientErrorRequestTimeout = 408, 109
111 // 409 Client error: Server could not fulfill the request for 110 /// <summary>
112 // a resource as there is a conflict with the current state of 111 /// 304 Redirect: Resource still the same as before
113 // the resource but thinks client can do something about this 112 /// </summary>
114 ClientErrorConflict = 409, 113 RedirectNotModified = 304,
115 // 410 Client error: The resource has moved somewhere else, 114
116 // but server has no clue where. 115 /// <summary>
117 ClientErrorGone = 410, 116 /// 305 Redirect: Resource must be accessed via proxy provided in location field
118 // 411 Client error: The server is picky again and insists on 117 /// </summary>
119 // having a content-length header field in the request 118 RedirectUseProxy = 305,
120 ClientErrorLengthRequired = 411, 119
121 // 412 Client error: one or more preconditions supplied in the 120 /// <summary>
122 // client's request is false 121 /// 307 Redirect: Resource temporarily somewhere else, location might change
123 ClientErrorPreconditionFailed = 412, 122 /// </summary>
124 // 413 Client error: For fear of reflux, the server refuses to 123 RedirectMovedTemporarily = 307,
125 // swallow that much data. 124
126 ClientErrorRequestEntityToLarge = 413, 125 #endregion
127 // 414 Client error: The server considers the Request-URI to 126
128 // be indecently long and refuses to even look at it. 127 #region 4xx Client error: the client borked the request
129 ClientErrorRequestURITooLong = 414, 128
130 // 415 Client error: The server has no clue about the media 129 /// <summary>
131 // type requested by the client (contrary to popular belief it 130 /// 400 Client error: bad request, server does not grok what the client wants
132 // is not a warez server) 131 /// </summary>
133 ClientErrorUnsupportedMediaType = 415, 132 ClientErrorBadRequest = 400,
134 // 416 Client error: The requested range cannot be delivered 133
135 // by the server. 134 /// <summary>
135 /// 401 Client error: the client is not authorized, response provides WWW-Authenticate header field with a challenge
136 /// </summary>
137 ClientErrorUnauthorized = 401,
138
139 /// <summary>
140 /// 402 Client error: Payment required (reserved for future use)
141 /// </summary>
142 ClientErrorPaymentRequired = 402,
143
144 /// <summary>
145 /// 403 Client error: Server understood request, will not deliver, do not try again.
146 ClientErrorForbidden = 403,
147
148 /// <summary>
149 /// 404 Client error: Server cannot find anything matching the client request.
150 /// </summary>
151 ClientErrorNotFound = 404,
152
153 /// <summary>
154 /// 405 Client error: The method specified by the client in the request is not allowed for the resource requested
155 /// </summary>
156 ClientErrorMethodNotAllowed = 405,
157
158 /// <summary>
159 /// 406 Client error: Server cannot generate suitable response for the resource and content characteristics requested by the client
160 /// </summary>
161 ClientErrorNotAcceptable = 406,
162
163 /// <summary>
164 /// 407 Client error: Similar to 401, Server requests that client authenticate itself with the proxy first
165 /// </summary>
166 ClientErrorProxyAuthRequired = 407,
167
168 /// <summary>
169 /// 408 Client error: Server got impatient with client and decided to give up waiting for the client's request to arrive
170 /// </summary>
171 ClientErrorRequestTimeout = 408,
172
173 /// <summary>
174 /// 409 Client error: Server could not fulfill the request for a resource as there is a conflict with the current state of the resource but thinks client can do something about this
175 /// </summary>
176 ClientErrorConflict = 409,
177
178 /// <summary>
179 /// 410 Client error: The resource has moved somewhere else, but server has no clue where.
180 /// </summary>
181 ClientErrorGone = 410,
182
183 /// <summary>
184 /// 411 Client error: The server is picky again and insists on having a content-length header field in the request
185 /// </summary>
186 ClientErrorLengthRequired = 411,
187
188 /// <summary>
189 /// 412 Client error: one or more preconditions supplied in the client's request is false
190 /// </summary>
191 ClientErrorPreconditionFailed = 412,
192
193 /// <summary>
194 /// 413 Client error: For fear of reflux, the server refuses to swallow that much data.
195 /// </summary>
196 ClientErrorRequestEntityToLarge = 413,
197
198 /// <summary>
199 /// 414 Client error: The server considers the Request-URI to be indecently long and refuses to even look at it.
200 /// </summary>
201 ClientErrorRequestURITooLong = 414,
202
203 /// <summary>
204 /// 415 Client error: The server has no clue about the media type requested by the client (contrary to popular belief it is not a warez server)
205 /// </summary>
206 ClientErrorUnsupportedMediaType = 415,
207
208 /// <summary>
209 /// 416 Client error: The requested range cannot be delivered by the server.
210 /// </summary>
136 ClientErrorRequestRangeNotSatisfiable = 416, 211 ClientErrorRequestRangeNotSatisfiable = 416,
137 // 417 Client error: The expectations of the client as 212
138 // expressed in one or more Expect header fields cannot be met 213 /// <summary>
139 // by the server, the server is awfully sorry about this. 214 /// 417 Client error: The expectations of the client as expressed in one or more Expect header fields cannot be met by the server, the server is awfully sorry about this.
140 ClientErrorExpectationFailed = 417, 215 /// </summary>
141 // 499 Client error: Wildcard error. 216 ClientErrorExpectationFailed = 417,
142 ClientErrorJoker = 499, 217
143 218 /// <summary>
144 // 5xx Server errors (rare) 219 /// 428 Client error :The 428 status code indicates that the origin server requires the request to be conditional.
145 // 500 Server error: something really strange and unexpected 220 /// </summary>
146 // happened 221 ClientErrorPreconditionRequired = 428,
147 ServerErrorInternalError = 500, 222
148 // 501 Server error: The server does not do the functionality 223 /// <summary>
149 // required to carry out the client request. not at 224 /// 429 Client error: The 429 status code indicates that the user has sent too many requests in a given amount of time ("rate limiting").
150 // all. certainly not before breakfast. but also not after 225 /// </summary>
151 // breakfast. 226 ClientErrorTooManyRequests = 429,
152 ServerErrorNotImplemented = 501, 227
153 // 502 Server error: While acting as a proxy or a gateway, the 228 /// <summary>
154 // server got ditched by the upstream server and as a 229 /// 431 Client error: The 431 status code indicates that the server is unwilling to process the request because its header fields are too large. The request MAY be resubmitted after reducing the size of the request header fields.
155 // consequence regretfully cannot fulfill the client's request 230 /// </summary>
156 ServerErrorBadGateway = 502, 231 ClientErrorRequestHeaderFieldsTooLarge = 431,
157 // 503 Server error: Due to unforseen circumstances the server 232
158 // cannot currently deliver the service requested. Retry-After 233 /// <summary>
159 // header might indicate when to try again. 234 /// 499 Client error: Wildcard error.
160 ServerErrorServiceUnavailable = 503, 235 /// </summary>
161 // 504 Server error: The server blames the upstream server 236 ClientErrorJoker = 499,
162 // for not being able to deliver the service requested and 237
163 // claims that the upstream server is too slow delivering the 238 #endregion
164 // goods. 239
165 ServerErrorGatewayTimeout = 504, 240 #region 5xx Server errors (rare)
166 // 505 Server error: The server does not support the HTTP 241
167 // version conveyed in the client's request. 242 /// <summary>
168 ServerErrorHttpVersionNotSupported = 505, 243 /// 500 Server error: something really strange and unexpected happened
244 /// </summary>
245 ServerErrorInternalError = 500,
246
247 /// <summary>
248 /// 501 Server error: The server does not do the functionality required to carry out the client request. not at all. certainly not before breakfast. but also not after breakfast.
249 /// </summary>
250 ServerErrorNotImplemented = 501,
251
252 /// <summary>
253 /// 502 Server error: While acting as a proxy or a gateway, the server got ditched by the upstream server and as a consequence regretfully cannot fulfill the client's request
254 /// </summary>
255 ServerErrorBadGateway = 502,
256
257 /// <summary>
258 /// 503 Server error: Due to unforseen circumstances the server cannot currently deliver the service requested. Retry-After header might indicate when to try again.
259 /// </summary>
260 ServerErrorServiceUnavailable = 503,
261
262 /// <summary>
263 /// 504 Server error: The server blames the upstream server for not being able to deliver the service requested and claims that the upstream server is too slow delivering the goods.
264 /// </summary>
265 ServerErrorGatewayTimeout = 504,
266
267 /// <summary>
268 /// 505 Server error: The server does not support the HTTP version conveyed in the client's request.
269 /// </summary>
270 ServerErrorHttpVersionNotSupported = 505,
271
272 /// <summary>
273 /// 511 Server error: The 511 status code indicates that the client needs to authenticate to gain network access.
274 /// </summary>
275 ServerErrorNetworkAuthenticationRequired = 511,
276
277 #endregion
169 } 278 }
170} 279}
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
index 7c92a50..bb43cd2 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using OpenMetaverse; 30using OpenMetaverse;
31
31namespace OpenSim.Framework.Servers.HttpServer 32namespace OpenSim.Framework.Servers.HttpServer
32{ 33{
33 public delegate void RequestMethod(UUID requestID, Hashtable request); 34 public delegate void RequestMethod(UUID requestID, Hashtable request);
@@ -53,7 +54,10 @@ namespace OpenSim.Framework.Servers.HttpServer
53 LslHttp = 1 54 LslHttp = 1
54 } 55 }
55 56
56 public PollServiceEventArgs(RequestMethod pRequest, HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents, UUID pId, int pTimeOutms) 57 public PollServiceEventArgs(
58 RequestMethod pRequest,
59 HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,
60 UUID pId, int pTimeOutms)
57 { 61 {
58 Request = pRequest; 62 Request = pRequest;
59 HasEvents = pHasEvents; 63 HasEvents = pHasEvents;
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
index 553a7eb..723530a 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
@@ -31,7 +31,6 @@ using OpenMetaverse;
31 31
32namespace OpenSim.Framework.Servers.HttpServer 32namespace OpenSim.Framework.Servers.HttpServer
33{ 33{
34
35 public class PollServiceHttpRequest 34 public class PollServiceHttpRequest
36 { 35 {
37 public readonly PollServiceEventArgs PollServiceArgs; 36 public readonly PollServiceEventArgs PollServiceArgs;
@@ -39,7 +38,9 @@ namespace OpenSim.Framework.Servers.HttpServer
39 public readonly IHttpRequest Request; 38 public readonly IHttpRequest Request;
40 public readonly int RequestTime; 39 public readonly int RequestTime;
41 public readonly UUID RequestID; 40 public readonly UUID RequestID;
42 public PollServiceHttpRequest(PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest) 41
42 public PollServiceHttpRequest(
43 PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest)
43 { 44 {
44 PollServiceArgs = pPollServiceArgs; 45 PollServiceArgs = pPollServiceArgs;
45 HttpContext = pHttpContext; 46 HttpContext = pHttpContext;
@@ -48,4 +49,4 @@ namespace OpenSim.Framework.Servers.HttpServer
48 RequestID = UUID.Random(); 49 RequestID = UUID.Random();
49 } 50 }
50 } 51 }
51} 52} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index 6f87c85..3a14b6f 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -70,6 +70,7 @@ namespace OpenSim.Framework.Servers.HttpServer
70 ThreadPriority.Normal, 70 ThreadPriority.Normal,
71 false, 71 false,
72 true, 72 true,
73 null,
73 int.MaxValue); 74 int.MaxValue);
74 } 75 }
75 76
@@ -79,6 +80,7 @@ namespace OpenSim.Framework.Servers.HttpServer
79 ThreadPriority.Normal, 80 ThreadPriority.Normal,
80 false, 81 false,
81 true, 82 true,
83 null,
82 1000 * 60 * 10); 84 1000 * 60 * 10);
83 } 85 }
84 86
@@ -144,9 +146,8 @@ namespace OpenSim.Framework.Servers.HttpServer
144 foreach (object o in m_requests) 146 foreach (object o in m_requests)
145 { 147 {
146 PollServiceHttpRequest req = (PollServiceHttpRequest) o; 148 PollServiceHttpRequest req = (PollServiceHttpRequest) o;
147 m_server.DoHTTPGruntWork( 149 PollServiceWorkerThread.DoHTTPGruntWork(
148 req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id), 150 m_server, req, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
149 new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext));
150 } 151 }
151 152
152 m_requests.Clear(); 153 m_requests.Clear();
@@ -155,6 +156,7 @@ namespace OpenSim.Framework.Servers.HttpServer
155 { 156 {
156 t.Abort(); 157 t.Abort();
157 } 158 }
159
158 m_running = false; 160 m_running = false;
159 } 161 }
160 } 162 }
@@ -184,7 +186,7 @@ namespace OpenSim.Framework.Servers.HttpServer
184 private bool m_running = true; 186 private bool m_running = true;
185 private int slowCount = 0; 187 private int slowCount = 0;
186 188
187// private int m_timeout = 1000; // increase timeout 250; now use the event one 189 // private int m_timeout = 250; // increase timeout 250; now use the event one
188 190
189 public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout) 191 public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout)
190 { 192 {
@@ -202,6 +204,7 @@ namespace OpenSim.Framework.Servers.HttpServer
202 ThreadPriority.Normal, 204 ThreadPriority.Normal,
203 false, 205 false,
204 true, 206 true,
207 null,
205 int.MaxValue); 208 int.MaxValue);
206 } 209 }
207 210
@@ -211,6 +214,7 @@ namespace OpenSim.Framework.Servers.HttpServer
211 ThreadPriority.Normal, 214 ThreadPriority.Normal,
212 false, 215 false,
213 true, 216 true,
217 null,
214 1000 * 60 * 10); 218 1000 * 60 * 10);
215 } 219 }
216 220
@@ -368,8 +372,7 @@ namespace OpenSim.Framework.Servers.HttpServer
368 } 372 }
369 else 373 else
370 { 374 {
371// if ((Environment.TickCount - req.RequestTime) > m_timeout) 375 // if ((Environment.TickCount - req.RequestTime) > m_timeout)
372
373 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) 376 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
374 { 377 {
375 m_server.DoHTTPGruntWork(req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id), 378 m_server.DoHTTPGruntWork(req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id),
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs
index 7cd27e5..1e3fbf0 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs
@@ -94,8 +94,7 @@ namespace OpenSim.Framework.Servers.HttpServer
94 try 94 try
95 { 95 {
96 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id, str.ReadToEnd()); 96 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id, str.ReadToEnd());
97 m_server.DoHTTPGruntWork(responsedata, 97 DoHTTPGruntWork(m_server, req, responsedata);
98 new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request),req.HttpContext));
99 } 98 }
100 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream 99 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
101 { 100 {
@@ -106,8 +105,10 @@ namespace OpenSim.Framework.Servers.HttpServer
106 { 105 {
107 if ((Environment.TickCount - req.RequestTime) > m_timeout) 106 if ((Environment.TickCount - req.RequestTime) > m_timeout)
108 { 107 {
109 m_server.DoHTTPGruntWork(req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id), 108 DoHTTPGruntWork(
110 new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request),req.HttpContext)); 109 m_server,
110 req,
111 req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
111 } 112 }
112 else 113 else
113 { 114 {
@@ -128,6 +129,46 @@ namespace OpenSim.Framework.Servers.HttpServer
128 { 129 {
129 m_request.Enqueue(pPollServiceHttpRequest); 130 m_request.Enqueue(pPollServiceHttpRequest);
130 } 131 }
132
133 /// <summary>
134 /// FIXME: This should be part of BaseHttpServer
135 /// </summary>
136 internal static void DoHTTPGruntWork(BaseHttpServer server, PollServiceHttpRequest req, Hashtable responsedata)
137 {
138 OSHttpResponse response
139 = new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext);
140
141 byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
142
143 response.SendChunked = false;
144 response.ContentLength64 = buffer.Length;
145 response.ContentEncoding = Encoding.UTF8;
146
147 try
148 {
149 response.OutputStream.Write(buffer, 0, buffer.Length);
150 }
151 catch (Exception ex)
152 {
153 m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
154 }
155 finally
156 {
157 //response.OutputStream.Close();
158 try
159 {
160 response.OutputStream.Flush();
161 response.Send();
162
163 //if (!response.KeepAlive && response.ReuseContext)
164 // response.FreeContext();
165 }
166 catch (Exception e)
167 {
168 m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
169 }
170 }
171 }
131 } 172 }
132} 173}
133*/ \ No newline at end of file 174*/ \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
index a467a83..07082a8 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
@@ -39,7 +39,11 @@ namespace OpenSim.Framework.Servers.HttpServer
39 private RestDeserialiseMethod<TRequest, TResponse> m_method; 39 private RestDeserialiseMethod<TRequest, TResponse> m_method;
40 40
41 public RestDeserialiseHandler(string httpMethod, string path, RestDeserialiseMethod<TRequest, TResponse> method) 41 public RestDeserialiseHandler(string httpMethod, string path, RestDeserialiseMethod<TRequest, TResponse> method)
42 : base(httpMethod, path) 42 : this(httpMethod, path, method, null, null) {}
43
44 public RestDeserialiseHandler(
45 string httpMethod, string path, RestDeserialiseMethod<TRequest, TResponse> method, string name, string description)
46 : base(httpMethod, path, name, description)
43 { 47 {
44 m_method = method; 48 m_method = method;
45 } 49 }
diff --git a/OpenSim/Framework/Servers/HttpServer/RestHTTPHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestHTTPHandler.cs
index 1f23cac..7f89839 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestHTTPHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestHTTPHandler.cs
@@ -38,19 +38,25 @@ namespace OpenSim.Framework.Servers.HttpServer
38 get { return m_dhttpMethod; } 38 get { return m_dhttpMethod; }
39 } 39 }
40 40
41 public override Hashtable Handle(string path, Hashtable request) 41 public RestHTTPHandler(string httpMethod, string path, GenericHTTPMethod dhttpMethod)
42 : base(httpMethod, path)
42 { 43 {
44 m_dhttpMethod = dhttpMethod;
45 }
46
47 public RestHTTPHandler(
48 string httpMethod, string path, GenericHTTPMethod dhttpMethod, string name, string description)
49 : base(httpMethod, path, name, description)
50 {
51 m_dhttpMethod = dhttpMethod;
52 }
43 53
54 public override Hashtable Handle(string path, Hashtable request)
55 {
44 string param = GetParam(path); 56 string param = GetParam(path);
45 request.Add("param", param); 57 request.Add("param", param);
46 request.Add("path", path); 58 request.Add("path", path);
47 return m_dhttpMethod(request); 59 return m_dhttpMethod(request);
48 } 60 }
49
50 public RestHTTPHandler(string httpMethod, string path, GenericHTTPMethod dhttpMethod)
51 : base(httpMethod, path)
52 {
53 m_dhttpMethod = dhttpMethod;
54 }
55 } 61 }
56} 62}
diff --git a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
index d2c4002..1f17fee 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
@@ -39,6 +39,15 @@ namespace OpenSim.Framework.Servers.HttpServer
39 get { return m_restMethod; } 39 get { return m_restMethod; }
40 } 40 }
41 41
42 public RestStreamHandler(string httpMethod, string path, RestMethod restMethod)
43 : this(httpMethod, path, restMethod, null, null) {}
44
45 public RestStreamHandler(string httpMethod, string path, RestMethod restMethod, string name, string description)
46 : base(httpMethod, path, name, description)
47 {
48 m_restMethod = restMethod;
49 }
50
42 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 51 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
43 { 52 {
44 Encoding encoding = Encoding.UTF8; 53 Encoding encoding = Encoding.UTF8;
@@ -52,10 +61,5 @@ namespace OpenSim.Framework.Servers.HttpServer
52 61
53 return Encoding.UTF8.GetBytes(responseString); 62 return Encoding.UTF8.GetBytes(responseString);
54 } 63 }
55
56 public RestStreamHandler(string httpMethod, string path, RestMethod restMethod) : base(httpMethod, path)
57 {
58 m_restMethod = restMethod;
59 }
60 } 64 }
61} 65}
diff --git a/OpenSim/Framework/Servers/MainServer.cs b/OpenSim/Framework/Servers/MainServer.cs
index b8ab8d9..8dc0e3a 100644
--- a/OpenSim/Framework/Servers/MainServer.cs
+++ b/OpenSim/Framework/Servers/MainServer.cs
@@ -25,57 +25,209 @@
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;
28using System.Collections.Generic; 29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
30using System.Net; 31using System.Net;
31using log4net; 32using log4net;
33using OpenSim.Framework;
34using OpenSim.Framework.Console;
32using OpenSim.Framework.Servers.HttpServer; 35using OpenSim.Framework.Servers.HttpServer;
33 36
34namespace OpenSim.Framework.Servers 37namespace OpenSim.Framework.Servers
35{ 38{
36 public class MainServer 39 public class MainServer
37 { 40 {
38 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 41// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39 42
40 private static BaseHttpServer instance = null; 43 private static BaseHttpServer instance = null;
41 private static Dictionary<uint, BaseHttpServer> m_Servers = 44 private static Dictionary<uint, BaseHttpServer> m_Servers = new Dictionary<uint, BaseHttpServer>();
42 new Dictionary<uint, BaseHttpServer>();
43 45
46 /// <summary>
47 /// Control the printing of certain debug messages.
48 /// </summary>
49 /// <remarks>
50 /// If DebugLevel >= 1, then short warnings are logged when receiving bad input data.
51 /// If DebugLevel >= 2, then long warnings are logged when receiving bad input data.
52 /// If DebugLevel >= 3, then short notices about all incoming non-poll HTTP requests are logged.
53 /// </remarks>
54 public static int DebugLevel
55 {
56 get { return s_debugLevel; }
57 set
58 {
59 s_debugLevel = value;
60
61 lock (m_Servers)
62 foreach (BaseHttpServer server in m_Servers.Values)
63 server.DebugLevel = s_debugLevel;
64 }
65 }
66
67 private static int s_debugLevel;
68
69 /// <summary>
70 /// Set the main HTTP server instance.
71 /// </summary>
72 /// <remarks>
73 /// This will be used to register all handlers that listen to the default port.
74 /// </remarks>
75 /// <exception cref='Exception'>
76 /// Thrown if the HTTP server has not already been registered via AddHttpServer()
77 /// </exception>
44 public static BaseHttpServer Instance 78 public static BaseHttpServer Instance
45 { 79 {
46 get { return instance; } 80 get { return instance; }
47 set { instance = value; } 81
82 set
83 {
84 lock (m_Servers)
85 if (!m_Servers.ContainsValue(value))
86 throw new Exception("HTTP server must already have been registered to be set as the main instance");
87
88 instance = value;
89 }
48 } 90 }
49 91
50 public static IHttpServer GetHttpServer(uint port) 92 /// <summary>
93 /// Get all the registered servers.
94 /// </summary>
95 /// <remarks>
96 /// Returns a copy of the dictionary so this can be iterated through without locking.
97 /// </remarks>
98 /// <value></value>
99 public static Dictionary<uint, BaseHttpServer> Servers
100 {
101 get { return new Dictionary<uint, BaseHttpServer>(m_Servers); }
102 }
103
104
105 public static void RegisterHttpConsoleCommands(ICommandConsole console)
106 {
107 console.Commands.AddCommand(
108 "Debug", false, "debug http", "debug http [<level>]",
109 "Turn on inbound non-poll http request debugging.",
110 "If level <= 0, then no extra logging is done.\n"
111 + "If level >= 1, then short warnings are logged when receiving bad input data.\n"
112 + "If level >= 2, then long warnings are logged when receiving bad input data.\n"
113 + "If level >= 3, then short notices about all incoming non-poll HTTP requests are logged.\n"
114 + "If no level is specified then the current level is returned.",
115 HandleDebugHttpCommand);
116 }
117
118 /// <summary>
119 /// Turn on some debugging values for OpenSim.
120 /// </summary>
121 /// <param name="args"></param>
122 private static void HandleDebugHttpCommand(string module, string[] args)
51 { 123 {
52 return GetHttpServer(port,null); 124 if (args.Length == 3)
125 {
126 int newDebug;
127 if (int.TryParse(args[2], out newDebug))
128 {
129 MainServer.DebugLevel = newDebug;
130 MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug);
131 }
132 }
133 else if (args.Length == 2)
134 {
135 MainConsole.Instance.OutputFormat("Current debug http level is {0}", MainServer.DebugLevel);
136 }
137 else
138 {
139 MainConsole.Instance.Output("Usage: debug http 0..3");
140 }
53 } 141 }
54 142
143 /// <summary>
144 /// Register an already started HTTP server to the collection of known servers.
145 /// </summary>
146 /// <param name='server'></param>
55 public static void AddHttpServer(BaseHttpServer server) 147 public static void AddHttpServer(BaseHttpServer server)
56 { 148 {
57 m_Servers.Add(server.Port, server); 149 lock (m_Servers)
150 {
151 if (m_Servers.ContainsKey(server.Port))
152 throw new Exception(string.Format("HTTP server for port {0} already exists.", server.Port));
153
154 m_Servers.Add(server.Port, server);
155 }
156 }
157
158 /// <summary>
159 /// Removes the http server listening on the given port.
160 /// </summary>
161 /// <remarks>
162 /// It is the responsibility of the caller to do clean up.
163 /// </remarks>
164 /// <param name='port'></param>
165 /// <returns></returns>
166 public static bool RemoveHttpServer(uint port)
167 {
168 lock (m_Servers)
169 return m_Servers.Remove(port);
170 }
171
172 /// <summary>
173 /// Does this collection of servers contain one with the given port?
174 /// </summary>
175 /// <remarks>
176 /// Unlike GetHttpServer, this will not instantiate a server if one does not exist on that port.
177 /// </remarks>
178 /// <param name='port'></param>
179 /// <returns>true if a server with the given port is registered, false otherwise.</returns>
180 public static bool ContainsHttpServer(uint port)
181 {
182 lock (m_Servers)
183 return m_Servers.ContainsKey(port);
58 } 184 }
59 185
186 /// <summary>
187 /// Get the default http server or an http server for a specific port.
188 /// </summary>
189 /// <remarks>
190 /// If the requested HTTP server doesn't already exist then a new one is instantiated and started.
191 /// </remarks>
192 /// <returns></returns>
193 /// <param name='port'>If 0 then the default HTTP server is returned.</param>
194 public static IHttpServer GetHttpServer(uint port)
195 {
196 return GetHttpServer(port, null);
197 }
198
199 /// <summary>
200 /// Get the default http server, an http server for a specific port
201 /// and/or an http server bound to a specific address
202 /// </summary>
203 /// <remarks>
204 /// If the requested HTTP server doesn't already exist then a new one is instantiated and started.
205 /// </remarks>
206 /// <returns></returns>
207 /// <param name='port'>If 0 then the default HTTP server is returned.</param>
208 /// <param name='ipaddr'>A specific IP address to bind to. If null then the default IP address is used.</param>
60 public static IHttpServer GetHttpServer(uint port, IPAddress ipaddr) 209 public static IHttpServer GetHttpServer(uint port, IPAddress ipaddr)
61 { 210 {
62 if (port == 0) 211 if (port == 0)
63 return Instance; 212 return Instance;
213
64 if (instance != null && port == Instance.Port) 214 if (instance != null && port == Instance.Port)
65 return Instance; 215 return Instance;
66 216
67 if (m_Servers.ContainsKey(port)) 217 lock (m_Servers)
68 return m_Servers[port]; 218 {
219 if (m_Servers.ContainsKey(port))
220 return m_Servers[port];
69 221
70 m_Servers[port] = new BaseHttpServer(port); 222 m_Servers[port] = new BaseHttpServer(port);
71 223
72 if (ipaddr != null) 224 if (ipaddr != null)
73 m_Servers[port].ListenIPAddress = ipaddr; 225 m_Servers[port].ListenIPAddress = ipaddr;
74 226
75 m_log.InfoFormat("[MAIN HTTP SERVER]: Starting main http server on port {0}", port); 227 m_Servers[port].Start();
76 m_Servers[port].Start();
77 228
78 return m_Servers[port]; 229 return m_Servers[port];
230 }
79 } 231 }
80 } 232 }
81} 233} \ No newline at end of file
diff --git a/OpenSim/Framework/Statistics/StatsManager.cs b/OpenSim/Framework/Statistics/StatsManager.cs
index 43159ef..436ce2f 100644
--- a/OpenSim/Framework/Statistics/StatsManager.cs
+++ b/OpenSim/Framework/Statistics/StatsManager.cs
@@ -34,14 +34,12 @@ namespace OpenSim.Framework.Statistics
34 { 34 {
35 private static AssetStatsCollector assetStats; 35 private static AssetStatsCollector assetStats;
36 private static UserStatsCollector userStats; 36 private static UserStatsCollector userStats;
37 private static SimExtraStatsCollector simExtraStats; 37 private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
38 38
39 public static AssetStatsCollector AssetStats { get { return assetStats; } } 39 public static AssetStatsCollector AssetStats { get { return assetStats; } }
40 public static UserStatsCollector UserStats { get { return userStats; } } 40 public static UserStatsCollector UserStats { get { return userStats; } }
41 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } 41 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
42 42
43 private StatsManager() {}
44
45 /// <summary> 43 /// <summary>
46 /// Start collecting statistics related to assets. 44 /// Start collecting statistics related to assets.
47 /// Should only be called once. 45 /// Should only be called once.
@@ -63,16 +61,5 @@ namespace OpenSim.Framework.Statistics
63 61
64 return userStats; 62 return userStats;
65 } 63 }
66
67 /// <summary>
68 /// Start collecting extra sim statistics apart from those collected for the client.
69 /// Should only be called once.
70 /// </summary>
71 public static SimExtraStatsCollector StartCollectingSimExtraStats()
72 {
73 simExtraStats = new SimExtraStatsCollector();
74
75 return simExtraStats;
76 }
77 } 64 }
78} 65} \ No newline at end of file
diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs
index 814758a..4d07746 100644
--- a/OpenSim/Framework/TaskInventoryDictionary.cs
+++ b/OpenSim/Framework/TaskInventoryDictionary.cs
@@ -52,10 +52,10 @@ namespace OpenSim.Framework
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 53
54 private Thread LockedByThread; 54 private Thread LockedByThread;
55 private string WriterStack; 55// private string WriterStack;
56 56
57 private Dictionary<Thread, string> ReadLockers = 57// private Dictionary<Thread, string> ReadLockers =
58 new Dictionary<Thread, string>(); 58// new Dictionary<Thread, string>();
59 59
60 /// <value> 60 /// <value>
61 /// An advanced lock for inventory data 61 /// An advanced lock for inventory data
@@ -98,14 +98,25 @@ namespace OpenSim.Framework
98 m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); 98 m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
99 try 99 try
100 { 100 {
101 StackTrace stackTrace = new StackTrace(); // get call stack 101 // That call stack is useful for end users only. RealProgrammers need a full dump. Commented.
102 StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) 102 // StackTrace stackTrace = new StackTrace(); // get call stack
103 // StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
104 //
105 // // write call stack method names
106 // foreach (StackFrame stackFrame in stackFrames)
107 // {
108 // m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name)); // write method name
109 // }
103 110
104 // write call stack method names 111 // The below is far more useful
105 foreach (StackFrame stackFrame in stackFrames) 112// System.Console.WriteLine("------------------------------------------");
106 { 113// System.Console.WriteLine("My call stack:\n" + Environment.StackTrace);
107 m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name)); // write method name 114// System.Console.WriteLine("------------------------------------------");
108 } 115// foreach (KeyValuePair<Thread, string> kvp in ReadLockers)
116// {
117// System.Console.WriteLine("Locker name {0} call stack:\n" + kvp.Value, kvp.Key.Name);
118// System.Console.WriteLine("------------------------------------------");
119// }
109 } 120 }
110 catch 121 catch
111 {} 122 {}
@@ -114,6 +125,16 @@ namespace OpenSim.Framework
114 if (m_itemLock.RecursiveWriteCount > 0) 125 if (m_itemLock.RecursiveWriteCount > 0)
115 { 126 {
116 m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); 127 m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed.");
128// try
129// {
130// System.Console.WriteLine("------------------------------------------");
131// System.Console.WriteLine("My call stack:\n" + Environment.StackTrace);
132// System.Console.WriteLine("------------------------------------------");
133// System.Console.WriteLine("Locker's call stack:\n" + WriterStack);
134// System.Console.WriteLine("------------------------------------------");
135// }
136// catch
137// {}
117 m_itemLock.ExitWriteLock(); 138 m_itemLock.ExitWriteLock();
118 } 139 }
119 140
@@ -123,15 +144,16 @@ namespace OpenSim.Framework
123 if (m_itemLock.IsWriteLockHeld) 144 if (m_itemLock.IsWriteLockHeld)
124 { 145 {
125 m_itemLock = new System.Threading.ReaderWriterLockSlim(); 146 m_itemLock = new System.Threading.ReaderWriterLockSlim();
126 System.Console.WriteLine("------------------------------------------"); 147// System.Console.WriteLine("------------------------------------------");
127 System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); 148// System.Console.WriteLine("My call stack:\n" + Environment.StackTrace);
128 System.Console.WriteLine("------------------------------------------"); 149// System.Console.WriteLine("------------------------------------------");
129 System.Console.WriteLine("Locker's call stack:\n" + WriterStack); 150// System.Console.WriteLine("Locker's call stack:\n" + WriterStack);
130 System.Console.WriteLine("------------------------------------------"); 151// System.Console.WriteLine("------------------------------------------");
131 LockedByThread = null; 152// LockedByThread = null;
132 ReadLockers.Clear(); 153// ReadLockers.Clear();
133 } 154 }
134 } 155 }
156// ReadLockers[Thread.CurrentThread] = Environment.StackTrace;
135 } 157 }
136 else 158 else
137 { 159 {
@@ -139,6 +161,8 @@ namespace OpenSim.Framework
139 { 161 {
140 m_itemLock.ExitReadLock(); 162 m_itemLock.ExitReadLock();
141 } 163 }
164// if (m_itemLock.RecursiveReadCount == 0)
165// ReadLockers.Remove(Thread.CurrentThread);
142 } 166 }
143 } 167 }
144 168
@@ -158,6 +182,7 @@ namespace OpenSim.Framework
158 if (m_itemLock.RecursiveWriteCount > 0) 182 if (m_itemLock.RecursiveWriteCount > 0)
159 { 183 {
160 m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); 184 m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed.");
185
161 m_itemLock.ExitWriteLock(); 186 m_itemLock.ExitWriteLock();
162 } 187 }
163 while (!m_itemLock.TryEnterWriteLock(60000)) 188 while (!m_itemLock.TryEnterWriteLock(60000))
@@ -165,30 +190,30 @@ namespace OpenSim.Framework
165 if (m_itemLock.IsWriteLockHeld) 190 if (m_itemLock.IsWriteLockHeld)
166 { 191 {
167 m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); 192 m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
168 System.Console.WriteLine("------------------------------------------"); 193// System.Console.WriteLine("------------------------------------------");
169 System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); 194// System.Console.WriteLine("My call stack:\n" + Environment.StackTrace);
170 System.Console.WriteLine("------------------------------------------"); 195// System.Console.WriteLine("------------------------------------------");
171 System.Console.WriteLine("Locker's call stack:\n" + WriterStack); 196// System.Console.WriteLine("Locker's call stack:\n" + WriterStack);
172 System.Console.WriteLine("------------------------------------------"); 197// System.Console.WriteLine("------------------------------------------");
173 } 198 }
174 else 199 else
175 { 200 {
176 m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by a reader. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); 201 m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by a reader. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
177 System.Console.WriteLine("------------------------------------------"); 202// System.Console.WriteLine("------------------------------------------");
178 System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); 203// System.Console.WriteLine("My call stack:\n" + Environment.StackTrace);
179 System.Console.WriteLine("------------------------------------------"); 204// System.Console.WriteLine("------------------------------------------");
180 foreach (KeyValuePair<Thread, string> kvp in ReadLockers) 205// foreach (KeyValuePair<Thread, string> kvp in ReadLockers)
181 { 206// {
182 System.Console.WriteLine("Locker name {0} call stack:\n" + kvp.Value, kvp.Key.Name); 207// System.Console.WriteLine("Locker name {0} call stack:\n" + kvp.Value, kvp.Key.Name);
183 System.Console.WriteLine("------------------------------------------"); 208// System.Console.WriteLine("------------------------------------------");
184 } 209// }
185 } 210 }
186 m_itemLock = new System.Threading.ReaderWriterLockSlim(); 211 m_itemLock = new System.Threading.ReaderWriterLockSlim();
187 ReadLockers.Clear(); 212// ReadLockers.Clear();
188 } 213 }
189 214
190 LockedByThread = Thread.CurrentThread; 215 LockedByThread = Thread.CurrentThread;
191 WriterStack = Environment.StackTrace; 216// WriterStack = Environment.StackTrace;
192 } 217 }
193 else 218 else
194 { 219 {
diff --git a/OpenSim/Framework/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs
index 7ef8bf7..fb818ee 100644
--- a/OpenSim/Framework/TaskInventoryItem.cs
+++ b/OpenSim/Framework/TaskInventoryItem.cs
@@ -26,6 +26,8 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Reflection;
30using log4net;
29using OpenMetaverse; 31using OpenMetaverse;
30 32
31namespace OpenSim.Framework 33namespace OpenSim.Framework
@@ -35,6 +37,8 @@ namespace OpenSim.Framework
35 /// </summary> 37 /// </summary>
36 public class TaskInventoryItem : ICloneable 38 public class TaskInventoryItem : ICloneable
37 { 39 {
40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
38 /// <summary> 42 /// <summary>
39 /// XXX This should really be factored out into some constants class. 43 /// XXX This should really be factored out into some constants class.
40 /// </summary> 44 /// </summary>
@@ -334,12 +338,18 @@ namespace OpenSim.Framework
334 } 338 }
335 } 339 }
336 340
337 public bool OwnerChanged { 341 public bool OwnerChanged
338 get { 342 {
343 get
344 {
339 return _ownerChanged; 345 return _ownerChanged;
340 } 346 }
341 set { 347 set
348 {
342 _ownerChanged = value; 349 _ownerChanged = value;
350// m_log.DebugFormat(
351// "[TASK INVENTORY ITEM]: Owner changed set {0} for {1} {2} owned by {3}",
352// _ownerChanged, Name, ItemID, OwnerID);
343 } 353 }
344 } 354 }
345 355
diff --git a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
index 34a3f15..6fde488 100644
--- a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
+++ b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
@@ -227,10 +227,10 @@ namespace OpenSim.Framework.Tests
227 es.AddEstateManager(UUID.Zero); 227 es.AddEstateManager(UUID.Zero);
228 228
229 es.AddEstateManager(bannedUserId); 229 es.AddEstateManager(bannedUserId);
230 Assert.IsTrue(es.IsEstateManager(bannedUserId), "bannedUserId should be EstateManager but isn't."); 230 Assert.IsTrue(es.IsEstateManagerOrOwner(bannedUserId), "bannedUserId should be EstateManager but isn't.");
231 231
232 es.RemoveEstateManager(bannedUserId); 232 es.RemoveEstateManager(bannedUserId);
233 Assert.IsFalse(es.IsEstateManager(bannedUserId), "bannedUserID is estateManager but shouldn't be"); 233 Assert.IsFalse(es.IsEstateManagerOrOwner(bannedUserId), "bannedUserID is estateManager but shouldn't be");
234 234
235 Assert.IsFalse(es.HasAccess(bannedUserId), "bannedUserID has access but shouldn't"); 235 Assert.IsFalse(es.HasAccess(bannedUserId), "bannedUserID has access but shouldn't");
236 236
diff --git a/OpenSim/Framework/Tests/UtilTest.cs b/OpenSim/Framework/Tests/UtilTest.cs
index 1ca35df..f0d2a3f 100644
--- a/OpenSim/Framework/Tests/UtilTest.cs
+++ b/OpenSim/Framework/Tests/UtilTest.cs
@@ -214,16 +214,13 @@ namespace OpenSim.Framework.Tests
214 214
215 for (int i = 0; i < contenttypes.Length; i++) 215 for (int i = 0; i < contenttypes.Length; i++)
216 { 216 {
217 if (SLUtil.ContentTypeToSLAssetType(contenttypes[i]) == 18) 217 int expected;
218 { 218 if (contenttypes[i] == "image/tga")
219 Assert.That(contenttypes[i] == "image/tga"); 219 expected = 12; // if we know only the content-type "image/tga", then we assume the asset type is TextureTGA; not ImageTGA
220 }
221 else 220 else
222 { 221 expected = assettypes[i];
223 Assert.That(SLUtil.ContentTypeToSLAssetType(contenttypes[i]) == assettypes[i], 222 Assert.AreEqual(expected, SLUtil.ContentTypeToSLAssetType(contenttypes[i]),
224 "Expecting {0} but got {1}", assettypes[i], 223 String.Format("Incorrect AssetType mapped from Content-Type {0}", contenttypes[i]));
225 SLUtil.ContentTypeToSLAssetType(contenttypes[i]));
226 }
227 } 224 }
228 225
229 int[] inventorytypes = new int[] {-1,0,1,2,3,6,7,8,9,10,15,17,18,20}; 226 int[] inventorytypes = new int[] {-1,0,1,2,3,6,7,8,9,10,15,17,18,20};
@@ -237,7 +234,7 @@ namespace OpenSim.Framework.Tests
237 "application/vnd.ll.primitive", 234 "application/vnd.ll.primitive",
238 "application/vnd.ll.notecard", 235 "application/vnd.ll.notecard",
239 "application/vnd.ll.folder", 236 "application/vnd.ll.folder",
240 "application/octet-stream", 237 "application/vnd.ll.rootfolder",
241 "application/vnd.ll.lsltext", 238 "application/vnd.ll.lsltext",
242 "image/x-j2c", 239 "image/x-j2c",
243 "application/vnd.ll.primitive", 240 "application/vnd.ll.primitive",
@@ -247,7 +244,8 @@ namespace OpenSim.Framework.Tests
247 244
248 for (int i=0;i<inventorytypes.Length;i++) 245 for (int i=0;i<inventorytypes.Length;i++)
249 { 246 {
250 Assert.That(SLUtil.SLInvTypeToContentType(inventorytypes[i]) == invcontenttypes[i], "Expected {0}, Got {1}", invcontenttypes[i], SLUtil.SLInvTypeToContentType(inventorytypes[i])); 247 Assert.AreEqual(invcontenttypes[i], SLUtil.SLInvTypeToContentType(inventorytypes[i]),
248 String.Format("Incorrect Content-Type mapped from InventoryType {0}", inventorytypes[i]));
251 } 249 }
252 250
253 invcontenttypes = new string[] 251 invcontenttypes = new string[]
@@ -280,7 +278,8 @@ namespace OpenSim.Framework.Tests
280 278
281 for (int i = 0; i < invtypes.Length; i++) 279 for (int i = 0; i < invtypes.Length; i++)
282 { 280 {
283 Assert.That(SLUtil.ContentTypeToSLInvType(invcontenttypes[i]) == invtypes[i], "Expected {0}, Got {1}", invtypes[i], SLUtil.ContentTypeToSLInvType(invcontenttypes[i])); 281 Assert.AreEqual(invtypes[i], SLUtil.ContentTypeToSLInvType(invcontenttypes[i]),
282 String.Format("Incorrect InventoryType mapped from Content-Type {0}", invcontenttypes[i]));
284 } 283 }
285 } 284 }
286 } 285 }
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 728cda0..384f716 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -148,6 +148,7 @@ namespace OpenSim.Framework
148 } 148 }
149 149
150 public static Encoding UTF8 = Encoding.UTF8; 150 public static Encoding UTF8 = Encoding.UTF8;
151 public static Encoding UTF8NoBomEncoding = new UTF8Encoding(false);
151 152
152 /// <value> 153 /// <value>
153 /// Well known UUID for the blank texture used in the Linden SL viewer version 1.20 (and hopefully onwards) 154 /// Well known UUID for the blank texture used in the Linden SL viewer version 1.20 (and hopefully onwards)
@@ -1248,8 +1249,7 @@ namespace OpenSim.Framework
1248 1249
1249 public static string Base64ToString(string str) 1250 public static string Base64ToString(string str)
1250 { 1251 {
1251 UTF8Encoding encoder = new UTF8Encoding(); 1252 Decoder utf8Decode = Encoding.UTF8.GetDecoder();
1252 Decoder utf8Decode = encoder.GetDecoder();
1253 1253
1254 byte[] todecode_byte = Convert.FromBase64String(str); 1254 byte[] todecode_byte = Convert.FromBase64String(str);
1255 int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length); 1255 int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Watchdog.cs
index 881b6aa..449d014 100644
--- a/OpenSim/Framework/Watchdog.cs
+++ b/OpenSim/Framework/Watchdog.cs
@@ -41,8 +41,8 @@ namespace OpenSim.Framework
41 /// <summary>Timer interval in milliseconds for the watchdog timer</summary> 41 /// <summary>Timer interval in milliseconds for the watchdog timer</summary>
42 const double WATCHDOG_INTERVAL_MS = 2500.0d; 42 const double WATCHDOG_INTERVAL_MS = 2500.0d;
43 43
44 /// <summary>Maximum timeout in milliseconds before a thread is considered dead</summary> 44 /// <summary>Default timeout in milliseconds before a thread is considered dead</summary>
45 const int WATCHDOG_TIMEOUT_MS = 5000; 45 public const int DEFAULT_WATCHDOG_TIMEOUT_MS = 5000;
46 46
47 [System.Diagnostics.DebuggerDisplay("{Thread.Name}")] 47 [System.Diagnostics.DebuggerDisplay("{Thread.Name}")]
48 public class ThreadWatchdogInfo 48 public class ThreadWatchdogInfo
@@ -58,7 +58,7 @@ namespace OpenSim.Framework
58 public int FirstTick { get; private set; } 58 public int FirstTick { get; private set; }
59 59
60 /// <summary> 60 /// <summary>
61 /// First time this heartbeat update was invoked 61 /// Last time this heartbeat update was invoked
62 /// </summary> 62 /// </summary>
63 public int LastTick { get; set; } 63 public int LastTick { get; set; }
64 64
@@ -77,6 +77,11 @@ namespace OpenSim.Framework
77 /// </summary> 77 /// </summary>
78 public bool AlarmIfTimeout { get; set; } 78 public bool AlarmIfTimeout { get; set; }
79 79
80 /// <summary>
81 /// Method execute if alarm goes off. If null then no alarm method is fired.
82 /// </summary>
83 public Func<string> AlarmMethod { get; set; }
84
80 public ThreadWatchdogInfo(Thread thread, int timeout) 85 public ThreadWatchdogInfo(Thread thread, int timeout)
81 { 86 {
82 Thread = thread; 87 Thread = thread;
@@ -87,27 +92,33 @@ namespace OpenSim.Framework
87 } 92 }
88 93
89 /// <summary> 94 /// <summary>
90 /// This event is called whenever a tracked thread is stopped or 95 /// This event is called whenever a tracked thread is
91 /// has not called UpdateThread() in time 96 /// stopped or has not called UpdateThread() in time<
92 /// </summary> 97 /// /summary>
93 /// <param name="thread">The thread that has been identified as dead</param> 98 public static event Action<ThreadWatchdogInfo> OnWatchdogTimeout;
94 /// <param name="lastTick">The last time this thread called UpdateThread()</param>
95 public delegate void WatchdogTimeout(Thread thread, int lastTick);
96
97 /// <summary>This event is called whenever a tracked thread is
98 /// stopped or has not called UpdateThread() in time</summary>
99 public static event WatchdogTimeout OnWatchdogTimeout;
100 99
101 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 100 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
102 private static Dictionary<int, ThreadWatchdogInfo> m_threads; 101 private static Dictionary<int, ThreadWatchdogInfo> m_threads;
103 private static System.Timers.Timer m_watchdogTimer; 102 private static System.Timers.Timer m_watchdogTimer;
104 103
104 /// <summary>
105 /// Last time the watchdog thread ran.
106 /// </summary>
107 /// <remarks>
108 /// Should run every WATCHDOG_INTERVAL_MS
109 /// </remarks>
110 public static int LastWatchdogThreadTick { get; private set; }
111
105 static Watchdog() 112 static Watchdog()
106 { 113 {
107 m_threads = new Dictionary<int, ThreadWatchdogInfo>(); 114 m_threads = new Dictionary<int, ThreadWatchdogInfo>();
108 m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS); 115 m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS);
109 m_watchdogTimer.AutoReset = false; 116 m_watchdogTimer.AutoReset = false;
110 m_watchdogTimer.Elapsed += WatchdogTimerElapsed; 117 m_watchdogTimer.Elapsed += WatchdogTimerElapsed;
118
119 // Set now so we don't get alerted on the first run
120 LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
121
111 m_watchdogTimer.Start(); 122 m_watchdogTimer.Start();
112 } 123 }
113 124
@@ -123,7 +134,7 @@ namespace OpenSim.Framework
123 public static Thread StartThread( 134 public static Thread StartThread(
124 ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout) 135 ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout)
125 { 136 {
126 return StartThread(start, name, priority, isBackground, alarmIfTimeout, WATCHDOG_TIMEOUT_MS); 137 return StartThread(start, name, priority, isBackground, alarmIfTimeout, null, DEFAULT_WATCHDOG_TIMEOUT_MS);
127 } 138 }
128 139
129 /// <summary> 140 /// <summary>
@@ -135,17 +146,24 @@ namespace OpenSim.Framework
135 /// <param name="isBackground">True to run this thread as a background 146 /// <param name="isBackground">True to run this thread as a background
136 /// thread, otherwise false</param> 147 /// thread, otherwise false</param>
137 /// <param name="alarmIfTimeout">Trigger an alarm function is we have timed out</param> 148 /// <param name="alarmIfTimeout">Trigger an alarm function is we have timed out</param>
149 /// <param name="alarmMethod">
150 /// Alarm method to call if alarmIfTimeout is true and there is a timeout.
151 /// Normally, this will just return some useful debugging information.
152 /// </param>
138 /// <param name="timeout">Number of milliseconds to wait until we issue a warning about timeout.</param> 153 /// <param name="timeout">Number of milliseconds to wait until we issue a warning about timeout.</param>
139 /// <returns>The newly created Thread object</returns> 154 /// <returns>The newly created Thread object</returns>
140 public static Thread StartThread( 155 public static Thread StartThread(
141 ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout, int timeout) 156 ThreadStart start, string name, ThreadPriority priority, bool isBackground,
157 bool alarmIfTimeout, Func<string> alarmMethod, int timeout)
142 { 158 {
143 Thread thread = new Thread(start); 159 Thread thread = new Thread(start);
144 thread.Name = name; 160 thread.Name = name;
145 thread.Priority = priority; 161 thread.Priority = priority;
146 thread.IsBackground = isBackground; 162 thread.IsBackground = isBackground;
147 163
148 ThreadWatchdogInfo twi = new ThreadWatchdogInfo(thread, timeout) { AlarmIfTimeout = alarmIfTimeout }; 164 ThreadWatchdogInfo twi
165 = new ThreadWatchdogInfo(thread, timeout)
166 { AlarmIfTimeout = alarmIfTimeout, AlarmMethod = alarmMethod };
149 167
150 m_log.DebugFormat( 168 m_log.DebugFormat(
151 "[WATCHDOG]: Started tracking thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId); 169 "[WATCHDOG]: Started tracking thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
@@ -258,7 +276,17 @@ namespace OpenSim.Framework
258 /// <param name="e"></param> 276 /// <param name="e"></param>
259 private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) 277 private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
260 { 278 {
261 WatchdogTimeout callback = OnWatchdogTimeout; 279 int now = Environment.TickCount & Int32.MaxValue;
280 int msElapsed = now - LastWatchdogThreadTick;
281
282 if (msElapsed > WATCHDOG_INTERVAL_MS * 2)
283 m_log.WarnFormat(
284 "[WATCHDOG]: {0} ms since Watchdog last ran. Interval should be approximately {1} ms",
285 msElapsed, WATCHDOG_INTERVAL_MS);
286
287 LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
288
289 Action<ThreadWatchdogInfo> callback = OnWatchdogTimeout;
262 290
263 if (callback != null) 291 if (callback != null)
264 { 292 {
@@ -266,8 +294,6 @@ namespace OpenSim.Framework
266 294
267 lock (m_threads) 295 lock (m_threads)
268 { 296 {
269 int now = Environment.TickCount;
270
271 foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) 297 foreach (ThreadWatchdogInfo threadInfo in m_threads.Values)
272 { 298 {
273 if (threadInfo.Thread.ThreadState == ThreadState.Stopped) 299 if (threadInfo.Thread.ThreadState == ThreadState.Stopped)
@@ -296,7 +322,7 @@ namespace OpenSim.Framework
296 322
297 if (callbackInfos != null) 323 if (callbackInfos != null)
298 foreach (ThreadWatchdogInfo callbackInfo in callbackInfos) 324 foreach (ThreadWatchdogInfo callbackInfo in callbackInfos)
299 callback(callbackInfo.Thread, callbackInfo.LastTick); 325 callback(callbackInfo);
300 } 326 }
301 327
302 m_watchdogTimer.Start(); 328 m_watchdogTimer.Start();
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index aac575c..6a40cd5 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -53,19 +53,36 @@ namespace OpenSim.Framework
53 LogManager.GetLogger( 53 LogManager.GetLogger(
54 MethodBase.GetCurrentMethod().DeclaringType); 54 MethodBase.GetCurrentMethod().DeclaringType);
55 55
56 private static int m_requestNumber = 0; 56 /// <summary>
57 /// Request number for diagnostic purposes.
58 /// </summary>
59 public static int RequestNumber = 0;
57 60
58 // this is the header field used to communicate the local request id 61 /// <summary>
59 // used for performance and debugging 62 /// this is the header field used to communicate the local request id
63 /// used for performance and debugging
64 /// </summary>
60 public const string OSHeaderRequestID = "opensim-request-id"; 65 public const string OSHeaderRequestID = "opensim-request-id";
61 66
62 // number of milliseconds a call can take before it is considered 67 /// <summary>
63 // a "long" call for warning & debugging purposes 68 /// Number of milliseconds a call can take before it is considered
64 public const int LongCallTime = 500; 69 /// a "long" call for warning & debugging purposes
70 /// </summary>
71 public const int LongCallTime = 3000;
65 72
66 // dictionary of end points 73 /// <summary>
74 /// The maximum length of any data logged because of a long request time.
75 /// </summary>
76 /// <remarks>
77 /// This is to truncate any really large post data, such as an asset. In theory, the first section should
78 /// give us useful information about the call (which agent it relates to if applicable, etc.).
79 /// </remarks>
80 public const int MaxRequestDiagLength = 100;
81
82 /// <summary>
83 /// Dictionary of end points
84 /// </summary>
67 private static Dictionary<string,object> m_endpointSerializer = new Dictionary<string,object>(); 85 private static Dictionary<string,object> m_endpointSerializer = new Dictionary<string,object>();
68
69 86
70 private static object EndPointLock(string url) 87 private static object EndPointLock(string url)
71 { 88 {
@@ -86,8 +103,7 @@ namespace OpenSim.Framework
86 return eplock; 103 return eplock;
87 } 104 }
88 } 105 }
89 106
90
91 #region JSONRequest 107 #region JSONRequest
92 108
93 /// <summary> 109 /// <summary>
@@ -129,12 +145,13 @@ namespace OpenSim.Framework
129 145
130 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed) 146 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed)
131 { 147 {
132 int reqnum = m_requestNumber++; 148 int reqnum = RequestNumber++;
133 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); 149 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
134 150
135 string errorMessage = "unknown error"; 151 string errorMessage = "unknown error";
136 int tickstart = Util.EnvironmentTickCount(); 152 int tickstart = Util.EnvironmentTickCount();
137 int tickdata = 0; 153 int tickdata = 0;
154 string strBuffer = null;
138 155
139 try 156 try
140 { 157 {
@@ -149,7 +166,7 @@ namespace OpenSim.Framework
149 // If there is some input, write it into the request 166 // If there is some input, write it into the request
150 if (data != null) 167 if (data != null)
151 { 168 {
152 string strBuffer = OSDParser.SerializeJsonString(data); 169 strBuffer = OSDParser.SerializeJsonString(data);
153 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer); 170 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer);
154 171
155 if (compressed) 172 if (compressed)
@@ -210,14 +227,23 @@ namespace OpenSim.Framework
210 } 227 }
211 finally 228 finally
212 { 229 {
213 // This just dumps a warning for any operation that takes more than 100 ms
214 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 230 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
215 if (tickdiff > LongCallTime) 231 if (tickdiff > LongCallTime)
216 m_log.DebugFormat("[WEB UTIL]: osd request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing", 232 m_log.InfoFormat(
217 reqnum,url,method,tickdiff,tickdata); 233 "[OSD REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
234 reqnum,
235 method,
236 url,
237 tickdiff,
238 tickdata,
239 strBuffer != null
240 ? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer)
241 : "");
218 } 242 }
219 243
220 m_log.DebugFormat("[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage); 244 m_log.DebugFormat(
245 "[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage);
246
221 return ErrorResponseMap(errorMessage); 247 return ErrorResponseMap(errorMessage);
222 } 248 }
223 249
@@ -290,17 +316,17 @@ namespace OpenSim.Framework
290 316
291 private static OSDMap ServiceFormRequestWorker(string url, NameValueCollection data, int timeout) 317 private static OSDMap ServiceFormRequestWorker(string url, NameValueCollection data, int timeout)
292 { 318 {
293 int reqnum = m_requestNumber++; 319 int reqnum = RequestNumber++;
294 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown"; 320 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown";
295 // m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method); 321 // m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method);
296 322
297 string errorMessage = "unknown error"; 323 string errorMessage = "unknown error";
298 int tickstart = Util.EnvironmentTickCount(); 324 int tickstart = Util.EnvironmentTickCount();
299 int tickdata = 0; 325 int tickdata = 0;
326 string queryString = null;
300 327
301 try 328 try
302 { 329 {
303
304 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); 330 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
305 request.Method = "POST"; 331 request.Method = "POST";
306 request.Timeout = timeout; 332 request.Timeout = timeout;
@@ -311,7 +337,7 @@ namespace OpenSim.Framework
311 337
312 if (data != null) 338 if (data != null)
313 { 339 {
314 string queryString = BuildQueryString(data); 340 queryString = BuildQueryString(data);
315 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString); 341 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString);
316 342
317 request.ContentLength = buffer.Length; 343 request.ContentLength = buffer.Length;
@@ -354,11 +380,20 @@ namespace OpenSim.Framework
354 { 380 {
355 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 381 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
356 if (tickdiff > LongCallTime) 382 if (tickdiff > LongCallTime)
357 m_log.InfoFormat("[WEB UTIL]: form request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing", 383 m_log.InfoFormat(
358 reqnum,url,method,tickdiff,tickdata); 384 "[SERVICE FORM]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
385 reqnum,
386 method,
387 url,
388 tickdiff,
389 tickdata,
390 queryString != null
391 ? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString
392 : "");
359 } 393 }
360 394
361 m_log.WarnFormat("[WEB UTIL]: <{0}> form request failed: {1}",reqnum,errorMessage); 395 m_log.WarnFormat("[SERVICE FORM]: <{0}> form request to {1} failed: {2}", reqnum, url, errorMessage);
396
362 return ErrorResponseMap(errorMessage); 397 return ErrorResponseMap(errorMessage);
363 } 398 }
364 399
@@ -638,8 +673,6 @@ namespace OpenSim.Framework
638 673
639 return new string[0]; 674 return new string[0];
640 } 675 }
641
642
643 } 676 }
644 677
645 public static class AsynchronousRestObjectRequester 678 public static class AsynchronousRestObjectRequester
@@ -662,6 +695,12 @@ namespace OpenSim.Framework
662 public static void MakeRequest<TRequest, TResponse>(string verb, 695 public static void MakeRequest<TRequest, TResponse>(string verb,
663 string requestUrl, TRequest obj, Action<TResponse> action) 696 string requestUrl, TRequest obj, Action<TResponse> action)
664 { 697 {
698 int reqnum = WebUtil.RequestNumber++;
699 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
700
701 int tickstart = Util.EnvironmentTickCount();
702 int tickdata = 0;
703
665 // m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl); 704 // m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl);
666 705
667 Type type = typeof(TRequest); 706 Type type = typeof(TRequest);
@@ -672,12 +711,13 @@ namespace OpenSim.Framework
672 XmlSerializer deserializer = new XmlSerializer(typeof(TResponse)); 711 XmlSerializer deserializer = new XmlSerializer(typeof(TResponse));
673 712
674 request.Method = verb; 713 request.Method = verb;
714 MemoryStream buffer = null;
675 715
676 if (verb == "POST") 716 if (verb == "POST")
677 { 717 {
678 request.ContentType = "text/xml"; 718 request.ContentType = "text/xml";
679 719
680 MemoryStream buffer = new MemoryStream(); 720 buffer = new MemoryStream();
681 721
682 XmlWriterSettings settings = new XmlWriterSettings(); 722 XmlWriterSettings settings = new XmlWriterSettings();
683 settings.Encoding = Encoding.UTF8; 723 settings.Encoding = Encoding.UTF8;
@@ -699,6 +739,9 @@ namespace OpenSim.Framework
699 requestStream.Write(buffer.ToArray(), 0, length); 739 requestStream.Write(buffer.ToArray(), 0, length);
700 requestStream.Close(); 740 requestStream.Close();
701 741
742 // capture how much time was spent writing
743 tickdata = Util.EnvironmentTickCountSubtract(tickstart);
744
702 request.BeginGetResponse(delegate(IAsyncResult ar) 745 request.BeginGetResponse(delegate(IAsyncResult ar)
703 { 746 {
704 response = request.EndGetResponse(ar); 747 response = request.EndGetResponse(ar);
@@ -724,83 +767,108 @@ namespace OpenSim.Framework
724 767
725 }, null); 768 }, null);
726 }, null); 769 }, null);
727
728
729 return;
730 } 770 }
731 771 else
732 request.BeginGetResponse(delegate(IAsyncResult res2)
733 { 772 {
734 try 773 request.BeginGetResponse(delegate(IAsyncResult res2)
735 { 774 {
736 // If the server returns a 404, this appears to trigger a System.Net.WebException even though that isn't
737 // documented in MSDN
738 response = request.EndGetResponse(res2);
739
740 Stream respStream = null;
741 try 775 try
742 { 776 {
743 respStream = response.GetResponseStream(); 777 // If the server returns a 404, this appears to trigger a System.Net.WebException even though that isn't
744 deserial = (TResponse)deserializer.Deserialize(respStream); 778 // documented in MSDN
745 } 779 response = request.EndGetResponse(res2);
746 catch (System.InvalidOperationException) 780
747 { 781 Stream respStream = null;
748 } 782 try
749 finally 783 {
750 { 784 respStream = response.GetResponseStream();
751 respStream.Close(); 785 deserial = (TResponse)deserializer.Deserialize(respStream);
752 response.Close(); 786 }
787 catch (System.InvalidOperationException)
788 {
789 }
790 finally
791 {
792 respStream.Close();
793 response.Close();
794 }
753 } 795 }
754 } 796 catch (WebException e)
755 catch (WebException e)
756 {
757 if (e.Status == WebExceptionStatus.ProtocolError)
758 { 797 {
759 if (e.Response is HttpWebResponse) 798 if (e.Status == WebExceptionStatus.ProtocolError)
760 { 799 {
761 HttpWebResponse httpResponse = (HttpWebResponse)e.Response; 800 if (e.Response is HttpWebResponse)
762
763 if (httpResponse.StatusCode != HttpStatusCode.NotFound)
764 { 801 {
765 // We don't appear to be handling any other status codes, so log these feailures to that 802 HttpWebResponse httpResponse = (HttpWebResponse)e.Response;
766 // people don't spend unnecessary hours hunting phantom bugs. 803
767 m_log.DebugFormat( 804 if (httpResponse.StatusCode != HttpStatusCode.NotFound)
768 "[ASYNC REQUEST]: Request {0} {1} failed with unexpected status code {2}", 805 {
769 verb, requestUrl, httpResponse.StatusCode); 806 // We don't appear to be handling any other status codes, so log these feailures to that
807 // people don't spend unnecessary hours hunting phantom bugs.
808 m_log.DebugFormat(
809 "[ASYNC REQUEST]: Request {0} {1} failed with unexpected status code {2}",
810 verb, requestUrl, httpResponse.StatusCode);
811 }
770 } 812 }
771 } 813 }
814 else
815 {
816 m_log.ErrorFormat(
817 "[ASYNC REQUEST]: Request {0} {1} failed with status {2} and message {3}",
818 verb, requestUrl, e.Status, e.Message);
819 }
772 } 820 }
773 else 821 catch (Exception e)
774 { 822 {
775 m_log.ErrorFormat("[ASYNC REQUEST]: Request {0} {1} failed with status {2} and message {3}", verb, requestUrl, e.Status, e.Message); 823 m_log.ErrorFormat(
824 "[ASYNC REQUEST]: Request {0} {1} failed with exception {2}{3}",
825 verb, requestUrl, e.Message, e.StackTrace);
776 } 826 }
777 } 827
778 catch (Exception e) 828 // m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString());
779 {
780 m_log.ErrorFormat("[ASYNC REQUEST]: Request {0} {1} failed with exception {2}", verb, requestUrl, e);
781 }
782 829
783 // m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString()); 830 try
831 {
832 action(deserial);
833 }
834 catch (Exception e)
835 {
836 m_log.ErrorFormat(
837 "[ASYNC REQUEST]: Request {0} {1} callback failed with exception {2}{3}",
838 verb, requestUrl, e.Message, e.StackTrace);
839 }
840
841 }, null);
842 }
784 843
785 try 844 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
786 { 845 if (tickdiff > WebUtil.LongCallTime)
787 action(deserial); 846 {
788 } 847 string originalRequest = null;
789 catch (Exception e) 848
849 if (buffer != null)
790 { 850 {
791 m_log.ErrorFormat( 851 originalRequest = Encoding.UTF8.GetString(buffer.ToArray());
792 "[ASYNC REQUEST]: Request {0} {1} callback failed with exception {2}", verb, requestUrl, e); 852
853 if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
854 originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
793 } 855 }
794 856
795 }, null); 857 m_log.InfoFormat(
858 "[ASYNC REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
859 reqnum,
860 verb,
861 requestUrl,
862 tickdiff,
863 tickdata,
864 originalRequest);
865 }
796 } 866 }
797 } 867 }
798 868
799 public static class SynchronousRestFormsRequester 869 public static class SynchronousRestFormsRequester
800 { 870 {
801 private static readonly ILog m_log = 871 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
802 LogManager.GetLogger(
803 MethodBase.GetCurrentMethod().DeclaringType);
804 872
805 /// <summary> 873 /// <summary>
806 /// Perform a synchronous REST request. 874 /// Perform a synchronous REST request.
@@ -814,6 +882,12 @@ namespace OpenSim.Framework
814 /// the request. You'll want to make sure you deal with this as they're not uncommon</exception> 882 /// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
815 public static string MakeRequest(string verb, string requestUrl, string obj) 883 public static string MakeRequest(string verb, string requestUrl, string obj)
816 { 884 {
885 int reqnum = WebUtil.RequestNumber++;
886 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
887
888 int tickstart = Util.EnvironmentTickCount();
889 int tickdata = 0;
890
817 WebRequest request = WebRequest.Create(requestUrl); 891 WebRequest request = WebRequest.Create(requestUrl);
818 request.Method = verb; 892 request.Method = verb;
819 string respstring = String.Empty; 893 string respstring = String.Empty;
@@ -842,12 +916,16 @@ namespace OpenSim.Framework
842 } 916 }
843 catch (Exception e) 917 catch (Exception e)
844 { 918 {
845 m_log.DebugFormat("[FORMS]: exception occured on sending request to {0}: " + e.ToString(), requestUrl); 919 m_log.DebugFormat(
920 "[FORMS]: exception occured {0} {1}: {2}{3}", verb, requestUrl, e.Message, e.StackTrace);
846 } 921 }
847 finally 922 finally
848 { 923 {
849 if (requestStream != null) 924 if (requestStream != null)
850 requestStream.Close(); 925 requestStream.Close();
926
927 // capture how much time was spent writing
928 tickdata = Util.EnvironmentTickCountSubtract(tickstart);
851 } 929 }
852 } 930 }
853 931
@@ -868,7 +946,9 @@ namespace OpenSim.Framework
868 } 946 }
869 catch (Exception e) 947 catch (Exception e)
870 { 948 {
871 m_log.DebugFormat("[FORMS]: exception occured on receiving reply " + e.ToString()); 949 m_log.DebugFormat(
950 "[FORMS]: Exception occured on receiving {0} {1}: {2}{3}",
951 verb, requestUrl, e.Message, e.StackTrace);
872 } 952 }
873 finally 953 finally
874 { 954 {
@@ -881,9 +961,21 @@ namespace OpenSim.Framework
881 catch (System.InvalidOperationException) 961 catch (System.InvalidOperationException)
882 { 962 {
883 // This is what happens when there is invalid XML 963 // This is what happens when there is invalid XML
884 m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving request"); 964 m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving {0} {1}", verb, requestUrl);
885 } 965 }
886 } 966 }
967
968 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
969 if (tickdiff > WebUtil.LongCallTime)
970 m_log.InfoFormat(
971 "[FORMS]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
972 reqnum,
973 verb,
974 requestUrl,
975 tickdiff,
976 tickdata,
977 obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
978
887 return respstring; 979 return respstring;
888 } 980 }
889 } 981 }
@@ -911,6 +1003,12 @@ namespace OpenSim.Framework
911 1003
912 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout) 1004 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout)
913 { 1005 {
1006 int reqnum = WebUtil.RequestNumber++;
1007 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
1008
1009 int tickstart = Util.EnvironmentTickCount();
1010 int tickdata = 0;
1011
914 Type type = typeof(TRequest); 1012 Type type = typeof(TRequest);
915 TResponse deserial = default(TResponse); 1013 TResponse deserial = default(TResponse);
916 1014
@@ -918,12 +1016,13 @@ namespace OpenSim.Framework
918 request.Method = verb; 1016 request.Method = verb;
919 if (pTimeout != 0) 1017 if (pTimeout != 0)
920 request.Timeout = pTimeout * 1000; 1018 request.Timeout = pTimeout * 1000;
1019 MemoryStream buffer = null;
921 1020
922 if ((verb == "POST") || (verb == "PUT")) 1021 if ((verb == "POST") || (verb == "PUT"))
923 { 1022 {
924 request.ContentType = "text/xml"; 1023 request.ContentType = "text/xml";
925 1024
926 MemoryStream buffer = new MemoryStream(); 1025 buffer = new MemoryStream();
927 1026
928 XmlWriterSettings settings = new XmlWriterSettings(); 1027 XmlWriterSettings settings = new XmlWriterSettings();
929 settings.Encoding = Encoding.UTF8; 1028 settings.Encoding = Encoding.UTF8;
@@ -946,13 +1045,19 @@ namespace OpenSim.Framework
946 } 1045 }
947 catch (Exception e) 1046 catch (Exception e)
948 { 1047 {
949 m_log.DebugFormat("[SynchronousRestObjectRequester]: exception in sending data to {0}: {1}", requestUrl, e); 1048 m_log.DebugFormat(
1049 "[SynchronousRestObjectRequester]: Exception in making request {0} {1}: {2}{3}",
1050 verb, requestUrl, e.Message, e.StackTrace);
1051
950 return deserial; 1052 return deserial;
951 } 1053 }
952 finally 1054 finally
953 { 1055 {
954 if (requestStream != null) 1056 if (requestStream != null)
955 requestStream.Close(); 1057 requestStream.Close();
1058
1059 // capture how much time was spent writing
1060 tickdata = Util.EnvironmentTickCountSubtract(tickstart);
956 } 1061 }
957 } 1062 }
958 1063
@@ -968,7 +1073,11 @@ namespace OpenSim.Framework
968 respStream.Close(); 1073 respStream.Close();
969 } 1074 }
970 else 1075 else
971 m_log.DebugFormat("[SynchronousRestObjectRequester]: Oops! no content found in response stream from {0} {1}", requestUrl, verb); 1076 {
1077 m_log.DebugFormat(
1078 "[SynchronousRestObjectRequester]: Oops! no content found in response stream from {0} {1}",
1079 verb, requestUrl);
1080 }
972 } 1081 }
973 } 1082 }
974 catch (WebException e) 1083 catch (WebException e)
@@ -979,17 +1088,44 @@ namespace OpenSim.Framework
979 return deserial; 1088 return deserial;
980 else 1089 else
981 m_log.ErrorFormat( 1090 m_log.ErrorFormat(
982 "[SynchronousRestObjectRequester]: WebException {0} {1} {2} {3}", 1091 "[SynchronousRestObjectRequester]: WebException for {0} {1} {2}: {3} {4}",
983 requestUrl, typeof(TResponse).ToString(), e.Message, e.StackTrace); 1092 verb, requestUrl, typeof(TResponse).ToString(), e.Message, e.StackTrace);
984 } 1093 }
985 catch (System.InvalidOperationException) 1094 catch (System.InvalidOperationException)
986 { 1095 {
987 // This is what happens when there is invalid XML 1096 // This is what happens when there is invalid XML
988 m_log.DebugFormat("[SynchronousRestObjectRequester]: Invalid XML {0} {1}", requestUrl, typeof(TResponse).ToString()); 1097 m_log.DebugFormat(
1098 "[SynchronousRestObjectRequester]: Invalid XML from {0} {1} {2}",
1099 verb, requestUrl, typeof(TResponse).ToString());
989 } 1100 }
990 catch (Exception e) 1101 catch (Exception e)
991 { 1102 {
992 m_log.DebugFormat("[SynchronousRestObjectRequester]: Exception on response from {0} {1}", requestUrl, e); 1103 m_log.DebugFormat(
1104 "[SynchronousRestObjectRequester]: Exception on response from {0} {1}: {2}{3}",
1105 verb, requestUrl, e.Message, e.StackTrace);
1106 }
1107
1108 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
1109 if (tickdiff > WebUtil.LongCallTime)
1110 {
1111 string originalRequest = null;
1112
1113 if (buffer != null)
1114 {
1115 originalRequest = Encoding.UTF8.GetString(buffer.ToArray());
1116
1117 if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
1118 originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
1119 }
1120
1121 m_log.InfoFormat(
1122 "[SynchronousRestObjectRequester]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
1123 reqnum,
1124 verb,
1125 requestUrl,
1126 tickdiff,
1127 tickdata,
1128 originalRequest);
993 } 1129 }
994 1130
995 return deserial; 1131 return deserial;