Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
commit
c7fa637f0d
|
@ -1,34 +1,36 @@
|
||||||
The following people have contributed to OpenSim (Thank you
|
The following people have contributed to OpenSim (Thank you
|
||||||
for your effort!)
|
for your effort!)
|
||||||
|
|
||||||
Add your name in here if you have committed to OpenSim
|
|
||||||
|
|
||||||
= Current OpenSim Developers (in very rough order of appearance) =
|
= Current OpenSim Developers (in very rough order of appearance) =
|
||||||
These folks represent the current core team for OpenSim, and are the
|
These folks represent the current core team for OpenSim, and are the
|
||||||
people that make the day to day of OpenSim happen.
|
people that make the day to day of OpenSim happen.
|
||||||
|
|
||||||
|
* justincc
|
||||||
|
* chi11ken (Genkii)
|
||||||
|
* dahlia
|
||||||
|
* Melanie Thielker
|
||||||
|
* Diva (Crista Lopes, University of California, Irvine)
|
||||||
|
* Dan Lake (Intel)
|
||||||
|
* Marck
|
||||||
|
* Mic Bowman (Intel)
|
||||||
|
* BlueWall (James Hughes)
|
||||||
|
|
||||||
|
= Core Developers Following the White Rabbit =
|
||||||
|
Core developers who have temporarily (we hope) gone chasing the white rabbit.
|
||||||
|
They are in all similar to the active core developers, except that they haven't
|
||||||
|
been that active lately, so their voting rights are awaiting their come back.
|
||||||
|
|
||||||
* MW (Tribal Media AB)
|
* MW (Tribal Media AB)
|
||||||
* Adam Frisby (DeepThink Pty Ltd)
|
* Adam Frisby (DeepThink Pty Ltd)
|
||||||
* MingChen (DeepThink Pty Ltd)
|
|
||||||
* lbsa71 (Tribal Media AB)
|
* lbsa71 (Tribal Media AB)
|
||||||
* Sean Dague / sdague (IBM)
|
|
||||||
* Tedd
|
|
||||||
* justincc
|
|
||||||
* Teravus (w3z)
|
* Teravus (w3z)
|
||||||
* Johan Berntsson (3Di)
|
|
||||||
* Ckrinke (Charles Krinke)
|
* Ckrinke (Charles Krinke)
|
||||||
* chi11ken (Genkii)
|
|
||||||
* adjohn (Genkii)
|
|
||||||
* Dr Scofield aka Dirk Husemann (IBM Research - Zurich)
|
* Dr Scofield aka Dirk Husemann (IBM Research - Zurich)
|
||||||
* dahlia
|
|
||||||
* mikem (3Di)
|
* mikem (3Di)
|
||||||
* Melanie Thielker
|
|
||||||
* Homer_Horwitz
|
* Homer_Horwitz
|
||||||
* idb (Ian Brown)
|
|
||||||
* Diva (Crista Lopes, University of California, Irvine)
|
|
||||||
* nlin (3Di)
|
* nlin (3Di)
|
||||||
* Arthur Rodrigo S Valadares (IBM)
|
* Arthur Rodrigo S Valadares (IBM)
|
||||||
* BlueWall (James Hughes)
|
* John Hurliman
|
||||||
|
|
||||||
= Past Open Sim Developers =
|
= Past Open Sim Developers =
|
||||||
These folks are alumns of the OpenSim core group, but are now
|
These folks are alumns of the OpenSim core group, but are now
|
||||||
|
@ -44,6 +46,12 @@ where we are today.
|
||||||
* Dalien
|
* Dalien
|
||||||
* Darok
|
* Darok
|
||||||
* Alondria
|
* Alondria
|
||||||
|
* Sean Dague / sdague (IBM)
|
||||||
|
* Tedd
|
||||||
|
* MingChen (DeepThink Pty Ltd)
|
||||||
|
* adjohn (Genkii)
|
||||||
|
* idb (Ian Brown)
|
||||||
|
* Johan Berntsson (3Di)
|
||||||
|
|
||||||
|
|
||||||
= Additional OpenSim Contributors =
|
= Additional OpenSim Contributors =
|
||||||
|
@ -102,6 +110,7 @@ what it is today.
|
||||||
* Misterblue (Intel)
|
* Misterblue (Intel)
|
||||||
* Mircea Kitsune
|
* Mircea Kitsune
|
||||||
* mpallari
|
* mpallari
|
||||||
|
* MrMonkE
|
||||||
* nornalbion
|
* nornalbion
|
||||||
* Omar Vera Ustariz (IBM)
|
* Omar Vera Ustariz (IBM)
|
||||||
* openlifegrid.com
|
* openlifegrid.com
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,131 +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.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using System.Timers;
|
|
||||||
using log4net;
|
|
||||||
using MXP;
|
|
||||||
using Nini.Config;
|
|
||||||
using OpenMetaverse;
|
|
||||||
using OpenSim.Client.MXP.PacketHandler;
|
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
|
||||||
using OpenSim.Region.Framework.Scenes;
|
|
||||||
|
|
||||||
namespace OpenSim.Client.MXP
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MXP Client Module which adds MXP support to client / region communication.
|
|
||||||
*/
|
|
||||||
public class MXPModule : IRegionModule
|
|
||||||
{
|
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
|
||||||
|
|
||||||
private MXPPacketServer m_server;
|
|
||||||
|
|
||||||
private IConfigSource m_config;
|
|
||||||
private int m_port = 1253;
|
|
||||||
private Timer m_ticker;
|
|
||||||
|
|
||||||
private readonly Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
|
|
||||||
private bool m_shutdown;
|
|
||||||
|
|
||||||
public void Initialise(Scene scene, IConfigSource source)
|
|
||||||
{
|
|
||||||
if (!m_scenes.ContainsKey(scene.RegionInfo.RegionID))
|
|
||||||
m_scenes.Add(scene.RegionInfo.RegionID, scene);
|
|
||||||
|
|
||||||
m_config = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PostInitialise()
|
|
||||||
{
|
|
||||||
if (m_config.Configs["MXP"] != null)
|
|
||||||
{
|
|
||||||
IConfig con = m_config.Configs["MXP"];
|
|
||||||
|
|
||||||
if (!con.GetBoolean("Enabled", false))
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_port = con.GetInt("Port", m_port);
|
|
||||||
|
|
||||||
m_server = new MXPPacketServer(m_port, m_scenes,m_config.Configs["StandAlone"].GetBoolean("accounts_authenticate",true));
|
|
||||||
|
|
||||||
m_ticker = new Timer(100);
|
|
||||||
m_ticker.AutoReset = false;
|
|
||||||
m_ticker.Elapsed += ticker_Elapsed;
|
|
||||||
|
|
||||||
lock (m_ticker)
|
|
||||||
m_ticker.Start();
|
|
||||||
|
|
||||||
m_log.Info("[MXP ClientStack] MXP Enabled and Listening");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ticker_Elapsed(object sender, ElapsedEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
m_server.Process();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
m_log.Error("[MXP ClientStack]: Unhandled exception in process loop: " + ex.ToString() + " :" + ex.StackTrace.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_shutdown)
|
|
||||||
{
|
|
||||||
lock (m_ticker)
|
|
||||||
m_ticker.Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Close()
|
|
||||||
{
|
|
||||||
m_shutdown = true;
|
|
||||||
if (m_ticker != null)
|
|
||||||
{
|
|
||||||
lock (m_ticker)
|
|
||||||
m_ticker.Stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get { return "MXP ClientStack Module"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSharedModule
|
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +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.Text;
|
|
||||||
using OpenMetaverse;
|
|
||||||
|
|
||||||
namespace OpenSim.Client.MXP
|
|
||||||
{
|
|
||||||
public static class MXPUtil
|
|
||||||
{
|
|
||||||
public static string GenerateMXPURL(string server, int port, UUID bubbleID, Vector3 location)
|
|
||||||
{
|
|
||||||
return string.Format("mxp://{0}:{1}/{2}/{3}", server, port, bubbleID.Guid, location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,561 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This file borrows heavily from MXPServer.cs - the reference MXPServer
|
|
||||||
* See http://www.bubblecloud.org for a copy of the original file and
|
|
||||||
* implementation details. */
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading;
|
|
||||||
using log4net;
|
|
||||||
using MXP;
|
|
||||||
using MXP.Messages;
|
|
||||||
using OpenMetaverse;
|
|
||||||
using OpenSim.Client.MXP.ClientStack;
|
|
||||||
using OpenSim.Framework;
|
|
||||||
using OpenSim.Region.Framework.Scenes;
|
|
||||||
using OpenSim.Framework.Communications;
|
|
||||||
using OpenSim.Services.Interfaces;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
|
|
||||||
namespace OpenSim.Client.MXP.PacketHandler
|
|
||||||
{
|
|
||||||
public class MXPPacketServer
|
|
||||||
{
|
|
||||||
internal static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
|
||||||
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
private readonly List<MXPClientView> m_clients = new List<MXPClientView>();
|
|
||||||
private readonly Dictionary<UUID, Scene> m_scenes;
|
|
||||||
private readonly Transmitter m_transmitter;
|
|
||||||
|
|
||||||
// private readonly Thread m_clientThread;
|
|
||||||
|
|
||||||
private readonly IList<Session> m_sessions = new List<Session>();
|
|
||||||
private readonly IList<Session> m_sessionsToClient = new List<Session>();
|
|
||||||
private readonly IList<MXPClientView> m_sessionsToRemove = new List<MXPClientView>();
|
|
||||||
|
|
||||||
private readonly int m_port;
|
|
||||||
// private readonly bool m_accountsAuthenticate;
|
|
||||||
|
|
||||||
private readonly String m_programName;
|
|
||||||
private readonly byte m_programMajorVersion;
|
|
||||||
private readonly byte m_programMinorVersion;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
|
|
||||||
public MXPPacketServer(int port, Dictionary<UUID, Scene> scenes, bool accountsAuthenticate)
|
|
||||||
{
|
|
||||||
m_port = port;
|
|
||||||
// m_accountsAuthenticate = accountsAuthenticate;
|
|
||||||
|
|
||||||
m_scenes = scenes;
|
|
||||||
|
|
||||||
m_programMinorVersion = 63;
|
|
||||||
m_programMajorVersion = 0;
|
|
||||||
m_programName = "OpenSimulator";
|
|
||||||
|
|
||||||
m_transmitter = new Transmitter(port);
|
|
||||||
|
|
||||||
StartListener();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void StartListener()
|
|
||||||
{
|
|
||||||
m_log.Info("[MXP ClientStack] Transmitter starting on UDP server port: " + m_port);
|
|
||||||
m_transmitter.Startup();
|
|
||||||
m_log.Info("[MXP ClientStack] Transmitter started. MXP version: "+MxpConstants.ProtocolMajorVersion+"."+MxpConstants.ProtocolMinorVersion+" Source Revision: "+MxpConstants.ProtocolSourceRevision);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of sessions pending. (Process() accepts pending sessions).
|
|
||||||
/// </summary>
|
|
||||||
public int PendingSessionCount
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_transmitter.PendingSessionCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Number of connected sessions.
|
|
||||||
/// </summary>
|
|
||||||
public int SessionCount
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_sessions.Count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Property reflecting whether client transmitter threads are alive.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsTransmitterAlive
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_transmitter != null && m_transmitter.IsAlive;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Number of packets sent.
|
|
||||||
/// </summary>
|
|
||||||
public ulong PacketsSent
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_transmitter != null ? m_transmitter.PacketsSent : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Number of packets received.
|
|
||||||
/// </summary>
|
|
||||||
public ulong PacketsReceived
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_transmitter != null ? m_transmitter.PacketsReceived : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Bytes client has received so far.
|
|
||||||
/// </summary>
|
|
||||||
public ulong BytesReceived
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_transmitter != null ? m_transmitter.BytesReceived : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Bytes client has sent so far.
|
|
||||||
/// </summary>
|
|
||||||
public ulong BytesSent
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_transmitter != null ? m_transmitter.BytesSent : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Number of bytes received (bytes per second) during past second.
|
|
||||||
/// </summary>
|
|
||||||
public double ReceiveRate
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_transmitter != null ? m_transmitter.ReceiveRate : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Number of bytes sent (bytes per second) during past second.
|
|
||||||
/// </summary>
|
|
||||||
public double SendRate
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_transmitter != null ? m_transmitter.SendRate : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Session Management
|
|
||||||
|
|
||||||
public void Disconnect(Session session)
|
|
||||||
{
|
|
||||||
if (session.IsConnected)
|
|
||||||
{
|
|
||||||
Message message = MessageFactory.Current.ReserveMessage(typeof(LeaveRequestMessage));
|
|
||||||
session.Send(message);
|
|
||||||
MessageFactory.Current.ReleaseMessage(message);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("Not connected.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Processing
|
|
||||||
|
|
||||||
public void Process()
|
|
||||||
{
|
|
||||||
ProcessMessages();
|
|
||||||
Clean();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clean()
|
|
||||||
{
|
|
||||||
foreach (MXPClientView clientView in m_clients)
|
|
||||||
{
|
|
||||||
if (clientView.Session.SessionState == SessionState.Disconnected)
|
|
||||||
{
|
|
||||||
m_sessionsToRemove.Add(clientView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (MXPClientView clientView in m_sessionsToRemove)
|
|
||||||
{
|
|
||||||
clientView.Scene.RemoveClient(clientView.AgentId);
|
|
||||||
clientView.OnClean();
|
|
||||||
m_clients.Remove(clientView);
|
|
||||||
m_sessions.Remove(clientView.Session);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_sessionsToRemove.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ProcessMessages()
|
|
||||||
{
|
|
||||||
if (m_transmitter.PendingSessionCount > 0)
|
|
||||||
{
|
|
||||||
Session tmp = m_transmitter.AcceptPendingSession();
|
|
||||||
m_sessions.Add(tmp);
|
|
||||||
m_sessionsToClient.Add(tmp);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Session> tmpRemove = new List<Session>();
|
|
||||||
|
|
||||||
foreach (Session session in m_sessionsToClient)
|
|
||||||
{
|
|
||||||
while (session.AvailableMessages > 0)
|
|
||||||
{
|
|
||||||
Message message = session.Receive();
|
|
||||||
|
|
||||||
if (message.GetType() == typeof (JoinRequestMessage))
|
|
||||||
{
|
|
||||||
|
|
||||||
JoinRequestMessage joinRequestMessage = (JoinRequestMessage) message;
|
|
||||||
|
|
||||||
m_log.Info("[MXP ClientStack]: Session join request: " + session.SessionId + " (" +
|
|
||||||
(session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" +
|
|
||||||
session.RemoteEndPoint.Port + ")");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
if (joinRequestMessage.BubbleId == Guid.Empty)
|
|
||||||
{
|
|
||||||
foreach (Scene scene in m_scenes.Values)
|
|
||||||
{
|
|
||||||
if (scene.RegionInfo.RegionName == joinRequestMessage.BubbleName)
|
|
||||||
{
|
|
||||||
m_log.Info("[MXP ClientStack]: Resolved region by name: " + joinRequestMessage.BubbleName + " (" + scene.RegionInfo.RegionID + ")");
|
|
||||||
joinRequestMessage.BubbleId = scene.RegionInfo.RegionID.Guid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (joinRequestMessage.BubbleId == Guid.Empty)
|
|
||||||
{
|
|
||||||
m_log.Warn("[MXP ClientStack]: Failed to resolve region by name: " + joinRequestMessage.BubbleName);
|
|
||||||
}
|
|
||||||
|
|
||||||
UUID sceneId = new UUID(joinRequestMessage.BubbleId);
|
|
||||||
|
|
||||||
bool regionExists = true;
|
|
||||||
if (!m_scenes.ContainsKey(sceneId))
|
|
||||||
{
|
|
||||||
m_log.Info("[MXP ClientStack]: No such region: " + sceneId);
|
|
||||||
regionExists = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UUID userId = UUID.Zero;
|
|
||||||
UserAccount account = null;
|
|
||||||
bool authorized = regionExists ? AuthoriseUser(joinRequestMessage.ParticipantName,
|
|
||||||
joinRequestMessage.ParticipantPassphrase,
|
|
||||||
new UUID(joinRequestMessage.BubbleId), out account)
|
|
||||||
: false;
|
|
||||||
|
|
||||||
if (authorized)
|
|
||||||
{
|
|
||||||
Scene scene = m_scenes[sceneId];
|
|
||||||
UUID mxpSessionID = UUID.Random();
|
|
||||||
|
|
||||||
string reason;
|
|
||||||
|
|
||||||
m_log.Debug("[MXP ClientStack]: Session join request success: " + session.SessionId + " (" +
|
|
||||||
(session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" +
|
|
||||||
session.RemoteEndPoint.Port + ")");
|
|
||||||
|
|
||||||
m_log.Debug("[MXP ClientStack]: Attaching UserAgent to UserProfile...");
|
|
||||||
UUID secureSession = UUID.Zero;
|
|
||||||
AttachUserAgentToUserProfile(account, session, mxpSessionID, sceneId, out secureSession);
|
|
||||||
m_log.Debug("[MXP ClientStack]: Attached UserAgent to UserProfile.");
|
|
||||||
m_log.Debug("[MXP ClientStack]: Preparing Scene to Connection...");
|
|
||||||
if (!PrepareSceneForConnection(mxpSessionID, secureSession, sceneId, account, out reason))
|
|
||||||
{
|
|
||||||
m_log.DebugFormat("[MXP ClientStack]: Scene refused connection: {0}", reason);
|
|
||||||
DeclineConnection(session, joinRequestMessage);
|
|
||||||
tmpRemove.Add(session);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
m_log.Debug("[MXP ClientStack]: Prepared Scene to Connection.");
|
|
||||||
m_log.Debug("[MXP ClientStack]: Accepting connection...");
|
|
||||||
AcceptConnection(session, joinRequestMessage, mxpSessionID, userId);
|
|
||||||
m_log.Info("[MXP ClientStack]: Accepted connection.");
|
|
||||||
|
|
||||||
m_log.Debug("[MXP ClientStack]: Creating ClientView....");
|
|
||||||
MXPClientView client = new MXPClientView(session, mxpSessionID, userId, scene, account.FirstName, account.LastName);
|
|
||||||
m_clients.Add(client);
|
|
||||||
m_log.Debug("[MXP ClientStack]: Created ClientView.");
|
|
||||||
|
|
||||||
client.MXPSendSynchronizationBegin(m_scenes[new UUID(joinRequestMessage.BubbleId)].SceneContents.GetTotalObjectsCount());
|
|
||||||
|
|
||||||
m_log.Debug("[MXP ClientStack]: Starting ClientView...");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
client.Start();
|
|
||||||
m_log.Debug("[MXP ClientStack]: Started ClientView.");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
m_log.Error(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_log.Debug("[MXP ClientStack]: Connected");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_log.Info("[MXP ClientStack]: Session join request failure: " + session.SessionId + " (" +
|
|
||||||
(session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" +
|
|
||||||
session.RemoteEndPoint.Port + ")");
|
|
||||||
|
|
||||||
DeclineConnection(session, joinRequestMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
m_log.Error("[MXP ClientStack]: Session join request failure: " + session.SessionId + " (" +
|
|
||||||
(session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" +
|
|
||||||
session.RemoteEndPoint.Port + "): "+e.ToString()+" :"+e.StackTrace.ToString());
|
|
||||||
}
|
|
||||||
tmpRemove.Add(session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Session session in tmpRemove)
|
|
||||||
{
|
|
||||||
m_sessionsToClient.Remove(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (MXPClientView clientView in m_clients)
|
|
||||||
{
|
|
||||||
int messagesProcessedCount = 0;
|
|
||||||
Session session = clientView.Session;
|
|
||||||
|
|
||||||
while (session.AvailableMessages > 0)
|
|
||||||
{
|
|
||||||
Message message = session.Receive();
|
|
||||||
|
|
||||||
if (message.GetType() == typeof(LeaveRequestMessage))
|
|
||||||
{
|
|
||||||
LeaveResponseMessage leaveResponseMessage = (LeaveResponseMessage)MessageFactory.Current.ReserveMessage(
|
|
||||||
typeof(LeaveResponseMessage));
|
|
||||||
|
|
||||||
m_log.Debug("[MXP ClientStack]: Session leave request: " + session.SessionId + " (" + (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + session.RemoteEndPoint.Port + ")");
|
|
||||||
|
|
||||||
leaveResponseMessage.RequestMessageId = message.MessageId;
|
|
||||||
leaveResponseMessage.FailureCode = 0;
|
|
||||||
session.Send(leaveResponseMessage);
|
|
||||||
|
|
||||||
if (session.SessionState != SessionState.Disconnected)
|
|
||||||
{
|
|
||||||
session.SetStateDisconnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_log.Debug("[MXP ClientStack]: Removing Client from Scene");
|
|
||||||
//clientView.Scene.RemoveClient(clientView.AgentId);
|
|
||||||
}
|
|
||||||
if (message.GetType() == typeof(LeaveResponseMessage))
|
|
||||||
{
|
|
||||||
LeaveResponseMessage leaveResponseMessage = (LeaveResponseMessage)message;
|
|
||||||
|
|
||||||
m_log.Debug("[MXP ClientStack]: Session leave response: " + session.SessionId + " (" + (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + session.RemoteEndPoint.Port + ")");
|
|
||||||
|
|
||||||
if (leaveResponseMessage.FailureCode == 0)
|
|
||||||
{
|
|
||||||
session.SetStateDisconnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_log.Debug("[MXP ClientStack]: Removing Client from Scene");
|
|
||||||
//clientView.Scene.RemoveClient(clientView.AgentId);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clientView.MXPPRocessMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageFactory.Current.ReleaseMessage(message);
|
|
||||||
messagesProcessedCount++;
|
|
||||||
if (messagesProcessedCount > 1000)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AcceptConnection(Session session, JoinRequestMessage joinRequestMessage, UUID mxpSessionID, UUID userId)
|
|
||||||
{
|
|
||||||
JoinResponseMessage joinResponseMessage = (JoinResponseMessage)MessageFactory.Current.ReserveMessage(
|
|
||||||
typeof(JoinResponseMessage));
|
|
||||||
|
|
||||||
joinResponseMessage.RequestMessageId = joinRequestMessage.MessageId;
|
|
||||||
joinResponseMessage.FailureCode = MxpResponseCodes.SUCCESS;
|
|
||||||
|
|
||||||
joinResponseMessage.BubbleId = joinRequestMessage.BubbleId;
|
|
||||||
joinResponseMessage.ParticipantId = userId.Guid;
|
|
||||||
joinResponseMessage.AvatarId = userId.Guid;
|
|
||||||
joinResponseMessage.BubbleAssetCacheUrl = "http://" +
|
|
||||||
NetworkUtil.GetHostFor(session.RemoteEndPoint.Address,
|
|
||||||
m_scenes[
|
|
||||||
new UUID(joinRequestMessage.BubbleId)].
|
|
||||||
RegionInfo.
|
|
||||||
ExternalHostName) + ":" +
|
|
||||||
m_scenes[new UUID(joinRequestMessage.BubbleId)].RegionInfo.
|
|
||||||
HttpPort + "/assets/";
|
|
||||||
|
|
||||||
joinResponseMessage.BubbleName = m_scenes[new UUID(joinRequestMessage.BubbleId)].RegionInfo.RegionName;
|
|
||||||
|
|
||||||
joinResponseMessage.BubbleRange = 128;
|
|
||||||
joinResponseMessage.BubblePerceptionRange = 128 + 256;
|
|
||||||
joinResponseMessage.BubbleRealTime = 0;
|
|
||||||
joinResponseMessage.ProgramName = m_programName;
|
|
||||||
joinResponseMessage.ProgramMajorVersion = m_programMajorVersion;
|
|
||||||
joinResponseMessage.ProgramMinorVersion = m_programMinorVersion;
|
|
||||||
joinResponseMessage.ProtocolMajorVersion = MxpConstants.ProtocolMajorVersion;
|
|
||||||
joinResponseMessage.ProtocolMinorVersion = MxpConstants.ProtocolMinorVersion;
|
|
||||||
joinResponseMessage.ProtocolSourceRevision = MxpConstants.ProtocolSourceRevision;
|
|
||||||
|
|
||||||
session.Send(joinResponseMessage);
|
|
||||||
|
|
||||||
session.SetStateConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DeclineConnection(Session session, Message joinRequestMessage)
|
|
||||||
{
|
|
||||||
JoinResponseMessage joinResponseMessage = (JoinResponseMessage)MessageFactory.Current.ReserveMessage(typeof(JoinResponseMessage));
|
|
||||||
|
|
||||||
joinResponseMessage.RequestMessageId = joinRequestMessage.MessageId;
|
|
||||||
joinResponseMessage.FailureCode = MxpResponseCodes.UNAUTHORIZED_OPERATION;
|
|
||||||
|
|
||||||
joinResponseMessage.ProgramName = m_programName;
|
|
||||||
joinResponseMessage.ProgramMajorVersion = m_programMajorVersion;
|
|
||||||
joinResponseMessage.ProgramMinorVersion = m_programMinorVersion;
|
|
||||||
joinResponseMessage.ProtocolMajorVersion = MxpConstants.ProtocolMajorVersion;
|
|
||||||
joinResponseMessage.ProtocolMinorVersion = MxpConstants.ProtocolMinorVersion;
|
|
||||||
joinResponseMessage.ProtocolSourceRevision = MxpConstants.ProtocolSourceRevision;
|
|
||||||
|
|
||||||
session.Send(joinResponseMessage);
|
|
||||||
|
|
||||||
session.SetStateDisconnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AuthoriseUser(string participantName, string password, UUID sceneId, out UserAccount account)
|
|
||||||
{
|
|
||||||
string firstName = "";
|
|
||||||
string lastName = "";
|
|
||||||
account = null;
|
|
||||||
|
|
||||||
string[] nameParts = participantName.Split(' ');
|
|
||||||
if (nameParts.Length != 2)
|
|
||||||
{
|
|
||||||
m_log.Error("[MXP ClientStack]: Login failed as user name is not formed of first and last name separated by space: " + participantName);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
firstName = nameParts[0];
|
|
||||||
lastName = nameParts[1];
|
|
||||||
|
|
||||||
account = m_scenes[sceneId].UserAccountService.GetUserAccount(m_scenes[sceneId].RegionInfo.ScopeID, firstName, lastName);
|
|
||||||
if (account != null)
|
|
||||||
return (m_scenes[sceneId].AuthenticationService.Authenticate(account.PrincipalID, password, 1) != string.Empty);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AttachUserAgentToUserProfile(UserAccount account, Session session, UUID sessionId, UUID sceneId, out UUID secureSessionId)
|
|
||||||
{
|
|
||||||
secureSessionId = UUID.Random();
|
|
||||||
Scene scene = m_scenes[sceneId];
|
|
||||||
scene.PresenceService.LoginAgent(account.PrincipalID.ToString(), sessionId, secureSessionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool PrepareSceneForConnection(UUID sessionId, UUID secureSessionId, UUID sceneId, UserAccount account, out string reason)
|
|
||||||
{
|
|
||||||
Scene scene = m_scenes[sceneId];
|
|
||||||
|
|
||||||
AgentCircuitData agent = new AgentCircuitData();
|
|
||||||
agent.AgentID = account.PrincipalID;
|
|
||||||
agent.firstname = account.FirstName;
|
|
||||||
agent.lastname = account.LastName;
|
|
||||||
agent.SessionID = sessionId;
|
|
||||||
agent.SecureSessionID = secureSessionId;
|
|
||||||
agent.circuitcode = sessionId.CRC();
|
|
||||||
agent.BaseFolder = UUID.Zero;
|
|
||||||
agent.InventoryFolder = UUID.Zero;
|
|
||||||
agent.startpos = new Vector3(0, 0, 0); // TODO Fill in region start position
|
|
||||||
agent.CapsPath = "http://localhost/";
|
|
||||||
agent.Appearance = scene.AvatarService.GetAppearance(account.PrincipalID);
|
|
||||||
|
|
||||||
if (agent.Appearance == null)
|
|
||||||
{
|
|
||||||
m_log.WarnFormat("[INTER]: Appearance not found for {0} {1}. Creating default.", agent.firstname, agent.lastname);
|
|
||||||
agent.Appearance = new AvatarAppearance();
|
|
||||||
}
|
|
||||||
|
|
||||||
return scene.NewUserConnection(agent, 0, out reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PrintDebugInformation()
|
|
||||||
{
|
|
||||||
m_log.Info("[MXP ClientStack]: Statistics report");
|
|
||||||
m_log.Info("Pending Sessions: " + PendingSessionCount);
|
|
||||||
m_log.Info("Sessions: " + SessionCount + " (Clients: " + m_clients.Count + " )");
|
|
||||||
m_log.Info("Transmitter Alive?: " + IsTransmitterAlive);
|
|
||||||
m_log.Info("Packets Sent/Received: " + PacketsSent + " / " + PacketsReceived);
|
|
||||||
m_log.Info("Bytes Sent/Received: " + BytesSent + " / " + BytesReceived);
|
|
||||||
m_log.Info("Send/Receive Rate (bps): " + SendRate + " / " + ReceiveRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,133 +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.Text;
|
|
||||||
using Nini.Config;
|
|
||||||
using OpenMetaverse;
|
|
||||||
using OpenSim.Client.VWoHTTP.ClientStack;
|
|
||||||
using OpenSim.Framework;
|
|
||||||
using OpenSim.Framework.Servers;
|
|
||||||
using OpenSim.Framework.Servers.HttpServer;
|
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
|
||||||
using OpenSim.Region.Framework.Scenes;
|
|
||||||
|
|
||||||
namespace OpenSim.Client.VWoHTTP
|
|
||||||
{
|
|
||||||
class VWoHTTPModule : IRegionModule, IHttpAgentHandler
|
|
||||||
{
|
|
||||||
private bool m_disabled = true;
|
|
||||||
|
|
||||||
private IHttpServer m_httpd;
|
|
||||||
|
|
||||||
private readonly List<Scene> m_scenes = new List<Scene>();
|
|
||||||
|
|
||||||
private Dictionary<UUID, VWHClientView> m_clients = new Dictionary<UUID, VWHClientView>();
|
|
||||||
|
|
||||||
#region Implementation of IRegionModule
|
|
||||||
|
|
||||||
public void Initialise(Scene scene, IConfigSource source)
|
|
||||||
{
|
|
||||||
if (m_disabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_scenes.Add(scene);
|
|
||||||
|
|
||||||
m_httpd = MainServer.Instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PostInitialise()
|
|
||||||
{
|
|
||||||
if (m_disabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_httpd.AddAgentHandler("vwohttp", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Close()
|
|
||||||
{
|
|
||||||
if (m_disabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_httpd.RemoveAgentHandler("vwohttp", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get { return "VWoHTTP ClientStack"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSharedModule
|
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Implementation of IHttpAgentHandler
|
|
||||||
|
|
||||||
public bool Handle(OSHttpRequest req, OSHttpResponse resp)
|
|
||||||
{
|
|
||||||
string[] urlparts = req.Url.AbsolutePath.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
|
|
||||||
if (urlparts.Length < 2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (urlparts[1] == "connect")
|
|
||||||
{
|
|
||||||
UUID sessID = UUID.Random();
|
|
||||||
|
|
||||||
VWHClientView client = new VWHClientView(sessID, UUID.Random(), "VWoHTTPClient", m_scenes[0]);
|
|
||||||
|
|
||||||
m_clients.Add(sessID, client);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (urlparts.Length < 3)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
UUID sessionID;
|
|
||||||
if (!UUID.TryParse(urlparts[1], out sessionID))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!m_clients.ContainsKey(sessionID))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return m_clients[sessionID].ProcessInMsg(req, resp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Match(OSHttpRequest req, OSHttpResponse resp)
|
|
||||||
{
|
|
||||||
return req.Url.ToString().Contains("vwohttp");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -56,15 +56,15 @@ namespace OpenSim.Data.MSSQL
|
||||||
string realm, string storeName)
|
string realm, string storeName)
|
||||||
{
|
{
|
||||||
m_Realm = realm;
|
m_Realm = realm;
|
||||||
|
|
||||||
|
m_ConnectionString = connectionString;
|
||||||
|
|
||||||
if (storeName != String.Empty)
|
if (storeName != String.Empty)
|
||||||
{
|
{
|
||||||
Assembly assem = GetType().Assembly;
|
|
||||||
m_ConnectionString = connectionString;
|
|
||||||
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
|
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
|
||||||
{
|
{
|
||||||
conn.Open();
|
conn.Open();
|
||||||
Migration m = new Migration(conn, assem, storeName);
|
Migration m = new Migration(conn, GetType().Assembly, storeName);
|
||||||
m.Update();
|
m.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,8 @@ namespace OpenSim.Data.MSSQL
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// Something went wrong, so we're version 0
|
// Return -1 to indicate table does not exist
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return version;
|
return version;
|
||||||
|
|
|
@ -492,12 +492,11 @@ ELSE
|
||||||
using (SqlConnection conn = new SqlConnection(m_connectionString))
|
using (SqlConnection conn = new SqlConnection(m_connectionString))
|
||||||
using (SqlCommand cmd = new SqlCommand(sql, conn))
|
using (SqlCommand cmd = new SqlCommand(sql, conn))
|
||||||
{
|
{
|
||||||
|
conn.Open();
|
||||||
foreach (TaskInventoryItem taskItem in items)
|
foreach (TaskInventoryItem taskItem in items)
|
||||||
{
|
{
|
||||||
cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem));
|
cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem));
|
||||||
conn.Open();
|
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
|
|
||||||
cmd.Parameters.Clear();
|
cmd.Parameters.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1154,9 +1153,9 @@ VALUES
|
||||||
PrimitiveBaseShape baseShape = new PrimitiveBaseShape();
|
PrimitiveBaseShape baseShape = new PrimitiveBaseShape();
|
||||||
|
|
||||||
baseShape.Scale = new Vector3(
|
baseShape.Scale = new Vector3(
|
||||||
Convert.ToSingle(shapeRow["ScaleX"]),
|
(float)Convert.ToDouble(shapeRow["ScaleX"]),
|
||||||
Convert.ToSingle(shapeRow["ScaleY"]),
|
(float)Convert.ToDouble(shapeRow["ScaleY"]),
|
||||||
Convert.ToSingle(shapeRow["ScaleZ"]));
|
(float)Convert.ToDouble(shapeRow["ScaleZ"]));
|
||||||
|
|
||||||
// paths
|
// paths
|
||||||
baseShape.PCode = Convert.ToByte(shapeRow["PCode"]);
|
baseShape.PCode = Convert.ToByte(shapeRow["PCode"]);
|
||||||
|
@ -1193,8 +1192,11 @@ VALUES
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(shapeRow["Media"] is System.DBNull))
|
if (!(shapeRow["Media"] is System.DBNull) )
|
||||||
|
{
|
||||||
baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]);
|
baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return baseShape;
|
return baseShape;
|
||||||
}
|
}
|
||||||
|
@ -1573,7 +1575,16 @@ VALUES
|
||||||
parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry));
|
parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry));
|
||||||
parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams));
|
parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams));
|
||||||
parameters.Add(_Database.CreateParameter("State", s.State));
|
parameters.Add(_Database.CreateParameter("State", s.State));
|
||||||
parameters.Add(_Database.CreateParameter("Media", null == s.Media ? null : s.Media.ToXml()));
|
|
||||||
|
if(null == s.Media )
|
||||||
|
{
|
||||||
|
parameters.Add(_Database.CreateParameter("Media", DBNull.Value));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return parameters.ToArray();
|
return parameters.ToArray();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,11 @@ COMMIT
|
||||||
|
|
||||||
BEGIN TRANSACTION
|
BEGIN TRANSACTION
|
||||||
|
|
||||||
INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey, accountType) SELECT [UUID] AS UUID, [passwordHash] AS passwordHash, [passwordSalt] AS passwordSalt, [webLoginKey] AS webLoginKey, 'UserAccount' as [accountType] FROM users;
|
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[users]') AND type in (N'U'))
|
||||||
|
INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey, accountType) SELECT [UUID] AS UUID, [passwordHash] AS passwordHash, [passwordSalt] AS passwordSalt, [webLoginKey] AS webLoginKey, 'UserAccount' as [accountType] FROM users;
|
||||||
|
|
||||||
|
COMMIT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
COMMIT
|
|
|
@ -13,5 +13,28 @@ PRIMARY KEY CLUSTERED
|
||||||
) ON [PRIMARY]
|
) ON [PRIMARY]
|
||||||
|
|
||||||
|
|
||||||
|
COMMIT
|
||||||
|
|
||||||
|
:VERSION 2
|
||||||
|
|
||||||
|
BEGIN TRANSACTION
|
||||||
|
|
||||||
|
CREATE TABLE dbo.Tmp_Avatars
|
||||||
|
(
|
||||||
|
PrincipalID uniqueidentifier NOT NULL,
|
||||||
|
[Name] varchar(32) NOT NULL,
|
||||||
|
Value text NOT NULL DEFAULT '',
|
||||||
|
) ON [PRIMARY]
|
||||||
|
TEXTIMAGE_ON [PRIMARY]
|
||||||
|
|
||||||
|
IF EXISTS(SELECT * FROM dbo.Avatars)
|
||||||
|
EXEC('INSERT INTO dbo.Tmp_Avatars (PrincipalID, Name, Value)
|
||||||
|
SELECT PrincipalID, CONVERT(text, Name), Value FROM dbo.Avatars WITH (HOLDLOCK TABLOCKX)')
|
||||||
|
|
||||||
|
DROP TABLE dbo.Avatars
|
||||||
|
|
||||||
|
EXECUTE sp_rename N'dbo.Tmp_Avatars', N'Avatars', 'OBJECT'
|
||||||
|
|
||||||
|
COMMIT
|
||||||
|
|
||||||
|
|
||||||
COMMIT
|
|
|
@ -15,6 +15,8 @@ COMMIT
|
||||||
|
|
||||||
BEGIN TRANSACTION
|
BEGIN TRANSACTION
|
||||||
|
|
||||||
INSERT INTO Friends (PrincipalID, Friend, Flags, Offered) SELECT [ownerID], [friendID], [friendPerms], 0 FROM userfriends;
|
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[userfriends]') AND type in (N'U'))
|
||||||
|
INSERT INTO Friends (PrincipalID, Friend, Flags, Offered)
|
||||||
|
SELECT [ownerID], [friendID], [friendPerms], 0 FROM userfriends;
|
||||||
|
|
||||||
COMMIT
|
COMMIT
|
|
@ -222,4 +222,17 @@ ALTER TABLE [regions] ADD [Token] varchar(255) NOT NULL DEFAULT 0;
|
||||||
|
|
||||||
COMMIT
|
COMMIT
|
||||||
|
|
||||||
|
:VERSION 8
|
||||||
|
|
||||||
|
BEGIN TRANSACTION
|
||||||
|
ALTER TABLE regions ALTER COLUMN regionName VarChar(128)
|
||||||
|
|
||||||
|
DROP INDEX IX_regions_name ON dbo.regions
|
||||||
|
ALTER TABLE regions ALTER COLUMN regionName VarChar(128) null
|
||||||
|
|
||||||
|
CREATE NONCLUSTERED INDEX IX_regions_name ON dbo.regions
|
||||||
|
(
|
||||||
|
regionName
|
||||||
|
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||||
|
|
||||||
|
COMMIT
|
|
@ -238,7 +238,10 @@ alter table inventoryitems
|
||||||
|
|
||||||
COMMIT
|
COMMIT
|
||||||
|
|
||||||
|
:VERSION 8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE inventoryitems
|
||||||
|
ADD CONSTRAINT DF_inventoryitems_creatorID
|
||||||
|
DEFAULT '00000000-0000-0000-0000-000000000000' FOR creatorID
|
||||||
|
|
||||||
|
:GO
|
|
@ -7,14 +7,7 @@ CREATE TABLE [Presence] (
|
||||||
[RegionID] uniqueidentifier NOT NULL,
|
[RegionID] uniqueidentifier NOT NULL,
|
||||||
[SessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
[SessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||||
[SecureSessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
[SecureSessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||||
[Online] char(5) NOT NULL DEFAULT 'false',
|
|
||||||
[Login] char(16) NOT NULL DEFAULT '0',
|
|
||||||
[Logout] char(16) NOT NULL DEFAULT '0',
|
|
||||||
[Position] char(64) NOT NULL DEFAULT '<0,0,0>',
|
|
||||||
[LookAt] char(64) NOT NULL DEFAULT '<0,0,0>',
|
|
||||||
[HomeRegionID] uniqueidentifier NOT NULL,
|
|
||||||
[HomePosition] CHAR(64) NOT NULL DEFAULT '<0,0,0>',
|
|
||||||
[HomeLookAt] CHAR(64) NOT NULL DEFAULT '<0,0,0>',
|
|
||||||
)
|
)
|
||||||
ON [PRIMARY]
|
ON [PRIMARY]
|
||||||
|
|
||||||
|
@ -27,4 +20,12 @@ BEGIN TRANSACTION
|
||||||
CREATE UNIQUE INDEX SessionID ON Presence(SessionID);
|
CREATE UNIQUE INDEX SessionID ON Presence(SessionID);
|
||||||
CREATE INDEX UserID ON Presence(UserID);
|
CREATE INDEX UserID ON Presence(UserID);
|
||||||
|
|
||||||
|
COMMIT
|
||||||
|
|
||||||
|
:VERSION 2
|
||||||
|
|
||||||
|
BEGIN TRANSACTION
|
||||||
|
|
||||||
|
ALTER TABLE Presence ADD LastSeen DateTime
|
||||||
|
|
||||||
COMMIT
|
COMMIT
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
:VERSION 1
|
:VERSION 1
|
||||||
|
|
||||||
CREATE TABLE [dbo].[prims](
|
CREATE TABLE [dbo].[prims](
|
||||||
|
@ -926,11 +925,121 @@ ALTER TABLE regionsettings ADD loaded_creation_datetime int NOT NULL default 0
|
||||||
COMMIT
|
COMMIT
|
||||||
|
|
||||||
:VERSION 24
|
:VERSION 24
|
||||||
-- Added post 0.7
|
|
||||||
|
|
||||||
BEGIN TRANSACTION
|
BEGIN TRANSACTION
|
||||||
|
|
||||||
ALTER TABLE prims ADD COLUMN MediaURL varchar(255)
|
ALTER TABLE prims ADD MediaURL varchar(255)
|
||||||
ALTER TABLE primshapes ADD COLUMN Media TEXT
|
ALTER TABLE primshapes ADD Media TEXT NULL
|
||||||
|
|
||||||
COMMIT
|
COMMIT
|
||||||
|
|
||||||
|
:VERSION 25
|
||||||
|
|
||||||
|
BEGIN TRANSACTION
|
||||||
|
CREATE TABLE "regionwindlight" (
|
||||||
|
"region_id" varchar(36) NOT NULL DEFAULT '000000-0000-0000-0000-000000000000',
|
||||||
|
"water_color_r" [float] NOT NULL DEFAULT '4.000000',
|
||||||
|
"water_color_g" [float] NOT NULL DEFAULT '38.000000',
|
||||||
|
"water_color_b" [float] NOT NULL DEFAULT '64.000000',
|
||||||
|
"water_fog_density_exponent" [float] NOT NULL DEFAULT '4.0',
|
||||||
|
"underwater_fog_modifier" [float] NOT NULL DEFAULT '0.25',
|
||||||
|
"reflection_wavelet_scale_1" [float] NOT NULL DEFAULT '2.0',
|
||||||
|
"reflection_wavelet_scale_2" [float] NOT NULL DEFAULT '2.0',
|
||||||
|
"reflection_wavelet_scale_3" [float] NOT NULL DEFAULT '2.0',
|
||||||
|
"fresnel_scale" [float] NOT NULL DEFAULT '0.40',
|
||||||
|
"fresnel_offset" [float] NOT NULL DEFAULT '0.50',
|
||||||
|
"refract_scale_above" [float] NOT NULL DEFAULT '0.03',
|
||||||
|
"refract_scale_below" [float] NOT NULL DEFAULT '0.20',
|
||||||
|
"blur_multiplier" [float] NOT NULL DEFAULT '0.040',
|
||||||
|
"big_wave_direction_x" [float] NOT NULL DEFAULT '1.05',
|
||||||
|
"big_wave_direction_y" [float] NOT NULL DEFAULT '-0.42',
|
||||||
|
"little_wave_direction_x" [float] NOT NULL DEFAULT '1.11',
|
||||||
|
"little_wave_direction_y" [float] NOT NULL DEFAULT '-1.16',
|
||||||
|
"normal_map_texture" varchar(36) NOT NULL DEFAULT '822ded49-9a6c-f61c-cb89-6df54f42cdf4',
|
||||||
|
"horizon_r" [float] NOT NULL DEFAULT '0.25',
|
||||||
|
"horizon_g" [float] NOT NULL DEFAULT '0.25',
|
||||||
|
"horizon_b" [float] NOT NULL DEFAULT '0.32',
|
||||||
|
"horizon_i" [float] NOT NULL DEFAULT '0.32',
|
||||||
|
"haze_horizon" [float] NOT NULL DEFAULT '0.19',
|
||||||
|
"blue_density_r" [float] NOT NULL DEFAULT '0.12',
|
||||||
|
"blue_density_g" [float] NOT NULL DEFAULT '0.22',
|
||||||
|
"blue_density_b" [float] NOT NULL DEFAULT '0.38',
|
||||||
|
"blue_density_i" [float] NOT NULL DEFAULT '0.38',
|
||||||
|
"haze_density" [float] NOT NULL DEFAULT '0.70',
|
||||||
|
"density_multiplier" [float] NOT NULL DEFAULT '0.18',
|
||||||
|
"distance_multiplier" [float] NOT NULL DEFAULT '0.8',
|
||||||
|
"max_altitude" int NOT NULL DEFAULT '1605',
|
||||||
|
"sun_moon_color_r" [float] NOT NULL DEFAULT '0.24',
|
||||||
|
"sun_moon_color_g" [float] NOT NULL DEFAULT '0.26',
|
||||||
|
"sun_moon_color_b" [float] NOT NULL DEFAULT '0.30',
|
||||||
|
"sun_moon_color_i" [float] NOT NULL DEFAULT '0.30',
|
||||||
|
"sun_moon_position" [float] NOT NULL DEFAULT '0.317',
|
||||||
|
"ambient_r" [float] NOT NULL DEFAULT '0.35',
|
||||||
|
"ambient_g" [float] NOT NULL DEFAULT '0.35',
|
||||||
|
"ambient_b" [float] NOT NULL DEFAULT '0.35',
|
||||||
|
"ambient_i" [float] NOT NULL DEFAULT '0.35',
|
||||||
|
"east_angle" [float] NOT NULL DEFAULT '0.00',
|
||||||
|
"sun_glow_focus" [float] NOT NULL DEFAULT '0.10',
|
||||||
|
"sun_glow_size" [float] NOT NULL DEFAULT '1.75',
|
||||||
|
"scene_gamma" [float] NOT NULL DEFAULT '1.00',
|
||||||
|
"star_brightness" [float] NOT NULL DEFAULT '0.00',
|
||||||
|
"cloud_color_r" [float] NOT NULL DEFAULT '0.41',
|
||||||
|
"cloud_color_g" [float] NOT NULL DEFAULT '0.41',
|
||||||
|
"cloud_color_b" [float] NOT NULL DEFAULT '0.41',
|
||||||
|
"cloud_color_i" [float] NOT NULL DEFAULT '0.41',
|
||||||
|
"cloud_x" [float] NOT NULL DEFAULT '1.00',
|
||||||
|
"cloud_y" [float] NOT NULL DEFAULT '0.53',
|
||||||
|
"cloud_density" [float] NOT NULL DEFAULT '1.00',
|
||||||
|
"cloud_coverage" [float] NOT NULL DEFAULT '0.27',
|
||||||
|
"cloud_scale" [float] NOT NULL DEFAULT '0.42',
|
||||||
|
"cloud_detail_x" [float] NOT NULL DEFAULT '1.00',
|
||||||
|
"cloud_detail_y" [float] NOT NULL DEFAULT '0.53',
|
||||||
|
"cloud_detail_density" [float] NOT NULL DEFAULT '0.12',
|
||||||
|
"cloud_scroll_x" [float] NOT NULL DEFAULT '0.20',
|
||||||
|
"cloud_scroll_x_lock" tinyint NOT NULL DEFAULT '0',
|
||||||
|
"cloud_scroll_y" [float] NOT NULL DEFAULT '0.01',
|
||||||
|
"cloud_scroll_y_lock" tinyint NOT NULL DEFAULT '0',
|
||||||
|
"draw_classic_clouds" tinyint NOT NULL DEFAULT '1',
|
||||||
|
PRIMARY KEY ("region_id")
|
||||||
|
)
|
||||||
|
|
||||||
|
COMMIT TRANSACTION
|
||||||
|
|
||||||
|
:VERSION 26
|
||||||
|
|
||||||
|
BEGIN TRANSACTION
|
||||||
|
|
||||||
|
ALTER TABLE regionsettings ADD map_tile_ID CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'
|
||||||
|
|
||||||
|
COMMIT
|
||||||
|
|
||||||
|
:VERSION 27 #---------------------
|
||||||
|
|
||||||
|
BEGIN TRANSACTION
|
||||||
|
ALTER TABLE land ADD MediaType VARCHAR(32) NOT NULL DEFAULT 'none/none'
|
||||||
|
ALTER TABLE land ADD MediaDescription VARCHAR(255) NOT NULL DEFAULT ''
|
||||||
|
ALTER TABLE land ADD MediaSize VARCHAR(16) NOT NULL DEFAULT '0,0'
|
||||||
|
ALTER TABLE land ADD MediaLoop bit NOT NULL DEFAULT 0
|
||||||
|
ALTER TABLE land ADD ObscureMusic bit NOT NULL DEFAULT 0
|
||||||
|
ALTER TABLE land ADD ObscureMedia bit NOT NULL DEFAULT 0
|
||||||
|
COMMIT
|
||||||
|
|
||||||
|
:VERSION 28 #---------------------
|
||||||
|
|
||||||
|
BEGIN TRANSACTION
|
||||||
|
|
||||||
|
ALTER TABLE prims
|
||||||
|
ADD CONSTRAINT DF_prims_CreatorID
|
||||||
|
DEFAULT '00000000-0000-0000-0000-000000000000'
|
||||||
|
FOR CreatorID
|
||||||
|
|
||||||
|
ALTER TABLE prims ALTER COLUMN CreatorID uniqueidentifier NOT NULL
|
||||||
|
|
||||||
|
ALTER TABLE primitems
|
||||||
|
ADD CONSTRAINT DF_primitems_CreatorID
|
||||||
|
DEFAULT '00000000-0000-0000-0000-000000000000'
|
||||||
|
FOR CreatorID
|
||||||
|
|
||||||
|
ALTER TABLE primitems ALTER COLUMN CreatorID uniqueidentifier NOT NULL
|
||||||
|
|
||||||
|
COMMIT
|
||||||
|
|
|
@ -19,7 +19,7 @@ CREATE TABLE [UserAccounts] (
|
||||||
:VERSION 2
|
:VERSION 2
|
||||||
|
|
||||||
BEGIN TRANSACTION
|
BEGIN TRANSACTION
|
||||||
|
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[users]') AND type in (N'U'))
|
||||||
INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT [UUID] AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID,
|
INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT [UUID] AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID,
|
||||||
username AS FirstName,
|
username AS FirstName,
|
||||||
lastname AS LastName,
|
lastname AS LastName,
|
||||||
|
|
|
@ -592,9 +592,7 @@ namespace OpenSim.Framework.Console
|
||||||
string line = ReadLine(m_defaultPrompt + "# ", true, true);
|
string line = ReadLine(m_defaultPrompt + "# ", true, true);
|
||||||
|
|
||||||
if (line != String.Empty)
|
if (line != String.Empty)
|
||||||
{
|
Output("Invalid command");
|
||||||
m_log.Info("[CONSOLE] Invalid command");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RunCommand(string cmd)
|
public void RunCommand(string cmd)
|
||||||
|
|
|
@ -572,34 +572,69 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
public class IEntityUpdate
|
public class IEntityUpdate
|
||||||
{
|
{
|
||||||
public ISceneEntity Entity;
|
private ISceneEntity m_entity;
|
||||||
public uint Flags;
|
private uint m_flags;
|
||||||
|
private int m_updateTime;
|
||||||
|
|
||||||
|
public ISceneEntity Entity
|
||||||
|
{
|
||||||
|
get { return m_entity; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint Flags
|
||||||
|
{
|
||||||
|
get { return m_flags; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int UpdateTime
|
||||||
|
{
|
||||||
|
get { return m_updateTime; }
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void Update(IEntityUpdate update)
|
public virtual void Update(IEntityUpdate update)
|
||||||
{
|
{
|
||||||
this.Flags |= update.Flags;
|
m_flags |= update.Flags;
|
||||||
|
|
||||||
|
// Use the older of the updates as the updateTime
|
||||||
|
if (Util.EnvironmentTickCountCompare(UpdateTime, update.UpdateTime) > 0)
|
||||||
|
m_updateTime = update.UpdateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEntityUpdate(ISceneEntity entity, uint flags)
|
public IEntityUpdate(ISceneEntity entity, uint flags)
|
||||||
{
|
{
|
||||||
Entity = entity;
|
m_entity = entity;
|
||||||
Flags = flags;
|
m_flags = flags;
|
||||||
|
m_updateTime = Util.EnvironmentTickCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEntityUpdate(ISceneEntity entity, uint flags, Int32 updateTime)
|
||||||
|
{
|
||||||
|
m_entity = entity;
|
||||||
|
m_flags = flags;
|
||||||
|
m_updateTime = updateTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class EntityUpdate : IEntityUpdate
|
public class EntityUpdate : IEntityUpdate
|
||||||
{
|
{
|
||||||
// public ISceneEntity Entity;
|
private float m_timeDilation;
|
||||||
// public PrimUpdateFlags Flags;
|
|
||||||
public float TimeDilation;
|
public float TimeDilation
|
||||||
|
{
|
||||||
|
get { return m_timeDilation; }
|
||||||
|
}
|
||||||
|
|
||||||
public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation)
|
public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation)
|
||||||
: base(entity,(uint)flags)
|
: base(entity, (uint)flags)
|
||||||
{
|
{
|
||||||
//Entity = entity;
|
|
||||||
// Flags = flags;
|
// Flags = flags;
|
||||||
TimeDilation = timedilation;
|
m_timeDilation = timedilation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation, Int32 updateTime)
|
||||||
|
: base(entity,(uint)flags,updateTime)
|
||||||
|
{
|
||||||
|
m_timeDilation = timedilation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,50 +34,81 @@ using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Client;
|
using OpenSim.Framework.Client;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
|
||||||
namespace OpenSim.Region.ClientStack.LindenUDP
|
namespace OpenSim.Framework
|
||||||
{
|
{
|
||||||
public class PriorityQueue
|
public class PriorityQueue
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
internal delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity);
|
public delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity);
|
||||||
|
|
||||||
// Heap[0] for self updates
|
/// <summary>
|
||||||
// Heap[1..12] for entity updates
|
/// Total number of queues (priorities) available
|
||||||
|
/// </summary>
|
||||||
|
public const uint NumberOfQueues = 12;
|
||||||
|
|
||||||
internal const uint m_numberOfQueues = 12;
|
/// <summary>
|
||||||
|
/// Number of queuest (priorities) that are processed immediately
|
||||||
|
/// </summary.
|
||||||
|
public const uint NumberOfImmediateQueues = 2;
|
||||||
|
|
||||||
private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[m_numberOfQueues];
|
private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[NumberOfQueues];
|
||||||
private Dictionary<uint, LookupItem> m_lookupTable;
|
private Dictionary<uint, LookupItem> m_lookupTable;
|
||||||
|
|
||||||
|
// internal state used to ensure the deqeues are spread across the priority
|
||||||
|
// queues "fairly". queuecounts is the amount to pull from each queue in
|
||||||
|
// each pass. weighted towards the higher priority queues
|
||||||
private uint m_nextQueue = 0;
|
private uint m_nextQueue = 0;
|
||||||
|
private uint m_countFromQueue = 0;
|
||||||
|
private uint[] m_queueCounts = { 8, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1 };
|
||||||
|
|
||||||
|
// next request is a counter of the number of updates queued, it provides
|
||||||
|
// a total ordering on the updates coming through the queue and is more
|
||||||
|
// lightweight (and more discriminating) than tick count
|
||||||
private UInt64 m_nextRequest = 0;
|
private UInt64 m_nextRequest = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Lock for enqueue and dequeue operations on the priority queue
|
||||||
|
/// </summary>
|
||||||
private object m_syncRoot = new object();
|
private object m_syncRoot = new object();
|
||||||
public object SyncRoot {
|
public object SyncRoot {
|
||||||
get { return this.m_syncRoot; }
|
get { return this.m_syncRoot; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { }
|
#region constructor
|
||||||
|
public PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { }
|
||||||
|
|
||||||
internal PriorityQueue(int capacity)
|
public PriorityQueue(int capacity)
|
||||||
{
|
{
|
||||||
m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
|
m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
|
||||||
|
|
||||||
for (int i = 0; i < m_heaps.Length; ++i)
|
for (int i = 0; i < m_heaps.Length; ++i)
|
||||||
m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
|
m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
|
||||||
}
|
|
||||||
|
|
||||||
internal int Count
|
m_nextQueue = NumberOfImmediateQueues;
|
||||||
|
m_countFromQueue = m_queueCounts[m_nextQueue];
|
||||||
|
}
|
||||||
|
#endregion Constructor
|
||||||
|
|
||||||
|
#region PublicMethods
|
||||||
|
/// <summary>
|
||||||
|
/// Return the number of items in the queues
|
||||||
|
/// </summary>
|
||||||
|
public int Count
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int i = 0; i < m_heaps.Length; ++i)
|
for (int i = 0; i < m_heaps.Length; ++i)
|
||||||
count += m_heaps[i].Count;
|
count += m_heaps[i].Count;
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enqueue an item into the specified priority queue
|
||||||
|
/// </summary>
|
||||||
public bool Enqueue(uint pqueue, IEntityUpdate value)
|
public bool Enqueue(uint pqueue, IEntityUpdate value)
|
||||||
{
|
{
|
||||||
LookupItem lookup;
|
LookupItem lookup;
|
||||||
|
@ -91,7 +122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
lookup.Heap.Remove(lookup.Handle);
|
lookup.Heap.Remove(lookup.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1);
|
pqueue = Util.Clamp<uint>(pqueue, 0, NumberOfQueues - 1);
|
||||||
lookup.Heap = m_heaps[pqueue];
|
lookup.Heap = m_heaps[pqueue];
|
||||||
lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle);
|
lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle);
|
||||||
m_lookupTable[localid] = lookup;
|
m_lookupTable[localid] = lookup;
|
||||||
|
@ -99,20 +130,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue)
|
/// <summary>
|
||||||
|
/// Remove an item from one of the queues. Specifically, it removes the
|
||||||
|
/// oldest item from the next queue in order to provide fair access to
|
||||||
|
/// all of the queues
|
||||||
|
/// </summary>
|
||||||
|
public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_numberOfQueues; ++i)
|
// If there is anything in priority queue 0, return it first no
|
||||||
|
// matter what else. Breaks fairness. But very useful.
|
||||||
|
for (int iq = 0; iq < NumberOfImmediateQueues; iq++)
|
||||||
{
|
{
|
||||||
// To get the fair queing, we cycle through each of the
|
if (m_heaps[iq].Count > 0)
|
||||||
// queues when finding an element to dequeue, this code
|
|
||||||
// assumes that the distribution of updates in the queues
|
|
||||||
// is polynomial, probably quadractic (eg distance of PI * R^2)
|
|
||||||
uint h = (uint)((m_nextQueue + i) % m_numberOfQueues);
|
|
||||||
if (m_heaps[h].Count > 0)
|
|
||||||
{
|
{
|
||||||
m_nextQueue = (uint)((h + 1) % m_numberOfQueues);
|
MinHeapItem item = m_heaps[iq].RemoveMin();
|
||||||
|
m_lookupTable.Remove(item.Value.Entity.LocalId);
|
||||||
|
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
|
||||||
|
value = item.Value;
|
||||||
|
|
||||||
MinHeapItem item = m_heaps[h].RemoveMin();
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// To get the fair queing, we cycle through each of the
|
||||||
|
// queues when finding an element to dequeue.
|
||||||
|
// We pull (NumberOfQueues - QueueIndex) items from each queue in order
|
||||||
|
// to give lower numbered queues a higher priority and higher percentage
|
||||||
|
// of the bandwidth.
|
||||||
|
|
||||||
|
// Check for more items to be pulled from the current queue
|
||||||
|
if (m_heaps[m_nextQueue].Count > 0 && m_countFromQueue > 0)
|
||||||
|
{
|
||||||
|
m_countFromQueue--;
|
||||||
|
|
||||||
|
MinHeapItem item = m_heaps[m_nextQueue].RemoveMin();
|
||||||
|
m_lookupTable.Remove(item.Value.Entity.LocalId);
|
||||||
|
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
|
||||||
|
value = item.Value;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the next non-immediate queue with updates in it
|
||||||
|
for (int i = 0; i < NumberOfQueues; ++i)
|
||||||
|
{
|
||||||
|
m_nextQueue = (uint)((m_nextQueue + 1) % NumberOfQueues);
|
||||||
|
m_countFromQueue = m_queueCounts[m_nextQueue];
|
||||||
|
|
||||||
|
// if this is one of the immediate queues, just skip it
|
||||||
|
if (m_nextQueue < NumberOfImmediateQueues)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (m_heaps[m_nextQueue].Count > 0)
|
||||||
|
{
|
||||||
|
m_countFromQueue--;
|
||||||
|
|
||||||
|
MinHeapItem item = m_heaps[m_nextQueue].RemoveMin();
|
||||||
m_lookupTable.Remove(item.Value.Entity.LocalId);
|
m_lookupTable.Remove(item.Value.Entity.LocalId);
|
||||||
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
|
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
|
||||||
value = item.Value;
|
value = item.Value;
|
||||||
|
@ -126,7 +199,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Reprioritize(UpdatePriorityHandler handler)
|
/// <summary>
|
||||||
|
/// Reapply the prioritization function to each of the updates currently
|
||||||
|
/// stored in the priority queues.
|
||||||
|
/// </summary
|
||||||
|
public void Reprioritize(UpdatePriorityHandler handler)
|
||||||
{
|
{
|
||||||
MinHeapItem item;
|
MinHeapItem item;
|
||||||
foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
|
foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
|
||||||
|
@ -140,7 +217,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
// unless the priority queue has changed, there is no need to modify
|
// unless the priority queue has changed, there is no need to modify
|
||||||
// the entry
|
// the entry
|
||||||
pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1);
|
pqueue = Util.Clamp<uint>(pqueue, 0, NumberOfQueues - 1);
|
||||||
if (pqueue != item.PriorityQueue)
|
if (pqueue != item.PriorityQueue)
|
||||||
{
|
{
|
||||||
lookup.Heap.Remove(lookup.Handle);
|
lookup.Heap.Remove(lookup.Handle);
|
||||||
|
@ -161,17 +238,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
string s = "";
|
string s = "";
|
||||||
for (int i = 0; i < m_numberOfQueues; i++)
|
for (int i = 0; i < NumberOfQueues; i++)
|
||||||
{
|
s += String.Format("{0,7} ",m_heaps[i].Count);
|
||||||
if (s != "") s += ",";
|
|
||||||
s += m_heaps[i].Count.ToString();
|
|
||||||
}
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion PublicMethods
|
||||||
|
|
||||||
#region MinHeapItem
|
#region MinHeapItem
|
||||||
private struct MinHeapItem : IComparable<MinHeapItem>
|
private struct MinHeapItem : IComparable<MinHeapItem>
|
||||||
{
|
{
|
|
@ -369,6 +369,7 @@ namespace OpenSim.Framework
|
||||||
private int m_physPrimMax = 0;
|
private int m_physPrimMax = 0;
|
||||||
private bool m_clampPrimSize = false;
|
private bool m_clampPrimSize = false;
|
||||||
private int m_objectCapacity = 0;
|
private int m_objectCapacity = 0;
|
||||||
|
private int m_agentCapacity = 0;
|
||||||
private string m_regionType = String.Empty;
|
private string m_regionType = String.Empty;
|
||||||
private RegionLightShareData m_windlight = new RegionLightShareData();
|
private RegionLightShareData m_windlight = new RegionLightShareData();
|
||||||
protected uint m_httpPort;
|
protected uint m_httpPort;
|
||||||
|
@ -547,6 +548,11 @@ namespace OpenSim.Framework
|
||||||
get { return m_objectCapacity; }
|
get { return m_objectCapacity; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int AgentCapacity
|
||||||
|
{
|
||||||
|
get { return m_agentCapacity; }
|
||||||
|
}
|
||||||
|
|
||||||
public byte AccessLevel
|
public byte AccessLevel
|
||||||
{
|
{
|
||||||
get { return (byte)Util.ConvertMaturityToAccessLevel((uint)RegionSettings.Maturity); }
|
get { return (byte)Util.ConvertMaturityToAccessLevel((uint)RegionSettings.Maturity); }
|
||||||
|
@ -821,6 +827,8 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
m_objectCapacity = config.GetInt("MaxPrims", 15000);
|
m_objectCapacity = config.GetInt("MaxPrims", 15000);
|
||||||
|
|
||||||
|
m_agentCapacity = config.GetInt("MaxAgents", 100);
|
||||||
|
|
||||||
|
|
||||||
// Multi-tenancy
|
// Multi-tenancy
|
||||||
//
|
//
|
||||||
|
@ -857,6 +865,9 @@ namespace OpenSim.Framework
|
||||||
if (m_objectCapacity != 0)
|
if (m_objectCapacity != 0)
|
||||||
config.Set("MaxPrims", m_objectCapacity);
|
config.Set("MaxPrims", m_objectCapacity);
|
||||||
|
|
||||||
|
if (m_agentCapacity != 0)
|
||||||
|
config.Set("MaxAgents", m_agentCapacity);
|
||||||
|
|
||||||
if (ScopeID != UUID.Zero)
|
if (ScopeID != UUID.Zero)
|
||||||
config.Set("ScopeID", ScopeID.ToString());
|
config.Set("ScopeID", ScopeID.ToString());
|
||||||
|
|
||||||
|
@ -943,6 +954,9 @@ namespace OpenSim.Framework
|
||||||
configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||||
"Max objects this sim will hold", m_objectCapacity.ToString(), true);
|
"Max objects this sim will hold", m_objectCapacity.ToString(), true);
|
||||||
|
|
||||||
|
configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||||
|
"Max avatars this sim will hold", m_agentCapacity.ToString(), true);
|
||||||
|
|
||||||
configMember.addConfigurationOption("scope_id", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
|
configMember.addConfigurationOption("scope_id", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
|
||||||
"Scope ID for this region", ScopeID.ToString(), true);
|
"Scope ID for this region", ScopeID.ToString(), true);
|
||||||
|
|
||||||
|
@ -1055,6 +1069,9 @@ namespace OpenSim.Framework
|
||||||
case "object_capacity":
|
case "object_capacity":
|
||||||
m_objectCapacity = (int)configuration_result;
|
m_objectCapacity = (int)configuration_result;
|
||||||
break;
|
break;
|
||||||
|
case "agent_capacity":
|
||||||
|
m_agentCapacity = (int)configuration_result;
|
||||||
|
break;
|
||||||
case "scope_id":
|
case "scope_id":
|
||||||
ScopeID = (UUID)configuration_result;
|
ScopeID = (UUID)configuration_result;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -430,7 +430,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
string path = request.RawUrl;
|
string path = request.RawUrl;
|
||||||
string handlerKey = GetHandlerKey(request.HttpMethod, path);
|
string handlerKey = GetHandlerKey(request.HttpMethod, path);
|
||||||
|
|
||||||
//m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path);
|
// m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path);
|
||||||
|
|
||||||
if (TryGetStreamHandler(handlerKey, out requestHandler))
|
if (TryGetStreamHandler(handlerKey, out requestHandler))
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace OpenSim
|
||||||
{
|
{
|
||||||
public class VersionInfo
|
public class VersionInfo
|
||||||
{
|
{
|
||||||
private const string VERSION_NUMBER = "0.7.1";
|
private const string VERSION_NUMBER = "0.7.2";
|
||||||
private const Flavour VERSION_FLAVOUR = Flavour.Dev;
|
private const Flavour VERSION_FLAVOUR = Flavour.Dev;
|
||||||
|
|
||||||
public enum Flavour
|
public enum Flavour
|
||||||
|
|
|
@ -1537,6 +1537,23 @@ namespace OpenSim.Framework
|
||||||
return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1);
|
return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount
|
||||||
|
// Assumes both tcA and tcB came from previous calls to Util.EnvironmentTickCount().
|
||||||
|
// A positive return value indicates A occured later than B
|
||||||
|
public static Int32 EnvironmentTickCountCompare(Int32 tcA, Int32 tcB)
|
||||||
|
{
|
||||||
|
// A, B and TC are all between 0 and 0x3fffffff
|
||||||
|
int tc = EnvironmentTickCount();
|
||||||
|
|
||||||
|
if (tc - tcA >= 0)
|
||||||
|
tcA += EnvironmentTickCountMask + 1;
|
||||||
|
|
||||||
|
if (tc - tcB >= 0)
|
||||||
|
tcB += EnvironmentTickCountMask + 1;
|
||||||
|
|
||||||
|
return tcA - tcB;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prints the call stack at any given point. Useful for debugging.
|
/// Prints the call stack at any given point. Useful for debugging.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -384,6 +384,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } }
|
public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } }
|
||||||
public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
|
public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Entity update queues
|
||||||
|
/// </summary>
|
||||||
|
public PriorityQueue EntityUpdateQueue { get { return m_entityUpdates; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// First name of the agent/avatar represented by the client
|
/// First name of the agent/avatar represented by the client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -3561,6 +3566,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
|
m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Requeue an EntityUpdate when it was not acknowledged by the client.
|
||||||
|
/// We will update the priority and put it in the correct queue, merging update flags
|
||||||
|
/// with any other updates that may be queued for the same entity.
|
||||||
|
/// The original update time is used for the merged update.
|
||||||
|
/// </summary>
|
||||||
|
private void ResendPrimUpdate(EntityUpdate update)
|
||||||
|
{
|
||||||
|
// If the update exists in priority queue, it will be updated.
|
||||||
|
// If it does not exist then it will be added with the current (rather than its original) priority
|
||||||
|
uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity);
|
||||||
|
|
||||||
|
lock (m_entityUpdates.SyncRoot)
|
||||||
|
m_entityUpdates.Enqueue(priority, update);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Requeue a list of EntityUpdates when they were not acknowledged by the client.
|
||||||
|
/// We will update the priority and put it in the correct queue, merging update flags
|
||||||
|
/// with any other updates that may be queued for the same entity.
|
||||||
|
/// The original update time is used for the merged update.
|
||||||
|
/// </summary>
|
||||||
|
private void ResendPrimUpdates(List<EntityUpdate> updates, OutgoingPacket oPacket)
|
||||||
|
{
|
||||||
|
// m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime);
|
||||||
|
|
||||||
|
// Remove the update packet from the list of packets waiting for acknowledgement
|
||||||
|
// because we are requeuing the list of updates. They will be resent in new packets
|
||||||
|
// with the most recent state and priority.
|
||||||
|
m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
|
||||||
|
|
||||||
|
// Count this as a resent packet since we are going to requeue all of the updates contained in it
|
||||||
|
Interlocked.Increment(ref m_udpClient.PacketsResent);
|
||||||
|
|
||||||
|
foreach (EntityUpdate update in updates)
|
||||||
|
ResendPrimUpdate(update);
|
||||||
|
}
|
||||||
|
|
||||||
private void ProcessEntityUpdates(int maxUpdates)
|
private void ProcessEntityUpdates(int maxUpdates)
|
||||||
{
|
{
|
||||||
OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
|
OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
|
||||||
|
@ -3568,6 +3611,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
|
OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
|
||||||
OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
|
OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
|
||||||
|
|
||||||
|
OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
|
||||||
|
OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
|
||||||
|
OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
|
||||||
|
OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
|
||||||
|
|
||||||
// Check to see if this is a flush
|
// Check to see if this is a flush
|
||||||
if (maxUpdates <= 0)
|
if (maxUpdates <= 0)
|
||||||
{
|
{
|
||||||
|
@ -3583,7 +3631,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
float avgTimeDilation = 1.0f;
|
float avgTimeDilation = 1.0f;
|
||||||
IEntityUpdate iupdate;
|
IEntityUpdate iupdate;
|
||||||
Int32 timeinqueue; // this is just debugging code & can be dropped later
|
Int32 timeinqueue; // this is just debugging code & can be dropped later
|
||||||
|
|
||||||
while (updatesThisCall < maxUpdates)
|
while (updatesThisCall < maxUpdates)
|
||||||
{
|
{
|
||||||
lock (m_entityUpdates.SyncRoot)
|
lock (m_entityUpdates.SyncRoot)
|
||||||
|
@ -3688,24 +3736,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if (update.Entity is ScenePresence)
|
if (update.Entity is ScenePresence)
|
||||||
{
|
{
|
||||||
objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
|
objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
|
||||||
|
objectUpdates.Value.Add(update);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
|
objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
|
||||||
|
objectUpdates.Value.Add(update);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!canUseImproved)
|
else if (!canUseImproved)
|
||||||
{
|
{
|
||||||
compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
|
compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
|
||||||
|
compressedUpdates.Value.Add(update);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
|
if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
|
||||||
|
{
|
||||||
// Self updates go into a special list
|
// Self updates go into a special list
|
||||||
terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
|
terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
|
||||||
|
terseAgentUpdates.Value.Add(update);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
// Everything else goes here
|
// Everything else goes here
|
||||||
terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
|
terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
|
||||||
|
terseUpdates.Value.Add(update);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Block Construction
|
#endregion Block Construction
|
||||||
|
@ -3713,28 +3770,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
|
|
||||||
#region Packet Sending
|
#region Packet Sending
|
||||||
|
|
||||||
//const float TIME_DILATION = 1.0f;
|
|
||||||
|
|
||||||
|
|
||||||
ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
|
ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
|
||||||
|
|
||||||
if (terseAgentUpdateBlocks.IsValueCreated)
|
if (terseAgentUpdateBlocks.IsValueCreated)
|
||||||
{
|
{
|
||||||
List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
|
List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
|
||||||
|
|
||||||
ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
|
ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
|
||||||
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
|
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
|
||||||
packet.RegionData.TimeDilation = timeDilation;
|
packet.RegionData.TimeDilation = timeDilation;
|
||||||
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
|
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
|
||||||
|
|
||||||
for (int i = 0; i < blocks.Count; i++)
|
for (int i = 0; i < blocks.Count; i++)
|
||||||
packet.ObjectData[i] = blocks[i];
|
packet.ObjectData[i] = blocks[i];
|
||||||
|
// If any of the packets created from this call go unacknowledged, all of the updates will be resent
|
||||||
|
OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); });
|
||||||
OutPacket(packet, ThrottleOutPacketType.Unknown, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (objectUpdateBlocks.IsValueCreated)
|
if (objectUpdateBlocks.IsValueCreated)
|
||||||
{
|
{
|
||||||
List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
|
List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
|
||||||
|
@ -3746,8 +3798,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
for (int i = 0; i < blocks.Count; i++)
|
for (int i = 0; i < blocks.Count; i++)
|
||||||
packet.ObjectData[i] = blocks[i];
|
packet.ObjectData[i] = blocks[i];
|
||||||
|
// If any of the packets created from this call go unacknowledged, all of the updates will be resent
|
||||||
OutPacket(packet, ThrottleOutPacketType.Task, true);
|
OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compressedUpdateBlocks.IsValueCreated)
|
if (compressedUpdateBlocks.IsValueCreated)
|
||||||
|
@ -3761,10 +3813,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
for (int i = 0; i < blocks.Count; i++)
|
for (int i = 0; i < blocks.Count; i++)
|
||||||
packet.ObjectData[i] = blocks[i];
|
packet.ObjectData[i] = blocks[i];
|
||||||
|
// If any of the packets created from this call go unacknowledged, all of the updates will be resent
|
||||||
OutPacket(packet, ThrottleOutPacketType.Task, true);
|
OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (terseUpdateBlocks.IsValueCreated)
|
if (terseUpdateBlocks.IsValueCreated)
|
||||||
{
|
{
|
||||||
List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
|
List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
|
||||||
|
@ -3776,8 +3828,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
for (int i = 0; i < blocks.Count; i++)
|
for (int i = 0; i < blocks.Count; i++)
|
||||||
packet.ObjectData[i] = blocks[i];
|
packet.ObjectData[i] = blocks[i];
|
||||||
|
// If any of the packets created from this call go unacknowledged, all of the updates will be resent
|
||||||
OutPacket(packet, ThrottleOutPacketType.Task, true);
|
OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3969,7 +4021,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
SendFamilyProps = SendFamilyProps || update.SendFamilyProps;
|
SendFamilyProps = SendFamilyProps || update.SendFamilyProps;
|
||||||
SendObjectProps = SendObjectProps || update.SendObjectProps;
|
SendObjectProps = SendObjectProps || update.SendObjectProps;
|
||||||
Flags |= update.Flags;
|
// other properties may need to be updated by base class
|
||||||
|
base.Update(update);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3980,6 +4033,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false));
|
m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ResendPropertyUpdate(ObjectPropertyUpdate update)
|
||||||
|
{
|
||||||
|
uint priority = 0;
|
||||||
|
lock (m_entityProps.SyncRoot)
|
||||||
|
m_entityProps.Enqueue(priority, update);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResendPropertyUpdates(List<ObjectPropertyUpdate> updates, OutgoingPacket oPacket)
|
||||||
|
{
|
||||||
|
// m_log.WarnFormat("[CLIENT] resending object property {0}",updates[0].UpdateTime);
|
||||||
|
|
||||||
|
// Remove the update packet from the list of packets waiting for acknowledgement
|
||||||
|
// because we are requeuing the list of updates. They will be resent in new packets
|
||||||
|
// with the most recent state.
|
||||||
|
m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
|
||||||
|
|
||||||
|
// Count this as a resent packet since we are going to requeue all of the updates contained in it
|
||||||
|
Interlocked.Increment(ref m_udpClient.PacketsResent);
|
||||||
|
|
||||||
|
foreach (ObjectPropertyUpdate update in updates)
|
||||||
|
ResendPropertyUpdate(update);
|
||||||
|
}
|
||||||
|
|
||||||
public void SendObjectPropertiesReply(ISceneEntity entity)
|
public void SendObjectPropertiesReply(ISceneEntity entity)
|
||||||
{
|
{
|
||||||
uint priority = 0; // time based ordering only
|
uint priority = 0; // time based ordering only
|
||||||
|
@ -3995,6 +4071,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks =
|
OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks =
|
||||||
new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>();
|
new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>();
|
||||||
|
|
||||||
|
OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> familyUpdates =
|
||||||
|
new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
|
||||||
|
|
||||||
|
OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates =
|
||||||
|
new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
|
||||||
|
|
||||||
IEntityUpdate iupdate;
|
IEntityUpdate iupdate;
|
||||||
Int32 timeinqueue; // this is just debugging code & can be dropped later
|
Int32 timeinqueue; // this is just debugging code & can be dropped later
|
||||||
|
|
||||||
|
@ -4013,6 +4095,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
SceneObjectPart sop = (SceneObjectPart)update.Entity;
|
SceneObjectPart sop = (SceneObjectPart)update.Entity;
|
||||||
ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
|
ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
|
||||||
objectFamilyBlocks.Value.Add(objPropDB);
|
objectFamilyBlocks.Value.Add(objPropDB);
|
||||||
|
familyUpdates.Value.Add(update);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4023,6 +4106,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
SceneObjectPart sop = (SceneObjectPart)update.Entity;
|
SceneObjectPart sop = (SceneObjectPart)update.Entity;
|
||||||
ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
|
ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
|
||||||
objectPropertiesBlocks.Value.Add(objPropDB);
|
objectPropertiesBlocks.Value.Add(objPropDB);
|
||||||
|
propertyUpdates.Value.Add(update);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4030,12 +4114,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Int32 ppcnt = 0;
|
// Int32 ppcnt = 0;
|
||||||
Int32 pbcnt = 0;
|
// Int32 pbcnt = 0;
|
||||||
|
|
||||||
if (objectPropertiesBlocks.IsValueCreated)
|
if (objectPropertiesBlocks.IsValueCreated)
|
||||||
{
|
{
|
||||||
List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value;
|
List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value;
|
||||||
|
List<ObjectPropertyUpdate> updates = propertyUpdates.Value;
|
||||||
|
|
||||||
ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
|
ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
|
||||||
packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count];
|
packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count];
|
||||||
|
@ -4043,28 +4128,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
packet.ObjectData[i] = blocks[i];
|
packet.ObjectData[i] = blocks[i];
|
||||||
|
|
||||||
packet.Header.Zerocoded = true;
|
packet.Header.Zerocoded = true;
|
||||||
OutPacket(packet, ThrottleOutPacketType.Task, true);
|
|
||||||
|
|
||||||
pbcnt += blocks.Count;
|
// Pass in the delegate so that if this packet needs to be resent, we send the current properties
|
||||||
ppcnt++;
|
// of the object rather than the properties when the packet was created
|
||||||
|
OutPacket(packet, ThrottleOutPacketType.Task, true,
|
||||||
|
delegate(OutgoingPacket oPacket)
|
||||||
|
{
|
||||||
|
ResendPropertyUpdates(updates, oPacket);
|
||||||
|
});
|
||||||
|
|
||||||
|
// pbcnt += blocks.Count;
|
||||||
|
// ppcnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Int32 fpcnt = 0;
|
// Int32 fpcnt = 0;
|
||||||
Int32 fbcnt = 0;
|
// Int32 fbcnt = 0;
|
||||||
|
|
||||||
if (objectFamilyBlocks.IsValueCreated)
|
if (objectFamilyBlocks.IsValueCreated)
|
||||||
{
|
{
|
||||||
List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value;
|
List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value;
|
||||||
|
|
||||||
// ObjectPropertiesFamilyPacket objPropFamilyPack =
|
|
||||||
// (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
|
|
||||||
//
|
|
||||||
// objPropFamilyPack.ObjectData = new ObjectPropertiesFamilyPacket.ObjectDataBlock[blocks.Count];
|
|
||||||
// for (int i = 0; i < blocks.Count; i++)
|
|
||||||
// objPropFamilyPack.ObjectData[i] = blocks[i];
|
|
||||||
//
|
|
||||||
// OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task, true);
|
|
||||||
|
|
||||||
// one packet per object block... uggh...
|
// one packet per object block... uggh...
|
||||||
for (int i = 0; i < blocks.Count; i++)
|
for (int i = 0; i < blocks.Count; i++)
|
||||||
{
|
{
|
||||||
|
@ -4073,10 +4156,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
packet.ObjectData = blocks[i];
|
packet.ObjectData = blocks[i];
|
||||||
packet.Header.Zerocoded = true;
|
packet.Header.Zerocoded = true;
|
||||||
OutPacket(packet, ThrottleOutPacketType.Task);
|
|
||||||
|
|
||||||
fpcnt++;
|
// Pass in the delegate so that if this packet needs to be resent, we send the current properties
|
||||||
fbcnt++;
|
// of the object rather than the properties when the packet was created
|
||||||
|
List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
|
||||||
|
updates.Add(familyUpdates.Value[i]);
|
||||||
|
OutPacket(packet, ThrottleOutPacketType.Task, true,
|
||||||
|
delegate(OutgoingPacket oPacket)
|
||||||
|
{
|
||||||
|
ResendPropertyUpdates(updates, oPacket);
|
||||||
|
});
|
||||||
|
|
||||||
|
// fpcnt++;
|
||||||
|
// fbcnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4113,7 +4205,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop)
|
private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop)
|
||||||
{
|
{
|
||||||
//ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
|
//ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
|
||||||
|
@ -4764,7 +4856,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
data.RelativePosition.ToBytes(objectData, 0);
|
data.RelativePosition.ToBytes(objectData, 0);
|
||||||
data.Velocity.ToBytes(objectData, 12);
|
data.Velocity.ToBytes(objectData, 12);
|
||||||
data.Acceleration.ToBytes(objectData, 24);
|
data.Acceleration.ToBytes(objectData, 24);
|
||||||
data.RotationOffset.ToBytes(objectData, 36);
|
try
|
||||||
|
{
|
||||||
|
data.RotationOffset.ToBytes(objectData, 36);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.Warn("[LLClientView]: exception converting quaternion to bytes, using Quaternion.Identity. Exception: " + e.ToString());
|
||||||
|
OpenMetaverse.Quaternion.Identity.ToBytes(objectData, 36);
|
||||||
|
}
|
||||||
data.AngularVelocity.ToBytes(objectData, 48);
|
data.AngularVelocity.ToBytes(objectData, 48);
|
||||||
|
|
||||||
ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
|
ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
|
||||||
|
@ -11328,7 +11428,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public byte[] GetThrottlesPacked(float multiplier)
|
public byte[] GetThrottlesPacked(float multiplier)
|
||||||
{
|
{
|
||||||
return m_udpClient.GetThrottlesPacked();
|
return m_udpClient.GetThrottlesPacked(multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -11362,6 +11462,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// packets (the default), or false to disable splitting if the calling code
|
/// packets (the default), or false to disable splitting if the calling code
|
||||||
/// handles splitting manually</param>
|
/// handles splitting manually</param>
|
||||||
protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting)
|
protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting)
|
||||||
|
{
|
||||||
|
OutPacket(packet, throttlePacketType, doAutomaticSplitting, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is the starting point for sending a simulator packet out to the client
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="packet">Packet to send</param>
|
||||||
|
/// <param name="throttlePacketType">Throttling category for the packet</param>
|
||||||
|
/// <param name="doAutomaticSplitting">True to automatically split oversized
|
||||||
|
/// packets (the default), or false to disable splitting if the calling code
|
||||||
|
/// handles splitting manually</param>
|
||||||
|
/// <param name="method">The method to be called in the event this packet is reliable
|
||||||
|
/// and unacknowledged. The server will provide normal resend capability if you do not
|
||||||
|
/// provide your own method.</param>
|
||||||
|
protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
|
||||||
{
|
{
|
||||||
if (m_debugPacketLevel > 0)
|
if (m_debugPacketLevel > 0)
|
||||||
{
|
{
|
||||||
|
@ -11388,7 +11504,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type);
|
m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting);
|
m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AddMoney(int debit)
|
public bool AddMoney(int debit)
|
||||||
|
|
|
@ -135,7 +135,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
private int m_nextOnQueueEmpty = 1;
|
private int m_nextOnQueueEmpty = 1;
|
||||||
|
|
||||||
/// <summary>Throttle bucket for this agent's connection</summary>
|
/// <summary>Throttle bucket for this agent's connection</summary>
|
||||||
private readonly TokenBucket m_throttleClient;
|
private readonly AdaptiveTokenBucket m_throttleClient;
|
||||||
|
public AdaptiveTokenBucket FlowThrottle
|
||||||
|
{
|
||||||
|
get { return m_throttleClient; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Throttle bucket for this agent's connection</summary>
|
/// <summary>Throttle bucket for this agent's connection</summary>
|
||||||
private readonly TokenBucket m_throttleCategory;
|
private readonly TokenBucket m_throttleCategory;
|
||||||
/// <summary>Throttle buckets for each packet category</summary>
|
/// <summary>Throttle buckets for each packet category</summary>
|
||||||
|
@ -176,9 +181,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
m_maxRTO = maxRTO;
|
m_maxRTO = maxRTO;
|
||||||
|
|
||||||
// Create a token bucket throttle for this client that has the scene token bucket as a parent
|
// Create a token bucket throttle for this client that has the scene token bucket as a parent
|
||||||
m_throttleClient = new TokenBucket(parentThrottle, rates.TotalLimit);
|
m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled);
|
||||||
// Create a token bucket throttle for the total categary with the client bucket as a throttle
|
// Create a token bucket throttle for the total categary with the client bucket as a throttle
|
||||||
m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit);
|
m_throttleCategory = new TokenBucket(m_throttleClient, 0);
|
||||||
// Create an array of token buckets for this clients different throttle categories
|
// Create an array of token buckets for this clients different throttle categories
|
||||||
m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
|
m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
|
||||||
|
|
||||||
|
@ -189,7 +194,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// Initialize the packet outboxes, where packets sit while they are waiting for tokens
|
// Initialize the packet outboxes, where packets sit while they are waiting for tokens
|
||||||
m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
|
m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
|
||||||
// Initialize the token buckets that control the throttling for each category
|
// Initialize the token buckets that control the throttling for each category
|
||||||
m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetLimit(type));
|
m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default the retransmission timeout to three seconds
|
// Default the retransmission timeout to three seconds
|
||||||
|
@ -223,26 +228,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <returns>Information about the client connection</returns>
|
/// <returns>Information about the client connection</returns>
|
||||||
public ClientInfo GetClientInfo()
|
public ClientInfo GetClientInfo()
|
||||||
{
|
{
|
||||||
///<mic>
|
|
||||||
TokenBucket tb;
|
|
||||||
|
|
||||||
tb = m_throttleClient.Parent;
|
|
||||||
m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest,"ROOT");
|
|
||||||
|
|
||||||
tb = m_throttleClient;
|
|
||||||
m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CLIENT");
|
|
||||||
|
|
||||||
tb = m_throttleCategory;
|
|
||||||
m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CATEGORY");
|
|
||||||
|
|
||||||
for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
|
|
||||||
{
|
|
||||||
tb = m_throttleCategories[i];
|
|
||||||
m_log.WarnFormat("[TOKENS] {4} <{0}:{1}>: Actual={2},Requested={3}",AgentID,i,tb.DripRate,tb.RequestedDripRate," BUCKET");
|
|
||||||
}
|
|
||||||
|
|
||||||
///</mic>
|
|
||||||
|
|
||||||
// TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
|
// TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
|
||||||
// of pending and needed ACKs for every client every time some method wants information about
|
// of pending and needed ACKs for every client every time some method wants information about
|
||||||
// this connection is a recipe for poor performance
|
// this connection is a recipe for poor performance
|
||||||
|
@ -254,12 +239,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
|
info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
|
||||||
info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
|
info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
|
||||||
info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
|
info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
|
||||||
// info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
|
|
||||||
info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
|
info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
|
||||||
info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
|
info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
|
||||||
info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
|
info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
|
||||||
info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle +
|
info.totalThrottle = (int)m_throttleCategory.DripRate;
|
||||||
info.taskThrottle + info.assetThrottle + info.textureThrottle;
|
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
@ -346,8 +329,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
|
int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
|
||||||
// State is a subcategory of task that we allocate a percentage to
|
// State is a subcategory of task that we allocate a percentage to
|
||||||
int state = 0;
|
int state = 0;
|
||||||
// int state = (int)((float)task * STATE_TASK_PERCENTAGE);
|
|
||||||
// task -= state;
|
|
||||||
|
|
||||||
// Make sure none of the throttles are set below our packet MTU,
|
// Make sure none of the throttles are set below our packet MTU,
|
||||||
// otherwise a throttle could become permanently clogged
|
// otherwise a throttle could become permanently clogged
|
||||||
|
@ -358,19 +339,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
task = Math.Max(task, LLUDPServer.MTU);
|
task = Math.Max(task, LLUDPServer.MTU);
|
||||||
texture = Math.Max(texture, LLUDPServer.MTU);
|
texture = Math.Max(texture, LLUDPServer.MTU);
|
||||||
asset = Math.Max(asset, LLUDPServer.MTU);
|
asset = Math.Max(asset, LLUDPServer.MTU);
|
||||||
state = Math.Max(state, LLUDPServer.MTU);
|
|
||||||
|
|
||||||
int total = resend + land + wind + cloud + task + texture + asset + state;
|
//int total = resend + land + wind + cloud + task + texture + asset;
|
||||||
|
//m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
|
||||||
//m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}",
|
// AgentID, resend, land, wind, cloud, task, texture, asset, total);
|
||||||
// AgentID, resend, land, wind, cloud, task, texture, asset, state, total);
|
|
||||||
|
|
||||||
// Update the token buckets with new throttle values
|
// Update the token buckets with new throttle values
|
||||||
TokenBucket bucket;
|
TokenBucket bucket;
|
||||||
|
|
||||||
bucket = m_throttleCategory;
|
|
||||||
bucket.RequestedDripRate = total;
|
|
||||||
|
|
||||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
|
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
|
||||||
bucket.RequestedDripRate = resend;
|
bucket.RequestedDripRate = resend;
|
||||||
|
|
||||||
|
@ -399,22 +375,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
m_packedThrottles = null;
|
m_packedThrottles = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] GetThrottlesPacked()
|
public byte[] GetThrottlesPacked(float multiplier)
|
||||||
{
|
{
|
||||||
byte[] data = m_packedThrottles;
|
byte[] data = m_packedThrottles;
|
||||||
|
|
||||||
if (data == null)
|
if (data == null)
|
||||||
{
|
{
|
||||||
|
float rate;
|
||||||
|
|
||||||
data = new byte[7 * 4];
|
data = new byte[7 * 4];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate), 0, data, i, 4); i += 4;
|
// multiply by 8 to convert bytes back to bits
|
||||||
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate), 0, data, i, 4); i += 4;
|
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier;
|
||||||
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate), 0, data, i, 4); i += 4;
|
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
|
||||||
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate), 0, data, i, 4); i += 4;
|
|
||||||
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate), 0, data, i, 4); i += 4;
|
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier;
|
||||||
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate), 0, data, i, 4); i += 4;
|
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
|
||||||
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate), 0, data, i, 4); i += 4;
|
|
||||||
|
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * 8 * multiplier;
|
||||||
|
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
|
||||||
|
|
||||||
|
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * 8 * multiplier;
|
||||||
|
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
|
||||||
|
|
||||||
|
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * 8 * multiplier;
|
||||||
|
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
|
||||||
|
|
||||||
|
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * 8 * multiplier;
|
||||||
|
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
|
||||||
|
|
||||||
|
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * 8 * multiplier;
|
||||||
|
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
|
||||||
|
|
||||||
m_packedThrottles = data;
|
m_packedThrottles = data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,7 +297,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
delegate(IClientAPI client)
|
delegate(IClientAPI client)
|
||||||
{
|
{
|
||||||
if (client is LLClientView)
|
if (client is LLClientView)
|
||||||
SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
|
SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -309,7 +309,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
delegate(IClientAPI client)
|
delegate(IClientAPI client)
|
||||||
{
|
{
|
||||||
if (client is LLClientView)
|
if (client is LLClientView)
|
||||||
SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
|
SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -322,7 +322,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <param name="packet"></param>
|
/// <param name="packet"></param>
|
||||||
/// <param name="category"></param>
|
/// <param name="category"></param>
|
||||||
/// <param name="allowSplitting"></param>
|
/// <param name="allowSplitting"></param>
|
||||||
public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting)
|
public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method)
|
||||||
{
|
{
|
||||||
// CoarseLocationUpdate packets cannot be split in an automated way
|
// CoarseLocationUpdate packets cannot be split in an automated way
|
||||||
if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
|
if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
|
||||||
|
@ -339,13 +339,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
for (int i = 0; i < packetCount; i++)
|
for (int i = 0; i < packetCount; i++)
|
||||||
{
|
{
|
||||||
byte[] data = datas[i];
|
byte[] data = datas[i];
|
||||||
SendPacketData(udpClient, data, packet.Type, category);
|
SendPacketData(udpClient, data, packet.Type, category, method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
byte[] data = packet.ToBytes();
|
byte[] data = packet.ToBytes();
|
||||||
SendPacketData(udpClient, data, packet.Type, category);
|
SendPacketData(udpClient, data, packet.Type, category, method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +356,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <param name="data"></param>
|
/// <param name="data"></param>
|
||||||
/// <param name="type"></param>
|
/// <param name="type"></param>
|
||||||
/// <param name="category"></param>
|
/// <param name="category"></param>
|
||||||
public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category)
|
public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method)
|
||||||
{
|
{
|
||||||
int dataLength = data.Length;
|
int dataLength = data.Length;
|
||||||
bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
|
bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
|
||||||
|
@ -411,7 +411,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
#region Queue or Send
|
#region Queue or Send
|
||||||
|
|
||||||
OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);
|
OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
|
||||||
|
// If we were not provided a method for handling unacked, use the UDPServer default method
|
||||||
|
outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);
|
||||||
|
|
||||||
// If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
|
// If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
|
||||||
// continue to display the deleted object until relog. Therefore, we need to always queue a kill object
|
// continue to display the deleted object until relog. Therefore, we need to always queue a kill object
|
||||||
|
@ -445,7 +447,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
packet.Header.Reliable = false;
|
packet.Header.Reliable = false;
|
||||||
packet.Packets = blocks.ToArray();
|
packet.Packets = blocks.ToArray();
|
||||||
|
|
||||||
SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true);
|
SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,17 +460,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// We *could* get OldestUnacked, but it would hurt performance and not provide any benefit
|
// We *could* get OldestUnacked, but it would hurt performance and not provide any benefit
|
||||||
pc.PingID.OldestUnacked = 0;
|
pc.PingID.OldestUnacked = 0;
|
||||||
|
|
||||||
SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false);
|
SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CompletePing(LLUDPClient udpClient, byte pingID)
|
public void CompletePing(LLUDPClient udpClient, byte pingID)
|
||||||
{
|
{
|
||||||
CompletePingCheckPacket completePing = new CompletePingCheckPacket();
|
CompletePingCheckPacket completePing = new CompletePingCheckPacket();
|
||||||
completePing.PingID.PingID = pingID;
|
completePing.PingID.PingID = pingID;
|
||||||
SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false);
|
SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResendUnacked(LLUDPClient udpClient)
|
public void HandleUnacked(LLUDPClient udpClient)
|
||||||
{
|
{
|
||||||
if (!udpClient.IsConnected)
|
if (!udpClient.IsConnected)
|
||||||
return;
|
return;
|
||||||
|
@ -488,33 +490,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
if (expiredPackets != null)
|
if (expiredPackets != null)
|
||||||
{
|
{
|
||||||
//m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO);
|
//m_log.Debug("[LLUDPSERVER]: Handling " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO);
|
||||||
|
|
||||||
// Exponential backoff of the retransmission timeout
|
// Exponential backoff of the retransmission timeout
|
||||||
udpClient.BackoffRTO();
|
udpClient.BackoffRTO();
|
||||||
|
for (int i = 0; i < expiredPackets.Count; ++i)
|
||||||
// Resend packets
|
expiredPackets[i].UnackedMethod(expiredPackets[i]);
|
||||||
for (int i = 0; i < expiredPackets.Count; i++)
|
|
||||||
{
|
|
||||||
OutgoingPacket outgoingPacket = expiredPackets[i];
|
|
||||||
|
|
||||||
//m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
|
|
||||||
// outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount);
|
|
||||||
|
|
||||||
// Set the resent flag
|
|
||||||
outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
|
|
||||||
outgoingPacket.Category = ThrottleOutPacketType.Resend;
|
|
||||||
|
|
||||||
// Bump up the resend count on this packet
|
|
||||||
Interlocked.Increment(ref outgoingPacket.ResendCount);
|
|
||||||
|
|
||||||
// Requeue or resend the packet
|
|
||||||
if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false))
|
|
||||||
SendPacketFinal(outgoingPacket);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ResendUnacked(OutgoingPacket outgoingPacket)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
|
||||||
|
// outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount);
|
||||||
|
|
||||||
|
// Set the resent flag
|
||||||
|
outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
|
||||||
|
outgoingPacket.Category = ThrottleOutPacketType.Resend;
|
||||||
|
|
||||||
|
// Bump up the resend count on this packet
|
||||||
|
Interlocked.Increment(ref outgoingPacket.ResendCount);
|
||||||
|
|
||||||
|
// Requeue or resend the packet
|
||||||
|
if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false))
|
||||||
|
SendPacketFinal(outgoingPacket);
|
||||||
|
}
|
||||||
|
|
||||||
public void Flush(LLUDPClient udpClient)
|
public void Flush(LLUDPClient udpClient)
|
||||||
{
|
{
|
||||||
// FIXME: Implement?
|
// FIXME: Implement?
|
||||||
|
@ -672,7 +672,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if (packet.Header.AppendedAcks && packet.Header.AckList != null)
|
if (packet.Header.AppendedAcks && packet.Header.AckList != null)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < packet.Header.AckList.Length; i++)
|
for (int i = 0; i < packet.Header.AckList.Length; i++)
|
||||||
udpClient.NeedAcks.Remove(packet.Header.AckList[i], now, packet.Header.Resent);
|
udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle PacketAck packets
|
// Handle PacketAck packets
|
||||||
|
@ -681,7 +681,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
PacketAckPacket ackPacket = (PacketAckPacket)packet;
|
PacketAckPacket ackPacket = (PacketAckPacket)packet;
|
||||||
|
|
||||||
for (int i = 0; i < ackPacket.Packets.Length; i++)
|
for (int i = 0; i < ackPacket.Packets.Length; i++)
|
||||||
udpClient.NeedAcks.Remove(ackPacket.Packets[i].ID, now, packet.Header.Resent);
|
udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
|
||||||
|
|
||||||
// We don't need to do anything else with PacketAck packets
|
// We don't need to do anything else with PacketAck packets
|
||||||
return;
|
return;
|
||||||
|
@ -1096,7 +1096,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if (udpClient.IsConnected)
|
if (udpClient.IsConnected)
|
||||||
{
|
{
|
||||||
if (m_resendUnacked)
|
if (m_resendUnacked)
|
||||||
ResendUnacked(udpClient);
|
HandleUnacked(udpClient);
|
||||||
|
|
||||||
if (m_sendAcks)
|
if (m_sendAcks)
|
||||||
SendAcks(udpClient);
|
SendAcks(udpClient);
|
||||||
|
@ -1152,7 +1152,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
nticksUnack++;
|
nticksUnack++;
|
||||||
watch2.Start();
|
watch2.Start();
|
||||||
|
|
||||||
ResendUnacked(udpClient);
|
HandleUnacked(udpClient);
|
||||||
|
|
||||||
watch2.Stop();
|
watch2.Stop();
|
||||||
avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
|
avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
|
||||||
|
|
|
@ -31,6 +31,8 @@ using OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Region.ClientStack.LindenUDP
|
namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public delegate void UnackedPacketMethod(OutgoingPacket oPacket);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Holds a reference to the <seealso cref="LLUDPClient"/> this packet is
|
/// Holds a reference to the <seealso cref="LLUDPClient"/> this packet is
|
||||||
/// destined for, along with the serialized packet data, sequence number
|
/// destined for, along with the serialized packet data, sequence number
|
||||||
|
@ -52,6 +54,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
public int TickCount;
|
public int TickCount;
|
||||||
/// <summary>Category this packet belongs to</summary>
|
/// <summary>Category this packet belongs to</summary>
|
||||||
public ThrottleOutPacketType Category;
|
public ThrottleOutPacketType Category;
|
||||||
|
/// <summary>The delegate to be called if this packet is determined to be unacknowledged</summary>
|
||||||
|
public UnackedPacketMethod UnackedMethod;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
|
@ -60,11 +64,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <param name="buffer">Serialized packet data. If the flags or sequence number
|
/// <param name="buffer">Serialized packet data. If the flags or sequence number
|
||||||
/// need to be updated, they will be injected directly into this binary buffer</param>
|
/// need to be updated, they will be injected directly into this binary buffer</param>
|
||||||
/// <param name="category">Throttling category for this packet</param>
|
/// <param name="category">Throttling category for this packet</param>
|
||||||
public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category)
|
public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method)
|
||||||
{
|
{
|
||||||
Client = client;
|
Client = client;
|
||||||
Buffer = buffer;
|
Buffer = buffer;
|
||||||
Category = category;
|
Category = category;
|
||||||
|
UnackedMethod = method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,30 +52,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
public int Texture;
|
public int Texture;
|
||||||
/// <summary>Drip rate for asset packets</summary>
|
/// <summary>Drip rate for asset packets</summary>
|
||||||
public int Asset;
|
public int Asset;
|
||||||
/// <summary>Drip rate for state packets</summary>
|
|
||||||
public int State;
|
|
||||||
/// <summary>Drip rate for the parent token bucket</summary>
|
/// <summary>Drip rate for the parent token bucket</summary>
|
||||||
public int Total;
|
public int Total;
|
||||||
|
|
||||||
/// <summary>Maximum burst rate for resent packets</summary>
|
/// <summary>Flag used to enable adaptive throttles</summary>
|
||||||
public int ResendLimit;
|
public bool AdaptiveThrottlesEnabled;
|
||||||
/// <summary>Maximum burst rate for land packets</summary>
|
|
||||||
public int LandLimit;
|
|
||||||
/// <summary>Maximum burst rate for wind packets</summary>
|
|
||||||
public int WindLimit;
|
|
||||||
/// <summary>Maximum burst rate for cloud packets</summary>
|
|
||||||
public int CloudLimit;
|
|
||||||
/// <summary>Maximum burst rate for task (state and transaction) packets</summary>
|
|
||||||
public int TaskLimit;
|
|
||||||
/// <summary>Maximum burst rate for texture packets</summary>
|
|
||||||
public int TextureLimit;
|
|
||||||
/// <summary>Maximum burst rate for asset packets</summary>
|
|
||||||
public int AssetLimit;
|
|
||||||
/// <summary>Maximum burst rate for state packets</summary>
|
|
||||||
public int StateLimit;
|
|
||||||
/// <summary>Burst rate for the parent token bucket</summary>
|
|
||||||
public int TotalLimit;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -86,26 +69,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"];
|
IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"];
|
||||||
|
|
||||||
Resend = throttleConfig.GetInt("resend_default", 12500);
|
Resend = throttleConfig.GetInt("resend_default", 6625);
|
||||||
Land = throttleConfig.GetInt("land_default", 1000);
|
Land = throttleConfig.GetInt("land_default", 9125);
|
||||||
Wind = throttleConfig.GetInt("wind_default", 1000);
|
Wind = throttleConfig.GetInt("wind_default", 1750);
|
||||||
Cloud = throttleConfig.GetInt("cloud_default", 1000);
|
Cloud = throttleConfig.GetInt("cloud_default", 1750);
|
||||||
Task = throttleConfig.GetInt("task_default", 1000);
|
Task = throttleConfig.GetInt("task_default", 18500);
|
||||||
Texture = throttleConfig.GetInt("texture_default", 1000);
|
Texture = throttleConfig.GetInt("texture_default", 18500);
|
||||||
Asset = throttleConfig.GetInt("asset_default", 1000);
|
Asset = throttleConfig.GetInt("asset_default", 10500);
|
||||||
State = throttleConfig.GetInt("state_default", 1000);
|
|
||||||
|
|
||||||
ResendLimit = throttleConfig.GetInt("resend_limit", 18750);
|
|
||||||
LandLimit = throttleConfig.GetInt("land_limit", 29750);
|
|
||||||
WindLimit = throttleConfig.GetInt("wind_limit", 18750);
|
|
||||||
CloudLimit = throttleConfig.GetInt("cloud_limit", 18750);
|
|
||||||
TaskLimit = throttleConfig.GetInt("task_limit", 18750);
|
|
||||||
TextureLimit = throttleConfig.GetInt("texture_limit", 55750);
|
|
||||||
AssetLimit = throttleConfig.GetInt("asset_limit", 27500);
|
|
||||||
StateLimit = throttleConfig.GetInt("state_limit", 37000);
|
|
||||||
|
|
||||||
Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
|
Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
|
||||||
TotalLimit = Total;
|
|
||||||
|
AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
catch (Exception) { }
|
||||||
}
|
}
|
||||||
|
@ -128,34 +102,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
return Texture;
|
return Texture;
|
||||||
case ThrottleOutPacketType.Asset:
|
case ThrottleOutPacketType.Asset:
|
||||||
return Asset;
|
return Asset;
|
||||||
case ThrottleOutPacketType.State:
|
|
||||||
return State;
|
|
||||||
case ThrottleOutPacketType.Unknown:
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetLimit(ThrottleOutPacketType type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case ThrottleOutPacketType.Resend:
|
|
||||||
return ResendLimit;
|
|
||||||
case ThrottleOutPacketType.Land:
|
|
||||||
return LandLimit;
|
|
||||||
case ThrottleOutPacketType.Wind:
|
|
||||||
return WindLimit;
|
|
||||||
case ThrottleOutPacketType.Cloud:
|
|
||||||
return CloudLimit;
|
|
||||||
case ThrottleOutPacketType.Task:
|
|
||||||
return TaskLimit;
|
|
||||||
case ThrottleOutPacketType.Texture:
|
|
||||||
return TextureLimit;
|
|
||||||
case ThrottleOutPacketType.Asset:
|
|
||||||
return AssetLimit;
|
|
||||||
case ThrottleOutPacketType.State:
|
|
||||||
return StateLimit;
|
|
||||||
case ThrottleOutPacketType.Unknown:
|
case ThrottleOutPacketType.Unknown:
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -29,6 +29,8 @@ using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
using log4net;
|
using log4net;
|
||||||
|
|
||||||
namespace OpenSim.Region.ClientStack.LindenUDP
|
namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
@ -48,31 +50,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// Number of ticks (ms) per quantum, drip rate and max burst
|
/// Number of ticks (ms) per quantum, drip rate and max burst
|
||||||
/// are defined over this interval.
|
/// are defined over this interval.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const Int32 m_ticksPerQuantum = 1000;
|
protected const Int32 m_ticksPerQuantum = 1000;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is the number of quantums worth of packets that can
|
/// This is the number of quantums worth of packets that can
|
||||||
/// be accommodated during a burst
|
/// be accommodated during a burst
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const Double m_quantumsPerBurst = 1.5;
|
protected const Double m_quantumsPerBurst = 1.5;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const Int32 m_minimumDripRate = 1400;
|
protected const Int32 m_minimumDripRate = 1400;
|
||||||
|
|
||||||
/// <summary>Time of the last drip, in system ticks</summary>
|
/// <summary>Time of the last drip, in system ticks</summary>
|
||||||
private Int32 m_lastDrip;
|
protected Int32 m_lastDrip;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The number of bytes that can be sent at this moment. This is the
|
/// The number of bytes that can be sent at this moment. This is the
|
||||||
/// current number of tokens in the bucket
|
/// current number of tokens in the bucket
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Int64 m_tokenCount;
|
protected Int64 m_tokenCount;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Map of children buckets and their requested maximum burst rate
|
/// Map of children buckets and their requested maximum burst rate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>();
|
protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>();
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
|
|
||||||
|
@ -81,7 +83,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// parent. The parent bucket will limit the aggregate bandwidth of all
|
/// parent. The parent bucket will limit the aggregate bandwidth of all
|
||||||
/// of its children buckets
|
/// of its children buckets
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private TokenBucket m_parent;
|
protected TokenBucket m_parent;
|
||||||
public TokenBucket Parent
|
public TokenBucket Parent
|
||||||
{
|
{
|
||||||
get { return m_parent; }
|
get { return m_parent; }
|
||||||
|
@ -93,7 +95,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// of tokens that can accumulate in the bucket at any one time. This
|
/// of tokens that can accumulate in the bucket at any one time. This
|
||||||
/// also sets the total request for leaf nodes
|
/// also sets the total request for leaf nodes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Int64 m_burstRate;
|
protected Int64 m_burstRate;
|
||||||
public Int64 RequestedBurstRate
|
public Int64 RequestedBurstRate
|
||||||
{
|
{
|
||||||
get { return m_burstRate; }
|
get { return m_burstRate; }
|
||||||
|
@ -118,8 +120,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <remarks>Tokens are added to the bucket any time
|
/// <remarks>Tokens are added to the bucket any time
|
||||||
/// <seealso cref="RemoveTokens"/> is called, at the granularity of
|
/// <seealso cref="RemoveTokens"/> is called, at the granularity of
|
||||||
/// the system tick interval (typically around 15-22ms)</remarks>
|
/// the system tick interval (typically around 15-22ms)</remarks>
|
||||||
private Int64 m_dripRate;
|
protected Int64 m_dripRate;
|
||||||
public Int64 RequestedDripRate
|
public virtual Int64 RequestedDripRate
|
||||||
{
|
{
|
||||||
get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
|
get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
|
||||||
set {
|
set {
|
||||||
|
@ -131,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Int64 DripRate
|
public virtual Int64 DripRate
|
||||||
{
|
{
|
||||||
get {
|
get {
|
||||||
if (m_parent == null)
|
if (m_parent == null)
|
||||||
|
@ -149,7 +151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// The current total of the requested maximum burst rates of
|
/// The current total of the requested maximum burst rates of
|
||||||
/// this bucket's children buckets.
|
/// this bucket's children buckets.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Int64 m_totalDripRequest;
|
protected Int64 m_totalDripRequest;
|
||||||
public Int64 TotalDripRequest
|
public Int64 TotalDripRequest
|
||||||
{
|
{
|
||||||
get { return m_totalDripRequest; }
|
get { return m_totalDripRequest; }
|
||||||
|
@ -177,7 +179,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
RequestedDripRate = dripRate;
|
RequestedDripRate = dripRate;
|
||||||
// TotalDripRequest = dripRate; // this will be overwritten when a child node registers
|
// TotalDripRequest = dripRate; // this will be overwritten when a child node registers
|
||||||
// MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst);
|
// MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst);
|
||||||
m_lastDrip = Environment.TickCount & Int32.MaxValue;
|
m_lastDrip = Util.EnvironmentTickCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Constructor
|
#endregion Constructor
|
||||||
|
@ -189,7 +191,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// hierarchy. However, if any of the parents is over-booked, then
|
/// hierarchy. However, if any of the parents is over-booked, then
|
||||||
/// the modifier will be less than 1.
|
/// the modifier will be less than 1.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private double DripRateModifier()
|
protected double DripRateModifier()
|
||||||
{
|
{
|
||||||
Int64 driprate = DripRate;
|
Int64 driprate = DripRate;
|
||||||
return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest;
|
return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest;
|
||||||
|
@ -197,7 +199,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private double BurstRateModifier()
|
protected double BurstRateModifier()
|
||||||
{
|
{
|
||||||
// for now... burst rate is always m_quantumsPerBurst (constant)
|
// for now... burst rate is always m_quantumsPerBurst (constant)
|
||||||
// larger than drip rate so the ratio of burst requests is the
|
// larger than drip rate so the ratio of burst requests is the
|
||||||
|
@ -211,12 +213,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void RegisterRequest(TokenBucket child, Int64 request)
|
public void RegisterRequest(TokenBucket child, Int64 request)
|
||||||
{
|
{
|
||||||
m_children[child] = request;
|
lock (m_children)
|
||||||
// m_totalDripRequest = m_children.Values.Sum();
|
{
|
||||||
|
m_children[child] = request;
|
||||||
|
// m_totalDripRequest = m_children.Values.Sum();
|
||||||
|
|
||||||
m_totalDripRequest = 0;
|
m_totalDripRequest = 0;
|
||||||
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
|
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
|
||||||
m_totalDripRequest += cref.Value;
|
m_totalDripRequest += cref.Value;
|
||||||
|
}
|
||||||
|
|
||||||
// Pass the new values up to the parent
|
// Pass the new values up to the parent
|
||||||
if (m_parent != null)
|
if (m_parent != null)
|
||||||
|
@ -229,12 +234,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void UnregisterRequest(TokenBucket child)
|
public void UnregisterRequest(TokenBucket child)
|
||||||
{
|
{
|
||||||
m_children.Remove(child);
|
lock (m_children)
|
||||||
// m_totalDripRequest = m_children.Values.Sum();
|
{
|
||||||
|
m_children.Remove(child);
|
||||||
|
// m_totalDripRequest = m_children.Values.Sum();
|
||||||
|
|
||||||
m_totalDripRequest = 0;
|
m_totalDripRequest = 0;
|
||||||
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
|
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
|
||||||
m_totalDripRequest += cref.Value;
|
m_totalDripRequest += cref.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Pass the new values up to the parent
|
// Pass the new values up to the parent
|
||||||
if (m_parent != null)
|
if (m_parent != null)
|
||||||
|
@ -268,7 +277,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// Deposit tokens into the bucket from a child bucket that did
|
/// Deposit tokens into the bucket from a child bucket that did
|
||||||
/// not use all of its available tokens
|
/// not use all of its available tokens
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void Deposit(Int64 count)
|
protected void Deposit(Int64 count)
|
||||||
{
|
{
|
||||||
m_tokenCount += count;
|
m_tokenCount += count;
|
||||||
|
|
||||||
|
@ -285,7 +294,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// call to Drip
|
/// call to Drip
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if tokens were added to the bucket, otherwise false</returns>
|
/// <returns>True if tokens were added to the bucket, otherwise false</returns>
|
||||||
private void Drip()
|
protected void Drip()
|
||||||
{
|
{
|
||||||
// This should never happen... means we are a leaf node and were created
|
// This should never happen... means we are a leaf node and were created
|
||||||
// with no drip rate...
|
// with no drip rate...
|
||||||
|
@ -297,10 +306,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
// Determine the interval over which we are adding tokens, never add
|
// Determine the interval over which we are adding tokens, never add
|
||||||
// more than a single quantum of tokens
|
// more than a single quantum of tokens
|
||||||
Int32 now = Environment.TickCount & Int32.MaxValue;
|
Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum);
|
||||||
Int32 deltaMS = Math.Min(now - m_lastDrip, m_ticksPerQuantum);
|
m_lastDrip = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
m_lastDrip = now;
|
|
||||||
|
|
||||||
// This can be 0 in the very unusual case that the timer wrapped
|
// This can be 0 in the very unusual case that the timer wrapped
|
||||||
// It can be 0 if we try add tokens at a sub-tick rate
|
// It can be 0 if we try add tokens at a sub-tick rate
|
||||||
|
@ -310,4 +317,77 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
Deposit(deltaMS * DripRate / m_ticksPerQuantum);
|
Deposit(deltaMS * DripRate / m_ticksPerQuantum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class AdaptiveTokenBucket : TokenBucket
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The minimum rate for flow control. Minimum drip rate is one
|
||||||
|
/// packet per second. Open the throttle to 15 packets per second
|
||||||
|
/// or about 160kbps.
|
||||||
|
/// </summary>
|
||||||
|
protected const Int64 m_minimumFlow = m_minimumDripRate * 15;
|
||||||
|
|
||||||
|
// <summary>
|
||||||
|
// The maximum rate for flow control. Drip rate can never be
|
||||||
|
// greater than this.
|
||||||
|
// </summary>
|
||||||
|
protected Int64 m_maxDripRate = 0;
|
||||||
|
protected Int64 MaxDripRate
|
||||||
|
{
|
||||||
|
get { return (m_maxDripRate == 0 ? m_totalDripRequest : m_maxDripRate); }
|
||||||
|
set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool m_enabled = false;
|
||||||
|
|
||||||
|
// <summary>
|
||||||
|
//
|
||||||
|
// </summary>
|
||||||
|
public virtual Int64 AdjustedDripRate
|
||||||
|
{
|
||||||
|
get { return m_dripRate; }
|
||||||
|
set {
|
||||||
|
m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value,m_minimumFlow,MaxDripRate);
|
||||||
|
m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst);
|
||||||
|
if (m_parent != null)
|
||||||
|
m_parent.RegisterRequest(this,m_dripRate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// <summary>
|
||||||
|
//
|
||||||
|
// </summary>
|
||||||
|
public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate, bool enabled) : base(parent,maxDripRate)
|
||||||
|
{
|
||||||
|
m_enabled = enabled;
|
||||||
|
|
||||||
|
if (m_enabled)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[TOKENBUCKET] Adaptive throttle enabled");
|
||||||
|
MaxDripRate = maxDripRate;
|
||||||
|
AdjustedDripRate = m_minimumFlow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// <summary>
|
||||||
|
//
|
||||||
|
// </summary>
|
||||||
|
public void ExpirePackets(Int32 count)
|
||||||
|
{
|
||||||
|
// m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count);
|
||||||
|
if (m_enabled)
|
||||||
|
AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count));
|
||||||
|
}
|
||||||
|
|
||||||
|
// <summary>
|
||||||
|
//
|
||||||
|
// </summary>
|
||||||
|
public void AcknowledgePackets(Int32 count)
|
||||||
|
{
|
||||||
|
if (m_enabled)
|
||||||
|
AdjustedDripRate = AdjustedDripRate + count;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <summary>Holds packets that need to be added to the unacknowledged list</summary>
|
/// <summary>Holds packets that need to be added to the unacknowledged list</summary>
|
||||||
private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>();
|
private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>();
|
||||||
/// <summary>Holds information about pending acknowledgements</summary>
|
/// <summary>Holds information about pending acknowledgements</summary>
|
||||||
private LocklessQueue<PendingAck> m_pendingRemoves = new LocklessQueue<PendingAck>();
|
private LocklessQueue<PendingAck> m_pendingAcknowledgements = new LocklessQueue<PendingAck>();
|
||||||
|
/// <summary>Holds information about pending removals</summary>
|
||||||
|
private LocklessQueue<uint> m_pendingRemoves = new LocklessQueue<uint>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add an unacked packet to the collection
|
/// Add an unacked packet to the collection
|
||||||
|
@ -83,15 +85,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Marks a packet as acknowledged
|
/// Marks a packet as acknowledged
|
||||||
|
/// This method is used when an acknowledgement is received from the network for a previously
|
||||||
|
/// sent packet. Effects of removal this way are to update unacked byte count, adjust RTT
|
||||||
|
/// and increase throttle to the coresponding client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sequenceNumber">Sequence number of the packet to
|
/// <param name="sequenceNumber">Sequence number of the packet to
|
||||||
/// acknowledge</param>
|
/// acknowledge</param>
|
||||||
/// <param name="currentTime">Current value of Environment.TickCount</param>
|
/// <param name="currentTime">Current value of Environment.TickCount</param>
|
||||||
/// <remarks>This does not immediately acknowledge the packet, it only
|
/// <remarks>This does not immediately acknowledge the packet, it only
|
||||||
/// queues the ack so it can be handled in a thread-safe way later</remarks>
|
/// queues the ack so it can be handled in a thread-safe way later</remarks>
|
||||||
public void Remove(uint sequenceNumber, int currentTime, bool fromResend)
|
public void Acknowledge(uint sequenceNumber, int currentTime, bool fromResend)
|
||||||
{
|
{
|
||||||
m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend));
|
m_pendingAcknowledgements.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Marks a packet as no longer needing acknowledgement without a received acknowledgement.
|
||||||
|
/// This method is called when a packet expires and we no longer need an acknowledgement.
|
||||||
|
/// When some reliable packet types expire, they are handled in a way other than simply
|
||||||
|
/// resending them. The only effect of removal this way is to update unacked byte count.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sequenceNumber">Sequence number of the packet to
|
||||||
|
/// acknowledge</param>
|
||||||
|
/// <remarks>The does not immediately remove the packet, it only queues the removal
|
||||||
|
/// so it can be handled in a thread safe way later</remarks>
|
||||||
|
public void Remove(uint sequenceNumber)
|
||||||
|
{
|
||||||
|
m_pendingRemoves.Enqueue(sequenceNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -130,6 +150,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// is actually sent out again
|
// is actually sent out again
|
||||||
packet.TickCount = 0;
|
packet.TickCount = 0;
|
||||||
|
|
||||||
|
// As with other network applications, assume that an expired packet is
|
||||||
|
// an indication of some network problem, slow transmission
|
||||||
|
packet.Client.FlowThrottle.ExpirePackets(1);
|
||||||
|
|
||||||
expiredPackets.Add(packet);
|
expiredPackets.Add(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,29 +171,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
m_packets[pendingAdd.SequenceNumber] = pendingAdd;
|
m_packets[pendingAdd.SequenceNumber] = pendingAdd;
|
||||||
|
|
||||||
// Process all the pending removes, including updating statistics and round-trip times
|
// Process all the pending removes, including updating statistics and round-trip times
|
||||||
PendingAck pendingRemove;
|
PendingAck pendingAcknowledgement;
|
||||||
OutgoingPacket ackedPacket;
|
while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement))
|
||||||
while (m_pendingRemoves.TryDequeue(out pendingRemove))
|
|
||||||
{
|
{
|
||||||
if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket))
|
OutgoingPacket ackedPacket;
|
||||||
|
if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket))
|
||||||
{
|
{
|
||||||
if (ackedPacket != null)
|
if (ackedPacket != null)
|
||||||
{
|
{
|
||||||
m_packets.Remove(pendingRemove.SequenceNumber);
|
m_packets.Remove(pendingAcknowledgement.SequenceNumber);
|
||||||
|
|
||||||
|
// As with other network applications, assume that an acknowledged packet is an
|
||||||
|
// indication that the network can handle a little more load, speed up the transmission
|
||||||
|
ackedPacket.Client.FlowThrottle.AcknowledgePackets(ackedPacket.Buffer.DataLength);
|
||||||
|
|
||||||
// Update stats
|
// Update stats
|
||||||
Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
|
Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
|
||||||
|
|
||||||
if (!pendingRemove.FromResend)
|
if (!pendingAcknowledgement.FromResend)
|
||||||
{
|
{
|
||||||
// Calculate the round-trip time for this packet and its ACK
|
// Calculate the round-trip time for this packet and its ACK
|
||||||
int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount;
|
int rtt = pendingAcknowledgement.RemoveTime - ackedPacket.TickCount;
|
||||||
if (rtt > 0)
|
if (rtt > 0)
|
||||||
ackedPacket.Client.UpdateRoundTrip(rtt);
|
ackedPacket.Client.UpdateRoundTrip(rtt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint pendingRemove;
|
||||||
|
while(m_pendingRemoves.TryDequeue(out pendingRemove))
|
||||||
|
{
|
||||||
|
OutgoingPacket removedPacket;
|
||||||
|
if (m_packets.TryGetValue(pendingRemove, out removedPacket))
|
||||||
|
{
|
||||||
|
if (removedPacket != null)
|
||||||
|
{
|
||||||
|
m_packets.Remove(pendingRemove);
|
||||||
|
|
||||||
|
// Update stats
|
||||||
|
Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AgentAssetTransactions
|
public class AgentAssetTransactions
|
||||||
{
|
{
|
||||||
// private static readonly ILog m_log = LogManager.GetLogger(
|
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
// MethodBase.GetCurrentMethod().DeclaringType);
|
|
||||||
|
|
||||||
// Fields
|
// Fields
|
||||||
private bool m_dumpAssetsToFile;
|
private bool m_dumpAssetsToFile;
|
||||||
|
@ -149,6 +148,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
||||||
|
|
||||||
if (asset != null)
|
if (asset != null)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}",
|
||||||
|
// item.Name, part.Name, transactionID);
|
||||||
|
|
||||||
asset.FullID = UUID.Random();
|
asset.FullID = UUID.Random();
|
||||||
asset.Name = item.Name;
|
asset.Name = item.Name;
|
||||||
asset.Description = item.Description;
|
asset.Description = item.Description;
|
||||||
|
@ -156,8 +159,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
||||||
item.AssetID = asset.FullID;
|
item.AssetID = asset.FullID;
|
||||||
|
|
||||||
m_Scene.AssetService.Store(asset);
|
m_Scene.AssetService.Store(asset);
|
||||||
|
|
||||||
part.Inventory.UpdateInventoryItem(item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
|
||||||
if (meshConfig == null)
|
if (meshConfig == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_enabled = meshConfig.GetBoolean("ColladaMesh", true);
|
m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddRegion(Scene pScene)
|
public void AddRegion(Scene pScene)
|
||||||
|
|
|
@ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
|
||||||
if (meshConfig == null)
|
if (meshConfig == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_enabled = meshConfig.GetBoolean("ColladaMesh", true);
|
m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddRegion(Scene pScene)
|
public void AddRegion(Scene pScene)
|
||||||
|
|
|
@ -182,9 +182,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
||||||
public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
|
public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
|
||||||
{
|
{
|
||||||
InventoryCollection invCol = m_InventoryService.GetFolderContent(userID, folderID);
|
InventoryCollection invCol = m_InventoryService.GetFolderContent(userID, folderID);
|
||||||
if (UserManager != null)
|
Util.FireAndForget(delegate
|
||||||
foreach (InventoryItemBase item in invCol.Items)
|
{
|
||||||
UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
|
if (UserManager != null)
|
||||||
|
foreach (InventoryItemBase item in invCol.Items)
|
||||||
|
UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
|
||||||
|
});
|
||||||
|
|
||||||
return invCol;
|
return invCol;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,10 +46,22 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
||||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private bool m_Enabled = false;
|
private bool m_Enabled = false;
|
||||||
private bool m_Initialized = false;
|
private Scene m_Scene;
|
||||||
// private Scene m_Scene;
|
|
||||||
private XInventoryServicesConnector m_RemoteConnector;
|
private XInventoryServicesConnector m_RemoteConnector;
|
||||||
|
|
||||||
|
private IUserManagement m_UserManager;
|
||||||
|
private IUserManagement UserManager
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_UserManager == null)
|
||||||
|
{
|
||||||
|
m_UserManager = m_Scene.RequestModuleInterface<IUserManagement>();
|
||||||
|
}
|
||||||
|
return m_UserManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Type ReplaceableInterface
|
public Type ReplaceableInterface
|
||||||
{
|
{
|
||||||
get { return null; }
|
get { return null; }
|
||||||
|
@ -114,12 +126,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
||||||
if (!m_Enabled)
|
if (!m_Enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!m_Initialized)
|
|
||||||
{
|
|
||||||
m_Initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
scene.RegisterModuleInterface<IInventoryService>(this);
|
scene.RegisterModuleInterface<IInventoryService>(this);
|
||||||
|
|
||||||
|
if (m_Scene == null)
|
||||||
|
m_Scene = scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveRegion(Scene scene)
|
public void RemoveRegion(Scene scene)
|
||||||
|
@ -173,7 +183,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
||||||
|
|
||||||
public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
|
public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
|
||||||
{
|
{
|
||||||
return m_RemoteConnector.GetFolderContent(userID, folderID);
|
InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID);
|
||||||
|
Util.FireAndForget(delegate
|
||||||
|
{
|
||||||
|
if (UserManager != null)
|
||||||
|
foreach (InventoryItemBase item in invCol.Items)
|
||||||
|
UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
|
||||||
|
});
|
||||||
|
|
||||||
|
return invCol;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
|
public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
|
||||||
|
|
|
@ -125,7 +125,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
|
||||||
else
|
else
|
||||||
Scene.RegionInfo.RegionSettings.AllowLandResell = true;
|
Scene.RegionInfo.RegionSettings.AllowLandResell = true;
|
||||||
|
|
||||||
Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents;
|
if((byte)maxAgents <= Scene.RegionInfo.AgentCapacity)
|
||||||
|
Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents;
|
||||||
|
else
|
||||||
|
Scene.RegionInfo.RegionSettings.AgentLimit = Scene.RegionInfo.AgentCapacity;
|
||||||
|
|
||||||
Scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor;
|
Scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor;
|
||||||
|
|
||||||
|
|
|
@ -119,16 +119,40 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity)
|
private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity)
|
||||||
{
|
{
|
||||||
return 1;
|
// And anything attached to this avatar gets top priority as well
|
||||||
|
if (entity is SceneObjectPart)
|
||||||
|
{
|
||||||
|
SceneObjectPart sop = (SceneObjectPart)entity;
|
||||||
|
if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PriorityQueue.NumberOfImmediateQueues; // first queue past the immediate queues
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity)
|
private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity)
|
||||||
{
|
{
|
||||||
|
// And anything attached to this avatar gets top priority as well
|
||||||
|
if (entity is SceneObjectPart)
|
||||||
|
{
|
||||||
|
SceneObjectPart sop = (SceneObjectPart)entity;
|
||||||
|
if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return ComputeDistancePriority(client,entity,false);
|
return ComputeDistancePriority(client,entity,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
|
private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
|
||||||
{
|
{
|
||||||
|
// And anything attached to this avatar gets top priority as well
|
||||||
|
if (entity is SceneObjectPart)
|
||||||
|
{
|
||||||
|
SceneObjectPart sop = (SceneObjectPart)entity;
|
||||||
|
if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return ComputeDistancePriority(client,entity,true);
|
return ComputeDistancePriority(client,entity,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,18 +165,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
if (!presence.IsChildAgent)
|
if (!presence.IsChildAgent)
|
||||||
{
|
{
|
||||||
|
// All avatars other than our own go into pqueue 1
|
||||||
|
if (entity is ScenePresence)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (entity is SceneObjectPart)
|
if (entity is SceneObjectPart)
|
||||||
{
|
{
|
||||||
|
// Attachments are high priority,
|
||||||
|
if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
|
||||||
|
return 1;
|
||||||
|
|
||||||
// Non physical prims are lower priority than physical prims
|
// Non physical prims are lower priority than physical prims
|
||||||
PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
|
PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
|
||||||
if (physActor == null || !physActor.IsPhysical)
|
if (physActor == null || !physActor.IsPhysical)
|
||||||
pqueue++;
|
pqueue++;
|
||||||
|
|
||||||
// Attachments are high priority,
|
|
||||||
// MIC: shouldn't these already be in the highest priority queue already
|
|
||||||
// since their root position is same as the avatars?
|
|
||||||
if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
|
|
||||||
pqueue = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,7 +198,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
// m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId);
|
// m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId);
|
||||||
// throw new InvalidOperationException("Prioritization agent not defined");
|
// throw new InvalidOperationException("Prioritization agent not defined");
|
||||||
return Int32.MaxValue;
|
return PriorityQueue.NumberOfQueues - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use group position for child prims, since we are putting child prims in
|
// Use group position for child prims, since we are putting child prims in
|
||||||
|
@ -197,8 +223,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
// And convert the distance to a priority queue, this computation gives queues
|
// And convert the distance to a priority queue, this computation gives queues
|
||||||
// at 10, 20, 40, 80, 160, 320, 640, and 1280m
|
// at 10, 20, 40, 80, 160, 320, 640, and 1280m
|
||||||
uint pqueue = 1;
|
uint pqueue = PriorityQueue.NumberOfImmediateQueues;
|
||||||
for (int i = 0; i < 8; i++)
|
uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues;
|
||||||
|
|
||||||
|
for (int i = 0; i < queues - 1; i++)
|
||||||
{
|
{
|
||||||
if (distance < 10 * Math.Pow(2.0,i))
|
if (distance < 10 * Math.Pow(2.0,i))
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1430,6 +1430,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
else // Updating existing item with new perms etc
|
else // Updating existing item with new perms etc
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()",
|
||||||
|
// currentItem.Name, part.Name);
|
||||||
|
|
||||||
IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>();
|
IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>();
|
||||||
if (agentTransactions != null)
|
if (agentTransactions != null)
|
||||||
{
|
{
|
||||||
|
@ -2039,6 +2043,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (rot != null)
|
if (rot != null)
|
||||||
group.UpdateGroupRotationR((Quaternion)rot);
|
group.UpdateGroupRotationR((Quaternion)rot);
|
||||||
|
|
||||||
|
// TODO: This needs to be refactored with the similar code in
|
||||||
|
// SceneGraph.AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel)
|
||||||
|
// possibly by allowing this method to take a null rotation.
|
||||||
|
if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero)
|
||||||
|
group.RootPart.ApplyImpulse((vel * group.GetMass()), false);
|
||||||
|
|
||||||
// We can only call this after adding the scene object, since the scene object references the scene
|
// We can only call this after adding the scene object, since the scene object references the scene
|
||||||
// to find out if scripts should be activated at all.
|
// to find out if scripts should be activated at all.
|
||||||
group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
|
group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
|
||||||
|
|
|
@ -3665,6 +3665,15 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int num = m_sceneGraph.GetNumberOfScenePresences();
|
||||||
|
|
||||||
|
if (num >= RegionInfo.RegionSettings.AgentLimit)
|
||||||
|
{
|
||||||
|
if (!Permissions.IsAdministrator(cAgentData.AgentID))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
|
ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
|
||||||
|
|
||||||
if (childAgentUpdate != null)
|
if (childAgentUpdate != null)
|
||||||
|
@ -4966,6 +4975,17 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// child agent creation, thereby emulating the SL behavior.
|
// child agent creation, thereby emulating the SL behavior.
|
||||||
public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
|
public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
|
||||||
{
|
{
|
||||||
|
int num = m_sceneGraph.GetNumberOfScenePresences();
|
||||||
|
|
||||||
|
if (num >= RegionInfo.RegionSettings.AgentLimit)
|
||||||
|
{
|
||||||
|
if (!Permissions.IsAdministrator(agentID))
|
||||||
|
{
|
||||||
|
reason = "The region is full";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
reason = String.Empty;
|
reason = String.Empty;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -800,6 +800,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return m_scenePresenceArray;
|
return m_scenePresenceArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int GetNumberOfScenePresences()
|
||||||
|
{
|
||||||
|
return m_scenePresenceArray.Count;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Request a scene presence by UUID. Fast, indexed lookup.
|
/// Request a scene presence by UUID. Fast, indexed lookup.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -81,16 +81,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add an inventory item to a prim in this group.
|
/// Add an inventory item from a user's inventory to a prim in this scene object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="remoteClient"></param>
|
/// <param name="remoteClient">The client adding the item.</param>
|
||||||
/// <param name="localID"></param>
|
/// <param name="localID">The local ID of the part receiving the add.</param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item">The user inventory item being added.</param>
|
||||||
/// <param name="copyItemID">The item UUID that should be used by the new item.</param>
|
/// <param name="copyItemID">The item UUID that should be used by the new item.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool AddInventoryItem(IClientAPI remoteClient, uint localID,
|
public bool AddInventoryItem(IClientAPI remoteClient, uint localID,
|
||||||
InventoryItemBase item, UUID copyItemID)
|
InventoryItemBase item, UUID copyItemID)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}",
|
||||||
|
// item.Name, remoteClient.Name, localID);
|
||||||
|
|
||||||
UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID;
|
UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID;
|
||||||
|
|
||||||
SceneObjectPart part = GetChildPart(localID);
|
SceneObjectPart part = GetChildPart(localID);
|
||||||
|
@ -132,15 +136,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
taskItem.GroupPermissions = item.GroupPermissions;
|
taskItem.GroupPermissions = item.GroupPermissions;
|
||||||
taskItem.NextPermissions = item.NextPermissions;
|
taskItem.NextPermissions = item.NextPermissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
taskItem.Flags = item.Flags;
|
taskItem.Flags = item.Flags;
|
||||||
|
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[PRIM INVENTORY]: Flags are 0x{0:X} for item {1} added to part {2} by {3}",
|
||||||
|
// taskItem.Flags, taskItem.Name, localID, remoteClient.Name);
|
||||||
|
|
||||||
// TODO: These are pending addition of those fields to TaskInventoryItem
|
// TODO: These are pending addition of those fields to TaskInventoryItem
|
||||||
// taskItem.SalePrice = item.SalePrice;
|
// taskItem.SalePrice = item.SalePrice;
|
||||||
// taskItem.SaleType = item.SaleType;
|
// taskItem.SaleType = item.SaleType;
|
||||||
taskItem.CreationDate = (uint)item.CreationDate;
|
taskItem.CreationDate = (uint)item.CreationDate;
|
||||||
|
|
||||||
bool addFromAllowedDrop = false;
|
bool addFromAllowedDrop = false;
|
||||||
if (remoteClient!=null)
|
if (remoteClient != null)
|
||||||
{
|
{
|
||||||
addFromAllowedDrop = remoteClient.AgentId != part.OwnerID;
|
addFromAllowedDrop = remoteClient.AgentId != part.OwnerID;
|
||||||
}
|
}
|
||||||
|
|
|
@ -693,8 +693,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
TaskInventoryItem it = GetInventoryItem(item.ItemID);
|
TaskInventoryItem it = GetInventoryItem(item.ItemID);
|
||||||
if (it != null)
|
if (it != null)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
|
||||||
|
|
||||||
item.ParentID = m_part.UUID;
|
item.ParentID = m_part.UUID;
|
||||||
item.ParentPartID = m_part.UUID;
|
item.ParentPartID = m_part.UUID;
|
||||||
|
|
||||||
|
@ -711,14 +712,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_items[item.ItemID] = item;
|
m_items[item.ItemID] = item;
|
||||||
m_inventorySerial++;
|
m_inventorySerial++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fireScriptEvents)
|
if (fireScriptEvents)
|
||||||
m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
|
m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
|
||||||
|
|
||||||
if (considerChanged)
|
if (considerChanged)
|
||||||
{
|
{
|
||||||
HasInventoryChanged = true;
|
HasInventoryChanged = true;
|
||||||
m_part.ParentGroup.HasGroupChanged = true;
|
m_part.ParentGroup.HasGroupChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -2340,12 +2340,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
#region Update Client(s)
|
#region Update Client(s)
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a location update to the client connected to this scenePresence
|
/// Sends a location update to the client connected to this scenePresence
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="remoteClient"></param>
|
/// <param name="remoteClient"></param>
|
||||||
public void SendTerseUpdateToClient(IClientAPI remoteClient)
|
public void SendTerseUpdateToClient(IClientAPI remoteClient)
|
||||||
{
|
{
|
||||||
|
|
||||||
// If the client is inactive, it's getting its updates from another
|
// If the client is inactive, it's getting its updates from another
|
||||||
// server.
|
// server.
|
||||||
if (remoteClient.IsActive)
|
if (remoteClient.IsActive)
|
||||||
|
@ -2358,8 +2360,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
//m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
|
//m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
|
||||||
|
|
||||||
remoteClient.SendPrimUpdate(
|
remoteClient.SendPrimUpdate(
|
||||||
this,
|
this,
|
||||||
PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
|
PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
|
||||||
| PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
|
| PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
|
||||||
|
|
||||||
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
|
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
|
||||||
|
@ -2367,16 +2369,31 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// vars to support reduced update frequency when velocity is unchanged
|
||||||
|
private Vector3 lastVelocitySentToAllClients = Vector3.Zero;
|
||||||
|
private int lastTerseUpdateToAllClientsTick = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send a location/velocity/accelleration update to all agents in scene
|
/// Send a location/velocity/accelleration update to all agents in scene
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SendTerseUpdateToAllClients()
|
public void SendTerseUpdateToAllClients()
|
||||||
{
|
{
|
||||||
m_perfMonMS = Util.EnvironmentTickCount();
|
int currentTick = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
m_scene.ForEachClient(SendTerseUpdateToClient);
|
|
||||||
|
|
||||||
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
|
// decrease update frequency when avatar is moving but velocity is not changing
|
||||||
|
if (m_velocity.Length() < 0.01f
|
||||||
|
|| Vector3.Distance(lastVelocitySentToAllClients, m_velocity) > 0.01f
|
||||||
|
|| currentTick - lastTerseUpdateToAllClientsTick > 1500)
|
||||||
|
{
|
||||||
|
m_perfMonMS = currentTick;
|
||||||
|
lastVelocitySentToAllClients = m_velocity;
|
||||||
|
lastTerseUpdateToAllClientsTick = currentTick;
|
||||||
|
|
||||||
|
m_scene.ForEachClient(SendTerseUpdateToClient);
|
||||||
|
|
||||||
|
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
|
public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
|
||||||
|
@ -2632,18 +2649,17 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
cadu.GroupAccess = 0;
|
cadu.GroupAccess = 0;
|
||||||
cadu.Position = AbsolutePosition;
|
cadu.Position = AbsolutePosition;
|
||||||
cadu.regionHandle = m_rootRegionHandle;
|
cadu.regionHandle = m_rootRegionHandle;
|
||||||
float multiplier = 1;
|
|
||||||
int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
|
|
||||||
if (innacurateNeighbors != 0)
|
|
||||||
{
|
|
||||||
multiplier = 1f / (float)innacurateNeighbors;
|
|
||||||
}
|
|
||||||
if (multiplier <= 0f)
|
|
||||||
{
|
|
||||||
multiplier = 0.25f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
|
// Throttles
|
||||||
|
float multiplier = 1;
|
||||||
|
int childRegions = m_knownChildRegions.Count;
|
||||||
|
if (childRegions != 0)
|
||||||
|
multiplier = 1f / childRegions;
|
||||||
|
|
||||||
|
// Minimum throttle for a child region is 1/4 of the root region throttle
|
||||||
|
if (multiplier <= 0.25f)
|
||||||
|
multiplier = 0.25f;
|
||||||
|
|
||||||
cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
|
cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
|
||||||
cadu.Velocity = Velocity;
|
cadu.Velocity = Velocity;
|
||||||
|
|
||||||
|
@ -3039,16 +3055,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
// Throttles
|
// Throttles
|
||||||
float multiplier = 1;
|
float multiplier = 1;
|
||||||
int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
|
int childRegions = m_knownChildRegions.Count;
|
||||||
if (innacurateNeighbors != 0)
|
if (childRegions != 0)
|
||||||
{
|
multiplier = 1f / childRegions;
|
||||||
multiplier = 1f / innacurateNeighbors;
|
|
||||||
}
|
// Minimum throttle for a child region is 1/4 of the root region throttle
|
||||||
if (multiplier <= 0f)
|
if (multiplier <= 0.25f)
|
||||||
{
|
|
||||||
multiplier = 0.25f;
|
multiplier = 0.25f;
|
||||||
}
|
|
||||||
//m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
|
|
||||||
cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
|
cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
|
||||||
|
|
||||||
cAgent.HeadRotation = m_headrotation;
|
cAgent.HeadRotation = m_headrotation;
|
||||||
|
@ -3271,10 +3285,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
m_updateflag = true;
|
m_updateflag = true;
|
||||||
|
|
||||||
// The magic constant 0.95f seems to make walking feel less jerky,
|
Velocity = force;
|
||||||
// probably because it hackishly accounts for the overall latency of
|
|
||||||
// these Velocity updates -- Diva
|
|
||||||
Velocity = force * .95F;
|
|
||||||
|
|
||||||
m_forceToApply = null;
|
m_forceToApply = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,29 +117,40 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
||||||
{
|
{
|
||||||
using (XmlTextReader reader = new XmlTextReader(sr))
|
using (XmlTextReader reader = new XmlTextReader(sr))
|
||||||
{
|
{
|
||||||
reader.Read();
|
try
|
||||||
if (reader.Name != "CoalescedObject")
|
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
reader.Read();
|
||||||
// "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false",
|
if (reader.Name != "CoalescedObject")
|
||||||
// reader.Name);
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false",
|
||||||
|
// reader.Name);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
coa = new CoalescedSceneObjects(UUID.Zero);
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "CoalescedObject")
|
||||||
|
{
|
||||||
|
if (reader.Name == "SceneObjectGroup")
|
||||||
|
{
|
||||||
|
string soXml = reader.ReadOuterXml();
|
||||||
|
coa.Add(SceneObjectSerializer.FromOriginalXmlFormat(soXml));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.ReadEndElement(); // CoalescedObject
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml failed with {0} {1}",
|
||||||
|
e.Message, e.StackTrace);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
coa = new CoalescedSceneObjects(UUID.Zero);
|
|
||||||
reader.Read();
|
|
||||||
|
|
||||||
while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "CoalescedObject")
|
|
||||||
{
|
|
||||||
if (reader.Name == "SceneObjectGroup")
|
|
||||||
{
|
|
||||||
string soXml = reader.ReadOuterXml();
|
|
||||||
coa.Add(SceneObjectSerializer.FromOriginalXmlFormat(soXml));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.ReadEndElement(); // CoalescedObject
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -298,10 +298,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (null != objectAsset)
|
if (null != objectAsset)
|
||||||
{
|
{
|
||||||
string xml = Utils.BytesToString(objectAsset.Data);
|
string xml = Utils.BytesToString(objectAsset.Data);
|
||||||
SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml);
|
|
||||||
|
CoalescedSceneObjects coa;
|
||||||
if (null != sog)
|
if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa))
|
||||||
GatherAssetUuids(sog, assetUuids);
|
{
|
||||||
|
foreach (SceneObjectGroup sog in coa.Objects)
|
||||||
|
GatherAssetUuids(sog, assetUuids);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml);
|
||||||
|
|
||||||
|
if (null != sog)
|
||||||
|
GatherAssetUuids(sog, assetUuids);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,14 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
||||||
lock (m_scenes)
|
lock (m_scenes)
|
||||||
m_scenes[scene.RegionInfo.RegionID] = scene;
|
m_scenes[scene.RegionInfo.RegionID] = scene;
|
||||||
|
|
||||||
|
scene.AddCommand(
|
||||||
|
this, "show pqueues",
|
||||||
|
"show pqueues [full]",
|
||||||
|
"Show priority queue data for each client",
|
||||||
|
"Without the 'full' option, only root agents are shown."
|
||||||
|
+ " With the 'full' option child agents are also shown.",
|
||||||
|
ShowPQueuesReport);
|
||||||
|
|
||||||
scene.AddCommand(
|
scene.AddCommand(
|
||||||
this, "show queues",
|
this, "show queues",
|
||||||
"show queues [full]",
|
"show queues [full]",
|
||||||
|
@ -119,6 +127,11 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
||||||
// m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
|
// m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void ShowPQueuesReport(string module, string[] cmd)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output(GetPQueuesReport(cmd));
|
||||||
|
}
|
||||||
|
|
||||||
protected void ShowQueuesReport(string module, string[] cmd)
|
protected void ShowQueuesReport(string module, string[] cmd)
|
||||||
{
|
{
|
||||||
MainConsole.Instance.Output(GetQueuesReport(cmd));
|
MainConsole.Instance.Output(GetQueuesReport(cmd));
|
||||||
|
@ -155,6 +168,80 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
||||||
"");
|
"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate UDP Queue data report for each client
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="showParams"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected string GetPQueuesReport(string[] showParams)
|
||||||
|
{
|
||||||
|
bool showChildren = false;
|
||||||
|
string pname = "";
|
||||||
|
|
||||||
|
if (showParams.Length > 2 && showParams[2] == "full")
|
||||||
|
showChildren = true;
|
||||||
|
else if (showParams.Length > 3)
|
||||||
|
pname = showParams[2] + " " + showParams[3];
|
||||||
|
|
||||||
|
StringBuilder report = new StringBuilder();
|
||||||
|
|
||||||
|
int columnPadding = 2;
|
||||||
|
int maxNameLength = 18;
|
||||||
|
int maxRegionNameLength = 14;
|
||||||
|
int maxTypeLength = 4;
|
||||||
|
int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding;
|
||||||
|
|
||||||
|
report.Append(GetColumnEntry("User", maxNameLength, columnPadding));
|
||||||
|
report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding));
|
||||||
|
report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding));
|
||||||
|
|
||||||
|
report.AppendFormat(
|
||||||
|
"{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7} {10,7} {11,7}\n",
|
||||||
|
"Pri 0",
|
||||||
|
"Pri 1",
|
||||||
|
"Pri 2",
|
||||||
|
"Pri 3",
|
||||||
|
"Pri 4",
|
||||||
|
"Pri 5",
|
||||||
|
"Pri 6",
|
||||||
|
"Pri 7",
|
||||||
|
"Pri 8",
|
||||||
|
"Pri 9",
|
||||||
|
"Pri 10",
|
||||||
|
"Pri 11");
|
||||||
|
|
||||||
|
lock (m_scenes)
|
||||||
|
{
|
||||||
|
foreach (Scene scene in m_scenes.Values)
|
||||||
|
{
|
||||||
|
scene.ForEachClient(
|
||||||
|
delegate(IClientAPI client)
|
||||||
|
{
|
||||||
|
if (client is LLClientView)
|
||||||
|
{
|
||||||
|
bool isChild = scene.PresenceChildStatus(client.AgentId);
|
||||||
|
if (isChild && !showChildren)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string name = client.Name;
|
||||||
|
if (pname != "" && name != pname)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string regionName = scene.RegionInfo.RegionName;
|
||||||
|
|
||||||
|
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
|
||||||
|
report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
|
||||||
|
report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
|
||||||
|
report.AppendLine(((LLClientView)client).EntityUpdateQueue.ToString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return report.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generate UDP Queue data report for each client
|
/// Generate UDP Queue data report for each client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -163,10 +250,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
||||||
protected string GetQueuesReport(string[] showParams)
|
protected string GetQueuesReport(string[] showParams)
|
||||||
{
|
{
|
||||||
bool showChildren = false;
|
bool showChildren = false;
|
||||||
|
string pname = "";
|
||||||
|
|
||||||
if (showParams.Length > 2 && showParams[2] == "full")
|
if (showParams.Length > 2 && showParams[2] == "full")
|
||||||
showChildren = true;
|
showChildren = true;
|
||||||
|
else if (showParams.Length > 3)
|
||||||
|
pname = showParams[2] + " " + showParams[3];
|
||||||
|
|
||||||
StringBuilder report = new StringBuilder();
|
StringBuilder report = new StringBuilder();
|
||||||
|
|
||||||
int columnPadding = 2;
|
int columnPadding = 2;
|
||||||
|
@ -224,6 +314,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string name = client.Name;
|
string name = client.Name;
|
||||||
|
if (pname != "" && name != pname)
|
||||||
|
return;
|
||||||
|
|
||||||
string regionName = scene.RegionInfo.RegionName;
|
string regionName = scene.RegionInfo.RegionName;
|
||||||
|
|
||||||
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
|
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
|
||||||
|
@ -249,10 +342,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
||||||
protected string GetThrottlesReport(string[] showParams)
|
protected string GetThrottlesReport(string[] showParams)
|
||||||
{
|
{
|
||||||
bool showChildren = false;
|
bool showChildren = false;
|
||||||
|
string pname = "";
|
||||||
|
|
||||||
if (showParams.Length > 2 && showParams[2] == "full")
|
if (showParams.Length > 2 && showParams[2] == "full")
|
||||||
showChildren = true;
|
showChildren = true;
|
||||||
|
else if (showParams.Length > 3)
|
||||||
|
pname = showParams[2] + " " + showParams[3];
|
||||||
|
|
||||||
StringBuilder report = new StringBuilder();
|
StringBuilder report = new StringBuilder();
|
||||||
|
|
||||||
int columnPadding = 2;
|
int columnPadding = 2;
|
||||||
|
@ -302,7 +398,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
||||||
if (client is LLClientView)
|
if (client is LLClientView)
|
||||||
{
|
{
|
||||||
LLClientView llClient = client as LLClientView;
|
LLClientView llClient = client as LLClientView;
|
||||||
|
|
||||||
if (firstClient)
|
if (firstClient)
|
||||||
{
|
{
|
||||||
report.AppendLine(GetServerThrottlesReport(llClient.UDPServer));
|
report.AppendLine(GetServerThrottlesReport(llClient.UDPServer));
|
||||||
|
@ -314,6 +410,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string name = client.Name;
|
string name = client.Name;
|
||||||
|
if (pname != "" && name != pname)
|
||||||
|
return;
|
||||||
|
|
||||||
string regionName = scene.RegionInfo.RegionName;
|
string regionName = scene.RegionInfo.RegionName;
|
||||||
|
|
||||||
LLUDPClient llUdpClient = llClient.UDPClient;
|
LLUDPClient llUdpClient = llClient.UDPClient;
|
||||||
|
@ -352,7 +451,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
||||||
int maxRegionNameLength = 14;
|
int maxRegionNameLength = 14;
|
||||||
int maxTypeLength = 4;
|
int maxTypeLength = 4;
|
||||||
|
|
||||||
string name = "SERVER AGENT LIMITS";
|
string name = "SERVER AGENT RATES";
|
||||||
|
|
||||||
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
|
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
|
||||||
report.Append(GetColumnEntry("-", maxRegionNameLength, columnPadding));
|
report.Append(GetColumnEntry("-", maxRegionNameLength, columnPadding));
|
||||||
|
@ -362,13 +461,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
||||||
report.AppendFormat(
|
report.AppendFormat(
|
||||||
"{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}",
|
"{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}",
|
||||||
(throttleRates.Total * 8) / 1000,
|
(throttleRates.Total * 8) / 1000,
|
||||||
(throttleRates.ResendLimit * 8) / 1000,
|
(throttleRates.Resend * 8) / 1000,
|
||||||
(throttleRates.LandLimit * 8) / 1000,
|
(throttleRates.Land * 8) / 1000,
|
||||||
(throttleRates.WindLimit * 8) / 1000,
|
(throttleRates.Wind * 8) / 1000,
|
||||||
(throttleRates.CloudLimit * 8) / 1000,
|
(throttleRates.Cloud * 8) / 1000,
|
||||||
(throttleRates.TaskLimit * 8) / 1000,
|
(throttleRates.Task * 8) / 1000,
|
||||||
(throttleRates.TextureLimit * 8) / 1000,
|
(throttleRates.Texture * 8) / 1000,
|
||||||
(throttleRates.AssetLimit * 8) / 1000);
|
(throttleRates.Asset * 8) / 1000);
|
||||||
|
|
||||||
return report.ToString();
|
return report.ToString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
|
|
||||||
if (serviceDll == String.Empty)
|
if (serviceDll == String.Empty)
|
||||||
{
|
{
|
||||||
m_log.Error("[FreeSwitchVoice]: No LocalServiceModule named in section FreeSwitchVoice");
|
m_log.Error("[FreeSwitchVoice]: No LocalServiceModule named in section FreeSwitchVoice. Not starting.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,8 +143,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
if (String.IsNullOrEmpty(m_freeSwitchRealm) ||
|
if (String.IsNullOrEmpty(m_freeSwitchRealm) ||
|
||||||
String.IsNullOrEmpty(m_freeSwitchAPIPrefix))
|
String.IsNullOrEmpty(m_freeSwitchAPIPrefix))
|
||||||
{
|
{
|
||||||
m_log.Error("[FreeSwitchVoice] plugin mis-configured");
|
m_log.Error("[FreeSwitchVoice]: Freeswitch service mis-configured. Not starting.");
|
||||||
m_log.Info("[FreeSwitchVoice] plugin disabled: incomplete configuration");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,24 +163,24 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
// String.Format("{0}/viv_get_prelogin.php", m_freeSwitchAPIPrefix), FreeSwitchSLVoiceGetPreloginHTTPHandler);
|
// String.Format("{0}/viv_get_prelogin.php", m_freeSwitchAPIPrefix), FreeSwitchSLVoiceGetPreloginHTTPHandler);
|
||||||
// MainServer.Instance.AddStreamHandler(h);
|
// MainServer.Instance.AddStreamHandler(h);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_signin.php", m_freeSwitchAPIPrefix),
|
MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_signin.php", m_freeSwitchAPIPrefix),
|
||||||
FreeSwitchSLVoiceSigninHTTPHandler);
|
FreeSwitchSLVoiceSigninHTTPHandler);
|
||||||
|
|
||||||
MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_buddy.php", m_freeSwitchAPIPrefix),
|
MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_buddy.php", m_freeSwitchAPIPrefix),
|
||||||
FreeSwitchSLVoiceBuddyHTTPHandler);
|
FreeSwitchSLVoiceBuddyHTTPHandler);
|
||||||
|
|
||||||
|
MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_watcher.php", m_freeSwitchAPIPrefix),
|
||||||
|
FreeSwitchSLVoiceWatcherHTTPHandler);
|
||||||
|
|
||||||
m_log.InfoFormat("[FreeSwitchVoice] using FreeSwitch server {0}", m_freeSwitchRealm);
|
m_log.InfoFormat("[FreeSwitchVoice]: using FreeSwitch server {0}", m_freeSwitchRealm);
|
||||||
|
|
||||||
m_Enabled = true;
|
m_Enabled = true;
|
||||||
|
|
||||||
m_log.Info("[FreeSwitchVoice] plugin enabled");
|
m_log.Info("[FreeSwitchVoice]: plugin enabled");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat("[FreeSwitchVoice] plugin initialization failed: {0}", e.Message);
|
m_log.ErrorFormat("[FreeSwitchVoice]: plugin initialization failed: {0} {1}", e.Message, e.StackTrace);
|
||||||
m_log.DebugFormat("[FreeSwitchVoice] plugin initialization failed: {0}", e.ToString());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +239,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
{
|
{
|
||||||
if (m_Enabled)
|
if (m_Enabled)
|
||||||
{
|
{
|
||||||
m_log.Info("[FreeSwitchVoice] registering IVoiceModule with the scene");
|
m_log.Info("[FreeSwitchVoice]: registering IVoiceModule with the scene");
|
||||||
|
|
||||||
// register the voice interface for this module, so the script engine can call us
|
// register the voice interface for this module, so the script engine can call us
|
||||||
scene.RegisterModuleInterface<IVoiceModule>(this);
|
scene.RegisterModuleInterface<IVoiceModule>(this);
|
||||||
|
@ -302,7 +301,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
// </summary>
|
// </summary>
|
||||||
public void OnRegisterCaps(Scene scene, UUID agentID, Caps caps)
|
public void OnRegisterCaps(Scene scene, UUID agentID, Caps caps)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[FreeSwitchVoice] OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
|
m_log.DebugFormat(
|
||||||
|
"[FreeSwitchVoice]: OnRegisterCaps() called with agentID {0} caps {1} in scene {2}",
|
||||||
|
agentID, caps, scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
string capsBase = "/CAPS/" + caps.CapsObjectPath;
|
string capsBase = "/CAPS/" + caps.CapsObjectPath;
|
||||||
caps.RegisterHandler("ProvisionVoiceAccountRequest",
|
caps.RegisterHandler("ProvisionVoiceAccountRequest",
|
||||||
|
@ -344,6 +345,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
public string ProvisionVoiceAccountRequest(Scene scene, string request, string path, string param,
|
public string ProvisionVoiceAccountRequest(Scene scene, string request, string path, string param,
|
||||||
UUID agentID, Caps caps)
|
UUID agentID, Caps caps)
|
||||||
{
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[FreeSwitchVoice][PROVISIONVOICE]: ProvisionVoiceAccountRequest() request: {0}, path: {1}, param: {2}", request, path, param);
|
||||||
|
|
||||||
ScenePresence avatar = scene.GetScenePresence(agentID);
|
ScenePresence avatar = scene.GetScenePresence(agentID);
|
||||||
if (avatar == null)
|
if (avatar == null)
|
||||||
{
|
{
|
||||||
|
@ -357,9 +361,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
|
|
||||||
// request, path, param);
|
|
||||||
|
|
||||||
//XmlElement resp;
|
//XmlElement resp;
|
||||||
string agentname = "x" + Convert.ToBase64String(agentID.GetBytes());
|
string agentname = "x" + Convert.ToBase64String(agentID.GetBytes());
|
||||||
string password = "1234";//temp hack//new UUID(Guid.NewGuid()).ToString().Replace('-','Z').Substring(0,16);
|
string password = "1234";//temp hack//new UUID(Guid.NewGuid()).ToString().Replace('-','Z').Substring(0,16);
|
||||||
|
@ -390,7 +391,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
|
|
||||||
string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
|
string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
|
||||||
|
|
||||||
m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r);
|
// m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -416,6 +417,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
public string ParcelVoiceInfoRequest(Scene scene, string request, string path, string param,
|
public string ParcelVoiceInfoRequest(Scene scene, string request, string path, string param,
|
||||||
UUID agentID, Caps caps)
|
UUID agentID, Caps caps)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[FreeSwitchVoice][PARCELVOICE]: ParcelVoiceInfoRequest() on {0} for {1}",
|
||||||
|
// scene.RegionInfo.RegionName, agentID);
|
||||||
|
|
||||||
ScenePresence avatar = scene.GetScenePresence(agentID);
|
ScenePresence avatar = scene.GetScenePresence(agentID);
|
||||||
string avatarName = avatar.Name;
|
string avatarName = avatar.Name;
|
||||||
|
|
||||||
|
@ -453,8 +458,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
|
|
||||||
if ((land.Flags & (uint)ParcelFlags.AllowVoiceChat) == 0)
|
if ((land.Flags & (uint)ParcelFlags.AllowVoiceChat) == 0)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel",
|
// m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel",
|
||||||
scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName);
|
// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName);
|
||||||
channelUri = String.Empty;
|
channelUri = String.Empty;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -469,8 +474,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds);
|
parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds);
|
||||||
string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
|
string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
|
||||||
|
|
||||||
m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}",
|
// m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}",
|
||||||
scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r);
|
// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -502,6 +507,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
|
|
||||||
m_log.DebugFormat("[FreeSwitchVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}",
|
m_log.DebugFormat("[FreeSwitchVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}",
|
||||||
avatarName, request, path, param);
|
avatarName, request, path, param);
|
||||||
|
|
||||||
return "<llsd>true</llsd>";
|
return "<llsd>true</llsd>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,10 +561,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request)
|
public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request)
|
||||||
{
|
{
|
||||||
m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceGetPreloginHTTPHandler called");
|
m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceGetPreloginHTTPHandler called");
|
||||||
|
|
||||||
Hashtable response = new Hashtable();
|
Hashtable response = new Hashtable();
|
||||||
response["content_type"] = "text/xml";
|
response["content_type"] = "text/xml";
|
||||||
|
@ -592,6 +597,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
|
|
||||||
public Hashtable FreeSwitchSLVoiceBuddyHTTPHandler(Hashtable request)
|
public Hashtable FreeSwitchSLVoiceBuddyHTTPHandler(Hashtable request)
|
||||||
{
|
{
|
||||||
|
m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceBuddyHTTPHandler called");
|
||||||
|
|
||||||
Hashtable response = new Hashtable();
|
Hashtable response = new Hashtable();
|
||||||
response["int_response_code"] = 200;
|
response["int_response_code"] = 200;
|
||||||
response["str_response_string"] = string.Empty;
|
response["str_response_string"] = string.Empty;
|
||||||
|
@ -650,21 +657,64 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
<bdy_status>A</bdy_status>
|
<bdy_status>A</bdy_status>
|
||||||
<modified_ts>{3}</modified_ts>
|
<modified_ts>{3}</modified_ts>
|
||||||
<b2g_group_id></b2g_group_id>
|
<b2g_group_id></b2g_group_id>
|
||||||
</level3>", ids[i],i,m_freeSwitchRealm,dt));
|
</level3>", ids[i], i ,m_freeSwitchRealm, dt));
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Append("</buddies><groups></groups></body></level0></response>");
|
resp.Append("</buddies><groups></groups></body></level0></response>");
|
||||||
|
|
||||||
response["str_response_string"] = resp.ToString();
|
response["str_response_string"] = resp.ToString();
|
||||||
// Regex normalizeEndLines = new Regex(@"\r\n", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline);
|
// Regex normalizeEndLines = new Regex(@"(\r\n|\n)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline);
|
||||||
|
//
|
||||||
//m_log.DebugFormat("[FREESWITCH]: {0}", normalizeEndLines.Replace((string)response["str_response_string"],""));
|
// m_log.DebugFormat(
|
||||||
|
// "[FREESWITCH]: FreeSwitchSLVoiceBuddyHTTPHandler() response {0}",
|
||||||
|
// normalizeEndLines.Replace((string)response["str_response_string"],""));
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Hashtable FreeSwitchSLVoiceWatcherHTTPHandler(Hashtable request)
|
||||||
|
{
|
||||||
|
m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceWatcherHTTPHandler called");
|
||||||
|
|
||||||
|
Hashtable response = new Hashtable();
|
||||||
|
response["int_response_code"] = 200;
|
||||||
|
response["content-type"] = "text/xml";
|
||||||
|
|
||||||
|
Hashtable requestBody = ParseRequestBody((string)request["body"]);
|
||||||
|
|
||||||
|
string auth_token = (string)requestBody["auth_token"];
|
||||||
|
//string[] auth_tokenvals = auth_token.Split(':');
|
||||||
|
//string username = auth_tokenvals[0];
|
||||||
|
|
||||||
|
StringBuilder resp = new StringBuilder();
|
||||||
|
resp.Append("<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?><response xmlns=\"http://www.vivox.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation= \"/xsd/buddy_list.xsd\">");
|
||||||
|
|
||||||
|
// FIXME: This is enough of a response to stop viewer 2 complaining about a login failure and get voice to work. If we don't
|
||||||
|
// give an OK response, then viewer 2 engages in an continuous viv_signin.php, viv_buddy.php, viv_watcher.php loop
|
||||||
|
// Viewer 1 appeared happy to ignore the lack of reply and still works with this reply.
|
||||||
|
//
|
||||||
|
// However, really we need to fill in whatever watcher data should be here (whatever that is).
|
||||||
|
resp.Append(string.Format(@"<level0>
|
||||||
|
<status>OK</status>
|
||||||
|
<cookie_name>lib_session</cookie_name>
|
||||||
|
<cookie>{0}</cookie>
|
||||||
|
<auth_token>{0}</auth_token>
|
||||||
|
<body/></level0></response>", auth_token));
|
||||||
|
|
||||||
|
response["str_response_string"] = resp.ToString();
|
||||||
|
|
||||||
|
// Regex normalizeEndLines = new Regex(@"(\r\n|\n)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline);
|
||||||
|
//
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[FREESWITCH]: FreeSwitchSLVoiceWatcherHTTPHandler() response {0}",
|
||||||
|
// normalizeEndLines.Replace((string)response["str_response_string"],""));
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request)
|
public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request)
|
||||||
{
|
{
|
||||||
m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceSigninHTTPHandler called");
|
m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceSigninHTTPHandler called");
|
||||||
// string requestbody = (string)request["body"];
|
// string requestbody = (string)request["body"];
|
||||||
// string uri = (string)request["uri"];
|
// string uri = (string)request["uri"];
|
||||||
// string contenttype = (string)request["content-type"];
|
// string contenttype = (string)request["content-type"];
|
||||||
|
@ -709,7 +759,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
</level0>
|
</level0>
|
||||||
</response>", userid, pos, avatarName);
|
</response>", userid, pos, avatarName);
|
||||||
|
|
||||||
response["int_response_code"] = 200;
|
response["int_response_code"] = 200;
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[FreeSwitchVoice]: Sending FreeSwitchSLVoiceSigninHTTPHandler response");
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -795,16 +848,27 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
response["keepalive"] = false;
|
response["keepalive"] = false;
|
||||||
response["int_response_code"] = 500;
|
response["int_response_code"] = 500;
|
||||||
|
|
||||||
Hashtable requestBody = ParseRequestBody((string) request["body"]);
|
Hashtable requestBody = ParseRequestBody((string)request["body"]);
|
||||||
|
|
||||||
string section = (string) requestBody["section"];
|
string section = (string) requestBody["section"];
|
||||||
|
|
||||||
if (section == "directory")
|
if (section == "directory")
|
||||||
|
{
|
||||||
|
string eventCallingFunction = (string)requestBody["Event-Calling-Function"];
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[FreeSwitchVoice]: Received request for config section directory, event calling function '{0}'",
|
||||||
|
eventCallingFunction);
|
||||||
|
|
||||||
response = m_FreeswitchService.HandleDirectoryRequest(requestBody);
|
response = m_FreeswitchService.HandleDirectoryRequest(requestBody);
|
||||||
|
}
|
||||||
else if (section == "dialplan")
|
else if (section == "dialplan")
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[FreeSwitchVoice]: Received request for config section dialplan");
|
||||||
|
|
||||||
response = m_FreeswitchService.HandleDialplanRequest(requestBody);
|
response = m_FreeswitchService.HandleDialplanRequest(requestBody);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_log.WarnFormat("[FreeSwitchVoice]: section was {0}", section);
|
m_log.WarnFormat("[FreeSwitchVoice]: Unknown section {0} was requested from config.", section);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
@ -821,4 +885,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -84,10 +84,11 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
public Meshmerizer(IConfigSource config)
|
public Meshmerizer(IConfigSource config)
|
||||||
{
|
{
|
||||||
IConfig start_config = config.Configs["Startup"];
|
IConfig start_config = config.Configs["Startup"];
|
||||||
|
IConfig mesh_config = config.Configs["Mesh"];
|
||||||
|
|
||||||
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
|
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
|
||||||
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
|
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
|
||||||
useMeshiesPhysicsMesh = start_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
|
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -62,6 +62,8 @@ namespace PrimMesher
|
||||||
|
|
||||||
bool needsScaling = false;
|
bool needsScaling = false;
|
||||||
|
|
||||||
|
bool smallMap = bmW * bmH <= lod * lod;
|
||||||
|
|
||||||
width = bmW;
|
width = bmW;
|
||||||
height = bmH;
|
height = bmH;
|
||||||
while (width * height > numLodPixels)
|
while (width * height > numLodPixels)
|
||||||
|
@ -104,9 +106,14 @@ namespace PrimMesher
|
||||||
{
|
{
|
||||||
for (int x = 0; x <= width; x++)
|
for (int x = 0; x <= width; x++)
|
||||||
{
|
{
|
||||||
int bmY = y < height ? y * 2 : y * 2 - 1;
|
Color c;
|
||||||
int bmX = x < width ? x * 2 : x * 2 - 1;
|
|
||||||
Color c = bm.GetPixel(bmX, bmY);
|
if (smallMap)
|
||||||
|
c = bm.GetPixel(x < width ? x : x - 1,
|
||||||
|
y < height ? y : y - 1);
|
||||||
|
else
|
||||||
|
c = bm.GetPixel(x < width ? x * 2 : x * 2 - 1,
|
||||||
|
y < height ? y * 2 : y * 2 - 1);
|
||||||
|
|
||||||
redBytes[byteNdx] = c.R;
|
redBytes[byteNdx] = c.R;
|
||||||
greenBytes[byteNdx] = c.G;
|
greenBytes[byteNdx] = c.G;
|
||||||
|
|
|
@ -158,7 +158,10 @@ namespace OpenSim.Services.Connectors
|
||||||
public InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
|
public InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
|
||||||
{
|
{
|
||||||
InventoryCollection inventory = new InventoryCollection();
|
InventoryCollection inventory = new InventoryCollection();
|
||||||
|
inventory.Folders = new List<InventoryFolderBase>();
|
||||||
|
inventory.Items = new List<InventoryItemBase>();
|
||||||
|
inventory.UserID = principalID;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Dictionary<string,object> ret = MakeRequest("GETFOLDERCONTENT",
|
Dictionary<string,object> ret = MakeRequest("GETFOLDERCONTENT",
|
||||||
|
@ -172,11 +175,6 @@ namespace OpenSim.Services.Connectors
|
||||||
if (ret.Count == 0)
|
if (ret.Count == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|
||||||
inventory.Folders = new List<InventoryFolderBase>();
|
|
||||||
inventory.Items = new List<InventoryItemBase>();
|
|
||||||
inventory.UserID = principalID;
|
|
||||||
|
|
||||||
Dictionary<string,object> folders =
|
Dictionary<string,object> folders =
|
||||||
(Dictionary<string,object>)ret["FOLDERS"];
|
(Dictionary<string,object>)ret["FOLDERS"];
|
||||||
Dictionary<string,object> items =
|
Dictionary<string,object> items =
|
||||||
|
|
|
@ -50,13 +50,13 @@ namespace OpenSim.Services.FreeswitchService
|
||||||
|
|
||||||
public Hashtable HandleDialplanRequest(Hashtable request)
|
public Hashtable HandleDialplanRequest(Hashtable request)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[FreeSwitchVoice] HandleDialplanRequest called with {0}",request.ToString());
|
m_log.DebugFormat("[FreeSwitchVoice]: HandleDialplanRequest called with {0}",request.ToString());
|
||||||
|
|
||||||
Hashtable response = new Hashtable();
|
Hashtable response = new Hashtable();
|
||||||
|
|
||||||
foreach (DictionaryEntry item in request)
|
foreach (DictionaryEntry item in request)
|
||||||
{
|
{
|
||||||
m_log.InfoFormat("[FreeSwitchDirectory] requestBody item {0} {1}",item.Key, item.Value);
|
// m_log.InfoFormat("[FreeSwitchDirectory]: requestBody item {0} {1}",item.Key, item.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
string requestcontext = (string) request["Hunt-Context"];
|
string requestcontext = (string) request["Hunt-Context"];
|
||||||
|
@ -66,7 +66,7 @@ namespace OpenSim.Services.FreeswitchService
|
||||||
|
|
||||||
if (m_freeSwitchContext != String.Empty && m_freeSwitchContext != requestcontext)
|
if (m_freeSwitchContext != String.Empty && m_freeSwitchContext != requestcontext)
|
||||||
{
|
{
|
||||||
m_log.Debug("[FreeSwitchDirectory] returning empty as it's for another context");
|
m_log.Debug("[FreeSwitchDirectory]: returning empty as it's for another context");
|
||||||
response["str_response_string"] = "";
|
response["str_response_string"] = "";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -116,13 +116,16 @@ namespace OpenSim.Services.FreeswitchService
|
||||||
{
|
{
|
||||||
Hashtable response = new Hashtable();
|
Hashtable response = new Hashtable();
|
||||||
string domain = (string) request["domain"];
|
string domain = (string) request["domain"];
|
||||||
if (domain != m_freeSwitchRealm) {
|
if (domain != m_freeSwitchRealm)
|
||||||
|
{
|
||||||
response["content_type"] = "text/xml";
|
response["content_type"] = "text/xml";
|
||||||
response["keepalive"] = false;
|
response["keepalive"] = false;
|
||||||
response["int_response_code"] = 200;
|
response["int_response_code"] = 200;
|
||||||
response["str_response_string"] = "";
|
response["str_response_string"] = "";
|
||||||
} else {
|
}
|
||||||
m_log.DebugFormat("[FreeSwitchDirectory] HandleDirectoryRequest called with {0}",request.ToString());
|
else
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[FreeSwitchDirectory]: HandleDirectoryRequest called with {0}",request.ToString());
|
||||||
|
|
||||||
// information in the request we might be interested in
|
// information in the request we might be interested in
|
||||||
|
|
||||||
|
@ -143,10 +146,8 @@ namespace OpenSim.Services.FreeswitchService
|
||||||
//domain=9.20.151.43
|
//domain=9.20.151.43
|
||||||
//ip=9.167.220.137 // this is the correct IP rather than sip_contact_host above when through a vpn or NAT setup
|
//ip=9.167.220.137 // this is the correct IP rather than sip_contact_host above when through a vpn or NAT setup
|
||||||
|
|
||||||
foreach (DictionaryEntry item in request)
|
// foreach (DictionaryEntry item in request)
|
||||||
{
|
// m_log.DebugFormat("[FreeSwitchDirectory]: requestBody item {0} {1}", item.Key, item.Value);
|
||||||
m_log.InfoFormat("[FreeSwitchDirectory] requestBody item {0} {1}", item.Key, item.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
string eventCallingFunction = (string) request["Event-Calling-Function"];
|
string eventCallingFunction = (string) request["Event-Calling-Function"];
|
||||||
if (eventCallingFunction == null)
|
if (eventCallingFunction == null)
|
||||||
|
@ -173,7 +174,7 @@ namespace OpenSim.Services.FreeswitchService
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat("[FreeSwitchVoice] HandleDirectoryRequest unknown sip_auth_method {0}",sipAuthMethod);
|
m_log.ErrorFormat("[FreeSwitchVoice]: HandleDirectoryRequest unknown sip_auth_method {0}",sipAuthMethod);
|
||||||
response["int_response_code"] = 404;
|
response["int_response_code"] = 404;
|
||||||
response["content_type"] = "text/xml";
|
response["content_type"] = "text/xml";
|
||||||
response["str_response_string"] = "";
|
response["str_response_string"] = "";
|
||||||
|
@ -205,7 +206,7 @@ namespace OpenSim.Services.FreeswitchService
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat("[FreeSwitchVoice] HandleDirectoryRequest unknown Event-Calling-Function {0}",eventCallingFunction);
|
m_log.ErrorFormat("[FreeSwitchVoice]: HandleDirectoryRequest unknown Event-Calling-Function {0}",eventCallingFunction);
|
||||||
response["int_response_code"] = 404;
|
response["int_response_code"] = 404;
|
||||||
response["keepalive"] = false;
|
response["keepalive"] = false;
|
||||||
response["content_type"] = "text/xml";
|
response["content_type"] = "text/xml";
|
||||||
|
@ -217,7 +218,7 @@ namespace OpenSim.Services.FreeswitchService
|
||||||
|
|
||||||
private Hashtable HandleRegister(string Context, string Realm, Hashtable request)
|
private Hashtable HandleRegister(string Context, string Realm, Hashtable request)
|
||||||
{
|
{
|
||||||
m_log.Info("[FreeSwitchDirectory] HandleRegister called");
|
m_log.Info("[FreeSwitchDirectory]: HandleRegister called");
|
||||||
|
|
||||||
// TODO the password we return needs to match that sent in the request, this is hard coded for now
|
// TODO the password we return needs to match that sent in the request, this is hard coded for now
|
||||||
string password = "1234";
|
string password = "1234";
|
||||||
|
@ -254,7 +255,7 @@ namespace OpenSim.Services.FreeswitchService
|
||||||
|
|
||||||
private Hashtable HandleInvite(string Context, string Realm, Hashtable request)
|
private Hashtable HandleInvite(string Context, string Realm, Hashtable request)
|
||||||
{
|
{
|
||||||
m_log.Info("[FreeSwitchDirectory] HandleInvite called");
|
m_log.Info("[FreeSwitchDirectory]: HandleInvite called");
|
||||||
|
|
||||||
// TODO the password we return needs to match that sent in the request, this is hard coded for now
|
// TODO the password we return needs to match that sent in the request, this is hard coded for now
|
||||||
string password = "1234";
|
string password = "1234";
|
||||||
|
@ -301,7 +302,7 @@ namespace OpenSim.Services.FreeswitchService
|
||||||
|
|
||||||
private Hashtable HandleLocateUser(String Realm, Hashtable request)
|
private Hashtable HandleLocateUser(String Realm, Hashtable request)
|
||||||
{
|
{
|
||||||
m_log.Info("[FreeSwitchDirectory] HandleLocateUser called");
|
m_log.Info("[FreeSwitchDirectory]: HandleLocateUser called");
|
||||||
|
|
||||||
// TODO the password we return needs to match that sent in the request, this is hard coded for now
|
// TODO the password we return needs to match that sent in the request, this is hard coded for now
|
||||||
string domain = (string) request["domain"];
|
string domain = (string) request["domain"];
|
||||||
|
@ -335,7 +336,7 @@ namespace OpenSim.Services.FreeswitchService
|
||||||
|
|
||||||
private Hashtable HandleConfigSofia(string Context, string Realm, Hashtable request)
|
private Hashtable HandleConfigSofia(string Context, string Realm, Hashtable request)
|
||||||
{
|
{
|
||||||
m_log.Info("[FreeSwitchDirectory] HandleConfigSofia called");
|
m_log.Info("[FreeSwitchDirectory]: HandleConfigSofia called.");
|
||||||
|
|
||||||
// TODO the password we return needs to match that sent in the request, this is hard coded for now
|
// TODO the password we return needs to match that sent in the request, this is hard coded for now
|
||||||
string domain = (string) request["domain"];
|
string domain = (string) request["domain"];
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace OpenSim.Services.FreeswitchService
|
||||||
m_freeSwitchDefaultWellKnownIP = freeswitchConfig.GetString("ServerAddress", String.Empty);
|
m_freeSwitchDefaultWellKnownIP = freeswitchConfig.GetString("ServerAddress", String.Empty);
|
||||||
if (m_freeSwitchDefaultWellKnownIP == String.Empty)
|
if (m_freeSwitchDefaultWellKnownIP == String.Empty)
|
||||||
{
|
{
|
||||||
m_log.Error("[FREESWITCH]: No FreeswitchServerAddress given, can't continue");
|
m_log.Error("[FREESWITCH]: No ServerAddress given, cannot start service.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Services.Interfaces;
|
using OpenSim.Services.Interfaces;
|
||||||
|
@ -57,6 +58,9 @@ namespace OpenSim.Services.HypergridService
|
||||||
private static IUserAgentService m_UserAgentService;
|
private static IUserAgentService m_UserAgentService;
|
||||||
private static ISimulationService m_SimulationService;
|
private static ISimulationService m_SimulationService;
|
||||||
|
|
||||||
|
protected string m_AllowedClients = string.Empty;
|
||||||
|
protected string m_DeniedClients = string.Empty;
|
||||||
|
|
||||||
private static UUID m_ScopeID;
|
private static UUID m_ScopeID;
|
||||||
private static bool m_AllowTeleportsToAnyRegion;
|
private static bool m_AllowTeleportsToAnyRegion;
|
||||||
private static string m_ExternalName;
|
private static string m_ExternalName;
|
||||||
|
@ -104,6 +108,9 @@ namespace OpenSim.Services.HypergridService
|
||||||
else if (simulationService != string.Empty)
|
else if (simulationService != string.Empty)
|
||||||
m_SimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args);
|
m_SimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args);
|
||||||
|
|
||||||
|
m_AllowedClients = serverConfig.GetString("AllowedClients", string.Empty);
|
||||||
|
m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty);
|
||||||
|
|
||||||
if (m_GridService == null || m_PresenceService == null || m_SimulationService == null)
|
if (m_GridService == null || m_PresenceService == null || m_SimulationService == null)
|
||||||
throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function.");
|
throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function.");
|
||||||
|
|
||||||
|
@ -181,8 +188,36 @@ namespace OpenSim.Services.HypergridService
|
||||||
string authURL = string.Empty;
|
string authURL = string.Empty;
|
||||||
if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
|
if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
|
||||||
authURL = aCircuit.ServiceURLs["HomeURI"].ToString();
|
authURL = aCircuit.ServiceURLs["HomeURI"].ToString();
|
||||||
m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to login foreign agent {0} {1} @ {2} ({3}) at destination {4}",
|
m_log.InfoFormat("[GATEKEEPER SERVICE]: Login request for {0} {1} @ {2} ({3}) at {4} using viewer {5}, channel {6}, IP {7}, Mac {8}, Id0 {9}",
|
||||||
aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName);
|
aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName,
|
||||||
|
aCircuit.Viewer, aCircuit.Channel, aCircuit.IPAddress, aCircuit.Mac, aCircuit.Id0);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check client
|
||||||
|
//
|
||||||
|
if (m_AllowedClients != string.Empty)
|
||||||
|
{
|
||||||
|
Regex arx = new Regex(m_AllowedClients);
|
||||||
|
Match am = arx.Match(aCircuit.Viewer);
|
||||||
|
|
||||||
|
if (!am.Success)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is not allowed", aCircuit.Viewer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_DeniedClients != string.Empty)
|
||||||
|
{
|
||||||
|
Regex drx = new Regex(m_DeniedClients);
|
||||||
|
Match dm = drx.Match(aCircuit.Viewer);
|
||||||
|
|
||||||
|
if (dm.Success)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is denied", aCircuit.Viewer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Authenticate the user
|
// Authenticate the user
|
||||||
|
|
|
@ -244,7 +244,7 @@ namespace OpenSim.Services.InventoryService
|
||||||
// connector. So we disregard the principal and look
|
// connector. So we disregard the principal and look
|
||||||
// by ID.
|
// by ID.
|
||||||
//
|
//
|
||||||
m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString());
|
//m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString());
|
||||||
InventoryCollection inventory = new InventoryCollection();
|
InventoryCollection inventory = new InventoryCollection();
|
||||||
inventory.UserID = principalID;
|
inventory.UserID = principalID;
|
||||||
inventory.Folders = new List<InventoryFolderBase>();
|
inventory.Folders = new List<InventoryFolderBase>();
|
||||||
|
|
|
@ -77,7 +77,11 @@ namespace OpenSim.Services.LLLoginService
|
||||||
protected string m_MapTileURL;
|
protected string m_MapTileURL;
|
||||||
protected string m_SearchURL;
|
protected string m_SearchURL;
|
||||||
|
|
||||||
|
protected string m_AllowedClients;
|
||||||
|
protected string m_DeniedClients;
|
||||||
|
|
||||||
IConfig m_LoginServerConfig;
|
IConfig m_LoginServerConfig;
|
||||||
|
IConfig m_ClientsConfig;
|
||||||
|
|
||||||
public LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService)
|
public LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService)
|
||||||
{
|
{
|
||||||
|
@ -105,7 +109,10 @@ namespace OpenSim.Services.LLLoginService
|
||||||
m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty);
|
m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty);
|
||||||
m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty);
|
m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty);
|
||||||
m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty);
|
m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty);
|
||||||
|
|
||||||
|
m_AllowedClients = m_LoginServerConfig.GetString("AllowedClients", string.Empty);
|
||||||
|
m_DeniedClients = m_LoginServerConfig.GetString("DeniedClients", string.Empty);
|
||||||
|
|
||||||
// These are required; the others aren't
|
// These are required; the others aren't
|
||||||
if (accountService == string.Empty || authService == string.Empty)
|
if (accountService == string.Empty || authService == string.Empty)
|
||||||
throw new Exception("LoginService is missing service specifications");
|
throw new Exception("LoginService is missing service specifications");
|
||||||
|
@ -215,10 +222,37 @@ namespace OpenSim.Services.LLLoginService
|
||||||
bool success = false;
|
bool success = false;
|
||||||
UUID session = UUID.Random();
|
UUID session = UUID.Random();
|
||||||
|
|
||||||
m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} from {2} with user agent {3} starting in {4}",
|
m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} at {2} using viewer {3}, channel {4}, IP {5}, Mac {6}, Id0 {7}",
|
||||||
firstName, lastName, clientIP.Address.ToString(), clientVersion, startLocation);
|
firstName, lastName, startLocation, clientVersion, channel, clientIP.Address.ToString(), mac, id0);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// Check client
|
||||||
|
//
|
||||||
|
if (m_AllowedClients != string.Empty)
|
||||||
|
{
|
||||||
|
Regex arx = new Regex(m_AllowedClients);
|
||||||
|
Match am = arx.Match(clientVersion);
|
||||||
|
|
||||||
|
if (!am.Success)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is not allowed", clientVersion);
|
||||||
|
return LLFailedLoginResponse.LoginBlockedProblem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_DeniedClients != string.Empty)
|
||||||
|
{
|
||||||
|
Regex drx = new Regex(m_DeniedClients);
|
||||||
|
Match dm = drx.Match(clientVersion);
|
||||||
|
|
||||||
|
if (dm.Success)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is denied", clientVersion);
|
||||||
|
return LLFailedLoginResponse.LoginBlockedProblem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the account and check that it exists
|
// Get the account and check that it exists
|
||||||
//
|
//
|
||||||
|
|
|
@ -37,7 +37,7 @@ Now see the "Configuring OpenSim" section
|
||||||
=== Running OpenSim on Linux ===
|
=== Running OpenSim on Linux ===
|
||||||
================================
|
================================
|
||||||
|
|
||||||
You will need Mono >= 2.4.2 to run OpenSim. On some Linux distributions you
|
You will need Mono >= 2.4.3 to run OpenSim. On some Linux distributions you
|
||||||
may need to install additional packages. See http://opensimulator.org/wiki/Dependencies
|
may need to install additional packages. See http://opensimulator.org/wiki/Dependencies
|
||||||
for more information.
|
for more information.
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
bin/DotSets.dll
BIN
bin/DotSets.dll
Binary file not shown.
BIN
bin/MXP.dll
BIN
bin/MXP.dll
Binary file not shown.
Binary file not shown.
|
@ -621,31 +621,49 @@
|
||||||
|
|
||||||
;; You need to load a local service for a standalone, and a remote service
|
;; You need to load a local service for a standalone, and a remote service
|
||||||
;; for a grid region. Use one of the lines below, as appropriate
|
;; for a grid region. Use one of the lines below, as appropriate
|
||||||
|
;; If you're using Freeswitch on a standalone then you will also need to configure the [FreeswitchService] section
|
||||||
; LocalServiceModule = OpenSim.Services.FreeswitchService.dll:FreeswitchService
|
; LocalServiceModule = OpenSim.Services.FreeswitchService.dll:FreeswitchService
|
||||||
; LocalServiceModule = OpenSim.Services.Connectors.dll:RemoteFreeswitchConnector
|
; LocalServiceModule = OpenSim.Services.Connectors.dll:RemoteFreeswitchConnector
|
||||||
|
|
||||||
;; If using a remote module, specify the server URL
|
;; If using a remote connector, specify the server URL
|
||||||
; FreeswitchServiceURL = http://my.grid.server:8003/fsapi
|
; FreeswitchServiceURL = http://my.grid.server:8004/fsapi
|
||||||
|
|
||||||
|
|
||||||
[FreeswitchService]
|
[FreeswitchService]
|
||||||
;; !!!!!!!!!!!!!!!!!!!!!!!!!!!
|
;; !!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
;; !!!!!!STANDALONE ONLY!!!!!!
|
;; !!!!!!STANDALONE ONLY!!!!!!
|
||||||
;; !!!!!!!!!!!!!!!!!!!!!!!!!!!
|
;; !!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
;; IP of your FS server
|
;; The IP address of your FreeSWITCH server. The common case is for this to be the same as the server running the OpenSim standalone
|
||||||
;ServerAddress = 85.25.142.92
|
;; This has to be set for the FreeSWITCH service to work
|
||||||
|
;ServerAddress = 127.0.0.1
|
||||||
|
|
||||||
;; All other options are - well - optional
|
;; The following configuration parameters are optional
|
||||||
; Realm = "127.0.0.1"
|
|
||||||
; SIPProxy = "127.0.0.1:5060"
|
;; By default, this is the same as the ServerAddress
|
||||||
; EchoServer = "127.0.0.1"
|
; Realm = 127.0.0.1
|
||||||
; EchoPort = 50505
|
|
||||||
; AttemptSTUN = "false"
|
;; By default, this is the same as the ServerAddress on port 5060
|
||||||
|
; SIPProxy = 127.0.0.1:5060
|
||||||
|
|
||||||
|
;; Default is 5000ms
|
||||||
; DefaultTimeout = 5000
|
; DefaultTimeout = 5000
|
||||||
; Context = "default"
|
|
||||||
; UserName = "freeswitch"
|
|
||||||
; Password = "password"
|
|
||||||
|
|
||||||
|
;; The dial plan context. Default is "default"
|
||||||
|
; Context = default
|
||||||
|
|
||||||
|
;; Currently unused
|
||||||
|
; UserName = freeswitch
|
||||||
|
|
||||||
|
;; Currently unused
|
||||||
|
; Password = password
|
||||||
|
|
||||||
|
;; The following parameters are for STUN = Simple Traversal of UDP through NATs
|
||||||
|
;; See http://wiki.freeswitch.org/wiki/NAT_Traversal
|
||||||
|
;; stun.freeswitch.org is not guaranteed to be running so use it in
|
||||||
|
;; production at your own risk
|
||||||
|
; EchoServer = 127.0.0.1
|
||||||
|
; EchoPort = 50505
|
||||||
|
; AttemptSTUN = false
|
||||||
|
|
||||||
[Groups]
|
[Groups]
|
||||||
;# {Enabled} {} {Enable groups?} {true false} false
|
;# {Enabled} {} {Enable groups?} {true false} false
|
||||||
|
|
|
@ -149,12 +149,6 @@
|
||||||
; to false if you have compatibility problems.
|
; to false if you have compatibility problems.
|
||||||
;CacheSculptMaps = true
|
;CacheSculptMaps = true
|
||||||
|
|
||||||
; if you use Meshmerizer and want collisions for meshies, setting this to true
|
|
||||||
; will cause OpenSim to attempt to decode meshies assets, extract the physics
|
|
||||||
; mesh, and use it for collisions. This is currently experimental code and enabling
|
|
||||||
; it may cause unexpected physics problems.
|
|
||||||
;UseMeshiesPhysicsMesh = false
|
|
||||||
|
|
||||||
; Choose one of the physics engines below
|
; Choose one of the physics engines below
|
||||||
; OpenDynamicsEngine is by some distance the most developed physics engine
|
; OpenDynamicsEngine is by some distance the most developed physics engine
|
||||||
; basicphysics effectively does not model physics at all, making all objects phantom
|
; basicphysics effectively does not model physics at all, making all objects phantom
|
||||||
|
@ -368,30 +362,24 @@
|
||||||
;
|
;
|
||||||
;client_throttle_max_bps = 196608
|
;client_throttle_max_bps = 196608
|
||||||
|
|
||||||
; Per-client bytes per second rates for the various throttle categories.
|
; Adaptive throttling attempts to limit network overload when multiple
|
||||||
; These are default values that will be overriden by clients
|
; clients login by starting each connection more slowly. Disabled by
|
||||||
|
; default
|
||||||
;
|
;
|
||||||
;resend_default = 12500
|
;enable_adaptive_throttles = true
|
||||||
;land_default = 1000
|
|
||||||
;wind_default = 1000
|
|
||||||
;cloud_default = 1000
|
|
||||||
;task_default = 1000
|
|
||||||
;texture_default = 1000
|
|
||||||
;asset_default = 1000
|
|
||||||
;state_default = 1000
|
|
||||||
|
|
||||||
; Per-client maximum burst rates in bytes per second for the various
|
; Per-client bytes per second rates for the various throttle categories.
|
||||||
; throttle categories. These are default values that will be overriden by
|
; These are default values that will be overriden by clients. These
|
||||||
; clients
|
; defaults are approximately equivalent to the throttles set by the Imprudence
|
||||||
;
|
; viewer when maximum bandwidth is set to 350kbps
|
||||||
;resend_limit = 18750
|
|
||||||
;land_limit = 29750
|
;resend_default = 6625
|
||||||
;wind_limit = 18750
|
;land_default = 9125
|
||||||
;cloud_limit = 18750
|
;wind_default = 1750
|
||||||
;task_limit = 18750
|
;cloud_default = 1750
|
||||||
;texture_limit = 55750
|
;task_default = 18500
|
||||||
;asset_limit = 27500
|
;texture_default = 18500
|
||||||
;state_limit = 37000
|
;asset_default = 10500
|
||||||
|
|
||||||
; Configures how ObjectUpdates are aggregated. These numbers
|
; Configures how ObjectUpdates are aggregated. These numbers
|
||||||
; do not literally mean how many updates will be put in each
|
; do not literally mean how many updates will be put in each
|
||||||
|
@ -459,7 +447,13 @@
|
||||||
[Mesh]
|
[Mesh]
|
||||||
; enable / disable Collada mesh support
|
; enable / disable Collada mesh support
|
||||||
; default is true
|
; default is true
|
||||||
; ColladaMesh = true
|
; AllowMeshUpload = true
|
||||||
|
|
||||||
|
; if you use Meshmerizer and want collisions for meshies, setting this to true
|
||||||
|
; will cause OpenSim to attempt to decode meshies assets, extract the physics
|
||||||
|
; mesh, and use it for collisions. This is currently experimental code and enabling
|
||||||
|
; it may cause unexpected physics problems.
|
||||||
|
;UseMeshiesPhysicsMesh = false
|
||||||
|
|
||||||
|
|
||||||
[ODEPhysicsSettings]
|
[ODEPhysicsSettings]
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue