aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorMelanie2013-06-23 01:49:45 +0100
committerMelanie2013-06-23 01:49:45 +0100
commit936700bda3969bc54166f0d6a3ca81e3d5c42935 (patch)
tree6bb97abf25f4a3f22ccb40e3b4be20c551327b09
parentFix prim locking to behave like SL (diff)
parentMerge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff)
downloadopensim-SC_OLD-936700bda3969bc54166f0d6a3ca81e3d5c42935.zip
opensim-SC_OLD-936700bda3969bc54166f0d6a3ca81e3d5c42935.tar.gz
opensim-SC_OLD-936700bda3969bc54166f0d6a3ca81e3d5c42935.tar.bz2
opensim-SC_OLD-936700bda3969bc54166f0d6a3ca81e3d5c42935.tar.xz
Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim
-rw-r--r--OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs2
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs4
-rw-r--r--OpenSim/Framework/Monitoring/BaseStatsCollector.cs12
-rw-r--r--OpenSim/Framework/Monitoring/MemoryWatchdog.cs8
-rw-r--r--OpenSim/Framework/Monitoring/ServerStatsCollector.cs349
-rw-r--r--OpenSim/Framework/Monitoring/Stats/Stat.cs24
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs130
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs46
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs30
-rw-r--r--OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs20
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs95
-rw-r--r--OpenSim/Framework/Util.cs104
-rw-r--r--OpenSim/Region/Application/Application.cs1
-rw-r--r--OpenSim/Region/Application/OpenSim.cs2
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs7
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs5
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs23
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs10
-rw-r--r--OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs339
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs44
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs66
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs3
-rw-r--r--OpenSim/Server/Base/ServicesServerBase.cs20
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs2
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs200
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs2
-rw-r--r--OpenSim/Server/Handlers/Simulation/AgentHandlers.cs77
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs68
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs138
-rw-r--r--OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs31
-rw-r--r--OpenSim/Services/HypergridService/UserAgentService.cs12
-rw-r--r--OpenSim/Services/Interfaces/IHypergridServices.cs5
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginService.cs2
-rw-r--r--prebuild.xml2
38 files changed, 963 insertions, 957 deletions
diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs
index 6ba022c..6731923 100644
--- a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs
+++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs
@@ -46,7 +46,7 @@ namespace OpenSim.OfflineIM
46{ 46{
47 public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService 47 public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService
48 { 48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 private const int MAX_IM = 25; 50 private const int MAX_IM = 25;
51 51
52 private XmlSerializer m_serializer; 52 private XmlSerializer m_serializer;
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs b/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs
index c0ca1e1..2c91328 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs
@@ -46,7 +46,7 @@ namespace OpenSim.Capabilities.Handlers
46{ 46{
47 public class FetchInventory2Handler 47 public class FetchInventory2Handler
48 { 48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 private IInventoryService m_inventoryService; 51 private IInventoryService m_inventoryService;
52 52
@@ -121,4 +121,4 @@ namespace OpenSim.Capabilities.Handlers
121 return llsdItem; 121 return llsdItem;
122 } 122 }
123 } 123 }
124} 124} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
index be1d02b..20495f6 100644
--- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -45,16 +45,16 @@ namespace OpenSim.Framework.Monitoring
45 sb.Append(Environment.NewLine); 45 sb.Append(Environment.NewLine);
46 46
47 sb.AppendFormat( 47 sb.AppendFormat(
48 "Allocated to OpenSim objects: {0} MB\n", 48 "Heap allocated to OpenSim : {0} MB\n",
49 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); 49 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
50 50
51 sb.AppendFormat( 51 sb.AppendFormat(
52 "OpenSim last object memory churn : {0} MB/s\n", 52 "Last heap allocation rate : {0} MB/s\n",
53 Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3)); 53 Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
54 54
55 sb.AppendFormat( 55 sb.AppendFormat(
56 "OpenSim average object memory churn : {0} MB/s\n", 56 "Average heap allocation rate: {0} MB/s\n",
57 Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); 57 Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
58 58
59 sb.AppendFormat( 59 sb.AppendFormat(
60 "Process memory : {0} MB\n", 60 "Process memory : {0} MB\n",
diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
index c6010cd..c474622 100644
--- a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
+++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
@@ -60,17 +60,17 @@ namespace OpenSim.Framework.Monitoring
60 private static bool m_enabled; 60 private static bool m_enabled;
61 61
62 /// <summary> 62 /// <summary>
63 /// Last memory churn in bytes per millisecond. 63 /// Average heap allocation rate in bytes per millisecond.
64 /// </summary> 64 /// </summary>
65 public static double AverageMemoryChurn 65 public static double AverageHeapAllocationRate
66 { 66 {
67 get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } 67 get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
68 } 68 }
69 69
70 /// <summary> 70 /// <summary>
71 /// Average memory churn in bytes per millisecond. 71 /// Last heap allocation in bytes
72 /// </summary> 72 /// </summary>
73 public static double LastMemoryChurn 73 public static double LastHeapAllocationRate
74 { 74 {
75 get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; } 75 get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; }
76 } 76 }
diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
new file mode 100644
index 0000000..ac0f0bc
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
@@ -0,0 +1,349 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Diagnostics;
31using System.Linq;
32using System.Net.NetworkInformation;
33using System.Text;
34using System.Threading;
35using log4net;
36using Nini.Config;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework;
39
40namespace OpenSim.Framework.Monitoring
41{
42 public class ServerStatsCollector
43 {
44 private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
45 private readonly string LogHeader = "[SERVER STATS]";
46
47 public bool Enabled = false;
48 private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>();
49
50 public readonly string CategoryServer = "server";
51
52 public readonly string ContainerThreadpool = "threadpool";
53 public readonly string ContainerProcessor = "processor";
54 public readonly string ContainerMemory = "memory";
55 public readonly string ContainerNetwork = "network";
56 public readonly string ContainerProcess = "process";
57
58 public string NetworkInterfaceTypes = "Ethernet";
59
60 readonly int performanceCounterSampleInterval = 500;
61// int lastperformanceCounterSampleTime = 0;
62
63 private class PerfCounterControl
64 {
65 public PerformanceCounter perfCounter;
66 public int lastFetch;
67 public string name;
68 public PerfCounterControl(PerformanceCounter pPc)
69 : this(pPc, String.Empty)
70 {
71 }
72 public PerfCounterControl(PerformanceCounter pPc, string pName)
73 {
74 perfCounter = pPc;
75 lastFetch = 0;
76 name = pName;
77 }
78 }
79
80 PerfCounterControl processorPercentPerfCounter = null;
81
82 // IRegionModuleBase.Initialize
83 public void Initialise(IConfigSource source)
84 {
85 IConfig cfg = source.Configs["Monitoring"];
86
87 if (cfg != null)
88 Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
89
90 if (Enabled)
91 {
92 NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
93 }
94 }
95
96 public void Start()
97 {
98 if (RegisteredStats.Count == 0)
99 RegisterServerStats();
100 }
101
102 public void Close()
103 {
104 if (RegisteredStats.Count > 0)
105 {
106 foreach (Stat stat in RegisteredStats.Values)
107 {
108 StatsManager.DeregisterStat(stat);
109 stat.Dispose();
110 }
111 RegisteredStats.Clear();
112 }
113 }
114
115 private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act)
116 {
117 MakeStat(pName, pDesc, pUnit, pContainer, act, MeasuresOfInterest.None);
118 }
119
120 private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act, MeasuresOfInterest moi)
121 {
122 string desc = pDesc;
123 if (desc == null)
124 desc = pName;
125 Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, moi, act, StatVerbosity.Debug);
126 StatsManager.RegisterStat(stat);
127 RegisteredStats.Add(pName, stat);
128 }
129
130 public void RegisterServerStats()
131 {
132// lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
133 PerformanceCounter tempPC;
134 Stat tempStat;
135 string tempName;
136
137 try
138 {
139 tempName = "CPUPercent";
140 tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
141 processorPercentPerfCounter = new PerfCounterControl(tempPC);
142 // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
143 tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
144 StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); },
145 StatVerbosity.Info);
146 StatsManager.RegisterStat(tempStat);
147 RegisteredStats.Add(tempName, tempStat);
148
149 MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,
150 (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
151
152 MakeStat("UserProcessorTime", null, "sec", ContainerProcessor,
153 (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
154
155 MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor,
156 (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
157
158 MakeStat("Threads", null, "threads", ContainerProcessor,
159 (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
160 }
161 catch (Exception e)
162 {
163 m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e);
164 }
165
166 MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool,
167 s =>
168 {
169 int workerThreads, iocpThreads;
170 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
171 s.Value = workerThreads;
172 });
173
174 MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool,
175 s =>
176 {
177 int workerThreads, iocpThreads;
178 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
179 s.Value = iocpThreads;
180 });
181
182 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool && Util.GetSmartThreadPoolInfo() != null)
183 {
184 MakeStat("STPMaxThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxThreads);
185 MakeStat("STPMinThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MinThreads);
186 MakeStat("STPConcurrency", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxConcurrentWorkItems);
187 MakeStat("STPActiveThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().ActiveThreads);
188 MakeStat("STPInUseThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().InUseThreads);
189 MakeStat("STPWorkItemsWaiting", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().WaitingCallbacks);
190 }
191
192 MakeStat(
193 "HTTPRequestsMade",
194 "Number of outbound HTTP requests made",
195 "requests",
196 ContainerNetwork,
197 s => s.Value = WebUtil.RequestNumber,
198 MeasuresOfInterest.AverageChangeOverTime);
199
200 try
201 {
202 List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
203
204 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
205 foreach (NetworkInterface nic in nics)
206 {
207 if (nic.OperationalStatus != OperationalStatus.Up)
208 continue;
209
210 string nicInterfaceType = nic.NetworkInterfaceType.ToString();
211 if (!okInterfaceTypes.Contains(nicInterfaceType))
212 {
213 m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.",
214 LogHeader, nic.Name, nicInterfaceType);
215 m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}",
216 LogHeader, NetworkInterfaceTypes);
217 continue;
218 }
219
220 if (nic.Supports(NetworkInterfaceComponent.IPv4))
221 {
222 IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
223 if (nicStats != null)
224 {
225 MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork,
226 (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
227 MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork,
228 (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
229 MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork,
230 (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
231 }
232 }
233 // TODO: add IPv6 (it may actually happen someday)
234 }
235 }
236 catch (Exception e)
237 {
238 m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
239 }
240
241 MakeStat("ProcessMemory", null, "MB", ContainerMemory,
242 (s) => { s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d, 3); });
243 MakeStat("HeapMemory", null, "MB", ContainerMemory,
244 (s) => { s.Value = Math.Round(GC.GetTotalMemory(false) / 1024d / 1024d, 3); });
245 MakeStat("LastHeapAllocationRate", null, "MB/sec", ContainerMemory,
246 (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
247 MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory,
248 (s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
249 }
250
251 // Notes on performance counters:
252 // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx
253 // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
254 // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
255 private delegate double PerfCounterNextValue();
256 private void GetNextValue(Stat stat, PerfCounterControl perfControl)
257 {
258 GetNextValue(stat, perfControl, 1.0);
259 }
260 private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
261 {
262 if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
263 {
264 if (perfControl != null && perfControl.perfCounter != null)
265 {
266 try
267 {
268 // Kludge for factor to run double duty. If -1, subtract the value from one
269 if (factor == -1)
270 stat.Value = 1 - perfControl.perfCounter.NextValue();
271 else
272 stat.Value = perfControl.perfCounter.NextValue() / factor;
273 }
274 catch (Exception e)
275 {
276 m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
277 }
278 perfControl.lastFetch = Util.EnvironmentTickCount();
279 }
280 }
281 }
282
283 // Lookup the nic that goes with this stat and set the value by using a fetch action.
284 // Not sure about closure with delegates inside delegates.
285 private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
286 private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor)
287 {
288 // Get the one nic that has the name of this stat
289 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
290 (network) => network.Name == stat.Description);
291 try
292 {
293 foreach (NetworkInterface nic in nics)
294 {
295 IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
296 if (intrStats != null)
297 {
298 double newVal = Math.Round(getter(intrStats) / factor, 3);
299 stat.Value = newVal;
300 }
301 break;
302 }
303 }
304 catch
305 {
306 // There are times interfaces go away so we just won't update the stat for this
307 m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
308 }
309 }
310 }
311
312 public class ServerStatsAggregator : Stat
313 {
314 public ServerStatsAggregator(
315 string shortName,
316 string name,
317 string description,
318 string unitName,
319 string category,
320 string container
321 )
322 : base(
323 shortName,
324 name,
325 description,
326 unitName,
327 category,
328 container,
329 StatType.Push,
330 MeasuresOfInterest.None,
331 null,
332 StatVerbosity.Info)
333 {
334 }
335 public override string ToConsoleString()
336 {
337 StringBuilder sb = new StringBuilder();
338
339 return sb.ToString();
340 }
341
342 public override OSDMap ToOSDMap()
343 {
344 OSDMap ret = new OSDMap();
345
346 return ret;
347 }
348 }
349}
diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs
index 2e7665f..c57ee0c 100644
--- a/OpenSim/Framework/Monitoring/Stats/Stat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs
@@ -27,8 +27,10 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
30using System.Text; 32using System.Text;
31 33using log4net;
32using OpenMetaverse.StructuredData; 34using OpenMetaverse.StructuredData;
33 35
34namespace OpenSim.Framework.Monitoring 36namespace OpenSim.Framework.Monitoring
@@ -38,6 +40,10 @@ namespace OpenSim.Framework.Monitoring
38 /// </summary> 40 /// </summary>
39 public class Stat : IDisposable 41 public class Stat : IDisposable
40 { 42 {
43// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 public static readonly char[] DisallowedShortNameCharacters = { '.' };
46
41 /// <summary> 47 /// <summary>
42 /// Category of this stat (e.g. cache, scene, etc). 48 /// Category of this stat (e.g. cache, scene, etc).
43 /// </summary> 49 /// </summary>
@@ -95,7 +101,7 @@ namespace OpenSim.Framework.Monitoring
95 /// <remarks> 101 /// <remarks>
96 /// Will be null if no measures of interest require samples. 102 /// Will be null if no measures of interest require samples.
97 /// </remarks> 103 /// </remarks>
98 private static Queue<double> m_samples; 104 private Queue<double> m_samples;
99 105
100 /// <summary> 106 /// <summary>
101 /// Maximum number of statistical samples. 107 /// Maximum number of statistical samples.
@@ -162,6 +168,12 @@ namespace OpenSim.Framework.Monitoring
162 throw new Exception( 168 throw new Exception(
163 string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category)); 169 string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
164 170
171 foreach (char c in DisallowedShortNameCharacters)
172 {
173 if (shortName.IndexOf(c) != -1)
174 throw new Exception(string.Format("Stat name {0} cannot contain character {1}", shortName, c));
175 }
176
165 ShortName = shortName; 177 ShortName = shortName;
166 Name = name; 178 Name = name;
167 Description = description; 179 Description = description;
@@ -204,6 +216,8 @@ namespace OpenSim.Framework.Monitoring
204 if (m_samples.Count >= m_maxSamples) 216 if (m_samples.Count >= m_maxSamples)
205 m_samples.Dequeue(); 217 m_samples.Dequeue();
206 218
219// m_log.DebugFormat("[STAT]: Recording value {0} for {1}", newValue, Name);
220
207 m_samples.Enqueue(newValue); 221 m_samples.Enqueue(newValue);
208 } 222 }
209 } 223 }
@@ -242,6 +256,10 @@ namespace OpenSim.Framework.Monitoring
242 256
243 lock (m_samples) 257 lock (m_samples)
244 { 258 {
259// m_log.DebugFormat(
260// "[STAT]: Samples for {0} are {1}",
261// Name, string.Join(",", m_samples.Select(s => s.ToString()).ToArray()));
262
245 foreach (double s in m_samples) 263 foreach (double s in m_samples)
246 { 264 {
247 if (lastSample != null) 265 if (lastSample != null)
@@ -253,7 +271,7 @@ namespace OpenSim.Framework.Monitoring
253 271
254 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1; 272 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1;
255 273
256 sb.AppendFormat(", {0:0.##}{1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName); 274 sb.AppendFormat(", {0:0.##} {1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName);
257 } 275 }
258 } 276 }
259 } 277 }
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 24db6d4..12d3a75 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
30using System.Text; 31using System.Text;
31 32
32namespace OpenSim.Framework.Monitoring 33namespace OpenSim.Framework.Monitoring
@@ -54,13 +55,13 @@ namespace OpenSim.Framework.Monitoring
54 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats 55 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
55 = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>(); 56 = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>();
56 57
57 private static AssetStatsCollector assetStats; 58// private static AssetStatsCollector assetStats;
58 private static UserStatsCollector userStats; 59// private static UserStatsCollector userStats;
59 private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); 60// private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
60 61
61 public static AssetStatsCollector AssetStats { get { return assetStats; } } 62// public static AssetStatsCollector AssetStats { get { return assetStats; } }
62 public static UserStatsCollector UserStats { get { return userStats; } } 63// public static UserStatsCollector UserStats { get { return userStats; } }
63 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } 64 public static SimExtraStatsCollector SimExtraStats { get; set; }
64 65
65 public static void RegisterConsoleCommands(ICommandConsole console) 66 public static void RegisterConsoleCommands(ICommandConsole console)
66 { 67 {
@@ -68,12 +69,14 @@ namespace OpenSim.Framework.Monitoring
68 "General", 69 "General",
69 false, 70 false,
70 "show stats", 71 "show stats",
71 "show stats [list|all|<category>]", 72 "show stats [list|all|(<category>[.<container>])+",
72 "Show statistical information for this server", 73 "Show statistical information for this server",
73 "If no final argument is specified then legacy statistics information is currently shown.\n" 74 "If no final argument is specified then legacy statistics information is currently shown.\n"
74 + "If list is specified then statistic categories are shown.\n" 75 + "'list' argument will show statistic categories.\n"
75 + "If all is specified then all registered statistics are shown.\n" 76 + "'all' will show all statistics.\n"
76 + "If a category name is specified then only statistics from that category are shown.\n" 77 + "A <category> name will show statistics from that category.\n"
78 + "A <category>.<container> name will show statistics from that category in that container.\n"
79 + "More than one name can be given separated by spaces.\n"
77 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", 80 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
78 HandleShowStatsCommand); 81 HandleShowStatsCommand);
79 } 82 }
@@ -84,43 +87,47 @@ namespace OpenSim.Framework.Monitoring
84 87
85 if (cmd.Length > 2) 88 if (cmd.Length > 2)
86 { 89 {
87 var categoryName = cmd[2]; 90 foreach (string name in cmd.Skip(2))
88 var containerName = cmd.Length > 3 ? cmd[3] : String.Empty;
89
90 if (categoryName == AllSubCommand)
91 { 91 {
92 foreach (var category in RegisteredStats.Values) 92 string[] components = name.Split('.');
93
94 string categoryName = components[0];
95 string containerName = components.Length > 1 ? components[1] : null;
96
97 if (categoryName == AllSubCommand)
93 { 98 {
94 OutputCategoryStatsToConsole(con, category); 99 OutputAllStatsToConsole(con);
95 } 100 }
96 } 101 else if (categoryName == ListSubCommand)
97 else if (categoryName == ListSubCommand)
98 {
99 con.Output("Statistic categories available are:");
100 foreach (string category in RegisteredStats.Keys)
101 con.OutputFormat(" {0}", category);
102 }
103 else
104 {
105 SortedDictionary<string, SortedDictionary<string, Stat>> category;
106 if (!RegisteredStats.TryGetValue(categoryName, out category))
107 { 102 {
108 con.OutputFormat("No such category as {0}", categoryName); 103 con.Output("Statistic categories available are:");
104 foreach (string category in RegisteredStats.Keys)
105 con.OutputFormat(" {0}", category);
109 } 106 }
110 else 107 else
111 { 108 {
112 if (String.IsNullOrEmpty(containerName)) 109 SortedDictionary<string, SortedDictionary<string, Stat>> category;
113 OutputCategoryStatsToConsole(con, category); 110 if (!RegisteredStats.TryGetValue(categoryName, out category))
111 {
112 con.OutputFormat("No such category as {0}", categoryName);
113 }
114 else 114 else
115 { 115 {
116 SortedDictionary<string, Stat> container; 116 if (String.IsNullOrEmpty(containerName))
117 if (category.TryGetValue(containerName, out container))
118 { 117 {
119 OutputContainerStatsToConsole(con, container); 118 OutputCategoryStatsToConsole(con, category);
120 } 119 }
121 else 120 else
122 { 121 {
123 con.OutputFormat("No such container {0} in category {1}", containerName, categoryName); 122 SortedDictionary<string, Stat> container;
123 if (category.TryGetValue(containerName, out container))
124 {
125 OutputContainerStatsToConsole(con, container);
126 }
127 else
128 {
129 con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
130 }
124 } 131 }
125 } 132 }
126 } 133 }
@@ -129,7 +136,18 @@ namespace OpenSim.Framework.Monitoring
129 else 136 else
130 { 137 {
131 // Legacy 138 // Legacy
132 con.Output(SimExtraStats.Report()); 139 if (SimExtraStats != null)
140 con.Output(SimExtraStats.Report());
141 else
142 OutputAllStatsToConsole(con);
143 }
144 }
145
146 private static void OutputAllStatsToConsole(ICommandConsole con)
147 {
148 foreach (var category in RegisteredStats.Values)
149 {
150 OutputCategoryStatsToConsole(con, category);
133 } 151 }
134 } 152 }
135 153
@@ -150,27 +168,27 @@ namespace OpenSim.Framework.Monitoring
150 } 168 }
151 } 169 }
152 170
153 /// <summary> 171// /// <summary>
154 /// Start collecting statistics related to assets. 172// /// Start collecting statistics related to assets.
155 /// Should only be called once. 173// /// Should only be called once.
156 /// </summary> 174// /// </summary>
157 public static AssetStatsCollector StartCollectingAssetStats() 175// public static AssetStatsCollector StartCollectingAssetStats()
158 { 176// {
159 assetStats = new AssetStatsCollector(); 177// assetStats = new AssetStatsCollector();
160 178//
161 return assetStats; 179// return assetStats;
162 } 180// }
163 181//
164 /// <summary> 182// /// <summary>
165 /// Start collecting statistics related to users. 183// /// Start collecting statistics related to users.
166 /// Should only be called once. 184// /// Should only be called once.
167 /// </summary> 185// /// </summary>
168 public static UserStatsCollector StartCollectingUserStats() 186// public static UserStatsCollector StartCollectingUserStats()
169 { 187// {
170 userStats = new UserStatsCollector(); 188// userStats = new UserStatsCollector();
171 189//
172 return userStats; 190// return userStats;
173 } 191// }
174 192
175 /// <summary> 193 /// <summary>
176 /// Registers a statistic. 194 /// Registers a statistic.
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 035b3ad..4ab6908 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -86,26 +86,23 @@ namespace OpenSim.Framework.Servers
86 /// </summary> 86 /// </summary>
87 protected virtual void StartupSpecific() 87 protected virtual void StartupSpecific()
88 { 88 {
89 if (m_console == null) 89 StatsManager.SimExtraStats = new SimExtraStatsCollector();
90 return;
91
92 RegisterCommonCommands(); 90 RegisterCommonCommands();
93 91 RegisterCommonComponents(Config);
94 m_console.Commands.AddCommand("General", false, "quit", 92 }
95 "quit", 93
96 "Quit the application", HandleQuit); 94 protected override void ShutdownSpecific()
95 {
96 m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
97
98 RemovePIDFile();
99
100 base.ShutdownSpecific();
97 101
98 m_console.Commands.AddCommand("General", false, "shutdown", 102 Environment.Exit(0);
99 "shutdown",
100 "Quit the application", HandleQuit);
101 } 103 }
102 104
103 /// <summary> 105 /// <summary>
104 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
105 /// </summary>
106 public virtual void ShutdownSpecific() {}
107
108 /// <summary>
109 /// Provides a list of help topics that are available. Overriding classes should append their topics to the 106 /// Provides a list of help topics that are available. Overriding classes should append their topics to the
110 /// information returned when the base method is called. 107 /// information returned when the base method is called.
111 /// </summary> 108 /// </summary>
@@ -143,25 +140,8 @@ namespace OpenSim.Framework.Servers
143 timeTaken.Minutes, timeTaken.Seconds); 140 timeTaken.Minutes, timeTaken.Seconds);
144 } 141 }
145 142
146 /// <summary> 143 public string osSecret
147 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
148 /// </summary>
149 public virtual void Shutdown()
150 { 144 {
151 ShutdownSpecific();
152
153 m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
154 RemovePIDFile();
155
156 Environment.Exit(0);
157 }
158
159 private void HandleQuit(string module, string[] args)
160 {
161 Shutdown();
162 }
163
164 public string osSecret {
165 // Secret uuid for the simulator 145 // Secret uuid for the simulator
166 get { return m_osSecret; } 146 get { return m_osSecret; }
167 } 147 }
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 96a030b..40b8c5c 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -54,7 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); 55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
56 56
57
58 /// <summary> 57 /// <summary>
59 /// This is a pending websocket request before it got an sucessful upgrade response. 58 /// This is a pending websocket request before it got an sucessful upgrade response.
60 /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to 59 /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to
@@ -81,6 +80,11 @@ namespace OpenSim.Framework.Servers.HttpServer
81 /// </remarks> 80 /// </remarks>
82 public int RequestNumber { get; private set; } 81 public int RequestNumber { get; private set; }
83 82
83 /// <summary>
84 /// Statistic for holding number of requests processed.
85 /// </summary>
86 private Stat m_requestsProcessedStat;
87
84 private volatile int NotSocketErrors = 0; 88 private volatile int NotSocketErrors = 0;
85 public volatile bool HTTPDRunning = false; 89 public volatile bool HTTPDRunning = false;
86 90
@@ -436,9 +440,8 @@ namespace OpenSim.Framework.Servers.HttpServer
436 } 440 }
437 } 441 }
438 442
439 public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request) 443 private void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
440 { 444 {
441
442 OSHttpRequest req = new OSHttpRequest(context, request); 445 OSHttpRequest req = new OSHttpRequest(context, request);
443 WebSocketRequestDelegate dWebSocketRequestDelegate = null; 446 WebSocketRequestDelegate dWebSocketRequestDelegate = null;
444 lock (m_WebSocketHandlers) 447 lock (m_WebSocketHandlers)
@@ -454,8 +457,7 @@ namespace OpenSim.Framework.Servers.HttpServer
454 457
455 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); 458 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
456 resp.ReuseContext = true; 459 resp.ReuseContext = true;
457 HandleRequest(req, resp); 460 HandleRequest(req, resp);
458
459 461
460 // !!!HACK ALERT!!! 462 // !!!HACK ALERT!!!
461 // There seems to be a bug in the underlying http code that makes subsequent requests 463 // There seems to be a bug in the underlying http code that makes subsequent requests
@@ -1824,6 +1826,21 @@ namespace OpenSim.Framework.Servers.HttpServer
1824 // useful without inbound HTTP. 1826 // useful without inbound HTTP.
1825 throw e; 1827 throw e;
1826 } 1828 }
1829
1830 m_requestsProcessedStat
1831 = new Stat(
1832 "HTTPRequestsServed",
1833 "Number of inbound HTTP requests processed",
1834 "",
1835 "requests",
1836 "httpserver",
1837 Port.ToString(),
1838 StatType.Pull,
1839 MeasuresOfInterest.AverageChangeOverTime,
1840 stat => stat.Value = RequestNumber,
1841 StatVerbosity.Debug);
1842
1843 StatsManager.RegisterStat(m_requestsProcessedStat);
1827 } 1844 }
1828 1845
1829 public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err) 1846 public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err)
@@ -1854,6 +1871,9 @@ namespace OpenSim.Framework.Servers.HttpServer
1854 public void Stop() 1871 public void Stop()
1855 { 1872 {
1856 HTTPDRunning = false; 1873 HTTPDRunning = false;
1874
1875 StatsManager.DeregisterStat(m_requestsProcessedStat);
1876
1857 try 1877 try
1858 { 1878 {
1859 m_PollServiceManager.Stop(); 1879 m_PollServiceManager.Stop();
diff --git a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
index ee96b47..de89e2e 100644
--- a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
@@ -75,7 +75,7 @@ namespace OpenSim.Framework.Servers.HttpServer
75 /// <summary> 75 /// <summary>
76 /// This is a regular HTTP Request... This may be removed in the future. 76 /// This is a regular HTTP Request... This may be removed in the future.
77 /// </summary> 77 /// </summary>
78 public event RegularHttpRequestDelegate OnRegularHttpRequest; 78// public event RegularHttpRequestDelegate OnRegularHttpRequest;
79 79
80 /// <summary> 80 /// <summary>
81 /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired 81 /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired
@@ -304,15 +304,14 @@ namespace OpenSim.Framework.Servers.HttpServer
304 if (d != null) 304 if (d != null)
305 d(this, new UpgradeCompletedEventArgs()); 305 d(this, new UpgradeCompletedEventArgs());
306 } 306 }
307 catch (IOException fail) 307 catch (IOException)
308 { 308 {
309 Close(string.Empty); 309 Close(string.Empty);
310 } 310 }
311 catch (ObjectDisposedException fail) 311 catch (ObjectDisposedException)
312 { 312 {
313 Close(string.Empty); 313 Close(string.Empty);
314 } 314 }
315
316 } 315 }
317 316
318 /// <summary> 317 /// <summary>
@@ -414,8 +413,6 @@ namespace OpenSim.Framework.Servers.HttpServer
414 _socketState.Header = pheader; 413 _socketState.Header = pheader;
415 } 414 }
416 415
417
418
419 if (_socketState.FrameComplete) 416 if (_socketState.FrameComplete)
420 { 417 {
421 ProcessFrame(_socketState); 418 ProcessFrame(_socketState);
@@ -424,7 +421,6 @@ namespace OpenSim.Framework.Servers.HttpServer
424 _socketState.ExpectedBytes = 0; 421 _socketState.ExpectedBytes = 0;
425 422
426 } 423 }
427
428 } 424 }
429 } 425 }
430 else 426 else
@@ -457,8 +453,7 @@ namespace OpenSim.Framework.Servers.HttpServer
457 _socketState.ReceivedBytes.Clear(); 453 _socketState.ReceivedBytes.Clear();
458 _socketState.ExpectedBytes = 0; 454 _socketState.ExpectedBytes = 0;
459 // do some processing 455 // do some processing
460 } 456 }
461
462 } 457 }
463 } 458 }
464 if (offset > 0) 459 if (offset > 0)
@@ -477,13 +472,12 @@ namespace OpenSim.Framework.Servers.HttpServer
477 { 472 {
478 // We can't read the stream anymore... 473 // We can't read the stream anymore...
479 } 474 }
480
481 } 475 }
482 catch (IOException fail) 476 catch (IOException)
483 { 477 {
484 Close(string.Empty); 478 Close(string.Empty);
485 } 479 }
486 catch (ObjectDisposedException fail) 480 catch (ObjectDisposedException)
487 { 481 {
488 Close(string.Empty); 482 Close(string.Empty);
489 } 483 }
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
index 2c4a687..029b848 100644
--- a/OpenSim/Framework/Servers/ServerBase.cs
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -62,6 +62,8 @@ namespace OpenSim.Framework.Servers
62 62
63 protected string m_pidFile = String.Empty; 63 protected string m_pidFile = String.Empty;
64 64
65 protected ServerStatsCollector m_serverStatsCollector;
66
65 /// <summary> 67 /// <summary>
66 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc. 68 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
67 /// </summary> 69 /// </summary>
@@ -259,6 +261,25 @@ namespace OpenSim.Framework.Servers
259 "force gc", 261 "force gc",
260 "Manually invoke runtime garbage collection. For debugging purposes", 262 "Manually invoke runtime garbage collection. For debugging purposes",
261 HandleForceGc); 263 HandleForceGc);
264
265 m_console.Commands.AddCommand(
266 "General", false, "quit",
267 "quit",
268 "Quit the application", (mod, args) => Shutdown());
269
270 m_console.Commands.AddCommand(
271 "General", false, "shutdown",
272 "shutdown",
273 "Quit the application", (mod, args) => Shutdown());
274
275 StatsManager.RegisterConsoleCommands(m_console);
276 }
277
278 public void RegisterCommonComponents(IConfigSource configSource)
279 {
280 m_serverStatsCollector = new ServerStatsCollector();
281 m_serverStatsCollector.Initialise(configSource);
282 m_serverStatsCollector.Start();
262 } 283 }
263 284
264 private void HandleForceGc(string module, string[] args) 285 private void HandleForceGc(string module, string[] args)
@@ -646,7 +667,68 @@ namespace OpenSim.Framework.Servers
646 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); 667 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
647 668
648 sb.Append("Main threadpool (excluding script engine pools)\n"); 669 sb.Append("Main threadpool (excluding script engine pools)\n");
649 sb.Append(Util.GetThreadPoolReport()); 670 sb.Append(GetThreadPoolReport());
671
672 return sb.ToString();
673 }
674
675 /// <summary>
676 /// Get a thread pool report.
677 /// </summary>
678 /// <returns></returns>
679 public static string GetThreadPoolReport()
680 {
681 string threadPoolUsed = null;
682 int maxThreads = 0;
683 int minThreads = 0;
684 int allocatedThreads = 0;
685 int inUseThreads = 0;
686 int waitingCallbacks = 0;
687 int completionPortThreads = 0;
688
689 StringBuilder sb = new StringBuilder();
690 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
691 {
692 STPInfo stpi = Util.GetSmartThreadPoolInfo();
693
694 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
695 if (stpi != null)
696 {
697 threadPoolUsed = "SmartThreadPool";
698 maxThreads = stpi.MaxThreads;
699 minThreads = stpi.MinThreads;
700 inUseThreads = stpi.InUseThreads;
701 allocatedThreads = stpi.ActiveThreads;
702 waitingCallbacks = stpi.WaitingCallbacks;
703 }
704 }
705 else if (
706 Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem
707 || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
708 {
709 threadPoolUsed = "BuiltInThreadPool";
710 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
711 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
712 int availableThreads;
713 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
714 inUseThreads = maxThreads - availableThreads;
715 allocatedThreads = -1;
716 waitingCallbacks = -1;
717 }
718
719 if (threadPoolUsed != null)
720 {
721 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
722 sb.AppendFormat("Max threads : {0}\n", maxThreads);
723 sb.AppendFormat("Min threads : {0}\n", minThreads);
724 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
725 sb.AppendFormat("In use threads : {0}\n", inUseThreads);
726 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
727 }
728 else
729 {
730 sb.AppendFormat("Thread pool not used\n");
731 }
650 732
651 return sb.ToString(); 733 return sb.ToString();
652 } 734 }
@@ -698,5 +780,16 @@ namespace OpenSim.Framework.Servers
698 if (m_console != null) 780 if (m_console != null)
699 m_console.OutputFormat(format, components); 781 m_console.OutputFormat(format, components);
700 } 782 }
783
784 public virtual void Shutdown()
785 {
786 m_serverStatsCollector.Close();
787 ShutdownSpecific();
788 }
789
790 /// <summary>
791 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
792 /// </summary>
793 protected virtual void ShutdownSpecific() {}
701 } 794 }
702} \ No newline at end of file 795} \ No newline at end of file
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 7f0850f..ba6cc75 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -89,9 +89,30 @@ namespace OpenSim.Framework
89 } 89 }
90 90
91 /// <summary> 91 /// <summary>
92 /// Class for delivering SmartThreadPool statistical information
93 /// </summary>
94 /// <remarks>
95 /// We do it this way so that we do not directly expose STP.
96 /// </remarks>
97 public class STPInfo
98 {
99 public string Name { get; set; }
100 public STPStartInfo STPStartInfo { get; set; }
101 public WIGStartInfo WIGStartInfo { get; set; }
102 public bool IsIdle { get; set; }
103 public bool IsShuttingDown { get; set; }
104 public int MaxThreads { get; set; }
105 public int MinThreads { get; set; }
106 public int InUseThreads { get; set; }
107 public int ActiveThreads { get; set; }
108 public int WaitingCallbacks { get; set; }
109 public int MaxConcurrentWorkItems { get; set; }
110 }
111
112 /// <summary>
92 /// Miscellaneous utility functions 113 /// Miscellaneous utility functions
93 /// </summary> 114 /// </summary>
94 public class Util 115 public static class Util
95 { 116 {
96 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 117 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
97 118
@@ -1852,74 +1873,31 @@ namespace OpenSim.Framework
1852 } 1873 }
1853 1874
1854 /// <summary> 1875 /// <summary>
1855 /// Get a thread pool report. 1876 /// Get information about the current state of the smart thread pool.
1856 /// </summary> 1877 /// </summary>
1857 /// <returns></returns> 1878 /// <returns>
1858 public static string GetThreadPoolReport() 1879 /// null if this isn't the pool being used for non-scriptengine threads.
1880 /// </returns>
1881 public static STPInfo GetSmartThreadPoolInfo()
1859 { 1882 {
1860 string threadPoolUsed = null; 1883 if (m_ThreadPool == null)
1861 int maxThreads = 0; 1884 return null;
1862 int minThreads = 0;
1863 int allocatedThreads = 0;
1864 int inUseThreads = 0;
1865 int waitingCallbacks = 0;
1866 int completionPortThreads = 0;
1867
1868 StringBuilder sb = new StringBuilder();
1869 if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
1870 {
1871 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
1872 if (m_ThreadPool != null)
1873 {
1874 threadPoolUsed = "SmartThreadPool";
1875 maxThreads = m_ThreadPool.MaxThreads;
1876 minThreads = m_ThreadPool.MinThreads;
1877 inUseThreads = m_ThreadPool.InUseThreads;
1878 allocatedThreads = m_ThreadPool.ActiveThreads;
1879 waitingCallbacks = m_ThreadPool.WaitingCallbacks;
1880 }
1881 }
1882 else if (
1883 FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
1884 || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
1885 {
1886 threadPoolUsed = "BuiltInThreadPool";
1887 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
1888 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
1889 int availableThreads;
1890 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
1891 inUseThreads = maxThreads - availableThreads;
1892 allocatedThreads = -1;
1893 waitingCallbacks = -1;
1894 }
1895 1885
1896 if (threadPoolUsed != null) 1886 STPInfo stpi = new STPInfo();
1897 { 1887 stpi.Name = m_ThreadPool.Name;
1898 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed); 1888 stpi.STPStartInfo = m_ThreadPool.STPStartInfo;
1899 sb.AppendFormat("Max threads : {0}\n", maxThreads); 1889 stpi.IsIdle = m_ThreadPool.IsIdle;
1900 sb.AppendFormat("Min threads : {0}\n", minThreads); 1890 stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown;
1901 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString()); 1891 stpi.MaxThreads = m_ThreadPool.MaxThreads;
1902 sb.AppendFormat("In use threads : {0}\n", inUseThreads); 1892 stpi.MinThreads = m_ThreadPool.MinThreads;
1903 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString()); 1893 stpi.InUseThreads = m_ThreadPool.InUseThreads;
1904 } 1894 stpi.ActiveThreads = m_ThreadPool.ActiveThreads;
1905 else 1895 stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks;
1906 { 1896 stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency;
1907 sb.AppendFormat("Thread pool not used\n");
1908 }
1909 1897
1910 return sb.ToString(); 1898 return stpi;
1911 } 1899 }
1912 1900
1913// private static object SmartThreadPoolCallback(object o)
1914// {
1915// object[] array = (object[])o;
1916// WaitCallback callback = (WaitCallback)array[0];
1917// object obj = array[1];
1918//
1919// callback(obj);
1920// return null;
1921// }
1922
1923 #endregion FireAndForget Threading Pattern 1901 #endregion FireAndForget Threading Pattern
1924 1902
1925 /// <summary> 1903 /// <summary>
diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs
index c3e7ec2..e451aa8 100644
--- a/OpenSim/Region/Application/Application.cs
+++ b/OpenSim/Region/Application/Application.cs
@@ -124,6 +124,7 @@ namespace OpenSim
124 workerThreads = workerThreadsMax; 124 workerThreads = workerThreadsMax;
125 m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads); 125 m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads);
126 } 126 }
127
127 // Increase the number of IOCP threads available. 128 // Increase the number of IOCP threads available.
128 // Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17) 129 // Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17)
129 if (iocpThreads < iocpThreadsMin) 130 if (iocpThreads < iocpThreadsMin)
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 11dd052..9325b12 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -372,7 +372,7 @@ namespace OpenSim
372 "Unload a module", HandleModules); 372 "Unload a module", HandleModules);
373 } 373 }
374 374
375 public override void ShutdownSpecific() 375 protected override void ShutdownSpecific()
376 { 376 {
377 if (m_shutdownCommandsFile != String.Empty) 377 if (m_shutdownCommandsFile != String.Empty)
378 { 378 {
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index f9e0cf1..7ca87a3 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -231,10 +231,7 @@ namespace OpenSim
231 } 231 }
232 232
233 if (m_console != null) 233 if (m_console != null)
234 {
235 StatsManager.RegisterConsoleCommands(m_console);
236 AddPluginCommands(m_console); 234 AddPluginCommands(m_console);
237 }
238 } 235 }
239 236
240 protected virtual void AddPluginCommands(ICommandConsole console) 237 protected virtual void AddPluginCommands(ICommandConsole console)
@@ -880,7 +877,7 @@ namespace OpenSim
880 /// <summary> 877 /// <summary>
881 /// Performs any last-minute sanity checking and shuts down the region server 878 /// Performs any last-minute sanity checking and shuts down the region server
882 /// </summary> 879 /// </summary>
883 public override void ShutdownSpecific() 880 protected override void ShutdownSpecific()
884 { 881 {
885 if (proxyUrl.Length > 0) 882 if (proxyUrl.Length > 0)
886 { 883 {
@@ -900,6 +897,8 @@ namespace OpenSim
900 { 897 {
901 m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e); 898 m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e);
902 } 899 }
900
901 base.ShutdownSpecific();
903 } 902 }
904 903
905 /// <summary> 904 /// <summary>
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 2024018..0e3cd6b 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -34,6 +34,7 @@ using log4net;
34using Nini.Config; 34using Nini.Config;
35using Mono.Addins; 35using Mono.Addins;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
37using OpenSim.Framework; 38using OpenSim.Framework;
38using OpenSim.Framework.Monitoring; 39using OpenSim.Framework.Monitoring;
39using OpenSim.Framework.Servers; 40using OpenSim.Framework.Servers;
@@ -44,8 +45,6 @@ using OpenSim.Framework.Capabilities;
44using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
45using Caps = OpenSim.Framework.Capabilities.Caps; 46using Caps = OpenSim.Framework.Capabilities.Caps;
46using OpenSim.Capabilities.Handlers; 47using OpenSim.Capabilities.Handlers;
47using OpenMetaverse;
48using OpenMetaverse.StructuredData;
49 48
50namespace OpenSim.Region.ClientStack.Linden 49namespace OpenSim.Region.ClientStack.Linden
51{ 50{
@@ -64,7 +63,7 @@ namespace OpenSim.Region.ClientStack.Linden
64 public List<UUID> folders; 63 public List<UUID> folders;
65 } 64 }
66 65
67 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 66// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
68 67
69 private Scene m_scene; 68 private Scene m_scene;
70 69
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
index 556df30..b47ff54 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
@@ -33,6 +33,7 @@ using NUnit.Framework;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Packets; 34using OpenMetaverse.Packets;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Monitoring;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using OpenSim.Tests.Common; 38using OpenSim.Tests.Common;
38using OpenSim.Tests.Common.Mock; 39using OpenSim.Tests.Common.Mock;
@@ -69,6 +70,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
69 { 70 {
70 base.SetUp(); 71 base.SetUp();
71 m_scene = new SceneHelpers().SetupScene(); 72 m_scene = new SceneHelpers().SetupScene();
73 StatsManager.SimExtraStats = new SimExtraStatsCollector();
72 } 74 }
73 75
74 /// <summary> 76 /// <summary>
@@ -210,8 +212,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
210 212
211 ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID); 213 ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
212 Assert.That(spAfterAckTimeout, Is.Null); 214 Assert.That(spAfterAckTimeout, Is.Null);
213
214// TestHelpers.DisableLogging();
215 } 215 }
216 216
217// /// <summary> 217// /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 7d763fa..7f3d0a2 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -182,7 +182,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
182 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId); 182 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
183 183
184 if (msglist == null) 184 if (msglist == null)
185 {
185 m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list."); 186 m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list.");
187 return;
188 }
186 189
187 foreach (GridInstantMessage im in msglist) 190 foreach (GridInstantMessage im in msglist)
188 { 191 {
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 02ed1a0..630d1c3 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -53,8 +53,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
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 54
55 private int m_levelHGTeleport = 0; 55 private int m_levelHGTeleport = 0;
56 private string m_ThisHomeURI;
56 57
57 private GatekeeperServiceConnector m_GatekeeperConnector; 58 private GatekeeperServiceConnector m_GatekeeperConnector;
59 private IUserAgentService m_UAS;
58 60
59 protected bool m_RestrictAppearanceAbroad; 61 protected bool m_RestrictAppearanceAbroad;
60 protected string m_AccountName; 62 protected string m_AccountName;
@@ -143,6 +145,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
143 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); 145 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
144 } 146 }
145 } 147 }
148
149 moduleConfig = source.Configs["Hypergrid"];
150 if (moduleConfig != null)
151 {
152 m_ThisHomeURI = moduleConfig.GetString("HomeURI", string.Empty);
153 if (m_ThisHomeURI != string.Empty && !m_ThisHomeURI.EndsWith("/"))
154 m_ThisHomeURI += '/';
155 }
146 } 156 }
147 157
148 public override void AddRegion(Scene scene) 158 public override void AddRegion(Scene scene)
@@ -194,7 +204,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
194 base.RegionLoaded(scene); 204 base.RegionLoaded(scene);
195 205
196 if (m_Enabled) 206 if (m_Enabled)
207 {
197 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService); 208 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
209 m_UAS = scene.RequestModuleInterface<IUserAgentService>();
210 }
198 } 211 }
199 212
200 public override void RemoveRegion(Scene scene) 213 public override void RemoveRegion(Scene scene)
@@ -272,8 +285,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
272 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI")) 285 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI"))
273 { 286 {
274 string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString(); 287 string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString();
275 IUserAgentService connector = new UserAgentServiceConnector(userAgentDriver); 288 IUserAgentService connector;
276 bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason); 289
290 if (userAgentDriver.Equals(m_ThisHomeURI) && m_UAS != null)
291 connector = m_UAS;
292 else
293 connector = new UserAgentServiceConnector(userAgentDriver);
294
295 bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, false, out reason);
277 logout = success; // flag for later logout from this grid; this is an HG TP 296 logout = success; // flag for later logout from this grid; this is an HG TP
278 297
279 if (success) 298 if (success)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index b2a1b23..d120e11 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -194,7 +194,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
194 return false; 194 return false;
195 195
196 // Try local first 196 // Try local first
197 if (m_localBackend.IsLocalRegion(destination.RegionHandle)) 197 if (m_localBackend.IsLocalRegion(destination.RegionID))
198 return m_localBackend.UpdateAgent(destination, cAgentData); 198 return m_localBackend.UpdateAgent(destination, cAgentData);
199 199
200 return m_remoteConnector.UpdateAgent(destination, cAgentData); 200 return m_remoteConnector.UpdateAgent(destination, cAgentData);
@@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
206 return false; 206 return false;
207 207
208 // Try local first 208 // Try local first
209 if (m_localBackend.IsLocalRegion(destination.RegionHandle)) 209 if (m_localBackend.IsLocalRegion(destination.RegionID))
210 return m_localBackend.UpdateAgent(destination, cAgentData); 210 return m_localBackend.UpdateAgent(destination, cAgentData);
211 211
212 return m_remoteConnector.UpdateAgent(destination, cAgentData); 212 return m_remoteConnector.UpdateAgent(destination, cAgentData);
@@ -224,7 +224,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
224 return true; 224 return true;
225 225
226 // else do the remote thing 226 // else do the remote thing
227 if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) 227 if (!m_localBackend.IsLocalRegion(destination.RegionID))
228 return m_remoteConnector.RetrieveAgent(destination, id, out agent); 228 return m_remoteConnector.RetrieveAgent(destination, id, out agent);
229 229
230 return false; 230 return false;
@@ -273,7 +273,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
273 return true; 273 return true;
274 274
275 // else do the remote thing 275 // else do the remote thing
276 if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) 276 if (!m_localBackend.IsLocalRegion(destination.RegionID))
277 return m_remoteConnector.CloseAgent(destination, id); 277 return m_remoteConnector.CloseAgent(destination, id);
278 278
279 return false; 279 return false;
@@ -296,7 +296,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
296 } 296 }
297 297
298 // else do the remote thing 298 // else do the remote thing
299 if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) 299 if (!m_localBackend.IsLocalRegion(destination.RegionID))
300 return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall); 300 return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall);
301 301
302 return false; 302 return false;
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 8406442..e55c9ed 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -81,14 +81,14 @@ namespace OpenSim.Region.CoreModules.World.Land
81 81
82 set { m_landData = value; } 82 set { m_landData = value; }
83 } 83 }
84 84
85 public IPrimCounts PrimCounts { get; set; } 85 public IPrimCounts PrimCounts { get; set; }
86 86
87 public UUID RegionUUID 87 public UUID RegionUUID
88 { 88 {
89 get { return m_scene.RegionInfo.RegionID; } 89 get { return m_scene.RegionInfo.RegionID; }
90 } 90 }
91 91
92 public Vector3 StartPoint 92 public Vector3 StartPoint
93 { 93 {
94 get 94 get
@@ -101,11 +101,11 @@ namespace OpenSim.Region.CoreModules.World.Land
101 return new Vector3(x * 4, y * 4, 0); 101 return new Vector3(x * 4, y * 4, 0);
102 } 102 }
103 } 103 }
104 104
105 return new Vector3(-1, -1, -1); 105 return new Vector3(-1, -1, -1);
106 } 106 }
107 } 107 }
108 108
109 public Vector3 EndPoint 109 public Vector3 EndPoint
110 { 110 {
111 get 111 get
@@ -116,15 +116,15 @@ namespace OpenSim.Region.CoreModules.World.Land
116 { 116 {
117 if (LandBitmap[x, y]) 117 if (LandBitmap[x, y])
118 { 118 {
119 return new Vector3(x * 4, y * 4, 0); 119 return new Vector3(x * 4 + 4, y * 4 + 4, 0);
120 } 120 }
121 } 121 }
122 } 122 }
123 123
124 return new Vector3(-1, -1, -1); 124 return new Vector3(-1, -1, -1);
125 } 125 }
126 } 126 }
127 127
128 #region Constructors 128 #region Constructors
129 129
130 public LandObject(UUID owner_id, bool is_group_owned, Scene scene) 130 public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 6c79b13..1e4d558 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -326,7 +326,7 @@ namespace OpenSim.Region.Framework.Scenes
326 // Update item with new asset 326 // Update item with new asset
327 item.AssetID = asset.FullID; 327 item.AssetID = asset.FullID;
328 if (group.UpdateInventoryItem(item)) 328 if (group.UpdateInventoryItem(item))
329 remoteClient.SendAgentAlertMessage("Script saved", false); 329 remoteClient.SendAlertMessage("Script saved");
330 330
331 part.SendPropertiesToClient(remoteClient); 331 part.SendPropertiesToClient(remoteClient);
332 332
@@ -342,7 +342,7 @@ namespace OpenSim.Region.Framework.Scenes
342 } 342 }
343 else 343 else
344 { 344 {
345 remoteClient.SendAgentAlertMessage("Script saved", false); 345 remoteClient.SendAlertMessage("Script saved");
346 } 346 }
347 347
348 // Tell anyone managing scripts that a script has been reloaded/changed 348 // Tell anyone managing scripts that a script has been reloaded/changed
@@ -1616,11 +1616,11 @@ namespace OpenSim.Region.Framework.Scenes
1616 remoteClient, part, transactionID, currentItem); 1616 remoteClient, part, transactionID, currentItem);
1617 1617
1618 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1618 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1619 remoteClient.SendAgentAlertMessage("Notecard saved", false); 1619 remoteClient.SendAlertMessage("Notecard saved");
1620 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1620 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1621 remoteClient.SendAgentAlertMessage("Script saved", false); 1621 remoteClient.SendAlertMessage("Script saved");
1622 else 1622 else
1623 remoteClient.SendAgentAlertMessage("Item saved", false); 1623 remoteClient.SendAlertMessage("Item saved");
1624 } 1624 }
1625 1625
1626 // Base ALWAYS has move 1626 // Base ALWAYS has move
diff --git a/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs b/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs
deleted file mode 100644
index 6e74ce0..0000000
--- a/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs
+++ /dev/null
@@ -1,339 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Diagnostics;
31using System.Linq;
32using System.Net.NetworkInformation;
33using System.Text;
34using System.Threading;
35
36using log4net;
37using Mono.Addins;
38using Nini.Config;
39
40using OpenSim.Framework;
41using OpenSim.Framework.Console;
42using OpenSim.Framework.Monitoring;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45
46using OpenMetaverse.StructuredData;
47
48namespace OpenSim.Region.OptionalModules.Framework.Monitoring
49{
50[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ServerStatistics")]
51public class ServerStats : ISharedRegionModule
52{
53 private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
54 private readonly string LogHeader = "[SERVER STATS]";
55
56 public bool Enabled = false;
57 private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>();
58
59 public readonly string CategoryServer = "server";
60
61 public readonly string ContainerProcessor = "processor";
62 public readonly string ContainerMemory = "memory";
63 public readonly string ContainerNetwork = "network";
64 public readonly string ContainerProcess = "process";
65
66 public string NetworkInterfaceTypes = "Ethernet";
67
68 readonly int performanceCounterSampleInterval = 500;
69 int lastperformanceCounterSampleTime = 0;
70
71 private class PerfCounterControl
72 {
73 public PerformanceCounter perfCounter;
74 public int lastFetch;
75 public string name;
76 public PerfCounterControl(PerformanceCounter pPc)
77 : this(pPc, String.Empty)
78 {
79 }
80 public PerfCounterControl(PerformanceCounter pPc, string pName)
81 {
82 perfCounter = pPc;
83 lastFetch = 0;
84 name = pName;
85 }
86 }
87
88 PerfCounterControl processorPercentPerfCounter = null;
89
90 #region ISharedRegionModule
91 // IRegionModuleBase.Name
92 public string Name { get { return "Server Stats"; } }
93 // IRegionModuleBase.ReplaceableInterface
94 public Type ReplaceableInterface { get { return null; } }
95 // IRegionModuleBase.Initialize
96 public void Initialise(IConfigSource source)
97 {
98 IConfig cfg = source.Configs["Monitoring"];
99
100 if (cfg != null)
101 Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
102
103 if (Enabled)
104 {
105 NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
106 }
107 }
108 // IRegionModuleBase.Close
109 public void Close()
110 {
111 if (RegisteredStats.Count > 0)
112 {
113 foreach (Stat stat in RegisteredStats.Values)
114 {
115 StatsManager.DeregisterStat(stat);
116 stat.Dispose();
117 }
118 RegisteredStats.Clear();
119 }
120 }
121 // IRegionModuleBase.AddRegion
122 public void AddRegion(Scene scene)
123 {
124 }
125 // IRegionModuleBase.RemoveRegion
126 public void RemoveRegion(Scene scene)
127 {
128 }
129 // IRegionModuleBase.RegionLoaded
130 public void RegionLoaded(Scene scene)
131 {
132 }
133 // ISharedRegionModule.PostInitialize
134 public void PostInitialise()
135 {
136 if (RegisteredStats.Count == 0)
137 {
138 RegisterServerStats();
139 }
140 }
141 #endregion ISharedRegionModule
142
143 private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act)
144 {
145 string desc = pDesc;
146 if (desc == null)
147 desc = pName;
148 Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info);
149 StatsManager.RegisterStat(stat);
150 RegisteredStats.Add(pName, stat);
151 }
152
153 public void RegisterServerStats()
154 {
155 lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
156 PerformanceCounter tempPC;
157 Stat tempStat;
158 string tempName;
159
160 try
161 {
162 tempName = "CPUPercent";
163 tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
164 processorPercentPerfCounter = new PerfCounterControl(tempPC);
165 // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
166 tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
167 StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); },
168 StatVerbosity.Info);
169 StatsManager.RegisterStat(tempStat);
170 RegisteredStats.Add(tempName, tempStat);
171
172 MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,
173 (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
174
175 MakeStat("UserProcessorTime", null, "sec", ContainerProcessor,
176 (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
177
178 MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor,
179 (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
180
181 MakeStat("Threads", null, "threads", ContainerProcessor,
182 (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
183 }
184 catch (Exception e)
185 {
186 m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e);
187 }
188
189 try
190 {
191 List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
192
193 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
194 foreach (NetworkInterface nic in nics)
195 {
196 if (nic.OperationalStatus != OperationalStatus.Up)
197 continue;
198
199 string nicInterfaceType = nic.NetworkInterfaceType.ToString();
200 if (!okInterfaceTypes.Contains(nicInterfaceType))
201 {
202 m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.",
203 LogHeader, nic.Name, nicInterfaceType);
204 m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}",
205 LogHeader, NetworkInterfaceTypes);
206 continue;
207 }
208
209 if (nic.Supports(NetworkInterfaceComponent.IPv4))
210 {
211 IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
212 if (nicStats != null)
213 {
214 MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork,
215 (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
216 MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork,
217 (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
218 MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork,
219 (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
220 }
221 }
222 // TODO: add IPv6 (it may actually happen someday)
223 }
224 }
225 catch (Exception e)
226 {
227 m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
228 }
229
230 MakeStat("ProcessMemory", null, "MB", ContainerMemory,
231 (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; });
232 MakeStat("ObjectMemory", null, "MB", ContainerMemory,
233 (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; });
234 MakeStat("LastMemoryChurn", null, "MB/sec", ContainerMemory,
235 (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); });
236 MakeStat("AverageMemoryChurn", null, "MB/sec", ContainerMemory,
237 (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); });
238 }
239
240 // Notes on performance counters:
241 // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx
242 // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
243 // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
244 private delegate double PerfCounterNextValue();
245 private void GetNextValue(Stat stat, PerfCounterControl perfControl)
246 {
247 GetNextValue(stat, perfControl, 1.0);
248 }
249 private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
250 {
251 if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
252 {
253 if (perfControl != null && perfControl.perfCounter != null)
254 {
255 try
256 {
257 // Kludge for factor to run double duty. If -1, subtract the value from one
258 if (factor == -1)
259 stat.Value = 1 - perfControl.perfCounter.NextValue();
260 else
261 stat.Value = perfControl.perfCounter.NextValue() / factor;
262 }
263 catch (Exception e)
264 {
265 m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
266 }
267 perfControl.lastFetch = Util.EnvironmentTickCount();
268 }
269 }
270 }
271
272 // Lookup the nic that goes with this stat and set the value by using a fetch action.
273 // Not sure about closure with delegates inside delegates.
274 private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
275 private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor)
276 {
277 // Get the one nic that has the name of this stat
278 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
279 (network) => network.Name == stat.Description);
280 try
281 {
282 foreach (NetworkInterface nic in nics)
283 {
284 IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
285 if (intrStats != null)
286 {
287 double newVal = Math.Round(getter(intrStats) / factor, 3);
288 stat.Value = newVal;
289 }
290 break;
291 }
292 }
293 catch
294 {
295 // There are times interfaces go away so we just won't update the stat for this
296 m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
297 }
298 }
299}
300
301public class ServerStatsAggregator : Stat
302{
303 public ServerStatsAggregator(
304 string shortName,
305 string name,
306 string description,
307 string unitName,
308 string category,
309 string container
310 )
311 : base(
312 shortName,
313 name,
314 description,
315 unitName,
316 category,
317 container,
318 StatType.Push,
319 MeasuresOfInterest.None,
320 null,
321 StatVerbosity.Info)
322 {
323 }
324 public override string ToConsoleString()
325 {
326 StringBuilder sb = new StringBuilder();
327
328 return sb.ToString();
329 }
330
331 public override OSDMap ToOSDMap()
332 {
333 OSDMap ret = new OSDMap();
334
335 return ret;
336 }
337}
338
339}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
index ac8c30c..928b350 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
@@ -43,8 +43,14 @@ public class BSActorAvatarMove : BSActor
43 // Set to true if we think we're going up stairs. 43 // Set to true if we think we're going up stairs.
44 // This state is remembered because collisions will turn on and off as we go up stairs. 44 // This state is remembered because collisions will turn on and off as we go up stairs.
45 int m_walkingUpStairs; 45 int m_walkingUpStairs;
46 // The amount the step up is applying. Used to smooth stair walking.
46 float m_lastStepUp; 47 float m_lastStepUp;
47 48
49 // Jumping happens over several frames. If use applies up force while colliding, start the
50 // jump and allow the jump to continue for this number of frames.
51 int m_jumpFrames = 0;
52 float m_jumpVelocity = 0f;
53
48 public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName) 54 public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
49 : base(physicsScene, pObj, actorName) 55 : base(physicsScene, pObj, actorName)
50 { 56 {
@@ -206,17 +212,45 @@ public class BSActorAvatarMove : BSActor
206 212
207 if (m_controllingPrim.Friction != BSParam.AvatarFriction) 213 if (m_controllingPrim.Friction != BSParam.AvatarFriction)
208 { 214 {
209 // Probably starting up walking. Set friction to moving friction. 215 // Probably starting to walk. Set friction to moving friction.
210 m_controllingPrim.Friction = BSParam.AvatarFriction; 216 m_controllingPrim.Friction = BSParam.AvatarFriction;
211 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); 217 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
212 } 218 }
213 219
214 // If falling, we keep the world's downward vector no matter what the other axis specify.
215 // The check for RawVelocity.Z < 0 makes jumping work (temporary upward force).
216 if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding) 220 if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
217 { 221 {
218 if (m_controllingPrim.RawVelocity.Z < 0) 222 stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
223 }
224
225
226 // Colliding and not flying with an upward force. The avatar must be trying to jump.
227 if (!m_controllingPrim.Flying && m_controllingPrim.IsColliding && stepVelocity.Z > 0)
228 {
229 // We allow the upward force to happen for this many frames.
230 m_jumpFrames = BSParam.AvatarJumpFrames;
231 m_jumpVelocity = stepVelocity.Z;
232 }
233
234 // The case where the avatar is not colliding and is not flying is special.
235 // The avatar is either falling or jumping and the user can be applying force to the avatar
236 // (force in some direction or force up or down).
237 // If the avatar has negative Z velocity and is not colliding, presume we're falling and keep the velocity.
238 // If the user is trying to apply upward force but we're not colliding, assume the avatar
239 // is trying to jump and don't apply the upward force if not touching the ground any more.
240 if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
241 {
242 // If upward velocity is being applied, this must be a jump and only allow that to go on so long
243 if (m_jumpFrames > 0)
244 {
245 // Since not touching the ground, only apply upward force for so long.
246 m_jumpFrames--;
247 stepVelocity.Z = m_jumpVelocity;
248 }
249 else
250 {
251 // Since we're not affected by anything, whatever vertical motion the avatar has, continue that.
219 stepVelocity.Z = m_controllingPrim.RawVelocity.Z; 252 stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
253 }
220 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); 254 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
221 } 255 }
222 256
@@ -241,7 +275,7 @@ public class BSActorAvatarMove : BSActor
241 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}", 275 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}",
242 m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying, 276 m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying,
243 m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z); 277 m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z);
244 // This test is done if moving forward, not flying and is colliding with something. 278
245 // Check for stairs climbing if colliding, not flying and moving forward 279 // Check for stairs climbing if colliding, not flying and moving forward
246 if ( m_controllingPrim.IsColliding 280 if ( m_controllingPrim.IsColliding
247 && !m_controllingPrim.Flying 281 && !m_controllingPrim.Flying
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 311cf4f..07e87d1 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -209,7 +209,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
209 m_VhoverTimescale = Math.Max(pValue, 0.01f); 209 m_VhoverTimescale = Math.Max(pValue, 0.01f);
210 break; 210 break;
211 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: 211 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
212 m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); 212 m_linearDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
213 break; 213 break;
214 case Vehicle.LINEAR_DEFLECTION_TIMESCALE: 214 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
215 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); 215 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
@@ -707,7 +707,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
707 private Vector3 m_knownRotationalVelocity; 707 private Vector3 m_knownRotationalVelocity;
708 private Vector3 m_knownRotationalForce; 708 private Vector3 m_knownRotationalForce;
709 private Vector3 m_knownRotationalImpulse; 709 private Vector3 m_knownRotationalImpulse;
710 private Vector3 m_knownForwardVelocity; // vehicle relative forward speed
711 710
712 private const int m_knownChangedPosition = 1 << 0; 711 private const int m_knownChangedPosition = 1 << 0;
713 private const int m_knownChangedVelocity = 1 << 1; 712 private const int m_knownChangedVelocity = 1 << 1;
@@ -719,7 +718,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
719 private const int m_knownChangedRotationalImpulse = 1 << 7; 718 private const int m_knownChangedRotationalImpulse = 1 << 7;
720 private const int m_knownChangedTerrainHeight = 1 << 8; 719 private const int m_knownChangedTerrainHeight = 1 << 8;
721 private const int m_knownChangedWaterLevel = 1 << 9; 720 private const int m_knownChangedWaterLevel = 1 << 9;
722 private const int m_knownChangedForwardVelocity = 1 <<10;
723 721
724 public void ForgetKnownVehicleProperties() 722 public void ForgetKnownVehicleProperties()
725 { 723 {
@@ -923,12 +921,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
923 { 921 {
924 get 922 get
925 { 923 {
926 if ((m_knownHas & m_knownChangedForwardVelocity) == 0) 924 return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
927 {
928 m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
929 m_knownHas |= m_knownChangedForwardVelocity;
930 }
931 return m_knownForwardVelocity;
932 } 925 }
933 } 926 }
934 private float VehicleForwardSpeed 927 private float VehicleForwardSpeed
@@ -981,6 +974,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
981 { 974 {
982 ComputeLinearVelocity(pTimestep); 975 ComputeLinearVelocity(pTimestep);
983 976
977 ComputeLinearDeflection(pTimestep);
978
984 ComputeLinearTerrainHeightCorrection(pTimestep); 979 ComputeLinearTerrainHeightCorrection(pTimestep);
985 980
986 ComputeLinearHover(pTimestep); 981 ComputeLinearHover(pTimestep);
@@ -1026,12 +1021,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1026 { 1021 {
1027 // Step the motor from the current value. Get the correction needed this step. 1022 // Step the motor from the current value. Get the correction needed this step.
1028 Vector3 origVelW = VehicleVelocity; // DEBUG 1023 Vector3 origVelW = VehicleVelocity; // DEBUG
1029 Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); 1024 Vector3 currentVelV = VehicleForwardVelocity;
1030 Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); 1025 Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV);
1031 1026
1032 // Friction reduces vehicle motion 1027 // Friction reduces vehicle motion based on absolute speed. Slow vehicle down by friction.
1033 Vector3 frictionFactorW = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep); 1028 Vector3 frictionFactorV = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep);
1034 linearMotorCorrectionV -= (currentVelV * frictionFactorW); 1029 linearMotorCorrectionV -= (currentVelV * frictionFactorV);
1035 1030
1036 // Motor is vehicle coordinates. Rotate it to world coordinates 1031 // Motor is vehicle coordinates. Rotate it to world coordinates
1037 Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; 1032 Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation;
@@ -1046,11 +1041,38 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1046 // Add this correction to the velocity to make it faster/slower. 1041 // Add this correction to the velocity to make it faster/slower.
1047 VehicleVelocity += linearMotorVelocityW; 1042 VehicleVelocity += linearMotorVelocityW;
1048 1043
1049
1050
1051 VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}", 1044 VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}",
1052 ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, 1045 ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV,
1053 linearMotorVelocityW, VehicleVelocity, frictionFactorW); 1046 linearMotorVelocityW, VehicleVelocity, frictionFactorV);
1047 }
1048
1049 //Given a Deflection Effiency and a Velocity, Returns a Velocity that is Partially Deflected onto the X Axis
1050 //Clamped so that a DeflectionTimescale of less then 1 does not increase force over original velocity
1051 private void ComputeLinearDeflection(float pTimestep)
1052 {
1053 Vector3 linearDeflectionV = Vector3.Zero;
1054 Vector3 velocityV = VehicleForwardVelocity;
1055
1056 // Velocity in Y and Z dimensions is movement to the side or turning.
1057 // Compute deflection factor from the to the side and rotational velocity
1058 linearDeflectionV.Y = SortedClampInRange(0, (velocityV.Y * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Y);
1059 linearDeflectionV.Z = SortedClampInRange(0, (velocityV.Z * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Z);
1060
1061 // Velocity to the side and around is corrected and moved into the forward direction
1062 linearDeflectionV.X += Math.Abs(linearDeflectionV.Y);
1063 linearDeflectionV.X += Math.Abs(linearDeflectionV.Z);
1064
1065 // Scale the deflection to the fractional simulation time
1066 linearDeflectionV *= pTimestep;
1067
1068 // Subtract the sideways and rotational velocity deflection factors while adding the correction forward
1069 linearDeflectionV *= new Vector3(1,-1,-1);
1070
1071 // Correciont is vehicle relative. Convert to world coordinates and add to the velocity
1072 VehicleVelocity += linearDeflectionV * VehicleOrientation;
1073
1074 VDetailLog("{0}, MoveLinear,LinearDeflection,linDefEff={1},linDefTS={2},linDeflectionV={3}",
1075 ControllingPrim.LocalID, m_linearDeflectionEfficiency, m_linearDeflectionTimescale, linearDeflectionV);
1054 } 1076 }
1055 1077
1056 public void ComputeLinearTerrainHeightCorrection(float pTimestep) 1078 public void ComputeLinearTerrainHeightCorrection(float pTimestep)
@@ -1652,6 +1674,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1652 return frictionFactor; 1674 return frictionFactor;
1653 } 1675 }
1654 1676
1677 private float SortedClampInRange(float clampa, float val, float clampb)
1678 {
1679 if (clampa > clampb)
1680 {
1681 float temp = clampa;
1682 clampa = clampb;
1683 clampb = temp;
1684 }
1685 return ClampInRange(clampa, val, clampb);
1686
1687 }
1688
1655 private float ClampInRange(float low, float val, float high) 1689 private float ClampInRange(float low, float val, float high)
1656 { 1690 {
1657 return Math.Max(low, Math.Min(val, high)); 1691 return Math.Max(low, Math.Min(val, high));
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index aad1108..6437b04 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -134,6 +134,7 @@ public static class BSParam
134 public static float AvatarHeightMidFudge { get; private set; } 134 public static float AvatarHeightMidFudge { get; private set; }
135 public static float AvatarHeightHighFudge { get; private set; } 135 public static float AvatarHeightHighFudge { get; private set; }
136 public static float AvatarContactProcessingThreshold { get; private set; } 136 public static float AvatarContactProcessingThreshold { get; private set; }
137 public static int AvatarJumpFrames { get; private set; }
137 public static float AvatarBelowGroundUpCorrectionMeters { get; private set; } 138 public static float AvatarBelowGroundUpCorrectionMeters { get; private set; }
138 public static float AvatarStepHeight { get; private set; } 139 public static float AvatarStepHeight { get; private set; }
139 public static float AvatarStepApproachFactor { get; private set; } 140 public static float AvatarStepApproachFactor { get; private set; }
@@ -567,6 +568,8 @@ public static class BSParam
567 0.1f ), 568 0.1f ),
568 new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", 569 new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
569 1.0f ), 570 1.0f ),
571 new ParameterDefn<int>("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.",
572 4 ),
570 new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction", 573 new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction",
571 0.6f ) , 574 0.6f ) ,
572 new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)", 575 new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs
index b13c87d..667cef8 100644
--- a/OpenSim/Server/Base/ServicesServerBase.cs
+++ b/OpenSim/Server/Base/ServicesServerBase.cs
@@ -34,6 +34,7 @@ using System.Text;
34using System.Xml; 34using System.Xml;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Console; 36using OpenSim.Framework.Console;
37using OpenSim.Framework.Monitoring;
37using OpenSim.Framework.Servers; 38using OpenSim.Framework.Servers;
38using log4net; 39using log4net;
39using log4net.Config; 40using log4net.Config;
@@ -190,16 +191,7 @@ namespace OpenSim.Server.Base
190 } 191 }
191 192
192 RegisterCommonCommands(); 193 RegisterCommonCommands();
193 194 RegisterCommonComponents(Config);
194 // Register the quit command
195 //
196 MainConsole.Instance.Commands.AddCommand("General", false, "quit",
197 "quit",
198 "Quit the application", HandleQuit);
199
200 MainConsole.Instance.Commands.AddCommand("General", false, "shutdown",
201 "shutdown",
202 "Quit the application", HandleQuit);
203 195
204 // Allow derived classes to perform initialization that 196 // Allow derived classes to perform initialization that
205 // needs to be done after the console has opened 197 // needs to be done after the console has opened
@@ -214,6 +206,9 @@ namespace OpenSim.Server.Base
214 206
215 public virtual int Run() 207 public virtual int Run()
216 { 208 {
209 Watchdog.Enabled = true;
210 MemoryWatchdog.Enabled = true;
211
217 while (m_Running) 212 while (m_Running)
218 { 213 {
219 try 214 try
@@ -231,11 +226,12 @@ namespace OpenSim.Server.Base
231 return 0; 226 return 0;
232 } 227 }
233 228
234 protected virtual void HandleQuit(string module, string[] args) 229 protected override void ShutdownSpecific()
235 { 230 {
236 m_Running = false; 231 m_Running = false;
237 m_log.Info("[CONSOLE] Quitting"); 232 m_log.Info("[CONSOLE] Quitting");
238 233
234 base.ShutdownSpecific();
239 } 235 }
240 236
241 protected virtual void ReadConfig() 237 protected virtual void ReadConfig()
@@ -246,4 +242,4 @@ namespace OpenSim.Server.Base
246 { 242 {
247 } 243 }
248 } 244 }
249} 245} \ No newline at end of file
diff --git a/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs
index cf1af15..adc2fbc 100644
--- a/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs
@@ -61,7 +61,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
61 m_Proxy = proxy; 61 m_Proxy = proxy;
62 } 62 }
63 63
64 protected override bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) 64 protected override bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
65 { 65 {
66 return m_GatekeeperService.LoginAgent(aCircuit, destination, out reason); 66 return m_GatekeeperService.LoginAgent(aCircuit, destination, out reason);
67 } 67 }
diff --git a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs
index 968c1e6..df875af 100644
--- a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs
@@ -49,191 +49,87 @@ using log4net;
49 49
50namespace OpenSim.Server.Handlers.Hypergrid 50namespace OpenSim.Server.Handlers.Hypergrid
51{ 51{
52 public class HomeAgentHandler 52 public class HomeAgentHandler : AgentPostHandler
53 { 53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private IUserAgentService m_UserAgentService; 55 private IUserAgentService m_UserAgentService;
56 56
57 private string m_LoginServerIP; 57 private string m_LoginServerIP;
58 private bool m_Proxy = false;
59 58
60 public HomeAgentHandler(IUserAgentService userAgentService, string loginServerIP, bool proxy) 59 public HomeAgentHandler(IUserAgentService userAgentService, string loginServerIP, bool proxy) :
60 base("/homeagent")
61 { 61 {
62 m_UserAgentService = userAgentService; 62 m_UserAgentService = userAgentService;
63 m_LoginServerIP = loginServerIP; 63 m_LoginServerIP = loginServerIP;
64 m_Proxy = proxy; 64 m_Proxy = proxy;
65 } 65 }
66 66
67 public Hashtable Handler(Hashtable request) 67 protected override AgentDestinationData CreateAgentDestinationData()
68 { 68 {
69// m_log.Debug("[CONNECTION DEBUGGING]: HomeAgentHandler Called"); 69 return new ExtendedAgentDestinationData();
70// 70 }
71// m_log.Debug("---------------------------"); 71 protected override void UnpackData(OSDMap args, AgentDestinationData d, Hashtable request)
72// m_log.Debug(" >> uri=" + request["uri"]); 72 {
73// m_log.Debug(" >> content-type=" + request["content-type"]); 73 base.UnpackData(args, d, request);
74// m_log.Debug(" >> http-method=" + request["http-method"]); 74 ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d;
75// m_log.Debug("---------------------------\n"); 75 try
76
77 Hashtable responsedata = new Hashtable();
78 responsedata["content_type"] = "text/html";
79 responsedata["keepalive"] = false;
80
81
82 UUID agentID;
83 UUID regionID;
84 string action;
85 if (!Utils.GetParams((string)request["uri"], out agentID, out regionID, out action))
86 { 76 {
87 m_log.InfoFormat("[HOME AGENT HANDLER]: Invalid parameters for agent message {0}", request["uri"]); 77 if (args.ContainsKey("gatekeeper_host") && args["gatekeeper_host"] != null)
88 responsedata["int_response_code"] = 404; 78 data.host = args["gatekeeper_host"].AsString();
89 responsedata["str_response_string"] = "false"; 79 if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null)
80 Int32.TryParse(args["gatekeeper_port"].AsString(), out data.port);
81 if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] != null)
82 data.gatekeeperServerURI = args["gatekeeper_serveruri"];
83 if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] != null)
84 data.destinationServerURI = args["destination_serveruri"];
90 85
91 return responsedata;
92 } 86 }
93 87 catch (InvalidCastException e)
94 // Next, let's parse the verb
95 string method = (string)request["http-method"];
96 if (method.Equals("POST"))
97 { 88 {
98 DoAgentPost(request, responsedata, agentID); 89 m_log.ErrorFormat("[HOME AGENT HANDLER]: Bad cast in UnpackData");
99 return responsedata;
100 } 90 }
101 else
102 {
103 m_log.InfoFormat("[HOME AGENT HANDLER]: method {0} not supported in agent message", method);
104 responsedata["int_response_code"] = HttpStatusCode.MethodNotAllowed;
105 responsedata["str_response_string"] = "Method not allowed";
106 91
107 return responsedata; 92 string callerIP = GetCallerIP(request);
108 } 93 // Verify if this call came from the login server
94 if (callerIP == m_LoginServerIP)
95 data.fromLogin = true;
109 96
110 } 97 }
111 98
112 protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id) 99 protected override GridRegion ExtractGatekeeper(AgentDestinationData d)
113 { 100 {
114 OSDMap args = Utils.GetOSDMap((string)request["body"]); 101 if (d is ExtendedAgentDestinationData)
115 if (args == null)
116 { 102 {
117 responsedata["int_response_code"] = HttpStatusCode.BadRequest; 103 ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d;
118 responsedata["str_response_string"] = "Bad request"; 104 GridRegion gatekeeper = new GridRegion();
119 return; 105 gatekeeper.ServerURI = data.gatekeeperServerURI;
106 gatekeeper.ExternalHostName = data.host;
107 gatekeeper.HttpPort = (uint)data.port;
108 gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
109
110 return gatekeeper;
120 } 111 }
121
122 // retrieve the input arguments
123 int x = 0, y = 0;
124 UUID uuid = UUID.Zero;
125 string regionname = string.Empty;
126 string gatekeeper_host = string.Empty;
127 string gatekeeper_serveruri = string.Empty;
128 string destination_serveruri = string.Empty;
129 int gatekeeper_port = 0;
130 IPEndPoint client_ipaddress = null;
131
132 if (args.ContainsKey("gatekeeper_host") && args["gatekeeper_host"] != null)
133 gatekeeper_host = args["gatekeeper_host"].AsString();
134 if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null)
135 Int32.TryParse(args["gatekeeper_port"].AsString(), out gatekeeper_port);
136 if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] !=null)
137 gatekeeper_serveruri = args["gatekeeper_serveruri"];
138 if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] !=null)
139 destination_serveruri = args["destination_serveruri"];
140
141 GridRegion gatekeeper = new GridRegion();
142 gatekeeper.ServerURI = gatekeeper_serveruri;
143 gatekeeper.ExternalHostName = gatekeeper_host;
144 gatekeeper.HttpPort = (uint)gatekeeper_port;
145 gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
146
147 if (args.ContainsKey("destination_x") && args["destination_x"] != null)
148 Int32.TryParse(args["destination_x"].AsString(), out x);
149 else 112 else
150 m_log.WarnFormat(" -- request didn't have destination_x"); 113 m_log.WarnFormat("[HOME AGENT HANDLER]: Wrong data type");
151 if (args.ContainsKey("destination_y") && args["destination_y"] != null)
152 Int32.TryParse(args["destination_y"].AsString(), out y);
153 else
154 m_log.WarnFormat(" -- request didn't have destination_y");
155 if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
156 UUID.TryParse(args["destination_uuid"].AsString(), out uuid);
157 if (args.ContainsKey("destination_name") && args["destination_name"] != null)
158 regionname = args["destination_name"].ToString();
159
160 if (args.ContainsKey("client_ip") && args["client_ip"] != null)
161 {
162 string ip_str = args["client_ip"].ToString();
163 try
164 {
165 string callerIP = GetCallerIP(request);
166 // Verify if this caller has authority to send the client IP
167 if (callerIP == m_LoginServerIP)
168 client_ipaddress = new IPEndPoint(IPAddress.Parse(ip_str), 0);
169 else // leaving this for now, but this warning should be removed
170 m_log.WarnFormat("[HOME AGENT HANDLER]: Unauthorized machine {0} tried to set client ip to {1}", callerIP, ip_str);
171 }
172 catch
173 {
174 m_log.DebugFormat("[HOME AGENT HANDLER]: Exception parsing client ip address from {0}", ip_str);
175 }
176 }
177
178 GridRegion destination = new GridRegion();
179 destination.RegionID = uuid;
180 destination.RegionLocX = x;
181 destination.RegionLocY = y;
182 destination.RegionName = regionname;
183 destination.ServerURI = destination_serveruri;
184
185 AgentCircuitData aCircuit = new AgentCircuitData();
186 try
187 {
188 aCircuit.UnpackAgentCircuitData(args);
189 }
190 catch (Exception ex)
191 {
192 m_log.InfoFormat("[HOME AGENT HANDLER]: exception on unpacking ChildCreate message {0}", ex.Message);
193 responsedata["int_response_code"] = HttpStatusCode.BadRequest;
194 responsedata["str_response_string"] = "Bad request";
195 return;
196 }
197
198 OSDMap resp = new OSDMap(2);
199 string reason = String.Empty;
200 114
201 bool result = m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, client_ipaddress, out reason); 115 return null;
202
203 resp["reason"] = OSD.FromString(reason);
204 resp["success"] = OSD.FromBoolean(result);
205
206 // TODO: add reason if not String.Empty?
207 responsedata["int_response_code"] = HttpStatusCode.OK;
208 responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
209 } 116 }
210 117
211 private string GetCallerIP(Hashtable request)
212 {
213 if (!m_Proxy)
214 return Util.GetCallerIP(request);
215
216 // We're behind a proxy
217 Hashtable headers = (Hashtable)request["headers"];
218 string xff = "X-Forwarded-For";
219 if (headers.ContainsKey(xff.ToLower()))
220 xff = xff.ToLower();
221 118
222 if (!headers.ContainsKey(xff) || headers[xff] == null) 119 protected override bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
223 { 120 {
224 m_log.WarnFormat("[AGENT HANDLER]: No XFF header"); 121 return m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, fromLogin, out reason);
225 return Util.GetCallerIP(request); 122 }
226 }
227 123
228 m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]); 124 }
229 125
230 IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]); 126 public class ExtendedAgentDestinationData : AgentDestinationData
231 if (ep != null) 127 {
232 return ep.Address.ToString(); 128 public string host;
129 public int port;
130 public string gatekeeperServerURI;
131 public string destinationServerURI;
233 132
234 // Oops
235 return Util.GetCallerIP(request);
236 }
237 } 133 }
238 134
239} 135}
diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
index b20f467..d9c1bd3 100644
--- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
@@ -108,7 +108,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
108 server.AddXmlRPCHandler("get_uui", GetUUI, false); 108 server.AddXmlRPCHandler("get_uui", GetUUI, false);
109 server.AddXmlRPCHandler("get_uuid", GetUUID, false); 109 server.AddXmlRPCHandler("get_uuid", GetUUID, false);
110 110
111 server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); 111 server.AddStreamHandler(new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy));
112 } 112 }
113 113
114 public XmlRpcResponse GetHomeRegion(XmlRpcRequest request, IPEndPoint remoteClient) 114 public XmlRpcResponse GetHomeRegion(XmlRpcRequest request, IPEndPoint remoteClient)
diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
index ae37ca7..71a9e6f 100644
--- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
@@ -328,31 +328,16 @@ namespace OpenSim.Server.Handlers.Simulation
328 return; 328 return;
329 } 329 }
330 330
331 // retrieve the input arguments 331 AgentDestinationData data = CreateAgentDestinationData();
332 int x = 0, y = 0; 332 UnpackData(args, data, request);
333 UUID uuid = UUID.Zero;
334 string regionname = string.Empty;
335 uint teleportFlags = 0;
336 if (args.ContainsKey("destination_x") && args["destination_x"] != null)
337 Int32.TryParse(args["destination_x"].AsString(), out x);
338 else
339 m_log.WarnFormat(" -- request didn't have destination_x");
340 if (args.ContainsKey("destination_y") && args["destination_y"] != null)
341 Int32.TryParse(args["destination_y"].AsString(), out y);
342 else
343 m_log.WarnFormat(" -- request didn't have destination_y");
344 if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
345 UUID.TryParse(args["destination_uuid"].AsString(), out uuid);
346 if (args.ContainsKey("destination_name") && args["destination_name"] != null)
347 regionname = args["destination_name"].ToString();
348 if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null)
349 teleportFlags = args["teleport_flags"].AsUInteger();
350 333
351 GridRegion destination = new GridRegion(); 334 GridRegion destination = new GridRegion();
352 destination.RegionID = uuid; 335 destination.RegionID = data.uuid;
353 destination.RegionLocX = x; 336 destination.RegionLocX = data.x;
354 destination.RegionLocY = y; 337 destination.RegionLocY = data.y;
355 destination.RegionName = regionname; 338 destination.RegionName = data.name;
339
340 GridRegion gatekeeper = ExtractGatekeeper(data);
356 341
357 AgentCircuitData aCircuit = new AgentCircuitData(); 342 AgentCircuitData aCircuit = new AgentCircuitData();
358 try 343 try
@@ -373,7 +358,7 @@ namespace OpenSim.Server.Handlers.Simulation
373 // This is the meaning of POST agent 358 // This is the meaning of POST agent
374 //m_regionClient.AdjustUserInformation(aCircuit); 359 //m_regionClient.AdjustUserInformation(aCircuit);
375 //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); 360 //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason);
376 bool result = CreateAgent(destination, aCircuit, teleportFlags, out reason); 361 bool result = CreateAgent(gatekeeper, destination, aCircuit, data.flags, data.fromLogin, out reason);
377 362
378 resp["reason"] = OSD.FromString(reason); 363 resp["reason"] = OSD.FromString(reason);
379 resp["success"] = OSD.FromBoolean(result); 364 resp["success"] = OSD.FromBoolean(result);
@@ -385,7 +370,36 @@ namespace OpenSim.Server.Handlers.Simulation
385 responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); 370 responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
386 } 371 }
387 372
388 private string GetCallerIP(Hashtable request) 373 protected virtual AgentDestinationData CreateAgentDestinationData()
374 {
375 return new AgentDestinationData();
376 }
377
378 protected virtual void UnpackData(OSDMap args, AgentDestinationData data, Hashtable request)
379 {
380 // retrieve the input arguments
381 if (args.ContainsKey("destination_x") && args["destination_x"] != null)
382 Int32.TryParse(args["destination_x"].AsString(), out data.x);
383 else
384 m_log.WarnFormat(" -- request didn't have destination_x");
385 if (args.ContainsKey("destination_y") && args["destination_y"] != null)
386 Int32.TryParse(args["destination_y"].AsString(), out data.y);
387 else
388 m_log.WarnFormat(" -- request didn't have destination_y");
389 if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
390 UUID.TryParse(args["destination_uuid"].AsString(), out data.uuid);
391 if (args.ContainsKey("destination_name") && args["destination_name"] != null)
392 data.name = args["destination_name"].ToString();
393 if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null)
394 data.flags = args["teleport_flags"].AsUInteger();
395 }
396
397 protected virtual GridRegion ExtractGatekeeper(AgentDestinationData data)
398 {
399 return null;
400 }
401
402 protected string GetCallerIP(Hashtable request)
389 { 403 {
390 if (!m_Proxy) 404 if (!m_Proxy)
391 return Util.GetCallerIP(request); 405 return Util.GetCallerIP(request);
@@ -418,7 +432,7 @@ namespace OpenSim.Server.Handlers.Simulation
418 } 432 }
419 433
420 // subclasses can override this 434 // subclasses can override this
421 protected virtual bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) 435 protected virtual bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
422 { 436 {
423 return m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); 437 return m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason);
424 } 438 }
@@ -562,7 +576,6 @@ namespace OpenSim.Server.Handlers.Simulation
562 //agent.Dump(); 576 //agent.Dump();
563 // This is one of the meanings of PUT agent 577 // This is one of the meanings of PUT agent
564 result = UpdateAgent(destination, agent); 578 result = UpdateAgent(destination, agent);
565
566 } 579 }
567 else if ("AgentPosition".Equals(messageType)) 580 else if ("AgentPosition".Equals(messageType))
568 { 581 {
@@ -593,4 +606,14 @@ namespace OpenSim.Server.Handlers.Simulation
593 return m_SimulationService.UpdateAgent(destination, agent); 606 return m_SimulationService.UpdateAgent(destination, agent);
594 } 607 }
595 } 608 }
609
610 public class AgentDestinationData
611 {
612 public int x;
613 public int y;
614 public string name;
615 public UUID uuid;
616 public uint flags;
617 public bool fromLogin;
618 }
596} 619}
diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
index 5bcff48..c9c6c31 100644
--- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
@@ -53,7 +53,8 @@ namespace OpenSim.Services.Connectors.Hypergrid
53 53
54 private IAssetService m_AssetService; 54 private IAssetService m_AssetService;
55 55
56 public GatekeeperServiceConnector() : base() 56 public GatekeeperServiceConnector()
57 : base()
57 { 58 {
58 } 59 }
59 60
@@ -123,11 +124,13 @@ namespace OpenSim.Services.Connectors.Hypergrid
123 realHandle = Convert.ToUInt64((string)hash["handle"]); 124 realHandle = Convert.ToUInt64((string)hash["handle"]);
124 //m_log.Debug(">> HERE, realHandle: " + realHandle); 125 //m_log.Debug(">> HERE, realHandle: " + realHandle);
125 } 126 }
126 if (hash["region_image"] != null) { 127 if (hash["region_image"] != null)
128 {
127 imageURL = (string)hash["region_image"]; 129 imageURL = (string)hash["region_image"];
128 //m_log.Debug(">> HERE, imageURL: " + imageURL); 130 //m_log.Debug(">> HERE, imageURL: " + imageURL);
129 } 131 }
130 if (hash["external_name"] != null) { 132 if (hash["external_name"] != null)
133 {
131 externalName = (string)hash["external_name"]; 134 externalName = (string)hash["external_name"];
132 //m_log.Debug(">> HERE, externalName: " + externalName); 135 //m_log.Debug(">> HERE, externalName: " + externalName);
133 } 136 }
@@ -178,7 +181,7 @@ namespace OpenSim.Services.Connectors.Hypergrid
178 //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width); 181 //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width);
179 imageData = OpenJPEG.EncodeFromImage(bitmap, true); 182 imageData = OpenJPEG.EncodeFromImage(bitmap, true);
180 } 183 }
181 184
182 AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString()); 185 AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString());
183 186
184 // !!! for now 187 // !!! for now
@@ -257,7 +260,8 @@ namespace OpenSim.Services.Connectors.Hypergrid
257 region.RegionName = (string)hash["region_name"]; 260 region.RegionName = (string)hash["region_name"];
258 //m_log.Debug(">> HERE, region_name: " + region.RegionName); 261 //m_log.Debug(">> HERE, region_name: " + region.RegionName);
259 } 262 }
260 if (hash["hostname"] != null) { 263 if (hash["hostname"] != null)
264 {
261 region.ExternalHostName = (string)hash["hostname"]; 265 region.ExternalHostName = (string)hash["hostname"];
262 //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); 266 //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName);
263 } 267 }
@@ -275,10 +279,10 @@ namespace OpenSim.Services.Connectors.Hypergrid
275 region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p); 279 region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p);
276 //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); 280 //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint);
277 } 281 }
278 282
279 if (hash["server_uri"] != null) 283 if (hash["server_uri"] != null)
280 { 284 {
281 region.ServerURI = (string) hash["server_uri"]; 285 region.ServerURI = (string)hash["server_uri"];
282 //m_log.Debug(">> HERE, server_uri: " + region.ServerURI); 286 //m_log.Debug(">> HERE, server_uri: " + region.ServerURI);
283 } 287 }
284 288
@@ -295,55 +299,5 @@ namespace OpenSim.Services.Connectors.Hypergrid
295 299
296 return null; 300 return null;
297 } 301 }
298
299 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason)
300 {
301 // m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: CreateAgent start");
302
303 myipaddress = String.Empty;
304 reason = String.Empty;
305
306 if (destination == null)
307 {
308 m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Given destination is null");
309 return false;
310 }
311
312 string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/";
313
314 try
315 {
316 OSDMap args = aCircuit.PackAgentCircuitData();
317
318 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
319 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
320 args["destination_name"] = OSD.FromString(destination.RegionName);
321 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
322 args["teleport_flags"] = OSD.FromString(flags.ToString());
323
324 OSDMap result = WebUtil.PostToService(uri, args, 80000);
325 if (result["Success"].AsBoolean())
326 {
327 OSDMap unpacked = (OSDMap)result["_Result"];
328
329 if (unpacked != null)
330 {
331 reason = unpacked["reason"].AsString();
332 myipaddress = unpacked["your_ip"].AsString();
333 return unpacked["success"].AsBoolean();
334 }
335 }
336
337 reason = result["Message"] != null ? result["Message"].AsString() : "error";
338 return false;
339 }
340 catch (Exception e)
341 {
342 m_log.Warn("[REMOTE SIMULATION CONNECTOR]: CreateAgent failed with exception: " + e.ToString());
343 reason = e.Message;
344 }
345
346 return false;
347 }
348 } 302 }
349} 303}
diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
index 47d0cce..d8a3184 100644
--- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
@@ -44,13 +44,14 @@ using Nini.Config;
44 44
45namespace OpenSim.Services.Connectors.Hypergrid 45namespace OpenSim.Services.Connectors.Hypergrid
46{ 46{
47 public class UserAgentServiceConnector : IUserAgentService 47 public class UserAgentServiceConnector : SimulationServiceConnector, IUserAgentService
48 { 48 {
49 private static readonly ILog m_log = 49 private static readonly ILog m_log =
50 LogManager.GetLogger( 50 LogManager.GetLogger(
51 MethodBase.GetCurrentMethod().DeclaringType); 51 MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 string m_ServerURL; 53 private string m_ServerURL;
54 private GridRegion m_Gatekeeper;
54 55
55 public UserAgentServiceConnector(string url) : this(url, true) 56 public UserAgentServiceConnector(string url) : this(url, true)
56 { 57 {
@@ -104,9 +105,15 @@ namespace OpenSim.Services.Connectors.Hypergrid
104 m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL); 105 m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL);
105 } 106 }
106 107
108 protected override string AgentPath()
109 {
110 return "homeagent/";
111 }
107 112
108 // The Login service calls this interface with a non-null [client] ipaddress 113 // The Login service calls this interface with fromLogin=true
109 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress, out string reason) 114 // Sims call it with fromLogin=false
115 // Either way, this is verified by the handler
116 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, bool fromLogin, out string reason)
110 { 117 {
111 reason = String.Empty; 118 reason = String.Empty;
112 119
@@ -117,119 +124,34 @@ namespace OpenSim.Services.Connectors.Hypergrid
117 return false; 124 return false;
118 } 125 }
119 126
120 string uri = m_ServerURL + "homeagent/" + aCircuit.AgentID + "/"; 127 GridRegion home = new GridRegion();
121 128 home.ServerURI = m_ServerURL;
122 Console.WriteLine(" >>> LoginAgentToGrid <<< " + uri); 129 home.RegionID = destination.RegionID;
123 130 home.RegionLocX = destination.RegionLocX;
124 HttpWebRequest AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri); 131 home.RegionLocY = destination.RegionLocY;
125 AgentCreateRequest.Method = "POST";
126 AgentCreateRequest.ContentType = "application/json";
127 AgentCreateRequest.Timeout = 10000;
128 //AgentCreateRequest.KeepAlive = false;
129 //AgentCreateRequest.Headers.Add("Authorization", authKey);
130
131 // Fill it in
132 OSDMap args = PackCreateAgentArguments(aCircuit, gatekeeper, destination, ipaddress);
133
134 string strBuffer = "";
135 byte[] buffer = new byte[1];
136 try
137 {
138 strBuffer = OSDParser.SerializeJsonString(args);
139 Encoding str = Util.UTF8;
140 buffer = str.GetBytes(strBuffer);
141
142 }
143 catch (Exception e)
144 {
145 m_log.WarnFormat("[USER AGENT CONNECTOR]: Exception thrown on serialization of ChildCreate: {0}", e.Message);
146 // ignore. buffer will be empty, caller should check.
147 }
148
149 Stream os = null;
150 try
151 { // send the Post
152 AgentCreateRequest.ContentLength = buffer.Length; //Count bytes to send
153 os = AgentCreateRequest.GetRequestStream();
154 os.Write(buffer, 0, strBuffer.Length); //Send it
155 m_log.InfoFormat("[USER AGENT CONNECTOR]: Posted CreateAgent request to remote sim {0}, region {1}, x={2} y={3}",
156 uri, destination.RegionName, destination.RegionLocX, destination.RegionLocY);
157 }
158 //catch (WebException ex)
159 catch
160 {
161 //m_log.InfoFormat("[USER AGENT CONNECTOR]: Bad send on ChildAgentUpdate {0}", ex.Message);
162 reason = "cannot contact remote region";
163 return false;
164 }
165 finally
166 {
167 if (os != null)
168 os.Close();
169 }
170
171 // Let's wait for the response
172 //m_log.Info("[USER AGENT CONNECTOR]: Waiting for a reply after DoCreateChildAgentCall");
173 132
174 try 133 m_Gatekeeper = gatekeeper;
175 {
176 using (WebResponse webResponse = AgentCreateRequest.GetResponse())
177 {
178 if (webResponse == null)
179 {
180 m_log.Info("[USER AGENT CONNECTOR]: Null reply on DoCreateChildAgentCall post");
181 }
182 else
183 {
184 using (Stream s = webResponse.GetResponseStream())
185 {
186 using (StreamReader sr = new StreamReader(s))
187 {
188 string response = sr.ReadToEnd().Trim();
189 m_log.InfoFormat("[USER AGENT CONNECTOR]: DoCreateChildAgentCall reply was {0} ", response);
190
191 if (!String.IsNullOrEmpty(response))
192 {
193 try
194 {
195 // we assume we got an OSDMap back
196 OSDMap r = Util.GetOSDMap(response);
197 bool success = r["success"].AsBoolean();
198 reason = r["reason"].AsString();
199 return success;
200 }
201 catch (NullReferenceException e)
202 {
203 m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", e.Message);
204
205 // check for old style response
206 if (response.ToLower().StartsWith("true"))
207 return true;
208
209 return false;
210 }
211 }
212 }
213 }
214 }
215 }
216 }
217 catch (WebException ex)
218 {
219 m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", ex.Message);
220 reason = "Destination did not reply";
221 return false;
222 }
223 134
224 return true; 135 Console.WriteLine(" >>> LoginAgentToGrid <<< " + home.ServerURI);
225 136
137 uint flags = fromLogin ? (uint)TeleportFlags.ViaLogin : (uint)TeleportFlags.ViaHome;
138 return CreateAgent(home, aCircuit, flags, out reason);
226 } 139 }
227 140
228 141
229 // The simulators call this interface 142 // The simulators call this interface
230 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason) 143 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason)
231 { 144 {
232 return LoginAgentToGrid(aCircuit, gatekeeper, destination, null, out reason); 145 return LoginAgentToGrid(aCircuit, gatekeeper, destination, false, out reason);
146 }
147
148 protected override void PackData(OSDMap args, AgentCircuitData aCircuit, GridRegion destination, uint flags)
149 {
150 base.PackData(args, aCircuit, destination, flags);
151 args["gatekeeper_serveruri"] = OSD.FromString(m_Gatekeeper.ServerURI);
152 args["gatekeeper_host"] = OSD.FromString(m_Gatekeeper.ExternalHostName);
153 args["gatekeeper_port"] = OSD.FromString(m_Gatekeeper.HttpPort.ToString());
154 args["destination_serveruri"] = OSD.FromString(destination.ServerURI);
233 } 155 }
234 156
235 protected OSDMap PackCreateAgentArguments(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress) 157 protected OSDMap PackCreateAgentArguments(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress)
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
index 57f2ffa..f51c809 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -79,11 +79,27 @@ namespace OpenSim.Services.Connectors.Simulation
79 return "agent/"; 79 return "agent/";
80 } 80 }
81 81
82 protected virtual void PackData(OSDMap args, AgentCircuitData aCircuit, GridRegion destination, uint flags)
83 {
84 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
85 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
86 args["destination_name"] = OSD.FromString(destination.RegionName);
87 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
88 args["teleport_flags"] = OSD.FromString(flags.ToString());
89 }
90
82 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) 91 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason)
83 { 92 {
84 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CreateAgent start"); 93 string tmp = String.Empty;
85 94 return CreateAgent(destination, aCircuit, flags, out tmp, out reason);
95 }
96
97 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason)
98 {
99 m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: Creating agent at {0}", destination.ServerURI);
86 reason = String.Empty; 100 reason = String.Empty;
101 myipaddress = String.Empty;
102
87 if (destination == null) 103 if (destination == null)
88 { 104 {
89 m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Given destination is null"); 105 m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Given destination is null");
@@ -95,12 +111,7 @@ namespace OpenSim.Services.Connectors.Simulation
95 try 111 try
96 { 112 {
97 OSDMap args = aCircuit.PackAgentCircuitData(); 113 OSDMap args = aCircuit.PackAgentCircuitData();
98 114 PackData(args, aCircuit, destination, flags);
99 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
100 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
101 args["destination_name"] = OSD.FromString(destination.RegionName);
102 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
103 args["teleport_flags"] = OSD.FromString(flags.ToString());
104 115
105 OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000); 116 OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000);
106 bool success = result["success"].AsBoolean(); 117 bool success = result["success"].AsBoolean();
@@ -110,6 +121,7 @@ namespace OpenSim.Services.Connectors.Simulation
110 121
111 reason = data["reason"].AsString(); 122 reason = data["reason"].AsString();
112 success = data["success"].AsBoolean(); 123 success = data["success"].AsBoolean();
124 myipaddress = data["your_ip"].AsString();
113 return success; 125 return success;
114 } 126 }
115 127
@@ -124,6 +136,7 @@ namespace OpenSim.Services.Connectors.Simulation
124 136
125 reason = data["reason"].AsString(); 137 reason = data["reason"].AsString();
126 success = data["success"].AsBoolean(); 138 success = data["success"].AsBoolean();
139 myipaddress = data["your_ip"].AsString();
127 m_log.WarnFormat( 140 m_log.WarnFormat(
128 "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName); 141 "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName);
129 return success; 142 return success;
@@ -228,7 +241,7 @@ namespace OpenSim.Services.Connectors.Simulation
228 /// </summary> 241 /// </summary>
229 private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout) 242 private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout)
230 { 243 {
231 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent start"); 244 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent in {0}", destination.ServerURI);
232 245
233 // Eventually, we want to use a caps url instead of the agentID 246 // Eventually, we want to use a caps url instead of the agentID
234 string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/"; 247 string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/";
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
index 737e9c9..733993f 100644
--- a/OpenSim/Services/HypergridService/UserAgentService.cs
+++ b/OpenSim/Services/HypergridService/UserAgentService.cs
@@ -210,10 +210,10 @@ namespace OpenSim.Services.HypergridService
210 return home; 210 return home;
211 } 211 }
212 212
213 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason) 213 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason)
214 { 214 {
215 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", 215 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}",
216 agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI); 216 agentCircuit.firstname, agentCircuit.lastname, (fromLogin ? agentCircuit.IPAddress : "stored IP"), gatekeeper.ServerURI);
217 217
218 string gridName = gatekeeper.ServerURI; 218 string gridName = gatekeeper.ServerURI;
219 219
@@ -265,7 +265,7 @@ namespace OpenSim.Services.HypergridService
265 bool success = false; 265 bool success = false;
266 string myExternalIP = string.Empty; 266 string myExternalIP = string.Empty;
267 267
268 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); 268 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}, desired region: {2}", m_GridName, gridName, region.RegionID);
269 269
270 if (m_GridName == gridName) 270 if (m_GridName == gridName)
271 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); 271 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason);
@@ -296,8 +296,8 @@ namespace OpenSim.Services.HypergridService
296 296
297 m_log.DebugFormat("[USER AGENT SERVICE]: Gatekeeper sees me as {0}", myExternalIP); 297 m_log.DebugFormat("[USER AGENT SERVICE]: Gatekeeper sees me as {0}", myExternalIP);
298 // else set the IP addresses associated with this client 298 // else set the IP addresses associated with this client
299 if (clientIP != null) 299 if (fromLogin)
300 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString(); 300 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = agentCircuit.IPAddress;
301 m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP; 301 m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP;
302 302
303 return true; 303 return true;
@@ -306,7 +306,7 @@ namespace OpenSim.Services.HypergridService
306 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason) 306 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason)
307 { 307 {
308 reason = string.Empty; 308 reason = string.Empty;
309 return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, null, out reason); 309 return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, false, out reason);
310 } 310 }
311 311
312 private void SetClientIP(UUID sessionID, string ip) 312 private void SetClientIP(UUID sessionID, string ip)
diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs
index 3dc877a..f9e7f08 100644
--- a/OpenSim/Services/Interfaces/IHypergridServices.cs
+++ b/OpenSim/Services/Interfaces/IHypergridServices.cs
@@ -48,10 +48,7 @@ namespace OpenSim.Services.Interfaces
48 /// </summary> 48 /// </summary>
49 public interface IUserAgentService 49 public interface IUserAgentService
50 { 50 {
51 // called by login service only 51 bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason);
52 bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason);
53 // called by simulators
54 bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason);
55 void LogoutAgent(UUID userID, UUID sessionID); 52 void LogoutAgent(UUID userID, UUID sessionID);
56 GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); 53 GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt);
57 Dictionary<string, object> GetServerURLs(UUID userID); 54 Dictionary<string, object> GetServerURLs(UUID userID);
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index 10cf90f..fe43582 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -933,7 +933,7 @@ namespace OpenSim.Services.LLLoginService
933 private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason) 933 private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason)
934 { 934 {
935 m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName); 935 m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName);
936 if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, clientIP, out reason)) 936 if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, true, out reason))
937 return true; 937 return true;
938 return false; 938 return false;
939 } 939 }
diff --git a/prebuild.xml b/prebuild.xml
index 88db6ed..4cf3b83 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -157,6 +157,7 @@
157 <Reference name="System"/> 157 <Reference name="System"/>
158 <Reference name="System.Core"/> 158 <Reference name="System.Core"/>
159 <Reference name="log4net" path="../../../bin/"/> 159 <Reference name="log4net" path="../../../bin/"/>
160 <Reference name="Nini" path="../../../bin/"/>
160 <Reference name="OpenMetaverseTypes" path="../../../bin/"/> 161 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
161 <Reference name="OpenMetaverse" path="../../../bin/"/> 162 <Reference name="OpenMetaverse" path="../../../bin/"/>
162 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/> 163 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
@@ -744,6 +745,7 @@
744 <Reference name="Mono.Addins.Setup" path="../../../bin/"/> 745 <Reference name="Mono.Addins.Setup" path="../../../bin/"/>
745 <Reference name="OpenSim.Framework"/> 746 <Reference name="OpenSim.Framework"/>
746 <Reference name="OpenSim.Framework.Console"/> 747 <Reference name="OpenSim.Framework.Console"/>
748 <Reference name="OpenSim.Framework.Monitoring"/>
747 <Reference name="OpenSim.Framework.Servers"/> 749 <Reference name="OpenSim.Framework.Servers"/>
748 <Reference name="OpenSim.Framework.Servers.HttpServer"/> 750 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
749 <Reference name="Nini" path="../../../bin/"/> 751 <Reference name="Nini" path="../../../bin/"/>