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
 | 
			
		||||
    {
 | 
			
		||||
        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 XmlSerializer m_serializer;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,7 @@ namespace OpenSim.Capabilities.Handlers
 | 
			
		|||
{
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -121,4 +121,4 @@ namespace OpenSim.Capabilities.Handlers
 | 
			
		|||
            return llsdItem;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
/*
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) Contributors, http://opensimulator.org/
 | 
			
		||||
 * See CONTRIBUTORS.TXT for a full list of copyright holders.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -44,16 +44,16 @@ namespace OpenSim.Framework.Monitoring
 | 
			
		|||
            sb.Append("MEMORY STATISTICS");
 | 
			
		||||
            sb.Append(Environment.NewLine);
 | 
			
		||||
            sb.AppendFormat(
 | 
			
		||||
                    "Allocated to OpenSim objects: {0} MB\n",
 | 
			
		||||
                    Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
 | 
			
		||||
                "Heap allocated to OpenSim   : {0} MB\n",
 | 
			
		||||
                Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
 | 
			
		||||
 | 
			
		||||
            sb.AppendFormat(
 | 
			
		||||
                "OpenSim last object memory churn    : {0} MB/s\n",
 | 
			
		||||
                Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3));
 | 
			
		||||
                "Last heap allocation rate   : {0} MB/s\n",
 | 
			
		||||
                Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
 | 
			
		||||
 | 
			
		||||
            sb.AppendFormat(
 | 
			
		||||
                "OpenSim average object memory churn : {0} MB/s\n",
 | 
			
		||||
                Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3));
 | 
			
		||||
                "Average heap allocation rate: {0} MB/s\n",
 | 
			
		||||
                Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
 | 
			
		||||
 | 
			
		||||
            Process myprocess = Process.GetCurrentProcess();
 | 
			
		||||
            if (!myprocess.HasExited)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,17 +60,17 @@ namespace OpenSim.Framework.Monitoring
 | 
			
		|||
        private static bool m_enabled;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Last memory churn in bytes per millisecond.
 | 
			
		||||
        /// Average heap allocation rate in bytes per millisecond.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static double AverageMemoryChurn
 | 
			
		||||
        public static double AverageHeapAllocationRate
 | 
			
		||||
        {
 | 
			
		||||
            get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Average memory churn in bytes per millisecond.
 | 
			
		||||
        /// Last heap allocation in bytes
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static double LastMemoryChurn
 | 
			
		||||
        public static double LastHeapAllocationRate
 | 
			
		||||
        {
 | 
			
		||||
            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.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using log4net;
 | 
			
		||||
using OpenMetaverse.StructuredData;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Framework.Monitoring
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +40,10 @@ namespace OpenSim.Framework.Monitoring
 | 
			
		|||
    /// </summary>
 | 
			
		||||
    public class Stat : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
//        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 | 
			
		||||
 | 
			
		||||
        public static readonly char[] DisallowedShortNameCharacters = { '.' };
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Category of this stat (e.g. cache, scene, etc).
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -95,7 +101,7 @@ namespace OpenSim.Framework.Monitoring
 | 
			
		|||
        /// <remarks>
 | 
			
		||||
        /// Will be null if no measures of interest require samples.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        private static Queue<double> m_samples;
 | 
			
		||||
        private Queue<double> m_samples;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Maximum number of statistical samples.
 | 
			
		||||
| 
						 | 
				
			
			@ -162,6 +168,12 @@ namespace OpenSim.Framework.Monitoring
 | 
			
		|||
                throw new Exception(
 | 
			
		||||
                    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;
 | 
			
		||||
            Name = name;
 | 
			
		||||
            Description = description;
 | 
			
		||||
| 
						 | 
				
			
			@ -204,6 +216,8 @@ namespace OpenSim.Framework.Monitoring
 | 
			
		|||
                if (m_samples.Count >= m_maxSamples)
 | 
			
		||||
                    m_samples.Dequeue();
 | 
			
		||||
 | 
			
		||||
//                m_log.DebugFormat("[STAT]: Recording value {0} for {1}", newValue, Name);
 | 
			
		||||
 | 
			
		||||
                m_samples.Enqueue(newValue);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -242,6 +256,10 @@ namespace OpenSim.Framework.Monitoring
 | 
			
		|||
 | 
			
		||||
                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)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (lastSample != null)
 | 
			
		||||
| 
						 | 
				
			
			@ -253,7 +271,7 @@ namespace OpenSim.Framework.Monitoring
 | 
			
		|||
 | 
			
		||||
                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.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Framework.Monitoring
 | 
			
		||||
| 
						 | 
				
			
			@ -54,13 +55,13 @@ namespace OpenSim.Framework.Monitoring
 | 
			
		|||
        public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
 | 
			
		||||
            = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>();
 | 
			
		||||
 | 
			
		||||
        private static AssetStatsCollector assetStats;
 | 
			
		||||
        private static UserStatsCollector userStats;
 | 
			
		||||
        private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
 | 
			
		||||
//        private static AssetStatsCollector assetStats;
 | 
			
		||||
//        private static UserStatsCollector userStats;
 | 
			
		||||
//        private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
 | 
			
		||||
 | 
			
		||||
        public static AssetStatsCollector AssetStats { get { return assetStats; } }
 | 
			
		||||
        public static UserStatsCollector UserStats { get { return userStats; } }
 | 
			
		||||
        public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
 | 
			
		||||
//        public static AssetStatsCollector AssetStats { get { return assetStats; } }
 | 
			
		||||
//        public static UserStatsCollector UserStats { get { return userStats; } }
 | 
			
		||||
        public static SimExtraStatsCollector SimExtraStats { get; set; }
 | 
			
		||||
 | 
			
		||||
        public static void RegisterConsoleCommands(ICommandConsole console)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -68,12 +69,14 @@ namespace OpenSim.Framework.Monitoring
 | 
			
		|||
                "General",
 | 
			
		||||
                false,
 | 
			
		||||
                "show stats",
 | 
			
		||||
                "show stats [list|all|<category>]",
 | 
			
		||||
                "show stats [list|all|(<category>[.<container>])+",
 | 
			
		||||
                "Show statistical information for this server",
 | 
			
		||||
                "If no final argument is specified then legacy statistics information is currently shown.\n"
 | 
			
		||||
                    + "If list is specified then statistic categories are shown.\n"
 | 
			
		||||
                    + "If all is specified then all registered statistics are shown.\n"
 | 
			
		||||
                    + "If a category name is specified then only statistics from that category are shown.\n"
 | 
			
		||||
                    + "'list' argument will show statistic categories.\n"
 | 
			
		||||
                    + "'all' will show all statistics.\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",
 | 
			
		||||
                HandleShowStatsCommand);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -84,43 +87,47 @@ namespace OpenSim.Framework.Monitoring
 | 
			
		|||
 | 
			
		||||
            if (cmd.Length > 2)
 | 
			
		||||
            {
 | 
			
		||||
                var categoryName = cmd[2];
 | 
			
		||||
                var containerName = cmd.Length > 3 ? cmd[3] : String.Empty;
 | 
			
		||||
                foreach (string name in cmd.Skip(2))
 | 
			
		||||
                {
 | 
			
		||||
                    string[] components = name.Split('.');
 | 
			
		||||
 | 
			
		||||
                if (categoryName == AllSubCommand)
 | 
			
		||||
                {
 | 
			
		||||
                    foreach (var category in RegisteredStats.Values)
 | 
			
		||||
                    string categoryName = components[0];
 | 
			
		||||
                    string containerName = components.Length > 1 ? components[1] : null;
 | 
			
		||||
 | 
			
		||||
                    if (categoryName == AllSubCommand)
 | 
			
		||||
                    {
 | 
			
		||||
                        OutputCategoryStatsToConsole(con, category);
 | 
			
		||||
                        OutputAllStatsToConsole(con);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (categoryName == ListSubCommand)
 | 
			
		||||
                {
 | 
			
		||||
                    con.Output("Statistic categories available are:");
 | 
			
		||||
                    foreach (string category in RegisteredStats.Keys)
 | 
			
		||||
                        con.OutputFormat("  {0}", category);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    SortedDictionary<string, SortedDictionary<string, Stat>> category;
 | 
			
		||||
                    if (!RegisteredStats.TryGetValue(categoryName, out category))
 | 
			
		||||
                    else if (categoryName == ListSubCommand)
 | 
			
		||||
                    {
 | 
			
		||||
                        con.OutputFormat("No such category as {0}", categoryName);
 | 
			
		||||
                        con.Output("Statistic categories available are:");
 | 
			
		||||
                        foreach (string category in RegisteredStats.Keys)
 | 
			
		||||
                            con.OutputFormat("  {0}", category);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        if (String.IsNullOrEmpty(containerName))
 | 
			
		||||
                            OutputCategoryStatsToConsole(con, category);
 | 
			
		||||
                        SortedDictionary<string, SortedDictionary<string, Stat>> category;
 | 
			
		||||
                        if (!RegisteredStats.TryGetValue(categoryName, out category))
 | 
			
		||||
                        {
 | 
			
		||||
                            con.OutputFormat("No such category as {0}", categoryName);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            SortedDictionary<string, Stat> container;
 | 
			
		||||
                            if (category.TryGetValue(containerName, out container))
 | 
			
		||||
                            if (String.IsNullOrEmpty(containerName))
 | 
			
		||||
                            {
 | 
			
		||||
                                OutputContainerStatsToConsole(con, container);
 | 
			
		||||
                                OutputCategoryStatsToConsole(con, category);
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
 | 
			
		||||
                                SortedDictionary<string, Stat> container;
 | 
			
		||||
                                if (category.TryGetValue(containerName, out container))
 | 
			
		||||
                                {
 | 
			
		||||
                                    OutputContainerStatsToConsole(con, container);
 | 
			
		||||
                                }
 | 
			
		||||
                                else
 | 
			
		||||
                                {
 | 
			
		||||
                                    con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -129,7 +136,18 @@ namespace OpenSim.Framework.Monitoring
 | 
			
		|||
            else
 | 
			
		||||
            {
 | 
			
		||||
                // Legacy
 | 
			
		||||
                con.Output(SimExtraStats.Report());
 | 
			
		||||
                if (SimExtraStats != null)
 | 
			
		||||
                    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>
 | 
			
		||||
        /// Start collecting statistics related to assets.
 | 
			
		||||
        /// Should only be called once.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static AssetStatsCollector StartCollectingAssetStats()
 | 
			
		||||
        {
 | 
			
		||||
            assetStats = new AssetStatsCollector();
 | 
			
		||||
 | 
			
		||||
            return assetStats;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Start collecting statistics related to users.
 | 
			
		||||
        /// Should only be called once.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static UserStatsCollector StartCollectingUserStats()
 | 
			
		||||
        {
 | 
			
		||||
            userStats = new UserStatsCollector();
 | 
			
		||||
 | 
			
		||||
            return userStats;
 | 
			
		||||
        }
 | 
			
		||||
//        /// <summary>
 | 
			
		||||
//        /// Start collecting statistics related to assets.
 | 
			
		||||
//        /// Should only be called once.
 | 
			
		||||
//        /// </summary>
 | 
			
		||||
//        public static AssetStatsCollector StartCollectingAssetStats()
 | 
			
		||||
//        {
 | 
			
		||||
//            assetStats = new AssetStatsCollector();
 | 
			
		||||
//
 | 
			
		||||
//            return assetStats;
 | 
			
		||||
//        }
 | 
			
		||||
//
 | 
			
		||||
//        /// <summary>
 | 
			
		||||
//        /// Start collecting statistics related to users.
 | 
			
		||||
//        /// Should only be called once.
 | 
			
		||||
//        /// </summary>
 | 
			
		||||
//        public static UserStatsCollector StartCollectingUserStats()
 | 
			
		||||
//        {
 | 
			
		||||
//            userStats = new UserStatsCollector();
 | 
			
		||||
//
 | 
			
		||||
//            return userStats;
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Registers a statistic.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,25 +86,22 @@ namespace OpenSim.Framework.Servers
 | 
			
		|||
        /// </summary>
 | 
			
		||||
        protected virtual void StartupSpecific()
 | 
			
		||||
        {
 | 
			
		||||
            if (m_console == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            StatsManager.SimExtraStats = new SimExtraStatsCollector();
 | 
			
		||||
            RegisterCommonCommands();
 | 
			
		||||
            
 | 
			
		||||
            m_console.Commands.AddCommand("General", false, "quit",
 | 
			
		||||
                    "quit",
 | 
			
		||||
                    "Quit the application", HandleQuit);
 | 
			
		||||
            RegisterCommonComponents(Config);
 | 
			
		||||
        }       
 | 
			
		||||
 | 
			
		||||
            m_console.Commands.AddCommand("General", false, "shutdown",
 | 
			
		||||
                    "shutdown",
 | 
			
		||||
                    "Quit the application", HandleQuit);
 | 
			
		||||
        protected override void ShutdownSpecific()
 | 
			
		||||
        {            
 | 
			
		||||
            m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete.  Exiting...");
 | 
			
		||||
 | 
			
		||||
            RemovePIDFile();
 | 
			
		||||
 | 
			
		||||
            base.ShutdownSpecific();
 | 
			
		||||
 | 
			
		||||
            Environment.Exit(0);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual void ShutdownSpecific() {}
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Provides a list of help topics that are available.  Overriding classes should append their topics to the
 | 
			
		||||
        /// information returned when the base method is called.
 | 
			
		||||
| 
						 | 
				
			
			@ -153,25 +150,8 @@ namespace OpenSim.Framework.Servers
 | 
			
		|||
                timeTaken.Minutes, timeTaken.Seconds);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual void Shutdown()
 | 
			
		||||
        public string osSecret 
 | 
			
		||||
        {
 | 
			
		||||
            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
 | 
			
		||||
            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 HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 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 
 | 
			
		||||
| 
						 | 
				
			
			@ -81,6 +80,11 @@ namespace OpenSim.Framework.Servers.HttpServer
 | 
			
		|||
        /// </remarks>
 | 
			
		||||
        public int RequestNumber { get; private set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Statistic for holding number of requests processed.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private Stat m_requestsProcessedStat;
 | 
			
		||||
 | 
			
		||||
        private volatile int NotSocketErrors = 0;
 | 
			
		||||
        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);
 | 
			
		||||
            WebSocketRequestDelegate dWebSocketRequestDelegate = null;
 | 
			
		||||
            lock (m_WebSocketHandlers)
 | 
			
		||||
| 
						 | 
				
			
			@ -455,8 +458,7 @@ namespace OpenSim.Framework.Servers.HttpServer
 | 
			
		|||
            
 | 
			
		||||
            OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
 | 
			
		||||
            resp.ReuseContext = true;
 | 
			
		||||
            HandleRequest(req, resp);
 | 
			
		||||
           
 | 
			
		||||
            HandleRequest(req, resp);           
 | 
			
		||||
 | 
			
		||||
            // !!!HACK ALERT!!!
 | 
			
		||||
            // There seems to be a bug in the underlying http code that makes subsequent requests
 | 
			
		||||
| 
						 | 
				
			
			@ -1870,6 +1872,21 @@ namespace OpenSim.Framework.Servers.HttpServer
 | 
			
		|||
                // useful without inbound HTTP.
 | 
			
		||||
                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)
 | 
			
		||||
| 
						 | 
				
			
			@ -1902,6 +1919,9 @@ namespace OpenSim.Framework.Servers.HttpServer
 | 
			
		|||
        public void Stop()
 | 
			
		||||
        {
 | 
			
		||||
            HTTPDRunning = false;
 | 
			
		||||
 | 
			
		||||
            StatsManager.DeregisterStat(m_requestsProcessedStat);
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                m_PollServiceManager.Stop();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -75,7 +75,7 @@ namespace OpenSim.Framework.Servers.HttpServer
 | 
			
		|||
        /// <summary>
 | 
			
		||||
        /// This is a regular HTTP Request...    This may be removed in the future.   
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public event RegularHttpRequestDelegate OnRegularHttpRequest;
 | 
			
		||||
//        public event RegularHttpRequestDelegate OnRegularHttpRequest;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 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)
 | 
			
		||||
                    d(this, new UpgradeCompletedEventArgs());
 | 
			
		||||
            }
 | 
			
		||||
            catch (IOException fail)
 | 
			
		||||
            catch (IOException)
 | 
			
		||||
            {
 | 
			
		||||
                Close(string.Empty);
 | 
			
		||||
            }
 | 
			
		||||
            catch (ObjectDisposedException fail)
 | 
			
		||||
            catch (ObjectDisposedException)
 | 
			
		||||
            {
 | 
			
		||||
                Close(string.Empty);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            }           
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -414,8 +413,6 @@ namespace OpenSim.Framework.Servers.HttpServer
 | 
			
		|||
                                _socketState.Header = pheader;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                            if (_socketState.FrameComplete)
 | 
			
		||||
                            {
 | 
			
		||||
                                ProcessFrame(_socketState);
 | 
			
		||||
| 
						 | 
				
			
			@ -424,7 +421,6 @@ namespace OpenSim.Framework.Servers.HttpServer
 | 
			
		|||
                                _socketState.ExpectedBytes = 0;
 | 
			
		||||
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
| 
						 | 
				
			
			@ -457,8 +453,7 @@ namespace OpenSim.Framework.Servers.HttpServer
 | 
			
		|||
                            _socketState.ReceivedBytes.Clear();
 | 
			
		||||
                            _socketState.ExpectedBytes = 0;
 | 
			
		||||
                            // do some processing
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        }                       
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (offset > 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -477,13 +472,12 @@ namespace OpenSim.Framework.Servers.HttpServer
 | 
			
		|||
                {
 | 
			
		||||
                    // We can't read the stream anymore...  
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            catch (IOException fail)
 | 
			
		||||
            catch (IOException)
 | 
			
		||||
            {
 | 
			
		||||
                Close(string.Empty);
 | 
			
		||||
            }
 | 
			
		||||
            catch (ObjectDisposedException fail)
 | 
			
		||||
            catch (ObjectDisposedException)
 | 
			
		||||
            {
 | 
			
		||||
                Close(string.Empty);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,6 +62,8 @@ namespace OpenSim.Framework.Servers
 | 
			
		|||
 | 
			
		||||
        protected string m_pidFile = String.Empty;
 | 
			
		||||
 | 
			
		||||
        protected ServerStatsCollector m_serverStatsCollector;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Server version information.  Usually VersionInfo + information about git commit, operating system, etc.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -259,6 +261,25 @@ namespace OpenSim.Framework.Servers
 | 
			
		|||
                "force gc",
 | 
			
		||||
                "Manually invoke runtime garbage collection.  For debugging purposes",
 | 
			
		||||
                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)
 | 
			
		||||
| 
						 | 
				
			
			@ -646,7 +667,68 @@ namespace OpenSim.Framework.Servers
 | 
			
		|||
                sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
 | 
			
		||||
 | 
			
		||||
            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();
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -698,5 +780,16 @@ namespace OpenSim.Framework.Servers
 | 
			
		|||
            if (m_console != null)
 | 
			
		||||
                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,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <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>
 | 
			
		||||
    /// Miscellaneous utility functions
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class Util
 | 
			
		||||
    public static class Util
 | 
			
		||||
    {
 | 
			
		||||
        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1864,74 +1885,31 @@ namespace OpenSim.Framework
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get a thread pool report.
 | 
			
		||||
        /// Get information about the current state of the smart thread pool.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static string GetThreadPoolReport()
 | 
			
		||||
        /// <returns>
 | 
			
		||||
        /// null if this isn't the pool being used for non-scriptengine threads.
 | 
			
		||||
        /// </returns>
 | 
			
		||||
        public static STPInfo GetSmartThreadPoolInfo()
 | 
			
		||||
        {
 | 
			
		||||
            string threadPoolUsed = null;
 | 
			
		||||
            int maxThreads = 0;
 | 
			
		||||
            int minThreads = 0;
 | 
			
		||||
            int allocatedThreads = 0;
 | 
			
		||||
            int inUseThreads = 0;
 | 
			
		||||
            int waitingCallbacks = 0;
 | 
			
		||||
            int completionPortThreads = 0;
 | 
			
		||||
            if (m_ThreadPool == null)
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            StringBuilder sb = new StringBuilder();
 | 
			
		||||
            if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
 | 
			
		||||
            {
 | 
			
		||||
                // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
 | 
			
		||||
                if (m_ThreadPool != null)
 | 
			
		||||
                {
 | 
			
		||||
                    threadPoolUsed = "SmartThreadPool";
 | 
			
		||||
                    maxThreads = m_ThreadPool.MaxThreads;
 | 
			
		||||
                    minThreads = m_ThreadPool.MinThreads;
 | 
			
		||||
                    inUseThreads = m_ThreadPool.InUseThreads;
 | 
			
		||||
                    allocatedThreads = m_ThreadPool.ActiveThreads;
 | 
			
		||||
                    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;
 | 
			
		||||
            }
 | 
			
		||||
            STPInfo stpi = new STPInfo();
 | 
			
		||||
            stpi.Name = m_ThreadPool.Name;
 | 
			
		||||
            stpi.STPStartInfo = m_ThreadPool.STPStartInfo;
 | 
			
		||||
            stpi.IsIdle = m_ThreadPool.IsIdle;
 | 
			
		||||
            stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown;
 | 
			
		||||
            stpi.MaxThreads = m_ThreadPool.MaxThreads;
 | 
			
		||||
            stpi.MinThreads = m_ThreadPool.MinThreads;
 | 
			
		||||
            stpi.InUseThreads = m_ThreadPool.InUseThreads;
 | 
			
		||||
            stpi.ActiveThreads = m_ThreadPool.ActiveThreads;
 | 
			
		||||
            stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks;
 | 
			
		||||
            stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency;
 | 
			
		||||
 | 
			
		||||
            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 stpi;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//        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
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -124,6 +124,7 @@ namespace OpenSim
 | 
			
		|||
                workerThreads = workerThreadsMax;
 | 
			
		||||
                m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
			// Increase the number of IOCP threads available.
 | 
			
		||||
			// Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17)
 | 
			
		||||
			if (iocpThreads < iocpThreadsMin)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -372,7 +372,7 @@ namespace OpenSim
 | 
			
		|||
                                          "Unload a module", HandleModules);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void ShutdownSpecific()
 | 
			
		||||
        protected override void ShutdownSpecific()
 | 
			
		||||
        {
 | 
			
		||||
            if (m_shutdownCommandsFile != String.Empty)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -246,10 +246,7 @@ namespace OpenSim
 | 
			
		|||
            }
 | 
			
		||||
 | 
			
		||||
            if (m_console != null)
 | 
			
		||||
            {
 | 
			
		||||
                StatsManager.RegisterConsoleCommands(m_console);
 | 
			
		||||
                AddPluginCommands(m_console);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected virtual void AddPluginCommands(ICommandConsole console)
 | 
			
		||||
| 
						 | 
				
			
			@ -964,7 +961,7 @@ namespace OpenSim
 | 
			
		|||
        /// <summary>
 | 
			
		||||
        /// Performs any last-minute sanity checking and shuts down the region server
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override void ShutdownSpecific()
 | 
			
		||||
        protected override void ShutdownSpecific()
 | 
			
		||||
        {
 | 
			
		||||
            if (proxyUrl.Length > 0)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -984,6 +981,8 @@ namespace OpenSim
 | 
			
		|||
            {
 | 
			
		||||
                m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            base.ShutdownSpecific();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,6 +33,7 @@ using NUnit.Framework;
 | 
			
		|||
using OpenMetaverse;
 | 
			
		||||
using OpenMetaverse.Packets;
 | 
			
		||||
using OpenSim.Framework;
 | 
			
		||||
using OpenSim.Framework.Monitoring;
 | 
			
		||||
using OpenSim.Region.Framework.Scenes;
 | 
			
		||||
using OpenSim.Tests.Common;
 | 
			
		||||
using OpenSim.Tests.Common.Mock;
 | 
			
		||||
| 
						 | 
				
			
			@ -69,6 +70,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
 | 
			
		|||
        {
 | 
			
		||||
            base.SetUp();
 | 
			
		||||
            m_scene = new SceneHelpers().SetupScene();
 | 
			
		||||
            StatsManager.SimExtraStats = new SimExtraStatsCollector();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -210,8 +212,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
 | 
			
		|||
 | 
			
		||||
            ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
 | 
			
		||||
            Assert.That(spAfterAckTimeout, Is.Null);
 | 
			
		||||
 | 
			
		||||
//            TestHelpers.DisableLogging();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,8 +53,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
 | 
			
		|||
        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 | 
			
		||||
 | 
			
		||||
        private int m_levelHGTeleport = 0;
 | 
			
		||||
        private string m_ThisHomeURI;
 | 
			
		||||
 | 
			
		||||
        private GatekeeperServiceConnector m_GatekeeperConnector;
 | 
			
		||||
        private IUserAgentService m_UAS;
 | 
			
		||||
 | 
			
		||||
        protected bool m_RestrictAppearanceAbroad;
 | 
			
		||||
        protected string m_AccountName;
 | 
			
		||||
| 
						 | 
				
			
			@ -143,6 +145,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
 | 
			
		|||
                    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)
 | 
			
		||||
| 
						 | 
				
			
			@ -194,7 +204,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
 | 
			
		|||
            base.RegionLoaded(scene);
 | 
			
		||||
 | 
			
		||||
            if (m_Enabled)
 | 
			
		||||
            {
 | 
			
		||||
                m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
 | 
			
		||||
                m_UAS = scene.RequestModuleInterface<IUserAgentService>();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void RemoveRegion(Scene scene)
 | 
			
		||||
| 
						 | 
				
			
			@ -272,8 +285,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
 | 
			
		|||
                if (agentCircuit.ServiceURLs.ContainsKey("HomeURI"))
 | 
			
		||||
                {
 | 
			
		||||
                    string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString();
 | 
			
		||||
                    IUserAgentService connector = new UserAgentServiceConnector(userAgentDriver);
 | 
			
		||||
                    bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason);
 | 
			
		||||
                    IUserAgentService connector;
 | 
			
		||||
 | 
			
		||||
                    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
 | 
			
		||||
 | 
			
		||||
                    if (success)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -194,7 +194,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
 | 
			
		|||
                return false;
 | 
			
		||||
 | 
			
		||||
            // Try local first
 | 
			
		||||
            if (m_localBackend.IsLocalRegion(destination.RegionHandle))
 | 
			
		||||
            if (m_localBackend.IsLocalRegion(destination.RegionID))
 | 
			
		||||
                return m_localBackend.UpdateAgent(destination, cAgentData);
 | 
			
		||||
 | 
			
		||||
            return m_remoteConnector.UpdateAgent(destination, cAgentData);
 | 
			
		||||
| 
						 | 
				
			
			@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
 | 
			
		|||
                return false;
 | 
			
		||||
 | 
			
		||||
            // Try local first
 | 
			
		||||
            if (m_localBackend.IsLocalRegion(destination.RegionHandle))
 | 
			
		||||
            if (m_localBackend.IsLocalRegion(destination.RegionID))
 | 
			
		||||
                return m_localBackend.UpdateAgent(destination, cAgentData);
 | 
			
		||||
 | 
			
		||||
            return m_remoteConnector.UpdateAgent(destination, cAgentData);
 | 
			
		||||
| 
						 | 
				
			
			@ -224,7 +224,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
 | 
			
		|||
                return true;
 | 
			
		||||
 | 
			
		||||
            // 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 false;
 | 
			
		||||
| 
						 | 
				
			
			@ -288,7 +288,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
 | 
			
		|||
                return true;
 | 
			
		||||
 | 
			
		||||
            // else do the remote thing
 | 
			
		||||
            if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
 | 
			
		||||
            if (!m_localBackend.IsLocalRegion(destination.RegionID))
 | 
			
		||||
                return m_remoteConnector.CloseAgent(destination, id);
 | 
			
		||||
            
 | 
			
		||||
            return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -311,7 +311,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
 | 
			
		|||
            }
 | 
			
		||||
 | 
			
		||||
            // 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 false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,14 +82,14 @@ namespace OpenSim.Region.CoreModules.World.Land
 | 
			
		|||
 | 
			
		||||
            set { m_landData = value; }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        public IPrimCounts PrimCounts { get; set; }
 | 
			
		||||
 | 
			
		||||
        public UUID RegionUUID
 | 
			
		||||
        {
 | 
			
		||||
            get { return m_scene.RegionInfo.RegionID; }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        public Vector3 StartPoint
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
| 
						 | 
				
			
			@ -102,11 +102,11 @@ namespace OpenSim.Region.CoreModules.World.Land
 | 
			
		|||
                            return new Vector3(x * 4, y * 4, 0);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
                return new Vector3(-1, -1, -1);
 | 
			
		||||
            }
 | 
			
		||||
        }        
 | 
			
		||||
        
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Vector3 EndPoint
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
| 
						 | 
				
			
			@ -117,15 +117,15 @@ namespace OpenSim.Region.CoreModules.World.Land
 | 
			
		|||
                    {
 | 
			
		||||
                        if (LandBitmap[x, y])
 | 
			
		||||
                        {
 | 
			
		||||
                            return new Vector3(x * 4, y * 4, 0);
 | 
			
		||||
                        }                        
 | 
			
		||||
                            return new Vector3(x * 4 + 4, y * 4 + 4, 0);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }   
 | 
			
		||||
                
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return new Vector3(-1, -1, -1);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
        #region Constructors
 | 
			
		||||
 | 
			
		||||
        public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
    //    This state is remembered because collisions will turn on and off as we go up stairs.
 | 
			
		||||
    int m_walkingUpStairs;
 | 
			
		||||
    // The amount the step up is applying. Used to smooth stair walking.
 | 
			
		||||
    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)
 | 
			
		||||
        : base(physicsScene, pObj, actorName)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -206,17 +212,45 @@ public class BSActorAvatarMove : BSActor
 | 
			
		|||
 | 
			
		||||
            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_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.RawVelocity.Z < 0)
 | 
			
		||||
                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);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying,
 | 
			
		||||
                        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
 | 
			
		||||
        if ( m_controllingPrim.IsColliding
 | 
			
		||||
                    && !m_controllingPrim.Flying
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -209,7 +209,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
			
		|||
                    m_VhoverTimescale = Math.Max(pValue, 0.01f);
 | 
			
		||||
                    break;
 | 
			
		||||
                case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
 | 
			
		||||
                    m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f);
 | 
			
		||||
                    m_linearDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
 | 
			
		||||
                    break;
 | 
			
		||||
                case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
 | 
			
		||||
                    m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
 | 
			
		||||
| 
						 | 
				
			
			@ -707,7 +707,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
			
		|||
        private Vector3 m_knownRotationalVelocity;
 | 
			
		||||
        private Vector3 m_knownRotationalForce;
 | 
			
		||||
        private Vector3 m_knownRotationalImpulse;
 | 
			
		||||
        private Vector3 m_knownForwardVelocity;    // vehicle relative forward speed
 | 
			
		||||
 | 
			
		||||
        private const int m_knownChangedPosition           = 1 << 0;
 | 
			
		||||
        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_knownChangedTerrainHeight      = 1 << 8;
 | 
			
		||||
        private const int m_knownChangedWaterLevel         = 1 << 9;
 | 
			
		||||
        private const int m_knownChangedForwardVelocity    = 1 <<10;
 | 
			
		||||
 | 
			
		||||
        public void ForgetKnownVehicleProperties()
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -923,12 +921,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
			
		|||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if ((m_knownHas & m_knownChangedForwardVelocity) == 0)
 | 
			
		||||
                {
 | 
			
		||||
                    m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
 | 
			
		||||
                    m_knownHas |= m_knownChangedForwardVelocity;
 | 
			
		||||
                }
 | 
			
		||||
                return m_knownForwardVelocity;
 | 
			
		||||
                return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        private float VehicleForwardSpeed
 | 
			
		||||
| 
						 | 
				
			
			@ -981,6 +974,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
			
		|||
        {
 | 
			
		||||
            ComputeLinearVelocity(pTimestep);
 | 
			
		||||
 | 
			
		||||
            ComputeLinearDeflection(pTimestep);
 | 
			
		||||
 | 
			
		||||
            ComputeLinearTerrainHeightCorrection(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.
 | 
			
		||||
            Vector3 origVelW = VehicleVelocity;             // DEBUG
 | 
			
		||||
            Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation);
 | 
			
		||||
            Vector3 currentVelV = VehicleForwardVelocity;
 | 
			
		||||
            Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV);
 | 
			
		||||
 | 
			
		||||
            // Friction reduces vehicle motion
 | 
			
		||||
            Vector3 frictionFactorW = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep);
 | 
			
		||||
            linearMotorCorrectionV -= (currentVelV * frictionFactorW);
 | 
			
		||||
            // Friction reduces vehicle motion based on absolute speed. Slow vehicle down by friction.
 | 
			
		||||
            Vector3 frictionFactorV = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep);
 | 
			
		||||
            linearMotorCorrectionV -= (currentVelV * frictionFactorV);
 | 
			
		||||
 | 
			
		||||
            // Motor is vehicle coordinates. Rotate it to world coordinates
 | 
			
		||||
            Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation;
 | 
			
		||||
| 
						 | 
				
			
			@ -1046,11 +1041,38 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
			
		|||
            // Add this correction to the velocity to make it faster/slower.
 | 
			
		||||
            VehicleVelocity += linearMotorVelocityW;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            VDetailLog("{0},  MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}",
 | 
			
		||||
                        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)
 | 
			
		||||
| 
						 | 
				
			
			@ -1652,6 +1674,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
			
		|||
            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)
 | 
			
		||||
        {
 | 
			
		||||
            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 AvatarHeightHighFudge { 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 AvatarStepHeight { get; private set; }
 | 
			
		||||
	public static float AvatarStepApproachFactor { get; private set; }
 | 
			
		||||
| 
						 | 
				
			
			@ -567,6 +568,8 @@ public static class BSParam
 | 
			
		|||
            0.1f ),
 | 
			
		||||
	    new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
 | 
			
		||||
            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",
 | 
			
		||||
            0.6f ) ,
 | 
			
		||||
	    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 OpenSim.Framework;
 | 
			
		||||
using OpenSim.Framework.Console;
 | 
			
		||||
using OpenSim.Framework.Monitoring;
 | 
			
		||||
using OpenSim.Framework.Servers;
 | 
			
		||||
using log4net;
 | 
			
		||||
using log4net.Config;
 | 
			
		||||
| 
						 | 
				
			
			@ -190,16 +191,7 @@ namespace OpenSim.Server.Base
 | 
			
		|||
            }
 | 
			
		||||
 | 
			
		||||
            RegisterCommonCommands();
 | 
			
		||||
 | 
			
		||||
            // 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);
 | 
			
		||||
            RegisterCommonComponents(Config);
 | 
			
		||||
 | 
			
		||||
            // Allow derived classes to perform initialization that
 | 
			
		||||
            // needs to be done after the console has opened
 | 
			
		||||
| 
						 | 
				
			
			@ -214,6 +206,9 @@ namespace OpenSim.Server.Base
 | 
			
		|||
 | 
			
		||||
        public virtual int Run()
 | 
			
		||||
        {
 | 
			
		||||
            Watchdog.Enabled = true;
 | 
			
		||||
            MemoryWatchdog.Enabled = true;
 | 
			
		||||
 | 
			
		||||
            while (m_Running)
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
| 
						 | 
				
			
			@ -231,11 +226,12 @@ namespace OpenSim.Server.Base
 | 
			
		|||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected virtual void HandleQuit(string module, string[] args)
 | 
			
		||||
        protected override void ShutdownSpecific()
 | 
			
		||||
        {
 | 
			
		||||
            m_Running = false;
 | 
			
		||||
            m_log.Info("[CONSOLE] Quitting");
 | 
			
		||||
 | 
			
		||||
            base.ShutdownSpecific();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected virtual void ReadConfig()
 | 
			
		||||
| 
						 | 
				
			
			@ -246,4 +242,4 @@ namespace OpenSim.Server.Base
 | 
			
		|||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
 | 
			
		|||
            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);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,191 +49,87 @@ using log4net;
 | 
			
		|||
 | 
			
		||||
namespace OpenSim.Server.Handlers.Hypergrid
 | 
			
		||||
{
 | 
			
		||||
    public class HomeAgentHandler 
 | 
			
		||||
    public class HomeAgentHandler : AgentPostHandler
 | 
			
		||||
    {
 | 
			
		||||
        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 | 
			
		||||
        private IUserAgentService m_UserAgentService;
 | 
			
		||||
 | 
			
		||||
        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_LoginServerIP = loginServerIP;
 | 
			
		||||
            m_Proxy = proxy;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Hashtable Handler(Hashtable request)
 | 
			
		||||
        protected override AgentDestinationData CreateAgentDestinationData()
 | 
			
		||||
        {
 | 
			
		||||
//            m_log.Debug("[CONNECTION DEBUGGING]: HomeAgentHandler Called");
 | 
			
		||||
//
 | 
			
		||||
//            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;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Next, let's parse the verb
 | 
			
		||||
            string method = (string)request["http-method"];
 | 
			
		||||
            if (method.Equals("POST"))
 | 
			
		||||
            {
 | 
			
		||||
                DoAgentPost(request, responsedata, agentID);
 | 
			
		||||
                return responsedata;
 | 
			
		||||
            }
 | 
			
		||||
            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;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new ExtendedAgentDestinationData();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id)
 | 
			
		||||
        protected override void UnpackData(OSDMap args, AgentDestinationData d, Hashtable request)
 | 
			
		||||
        {
 | 
			
		||||
            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)
 | 
			
		||||
                gatekeeper_host = args["gatekeeper_host"].AsString();
 | 
			
		||||
            if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null)
 | 
			
		||||
                Int32.TryParse(args["gatekeeper_port"].AsString(), out gatekeeper_port);
 | 
			
		||||
            if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] !=null)
 | 
			
		||||
                gatekeeper_serveruri = args["gatekeeper_serveruri"];
 | 
			
		||||
            if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] !=null)
 | 
			
		||||
                destination_serveruri = args["destination_serveruri"];
 | 
			
		||||
 | 
			
		||||
            GridRegion gatekeeper = new GridRegion();
 | 
			
		||||
            gatekeeper.ServerURI = gatekeeper_serveruri;
 | 
			
		||||
            gatekeeper.ExternalHostName = gatekeeper_host;
 | 
			
		||||
            gatekeeper.HttpPort = (uint)gatekeeper_port;
 | 
			
		||||
            gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 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("client_ip") && args["client_ip"] != null)
 | 
			
		||||
            {
 | 
			
		||||
                string ip_str = args["client_ip"].ToString();
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    string callerIP = GetCallerIP(request);
 | 
			
		||||
                    // Verify if this caller has authority to send the client IP
 | 
			
		||||
                    if (callerIP == m_LoginServerIP)
 | 
			
		||||
                        client_ipaddress = new IPEndPoint(IPAddress.Parse(ip_str), 0);
 | 
			
		||||
                    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();
 | 
			
		||||
            base.UnpackData(args, d, request);
 | 
			
		||||
            ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                aCircuit.UnpackAgentCircuitData(args);
 | 
			
		||||
                if (args.ContainsKey("gatekeeper_host") && args["gatekeeper_host"] != null)
 | 
			
		||||
                    data.host = args["gatekeeper_host"].AsString();
 | 
			
		||||
                if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null)
 | 
			
		||||
                    Int32.TryParse(args["gatekeeper_port"].AsString(), out data.port);
 | 
			
		||||
                if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] != null)
 | 
			
		||||
                    data.gatekeeperServerURI = args["gatekeeper_serveruri"];
 | 
			
		||||
                if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] != null)
 | 
			
		||||
                    data.destinationServerURI = args["destination_serveruri"];
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            catch (InvalidCastException e)
 | 
			
		||||
            {
 | 
			
		||||
                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;
 | 
			
		||||
                m_log.ErrorFormat("[HOME AGENT HANDLER]: Bad cast in UnpackData");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            OSDMap resp = new OSDMap(2);
 | 
			
		||||
            string reason = String.Empty;
 | 
			
		||||
            string callerIP = GetCallerIP(request);
 | 
			
		||||
            // Verify if this call came from the login server
 | 
			
		||||
            if (callerIP == m_LoginServerIP)
 | 
			
		||||
                data.fromLogin = true;
 | 
			
		||||
 | 
			
		||||
            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)
 | 
			
		||||
        protected override GridRegion ExtractGatekeeper(AgentDestinationData d)
 | 
			
		||||
        {
 | 
			
		||||
            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)
 | 
			
		||||
            if (d is ExtendedAgentDestinationData)
 | 
			
		||||
            {
 | 
			
		||||
                m_log.WarnFormat("[AGENT HANDLER]: No XFF header");
 | 
			
		||||
                return Util.GetCallerIP(request);
 | 
			
		||||
                ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d;
 | 
			
		||||
                GridRegion gatekeeper = new GridRegion();
 | 
			
		||||
                gatekeeper.ServerURI = data.gatekeeperServerURI;
 | 
			
		||||
                gatekeeper.ExternalHostName = data.host;
 | 
			
		||||
                gatekeeper.HttpPort = (uint)data.port;
 | 
			
		||||
                gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
 | 
			
		||||
 | 
			
		||||
                return gatekeeper;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
                m_log.WarnFormat("[HOME AGENT HANDLER]: Wrong data type");
 | 
			
		||||
 | 
			
		||||
            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);
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        protected override bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
 | 
			
		||||
        {
 | 
			
		||||
            return m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, fromLogin, out reason);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class ExtendedAgentDestinationData : AgentDestinationData
 | 
			
		||||
    {
 | 
			
		||||
        public string host;
 | 
			
		||||
        public int port;
 | 
			
		||||
        public string gatekeeperServerURI;
 | 
			
		||||
        public string destinationServerURI;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -108,7 +108,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
 | 
			
		|||
            server.AddXmlRPCHandler("get_uui", GetUUI, 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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -351,31 +351,16 @@ namespace OpenSim.Server.Handlers.Simulation
 | 
			
		|||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // retrieve the input arguments
 | 
			
		||||
            int x = 0, y = 0;
 | 
			
		||||
            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();
 | 
			
		||||
            AgentDestinationData data = CreateAgentDestinationData();
 | 
			
		||||
            UnpackData(args, data, request);
 | 
			
		||||
 | 
			
		||||
            GridRegion destination = new GridRegion();
 | 
			
		||||
            destination.RegionID = uuid;
 | 
			
		||||
            destination.RegionLocX = x;
 | 
			
		||||
            destination.RegionLocY = y;
 | 
			
		||||
            destination.RegionName = regionname;
 | 
			
		||||
            destination.RegionID = data.uuid;
 | 
			
		||||
            destination.RegionLocX = data.x;
 | 
			
		||||
            destination.RegionLocY = data.y;
 | 
			
		||||
            destination.RegionName = data.name;
 | 
			
		||||
 | 
			
		||||
            GridRegion gatekeeper = ExtractGatekeeper(data);
 | 
			
		||||
 | 
			
		||||
            AgentCircuitData aCircuit = new AgentCircuitData();
 | 
			
		||||
            try
 | 
			
		||||
| 
						 | 
				
			
			@ -396,7 +381,7 @@ namespace OpenSim.Server.Handlers.Simulation
 | 
			
		|||
            // This is the meaning of POST agent
 | 
			
		||||
            //m_regionClient.AdjustUserInformation(aCircuit);
 | 
			
		||||
            //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["success"] = OSD.FromBoolean(result);
 | 
			
		||||
| 
						 | 
				
			
			@ -408,7 +393,36 @@ namespace OpenSim.Server.Handlers.Simulation
 | 
			
		|||
            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)
 | 
			
		||||
                return Util.GetCallerIP(request);
 | 
			
		||||
| 
						 | 
				
			
			@ -441,7 +455,7 @@ namespace OpenSim.Server.Handlers.Simulation
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        // 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;
 | 
			
		||||
            
 | 
			
		||||
| 
						 | 
				
			
			@ -593,7 +607,6 @@ namespace OpenSim.Server.Handlers.Simulation
 | 
			
		|||
                //agent.Dump();
 | 
			
		||||
                // This is one of the meanings of PUT agent
 | 
			
		||||
                result = UpdateAgent(destination, agent);
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            else if ("AgentPosition".Equals(messageType))
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -624,4 +637,14 @@ namespace OpenSim.Server.Handlers.Simulation
 | 
			
		|||
            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;
 | 
			
		||||
 | 
			
		||||
        public GatekeeperServiceConnector() : base()
 | 
			
		||||
        public GatekeeperServiceConnector()
 | 
			
		||||
            : base()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -123,11 +124,13 @@ namespace OpenSim.Services.Connectors.Hypergrid
 | 
			
		|||
                        realHandle = Convert.ToUInt64((string)hash["handle"]);
 | 
			
		||||
                        //m_log.Debug(">> HERE, realHandle: " + realHandle);
 | 
			
		||||
                    }
 | 
			
		||||
                    if (hash["region_image"] != null) {
 | 
			
		||||
                    if (hash["region_image"] != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        imageURL = (string)hash["region_image"];
 | 
			
		||||
                        //m_log.Debug(">> HERE, imageURL: " + imageURL);
 | 
			
		||||
                    }
 | 
			
		||||
                    if (hash["external_name"] != null) {
 | 
			
		||||
                    if (hash["external_name"] != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        externalName = (string)hash["external_name"];
 | 
			
		||||
                        //m_log.Debug(">> HERE, externalName: " + externalName);
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -179,7 +182,7 @@ namespace OpenSim.Services.Connectors.Hypergrid
 | 
			
		|||
                    //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width);
 | 
			
		||||
                    imageData = OpenJPEG.EncodeFromImage(bitmap, true);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
                AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString());
 | 
			
		||||
 | 
			
		||||
                // !!! for now
 | 
			
		||||
| 
						 | 
				
			
			@ -257,7 +260,8 @@ namespace OpenSim.Services.Connectors.Hypergrid
 | 
			
		|||
                        region.RegionName = (string)hash["region_name"];
 | 
			
		||||
                        //m_log.Debug(">> HERE, region_name: " + region.RegionName);
 | 
			
		||||
                    }
 | 
			
		||||
                    if (hash["hostname"] != null) {
 | 
			
		||||
                    if (hash["hostname"] != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        region.ExternalHostName = (string)hash["hostname"];
 | 
			
		||||
                        //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName);
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -275,10 +279,10 @@ namespace OpenSim.Services.Connectors.Hypergrid
 | 
			
		|||
                        region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p);
 | 
			
		||||
                        //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint);
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
 | 
			
		||||
                    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);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -295,55 +299,5 @@ namespace OpenSim.Services.Connectors.Hypergrid
 | 
			
		|||
 | 
			
		||||
            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
 | 
			
		||||
{
 | 
			
		||||
    public class UserAgentServiceConnector : IUserAgentService
 | 
			
		||||
    public class UserAgentServiceConnector : SimulationServiceConnector, IUserAgentService
 | 
			
		||||
    {
 | 
			
		||||
        private static readonly ILog m_log =
 | 
			
		||||
            LogManager.GetLogger(
 | 
			
		||||
            MethodBase.GetCurrentMethod().DeclaringType);
 | 
			
		||||
 | 
			
		||||
        string m_ServerURL;
 | 
			
		||||
        private string m_ServerURL;
 | 
			
		||||
        private GridRegion m_Gatekeeper;
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override string AgentPath()
 | 
			
		||||
        {
 | 
			
		||||
            return "homeagent/";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // The Login service calls this interface with a non-null [client] ipaddress 
 | 
			
		||||
        public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress, out string reason)
 | 
			
		||||
        // The Login service calls this interface with fromLogin=true 
 | 
			
		||||
        // 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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -115,119 +122,34 @@ namespace OpenSim.Services.Connectors.Hypergrid
 | 
			
		|||
                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);
 | 
			
		||||
            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;
 | 
			
		||||
            Console.WriteLine("   >>> LoginAgentToGrid <<< " + home.ServerURI);
 | 
			
		||||
 | 
			
		||||
            uint flags = fromLogin ? (uint)TeleportFlags.ViaLogin : (uint)TeleportFlags.ViaHome;
 | 
			
		||||
            return CreateAgent(home, aCircuit, flags, out reason);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // The simulators call this interface
 | 
			
		||||
        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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,11 +79,27 @@ namespace OpenSim.Services.Connectors.Simulation
 | 
			
		|||
            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)
 | 
			
		||||
        {
 | 
			
		||||
            // 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;
 | 
			
		||||
            myipaddress = String.Empty;
 | 
			
		||||
 | 
			
		||||
            if (destination == null)
 | 
			
		||||
            {
 | 
			
		||||
                reason = "Destination not found";
 | 
			
		||||
| 
						 | 
				
			
			@ -96,12 +112,7 @@ namespace OpenSim.Services.Connectors.Simulation
 | 
			
		|||
            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());
 | 
			
		||||
                PackData(args, aCircuit, destination, flags);
 | 
			
		||||
 | 
			
		||||
                OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000);
 | 
			
		||||
                bool success = result["success"].AsBoolean();
 | 
			
		||||
| 
						 | 
				
			
			@ -111,6 +122,7 @@ namespace OpenSim.Services.Connectors.Simulation
 | 
			
		|||
 | 
			
		||||
                    reason = data["reason"].AsString();
 | 
			
		||||
                    success = data["success"].AsBoolean();
 | 
			
		||||
                    myipaddress = data["your_ip"].AsString();
 | 
			
		||||
                    return success;
 | 
			
		||||
                }
 | 
			
		||||
              
 | 
			
		||||
| 
						 | 
				
			
			@ -125,6 +137,7 @@ namespace OpenSim.Services.Connectors.Simulation
 | 
			
		|||
 | 
			
		||||
                        reason = data["reason"].AsString();
 | 
			
		||||
                        success = data["success"].AsBoolean();
 | 
			
		||||
                        myipaddress = data["your_ip"].AsString();
 | 
			
		||||
                        m_log.WarnFormat(
 | 
			
		||||
                            "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName);
 | 
			
		||||
                        return success;
 | 
			
		||||
| 
						 | 
				
			
			@ -229,7 +242,7 @@ namespace OpenSim.Services.Connectors.Simulation
 | 
			
		|||
        /// </summary>
 | 
			
		||||
        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
 | 
			
		||||
            string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -210,10 +210,10 @@ namespace OpenSim.Services.HypergridService
 | 
			
		|||
            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}", 
 | 
			
		||||
                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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -265,7 +265,7 @@ namespace OpenSim.Services.HypergridService
 | 
			
		|||
            bool success = false;
 | 
			
		||||
            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)
 | 
			
		||||
                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);
 | 
			
		||||
            // else set the IP addresses associated with this client
 | 
			
		||||
            if (clientIP != null)
 | 
			
		||||
                m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString();
 | 
			
		||||
            if (fromLogin)
 | 
			
		||||
                m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = agentCircuit.IPAddress;
 | 
			
		||||
            m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP;
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -306,7 +306,7 @@ namespace OpenSim.Services.HypergridService
 | 
			
		|||
        public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason)
 | 
			
		||||
        {
 | 
			
		||||
            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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,10 +48,7 @@ namespace OpenSim.Services.Interfaces
 | 
			
		|||
    /// </summary>
 | 
			
		||||
    public interface IUserAgentService
 | 
			
		||||
    {
 | 
			
		||||
        // called by login service only
 | 
			
		||||
        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);
 | 
			
		||||
        bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason);
 | 
			
		||||
        void LogoutAgent(UUID userID, UUID sessionID);
 | 
			
		||||
        GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt);
 | 
			
		||||
        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)
 | 
			
		||||
        {
 | 
			
		||||
            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 false;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -157,6 +157,7 @@
 | 
			
		|||
      <Reference name="System"/>
 | 
			
		||||
      <Reference name="System.Core"/>
 | 
			
		||||
      <Reference name="log4net" path="../../../bin/"/>
 | 
			
		||||
      <Reference name="Nini" path="../../../bin/"/>
 | 
			
		||||
      <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
 | 
			
		||||
      <Reference name="OpenMetaverse" path="../../../bin/"/>
 | 
			
		||||
      <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
 | 
			
		||||
| 
						 | 
				
			
			@ -863,6 +864,7 @@
 | 
			
		|||
      <Reference name="Mono.Addins.Setup" path="../../../bin/"/>
 | 
			
		||||
      <Reference name="OpenSim.Framework"/>
 | 
			
		||||
      <Reference name="OpenSim.Framework.Console"/>
 | 
			
		||||
      <Reference name="OpenSim.Framework.Monitoring"/>
 | 
			
		||||
      <Reference name="OpenSim.Framework.Servers"/>
 | 
			
		||||
      <Reference name="OpenSim.Framework.Servers.HttpServer"/>
 | 
			
		||||
      <Reference name="Nini" path="../../../bin/"/>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue