Merge branch 'master' into careminster
Conflicts: OpenSim/Framework/Monitoring/BaseStatsCollector.cs OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs OpenSim/Region/Framework/Scenes/Scene.Inventory.csavinationmerge
						commit
						f70357eaa3
					
				|  | @ -46,7 +46,7 @@ namespace OpenSim.OfflineIM | ||||||
| { | { | ||||||
|     public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService |     public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService | ||||||
|     { |     { | ||||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | //        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||||
|         private const int MAX_IM = 25; |         private const int MAX_IM = 25; | ||||||
| 
 | 
 | ||||||
|         private XmlSerializer m_serializer; |         private XmlSerializer m_serializer; | ||||||
|  |  | ||||||
|  | @ -46,7 +46,7 @@ namespace OpenSim.Capabilities.Handlers | ||||||
| { | { | ||||||
|     public class FetchInventory2Handler |     public class FetchInventory2Handler | ||||||
|     { |     { | ||||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | //        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||||
| 
 | 
 | ||||||
|         private IInventoryService m_inventoryService; |         private IInventoryService m_inventoryService; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| /* | /* | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  * Copyright (c) Contributors, http://opensimulator.org/ | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||||
|  * |  * | ||||||
|  | @ -44,16 +44,16 @@ namespace OpenSim.Framework.Monitoring | ||||||
|             sb.Append("MEMORY STATISTICS"); |             sb.Append("MEMORY STATISTICS"); | ||||||
|             sb.Append(Environment.NewLine); |             sb.Append(Environment.NewLine); | ||||||
|             sb.AppendFormat( |             sb.AppendFormat( | ||||||
|                     "Allocated to OpenSim objects: {0} MB\n", |                 "Heap allocated to OpenSim   : {0} MB\n", | ||||||
|                 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); |                 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); | ||||||
| 
 | 
 | ||||||
|             sb.AppendFormat( |             sb.AppendFormat( | ||||||
|                 "OpenSim last object memory churn    : {0} MB/s\n", |                 "Last heap allocation rate   : {0} MB/s\n", | ||||||
|                 Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3)); |                 Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1024.0 / 1024, 3)); | ||||||
| 
 | 
 | ||||||
|             sb.AppendFormat( |             sb.AppendFormat( | ||||||
|                 "OpenSim average object memory churn : {0} MB/s\n", |                 "Average heap allocation rate: {0} MB/s\n", | ||||||
|                 Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); |                 Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3)); | ||||||
| 
 | 
 | ||||||
|             Process myprocess = Process.GetCurrentProcess(); |             Process myprocess = Process.GetCurrentProcess(); | ||||||
|             if (!myprocess.HasExited) |             if (!myprocess.HasExited) | ||||||
|  |  | ||||||
|  | @ -60,17 +60,17 @@ namespace OpenSim.Framework.Monitoring | ||||||
|         private static bool m_enabled; |         private static bool m_enabled; | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Last memory churn in bytes per millisecond. |         /// Average heap allocation rate in bytes per millisecond. | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public static double AverageMemoryChurn |         public static double AverageHeapAllocationRate | ||||||
|         { |         { | ||||||
|             get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } |             get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Average memory churn in bytes per millisecond. |         /// Last heap allocation in bytes | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public static double LastMemoryChurn |         public static double LastHeapAllocationRate | ||||||
|         { |         { | ||||||
|             get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; } |             get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,349 @@ | ||||||
|  | /* | ||||||
|  |  * Copyright (c) Contributors, http://opensimulator.org/ | ||||||
|  |  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of the OpenSimulator Project nor the | ||||||
|  |  *       names of its contributors may be used to endorse or promote products | ||||||
|  |  *       derived from this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||||
|  |  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||||
|  |  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  |  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||||
|  |  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||||
|  |  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||||
|  |  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||||
|  |  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Diagnostics; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Net.NetworkInformation; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading; | ||||||
|  | using log4net; | ||||||
|  | using Nini.Config; | ||||||
|  | using OpenMetaverse.StructuredData; | ||||||
|  | using OpenSim.Framework; | ||||||
|  | 
 | ||||||
|  | namespace OpenSim.Framework.Monitoring | ||||||
|  | { | ||||||
|  |     public class ServerStatsCollector | ||||||
|  |     { | ||||||
|  |         private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||||||
|  |         private readonly string LogHeader = "[SERVER STATS]"; | ||||||
|  | 
 | ||||||
|  |         public bool Enabled = false; | ||||||
|  |         private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>(); | ||||||
|  | 
 | ||||||
|  |         public readonly string CategoryServer = "server"; | ||||||
|  | 
 | ||||||
|  |         public readonly string ContainerThreadpool = "threadpool"; | ||||||
|  |         public readonly string ContainerProcessor = "processor"; | ||||||
|  |         public readonly string ContainerMemory = "memory"; | ||||||
|  |         public readonly string ContainerNetwork = "network"; | ||||||
|  |         public readonly string ContainerProcess = "process"; | ||||||
|  | 
 | ||||||
|  |         public string NetworkInterfaceTypes = "Ethernet"; | ||||||
|  | 
 | ||||||
|  |         readonly int performanceCounterSampleInterval = 500; | ||||||
|  | //        int lastperformanceCounterSampleTime = 0; | ||||||
|  | 
 | ||||||
|  |         private class PerfCounterControl | ||||||
|  |         { | ||||||
|  |             public PerformanceCounter perfCounter; | ||||||
|  |             public int lastFetch; | ||||||
|  |             public string name; | ||||||
|  |             public PerfCounterControl(PerformanceCounter pPc) | ||||||
|  |                 : this(pPc, String.Empty) | ||||||
|  |             { | ||||||
|  |             } | ||||||
|  |             public PerfCounterControl(PerformanceCounter pPc, string pName) | ||||||
|  |             { | ||||||
|  |                 perfCounter = pPc; | ||||||
|  |                 lastFetch = 0; | ||||||
|  |                 name = pName; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         PerfCounterControl processorPercentPerfCounter = null; | ||||||
|  | 
 | ||||||
|  |         // IRegionModuleBase.Initialize | ||||||
|  |         public void Initialise(IConfigSource source) | ||||||
|  |         { | ||||||
|  |             IConfig cfg = source.Configs["Monitoring"]; | ||||||
|  | 
 | ||||||
|  |             if (cfg != null) | ||||||
|  |                 Enabled = cfg.GetBoolean("ServerStatsEnabled", true); | ||||||
|  | 
 | ||||||
|  |             if (Enabled) | ||||||
|  |             { | ||||||
|  |                 NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void Start() | ||||||
|  |         { | ||||||
|  |             if (RegisteredStats.Count == 0) | ||||||
|  |                 RegisterServerStats(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void Close() | ||||||
|  |         { | ||||||
|  |             if (RegisteredStats.Count > 0) | ||||||
|  |             { | ||||||
|  |                 foreach (Stat stat in RegisteredStats.Values) | ||||||
|  |                 { | ||||||
|  |                     StatsManager.DeregisterStat(stat); | ||||||
|  |                     stat.Dispose(); | ||||||
|  |                 } | ||||||
|  |                 RegisteredStats.Clear(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act) | ||||||
|  |         { | ||||||
|  |             MakeStat(pName, pDesc, pUnit, pContainer, act, MeasuresOfInterest.None); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act, MeasuresOfInterest moi) | ||||||
|  |         { | ||||||
|  |             string desc = pDesc; | ||||||
|  |             if (desc == null) | ||||||
|  |                 desc = pName; | ||||||
|  |             Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, moi, act, StatVerbosity.Debug); | ||||||
|  |             StatsManager.RegisterStat(stat); | ||||||
|  |             RegisteredStats.Add(pName, stat); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void RegisterServerStats() | ||||||
|  |         { | ||||||
|  | //            lastperformanceCounterSampleTime = Util.EnvironmentTickCount(); | ||||||
|  |             PerformanceCounter tempPC; | ||||||
|  |             Stat tempStat; | ||||||
|  |             string tempName; | ||||||
|  | 
 | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 tempName = "CPUPercent"; | ||||||
|  |                 tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total"); | ||||||
|  |                 processorPercentPerfCounter = new PerfCounterControl(tempPC); | ||||||
|  |                 // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy. | ||||||
|  |                 tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor, | ||||||
|  |                                 StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); }, | ||||||
|  |                                 StatVerbosity.Info); | ||||||
|  |                 StatsManager.RegisterStat(tempStat); | ||||||
|  |                 RegisteredStats.Add(tempName, tempStat); | ||||||
|  | 
 | ||||||
|  |                 MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor, | ||||||
|  |                                     (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; }); | ||||||
|  | 
 | ||||||
|  |                 MakeStat("UserProcessorTime", null, "sec", ContainerProcessor, | ||||||
|  |                                     (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; }); | ||||||
|  | 
 | ||||||
|  |                 MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor, | ||||||
|  |                                     (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; }); | ||||||
|  | 
 | ||||||
|  |                 MakeStat("Threads", null, "threads", ContainerProcessor, | ||||||
|  |                                     (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; }); | ||||||
|  |             } | ||||||
|  |             catch (Exception e) | ||||||
|  |             { | ||||||
|  |                 m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool, | ||||||
|  |                 s =>  | ||||||
|  |                 {  | ||||||
|  |                     int workerThreads, iocpThreads;  | ||||||
|  |                     ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);  | ||||||
|  |                     s.Value = workerThreads; | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool, | ||||||
|  |                 s =>  | ||||||
|  |                 {  | ||||||
|  |                     int workerThreads, iocpThreads;  | ||||||
|  |                     ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);  | ||||||
|  |                     s.Value = iocpThreads; | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool && Util.GetSmartThreadPoolInfo() != null) | ||||||
|  |             { | ||||||
|  |                 MakeStat("STPMaxThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxThreads); | ||||||
|  |                 MakeStat("STPMinThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MinThreads); | ||||||
|  |                 MakeStat("STPConcurrency", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxConcurrentWorkItems); | ||||||
|  |                 MakeStat("STPActiveThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().ActiveThreads); | ||||||
|  |                 MakeStat("STPInUseThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().InUseThreads); | ||||||
|  |                 MakeStat("STPWorkItemsWaiting", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().WaitingCallbacks); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             MakeStat( | ||||||
|  |                 "HTTPRequestsMade",  | ||||||
|  |                 "Number of outbound HTTP requests made",  | ||||||
|  |                 "requests",  | ||||||
|  |                 ContainerNetwork,  | ||||||
|  |                 s => s.Value = WebUtil.RequestNumber, | ||||||
|  |                 MeasuresOfInterest.AverageChangeOverTime); | ||||||
|  | 
 | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(',')); | ||||||
|  | 
 | ||||||
|  |                 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces(); | ||||||
|  |                 foreach (NetworkInterface nic in nics) | ||||||
|  |                 { | ||||||
|  |                     if (nic.OperationalStatus != OperationalStatus.Up) | ||||||
|  |                         continue; | ||||||
|  | 
 | ||||||
|  |                     string nicInterfaceType = nic.NetworkInterfaceType.ToString(); | ||||||
|  |                     if (!okInterfaceTypes.Contains(nicInterfaceType)) | ||||||
|  |                     { | ||||||
|  |                         m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.", | ||||||
|  |                                                 LogHeader, nic.Name, nicInterfaceType); | ||||||
|  |                         m_log.DebugFormat("{0}     To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}", | ||||||
|  |                                                 LogHeader, NetworkInterfaceTypes); | ||||||
|  |                         continue; | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     if (nic.Supports(NetworkInterfaceComponent.IPv4)) | ||||||
|  |                     { | ||||||
|  |                         IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics(); | ||||||
|  |                         if (nicStats != null) | ||||||
|  |                         { | ||||||
|  |                             MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork, | ||||||
|  |                                             (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); }); | ||||||
|  |                             MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork, | ||||||
|  |                                             (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); }); | ||||||
|  |                             MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork, | ||||||
|  |                                             (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); }); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     // TODO: add IPv6 (it may actually happen someday) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             catch (Exception e) | ||||||
|  |             { | ||||||
|  |                 m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             MakeStat("ProcessMemory", null, "MB", ContainerMemory, | ||||||
|  |                                 (s) => { s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d, 3); }); | ||||||
|  |             MakeStat("HeapMemory", null, "MB", ContainerMemory, | ||||||
|  |                                 (s) => { s.Value = Math.Round(GC.GetTotalMemory(false) / 1024d / 1024d, 3); }); | ||||||
|  |             MakeStat("LastHeapAllocationRate", null, "MB/sec", ContainerMemory, | ||||||
|  |                                 (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); | ||||||
|  |             MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory, | ||||||
|  |                                 (s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Notes on performance counters:  | ||||||
|  |         //  "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx | ||||||
|  |         //  "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c | ||||||
|  |         //  "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters | ||||||
|  |         private delegate double PerfCounterNextValue(); | ||||||
|  |         private void GetNextValue(Stat stat, PerfCounterControl perfControl) | ||||||
|  |         { | ||||||
|  |             GetNextValue(stat, perfControl, 1.0); | ||||||
|  |         } | ||||||
|  |         private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor) | ||||||
|  |         { | ||||||
|  |             if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval) | ||||||
|  |             { | ||||||
|  |                 if (perfControl != null && perfControl.perfCounter != null) | ||||||
|  |                 { | ||||||
|  |                     try | ||||||
|  |                     { | ||||||
|  |                         // Kludge for factor to run double duty. If -1, subtract the value from one | ||||||
|  |                         if (factor == -1) | ||||||
|  |                             stat.Value = 1 - perfControl.perfCounter.NextValue(); | ||||||
|  |                         else | ||||||
|  |                             stat.Value = perfControl.perfCounter.NextValue() / factor; | ||||||
|  |                     } | ||||||
|  |                     catch (Exception e) | ||||||
|  |                     { | ||||||
|  |                         m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e); | ||||||
|  |                     } | ||||||
|  |                     perfControl.lastFetch = Util.EnvironmentTickCount(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Lookup the nic that goes with this stat and set the value by using a fetch action. | ||||||
|  |         // Not sure about closure with delegates inside delegates. | ||||||
|  |         private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat); | ||||||
|  |         private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor) | ||||||
|  |         { | ||||||
|  |             // Get the one nic that has the name of this stat | ||||||
|  |             IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where( | ||||||
|  |                                   (network) => network.Name == stat.Description); | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 foreach (NetworkInterface nic in nics) | ||||||
|  |                 { | ||||||
|  |                     IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics(); | ||||||
|  |                     if (intrStats != null) | ||||||
|  |                     { | ||||||
|  |                         double newVal = Math.Round(getter(intrStats) / factor, 3); | ||||||
|  |                         stat.Value = newVal; | ||||||
|  |                     } | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             catch | ||||||
|  |             { | ||||||
|  |                 // There are times interfaces go away so we just won't update the stat for this | ||||||
|  |                 m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class ServerStatsAggregator : Stat | ||||||
|  |     { | ||||||
|  |         public ServerStatsAggregator( | ||||||
|  |             string shortName, | ||||||
|  |             string name, | ||||||
|  |             string description, | ||||||
|  |             string unitName, | ||||||
|  |             string category, | ||||||
|  |             string container | ||||||
|  |             ) | ||||||
|  |             : base( | ||||||
|  |                 shortName, | ||||||
|  |                 name, | ||||||
|  |                 description, | ||||||
|  |                 unitName, | ||||||
|  |                 category, | ||||||
|  |                 container, | ||||||
|  |                 StatType.Push, | ||||||
|  |                 MeasuresOfInterest.None, | ||||||
|  |                 null, | ||||||
|  |                 StatVerbosity.Info) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  |         public override string ToConsoleString() | ||||||
|  |         { | ||||||
|  |             StringBuilder sb = new StringBuilder(); | ||||||
|  | 
 | ||||||
|  |             return sb.ToString(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public override OSDMap ToOSDMap() | ||||||
|  |         { | ||||||
|  |             OSDMap ret = new OSDMap(); | ||||||
|  | 
 | ||||||
|  |             return ret; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -27,8 +27,10 @@ | ||||||
| 
 | 
 | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Reflection; | ||||||
| using System.Text; | using System.Text; | ||||||
| 
 | using log4net; | ||||||
| using OpenMetaverse.StructuredData; | using OpenMetaverse.StructuredData; | ||||||
| 
 | 
 | ||||||
| namespace OpenSim.Framework.Monitoring | namespace OpenSim.Framework.Monitoring | ||||||
|  | @ -38,6 +40,10 @@ namespace OpenSim.Framework.Monitoring | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public class Stat : IDisposable |     public class Stat : IDisposable | ||||||
|     { |     { | ||||||
|  | //        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||||
|  | 
 | ||||||
|  |         public static readonly char[] DisallowedShortNameCharacters = { '.' }; | ||||||
|  | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Category of this stat (e.g. cache, scene, etc). |         /// Category of this stat (e.g. cache, scene, etc). | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -95,7 +101,7 @@ namespace OpenSim.Framework.Monitoring | ||||||
|         /// <remarks> |         /// <remarks> | ||||||
|         /// Will be null if no measures of interest require samples. |         /// Will be null if no measures of interest require samples. | ||||||
|         /// </remarks> |         /// </remarks> | ||||||
|         private static Queue<double> m_samples; |         private Queue<double> m_samples; | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Maximum number of statistical samples. |         /// Maximum number of statistical samples. | ||||||
|  | @ -162,6 +168,12 @@ namespace OpenSim.Framework.Monitoring | ||||||
|                 throw new Exception( |                 throw new Exception( | ||||||
|                     string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category)); |                     string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category)); | ||||||
| 
 | 
 | ||||||
|  |             foreach (char c in DisallowedShortNameCharacters) | ||||||
|  |             { | ||||||
|  |                 if (shortName.IndexOf(c) != -1) | ||||||
|  |                     throw new Exception(string.Format("Stat name {0} cannot contain character {1}", shortName, c)); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             ShortName = shortName; |             ShortName = shortName; | ||||||
|             Name = name; |             Name = name; | ||||||
|             Description = description; |             Description = description; | ||||||
|  | @ -204,6 +216,8 @@ namespace OpenSim.Framework.Monitoring | ||||||
|                 if (m_samples.Count >= m_maxSamples) |                 if (m_samples.Count >= m_maxSamples) | ||||||
|                     m_samples.Dequeue(); |                     m_samples.Dequeue(); | ||||||
| 
 | 
 | ||||||
|  | //                m_log.DebugFormat("[STAT]: Recording value {0} for {1}", newValue, Name); | ||||||
|  | 
 | ||||||
|                 m_samples.Enqueue(newValue); |                 m_samples.Enqueue(newValue); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -242,6 +256,10 @@ namespace OpenSim.Framework.Monitoring | ||||||
| 
 | 
 | ||||||
|                 lock (m_samples) |                 lock (m_samples) | ||||||
|                 { |                 { | ||||||
|  | //                    m_log.DebugFormat( | ||||||
|  | //                        "[STAT]: Samples for {0} are {1}",  | ||||||
|  | //                        Name, string.Join(",", m_samples.Select(s => s.ToString()).ToArray())); | ||||||
|  | 
 | ||||||
|                     foreach (double s in m_samples) |                     foreach (double s in m_samples) | ||||||
|                     { |                     { | ||||||
|                         if (lastSample != null) |                         if (lastSample != null) | ||||||
|  | @ -253,7 +271,7 @@ namespace OpenSim.Framework.Monitoring | ||||||
| 
 | 
 | ||||||
|                 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1; |                 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1; | ||||||
| 
 | 
 | ||||||
|                 sb.AppendFormat(", {0:0.##}{1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName); |                 sb.AppendFormat(", {0:0.##} {1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ | ||||||
| 
 | 
 | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
| using System.Text; | using System.Text; | ||||||
| 
 | 
 | ||||||
| namespace OpenSim.Framework.Monitoring | namespace OpenSim.Framework.Monitoring | ||||||
|  | @ -54,13 +55,13 @@ namespace OpenSim.Framework.Monitoring | ||||||
|         public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats |         public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats | ||||||
|             = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>(); |             = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>(); | ||||||
| 
 | 
 | ||||||
|         private static AssetStatsCollector assetStats; | //        private static AssetStatsCollector assetStats; | ||||||
|         private static UserStatsCollector userStats; | //        private static UserStatsCollector userStats; | ||||||
|         private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); | //        private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); | ||||||
| 
 | 
 | ||||||
|         public static AssetStatsCollector AssetStats { get { return assetStats; } } | //        public static AssetStatsCollector AssetStats { get { return assetStats; } } | ||||||
|         public static UserStatsCollector UserStats { get { return userStats; } } | //        public static UserStatsCollector UserStats { get { return userStats; } } | ||||||
|         public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } |         public static SimExtraStatsCollector SimExtraStats { get; set; } | ||||||
| 
 | 
 | ||||||
|         public static void RegisterConsoleCommands(ICommandConsole console) |         public static void RegisterConsoleCommands(ICommandConsole console) | ||||||
|         { |         { | ||||||
|  | @ -68,12 +69,14 @@ namespace OpenSim.Framework.Monitoring | ||||||
|                 "General", |                 "General", | ||||||
|                 false, |                 false, | ||||||
|                 "show stats", |                 "show stats", | ||||||
|                 "show stats [list|all|<category>]", |                 "show stats [list|all|(<category>[.<container>])+", | ||||||
|                 "Show statistical information for this server", |                 "Show statistical information for this server", | ||||||
|                 "If no final argument is specified then legacy statistics information is currently shown.\n" |                 "If no final argument is specified then legacy statistics information is currently shown.\n" | ||||||
|                     + "If list is specified then statistic categories are shown.\n" |                     + "'list' argument will show statistic categories.\n" | ||||||
|                     + "If all is specified then all registered statistics are shown.\n" |                     + "'all' will show all statistics.\n" | ||||||
|                     + "If a category name is specified then only statistics from that category are shown.\n" |                     + "A <category> name will show statistics from that category.\n" | ||||||
|  |                     + "A <category>.<container> name will show statistics from that category in that container.\n" | ||||||
|  |                     + "More than one name can be given separated by spaces.\n" | ||||||
|                     + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", |                     + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", | ||||||
|                 HandleShowStatsCommand); |                 HandleShowStatsCommand); | ||||||
|         } |         } | ||||||
|  | @ -84,15 +87,16 @@ namespace OpenSim.Framework.Monitoring | ||||||
| 
 | 
 | ||||||
|             if (cmd.Length > 2) |             if (cmd.Length > 2) | ||||||
|             { |             { | ||||||
|                 var categoryName = cmd[2]; |                 foreach (string name in cmd.Skip(2)) | ||||||
|                 var containerName = cmd.Length > 3 ? cmd[3] : String.Empty; |                 { | ||||||
|  |                     string[] components = name.Split('.'); | ||||||
|  | 
 | ||||||
|  |                     string categoryName = components[0]; | ||||||
|  |                     string containerName = components.Length > 1 ? components[1] : null; | ||||||
| 
 | 
 | ||||||
|                     if (categoryName == AllSubCommand) |                     if (categoryName == AllSubCommand) | ||||||
|                     { |                     { | ||||||
|                     foreach (var category in RegisteredStats.Values) |                         OutputAllStatsToConsole(con); | ||||||
|                     { |  | ||||||
|                         OutputCategoryStatsToConsole(con, category); |  | ||||||
|                     } |  | ||||||
|                     } |                     } | ||||||
|                     else if (categoryName == ListSubCommand) |                     else if (categoryName == ListSubCommand) | ||||||
|                     { |                     { | ||||||
|  | @ -110,7 +114,9 @@ namespace OpenSim.Framework.Monitoring | ||||||
|                         else |                         else | ||||||
|                         { |                         { | ||||||
|                             if (String.IsNullOrEmpty(containerName)) |                             if (String.IsNullOrEmpty(containerName)) | ||||||
|  |                             { | ||||||
|                                 OutputCategoryStatsToConsole(con, category); |                                 OutputCategoryStatsToConsole(con, category); | ||||||
|  |                             } | ||||||
|                             else |                             else | ||||||
|                             { |                             { | ||||||
|                                 SortedDictionary<string, Stat> container; |                                 SortedDictionary<string, Stat> container; | ||||||
|  | @ -126,10 +132,22 @@ namespace OpenSim.Framework.Monitoring | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 // Legacy |                 // Legacy | ||||||
|  |                 if (SimExtraStats != null) | ||||||
|                     con.Output(SimExtraStats.Report()); |                     con.Output(SimExtraStats.Report()); | ||||||
|  |                 else | ||||||
|  |                     OutputAllStatsToConsole(con); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static void OutputAllStatsToConsole(ICommandConsole con) | ||||||
|  |         { | ||||||
|  |             foreach (var category in RegisteredStats.Values) | ||||||
|  |             { | ||||||
|  |                 OutputCategoryStatsToConsole(con, category); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -150,27 +168,27 @@ namespace OpenSim.Framework.Monitoring | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> | //        /// <summary> | ||||||
|         /// Start collecting statistics related to assets. | //        /// Start collecting statistics related to assets. | ||||||
|         /// Should only be called once. | //        /// Should only be called once. | ||||||
|         /// </summary> | //        /// </summary> | ||||||
|         public static AssetStatsCollector StartCollectingAssetStats() | //        public static AssetStatsCollector StartCollectingAssetStats() | ||||||
|         { | //        { | ||||||
|             assetStats = new AssetStatsCollector(); | //            assetStats = new AssetStatsCollector(); | ||||||
| 
 | // | ||||||
|             return assetStats; | //            return assetStats; | ||||||
|         } | //        } | ||||||
| 
 | // | ||||||
|         /// <summary> | //        /// <summary> | ||||||
|         /// Start collecting statistics related to users. | //        /// Start collecting statistics related to users. | ||||||
|         /// Should only be called once. | //        /// Should only be called once. | ||||||
|         /// </summary> | //        /// </summary> | ||||||
|         public static UserStatsCollector StartCollectingUserStats() | //        public static UserStatsCollector StartCollectingUserStats() | ||||||
|         { | //        { | ||||||
|             userStats = new UserStatsCollector(); | //            userStats = new UserStatsCollector(); | ||||||
| 
 | // | ||||||
|             return userStats; | //            return userStats; | ||||||
|         } | //        } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Registers a statistic. |         /// Registers a statistic. | ||||||
|  |  | ||||||
|  | @ -86,24 +86,21 @@ namespace OpenSim.Framework.Servers | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         protected virtual void StartupSpecific() |         protected virtual void StartupSpecific() | ||||||
|         { |         { | ||||||
|             if (m_console == null) |             StatsManager.SimExtraStats = new SimExtraStatsCollector(); | ||||||
|                 return; |  | ||||||
| 
 |  | ||||||
|             RegisterCommonCommands(); |             RegisterCommonCommands(); | ||||||
|              |             RegisterCommonComponents(Config); | ||||||
|             m_console.Commands.AddCommand("General", false, "quit", |  | ||||||
|                     "quit", |  | ||||||
|                     "Quit the application", HandleQuit); |  | ||||||
| 
 |  | ||||||
|             m_console.Commands.AddCommand("General", false, "shutdown", |  | ||||||
|                     "shutdown", |  | ||||||
|                     "Quit the application", HandleQuit); |  | ||||||
|         }        |         }        | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         protected override void ShutdownSpecific() | ||||||
|         /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing |         {             | ||||||
|         /// </summary> |             m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete.  Exiting..."); | ||||||
|         public virtual void ShutdownSpecific() {} | 
 | ||||||
|  |             RemovePIDFile(); | ||||||
|  | 
 | ||||||
|  |             base.ShutdownSpecific(); | ||||||
|  | 
 | ||||||
|  |             Environment.Exit(0); | ||||||
|  |         } | ||||||
|          |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Provides a list of help topics that are available.  Overriding classes should append their topics to the |         /// Provides a list of help topics that are available.  Overriding classes should append their topics to the | ||||||
|  | @ -153,25 +150,8 @@ namespace OpenSim.Framework.Servers | ||||||
|                 timeTaken.Minutes, timeTaken.Seconds); |                 timeTaken.Minutes, timeTaken.Seconds); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         public string osSecret  | ||||||
|         /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing |  | ||||||
|         /// </summary> |  | ||||||
|         public virtual void Shutdown() |  | ||||||
|         { |         { | ||||||
|             ShutdownSpecific(); |  | ||||||
|              |  | ||||||
|             m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete.  Exiting..."); |  | ||||||
|             RemovePIDFile(); |  | ||||||
|              |  | ||||||
|             Environment.Exit(0); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private void HandleQuit(string module, string[] args) |  | ||||||
|         { |  | ||||||
|             Shutdown(); |  | ||||||
|         }       |  | ||||||
|          |  | ||||||
|         public string osSecret { |  | ||||||
|             // Secret uuid for the simulator |             // Secret uuid for the simulator | ||||||
|             get { return m_osSecret; }             |             get { return m_osSecret; }             | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -54,7 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||||
|         private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); |         private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// This is a pending websocket request before it got an sucessful upgrade response. |         /// This is a pending websocket request before it got an sucessful upgrade response. | ||||||
|         /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to  |         /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to  | ||||||
|  | @ -81,6 +80,11 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|         /// </remarks> |         /// </remarks> | ||||||
|         public int RequestNumber { get; private set; } |         public int RequestNumber { get; private set; } | ||||||
| 
 | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Statistic for holding number of requests processed. | ||||||
|  |         /// </summary> | ||||||
|  |         private Stat m_requestsProcessedStat; | ||||||
|  | 
 | ||||||
|         private volatile int NotSocketErrors = 0; |         private volatile int NotSocketErrors = 0; | ||||||
|         public volatile bool HTTPDRunning = false; |         public volatile bool HTTPDRunning = false; | ||||||
| 
 | 
 | ||||||
|  | @ -437,9 +441,8 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request) |         private void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request) | ||||||
|         { |         { | ||||||
| 
 |  | ||||||
|             OSHttpRequest req = new OSHttpRequest(context, request); |             OSHttpRequest req = new OSHttpRequest(context, request); | ||||||
|             WebSocketRequestDelegate dWebSocketRequestDelegate = null; |             WebSocketRequestDelegate dWebSocketRequestDelegate = null; | ||||||
|             lock (m_WebSocketHandlers) |             lock (m_WebSocketHandlers) | ||||||
|  | @ -457,7 +460,6 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|             resp.ReuseContext = true; |             resp.ReuseContext = true; | ||||||
|             HandleRequest(req, resp);            |             HandleRequest(req, resp);            | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|             // !!!HACK ALERT!!! |             // !!!HACK ALERT!!! | ||||||
|             // There seems to be a bug in the underlying http code that makes subsequent requests |             // There seems to be a bug in the underlying http code that makes subsequent requests | ||||||
|             // come up with trash in Accept headers. Until that gets fixed, we're cleaning them up here. |             // come up with trash in Accept headers. Until that gets fixed, we're cleaning them up here. | ||||||
|  | @ -1870,6 +1872,21 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|                 // useful without inbound HTTP. |                 // useful without inbound HTTP. | ||||||
|                 throw e; |                 throw e; | ||||||
|             } |             } | ||||||
|  | 
 | ||||||
|  |             m_requestsProcessedStat  | ||||||
|  |                 = new Stat( | ||||||
|  |                     "HTTPRequestsServed", | ||||||
|  |                     "Number of inbound HTTP requests processed", | ||||||
|  |                     "", | ||||||
|  |                     "requests", | ||||||
|  |                     "httpserver", | ||||||
|  |                     Port.ToString(), | ||||||
|  |                     StatType.Pull, | ||||||
|  |                     MeasuresOfInterest.AverageChangeOverTime, | ||||||
|  |                     stat => stat.Value = RequestNumber, | ||||||
|  |                     StatVerbosity.Debug); | ||||||
|  |            | ||||||
|  |             StatsManager.RegisterStat(m_requestsProcessedStat); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err) |         public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err) | ||||||
|  | @ -1902,6 +1919,9 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|         public void Stop() |         public void Stop() | ||||||
|         { |         { | ||||||
|             HTTPDRunning = false; |             HTTPDRunning = false; | ||||||
|  | 
 | ||||||
|  |             StatsManager.DeregisterStat(m_requestsProcessedStat); | ||||||
|  | 
 | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 m_PollServiceManager.Stop(); |                 m_PollServiceManager.Stop(); | ||||||
|  |  | ||||||
|  | @ -75,7 +75,7 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// This is a regular HTTP Request...    This may be removed in the future.    |         /// This is a regular HTTP Request...    This may be removed in the future.    | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public event RegularHttpRequestDelegate OnRegularHttpRequest; | //        public event RegularHttpRequestDelegate OnRegularHttpRequest; | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired |         /// 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 | ||||||
|                 if (d != null) |                 if (d != null) | ||||||
|                     d(this, new UpgradeCompletedEventArgs()); |                     d(this, new UpgradeCompletedEventArgs()); | ||||||
|             } |             } | ||||||
|             catch (IOException fail) |             catch (IOException) | ||||||
|             { |             { | ||||||
|                 Close(string.Empty); |                 Close(string.Empty); | ||||||
|             } |             } | ||||||
|             catch (ObjectDisposedException fail) |             catch (ObjectDisposedException) | ||||||
|             { |             { | ||||||
|                 Close(string.Empty); |                 Close(string.Empty); | ||||||
|             }            |             }            | ||||||
|              |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|  | @ -414,8 +413,6 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|                                 _socketState.Header = pheader; |                                 _socketState.Header = pheader; | ||||||
|                             } |                             } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|                             if (_socketState.FrameComplete) |                             if (_socketState.FrameComplete) | ||||||
|                             { |                             { | ||||||
|                                 ProcessFrame(_socketState); |                                 ProcessFrame(_socketState); | ||||||
|  | @ -424,7 +421,6 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|                                 _socketState.ExpectedBytes = 0; |                                 _socketState.ExpectedBytes = 0; | ||||||
| 
 | 
 | ||||||
|                             } |                             } | ||||||
| 
 |  | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     else |                     else | ||||||
|  | @ -458,7 +454,6 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|                             _socketState.ExpectedBytes = 0; |                             _socketState.ExpectedBytes = 0; | ||||||
|                             // do some processing |                             // do some processing | ||||||
|                         }                        |                         }                        | ||||||
| 
 |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 if (offset > 0) |                 if (offset > 0) | ||||||
|  | @ -477,13 +472,12 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|                 { |                 { | ||||||
|                     // We can't read the stream anymore...   |                     // We can't read the stream anymore...   | ||||||
|                 } |                 } | ||||||
| 
 |  | ||||||
|             } |             } | ||||||
|             catch (IOException fail) |             catch (IOException) | ||||||
|             { |             { | ||||||
|                 Close(string.Empty); |                 Close(string.Empty); | ||||||
|             } |             } | ||||||
|             catch (ObjectDisposedException fail) |             catch (ObjectDisposedException) | ||||||
|             { |             { | ||||||
|                 Close(string.Empty); |                 Close(string.Empty); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -62,6 +62,8 @@ namespace OpenSim.Framework.Servers | ||||||
| 
 | 
 | ||||||
|         protected string m_pidFile = String.Empty; |         protected string m_pidFile = String.Empty; | ||||||
| 
 | 
 | ||||||
|  |         protected ServerStatsCollector m_serverStatsCollector; | ||||||
|  | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Server version information.  Usually VersionInfo + information about git commit, operating system, etc. |         /// Server version information.  Usually VersionInfo + information about git commit, operating system, etc. | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -259,6 +261,25 @@ namespace OpenSim.Framework.Servers | ||||||
|                 "force gc", |                 "force gc", | ||||||
|                 "Manually invoke runtime garbage collection.  For debugging purposes", |                 "Manually invoke runtime garbage collection.  For debugging purposes", | ||||||
|                 HandleForceGc); |                 HandleForceGc); | ||||||
|  | 
 | ||||||
|  |             m_console.Commands.AddCommand( | ||||||
|  |                 "General", false, "quit", | ||||||
|  |                 "quit", | ||||||
|  |                 "Quit the application", (mod, args) => Shutdown()); | ||||||
|  | 
 | ||||||
|  |             m_console.Commands.AddCommand( | ||||||
|  |                 "General", false, "shutdown", | ||||||
|  |                 "shutdown", | ||||||
|  |                 "Quit the application", (mod, args) => Shutdown()); | ||||||
|  | 
 | ||||||
|  |             StatsManager.RegisterConsoleCommands(m_console); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void RegisterCommonComponents(IConfigSource configSource) | ||||||
|  |         { | ||||||
|  |             m_serverStatsCollector = new ServerStatsCollector(); | ||||||
|  |             m_serverStatsCollector.Initialise(configSource); | ||||||
|  |             m_serverStatsCollector.Start(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void HandleForceGc(string module, string[] args) |         private void HandleForceGc(string module, string[] args) | ||||||
|  | @ -646,7 +667,68 @@ namespace OpenSim.Framework.Servers | ||||||
|                 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); |                 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); | ||||||
| 
 | 
 | ||||||
|             sb.Append("Main threadpool (excluding script engine pools)\n"); |             sb.Append("Main threadpool (excluding script engine pools)\n"); | ||||||
|             sb.Append(Util.GetThreadPoolReport()); |             sb.Append(GetThreadPoolReport()); | ||||||
|  | 
 | ||||||
|  |             return sb.ToString(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Get a thread pool report. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public static string GetThreadPoolReport() | ||||||
|  |         { | ||||||
|  |             string threadPoolUsed = null; | ||||||
|  |             int maxThreads = 0; | ||||||
|  |             int minThreads = 0; | ||||||
|  |             int allocatedThreads = 0; | ||||||
|  |             int inUseThreads = 0; | ||||||
|  |             int waitingCallbacks = 0; | ||||||
|  |             int completionPortThreads = 0; | ||||||
|  | 
 | ||||||
|  |             StringBuilder sb = new StringBuilder(); | ||||||
|  |             if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) | ||||||
|  |             { | ||||||
|  |                 STPInfo stpi = Util.GetSmartThreadPoolInfo(); | ||||||
|  | 
 | ||||||
|  |                 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool. | ||||||
|  |                 if (stpi != null) | ||||||
|  |                 { | ||||||
|  |                     threadPoolUsed = "SmartThreadPool"; | ||||||
|  |                     maxThreads = stpi.MaxThreads; | ||||||
|  |                     minThreads = stpi.MinThreads; | ||||||
|  |                     inUseThreads = stpi.InUseThreads; | ||||||
|  |                     allocatedThreads = stpi.ActiveThreads; | ||||||
|  |                     waitingCallbacks = stpi.WaitingCallbacks; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else if ( | ||||||
|  |                 Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem | ||||||
|  |                     || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem) | ||||||
|  |             { | ||||||
|  |                 threadPoolUsed = "BuiltInThreadPool"; | ||||||
|  |                 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads); | ||||||
|  |                 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads); | ||||||
|  |                 int availableThreads; | ||||||
|  |                 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads); | ||||||
|  |                 inUseThreads = maxThreads - availableThreads; | ||||||
|  |                 allocatedThreads = -1; | ||||||
|  |                 waitingCallbacks = -1; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (threadPoolUsed != null) | ||||||
|  |             { | ||||||
|  |                 sb.AppendFormat("Thread pool used           : {0}\n", threadPoolUsed); | ||||||
|  |                 sb.AppendFormat("Max threads                : {0}\n", maxThreads); | ||||||
|  |                 sb.AppendFormat("Min threads                : {0}\n", minThreads); | ||||||
|  |                 sb.AppendFormat("Allocated threads          : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString()); | ||||||
|  |                 sb.AppendFormat("In use threads             : {0}\n", inUseThreads); | ||||||
|  |                 sb.AppendFormat("Work items waiting         : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString()); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 sb.AppendFormat("Thread pool not used\n"); | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             return sb.ToString(); |             return sb.ToString(); | ||||||
|         } |         } | ||||||
|  | @ -698,5 +780,16 @@ namespace OpenSim.Framework.Servers | ||||||
|             if (m_console != null) |             if (m_console != null) | ||||||
|                 m_console.OutputFormat(format, components); |                 m_console.OutputFormat(format, components); | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         public virtual void Shutdown() | ||||||
|  |         { | ||||||
|  |             m_serverStatsCollector.Close(); | ||||||
|  |             ShutdownSpecific(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing | ||||||
|  |         /// </summary> | ||||||
|  |         protected virtual void ShutdownSpecific() {} | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -88,10 +88,31 @@ namespace OpenSim.Framework | ||||||
|         Thread, |         Thread, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// <summary> | ||||||
|  |     /// Class for delivering SmartThreadPool statistical information | ||||||
|  |     /// </summary> | ||||||
|  |     /// <remarks> | ||||||
|  |     /// We do it this way so that we do not directly expose STP. | ||||||
|  |     /// </remarks> | ||||||
|  |     public class STPInfo | ||||||
|  |     { | ||||||
|  |         public string Name { get; set; } | ||||||
|  |         public STPStartInfo STPStartInfo { get; set; } | ||||||
|  |         public WIGStartInfo WIGStartInfo { get; set; } | ||||||
|  |         public bool IsIdle { get; set; } | ||||||
|  |         public bool IsShuttingDown { get; set; }        | ||||||
|  |         public int MaxThreads { get; set; } | ||||||
|  |         public int MinThreads { get; set; } | ||||||
|  |         public int InUseThreads { get; set; } | ||||||
|  |         public int ActiveThreads { get; set; } | ||||||
|  |         public int WaitingCallbacks { get; set; } | ||||||
|  |         public int MaxConcurrentWorkItems { get; set; } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// Miscellaneous utility functions |     /// Miscellaneous utility functions | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public class Util |     public static class Util | ||||||
|     { |     { | ||||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||||
| 
 | 
 | ||||||
|  | @ -1864,73 +1885,30 @@ namespace OpenSim.Framework | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Get a thread pool report. |         /// Get information about the current state of the smart thread pool. | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <returns></returns> |         /// <returns> | ||||||
|         public static string GetThreadPoolReport() |         /// null if this isn't the pool being used for non-scriptengine threads. | ||||||
|  |         /// </returns> | ||||||
|  |         public static STPInfo GetSmartThreadPoolInfo() | ||||||
|         { |         { | ||||||
|             string threadPoolUsed = null; |             if (m_ThreadPool == null) | ||||||
|             int maxThreads = 0; |                 return null; | ||||||
|             int minThreads = 0; |  | ||||||
|             int allocatedThreads = 0; |  | ||||||
|             int inUseThreads = 0; |  | ||||||
|             int waitingCallbacks = 0; |  | ||||||
|             int completionPortThreads = 0; |  | ||||||
| 
 | 
 | ||||||
|             StringBuilder sb = new StringBuilder(); |             STPInfo stpi = new STPInfo(); | ||||||
|             if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) |             stpi.Name = m_ThreadPool.Name; | ||||||
|             { |             stpi.STPStartInfo = m_ThreadPool.STPStartInfo; | ||||||
|                 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool. |             stpi.IsIdle = m_ThreadPool.IsIdle; | ||||||
|                 if (m_ThreadPool != null) |             stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown; | ||||||
|                 { |             stpi.MaxThreads = m_ThreadPool.MaxThreads; | ||||||
|                     threadPoolUsed = "SmartThreadPool"; |             stpi.MinThreads = m_ThreadPool.MinThreads; | ||||||
|                     maxThreads = m_ThreadPool.MaxThreads; |             stpi.InUseThreads = m_ThreadPool.InUseThreads; | ||||||
|                     minThreads = m_ThreadPool.MinThreads; |             stpi.ActiveThreads = m_ThreadPool.ActiveThreads; | ||||||
|                     inUseThreads = m_ThreadPool.InUseThreads; |             stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks; | ||||||
|                     allocatedThreads = m_ThreadPool.ActiveThreads; |             stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency; | ||||||
|                     waitingCallbacks = m_ThreadPool.WaitingCallbacks; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else if ( |  | ||||||
|                 FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem |  | ||||||
|                     || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem) |  | ||||||
|             { |  | ||||||
|                 threadPoolUsed = "BuiltInThreadPool"; |  | ||||||
|                 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads); |  | ||||||
|                 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads); |  | ||||||
|                 int availableThreads; |  | ||||||
|                 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads); |  | ||||||
|                 inUseThreads = maxThreads - availableThreads; |  | ||||||
|                 allocatedThreads = -1; |  | ||||||
|                 waitingCallbacks = -1; |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             if (threadPoolUsed != null) |             return stpi; | ||||||
|             { |  | ||||||
|                 sb.AppendFormat("Thread pool used           : {0}\n", threadPoolUsed); |  | ||||||
|                 sb.AppendFormat("Max threads                : {0}\n", maxThreads); |  | ||||||
|                 sb.AppendFormat("Min threads                : {0}\n", minThreads); |  | ||||||
|                 sb.AppendFormat("Allocated threads          : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString()); |  | ||||||
|                 sb.AppendFormat("In use threads             : {0}\n", inUseThreads); |  | ||||||
|                 sb.AppendFormat("Work items waiting         : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString()); |  | ||||||
|         } |         } | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 sb.AppendFormat("Thread pool not used\n"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return sb.ToString(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
| //        private static object SmartThreadPoolCallback(object o) |  | ||||||
| //        { |  | ||||||
| //            object[] array = (object[])o; |  | ||||||
| //            WaitCallback callback = (WaitCallback)array[0]; |  | ||||||
| //            object obj = array[1]; |  | ||||||
| // |  | ||||||
| //            callback(obj); |  | ||||||
| //            return null; |  | ||||||
| //        } |  | ||||||
| 
 | 
 | ||||||
|         #endregion FireAndForget Threading Pattern |         #endregion FireAndForget Threading Pattern | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -124,6 +124,7 @@ namespace OpenSim | ||||||
|                 workerThreads = workerThreadsMax; |                 workerThreads = workerThreadsMax; | ||||||
|                 m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads); |                 m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads); | ||||||
|             } |             } | ||||||
|  | 
 | ||||||
| 			// Increase the number of IOCP threads available. | 			// Increase the number of IOCP threads available. | ||||||
| 			// Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17) | 			// Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17) | ||||||
| 			if (iocpThreads < iocpThreadsMin) | 			if (iocpThreads < iocpThreadsMin) | ||||||
|  |  | ||||||
|  | @ -372,7 +372,7 @@ namespace OpenSim | ||||||
|                                           "Unload a module", HandleModules); |                                           "Unload a module", HandleModules); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public override void ShutdownSpecific() |         protected override void ShutdownSpecific() | ||||||
|         { |         { | ||||||
|             if (m_shutdownCommandsFile != String.Empty) |             if (m_shutdownCommandsFile != String.Empty) | ||||||
|             { |             { | ||||||
|  |  | ||||||
|  | @ -246,11 +246,8 @@ namespace OpenSim | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (m_console != null) |             if (m_console != null) | ||||||
|             { |  | ||||||
|                 StatsManager.RegisterConsoleCommands(m_console); |  | ||||||
|                 AddPluginCommands(m_console); |                 AddPluginCommands(m_console); | ||||||
|         } |         } | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         protected virtual void AddPluginCommands(ICommandConsole console) |         protected virtual void AddPluginCommands(ICommandConsole console) | ||||||
|         { |         { | ||||||
|  | @ -964,7 +961,7 @@ namespace OpenSim | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Performs any last-minute sanity checking and shuts down the region server |         /// Performs any last-minute sanity checking and shuts down the region server | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public override void ShutdownSpecific() |         protected override void ShutdownSpecific() | ||||||
|         { |         { | ||||||
|             if (proxyUrl.Length > 0) |             if (proxyUrl.Length > 0) | ||||||
|             { |             { | ||||||
|  | @ -984,6 +981,8 @@ namespace OpenSim | ||||||
|             { |             { | ||||||
|                 m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e); |                 m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e); | ||||||
|             } |             } | ||||||
|  | 
 | ||||||
|  |             base.ShutdownSpecific(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <summary> | ||||||
|  |  | ||||||
|  | @ -33,6 +33,7 @@ using NUnit.Framework; | ||||||
| using OpenMetaverse; | using OpenMetaverse; | ||||||
| using OpenMetaverse.Packets; | using OpenMetaverse.Packets; | ||||||
| using OpenSim.Framework; | using OpenSim.Framework; | ||||||
|  | using OpenSim.Framework.Monitoring; | ||||||
| using OpenSim.Region.Framework.Scenes; | using OpenSim.Region.Framework.Scenes; | ||||||
| using OpenSim.Tests.Common; | using OpenSim.Tests.Common; | ||||||
| using OpenSim.Tests.Common.Mock; | using OpenSim.Tests.Common.Mock; | ||||||
|  | @ -69,6 +70,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | ||||||
|         { |         { | ||||||
|             base.SetUp(); |             base.SetUp(); | ||||||
|             m_scene = new SceneHelpers().SetupScene(); |             m_scene = new SceneHelpers().SetupScene(); | ||||||
|  |             StatsManager.SimExtraStats = new SimExtraStatsCollector(); | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|  | @ -210,8 +212,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | ||||||
| 
 | 
 | ||||||
|             ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID); |             ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID); | ||||||
|             Assert.That(spAfterAckTimeout, Is.Null); |             Assert.That(spAfterAckTimeout, Is.Null); | ||||||
| 
 |  | ||||||
| //            TestHelpers.DisableLogging(); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| //        /// <summary> | //        /// <summary> | ||||||
|  |  | ||||||
|  | @ -53,8 +53,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | ||||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||||
| 
 | 
 | ||||||
|         private int m_levelHGTeleport = 0; |         private int m_levelHGTeleport = 0; | ||||||
|  |         private string m_ThisHomeURI; | ||||||
| 
 | 
 | ||||||
|         private GatekeeperServiceConnector m_GatekeeperConnector; |         private GatekeeperServiceConnector m_GatekeeperConnector; | ||||||
|  |         private IUserAgentService m_UAS; | ||||||
| 
 | 
 | ||||||
|         protected bool m_RestrictAppearanceAbroad; |         protected bool m_RestrictAppearanceAbroad; | ||||||
|         protected string m_AccountName; |         protected string m_AccountName; | ||||||
|  | @ -143,6 +145,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | ||||||
|                     m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); |                     m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | 
 | ||||||
|  |             moduleConfig = source.Configs["Hypergrid"]; | ||||||
|  |             if (moduleConfig != null) | ||||||
|  |             { | ||||||
|  |                 m_ThisHomeURI = moduleConfig.GetString("HomeURI", string.Empty); | ||||||
|  |                 if (m_ThisHomeURI != string.Empty && !m_ThisHomeURI.EndsWith("/")) | ||||||
|  |                     m_ThisHomeURI += '/'; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public override void AddRegion(Scene scene) |         public override void AddRegion(Scene scene) | ||||||
|  | @ -194,7 +204,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | ||||||
|             base.RegionLoaded(scene); |             base.RegionLoaded(scene); | ||||||
| 
 | 
 | ||||||
|             if (m_Enabled) |             if (m_Enabled) | ||||||
|  |             { | ||||||
|                 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService); |                 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService); | ||||||
|  |                 m_UAS = scene.RequestModuleInterface<IUserAgentService>(); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public override void RemoveRegion(Scene scene) |         public override void RemoveRegion(Scene scene) | ||||||
|  | @ -272,8 +285,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | ||||||
|                 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI")) |                 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI")) | ||||||
|                 { |                 { | ||||||
|                     string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString(); |                     string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString(); | ||||||
|                     IUserAgentService connector = new UserAgentServiceConnector(userAgentDriver); |                     IUserAgentService connector; | ||||||
|                     bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason); | 
 | ||||||
|  |                     if (userAgentDriver.Equals(m_ThisHomeURI) && m_UAS != null) | ||||||
|  |                         connector = m_UAS; | ||||||
|  |                     else | ||||||
|  |                         connector = new UserAgentServiceConnector(userAgentDriver); | ||||||
|  | 
 | ||||||
|  |                     bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, false, out reason); | ||||||
|                     logout = success; // flag for later logout from this grid; this is an HG TP |                     logout = success; // flag for later logout from this grid; this is an HG TP | ||||||
| 
 | 
 | ||||||
|                     if (success) |                     if (success) | ||||||
|  |  | ||||||
|  | @ -194,7 +194,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | ||||||
|                 return false; |                 return false; | ||||||
| 
 | 
 | ||||||
|             // Try local first |             // Try local first | ||||||
|             if (m_localBackend.IsLocalRegion(destination.RegionHandle)) |             if (m_localBackend.IsLocalRegion(destination.RegionID)) | ||||||
|                 return m_localBackend.UpdateAgent(destination, cAgentData); |                 return m_localBackend.UpdateAgent(destination, cAgentData); | ||||||
| 
 | 
 | ||||||
|             return m_remoteConnector.UpdateAgent(destination, cAgentData); |             return m_remoteConnector.UpdateAgent(destination, cAgentData); | ||||||
|  | @ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | ||||||
|                 return false; |                 return false; | ||||||
| 
 | 
 | ||||||
|             // Try local first |             // Try local first | ||||||
|             if (m_localBackend.IsLocalRegion(destination.RegionHandle)) |             if (m_localBackend.IsLocalRegion(destination.RegionID)) | ||||||
|                 return m_localBackend.UpdateAgent(destination, cAgentData); |                 return m_localBackend.UpdateAgent(destination, cAgentData); | ||||||
| 
 | 
 | ||||||
|             return m_remoteConnector.UpdateAgent(destination, cAgentData); |             return m_remoteConnector.UpdateAgent(destination, cAgentData); | ||||||
|  | @ -224,7 +224,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | ||||||
|                 return true; |                 return true; | ||||||
| 
 | 
 | ||||||
|             // else do the remote thing |             // else do the remote thing | ||||||
|             if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) |             if (!m_localBackend.IsLocalRegion(destination.RegionID)) | ||||||
|                 return m_remoteConnector.RetrieveAgent(destination, id, out agent); |                 return m_remoteConnector.RetrieveAgent(destination, id, out agent); | ||||||
| 
 | 
 | ||||||
|             return false; |             return false; | ||||||
|  | @ -288,7 +288,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | ||||||
|                 return true; |                 return true; | ||||||
| 
 | 
 | ||||||
|             // else do the remote thing |             // else do the remote thing | ||||||
|             if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) |             if (!m_localBackend.IsLocalRegion(destination.RegionID)) | ||||||
|                 return m_remoteConnector.CloseAgent(destination, id); |                 return m_remoteConnector.CloseAgent(destination, id); | ||||||
|              |              | ||||||
|             return false; |             return false; | ||||||
|  | @ -311,7 +311,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // else do the remote thing |             // else do the remote thing | ||||||
|             if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) |             if (!m_localBackend.IsLocalRegion(destination.RegionID)) | ||||||
|                 return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall); |                 return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall); | ||||||
| 
 | 
 | ||||||
|             return false; |             return false; | ||||||
|  |  | ||||||
|  | @ -117,7 +117,7 @@ namespace OpenSim.Region.CoreModules.World.Land | ||||||
|                     { |                     { | ||||||
|                         if (LandBitmap[x, y]) |                         if (LandBitmap[x, y]) | ||||||
|                         { |                         { | ||||||
|                             return new Vector3(x * 4, y * 4, 0); |                             return new Vector3(x * 4 + 4, y * 4 + 4, 0); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | @ -1,339 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Diagnostics; |  | ||||||
| using System.Linq; |  | ||||||
| using System.Net.NetworkInformation; |  | ||||||
| using System.Text; |  | ||||||
| using System.Threading; |  | ||||||
| 
 |  | ||||||
| using log4net; |  | ||||||
| using Mono.Addins; |  | ||||||
| using Nini.Config; |  | ||||||
| 
 |  | ||||||
| using OpenSim.Framework; |  | ||||||
| using OpenSim.Framework.Console; |  | ||||||
| using OpenSim.Framework.Monitoring; |  | ||||||
| using OpenSim.Region.Framework.Interfaces; |  | ||||||
| using OpenSim.Region.Framework.Scenes; |  | ||||||
| 
 |  | ||||||
| using OpenMetaverse.StructuredData; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.Region.OptionalModules.Framework.Monitoring |  | ||||||
| { |  | ||||||
| [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ServerStatistics")] |  | ||||||
| public class ServerStats : ISharedRegionModule |  | ||||||
| { |  | ||||||
|     private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |  | ||||||
|     private readonly string LogHeader = "[SERVER STATS]"; |  | ||||||
| 
 |  | ||||||
|     public bool Enabled = false; |  | ||||||
|     private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>(); |  | ||||||
| 
 |  | ||||||
|     public readonly string CategoryServer = "server"; |  | ||||||
| 
 |  | ||||||
|     public readonly string ContainerProcessor = "processor"; |  | ||||||
|     public readonly string ContainerMemory = "memory"; |  | ||||||
|     public readonly string ContainerNetwork = "network"; |  | ||||||
|     public readonly string ContainerProcess = "process"; |  | ||||||
| 
 |  | ||||||
|     public string NetworkInterfaceTypes = "Ethernet"; |  | ||||||
| 
 |  | ||||||
|     readonly int performanceCounterSampleInterval = 500; |  | ||||||
|     int lastperformanceCounterSampleTime = 0; |  | ||||||
| 
 |  | ||||||
|     private class PerfCounterControl |  | ||||||
|     { |  | ||||||
|         public PerformanceCounter perfCounter; |  | ||||||
|         public int lastFetch; |  | ||||||
|         public string name; |  | ||||||
|         public PerfCounterControl(PerformanceCounter pPc) |  | ||||||
|             : this(pPc, String.Empty) |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
|         public PerfCounterControl(PerformanceCounter pPc, string pName) |  | ||||||
|         { |  | ||||||
|             perfCounter = pPc; |  | ||||||
|             lastFetch = 0; |  | ||||||
|             name = pName; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     PerfCounterControl processorPercentPerfCounter = null; |  | ||||||
| 
 |  | ||||||
|     #region ISharedRegionModule |  | ||||||
|     // IRegionModuleBase.Name |  | ||||||
|     public string Name { get { return "Server Stats"; } } |  | ||||||
|     // IRegionModuleBase.ReplaceableInterface |  | ||||||
|     public Type ReplaceableInterface { get { return null; } } |  | ||||||
|     // IRegionModuleBase.Initialize |  | ||||||
|     public void Initialise(IConfigSource source) |  | ||||||
|     { |  | ||||||
|         IConfig cfg = source.Configs["Monitoring"]; |  | ||||||
| 
 |  | ||||||
|         if (cfg != null) |  | ||||||
|             Enabled = cfg.GetBoolean("ServerStatsEnabled", true); |  | ||||||
| 
 |  | ||||||
|         if (Enabled) |  | ||||||
|         { |  | ||||||
|             NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet"); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     // IRegionModuleBase.Close |  | ||||||
|     public void Close() |  | ||||||
|     { |  | ||||||
|         if (RegisteredStats.Count > 0) |  | ||||||
|         { |  | ||||||
|             foreach (Stat stat in RegisteredStats.Values) |  | ||||||
|             { |  | ||||||
|                 StatsManager.DeregisterStat(stat); |  | ||||||
|                 stat.Dispose(); |  | ||||||
|             } |  | ||||||
|             RegisteredStats.Clear(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     // IRegionModuleBase.AddRegion |  | ||||||
|     public void AddRegion(Scene scene) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|     // IRegionModuleBase.RemoveRegion |  | ||||||
|     public void RemoveRegion(Scene scene) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|     // IRegionModuleBase.RegionLoaded |  | ||||||
|     public void RegionLoaded(Scene scene) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|     // ISharedRegionModule.PostInitialize |  | ||||||
|     public void PostInitialise() |  | ||||||
|     { |  | ||||||
|         if (RegisteredStats.Count == 0) |  | ||||||
|         { |  | ||||||
|             RegisterServerStats(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     #endregion ISharedRegionModule |  | ||||||
| 
 |  | ||||||
|     private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act) |  | ||||||
|     { |  | ||||||
|         string desc = pDesc; |  | ||||||
|         if (desc == null) |  | ||||||
|             desc = pName; |  | ||||||
|         Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info); |  | ||||||
|         StatsManager.RegisterStat(stat); |  | ||||||
|         RegisteredStats.Add(pName, stat); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void RegisterServerStats() |  | ||||||
|     { |  | ||||||
|         lastperformanceCounterSampleTime = Util.EnvironmentTickCount(); |  | ||||||
|         PerformanceCounter tempPC; |  | ||||||
|         Stat tempStat; |  | ||||||
|         string tempName; |  | ||||||
| 
 |  | ||||||
|         try |  | ||||||
|         { |  | ||||||
|             tempName = "CPUPercent"; |  | ||||||
|             tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total"); |  | ||||||
|             processorPercentPerfCounter = new PerfCounterControl(tempPC); |  | ||||||
|             // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy. |  | ||||||
|             tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor, |  | ||||||
|                             StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); }, |  | ||||||
|                             StatVerbosity.Info); |  | ||||||
|             StatsManager.RegisterStat(tempStat); |  | ||||||
|             RegisteredStats.Add(tempName, tempStat); |  | ||||||
| 
 |  | ||||||
|             MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,  |  | ||||||
|                                 (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; }); |  | ||||||
| 
 |  | ||||||
|             MakeStat("UserProcessorTime", null, "sec", ContainerProcessor, |  | ||||||
|                                 (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; }); |  | ||||||
| 
 |  | ||||||
|             MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor, |  | ||||||
|                                 (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; }); |  | ||||||
| 
 |  | ||||||
|             MakeStat("Threads", null, "threads", ContainerProcessor, |  | ||||||
|                                 (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; }); |  | ||||||
|         } |  | ||||||
|         catch (Exception e) |  | ||||||
|         { |  | ||||||
|             m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         try |  | ||||||
|         { |  | ||||||
|             List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(',')); |  | ||||||
| 
 |  | ||||||
|             IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces(); |  | ||||||
|             foreach (NetworkInterface nic in nics) |  | ||||||
|             { |  | ||||||
|                 if (nic.OperationalStatus != OperationalStatus.Up) |  | ||||||
|                     continue; |  | ||||||
| 
 |  | ||||||
|                 string nicInterfaceType = nic.NetworkInterfaceType.ToString(); |  | ||||||
|                 if (!okInterfaceTypes.Contains(nicInterfaceType)) |  | ||||||
|                 { |  | ||||||
|                     m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.", |  | ||||||
|                                             LogHeader, nic.Name, nicInterfaceType); |  | ||||||
|                     m_log.DebugFormat("{0}     To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}", |  | ||||||
|                                             LogHeader, NetworkInterfaceTypes); |  | ||||||
|                     continue; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 if (nic.Supports(NetworkInterfaceComponent.IPv4)) |  | ||||||
|                 { |  | ||||||
|                     IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics(); |  | ||||||
|                     if (nicStats != null) |  | ||||||
|                     { |  | ||||||
|                         MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork, |  | ||||||
|                                         (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); }); |  | ||||||
|                         MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork, |  | ||||||
|                                         (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); }); |  | ||||||
|                         MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork, |  | ||||||
|                                         (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); }); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 // TODO: add IPv6 (it may actually happen someday) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         catch (Exception e) |  | ||||||
|         { |  | ||||||
|             m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         MakeStat("ProcessMemory", null, "MB", ContainerMemory, |  | ||||||
|                             (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; }); |  | ||||||
|         MakeStat("ObjectMemory", null, "MB", ContainerMemory, |  | ||||||
|                             (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; }); |  | ||||||
|         MakeStat("LastMemoryChurn", null, "MB/sec", ContainerMemory, |  | ||||||
|                             (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); }); |  | ||||||
|         MakeStat("AverageMemoryChurn", null, "MB/sec", ContainerMemory, |  | ||||||
|                             (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Notes on performance counters:  |  | ||||||
|     //  "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx |  | ||||||
|     //  "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c |  | ||||||
|     //  "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters |  | ||||||
|     private delegate double PerfCounterNextValue(); |  | ||||||
|     private void GetNextValue(Stat stat, PerfCounterControl perfControl) |  | ||||||
|     { |  | ||||||
|         GetNextValue(stat, perfControl, 1.0); |  | ||||||
|     } |  | ||||||
|     private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor) |  | ||||||
|     { |  | ||||||
|         if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval) |  | ||||||
|         { |  | ||||||
|             if (perfControl != null && perfControl.perfCounter != null) |  | ||||||
|             { |  | ||||||
|                 try |  | ||||||
|                 { |  | ||||||
|                     // Kludge for factor to run double duty. If -1, subtract the value from one |  | ||||||
|                     if (factor == -1) |  | ||||||
|                         stat.Value = 1 - perfControl.perfCounter.NextValue(); |  | ||||||
|                     else |  | ||||||
|                         stat.Value = perfControl.perfCounter.NextValue() / factor; |  | ||||||
|                 } |  | ||||||
|                 catch (Exception e) |  | ||||||
|                 { |  | ||||||
|                     m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e); |  | ||||||
|                 } |  | ||||||
|                 perfControl.lastFetch = Util.EnvironmentTickCount(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Lookup the nic that goes with this stat and set the value by using a fetch action. |  | ||||||
|     // Not sure about closure with delegates inside delegates. |  | ||||||
|     private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat); |  | ||||||
|     private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor) |  | ||||||
|     { |  | ||||||
|         // Get the one nic that has the name of this stat |  | ||||||
|         IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where( |  | ||||||
|                               (network) => network.Name == stat.Description); |  | ||||||
|         try |  | ||||||
|         { |  | ||||||
|             foreach (NetworkInterface nic in nics) |  | ||||||
|             { |  | ||||||
|                 IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics(); |  | ||||||
|                 if (intrStats != null) |  | ||||||
|                 { |  | ||||||
|                     double newVal = Math.Round(getter(intrStats) / factor, 3); |  | ||||||
|                     stat.Value = newVal; |  | ||||||
|                 } |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         catch |  | ||||||
|         { |  | ||||||
|             // There are times interfaces go away so we just won't update the stat for this |  | ||||||
|             m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| public class ServerStatsAggregator : Stat |  | ||||||
| { |  | ||||||
|     public ServerStatsAggregator( |  | ||||||
|         string shortName, |  | ||||||
|         string name, |  | ||||||
|         string description, |  | ||||||
|         string unitName, |  | ||||||
|         string category, |  | ||||||
|         string container |  | ||||||
|         ) |  | ||||||
|         : base( |  | ||||||
|             shortName, |  | ||||||
|             name, |  | ||||||
|             description, |  | ||||||
|             unitName, |  | ||||||
|             category, |  | ||||||
|             container, |  | ||||||
|             StatType.Push, |  | ||||||
|             MeasuresOfInterest.None, |  | ||||||
|             null, |  | ||||||
|             StatVerbosity.Info) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|     public override string ToConsoleString() |  | ||||||
|     { |  | ||||||
|         StringBuilder sb = new StringBuilder(); |  | ||||||
| 
 |  | ||||||
|         return sb.ToString(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public override OSDMap ToOSDMap() |  | ||||||
|     { |  | ||||||
|         OSDMap ret = new OSDMap(); |  | ||||||
| 
 |  | ||||||
|         return ret; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -43,8 +43,14 @@ public class BSActorAvatarMove : BSActor | ||||||
|     // Set to true if we think we're going up stairs. |     // Set to true if we think we're going up stairs. | ||||||
|     //    This state is remembered because collisions will turn on and off as we go up stairs. |     //    This state is remembered because collisions will turn on and off as we go up stairs. | ||||||
|     int m_walkingUpStairs; |     int m_walkingUpStairs; | ||||||
|  |     // The amount the step up is applying. Used to smooth stair walking. | ||||||
|     float m_lastStepUp; |     float m_lastStepUp; | ||||||
| 
 | 
 | ||||||
|  |     // Jumping happens over several frames. If use applies up force while colliding, start the | ||||||
|  |     //    jump and allow the jump to continue for this number of frames. | ||||||
|  |     int m_jumpFrames = 0; | ||||||
|  |     float m_jumpVelocity = 0f; | ||||||
|  | 
 | ||||||
|     public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName) |     public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName) | ||||||
|         : base(physicsScene, pObj, actorName) |         : base(physicsScene, pObj, actorName) | ||||||
|     { |     { | ||||||
|  | @ -206,17 +212,45 @@ public class BSActorAvatarMove : BSActor | ||||||
| 
 | 
 | ||||||
|             if (m_controllingPrim.Friction != BSParam.AvatarFriction) |             if (m_controllingPrim.Friction != BSParam.AvatarFriction) | ||||||
|             { |             { | ||||||
|                 // Probably starting up walking. Set friction to moving friction. |                 // Probably starting to walk. Set friction to moving friction. | ||||||
|                 m_controllingPrim.Friction = BSParam.AvatarFriction; |                 m_controllingPrim.Friction = BSParam.AvatarFriction; | ||||||
|                 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); |                 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // If falling, we keep the world's downward vector no matter what the other axis specify. |  | ||||||
|             // The check for RawVelocity.Z < 0 makes jumping work (temporary upward force). |  | ||||||
|             if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding) |             if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding) | ||||||
|             { |             { | ||||||
|                 if (m_controllingPrim.RawVelocity.Z < 0) |  | ||||||
|                 stepVelocity.Z = m_controllingPrim.RawVelocity.Z; |                 stepVelocity.Z = m_controllingPrim.RawVelocity.Z; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |             // Colliding and not flying with an upward force. The avatar must be trying to jump. | ||||||
|  |             if (!m_controllingPrim.Flying && m_controllingPrim.IsColliding && stepVelocity.Z > 0) | ||||||
|  |             { | ||||||
|  |                 // We allow the upward force to happen for this many frames. | ||||||
|  |                 m_jumpFrames = BSParam.AvatarJumpFrames; | ||||||
|  |                 m_jumpVelocity = stepVelocity.Z; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // The case where the avatar is not colliding and is not flying is special. | ||||||
|  |             // The avatar is either falling or jumping and the user can be applying force to the avatar | ||||||
|  |             //     (force in some direction or force up or down). | ||||||
|  |             // If the avatar has negative Z velocity and is not colliding, presume we're falling and keep the velocity. | ||||||
|  |             // If the user is trying to apply upward force but we're not colliding, assume the avatar | ||||||
|  |             //     is trying to jump and don't apply the upward force if not touching the ground any more. | ||||||
|  |             if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding) | ||||||
|  |             { | ||||||
|  |                 // If upward velocity is being applied, this must be a jump and only allow that to go on so long | ||||||
|  |                 if (m_jumpFrames > 0) | ||||||
|  |                 { | ||||||
|  |                     // Since not touching the ground, only apply upward force for so long. | ||||||
|  |                     m_jumpFrames--; | ||||||
|  |                     stepVelocity.Z = m_jumpVelocity; | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     // Since we're not affected by anything, whatever vertical motion the avatar has, continue that. | ||||||
|  |                     stepVelocity.Z = m_controllingPrim.RawVelocity.Z; | ||||||
|  |                 } | ||||||
|                 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); |                 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -241,7 +275,7 @@ public class BSActorAvatarMove : BSActor | ||||||
|         m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}", |         m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}", | ||||||
|                         m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying, |                         m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying, | ||||||
|                         m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z); |                         m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z); | ||||||
|         // This test is done if moving forward, not flying and is colliding with something. | 
 | ||||||
|         // Check for stairs climbing if colliding, not flying and moving forward |         // Check for stairs climbing if colliding, not flying and moving forward | ||||||
|         if ( m_controllingPrim.IsColliding |         if ( m_controllingPrim.IsColliding | ||||||
|                     && !m_controllingPrim.Flying |                     && !m_controllingPrim.Flying | ||||||
|  |  | ||||||
|  | @ -209,7 +209,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | ||||||
|                     m_VhoverTimescale = Math.Max(pValue, 0.01f); |                     m_VhoverTimescale = Math.Max(pValue, 0.01f); | ||||||
|                     break; |                     break; | ||||||
|                 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: |                 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: | ||||||
|                     m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); |                     m_linearDeflectionEfficiency = ClampInRange(0f, pValue, 1f); | ||||||
|                     break; |                     break; | ||||||
|                 case Vehicle.LINEAR_DEFLECTION_TIMESCALE: |                 case Vehicle.LINEAR_DEFLECTION_TIMESCALE: | ||||||
|                     m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); |                     m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); | ||||||
|  | @ -707,7 +707,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin | ||||||
|         private Vector3 m_knownRotationalVelocity; |         private Vector3 m_knownRotationalVelocity; | ||||||
|         private Vector3 m_knownRotationalForce; |         private Vector3 m_knownRotationalForce; | ||||||
|         private Vector3 m_knownRotationalImpulse; |         private Vector3 m_knownRotationalImpulse; | ||||||
|         private Vector3 m_knownForwardVelocity;    // vehicle relative forward speed |  | ||||||
| 
 | 
 | ||||||
|         private const int m_knownChangedPosition           = 1 << 0; |         private const int m_knownChangedPosition           = 1 << 0; | ||||||
|         private const int m_knownChangedVelocity           = 1 << 1; |         private const int m_knownChangedVelocity           = 1 << 1; | ||||||
|  | @ -719,7 +718,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin | ||||||
|         private const int m_knownChangedRotationalImpulse  = 1 << 7; |         private const int m_knownChangedRotationalImpulse  = 1 << 7; | ||||||
|         private const int m_knownChangedTerrainHeight      = 1 << 8; |         private const int m_knownChangedTerrainHeight      = 1 << 8; | ||||||
|         private const int m_knownChangedWaterLevel         = 1 << 9; |         private const int m_knownChangedWaterLevel         = 1 << 9; | ||||||
|         private const int m_knownChangedForwardVelocity    = 1 <<10; |  | ||||||
| 
 | 
 | ||||||
|         public void ForgetKnownVehicleProperties() |         public void ForgetKnownVehicleProperties() | ||||||
|         { |         { | ||||||
|  | @ -923,12 +921,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | ||||||
|         { |         { | ||||||
|             get |             get | ||||||
|             { |             { | ||||||
|                 if ((m_knownHas & m_knownChangedForwardVelocity) == 0) |                 return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation)); | ||||||
|                 { |  | ||||||
|                     m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation)); |  | ||||||
|                     m_knownHas |= m_knownChangedForwardVelocity; |  | ||||||
|                 } |  | ||||||
|                 return m_knownForwardVelocity; |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         private float VehicleForwardSpeed |         private float VehicleForwardSpeed | ||||||
|  | @ -981,6 +974,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | ||||||
|         { |         { | ||||||
|             ComputeLinearVelocity(pTimestep); |             ComputeLinearVelocity(pTimestep); | ||||||
| 
 | 
 | ||||||
|  |             ComputeLinearDeflection(pTimestep); | ||||||
|  | 
 | ||||||
|             ComputeLinearTerrainHeightCorrection(pTimestep); |             ComputeLinearTerrainHeightCorrection(pTimestep); | ||||||
| 
 | 
 | ||||||
|             ComputeLinearHover(pTimestep); |             ComputeLinearHover(pTimestep); | ||||||
|  | @ -1026,12 +1021,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin | ||||||
|         { |         { | ||||||
|             // Step the motor from the current value. Get the correction needed this step. |             // Step the motor from the current value. Get the correction needed this step. | ||||||
|             Vector3 origVelW = VehicleVelocity;             // DEBUG |             Vector3 origVelW = VehicleVelocity;             // DEBUG | ||||||
|             Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); |             Vector3 currentVelV = VehicleForwardVelocity; | ||||||
|             Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); |             Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); | ||||||
| 
 | 
 | ||||||
|             // Friction reduces vehicle motion |             // Friction reduces vehicle motion based on absolute speed. Slow vehicle down by friction. | ||||||
|             Vector3 frictionFactorW = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep); |             Vector3 frictionFactorV = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep); | ||||||
|             linearMotorCorrectionV -= (currentVelV * frictionFactorW); |             linearMotorCorrectionV -= (currentVelV * frictionFactorV); | ||||||
| 
 | 
 | ||||||
|             // Motor is vehicle coordinates. Rotate it to world coordinates |             // Motor is vehicle coordinates. Rotate it to world coordinates | ||||||
|             Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; |             Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; | ||||||
|  | @ -1046,11 +1041,38 @@ namespace OpenSim.Region.Physics.BulletSPlugin | ||||||
|             // Add this correction to the velocity to make it faster/slower. |             // Add this correction to the velocity to make it faster/slower. | ||||||
|             VehicleVelocity += linearMotorVelocityW; |             VehicleVelocity += linearMotorVelocityW; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|             VDetailLog("{0},  MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}", |             VDetailLog("{0},  MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}", | ||||||
|                         ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, |                         ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, | ||||||
|                         linearMotorVelocityW, VehicleVelocity, frictionFactorW); |                         linearMotorVelocityW, VehicleVelocity, frictionFactorV); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         //Given a Deflection Effiency and a Velocity, Returns a Velocity that is Partially Deflected onto the X Axis | ||||||
|  |         //Clamped so that a DeflectionTimescale of less then 1 does not increase force over original velocity | ||||||
|  |         private void ComputeLinearDeflection(float pTimestep) | ||||||
|  |         { | ||||||
|  |             Vector3 linearDeflectionV = Vector3.Zero; | ||||||
|  |             Vector3 velocityV = VehicleForwardVelocity; | ||||||
|  | 
 | ||||||
|  |             // Velocity in Y and Z dimensions is movement to the side or turning. | ||||||
|  |             // Compute deflection factor from the to the side and rotational velocity | ||||||
|  |             linearDeflectionV.Y = SortedClampInRange(0, (velocityV.Y * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Y); | ||||||
|  |             linearDeflectionV.Z = SortedClampInRange(0, (velocityV.Z * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Z); | ||||||
|  | 
 | ||||||
|  |             // Velocity to the side and around is corrected and moved into the forward direction | ||||||
|  |             linearDeflectionV.X += Math.Abs(linearDeflectionV.Y); | ||||||
|  |             linearDeflectionV.X += Math.Abs(linearDeflectionV.Z); | ||||||
|  | 
 | ||||||
|  |             // Scale the deflection to the fractional simulation time | ||||||
|  |             linearDeflectionV *= pTimestep; | ||||||
|  | 
 | ||||||
|  |             // Subtract the sideways and rotational velocity deflection factors while adding the correction forward | ||||||
|  |             linearDeflectionV *= new Vector3(1,-1,-1); | ||||||
|  | 
 | ||||||
|  |             // Correciont is vehicle relative. Convert to world coordinates and add to the velocity | ||||||
|  |             VehicleVelocity += linearDeflectionV * VehicleOrientation; | ||||||
|  | 
 | ||||||
|  |             VDetailLog("{0},  MoveLinear,LinearDeflection,linDefEff={1},linDefTS={2},linDeflectionV={3}", | ||||||
|  |                         ControllingPrim.LocalID, m_linearDeflectionEfficiency, m_linearDeflectionTimescale, linearDeflectionV); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public void ComputeLinearTerrainHeightCorrection(float pTimestep) |         public void ComputeLinearTerrainHeightCorrection(float pTimestep) | ||||||
|  | @ -1652,6 +1674,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin | ||||||
|             return frictionFactor; |             return frictionFactor; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         private float SortedClampInRange(float clampa, float val, float clampb) | ||||||
|  |         { | ||||||
|  |             if (clampa > clampb) | ||||||
|  |             { | ||||||
|  |                 float temp = clampa; | ||||||
|  |                 clampa = clampb; | ||||||
|  |                 clampb = temp; | ||||||
|  |             } | ||||||
|  |            return ClampInRange(clampa, val, clampb); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         private float ClampInRange(float low, float val, float high) |         private float ClampInRange(float low, float val, float high) | ||||||
|         { |         { | ||||||
|             return Math.Max(low, Math.Min(val, high)); |             return Math.Max(low, Math.Min(val, high)); | ||||||
|  |  | ||||||
|  | @ -134,6 +134,7 @@ public static class BSParam | ||||||
|     public static float AvatarHeightMidFudge { get; private set; } |     public static float AvatarHeightMidFudge { get; private set; } | ||||||
|     public static float AvatarHeightHighFudge { get; private set; } |     public static float AvatarHeightHighFudge { get; private set; } | ||||||
| 	public static float AvatarContactProcessingThreshold { get; private set; } | 	public static float AvatarContactProcessingThreshold { get; private set; } | ||||||
|  | 	public static int AvatarJumpFrames { get; private set; } | ||||||
| 	public static float AvatarBelowGroundUpCorrectionMeters { get; private set; } | 	public static float AvatarBelowGroundUpCorrectionMeters { get; private set; } | ||||||
| 	public static float AvatarStepHeight { get; private set; } | 	public static float AvatarStepHeight { get; private set; } | ||||||
| 	public static float AvatarStepApproachFactor { get; private set; } | 	public static float AvatarStepApproachFactor { get; private set; } | ||||||
|  | @ -567,6 +568,8 @@ public static class BSParam | ||||||
|             0.1f ), |             0.1f ), | ||||||
| 	    new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", | 	    new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", | ||||||
|             1.0f ), |             1.0f ), | ||||||
|  | 	    new ParameterDefn<int>("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.", | ||||||
|  |             4 ), | ||||||
| 	    new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction", | 	    new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction", | ||||||
|             0.6f ) , |             0.6f ) , | ||||||
| 	    new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)", | 	    new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)", | ||||||
|  |  | ||||||
|  | @ -34,6 +34,7 @@ using System.Text; | ||||||
| using System.Xml; | using System.Xml; | ||||||
| using OpenSim.Framework; | using OpenSim.Framework; | ||||||
| using OpenSim.Framework.Console; | using OpenSim.Framework.Console; | ||||||
|  | using OpenSim.Framework.Monitoring; | ||||||
| using OpenSim.Framework.Servers; | using OpenSim.Framework.Servers; | ||||||
| using log4net; | using log4net; | ||||||
| using log4net.Config; | using log4net.Config; | ||||||
|  | @ -190,16 +191,7 @@ namespace OpenSim.Server.Base | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             RegisterCommonCommands(); |             RegisterCommonCommands(); | ||||||
| 
 |             RegisterCommonComponents(Config); | ||||||
|             // Register the quit command |  | ||||||
|             // |  | ||||||
|             MainConsole.Instance.Commands.AddCommand("General", false, "quit", |  | ||||||
|                     "quit", |  | ||||||
|                     "Quit the application", HandleQuit); |  | ||||||
| 
 |  | ||||||
|             MainConsole.Instance.Commands.AddCommand("General", false, "shutdown", |  | ||||||
|                     "shutdown", |  | ||||||
|                     "Quit the application", HandleQuit); |  | ||||||
| 
 | 
 | ||||||
|             // Allow derived classes to perform initialization that |             // Allow derived classes to perform initialization that | ||||||
|             // needs to be done after the console has opened |             // needs to be done after the console has opened | ||||||
|  | @ -214,6 +206,9 @@ namespace OpenSim.Server.Base | ||||||
| 
 | 
 | ||||||
|         public virtual int Run() |         public virtual int Run() | ||||||
|         { |         { | ||||||
|  |             Watchdog.Enabled = true; | ||||||
|  |             MemoryWatchdog.Enabled = true; | ||||||
|  | 
 | ||||||
|             while (m_Running) |             while (m_Running) | ||||||
|             { |             { | ||||||
|                 try |                 try | ||||||
|  | @ -231,11 +226,12 @@ namespace OpenSim.Server.Base | ||||||
|             return 0; |             return 0; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         protected virtual void HandleQuit(string module, string[] args) |         protected override void ShutdownSpecific() | ||||||
|         { |         { | ||||||
|             m_Running = false; |             m_Running = false; | ||||||
|             m_log.Info("[CONSOLE] Quitting"); |             m_log.Info("[CONSOLE] Quitting"); | ||||||
| 
 | 
 | ||||||
|  |             base.ShutdownSpecific(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         protected virtual void ReadConfig() |         protected virtual void ReadConfig() | ||||||
|  |  | ||||||
|  | @ -61,7 +61,7 @@ namespace OpenSim.Server.Handlers.Hypergrid | ||||||
|             m_Proxy = proxy; |             m_Proxy = proxy; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         protected override bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) |         protected override bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason) | ||||||
|         { |         { | ||||||
|             return m_GatekeeperService.LoginAgent(aCircuit, destination, out reason); |             return m_GatekeeperService.LoginAgent(aCircuit, destination, out reason); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -49,191 +49,87 @@ using log4net; | ||||||
| 
 | 
 | ||||||
| namespace OpenSim.Server.Handlers.Hypergrid | namespace OpenSim.Server.Handlers.Hypergrid | ||||||
| { | { | ||||||
|     public class HomeAgentHandler  |     public class HomeAgentHandler : AgentPostHandler | ||||||
|     { |     { | ||||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||||
|         private IUserAgentService m_UserAgentService; |         private IUserAgentService m_UserAgentService; | ||||||
| 
 | 
 | ||||||
|         private string m_LoginServerIP; |         private string m_LoginServerIP; | ||||||
|         private bool m_Proxy = false; |  | ||||||
| 
 | 
 | ||||||
|         public HomeAgentHandler(IUserAgentService userAgentService, string loginServerIP, bool proxy) |         public HomeAgentHandler(IUserAgentService userAgentService, string loginServerIP, bool proxy) : | ||||||
|  |             base("/homeagent") | ||||||
|         { |         { | ||||||
|             m_UserAgentService = userAgentService; |             m_UserAgentService = userAgentService; | ||||||
|             m_LoginServerIP = loginServerIP; |             m_LoginServerIP = loginServerIP; | ||||||
|             m_Proxy = proxy; |             m_Proxy = proxy; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public Hashtable Handler(Hashtable request) |         protected override AgentDestinationData CreateAgentDestinationData() | ||||||
|         { |         { | ||||||
| //            m_log.Debug("[CONNECTION DEBUGGING]: HomeAgentHandler Called"); |             return new ExtendedAgentDestinationData(); | ||||||
| // |  | ||||||
| //            m_log.Debug("---------------------------"); |  | ||||||
| //            m_log.Debug(" >> uri=" + request["uri"]); |  | ||||||
| //            m_log.Debug(" >> content-type=" + request["content-type"]); |  | ||||||
| //            m_log.Debug(" >> http-method=" + request["http-method"]); |  | ||||||
| //            m_log.Debug("---------------------------\n"); |  | ||||||
| 
 |  | ||||||
|             Hashtable responsedata = new Hashtable(); |  | ||||||
|             responsedata["content_type"] = "text/html"; |  | ||||||
|             responsedata["keepalive"] = false; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|             UUID agentID; |  | ||||||
|             UUID regionID; |  | ||||||
|             string action; |  | ||||||
|             if (!Utils.GetParams((string)request["uri"], out agentID, out regionID, out action)) |  | ||||||
|             { |  | ||||||
|                 m_log.InfoFormat("[HOME AGENT HANDLER]: Invalid parameters for agent message {0}", request["uri"]); |  | ||||||
|                 responsedata["int_response_code"] = 404; |  | ||||||
|                 responsedata["str_response_string"] = "false"; |  | ||||||
| 
 |  | ||||||
|                 return responsedata; |  | ||||||
|         } |         } | ||||||
| 
 |         protected override void UnpackData(OSDMap args, AgentDestinationData d, Hashtable request) | ||||||
|             // Next, let's parse the verb |  | ||||||
|             string method = (string)request["http-method"]; |  | ||||||
|             if (method.Equals("POST")) |  | ||||||
|         { |         { | ||||||
|                 DoAgentPost(request, responsedata, agentID); |             base.UnpackData(args, d, request); | ||||||
|                 return responsedata; |             ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d; | ||||||
|             } |             try | ||||||
|             else |  | ||||||
|             { |             { | ||||||
|                 m_log.InfoFormat("[HOME AGENT HANDLER]: method {0} not supported in agent message", method); |  | ||||||
|                 responsedata["int_response_code"] = HttpStatusCode.MethodNotAllowed; |  | ||||||
|                 responsedata["str_response_string"] = "Method not allowed"; |  | ||||||
| 
 |  | ||||||
|                 return responsedata; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id) |  | ||||||
|         { |  | ||||||
|             OSDMap args = Utils.GetOSDMap((string)request["body"]); |  | ||||||
|             if (args == null) |  | ||||||
|             { |  | ||||||
|                 responsedata["int_response_code"] = HttpStatusCode.BadRequest; |  | ||||||
|                 responsedata["str_response_string"] = "Bad request"; |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // retrieve the input arguments |  | ||||||
|             int x = 0, y = 0; |  | ||||||
|             UUID uuid = UUID.Zero; |  | ||||||
|             string regionname = string.Empty; |  | ||||||
|             string gatekeeper_host = string.Empty; |  | ||||||
|             string gatekeeper_serveruri = string.Empty; |  | ||||||
|             string destination_serveruri = string.Empty; |  | ||||||
|             int gatekeeper_port = 0; |  | ||||||
|             IPEndPoint client_ipaddress = null; |  | ||||||
| 
 |  | ||||||
|                 if (args.ContainsKey("gatekeeper_host") && args["gatekeeper_host"] != null) |                 if (args.ContainsKey("gatekeeper_host") && args["gatekeeper_host"] != null) | ||||||
|                 gatekeeper_host = args["gatekeeper_host"].AsString(); |                     data.host = args["gatekeeper_host"].AsString(); | ||||||
|                 if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null) |                 if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null) | ||||||
|                 Int32.TryParse(args["gatekeeper_port"].AsString(), out gatekeeper_port); |                     Int32.TryParse(args["gatekeeper_port"].AsString(), out data.port); | ||||||
|             if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] !=null) |                 if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] != null) | ||||||
|                 gatekeeper_serveruri = args["gatekeeper_serveruri"]; |                     data.gatekeeperServerURI = args["gatekeeper_serveruri"]; | ||||||
|             if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] !=null) |                 if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] != null) | ||||||
|                 destination_serveruri = args["destination_serveruri"]; |                     data.destinationServerURI = args["destination_serveruri"]; | ||||||
| 
 | 
 | ||||||
|  |             } | ||||||
|  |             catch (InvalidCastException e) | ||||||
|  |             { | ||||||
|  |                 m_log.ErrorFormat("[HOME AGENT HANDLER]: Bad cast in UnpackData"); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             string callerIP = GetCallerIP(request); | ||||||
|  |             // Verify if this call came from the login server | ||||||
|  |             if (callerIP == m_LoginServerIP) | ||||||
|  |                 data.fromLogin = true; | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         protected override GridRegion ExtractGatekeeper(AgentDestinationData d) | ||||||
|  |         { | ||||||
|  |             if (d is ExtendedAgentDestinationData) | ||||||
|  |             { | ||||||
|  |                 ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d; | ||||||
|                 GridRegion gatekeeper = new GridRegion(); |                 GridRegion gatekeeper = new GridRegion(); | ||||||
|             gatekeeper.ServerURI = gatekeeper_serveruri; |                 gatekeeper.ServerURI = data.gatekeeperServerURI; | ||||||
|             gatekeeper.ExternalHostName = gatekeeper_host; |                 gatekeeper.ExternalHostName = data.host; | ||||||
|             gatekeeper.HttpPort = (uint)gatekeeper_port; |                 gatekeeper.HttpPort = (uint)data.port; | ||||||
|                 gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0); |                 gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0); | ||||||
| 
 | 
 | ||||||
|             if (args.ContainsKey("destination_x") && args["destination_x"] != null) |                 return gatekeeper; | ||||||
|                 Int32.TryParse(args["destination_x"].AsString(), out x); |             } | ||||||
|             else |             else | ||||||
|                 m_log.WarnFormat("  -- request didn't have destination_x"); |                 m_log.WarnFormat("[HOME AGENT HANDLER]: Wrong data type"); | ||||||
|             if (args.ContainsKey("destination_y") && args["destination_y"] != null) |  | ||||||
|                 Int32.TryParse(args["destination_y"].AsString(), out y); |  | ||||||
|             else |  | ||||||
|                 m_log.WarnFormat("  -- request didn't have destination_y"); |  | ||||||
|             if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null) |  | ||||||
|                 UUID.TryParse(args["destination_uuid"].AsString(), out uuid); |  | ||||||
|             if (args.ContainsKey("destination_name") && args["destination_name"] != null) |  | ||||||
|                 regionname = args["destination_name"].ToString(); |  | ||||||
| 
 | 
 | ||||||
|             if (args.ContainsKey("client_ip") && args["client_ip"] != null) |             return null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         protected override bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason) | ||||||
|         { |         { | ||||||
|                 string ip_str = args["client_ip"].ToString(); |             return m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, fromLogin, out reason); | ||||||
|                 try |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class ExtendedAgentDestinationData : AgentDestinationData | ||||||
|     { |     { | ||||||
|                     string callerIP = GetCallerIP(request); |         public string host; | ||||||
|                     // Verify if this caller has authority to send the client IP |         public int port; | ||||||
|                     if (callerIP == m_LoginServerIP) |         public string gatekeeperServerURI; | ||||||
|                         client_ipaddress = new IPEndPoint(IPAddress.Parse(ip_str), 0); |         public string destinationServerURI; | ||||||
|                     else // leaving this for now, but this warning should be removed |  | ||||||
|                         m_log.WarnFormat("[HOME AGENT HANDLER]: Unauthorized machine {0} tried to set client ip to {1}", callerIP, ip_str); |  | ||||||
|                 } |  | ||||||
|                 catch |  | ||||||
|                 { |  | ||||||
|                     m_log.DebugFormat("[HOME AGENT HANDLER]: Exception parsing client ip address from {0}", ip_str); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             GridRegion destination = new GridRegion(); |  | ||||||
|             destination.RegionID = uuid; |  | ||||||
|             destination.RegionLocX = x; |  | ||||||
|             destination.RegionLocY = y; |  | ||||||
|             destination.RegionName = regionname; |  | ||||||
|             destination.ServerURI = destination_serveruri; |  | ||||||
|              |  | ||||||
|             AgentCircuitData aCircuit = new AgentCircuitData(); |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 aCircuit.UnpackAgentCircuitData(args); |  | ||||||
|             } |  | ||||||
|             catch (Exception ex) |  | ||||||
|             { |  | ||||||
|                 m_log.InfoFormat("[HOME AGENT HANDLER]: exception on unpacking ChildCreate message {0}", ex.Message); |  | ||||||
|                 responsedata["int_response_code"] = HttpStatusCode.BadRequest; |  | ||||||
|                 responsedata["str_response_string"] = "Bad request"; |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             OSDMap resp = new OSDMap(2); |  | ||||||
|             string reason = String.Empty; |  | ||||||
| 
 |  | ||||||
|             bool result = m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, client_ipaddress, out reason); |  | ||||||
| 
 |  | ||||||
|             resp["reason"] = OSD.FromString(reason); |  | ||||||
|             resp["success"] = OSD.FromBoolean(result); |  | ||||||
| 
 |  | ||||||
|             // TODO: add reason if not String.Empty? |  | ||||||
|             responsedata["int_response_code"] = HttpStatusCode.OK; |  | ||||||
|             responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private string GetCallerIP(Hashtable request) |  | ||||||
|         { |  | ||||||
|             if (!m_Proxy) |  | ||||||
|                 return Util.GetCallerIP(request); |  | ||||||
| 
 |  | ||||||
|             // We're behind a proxy |  | ||||||
|             Hashtable headers = (Hashtable)request["headers"]; |  | ||||||
|             string xff = "X-Forwarded-For"; |  | ||||||
|             if (headers.ContainsKey(xff.ToLower())) |  | ||||||
|                 xff = xff.ToLower(); |  | ||||||
| 
 |  | ||||||
|             if (!headers.ContainsKey(xff) || headers[xff] == null) |  | ||||||
|             { |  | ||||||
|                 m_log.WarnFormat("[AGENT HANDLER]: No XFF header"); |  | ||||||
|                 return Util.GetCallerIP(request); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]); |  | ||||||
| 
 |  | ||||||
|             IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]); |  | ||||||
|             if (ep != null) |  | ||||||
|                 return ep.Address.ToString(); |  | ||||||
| 
 |  | ||||||
|             // Oops |  | ||||||
|             return Util.GetCallerIP(request); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -108,7 +108,7 @@ namespace OpenSim.Server.Handlers.Hypergrid | ||||||
|             server.AddXmlRPCHandler("get_uui", GetUUI, false); |             server.AddXmlRPCHandler("get_uui", GetUUI, false); | ||||||
|             server.AddXmlRPCHandler("get_uuid", GetUUID, false); |             server.AddXmlRPCHandler("get_uuid", GetUUID, false); | ||||||
| 
 | 
 | ||||||
|             server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); |             server.AddStreamHandler(new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public XmlRpcResponse GetHomeRegion(XmlRpcRequest request, IPEndPoint remoteClient) |         public XmlRpcResponse GetHomeRegion(XmlRpcRequest request, IPEndPoint remoteClient) | ||||||
|  |  | ||||||
|  | @ -351,31 +351,16 @@ namespace OpenSim.Server.Handlers.Simulation | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // retrieve the input arguments |             AgentDestinationData data = CreateAgentDestinationData(); | ||||||
|             int x = 0, y = 0; |             UnpackData(args, data, request); | ||||||
|             UUID uuid = UUID.Zero; |  | ||||||
|             string regionname = string.Empty; |  | ||||||
|             uint teleportFlags = 0; |  | ||||||
|             if (args.ContainsKey("destination_x") && args["destination_x"] != null) |  | ||||||
|                 Int32.TryParse(args["destination_x"].AsString(), out x); |  | ||||||
|             else |  | ||||||
|                 m_log.WarnFormat("  -- request didn't have destination_x"); |  | ||||||
|             if (args.ContainsKey("destination_y") && args["destination_y"] != null) |  | ||||||
|                 Int32.TryParse(args["destination_y"].AsString(), out y); |  | ||||||
|             else |  | ||||||
|                 m_log.WarnFormat("  -- request didn't have destination_y"); |  | ||||||
|             if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null) |  | ||||||
|                 UUID.TryParse(args["destination_uuid"].AsString(), out uuid); |  | ||||||
|             if (args.ContainsKey("destination_name") && args["destination_name"] != null) |  | ||||||
|                 regionname = args["destination_name"].ToString(); |  | ||||||
|             if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null) |  | ||||||
|                 teleportFlags = args["teleport_flags"].AsUInteger(); |  | ||||||
| 
 | 
 | ||||||
|             GridRegion destination = new GridRegion(); |             GridRegion destination = new GridRegion(); | ||||||
|             destination.RegionID = uuid; |             destination.RegionID = data.uuid; | ||||||
|             destination.RegionLocX = x; |             destination.RegionLocX = data.x; | ||||||
|             destination.RegionLocY = y; |             destination.RegionLocY = data.y; | ||||||
|             destination.RegionName = regionname; |             destination.RegionName = data.name; | ||||||
|  | 
 | ||||||
|  |             GridRegion gatekeeper = ExtractGatekeeper(data); | ||||||
| 
 | 
 | ||||||
|             AgentCircuitData aCircuit = new AgentCircuitData(); |             AgentCircuitData aCircuit = new AgentCircuitData(); | ||||||
|             try |             try | ||||||
|  | @ -396,7 +381,7 @@ namespace OpenSim.Server.Handlers.Simulation | ||||||
|             // This is the meaning of POST agent |             // This is the meaning of POST agent | ||||||
|             //m_regionClient.AdjustUserInformation(aCircuit); |             //m_regionClient.AdjustUserInformation(aCircuit); | ||||||
|             //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); |             //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); | ||||||
|             bool result = CreateAgent(destination, aCircuit, teleportFlags, out reason); |             bool result = CreateAgent(gatekeeper, destination, aCircuit, data.flags, data.fromLogin, out reason); | ||||||
| 
 | 
 | ||||||
|             resp["reason"] = OSD.FromString(reason); |             resp["reason"] = OSD.FromString(reason); | ||||||
|             resp["success"] = OSD.FromBoolean(result); |             resp["success"] = OSD.FromBoolean(result); | ||||||
|  | @ -408,7 +393,36 @@ namespace OpenSim.Server.Handlers.Simulation | ||||||
|             responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); |             responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private string GetCallerIP(Hashtable request) |         protected virtual AgentDestinationData CreateAgentDestinationData() | ||||||
|  |         { | ||||||
|  |             return new AgentDestinationData(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         protected virtual void UnpackData(OSDMap args, AgentDestinationData data, Hashtable request) | ||||||
|  |         { | ||||||
|  |             // retrieve the input arguments | ||||||
|  |             if (args.ContainsKey("destination_x") && args["destination_x"] != null) | ||||||
|  |                 Int32.TryParse(args["destination_x"].AsString(), out data.x); | ||||||
|  |             else | ||||||
|  |                 m_log.WarnFormat("  -- request didn't have destination_x"); | ||||||
|  |             if (args.ContainsKey("destination_y") && args["destination_y"] != null) | ||||||
|  |                 Int32.TryParse(args["destination_y"].AsString(), out data.y); | ||||||
|  |             else | ||||||
|  |                 m_log.WarnFormat("  -- request didn't have destination_y"); | ||||||
|  |             if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null) | ||||||
|  |                 UUID.TryParse(args["destination_uuid"].AsString(), out data.uuid); | ||||||
|  |             if (args.ContainsKey("destination_name") && args["destination_name"] != null) | ||||||
|  |                 data.name = args["destination_name"].ToString(); | ||||||
|  |             if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null) | ||||||
|  |                 data.flags = args["teleport_flags"].AsUInteger(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         protected virtual GridRegion ExtractGatekeeper(AgentDestinationData data) | ||||||
|  |         { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         protected string GetCallerIP(Hashtable request) | ||||||
|         { |         { | ||||||
|             if (!m_Proxy) |             if (!m_Proxy) | ||||||
|                 return Util.GetCallerIP(request); |                 return Util.GetCallerIP(request); | ||||||
|  | @ -441,7 +455,7 @@ namespace OpenSim.Server.Handlers.Simulation | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // subclasses can override this |         // subclasses can override this | ||||||
|         protected virtual bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) |         protected virtual bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason) | ||||||
|         { |         { | ||||||
|             reason = String.Empty; |             reason = String.Empty; | ||||||
|              |              | ||||||
|  | @ -593,7 +607,6 @@ namespace OpenSim.Server.Handlers.Simulation | ||||||
|                 //agent.Dump(); |                 //agent.Dump(); | ||||||
|                 // This is one of the meanings of PUT agent |                 // This is one of the meanings of PUT agent | ||||||
|                 result = UpdateAgent(destination, agent); |                 result = UpdateAgent(destination, agent); | ||||||
| 
 |  | ||||||
|             } |             } | ||||||
|             else if ("AgentPosition".Equals(messageType)) |             else if ("AgentPosition".Equals(messageType)) | ||||||
|             { |             { | ||||||
|  | @ -624,4 +637,14 @@ namespace OpenSim.Server.Handlers.Simulation | ||||||
|             return m_SimulationService.UpdateAgent(destination, agent); |             return m_SimulationService.UpdateAgent(destination, agent); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     public class AgentDestinationData | ||||||
|  |     { | ||||||
|  |         public int x; | ||||||
|  |         public int y; | ||||||
|  |         public string name; | ||||||
|  |         public UUID uuid; | ||||||
|  |         public uint flags; | ||||||
|  |         public bool fromLogin; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -53,7 +53,8 @@ namespace OpenSim.Services.Connectors.Hypergrid | ||||||
| 
 | 
 | ||||||
|         private IAssetService m_AssetService; |         private IAssetService m_AssetService; | ||||||
| 
 | 
 | ||||||
|         public GatekeeperServiceConnector() : base() |         public GatekeeperServiceConnector() | ||||||
|  |             : base() | ||||||
|         { |         { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -123,11 +124,13 @@ namespace OpenSim.Services.Connectors.Hypergrid | ||||||
|                         realHandle = Convert.ToUInt64((string)hash["handle"]); |                         realHandle = Convert.ToUInt64((string)hash["handle"]); | ||||||
|                         //m_log.Debug(">> HERE, realHandle: " + realHandle); |                         //m_log.Debug(">> HERE, realHandle: " + realHandle); | ||||||
|                     } |                     } | ||||||
|                     if (hash["region_image"] != null) { |                     if (hash["region_image"] != null) | ||||||
|  |                     { | ||||||
|                         imageURL = (string)hash["region_image"]; |                         imageURL = (string)hash["region_image"]; | ||||||
|                         //m_log.Debug(">> HERE, imageURL: " + imageURL); |                         //m_log.Debug(">> HERE, imageURL: " + imageURL); | ||||||
|                     } |                     } | ||||||
|                     if (hash["external_name"] != null) { |                     if (hash["external_name"] != null) | ||||||
|  |                     { | ||||||
|                         externalName = (string)hash["external_name"]; |                         externalName = (string)hash["external_name"]; | ||||||
|                         //m_log.Debug(">> HERE, externalName: " + externalName); |                         //m_log.Debug(">> HERE, externalName: " + externalName); | ||||||
|                     } |                     } | ||||||
|  | @ -257,7 +260,8 @@ namespace OpenSim.Services.Connectors.Hypergrid | ||||||
|                         region.RegionName = (string)hash["region_name"]; |                         region.RegionName = (string)hash["region_name"]; | ||||||
|                         //m_log.Debug(">> HERE, region_name: " + region.RegionName); |                         //m_log.Debug(">> HERE, region_name: " + region.RegionName); | ||||||
|                     } |                     } | ||||||
|                     if (hash["hostname"] != null) { |                     if (hash["hostname"] != null) | ||||||
|  |                     { | ||||||
|                         region.ExternalHostName = (string)hash["hostname"]; |                         region.ExternalHostName = (string)hash["hostname"]; | ||||||
|                         //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); |                         //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); | ||||||
|                     } |                     } | ||||||
|  | @ -278,7 +282,7 @@ namespace OpenSim.Services.Connectors.Hypergrid | ||||||
| 
 | 
 | ||||||
|                     if (hash["server_uri"] != null) |                     if (hash["server_uri"] != null) | ||||||
|                     { |                     { | ||||||
|                         region.ServerURI = (string) hash["server_uri"]; |                         region.ServerURI = (string)hash["server_uri"]; | ||||||
|                         //m_log.Debug(">> HERE, server_uri: " + region.ServerURI); |                         //m_log.Debug(">> HERE, server_uri: " + region.ServerURI); | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|  | @ -295,55 +299,5 @@ namespace OpenSim.Services.Connectors.Hypergrid | ||||||
| 
 | 
 | ||||||
|             return null; |             return null; | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason) |  | ||||||
|         { |  | ||||||
|             // m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: CreateAgent start"); |  | ||||||
| 
 |  | ||||||
|             myipaddress = String.Empty; |  | ||||||
|             reason = String.Empty; |  | ||||||
| 
 |  | ||||||
|             if (destination == null) |  | ||||||
|             { |  | ||||||
|                 m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Given destination is null"); |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; |  | ||||||
| 
 |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 OSDMap args = aCircuit.PackAgentCircuitData(); |  | ||||||
| 
 |  | ||||||
|                 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString()); |  | ||||||
|                 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString()); |  | ||||||
|                 args["destination_name"] = OSD.FromString(destination.RegionName); |  | ||||||
|                 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); |  | ||||||
|                 args["teleport_flags"] = OSD.FromString(flags.ToString()); |  | ||||||
| 
 |  | ||||||
|                 OSDMap result = WebUtil.PostToService(uri, args, 80000); |  | ||||||
|                 if (result["Success"].AsBoolean()) |  | ||||||
|                 { |  | ||||||
|                     OSDMap unpacked = (OSDMap)result["_Result"]; |  | ||||||
| 
 |  | ||||||
|                     if (unpacked != null) |  | ||||||
|                     { |  | ||||||
|                         reason = unpacked["reason"].AsString(); |  | ||||||
|                         myipaddress = unpacked["your_ip"].AsString(); |  | ||||||
|                         return unpacked["success"].AsBoolean(); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                  |  | ||||||
|                 reason = result["Message"] != null ? result["Message"].AsString() : "error"; |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
|             catch (Exception e) |  | ||||||
|             { |  | ||||||
|                 m_log.Warn("[REMOTE SIMULATION CONNECTOR]: CreateAgent failed with exception: " + e.ToString()); |  | ||||||
|                 reason = e.Message; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -44,13 +44,14 @@ using Nini.Config; | ||||||
| 
 | 
 | ||||||
| namespace OpenSim.Services.Connectors.Hypergrid | namespace OpenSim.Services.Connectors.Hypergrid | ||||||
| { | { | ||||||
|     public class UserAgentServiceConnector : IUserAgentService |     public class UserAgentServiceConnector : SimulationServiceConnector, IUserAgentService | ||||||
|     { |     { | ||||||
|         private static readonly ILog m_log = |         private static readonly ILog m_log = | ||||||
|             LogManager.GetLogger( |             LogManager.GetLogger( | ||||||
|             MethodBase.GetCurrentMethod().DeclaringType); |             MethodBase.GetCurrentMethod().DeclaringType); | ||||||
| 
 | 
 | ||||||
|         string m_ServerURL; |         private string m_ServerURL; | ||||||
|  |         private GridRegion m_Gatekeeper; | ||||||
| 
 | 
 | ||||||
|         public UserAgentServiceConnector(string url) : this(url, true) |         public UserAgentServiceConnector(string url) : this(url, true) | ||||||
|         { |         { | ||||||
|  | @ -102,9 +103,15 @@ namespace OpenSim.Services.Connectors.Hypergrid | ||||||
|             m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL); |             m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         protected override string AgentPath() | ||||||
|  |         { | ||||||
|  |             return "homeagent/"; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         // The Login service calls this interface with a non-null [client] ipaddress  |         // The Login service calls this interface with fromLogin=true  | ||||||
|         public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress, out string reason) |         // Sims call it with fromLogin=false | ||||||
|  |         // Either way, this is verified by the handler | ||||||
|  |         public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, bool fromLogin, out string reason) | ||||||
|         { |         { | ||||||
|             reason = String.Empty; |             reason = String.Empty; | ||||||
| 
 | 
 | ||||||
|  | @ -115,119 +122,34 @@ namespace OpenSim.Services.Connectors.Hypergrid | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             string uri = m_ServerURL + "homeagent/" + aCircuit.AgentID + "/"; |             GridRegion home = new GridRegion(); | ||||||
|  |             home.ServerURI = m_ServerURL; | ||||||
|  |             home.RegionID = destination.RegionID; | ||||||
|  |             home.RegionLocX = destination.RegionLocX; | ||||||
|  |             home.RegionLocY = destination.RegionLocY; | ||||||
| 
 | 
 | ||||||
|             Console.WriteLine("   >>> LoginAgentToGrid <<< " + uri); |             m_Gatekeeper = gatekeeper; | ||||||
| 
 | 
 | ||||||
|             HttpWebRequest AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri); |             Console.WriteLine("   >>> LoginAgentToGrid <<< " + home.ServerURI); | ||||||
|             AgentCreateRequest.Method = "POST"; |  | ||||||
|             AgentCreateRequest.ContentType = "application/json"; |  | ||||||
|             AgentCreateRequest.Timeout = 10000; |  | ||||||
|             //AgentCreateRequest.KeepAlive = false; |  | ||||||
|             //AgentCreateRequest.Headers.Add("Authorization", authKey); |  | ||||||
| 
 |  | ||||||
|             // Fill it in |  | ||||||
|             OSDMap args = PackCreateAgentArguments(aCircuit, gatekeeper, destination, ipaddress); |  | ||||||
| 
 |  | ||||||
|             string strBuffer = ""; |  | ||||||
|             byte[] buffer = new byte[1]; |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 strBuffer = OSDParser.SerializeJsonString(args); |  | ||||||
|                 Encoding str = Util.UTF8; |  | ||||||
|                 buffer = str.GetBytes(strBuffer); |  | ||||||
| 
 |  | ||||||
|             } |  | ||||||
|             catch (Exception e) |  | ||||||
|             { |  | ||||||
|                 m_log.WarnFormat("[USER AGENT CONNECTOR]: Exception thrown on serialization of ChildCreate: {0}", e.Message); |  | ||||||
|                 // ignore. buffer will be empty, caller should check. |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             Stream os = null; |  | ||||||
|             try |  | ||||||
|             { // send the Post |  | ||||||
|                 AgentCreateRequest.ContentLength = buffer.Length;   //Count bytes to send |  | ||||||
|                 os = AgentCreateRequest.GetRequestStream(); |  | ||||||
|                 os.Write(buffer, 0, strBuffer.Length);         //Send it |  | ||||||
|                 m_log.InfoFormat("[USER AGENT CONNECTOR]: Posted CreateAgent request to remote sim {0}, region {1}, x={2} y={3}", |  | ||||||
|                     uri, destination.RegionName, destination.RegionLocX, destination.RegionLocY); |  | ||||||
|             } |  | ||||||
|             //catch (WebException ex) |  | ||||||
|             catch |  | ||||||
|             { |  | ||||||
|                 //m_log.InfoFormat("[USER AGENT CONNECTOR]: Bad send on ChildAgentUpdate {0}", ex.Message); |  | ||||||
|                 reason = "cannot contact remote region"; |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
|             finally |  | ||||||
|             { |  | ||||||
|                 if (os != null) |  | ||||||
|                     os.Close(); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Let's wait for the response |  | ||||||
|             //m_log.Info("[USER AGENT CONNECTOR]: Waiting for a reply after DoCreateChildAgentCall"); |  | ||||||
| 
 |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 using (WebResponse webResponse = AgentCreateRequest.GetResponse()) |  | ||||||
|                 { |  | ||||||
|                     if (webResponse == null) |  | ||||||
|                     { |  | ||||||
|                         m_log.Info("[USER AGENT CONNECTOR]: Null reply on DoCreateChildAgentCall post"); |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
|                         using (Stream s = webResponse.GetResponseStream()) |  | ||||||
|                         { |  | ||||||
|                             using (StreamReader sr = new StreamReader(s)) |  | ||||||
|                             { |  | ||||||
|                                 string response = sr.ReadToEnd().Trim(); |  | ||||||
|                                 m_log.InfoFormat("[USER AGENT CONNECTOR]: DoCreateChildAgentCall reply was {0} ", response); |  | ||||||
| 
 |  | ||||||
|                                 if (!String.IsNullOrEmpty(response)) |  | ||||||
|                                 { |  | ||||||
|                                     try |  | ||||||
|                                     { |  | ||||||
|                                         // we assume we got an OSDMap back |  | ||||||
|                                         OSDMap r = Util.GetOSDMap(response); |  | ||||||
|                                         bool success = r["success"].AsBoolean(); |  | ||||||
|                                         reason = r["reason"].AsString(); |  | ||||||
|                                         return success; |  | ||||||
|                                     } |  | ||||||
|                                     catch (NullReferenceException e) |  | ||||||
|                                     { |  | ||||||
|                                         m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", e.Message); |  | ||||||
| 
 |  | ||||||
|                                         // check for old style response |  | ||||||
|                                         if (response.ToLower().StartsWith("true")) |  | ||||||
|                                             return true; |  | ||||||
| 
 |  | ||||||
|                                         return false; |  | ||||||
|                                     } |  | ||||||
|                                 } |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             catch (WebException ex) |  | ||||||
|             { |  | ||||||
|                 m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", ex.Message); |  | ||||||
|                 reason = "Destination did not reply"; |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return true; |  | ||||||
| 
 | 
 | ||||||
|  |             uint flags = fromLogin ? (uint)TeleportFlags.ViaLogin : (uint)TeleportFlags.ViaHome; | ||||||
|  |             return CreateAgent(home, aCircuit, flags, out reason); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|         // The simulators call this interface |         // The simulators call this interface | ||||||
|         public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason) |         public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason) | ||||||
|         { |         { | ||||||
|             return LoginAgentToGrid(aCircuit, gatekeeper, destination, null, out reason); |             return LoginAgentToGrid(aCircuit, gatekeeper, destination, false, out reason); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         protected override void PackData(OSDMap args, AgentCircuitData aCircuit, GridRegion destination, uint flags) | ||||||
|  |         { | ||||||
|  |             base.PackData(args, aCircuit, destination, flags); | ||||||
|  |             args["gatekeeper_serveruri"] = OSD.FromString(m_Gatekeeper.ServerURI); | ||||||
|  |             args["gatekeeper_host"] = OSD.FromString(m_Gatekeeper.ExternalHostName); | ||||||
|  |             args["gatekeeper_port"] = OSD.FromString(m_Gatekeeper.HttpPort.ToString()); | ||||||
|  |             args["destination_serveruri"] = OSD.FromString(destination.ServerURI); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         protected OSDMap PackCreateAgentArguments(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress) |         protected OSDMap PackCreateAgentArguments(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress) | ||||||
|  |  | ||||||
|  | @ -79,11 +79,27 @@ namespace OpenSim.Services.Connectors.Simulation | ||||||
|             return "agent/"; |             return "agent/"; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         protected virtual void PackData(OSDMap args, AgentCircuitData aCircuit, GridRegion destination, uint flags) | ||||||
|  |         { | ||||||
|  |                 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString()); | ||||||
|  |                 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString()); | ||||||
|  |                 args["destination_name"] = OSD.FromString(destination.RegionName); | ||||||
|  |                 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); | ||||||
|  |                 args["teleport_flags"] = OSD.FromString(flags.ToString()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) |         public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) | ||||||
|         { |         { | ||||||
|             // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CreateAgent start"); |             string tmp = String.Empty; | ||||||
|  |             return CreateAgent(destination, aCircuit, flags, out tmp, out reason); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|  |         public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason) | ||||||
|  |         { | ||||||
|  |             m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: Creating agent at {0}", destination.ServerURI); | ||||||
|             reason = String.Empty; |             reason = String.Empty; | ||||||
|  |             myipaddress = String.Empty; | ||||||
|  | 
 | ||||||
|             if (destination == null) |             if (destination == null) | ||||||
|             { |             { | ||||||
|                 reason = "Destination not found"; |                 reason = "Destination not found"; | ||||||
|  | @ -96,12 +112,7 @@ namespace OpenSim.Services.Connectors.Simulation | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 OSDMap args = aCircuit.PackAgentCircuitData(); |                 OSDMap args = aCircuit.PackAgentCircuitData(); | ||||||
| 
 |                 PackData(args, aCircuit, destination, flags); | ||||||
|                 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString()); |  | ||||||
|                 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString()); |  | ||||||
|                 args["destination_name"] = OSD.FromString(destination.RegionName); |  | ||||||
|                 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); |  | ||||||
|                 args["teleport_flags"] = OSD.FromString(flags.ToString()); |  | ||||||
| 
 | 
 | ||||||
|                 OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000); |                 OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000); | ||||||
|                 bool success = result["success"].AsBoolean(); |                 bool success = result["success"].AsBoolean(); | ||||||
|  | @ -111,6 +122,7 @@ namespace OpenSim.Services.Connectors.Simulation | ||||||
| 
 | 
 | ||||||
|                     reason = data["reason"].AsString(); |                     reason = data["reason"].AsString(); | ||||||
|                     success = data["success"].AsBoolean(); |                     success = data["success"].AsBoolean(); | ||||||
|  |                     myipaddress = data["your_ip"].AsString(); | ||||||
|                     return success; |                     return success; | ||||||
|                 } |                 } | ||||||
|                |                | ||||||
|  | @ -125,6 +137,7 @@ namespace OpenSim.Services.Connectors.Simulation | ||||||
| 
 | 
 | ||||||
|                         reason = data["reason"].AsString(); |                         reason = data["reason"].AsString(); | ||||||
|                         success = data["success"].AsBoolean(); |                         success = data["success"].AsBoolean(); | ||||||
|  |                         myipaddress = data["your_ip"].AsString(); | ||||||
|                         m_log.WarnFormat( |                         m_log.WarnFormat( | ||||||
|                             "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName); |                             "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName); | ||||||
|                         return success; |                         return success; | ||||||
|  | @ -229,7 +242,7 @@ namespace OpenSim.Services.Connectors.Simulation | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout) |         private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout) | ||||||
|         { |         { | ||||||
|             // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent start"); |             // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent in {0}", destination.ServerURI); | ||||||
| 
 | 
 | ||||||
|             // Eventually, we want to use a caps url instead of the agentID |             // Eventually, we want to use a caps url instead of the agentID | ||||||
|             string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/"; |             string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/"; | ||||||
|  |  | ||||||
|  | @ -210,10 +210,10 @@ namespace OpenSim.Services.HypergridService | ||||||
|             return home; |             return home; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason) |         public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason) | ||||||
|         { |         { | ||||||
|             m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}",  |             m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}",  | ||||||
|                 agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI); |                 agentCircuit.firstname, agentCircuit.lastname, (fromLogin ? agentCircuit.IPAddress : "stored IP"), gatekeeper.ServerURI); | ||||||
| 
 | 
 | ||||||
|             string gridName = gatekeeper.ServerURI; |             string gridName = gatekeeper.ServerURI; | ||||||
| 
 | 
 | ||||||
|  | @ -265,7 +265,7 @@ namespace OpenSim.Services.HypergridService | ||||||
|             bool success = false; |             bool success = false; | ||||||
|             string myExternalIP = string.Empty; |             string myExternalIP = string.Empty; | ||||||
| 
 | 
 | ||||||
|             m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); |             m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}, desired region: {2}", m_GridName, gridName, region.RegionID); | ||||||
| 
 | 
 | ||||||
|             if (m_GridName == gridName) |             if (m_GridName == gridName) | ||||||
|                 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); |                 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); | ||||||
|  | @ -296,8 +296,8 @@ namespace OpenSim.Services.HypergridService | ||||||
| 
 | 
 | ||||||
|             m_log.DebugFormat("[USER AGENT SERVICE]: Gatekeeper sees me as {0}", myExternalIP); |             m_log.DebugFormat("[USER AGENT SERVICE]: Gatekeeper sees me as {0}", myExternalIP); | ||||||
|             // else set the IP addresses associated with this client |             // else set the IP addresses associated with this client | ||||||
|             if (clientIP != null) |             if (fromLogin) | ||||||
|                 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString(); |                 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = agentCircuit.IPAddress; | ||||||
|             m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP; |             m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP; | ||||||
| 
 | 
 | ||||||
|             return true; |             return true; | ||||||
|  | @ -306,7 +306,7 @@ namespace OpenSim.Services.HypergridService | ||||||
|         public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason) |         public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason) | ||||||
|         { |         { | ||||||
|             reason = string.Empty; |             reason = string.Empty; | ||||||
|             return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, null, out reason); |             return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, false, out reason); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void SetClientIP(UUID sessionID, string ip) |         private void SetClientIP(UUID sessionID, string ip) | ||||||
|  |  | ||||||
|  | @ -48,10 +48,7 @@ namespace OpenSim.Services.Interfaces | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public interface IUserAgentService |     public interface IUserAgentService | ||||||
|     { |     { | ||||||
|         // called by login service only |         bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason); | ||||||
|         bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason); |  | ||||||
|         // called by simulators |  | ||||||
|         bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason); |  | ||||||
|         void LogoutAgent(UUID userID, UUID sessionID); |         void LogoutAgent(UUID userID, UUID sessionID); | ||||||
|         GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); |         GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); | ||||||
|         Dictionary<string, object> GetServerURLs(UUID userID); |         Dictionary<string, object> GetServerURLs(UUID userID); | ||||||
|  |  | ||||||
|  | @ -941,7 +941,7 @@ namespace OpenSim.Services.LLLoginService | ||||||
|         private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason) |         private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason) | ||||||
|         { |         { | ||||||
|             m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName); |             m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName); | ||||||
|             if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, clientIP, out reason)) |             if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, true, out reason)) | ||||||
|                 return true; |                 return true; | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -157,6 +157,7 @@ | ||||||
|       <Reference name="System"/> |       <Reference name="System"/> | ||||||
|       <Reference name="System.Core"/> |       <Reference name="System.Core"/> | ||||||
|       <Reference name="log4net" path="../../../bin/"/> |       <Reference name="log4net" path="../../../bin/"/> | ||||||
|  |       <Reference name="Nini" path="../../../bin/"/> | ||||||
|       <Reference name="OpenMetaverseTypes" path="../../../bin/"/> |       <Reference name="OpenMetaverseTypes" path="../../../bin/"/> | ||||||
|       <Reference name="OpenMetaverse" path="../../../bin/"/> |       <Reference name="OpenMetaverse" path="../../../bin/"/> | ||||||
|       <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/> |       <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/> | ||||||
|  | @ -863,6 +864,7 @@ | ||||||
|       <Reference name="Mono.Addins.Setup" path="../../../bin/"/> |       <Reference name="Mono.Addins.Setup" path="../../../bin/"/> | ||||||
|       <Reference name="OpenSim.Framework"/> |       <Reference name="OpenSim.Framework"/> | ||||||
|       <Reference name="OpenSim.Framework.Console"/> |       <Reference name="OpenSim.Framework.Console"/> | ||||||
|  |       <Reference name="OpenSim.Framework.Monitoring"/> | ||||||
|       <Reference name="OpenSim.Framework.Servers"/> |       <Reference name="OpenSim.Framework.Servers"/> | ||||||
|       <Reference name="OpenSim.Framework.Servers.HttpServer"/> |       <Reference name="OpenSim.Framework.Servers.HttpServer"/> | ||||||
|       <Reference name="Nini" path="../../../bin/"/> |       <Reference name="Nini" path="../../../bin/"/> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Melanie
						Melanie