diff options
Diffstat (limited to '')
41 files changed, 1624 insertions, 934 deletions
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Linq; | ||
31 | using System.Text; | ||
32 | |||
33 | namespace 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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Linq; | ||
31 | using System.Text; | ||
32 | |||
33 | namespace 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..4b15325 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; } |
@@ -1423,8 +1430,6 @@ namespace OpenSim.Framework | |||
1423 | 1430 | ||
1424 | void SendGroupVoteHistory(UUID groupID, UUID transactionID, GroupVoteHistory[] Votes); | 1431 | void SendGroupVoteHistory(UUID groupID, UUID transactionID, GroupVoteHistory[] Votes); |
1425 | 1432 | ||
1426 | void KillEndDone(); | ||
1427 | |||
1428 | bool AddGenericPacketHandler(string MethodName, GenericMessage handler); | 1433 | bool AddGenericPacketHandler(string MethodName, GenericMessage handler); |
1429 | 1434 | ||
1430 | void SendRebakeAvatarTextures(UUID textureID); | 1435 | 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 | ||
28 | using System; | 28 | using System; |
29 | using OpenMetaverse; | ||
29 | 30 | ||
30 | namespace OpenSim.Framework | 31 | namespace 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; | |||
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.IO; | 30 | using System.IO; |
31 | using OpenMetaverse; | 31 | using OpenMetaverse; |
32 | using System.Runtime.Serialization; | ||
32 | 33 | ||
33 | namespace OpenSim.Framework | 34 | namespace 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..e8d82d3 100644 --- a/OpenSim/Framework/Serialization/External/LandDataSerializer.cs +++ b/OpenSim/Framework/Serialization/External/LandDataSerializer.cs | |||
@@ -42,7 +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 | 46 | ||
47 | protected static UTF8Encoding m_utf8Encoding = new UTF8Encoding(); | 47 | protected static UTF8Encoding m_utf8Encoding = new UTF8Encoding(); |
48 | 48 | ||
diff --git a/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs b/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs index 931898c..f18435d 100644 --- a/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs +++ b/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs | |||
@@ -30,6 +30,8 @@ using System.Text; | |||
30 | using System.Xml; | 30 | using System.Xml; |
31 | using OpenMetaverse; | 31 | using OpenMetaverse; |
32 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
33 | using log4net; | ||
34 | using System.Reflection; | ||
33 | 35 | ||
34 | namespace OpenSim.Framework.Serialization.External | 36 | namespace OpenSim.Framework.Serialization.External |
35 | { | 37 | { |
@@ -187,7 +189,29 @@ namespace OpenSim.Framework.Serialization.External | |||
187 | break; | 189 | break; |
188 | } | 190 | } |
189 | } | 191 | } |
190 | 192 | ||
193 | xtr.ReadEndElement(); | ||
194 | |||
195 | if (xtr.IsStartElement("Telehub")) | ||
196 | { | ||
197 | xtr.ReadStartElement("Telehub"); | ||
198 | |||
199 | while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement) | ||
200 | { | ||
201 | switch (xtr.Name) | ||
202 | { | ||
203 | case "TelehubObject": | ||
204 | settings.TelehubObject = UUID.Parse(xtr.ReadElementContentAsString()); | ||
205 | break; | ||
206 | case "SpawnPoint": | ||
207 | string str = xtr.ReadElementContentAsString(); | ||
208 | SpawnPoint sp = SpawnPoint.Parse(str); | ||
209 | settings.AddSpawnPoint(sp); | ||
210 | break; | ||
211 | } | ||
212 | } | ||
213 | } | ||
214 | |||
191 | xtr.Close(); | 215 | xtr.Close(); |
192 | sr.Close(); | 216 | sr.Close(); |
193 | 217 | ||
@@ -243,7 +267,16 @@ namespace OpenSim.Framework.Serialization.External | |||
243 | xtw.WriteElementString("SunPosition", settings.SunPosition.ToString()); | 267 | xtw.WriteElementString("SunPosition", settings.SunPosition.ToString()); |
244 | // Note: 'SunVector' isn't saved because this value is owned by the Sun Module, which | 268 | // 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. | 269 | // calculates it automatically according to the date and other factors. |
246 | xtw.WriteEndElement(); | 270 | xtw.WriteEndElement(); |
271 | |||
272 | xtw.WriteStartElement("Telehub"); | ||
273 | if (settings.TelehubObject != UUID.Zero) | ||
274 | { | ||
275 | xtw.WriteElementString("TelehubObject", settings.TelehubObject.ToString()); | ||
276 | foreach (SpawnPoint sp in settings.SpawnPoints()) | ||
277 | xtw.WriteElementString("SpawnPoint", sp.ToString()); | ||
278 | } | ||
279 | xtw.WriteEndElement(); | ||
247 | 280 | ||
248 | xtw.WriteEndElement(); | 281 | xtw.WriteEndElement(); |
249 | 282 | ||
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/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..7bbb290 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> |
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 ad5af1f..1d5b426 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(); |
@@ -1809,7 +1651,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1809 | 1651 | ||
1810 | public void httpServerException(object source, Exception exception) | 1652 | public void httpServerException(object source, Exception exception) |
1811 | { | 1653 | { |
1812 | m_log.ErrorFormat("[BASE HTTP SERVER]: {0} had an exception {1}", source.ToString(), exception.ToString()); | 1654 | m_log.Error(String.Format("[BASE HTTP SERVER]: {0} had an exception: {1} ", source.ToString(), exception.Message), exception); |
1813 | /* | 1655 | /* |
1814 | if (HTTPDRunning)// && NotSocketErrors > 5) | 1656 | if (HTTPDRunning)// && NotSocketErrors > 5) |
1815 | { | 1657 | { |
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 @@ | |||
28 | namespace OpenSim.Framework.Servers.HttpServer | 28 | namespace 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 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using OpenMetaverse; | 30 | using OpenMetaverse; |
31 | |||
31 | namespace OpenSim.Framework.Servers.HttpServer | 32 | namespace 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 | ||
32 | namespace OpenSim.Framework.Servers.HttpServer | 32 | namespace 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 | ||
28 | using System; | ||
28 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
29 | using System.Reflection; | 30 | using System.Reflection; |
30 | using System.Net; | 31 | using System.Net; |
31 | using log4net; | 32 | using log4net; |
33 | using OpenSim.Framework; | ||
34 | using OpenSim.Framework.Console; | ||
32 | using OpenSim.Framework.Servers.HttpServer; | 35 | using OpenSim.Framework.Servers.HttpServer; |
33 | 36 | ||
34 | namespace OpenSim.Framework.Servers | 37 | namespace 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 | ||
28 | using System; | 28 | using System; |
29 | using System.Reflection; | ||
30 | using log4net; | ||
29 | using OpenMetaverse; | 31 | using OpenMetaverse; |
30 | 32 | ||
31 | namespace OpenSim.Framework | 33 | namespace 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/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; |