Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
commit
8f14c3f04f
|
@ -1,34 +1,36 @@
|
|||
The following people have contributed to OpenSim (Thank you
|
||||
for your effort!)
|
||||
|
||||
Add your name in here if you have committed to OpenSim
|
||||
|
||||
= Current OpenSim Developers (in very rough order of appearance) =
|
||||
These folks represent the current core team for OpenSim, and are the
|
||||
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)
|
||||
* Adam Frisby (DeepThink Pty Ltd)
|
||||
* MingChen (DeepThink Pty Ltd)
|
||||
* lbsa71 (Tribal Media AB)
|
||||
* Sean Dague / sdague (IBM)
|
||||
* Tedd
|
||||
* justincc
|
||||
* Teravus (w3z)
|
||||
* Johan Berntsson (3Di)
|
||||
* Ckrinke (Charles Krinke)
|
||||
* chi11ken (Genkii)
|
||||
* adjohn (Genkii)
|
||||
* Dr Scofield aka Dirk Husemann (IBM Research - Zurich)
|
||||
* dahlia
|
||||
* mikem (3Di)
|
||||
* Melanie Thielker
|
||||
* Homer_Horwitz
|
||||
* idb (Ian Brown)
|
||||
* Diva (Crista Lopes, University of California, Irvine)
|
||||
* nlin (3Di)
|
||||
* Arthur Rodrigo S Valadares (IBM)
|
||||
* BlueWall (James Hughes)
|
||||
* John Hurliman
|
||||
|
||||
= Past Open Sim Developers =
|
||||
These folks are alumns of the OpenSim core group, but are now
|
||||
|
@ -44,6 +46,12 @@ where we are today.
|
|||
* Dalien
|
||||
* Darok
|
||||
* Alondria
|
||||
* Sean Dague / sdague (IBM)
|
||||
* Tedd
|
||||
* MingChen (DeepThink Pty Ltd)
|
||||
* adjohn (Genkii)
|
||||
* idb (Ian Brown)
|
||||
* Johan Berntsson (3Di)
|
||||
|
||||
|
||||
= Additional OpenSim Contributors =
|
||||
|
@ -102,6 +110,7 @@ what it is today.
|
|||
* Misterblue (Intel)
|
||||
* Mircea Kitsune
|
||||
* mpallari
|
||||
* MrMonkE
|
||||
* nornalbion
|
||||
* Omar Vera Ustariz (IBM)
|
||||
* 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
|
||||
}
|
||||
}
|
|
@ -57,14 +57,14 @@ namespace OpenSim.Data.MSSQL
|
|||
{
|
||||
m_Realm = realm;
|
||||
|
||||
m_ConnectionString = connectionString;
|
||||
|
||||
if (storeName != String.Empty)
|
||||
{
|
||||
Assembly assem = GetType().Assembly;
|
||||
m_ConnectionString = connectionString;
|
||||
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
Migration m = new Migration(conn, assem, storeName);
|
||||
Migration m = new Migration(conn, GetType().Assembly, storeName);
|
||||
m.Update();
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,8 @@ namespace OpenSim.Data.MSSQL
|
|||
}
|
||||
catch
|
||||
{
|
||||
// Something went wrong, so we're version 0
|
||||
// Return -1 to indicate table does not exist
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return version;
|
||||
|
|
|
@ -492,12 +492,11 @@ ELSE
|
|||
using (SqlConnection conn = new SqlConnection(m_connectionString))
|
||||
using (SqlCommand cmd = new SqlCommand(sql, conn))
|
||||
{
|
||||
conn.Open();
|
||||
foreach (TaskInventoryItem taskItem in items)
|
||||
{
|
||||
cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem));
|
||||
conn.Open();
|
||||
cmd.ExecuteNonQuery();
|
||||
|
||||
cmd.Parameters.Clear();
|
||||
}
|
||||
}
|
||||
|
@ -1154,9 +1153,9 @@ VALUES
|
|||
PrimitiveBaseShape baseShape = new PrimitiveBaseShape();
|
||||
|
||||
baseShape.Scale = new Vector3(
|
||||
Convert.ToSingle(shapeRow["ScaleX"]),
|
||||
Convert.ToSingle(shapeRow["ScaleY"]),
|
||||
Convert.ToSingle(shapeRow["ScaleZ"]));
|
||||
(float)Convert.ToDouble(shapeRow["ScaleX"]),
|
||||
(float)Convert.ToDouble(shapeRow["ScaleY"]),
|
||||
(float)Convert.ToDouble(shapeRow["ScaleZ"]));
|
||||
|
||||
// paths
|
||||
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"]);
|
||||
}
|
||||
|
||||
|
||||
return baseShape;
|
||||
}
|
||||
|
@ -1573,7 +1575,16 @@ VALUES
|
|||
parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry));
|
||||
parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams));
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -22,7 +22,11 @@ COMMIT
|
|||
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -13,5 +13,28 @@ PRIMARY KEY CLUSTERED
|
|||
) 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
|
||||
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ COMMIT
|
|||
|
||||
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
|
|
@ -222,4 +222,17 @@ ALTER TABLE [regions] ADD [Token] varchar(255) NOT NULL DEFAULT 0;
|
|||
|
||||
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
|
||||
|
||||
: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,
|
||||
[SessionID] 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]
|
||||
|
||||
|
@ -28,3 +21,11 @@ CREATE UNIQUE INDEX SessionID ON Presence(SessionID);
|
|||
CREATE INDEX UserID ON Presence(UserID);
|
||||
|
||||
COMMIT
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN TRANSACTION
|
||||
|
||||
ALTER TABLE Presence ADD LastSeen DateTime
|
||||
|
||||
COMMIT
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
:VERSION 1
|
||||
|
||||
CREATE TABLE [dbo].[prims](
|
||||
|
@ -926,11 +925,121 @@ ALTER TABLE regionsettings ADD loaded_creation_datetime int NOT NULL default 0
|
|||
COMMIT
|
||||
|
||||
:VERSION 24
|
||||
-- Added post 0.7
|
||||
|
||||
BEGIN TRANSACTION
|
||||
|
||||
ALTER TABLE prims ADD COLUMN MediaURL varchar(255)
|
||||
ALTER TABLE primshapes ADD COLUMN Media TEXT
|
||||
ALTER TABLE prims ADD MediaURL varchar(255)
|
||||
ALTER TABLE primshapes ADD Media TEXT NULL
|
||||
|
||||
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
|
||||
|
||||
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,
|
||||
username AS FirstName,
|
||||
lastname AS LastName,
|
||||
|
|
|
@ -151,27 +151,6 @@ namespace OpenSim.Framework
|
|||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create AgentCircuitData from a Serializable AgentCircuitData
|
||||
/// </summary>
|
||||
/// <param name="cAgent"></param>
|
||||
public AgentCircuitData(sAgentCircuitData cAgent)
|
||||
{
|
||||
AgentID = new UUID(cAgent.AgentID);
|
||||
SessionID = new UUID(cAgent.SessionID);
|
||||
SecureSessionID = new UUID(cAgent.SecureSessionID);
|
||||
startpos = new Vector3(cAgent.startposx, cAgent.startposy, cAgent.startposz);
|
||||
firstname = cAgent.firstname;
|
||||
lastname = cAgent.lastname;
|
||||
circuitcode = cAgent.circuitcode;
|
||||
child = cAgent.child;
|
||||
InventoryFolder = new UUID(cAgent.InventoryFolder);
|
||||
BaseFolder = new UUID(cAgent.BaseFolder);
|
||||
CapsPath = cAgent.CapsPath;
|
||||
ChildrenCapSeeds = cAgent.ChildrenCapSeeds;
|
||||
Viewer = cAgent.Viewer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pack AgentCircuitData into an OSDMap for transmission over LLSD XML or LLSD json
|
||||
/// </summary>
|
||||
|
@ -369,52 +348,4 @@ namespace OpenSim.Framework
|
|||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Serializable Agent Circuit Data
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class sAgentCircuitData
|
||||
{
|
||||
public Guid AgentID;
|
||||
public Guid BaseFolder;
|
||||
public string CapsPath = String.Empty;
|
||||
public Dictionary<ulong, string> ChildrenCapSeeds;
|
||||
public bool child;
|
||||
public uint circuitcode;
|
||||
public string firstname;
|
||||
public Guid InventoryFolder;
|
||||
public string lastname;
|
||||
public Guid SecureSessionID;
|
||||
public Guid SessionID;
|
||||
public float startposx;
|
||||
public float startposy;
|
||||
public float startposz;
|
||||
public string Viewer;
|
||||
public string Channel;
|
||||
public string Mac;
|
||||
public string Id0;
|
||||
|
||||
public sAgentCircuitData()
|
||||
{
|
||||
}
|
||||
|
||||
public sAgentCircuitData(AgentCircuitData cAgent)
|
||||
{
|
||||
AgentID = cAgent.AgentID.Guid;
|
||||
SessionID = cAgent.SessionID.Guid;
|
||||
SecureSessionID = cAgent.SecureSessionID.Guid;
|
||||
startposx = cAgent.startpos.X;
|
||||
startposy = cAgent.startpos.Y;
|
||||
startposz = cAgent.startpos.Z;
|
||||
firstname = cAgent.firstname;
|
||||
lastname = cAgent.lastname;
|
||||
circuitcode = cAgent.circuitcode;
|
||||
child = cAgent.child;
|
||||
InventoryFolder = cAgent.InventoryFolder.Guid;
|
||||
BaseFolder = cAgent.BaseFolder.Guid;
|
||||
CapsPath = cAgent.CapsPath;
|
||||
ChildrenCapSeeds = cAgent.ChildrenCapSeeds;
|
||||
Viewer = cAgent.Viewer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace OpenSim.Framework
|
|||
UUID AgentID { get; set; }
|
||||
|
||||
OSDMap Pack();
|
||||
void Unpack(OSDMap map);
|
||||
void Unpack(OSDMap map, IScene scene);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -122,7 +122,7 @@ namespace OpenSim.Framework
|
|||
return args;
|
||||
}
|
||||
|
||||
public void Unpack(OSDMap args)
|
||||
public void Unpack(OSDMap args, IScene scene)
|
||||
{
|
||||
if (args.ContainsKey("region_handle"))
|
||||
UInt64.TryParse(args["region_handle"].AsString(), out RegionHandle);
|
||||
|
@ -329,6 +329,10 @@ namespace OpenSim.Framework
|
|||
|
||||
public string CallbackURI;
|
||||
|
||||
// These two must have the same Count
|
||||
public List<ISceneObject> AttachmentObjects;
|
||||
public List<string> AttachmentObjectStates;
|
||||
|
||||
public virtual OSDMap Pack()
|
||||
{
|
||||
m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data");
|
||||
|
@ -441,7 +445,30 @@ namespace OpenSim.Framework
|
|||
if ((CallbackURI != null) && (!CallbackURI.Equals("")))
|
||||
args["callback_uri"] = OSD.FromString(CallbackURI);
|
||||
|
||||
// Attachment objects for fatpack messages
|
||||
if (AttachmentObjects != null)
|
||||
{
|
||||
int i = 0;
|
||||
OSDArray attObjs = new OSDArray(AttachmentObjects.Count);
|
||||
foreach (ISceneObject so in AttachmentObjects)
|
||||
{
|
||||
OSDMap info = new OSDMap(4);
|
||||
info["sog"] = OSD.FromString(so.ToXml2());
|
||||
info["extra"] = OSD.FromString(so.ExtraToXmlString());
|
||||
info["modified"] = OSD.FromBoolean(so.HasGroupChanged);
|
||||
try
|
||||
{
|
||||
info["state"] = OSD.FromString(AttachmentObjectStates[i++]);
|
||||
}
|
||||
catch (IndexOutOfRangeException e)
|
||||
{
|
||||
m_log.WarnFormat("[CHILD AGENT DATA]: scrtips list is shorter than object list.");
|
||||
}
|
||||
|
||||
attObjs.Add(info);
|
||||
}
|
||||
args["attach_objects"] = attObjs;
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
|
@ -450,7 +477,7 @@ namespace OpenSim.Framework
|
|||
/// Avoiding reflection makes it painful to write, but that's the price!
|
||||
/// </summary>
|
||||
/// <param name="hash"></param>
|
||||
public virtual void Unpack(OSDMap args)
|
||||
public virtual void Unpack(OSDMap args, IScene scene)
|
||||
{
|
||||
m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Unpack data");
|
||||
|
||||
|
@ -628,6 +655,26 @@ namespace OpenSim.Framework
|
|||
|
||||
if (args["callback_uri"] != null)
|
||||
CallbackURI = args["callback_uri"].AsString();
|
||||
|
||||
// Attachment objects
|
||||
if (args["attach_objects"] != null && args["attach_objects"].Type == OSDType.Array)
|
||||
{
|
||||
OSDArray attObjs = (OSDArray)(args["attach_objects"]);
|
||||
AttachmentObjects = new List<ISceneObject>();
|
||||
AttachmentObjectStates = new List<string>();
|
||||
foreach (OSD o in attObjs)
|
||||
{
|
||||
if (o.Type == OSDType.Map)
|
||||
{
|
||||
OSDMap info = (OSDMap)o;
|
||||
ISceneObject so = scene.DeserializeObject(info["sog"].AsString());
|
||||
so.ExtraFromXmlString(info["extra"].AsString());
|
||||
so.HasGroupChanged = info["modified"].AsBoolean();
|
||||
AttachmentObjects.Add(so);
|
||||
AttachmentObjectStates.Add(info["state"].AsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AgentData()
|
||||
|
@ -655,9 +702,9 @@ namespace OpenSim.Framework
|
|||
return base.Pack();
|
||||
}
|
||||
|
||||
public override void Unpack(OSDMap map)
|
||||
public override void Unpack(OSDMap map, IScene scene)
|
||||
{
|
||||
base.Unpack(map);
|
||||
base.Unpack(map, scene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,10 +31,9 @@ using System.Net;
|
|||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
[Serializable]
|
||||
public class ClientInfo
|
||||
{
|
||||
public sAgentCircuitData agentcircuit;
|
||||
public AgentCircuitData agentcircuit;
|
||||
|
||||
public Dictionary<uint, byte[]> needAck;
|
||||
|
||||
|
|
|
@ -592,9 +592,7 @@ namespace OpenSim.Framework.Console
|
|||
string line = ReadLine(m_defaultPrompt + "# ", true, true);
|
||||
|
||||
if (line != String.Empty)
|
||||
{
|
||||
m_log.Info("[CONSOLE] Invalid command");
|
||||
}
|
||||
Output("Invalid command");
|
||||
}
|
||||
|
||||
public void RunCommand(string cmd)
|
||||
|
|
|
@ -572,34 +572,69 @@ namespace OpenSim.Framework
|
|||
|
||||
public class IEntityUpdate
|
||||
{
|
||||
public ISceneEntity Entity;
|
||||
public uint Flags;
|
||||
private ISceneEntity m_entity;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Entity = entity;
|
||||
Flags = flags;
|
||||
m_entity = entity;
|
||||
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 ISceneEntity Entity;
|
||||
// public PrimUpdateFlags Flags;
|
||||
public float TimeDilation;
|
||||
private float m_timeDilation;
|
||||
|
||||
public float TimeDilation
|
||||
{
|
||||
get { return m_timeDilation; }
|
||||
}
|
||||
|
||||
public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation)
|
||||
: base(entity,(uint)flags)
|
||||
: base(entity, (uint)flags)
|
||||
{
|
||||
//Entity = entity;
|
||||
// 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 log4net;
|
||||
|
||||
namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public class PriorityQueue
|
||||
{
|
||||
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
|
||||
// Heap[1..12] for entity updates
|
||||
/// <summary>
|
||||
/// 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;
|
||||
|
||||
// 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_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;
|
||||
|
||||
/// <summary>
|
||||
/// Lock for enqueue and dequeue operations on the priority queue
|
||||
/// </summary>
|
||||
private object m_syncRoot = new object();
|
||||
public object 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);
|
||||
|
||||
for (int i = 0; i < m_heaps.Length; ++i)
|
||||
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
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < m_heaps.Length; ++i)
|
||||
count += m_heaps[i].Count;
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enqueue an item into the specified priority queue
|
||||
/// </summary>
|
||||
public bool Enqueue(uint pqueue, IEntityUpdate value)
|
||||
{
|
||||
LookupItem lookup;
|
||||
|
@ -91,7 +122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
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.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle);
|
||||
m_lookupTable[localid] = lookup;
|
||||
|
@ -99,20 +130,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
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
|
||||
// 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)
|
||||
if (m_heaps[iq].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);
|
||||
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
|
||||
value = item.Value;
|
||||
|
@ -126,7 +199,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
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;
|
||||
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
|
||||
// the entry
|
||||
pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1);
|
||||
pqueue = Util.Clamp<uint>(pqueue, 0, NumberOfQueues - 1);
|
||||
if (pqueue != item.PriorityQueue)
|
||||
{
|
||||
lookup.Heap.Remove(lookup.Handle);
|
||||
|
@ -161,17 +238,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
string s = "";
|
||||
for (int i = 0; i < m_numberOfQueues; i++)
|
||||
{
|
||||
if (s != "") s += ",";
|
||||
s += m_heaps[i].Count.ToString();
|
||||
}
|
||||
for (int i = 0; i < NumberOfQueues; i++)
|
||||
s += String.Format("{0,7} ",m_heaps[i].Count);
|
||||
return s;
|
||||
}
|
||||
|
||||
#endregion PublicMethods
|
||||
|
||||
#region MinHeapItem
|
||||
private struct MinHeapItem : IComparable<MinHeapItem>
|
||||
{
|
|
@ -369,6 +369,7 @@ namespace OpenSim.Framework
|
|||
private int m_physPrimMax = 0;
|
||||
private bool m_clampPrimSize = false;
|
||||
private int m_objectCapacity = 0;
|
||||
private int m_agentCapacity = 0;
|
||||
private string m_regionType = String.Empty;
|
||||
private RegionLightShareData m_windlight = new RegionLightShareData();
|
||||
protected uint m_httpPort;
|
||||
|
@ -547,6 +548,11 @@ namespace OpenSim.Framework
|
|||
get { return m_objectCapacity; }
|
||||
}
|
||||
|
||||
public int AgentCapacity
|
||||
{
|
||||
get { return m_agentCapacity; }
|
||||
}
|
||||
|
||||
public byte AccessLevel
|
||||
{
|
||||
get { return (byte)Util.ConvertMaturityToAccessLevel((uint)RegionSettings.Maturity); }
|
||||
|
@ -821,6 +827,8 @@ namespace OpenSim.Framework
|
|||
|
||||
m_objectCapacity = config.GetInt("MaxPrims", 15000);
|
||||
|
||||
m_agentCapacity = config.GetInt("MaxAgents", 100);
|
||||
|
||||
|
||||
// Multi-tenancy
|
||||
//
|
||||
|
@ -857,6 +865,9 @@ namespace OpenSim.Framework
|
|||
if (m_objectCapacity != 0)
|
||||
config.Set("MaxPrims", m_objectCapacity);
|
||||
|
||||
if (m_agentCapacity != 0)
|
||||
config.Set("MaxAgents", m_agentCapacity);
|
||||
|
||||
if (ScopeID != UUID.Zero)
|
||||
config.Set("ScopeID", ScopeID.ToString());
|
||||
|
||||
|
@ -943,6 +954,9 @@ namespace OpenSim.Framework
|
|||
configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"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,
|
||||
"Scope ID for this region", ScopeID.ToString(), true);
|
||||
|
||||
|
@ -1055,6 +1069,9 @@ namespace OpenSim.Framework
|
|||
case "object_capacity":
|
||||
m_objectCapacity = (int)configuration_result;
|
||||
break;
|
||||
case "agent_capacity":
|
||||
m_agentCapacity = (int)configuration_result;
|
||||
break;
|
||||
case "scope_id":
|
||||
ScopeID = (UUID)configuration_result;
|
||||
break;
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace OpenSim
|
|||
{
|
||||
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;
|
||||
|
||||
public enum Flavour
|
||||
|
|
|
@ -115,7 +115,7 @@ namespace OpenSim.Framework.Tests
|
|||
position2 = new AgentPosition();
|
||||
|
||||
Assert.IsFalse(position2.AgentID == position1.AgentID, "Test Error, position2 should be a blank uninitialized AgentPosition");
|
||||
position2.Unpack(position1.Pack());
|
||||
position2.Unpack(position1.Pack(), null);
|
||||
|
||||
Assert.IsTrue(position2.AgentID == position1.AgentID, "Agent ID didn't unpack the same way it packed");
|
||||
Assert.IsTrue(position2.Position == position1.Position, "Position didn't unpack the same way it packed");
|
||||
|
|
|
@ -1537,6 +1537,23 @@ namespace OpenSim.Framework
|
|||
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>
|
||||
/// Prints the call stack at any given point. Useful for debugging.
|
||||
/// </summary>
|
||||
|
|
|
@ -384,6 +384,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } }
|
||||
public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
|
||||
|
||||
/// <summary>
|
||||
/// Entity update queues
|
||||
/// </summary>
|
||||
public PriorityQueue EntityUpdateQueue { get { return m_entityUpdates; } }
|
||||
|
||||
/// <summary>
|
||||
/// First name of the agent/avatar represented by the client
|
||||
/// </summary>
|
||||
|
@ -3561,6 +3566,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
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)
|
||||
{
|
||||
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>> 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
|
||||
if (maxUpdates <= 0)
|
||||
{
|
||||
|
@ -3688,24 +3736,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
if (update.Entity is ScenePresence)
|
||||
{
|
||||
objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
|
||||
objectUpdates.Value.Add(update);
|
||||
}
|
||||
else
|
||||
{
|
||||
objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
|
||||
objectUpdates.Value.Add(update);
|
||||
}
|
||||
}
|
||||
else if (!canUseImproved)
|
||||
{
|
||||
compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
|
||||
compressedUpdates.Value.Add(update);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
|
||||
{
|
||||
// Self updates go into a special list
|
||||
terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
|
||||
terseAgentUpdates.Value.Add(update);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Everything else goes here
|
||||
terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
|
||||
terseUpdates.Value.Add(update);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Block Construction
|
||||
|
@ -3713,10 +3770,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
|
||||
#region Packet Sending
|
||||
|
||||
//const float TIME_DILATION = 1.0f;
|
||||
|
||||
|
||||
ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
|
||||
|
||||
if (terseAgentUpdateBlocks.IsValueCreated)
|
||||
|
@ -3730,9 +3783,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
for (int i = 0; i < blocks.Count; i++)
|
||||
packet.ObjectData[i] = blocks[i];
|
||||
|
||||
|
||||
OutPacket(packet, ThrottleOutPacketType.Unknown, true);
|
||||
// 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); });
|
||||
}
|
||||
|
||||
if (objectUpdateBlocks.IsValueCreated)
|
||||
|
@ -3746,8 +3798,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
for (int i = 0; i < blocks.Count; i++)
|
||||
packet.ObjectData[i] = blocks[i];
|
||||
|
||||
OutPacket(packet, ThrottleOutPacketType.Task, true);
|
||||
// If any of the packets created from this call go unacknowledged, all of the updates will be resent
|
||||
OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
|
||||
}
|
||||
|
||||
if (compressedUpdateBlocks.IsValueCreated)
|
||||
|
@ -3761,8 +3813,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
for (int i = 0; i < blocks.Count; i++)
|
||||
packet.ObjectData[i] = blocks[i];
|
||||
|
||||
OutPacket(packet, ThrottleOutPacketType.Task, true);
|
||||
// If any of the packets created from this call go unacknowledged, all of the updates will be resent
|
||||
OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
|
||||
}
|
||||
|
||||
if (terseUpdateBlocks.IsValueCreated)
|
||||
|
@ -3776,8 +3828,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
for (int i = 0; i < blocks.Count; i++)
|
||||
packet.ObjectData[i] = blocks[i];
|
||||
|
||||
OutPacket(packet, ThrottleOutPacketType.Task, true);
|
||||
// If any of the packets created from this call go unacknowledged, all of the updates will be resent
|
||||
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;
|
||||
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));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
uint priority = 0; // time based ordering only
|
||||
|
@ -3995,6 +4071,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks =
|
||||
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;
|
||||
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;
|
||||
ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
|
||||
objectFamilyBlocks.Value.Add(objPropDB);
|
||||
familyUpdates.Value.Add(update);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4023,6 +4106,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
SceneObjectPart sop = (SceneObjectPart)update.Entity;
|
||||
ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
|
||||
objectPropertiesBlocks.Value.Add(objPropDB);
|
||||
propertyUpdates.Value.Add(update);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4030,12 +4114,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
|
||||
|
||||
Int32 ppcnt = 0;
|
||||
Int32 pbcnt = 0;
|
||||
// Int32 ppcnt = 0;
|
||||
// Int32 pbcnt = 0;
|
||||
|
||||
if (objectPropertiesBlocks.IsValueCreated)
|
||||
{
|
||||
List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value;
|
||||
List<ObjectPropertyUpdate> updates = propertyUpdates.Value;
|
||||
|
||||
ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
|
||||
packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count];
|
||||
|
@ -4043,28 +4128,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
packet.ObjectData[i] = blocks[i];
|
||||
|
||||
packet.Header.Zerocoded = true;
|
||||
OutPacket(packet, ThrottleOutPacketType.Task, true);
|
||||
|
||||
pbcnt += blocks.Count;
|
||||
ppcnt++;
|
||||
// Pass in the delegate so that if this packet needs to be resent, we send the current properties
|
||||
// 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 fbcnt = 0;
|
||||
// Int32 fpcnt = 0;
|
||||
// Int32 fbcnt = 0;
|
||||
|
||||
if (objectFamilyBlocks.IsValueCreated)
|
||||
{
|
||||
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...
|
||||
for (int i = 0; i < blocks.Count; i++)
|
||||
{
|
||||
|
@ -4073,10 +4156,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
packet.ObjectData = blocks[i];
|
||||
packet.Header.Zerocoded = true;
|
||||
OutPacket(packet, ThrottleOutPacketType.Task);
|
||||
|
||||
fpcnt++;
|
||||
fbcnt++;
|
||||
// Pass in the delegate so that if this packet needs to be resent, we send the current properties
|
||||
// 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++;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4764,7 +4856,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
data.RelativePosition.ToBytes(objectData, 0);
|
||||
data.Velocity.ToBytes(objectData, 12);
|
||||
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);
|
||||
|
||||
ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
|
||||
|
@ -11328,7 +11428,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <returns></returns>
|
||||
public byte[] GetThrottlesPacked(float multiplier)
|
||||
{
|
||||
return m_udpClient.GetThrottlesPacked();
|
||||
return m_udpClient.GetThrottlesPacked(multiplier);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -11362,6 +11462,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// packets (the default), or false to disable splitting if the calling code
|
||||
/// handles splitting manually</param>
|
||||
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)
|
||||
{
|
||||
|
@ -11388,7 +11504,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
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)
|
||||
|
@ -11519,7 +11635,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
info.userEP = m_userEndPoint;
|
||||
info.proxyEP = null;
|
||||
info.agentcircuit = new sAgentCircuitData(RequestClientInfo());
|
||||
info.agentcircuit = RequestClientInfo();
|
||||
|
||||
return info;
|
||||
}
|
||||
|
|
|
@ -135,7 +135,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
private int m_nextOnQueueEmpty = 1;
|
||||
|
||||
/// <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>
|
||||
private readonly TokenBucket m_throttleCategory;
|
||||
/// <summary>Throttle buckets for each packet category</summary>
|
||||
|
@ -176,9 +181,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
m_maxRTO = maxRTO;
|
||||
|
||||
// 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
|
||||
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
|
||||
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
|
||||
m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
|
||||
// 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
|
||||
|
@ -223,26 +228,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <returns>Information about the client connection</returns>
|
||||
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
|
||||
// of pending and needed ACKs for every client every time some method wants information about
|
||||
// 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.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].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.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
|
||||
info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
|
||||
info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle +
|
||||
info.taskThrottle + info.assetThrottle + info.textureThrottle;
|
||||
info.totalThrottle = (int)m_throttleCategory.DripRate;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
@ -346,8 +329,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
|
||||
// State is a subcategory of task that we allocate a percentage to
|
||||
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,
|
||||
// otherwise a throttle could become permanently clogged
|
||||
|
@ -358,19 +339,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
task = Math.Max(task, LLUDPServer.MTU);
|
||||
texture = Math.Max(texture, LLUDPServer.MTU);
|
||||
asset = Math.Max(asset, LLUDPServer.MTU);
|
||||
state = Math.Max(state, LLUDPServer.MTU);
|
||||
|
||||
int total = resend + land + wind + cloud + task + texture + asset + state;
|
||||
|
||||
//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, state, total);
|
||||
//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}",
|
||||
// AgentID, resend, land, wind, cloud, task, texture, asset, total);
|
||||
|
||||
// Update the token buckets with new throttle values
|
||||
TokenBucket bucket;
|
||||
|
||||
bucket = m_throttleCategory;
|
||||
bucket.RequestedDripRate = total;
|
||||
|
||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
|
||||
bucket.RequestedDripRate = resend;
|
||||
|
||||
|
@ -399,22 +375,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
m_packedThrottles = null;
|
||||
}
|
||||
|
||||
public byte[] GetThrottlesPacked()
|
||||
public byte[] GetThrottlesPacked(float multiplier)
|
||||
{
|
||||
byte[] data = m_packedThrottles;
|
||||
|
||||
if (data == null)
|
||||
{
|
||||
float rate;
|
||||
|
||||
data = new byte[7 * 4];
|
||||
int i = 0;
|
||||
|
||||
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate), 0, data, i, 4); i += 4;
|
||||
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate), 0, data, i, 4); i += 4;
|
||||
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate), 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;
|
||||
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate), 0, data, i, 4); i += 4;
|
||||
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate), 0, data, i, 4); i += 4;
|
||||
// multiply by 8 to convert bytes back to bits
|
||||
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier;
|
||||
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
|
||||
|
||||
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier;
|
||||
Buffer.BlockCopy(Utils.FloatToBytes(rate), 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;
|
||||
}
|
||||
|
|
|
@ -297,7 +297,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
delegate(IClientAPI client)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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="category"></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
|
||||
if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
|
||||
|
@ -339,13 +339,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
for (int i = 0; i < packetCount; i++)
|
||||
{
|
||||
byte[] data = datas[i];
|
||||
SendPacketData(udpClient, data, packet.Type, category);
|
||||
SendPacketData(udpClient, data, packet.Type, category, method);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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="type"></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;
|
||||
bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
|
||||
|
@ -411,7 +411,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
#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
|
||||
// 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.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
|
||||
pc.PingID.OldestUnacked = 0;
|
||||
|
||||
SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false);
|
||||
SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null);
|
||||
}
|
||||
|
||||
public void CompletePing(LLUDPClient udpClient, byte pingID)
|
||||
{
|
||||
CompletePingCheckPacket completePing = new CompletePingCheckPacket();
|
||||
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)
|
||||
return;
|
||||
|
@ -488,33 +490,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
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
|
||||
udpClient.BackoffRTO();
|
||||
|
||||
// Resend packets
|
||||
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);
|
||||
}
|
||||
for (int i = 0; i < expiredPackets.Count; ++i)
|
||||
expiredPackets[i].UnackedMethod(expiredPackets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// FIXME: Implement?
|
||||
|
@ -672,7 +672,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
if (packet.Header.AppendedAcks && packet.Header.AckList != null)
|
||||
{
|
||||
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
|
||||
|
@ -681,7 +681,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
PacketAckPacket ackPacket = (PacketAckPacket)packet;
|
||||
|
||||
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
|
||||
return;
|
||||
|
@ -1096,7 +1096,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
if (udpClient.IsConnected)
|
||||
{
|
||||
if (m_resendUnacked)
|
||||
ResendUnacked(udpClient);
|
||||
HandleUnacked(udpClient);
|
||||
|
||||
if (m_sendAcks)
|
||||
SendAcks(udpClient);
|
||||
|
@ -1152,7 +1152,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
nticksUnack++;
|
||||
watch2.Start();
|
||||
|
||||
ResendUnacked(udpClient);
|
||||
HandleUnacked(udpClient);
|
||||
|
||||
watch2.Stop();
|
||||
avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
|
||||
|
|
|
@ -31,6 +31,8 @@ using OpenMetaverse;
|
|||
|
||||
namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
{
|
||||
|
||||
public delegate void UnackedPacketMethod(OutgoingPacket oPacket);
|
||||
/// <summary>
|
||||
/// Holds a reference to the <seealso cref="LLUDPClient"/> this packet is
|
||||
/// destined for, along with the serialized packet data, sequence number
|
||||
|
@ -52,6 +54,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
public int TickCount;
|
||||
/// <summary>Category this packet belongs to</summary>
|
||||
public ThrottleOutPacketType Category;
|
||||
/// <summary>The delegate to be called if this packet is determined to be unacknowledged</summary>
|
||||
public UnackedPacketMethod UnackedMethod;
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
|
@ -60,11 +64,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <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>
|
||||
/// <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;
|
||||
Buffer = buffer;
|
||||
Category = category;
|
||||
UnackedMethod = method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,29 +52,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
public int Texture;
|
||||
/// <summary>Drip rate for asset packets</summary>
|
||||
public int Asset;
|
||||
/// <summary>Drip rate for state packets</summary>
|
||||
public int State;
|
||||
|
||||
/// <summary>Drip rate for the parent token bucket</summary>
|
||||
public int Total;
|
||||
|
||||
/// <summary>Maximum burst rate for resent packets</summary>
|
||||
public int ResendLimit;
|
||||
/// <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>Flag used to enable adaptive throttles</summary>
|
||||
public bool AdaptiveThrottlesEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
|
@ -86,26 +69,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"];
|
||||
|
||||
Resend = throttleConfig.GetInt("resend_default", 12500);
|
||||
Land = throttleConfig.GetInt("land_default", 1000);
|
||||
Wind = throttleConfig.GetInt("wind_default", 1000);
|
||||
Cloud = throttleConfig.GetInt("cloud_default", 1000);
|
||||
Task = throttleConfig.GetInt("task_default", 1000);
|
||||
Texture = throttleConfig.GetInt("texture_default", 1000);
|
||||
Asset = throttleConfig.GetInt("asset_default", 1000);
|
||||
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);
|
||||
Resend = throttleConfig.GetInt("resend_default", 6625);
|
||||
Land = throttleConfig.GetInt("land_default", 9125);
|
||||
Wind = throttleConfig.GetInt("wind_default", 1750);
|
||||
Cloud = throttleConfig.GetInt("cloud_default", 1750);
|
||||
Task = throttleConfig.GetInt("task_default", 18500);
|
||||
Texture = throttleConfig.GetInt("texture_default", 18500);
|
||||
Asset = throttleConfig.GetInt("asset_default", 10500);
|
||||
|
||||
Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
|
||||
TotalLimit = Total;
|
||||
|
||||
AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
@ -128,34 +102,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
return Texture;
|
||||
case ThrottleOutPacketType.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:
|
||||
default:
|
||||
return 0;
|
||||
|
|
|
@ -29,6 +29,8 @@ using System;
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using OpenSim.Framework;
|
||||
|
||||
using log4net;
|
||||
|
||||
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
|
||||
/// are defined over this interval.
|
||||
/// </summary>
|
||||
private const Int32 m_ticksPerQuantum = 1000;
|
||||
protected const Int32 m_ticksPerQuantum = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// This is the number of quantums worth of packets that can
|
||||
/// be accommodated during a burst
|
||||
/// </summary>
|
||||
private const Double m_quantumsPerBurst = 1.5;
|
||||
protected const Double m_quantumsPerBurst = 1.5;
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
private const Int32 m_minimumDripRate = 1400;
|
||||
protected const Int32 m_minimumDripRate = 1400;
|
||||
|
||||
/// <summary>Time of the last drip, in system ticks</summary>
|
||||
private Int32 m_lastDrip;
|
||||
protected Int32 m_lastDrip;
|
||||
|
||||
/// <summary>
|
||||
/// The number of bytes that can be sent at this moment. This is the
|
||||
/// current number of tokens in the bucket
|
||||
/// </summary>
|
||||
private Int64 m_tokenCount;
|
||||
protected Int64 m_tokenCount;
|
||||
|
||||
/// <summary>
|
||||
/// Map of children buckets and their requested maximum burst rate
|
||||
/// </summary>
|
||||
private Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>();
|
||||
protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>();
|
||||
|
||||
#region Properties
|
||||
|
||||
|
@ -81,7 +83,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// parent. The parent bucket will limit the aggregate bandwidth of all
|
||||
/// of its children buckets
|
||||
/// </summary>
|
||||
private TokenBucket m_parent;
|
||||
protected TokenBucket m_parent;
|
||||
public TokenBucket 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
|
||||
/// also sets the total request for leaf nodes
|
||||
/// </summary>
|
||||
private Int64 m_burstRate;
|
||||
protected Int64 m_burstRate;
|
||||
public Int64 RequestedBurstRate
|
||||
{
|
||||
get { return m_burstRate; }
|
||||
|
@ -118,8 +120,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <remarks>Tokens are added to the bucket any time
|
||||
/// <seealso cref="RemoveTokens"/> is called, at the granularity of
|
||||
/// the system tick interval (typically around 15-22ms)</remarks>
|
||||
private Int64 m_dripRate;
|
||||
public Int64 RequestedDripRate
|
||||
protected Int64 m_dripRate;
|
||||
public virtual Int64 RequestedDripRate
|
||||
{
|
||||
get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
|
||||
set {
|
||||
|
@ -131,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
|
||||
public Int64 DripRate
|
||||
public virtual Int64 DripRate
|
||||
{
|
||||
get {
|
||||
if (m_parent == null)
|
||||
|
@ -149,7 +151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// The current total of the requested maximum burst rates of
|
||||
/// this bucket's children buckets.
|
||||
/// </summary>
|
||||
private Int64 m_totalDripRequest;
|
||||
protected Int64 m_totalDripRequest;
|
||||
public Int64 TotalDripRequest
|
||||
{
|
||||
get { return m_totalDripRequest; }
|
||||
|
@ -177,7 +179,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
RequestedDripRate = dripRate;
|
||||
// TotalDripRequest = dripRate; // this will be overwritten when a child node registers
|
||||
// MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst);
|
||||
m_lastDrip = Environment.TickCount & Int32.MaxValue;
|
||||
m_lastDrip = Util.EnvironmentTickCount();
|
||||
}
|
||||
|
||||
#endregion Constructor
|
||||
|
@ -189,7 +191,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// hierarchy. However, if any of the parents is over-booked, then
|
||||
/// the modifier will be less than 1.
|
||||
/// </summary>
|
||||
private double DripRateModifier()
|
||||
protected double DripRateModifier()
|
||||
{
|
||||
Int64 driprate = DripRate;
|
||||
return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest;
|
||||
|
@ -197,7 +199,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
private double BurstRateModifier()
|
||||
protected double BurstRateModifier()
|
||||
{
|
||||
// for now... burst rate is always m_quantumsPerBurst (constant)
|
||||
// larger than drip rate so the ratio of burst requests is the
|
||||
|
@ -211,12 +213,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// </summary>
|
||||
public void RegisterRequest(TokenBucket child, Int64 request)
|
||||
{
|
||||
m_children[child] = request;
|
||||
// m_totalDripRequest = m_children.Values.Sum();
|
||||
lock (m_children)
|
||||
{
|
||||
m_children[child] = request;
|
||||
// m_totalDripRequest = m_children.Values.Sum();
|
||||
|
||||
m_totalDripRequest = 0;
|
||||
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
|
||||
m_totalDripRequest += cref.Value;
|
||||
m_totalDripRequest = 0;
|
||||
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
|
||||
m_totalDripRequest += cref.Value;
|
||||
}
|
||||
|
||||
// Pass the new values up to the parent
|
||||
if (m_parent != null)
|
||||
|
@ -229,12 +234,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// </summary>
|
||||
public void UnregisterRequest(TokenBucket child)
|
||||
{
|
||||
m_children.Remove(child);
|
||||
// m_totalDripRequest = m_children.Values.Sum();
|
||||
lock (m_children)
|
||||
{
|
||||
m_children.Remove(child);
|
||||
// m_totalDripRequest = m_children.Values.Sum();
|
||||
|
||||
m_totalDripRequest = 0;
|
||||
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
|
||||
m_totalDripRequest += cref.Value;
|
||||
}
|
||||
|
||||
m_totalDripRequest = 0;
|
||||
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
|
||||
m_totalDripRequest += cref.Value;
|
||||
|
||||
// Pass the new values up to the parent
|
||||
if (m_parent != null)
|
||||
|
@ -268,7 +277,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// Deposit tokens into the bucket from a child bucket that did
|
||||
/// not use all of its available tokens
|
||||
/// </summary>
|
||||
private void Deposit(Int64 count)
|
||||
protected void Deposit(Int64 count)
|
||||
{
|
||||
m_tokenCount += count;
|
||||
|
||||
|
@ -285,7 +294,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// call to Drip
|
||||
/// </summary>
|
||||
/// <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
|
||||
// with no drip rate...
|
||||
|
@ -297,10 +306,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
// Determine the interval over which we are adding tokens, never add
|
||||
// more than a single quantum of tokens
|
||||
Int32 now = Environment.TickCount & Int32.MaxValue;
|
||||
Int32 deltaMS = Math.Min(now - m_lastDrip, m_ticksPerQuantum);
|
||||
|
||||
m_lastDrip = now;
|
||||
Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum);
|
||||
m_lastDrip = Util.EnvironmentTickCount();
|
||||
|
||||
// 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
|
||||
|
@ -310,4 +317,77 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
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>
|
||||
private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>();
|
||||
/// <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>
|
||||
/// Add an unacked packet to the collection
|
||||
|
@ -83,15 +85,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
/// <param name="sequenceNumber">Sequence number of the packet to
|
||||
/// acknowledge</param>
|
||||
/// <param name="currentTime">Current value of Environment.TickCount</param>
|
||||
/// <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>
|
||||
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>
|
||||
|
@ -130,6 +150,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
// is actually sent out again
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -147,29 +171,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
m_packets[pendingAdd.SequenceNumber] = pendingAdd;
|
||||
|
||||
// Process all the pending removes, including updating statistics and round-trip times
|
||||
PendingAck pendingRemove;
|
||||
OutgoingPacket ackedPacket;
|
||||
while (m_pendingRemoves.TryDequeue(out pendingRemove))
|
||||
PendingAck pendingAcknowledgement;
|
||||
while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement))
|
||||
{
|
||||
if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket))
|
||||
OutgoingPacket ackedPacket;
|
||||
if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket))
|
||||
{
|
||||
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
|
||||
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
|
||||
int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount;
|
||||
int rtt = pendingAcknowledgement.RemoveTime - ackedPacket.TickCount;
|
||||
if (rtt > 0)
|
||||
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>
|
||||
public class AgentAssetTransactions
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(
|
||||
// MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
// Fields
|
||||
private bool m_dumpAssetsToFile;
|
||||
|
@ -149,6 +148,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
|||
|
||||
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.Name = item.Name;
|
||||
asset.Description = item.Description;
|
||||
|
@ -156,8 +159,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
|||
item.AssetID = asset.FullID;
|
||||
|
||||
m_Scene.AssetService.Store(asset);
|
||||
|
||||
part.Inventory.UpdateInventoryItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
|
|||
if (meshConfig == null)
|
||||
return;
|
||||
|
||||
m_enabled = meshConfig.GetBoolean("ColladaMesh", true);
|
||||
m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true);
|
||||
}
|
||||
|
||||
public void AddRegion(Scene pScene)
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
|
|||
if (meshConfig == null)
|
||||
return;
|
||||
|
||||
m_enabled = meshConfig.GetBoolean("ColladaMesh", true);
|
||||
m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true);
|
||||
}
|
||||
|
||||
public void AddRegion(Scene pScene)
|
||||
|
|
|
@ -562,14 +562,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
/// <param name="sp"></param>
|
||||
/// <param name="so"></param>
|
||||
/// <param name="attachmentpoint"></param>
|
||||
/// <param name="AttachOffset"></param>
|
||||
/// <param name="attachOffset"></param>
|
||||
/// <param name="silent"></param>
|
||||
protected void AttachToAgent(ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 AttachOffset, bool silent)
|
||||
protected void AttachToAgent(ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
|
||||
{
|
||||
// don't attach attachments to child agents
|
||||
if (avatar.IsChildAgent) return;
|
||||
|
||||
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1}", Name, avatar.Name);
|
||||
m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", Name, avatar.Name,
|
||||
attachmentpoint, attachOffset, so.RootPart.AttachedPos);
|
||||
|
||||
so.DetachFromBackup();
|
||||
|
||||
|
@ -590,8 +589,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
so.RootPart.PhysActor = null;
|
||||
}
|
||||
|
||||
so.AbsolutePosition = AttachOffset;
|
||||
so.RootPart.AttachedPos = AttachOffset;
|
||||
so.AbsolutePosition = attachOffset;
|
||||
so.RootPart.AttachedPos = attachOffset;
|
||||
so.RootPart.IsAttachment = true;
|
||||
|
||||
so.RootPart.SetParentLocalId(avatar.LocalId);
|
||||
|
|
|
@ -285,11 +285,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
}
|
||||
|
||||
string reason;
|
||||
if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out reason))
|
||||
string version;
|
||||
if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason))
|
||||
{
|
||||
sp.ControllingClient.SendTeleportFailed("Teleport failed: " + reason);
|
||||
return;
|
||||
}
|
||||
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version);
|
||||
|
||||
sp.ControllingClient.SendTeleportStart(teleportFlags);
|
||||
|
||||
|
@ -371,20 +373,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
|
||||
}
|
||||
|
||||
// Expect avatar crossing is a heavy-duty function at the destination.
|
||||
// That is where MakeRoot is called, which fetches appearance and inventory.
|
||||
// Plus triggers OnMakeRoot, which spawns a series of asynchronous updates.
|
||||
//m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
|
||||
// position, false);
|
||||
|
||||
//{
|
||||
// avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
|
||||
// // We should close that agent we just created over at destination...
|
||||
// List<ulong> lst = new List<ulong>();
|
||||
// lst.Add(reg.RegionHandle);
|
||||
// SendCloseChildAgentAsync(avatar.UUID, lst);
|
||||
// return;
|
||||
//}
|
||||
|
||||
SetInTransit(sp.UUID);
|
||||
|
||||
|
@ -426,7 +414,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
|
||||
// TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
|
||||
// trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
|
||||
// that the client contacted the destination before we send the attachments and close things here.
|
||||
// that the client contacted the destination before we close things here.
|
||||
if (!WaitForCallback(sp.UUID))
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
|
@ -437,14 +425,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
return;
|
||||
}
|
||||
|
||||
// CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
|
||||
CrossAttachmentsIntoNewRegion(finalDestination, sp, true);
|
||||
// For backwards compatibility
|
||||
if (version == "Unknown" || version == string.Empty)
|
||||
{
|
||||
// CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
|
||||
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old simulator, sending attachments one by one...");
|
||||
CrossAttachmentsIntoNewRegion(finalDestination, sp, true);
|
||||
}
|
||||
|
||||
// May need to logout or other cleanup
|
||||
AgentHasMovedAway(sp, logout);
|
||||
|
||||
// Well, this is it. The agent is over there.
|
||||
KillEntity(sp.Scene, sp.LocalId);
|
||||
|
||||
// May need to logout or other cleanup
|
||||
AgentHasMovedAway(sp.ControllingClient.SessionId, logout);
|
||||
|
||||
// Now let's make it officially a child agent
|
||||
sp.MakeChildAgent();
|
||||
|
@ -513,8 +507,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
|
||||
}
|
||||
|
||||
protected virtual void AgentHasMovedAway(UUID sessionID, bool logout)
|
||||
protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout)
|
||||
{
|
||||
foreach (SceneObjectGroup sop in sp.Attachments)
|
||||
{
|
||||
sop.Scene.DeleteSceneObject(sop, true);
|
||||
}
|
||||
sp.Attachments.Clear();
|
||||
}
|
||||
|
||||
protected void KillEntity(Scene scene, uint localID)
|
||||
|
@ -784,7 +783,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
|
||||
|
||||
string reason;
|
||||
if (!scene.SimulationService.QueryAccess(neighbourRegion, agent.ControllingClient.AgentId, newpos, out reason))
|
||||
string version;
|
||||
if (!scene.SimulationService.QueryAccess(neighbourRegion, agent.ControllingClient.AgentId, newpos, out version, out reason))
|
||||
{
|
||||
agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel");
|
||||
if (r == null)
|
||||
|
@ -804,7 +804,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
agent.InTransit();
|
||||
|
||||
CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync;
|
||||
d.BeginInvoke(agent, newpos, neighbourx, neighboury, neighbourRegion, isFlying, CrossAgentToNewRegionCompleted, d);
|
||||
d.BeginInvoke(agent, newpos, neighbourx, neighboury, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -861,17 +861,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
icon.EndInvoke(iar);
|
||||
}
|
||||
|
||||
public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying);
|
||||
public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version);
|
||||
|
||||
/// <summary>
|
||||
/// This Closes child agents on neighbouring regions
|
||||
/// Calls an asynchronous method to do so.. so it doesn't lag the sim.
|
||||
/// </summary>
|
||||
protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying)
|
||||
protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version)
|
||||
{
|
||||
ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
|
||||
|
||||
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3}", agent.Firstname, agent.Lastname, neighbourx, neighboury);
|
||||
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3} running version {4}", agent.Firstname, agent.Lastname, neighbourx, neighboury, version);
|
||||
|
||||
Scene m_scene = agent.Scene;
|
||||
|
||||
|
@ -945,7 +945,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
agent.SendOtherAgentsAvatarDataToMe();
|
||||
agent.SendOtherAgentsAppearanceToMe();
|
||||
|
||||
CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
|
||||
// Backwards compatibility
|
||||
if (version == "Unknown" || version == string.Empty)
|
||||
{
|
||||
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old neighbor, passing attachments one by one...");
|
||||
CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
|
||||
}
|
||||
|
||||
AgentHasMovedAway(agent, false);
|
||||
|
||||
// the user may change their profile information in other region,
|
||||
// so the userinfo in UserProfileCache is not reliable any more, delete it
|
||||
|
|
|
@ -142,11 +142,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
return false;
|
||||
}
|
||||
|
||||
protected override void AgentHasMovedAway(UUID sessionID, bool logout)
|
||||
protected override void AgentHasMovedAway(ScenePresence sp, bool logout)
|
||||
{
|
||||
base.AgentHasMovedAway(sp, logout);
|
||||
if (logout)
|
||||
// Log them out of this grid
|
||||
m_aScene.PresenceService.LogoutAgent(sessionID);
|
||||
m_aScene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
|
||||
}
|
||||
|
||||
protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout)
|
||||
|
|
|
@ -182,9 +182,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
|||
public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
|
||||
{
|
||||
InventoryCollection invCol = m_InventoryService.GetFolderContent(userID, folderID);
|
||||
if (UserManager != null)
|
||||
foreach (InventoryItemBase item in invCol.Items)
|
||||
UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
|
||||
Util.FireAndForget(delegate
|
||||
{
|
||||
if (UserManager != null)
|
||||
foreach (InventoryItemBase item in invCol.Items)
|
||||
UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
|
||||
});
|
||||
|
||||
return invCol;
|
||||
}
|
||||
|
|
|
@ -46,10 +46,22 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
|||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private bool m_Enabled = false;
|
||||
private bool m_Initialized = false;
|
||||
// private Scene m_Scene;
|
||||
private Scene m_Scene;
|
||||
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
|
||||
{
|
||||
get { return null; }
|
||||
|
@ -114,12 +126,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
|||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
if (!m_Initialized)
|
||||
{
|
||||
m_Initialized = true;
|
||||
}
|
||||
|
||||
scene.RegisterModuleInterface<IInventoryService>(this);
|
||||
|
||||
if (m_Scene == null)
|
||||
m_Scene = scene;
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
|
@ -173,7 +183,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
|||
|
||||
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)
|
||||
|
|
|
@ -41,6 +41,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
|||
public class LocalSimulationConnectorModule : ISharedRegionModule, ISimulationService
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// Version of this service
|
||||
private const string m_Version = "SIMULATION/0.1";
|
||||
|
||||
private List<Scene> m_sceneList = new List<Scene>();
|
||||
|
||||
private IEntityTransferModule m_AgentTransferModule;
|
||||
|
@ -257,9 +260,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
|||
return false;
|
||||
}
|
||||
|
||||
public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason)
|
||||
public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
|
||||
{
|
||||
reason = "Communications failure";
|
||||
version = m_Version;
|
||||
if (destination == null)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -229,19 +229,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
|||
|
||||
}
|
||||
|
||||
public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason)
|
||||
public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
|
||||
{
|
||||
reason = "Communications failure";
|
||||
version = "Unknown";
|
||||
if (destination == null)
|
||||
return false;
|
||||
|
||||
// Try local first
|
||||
if (m_localBackend.QueryAccess(destination, id, position, out reason))
|
||||
if (m_localBackend.QueryAccess(destination, id, position, out version, out reason))
|
||||
return true;
|
||||
|
||||
// else do the remote thing
|
||||
if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
|
||||
return m_remoteConnector.QueryAccess(destination, id, position, out reason);
|
||||
return m_remoteConnector.QueryAccess(destination, id, position, out version, out reason);
|
||||
|
||||
return false;
|
||||
|
||||
|
|
|
@ -125,7 +125,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
|
|||
else
|
||||
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;
|
||||
|
||||
|
|
|
@ -119,16 +119,40 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
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)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -141,18 +165,20 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
if (!presence.IsChildAgent)
|
||||
{
|
||||
// All avatars other than our own go into pqueue 1
|
||||
if (entity is ScenePresence)
|
||||
return 1;
|
||||
|
||||
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
|
||||
PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
|
||||
if (physActor == null || !physActor.IsPhysical)
|
||||
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);
|
||||
// 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
|
||||
|
@ -197,8 +223,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
// And convert the distance to a priority queue, this computation gives queues
|
||||
// at 10, 20, 40, 80, 160, 320, 640, and 1280m
|
||||
uint pqueue = 1;
|
||||
for (int i = 0; i < 8; i++)
|
||||
uint pqueue = PriorityQueue.NumberOfImmediateQueues;
|
||||
uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues;
|
||||
|
||||
for (int i = 0; i < queues - 1; i++)
|
||||
{
|
||||
if (distance < 10 * Math.Pow(2.0,i))
|
||||
break;
|
||||
|
|
|
@ -1430,6 +1430,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
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>();
|
||||
if (agentTransactions != null)
|
||||
{
|
||||
|
@ -2039,6 +2043,12 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (rot != null)
|
||||
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
|
||||
// to find out if scripts should be activated at all.
|
||||
group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
|
||||
|
|
|
@ -2316,7 +2316,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// <returns></returns>
|
||||
public bool IncomingCreateObject(ISceneObject sog)
|
||||
{
|
||||
//m_log.Debug(" >>> IncomingCreateObject(sog) <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted);
|
||||
//m_log.DebugFormat(" >>> IncomingCreateObject(sog) <<< {0} deleted? {1} isAttach? {2}", ((SceneObjectGroup)sog).AbsolutePosition,
|
||||
// ((SceneObjectGroup)sog).IsDeleted, ((SceneObjectGroup)sog).RootPart.IsAttachment);
|
||||
|
||||
SceneObjectGroup newObject;
|
||||
try
|
||||
{
|
||||
|
@ -3665,6 +3667,15 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
return false;
|
||||
}
|
||||
|
||||
int num = m_sceneGraph.GetNumberOfScenePresences();
|
||||
|
||||
if (num >= RegionInfo.RegionSettings.AgentLimit)
|
||||
{
|
||||
if (!Permissions.IsAdministrator(cAgentData.AgentID))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
|
||||
|
||||
if (childAgentUpdate != null)
|
||||
|
@ -4966,6 +4977,17 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
// child agent creation, thereby emulating the SL behavior.
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -800,6 +800,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
return m_scenePresenceArray;
|
||||
}
|
||||
|
||||
public int GetNumberOfScenePresences()
|
||||
{
|
||||
return m_scenePresenceArray.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request a scene presence by UUID. Fast, indexed lookup.
|
||||
/// </summary>
|
||||
|
|
|
@ -693,8 +693,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
TaskInventoryItem it = GetInventoryItem(item.ItemID);
|
||||
if (it != null)
|
||||
|
||||
{
|
||||
// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
|
||||
|
||||
item.ParentID = m_part.UUID;
|
||||
item.ParentPartID = m_part.UUID;
|
||||
|
||||
|
@ -714,11 +715,13 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
if (fireScriptEvents)
|
||||
m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
|
||||
|
||||
if (considerChanged)
|
||||
{
|
||||
HasInventoryChanged = true;
|
||||
m_part.ParentGroup.HasGroupChanged = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -2340,12 +2340,14 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
#region Update Client(s)
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sends a location update to the client connected to this scenePresence
|
||||
/// </summary>
|
||||
/// <param name="remoteClient"></param>
|
||||
public void SendTerseUpdateToClient(IClientAPI remoteClient)
|
||||
{
|
||||
|
||||
// If the client is inactive, it's getting its updates from another
|
||||
// server.
|
||||
if (remoteClient.IsActive)
|
||||
|
@ -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>
|
||||
/// Send a location/velocity/accelleration update to all agents in scene
|
||||
/// </summary>
|
||||
public void SendTerseUpdateToAllClients()
|
||||
{
|
||||
m_perfMonMS = Util.EnvironmentTickCount();
|
||||
int currentTick = Util.EnvironmentTickCount();
|
||||
|
||||
m_scene.ForEachClient(SendTerseUpdateToClient);
|
||||
// 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.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
|
||||
m_scene.ForEachClient(SendTerseUpdateToClient);
|
||||
|
||||
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
|
||||
}
|
||||
}
|
||||
|
||||
public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
|
||||
|
@ -2632,18 +2649,17 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
cadu.GroupAccess = 0;
|
||||
cadu.Position = AbsolutePosition;
|
||||
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.Velocity = Velocity;
|
||||
|
||||
|
@ -3039,16 +3055,14 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
// Throttles
|
||||
float multiplier = 1;
|
||||
int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
|
||||
if (innacurateNeighbors != 0)
|
||||
{
|
||||
multiplier = 1f / innacurateNeighbors;
|
||||
}
|
||||
if (multiplier <= 0f)
|
||||
{
|
||||
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;
|
||||
}
|
||||
//m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
|
||||
|
||||
cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
|
||||
|
||||
cAgent.HeadRotation = m_headrotation;
|
||||
|
@ -3064,54 +3078,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
cAgent.Appearance = new AvatarAppearance(m_appearance);
|
||||
|
||||
/*
|
||||
try
|
||||
{
|
||||
// We might not pass the Wearables in all cases...
|
||||
// They're only needed so that persistent changes to the appearance
|
||||
// are preserved in the new region where the user is moving to.
|
||||
// But in Hypergrid we might not let this happen.
|
||||
int i = 0;
|
||||
UUID[] wears = new UUID[m_appearance.Wearables.Length * 2];
|
||||
foreach (AvatarWearable aw in m_appearance.Wearables)
|
||||
{
|
||||
if (aw != null)
|
||||
{
|
||||
wears[i++] = aw.ItemID;
|
||||
wears[i++] = aw.AssetID;
|
||||
}
|
||||
else
|
||||
{
|
||||
wears[i++] = UUID.Zero;
|
||||
wears[i++] = UUID.Zero;
|
||||
}
|
||||
}
|
||||
cAgent.Wearables = wears;
|
||||
|
||||
cAgent.VisualParams = m_appearance.VisualParams;
|
||||
|
||||
if (m_appearance.Texture != null)
|
||||
cAgent.AgentTextures = m_appearance.Texture.GetBytes();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Warn("[SCENE PRESENCE]: exception in CopyTo " + e.Message);
|
||||
}
|
||||
|
||||
//Attachments
|
||||
List<int> attPoints = m_appearance.GetAttachedPoints();
|
||||
if (attPoints != null)
|
||||
{
|
||||
//m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count);
|
||||
int i = 0;
|
||||
AvatarAttachment[] attachs = new AvatarAttachment[attPoints.Count];
|
||||
foreach (int point in attPoints)
|
||||
{
|
||||
attachs[i++] = new AvatarAttachment(point, m_appearance.GetAttachedItem(point), m_appearance.GetAttachedAsset(point));
|
||||
}
|
||||
cAgent.Attachments = attachs;
|
||||
}
|
||||
*/
|
||||
lock (scriptedcontrols)
|
||||
{
|
||||
ControllerData[] controls = new ControllerData[scriptedcontrols.Count];
|
||||
|
@ -3131,9 +3097,24 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
catch { }
|
||||
|
||||
// cAgent.GroupID = ??
|
||||
// Groups???
|
||||
|
||||
// Attachment objects
|
||||
if (m_attachments != null && m_attachments.Count > 0)
|
||||
{
|
||||
cAgent.AttachmentObjects = new List<ISceneObject>();
|
||||
cAgent.AttachmentObjectStates = new List<string>();
|
||||
IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
|
||||
foreach (SceneObjectGroup sog in m_attachments)
|
||||
{
|
||||
// We need to make a copy and pass that copy
|
||||
// because of transfers withn the same sim
|
||||
ISceneObject clone = sog.CloneForNewScene();
|
||||
// Attachment module assumes that GroupPosition holds the offsets...!
|
||||
((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos;
|
||||
((SceneObjectGroup)clone).RootPart.IsAttachment = false;
|
||||
cAgent.AttachmentObjects.Add(clone);
|
||||
cAgent.AttachmentObjectStates.Add(sog.GetStateSnapshot());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyFrom(AgentData cAgent)
|
||||
|
@ -3174,50 +3155,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
AddToPhysicalScene(isFlying);
|
||||
}
|
||||
|
||||
/*
|
||||
uint i = 0;
|
||||
try
|
||||
{
|
||||
if (cAgent.Wearables == null)
|
||||
cAgent.Wearables = new UUID[0];
|
||||
AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2];
|
||||
for (uint n = 0; n < cAgent.Wearables.Length; n += 2)
|
||||
{
|
||||
UUID itemId = cAgent.Wearables[n];
|
||||
UUID assetId = cAgent.Wearables[n + 1];
|
||||
wears[i++] = new AvatarWearable(itemId, assetId);
|
||||
}
|
||||
// m_appearance.Wearables = wears;
|
||||
Primitive.TextureEntry textures = null;
|
||||
if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1)
|
||||
textures = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length);
|
||||
|
||||
byte[] visuals = null;
|
||||
|
||||
if ((cAgent.VisualParams != null) && (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT))
|
||||
visuals = (byte[])cAgent.VisualParams.Clone();
|
||||
|
||||
m_appearance = new AvatarAppearance(cAgent.AgentID,wears,textures,visuals);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message);
|
||||
}
|
||||
|
||||
// Attachments
|
||||
try
|
||||
{
|
||||
if (cAgent.Attachments != null)
|
||||
{
|
||||
m_appearance.ClearAttachments();
|
||||
foreach (AvatarAttachment att in cAgent.Attachments)
|
||||
{
|
||||
m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
*/
|
||||
try
|
||||
{
|
||||
lock (scriptedcontrols)
|
||||
|
@ -3247,8 +3184,18 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
catch { }
|
||||
|
||||
//cAgent.GroupID = ??
|
||||
//Groups???
|
||||
if (cAgent.AttachmentObjects != null && cAgent.AttachmentObjects.Count > 0)
|
||||
{
|
||||
m_attachments = new List<SceneObjectGroup>();
|
||||
int i = 0;
|
||||
foreach (ISceneObject so in cAgent.AttachmentObjects)
|
||||
{
|
||||
((SceneObjectGroup)so).LocalId = 0;
|
||||
((SceneObjectGroup)so).RootPart.UpdateFlag = 0;
|
||||
so.SetState(cAgent.AttachmentObjectStates[i++], m_scene);
|
||||
m_scene.IncomingCreateObject(so);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool CopyAgent(out IAgentData agent)
|
||||
|
@ -3271,10 +3218,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
m_updateflag = true;
|
||||
|
||||
// The magic constant 0.95f seems to make walking feel less jerky,
|
||||
// probably because it hackishly accounts for the overall latency of
|
||||
// these Velocity updates -- Diva
|
||||
Velocity = force * .95F;
|
||||
Velocity = force;
|
||||
|
||||
m_forceToApply = null;
|
||||
}
|
||||
|
|
|
@ -81,6 +81,14 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
|||
lock (m_scenes)
|
||||
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(
|
||||
this, "show queues",
|
||||
"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);
|
||||
}
|
||||
|
||||
protected void ShowPQueuesReport(string module, string[] cmd)
|
||||
{
|
||||
MainConsole.Instance.Output(GetPQueuesReport(cmd));
|
||||
}
|
||||
|
||||
protected void ShowQueuesReport(string module, string[] 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>
|
||||
/// Generate UDP Queue data report for each client
|
||||
/// </summary>
|
||||
|
@ -163,9 +250,12 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
|||
protected string GetQueuesReport(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();
|
||||
|
||||
|
@ -224,6 +314,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
|||
return;
|
||||
|
||||
string name = client.Name;
|
||||
if (pname != "" && name != pname)
|
||||
return;
|
||||
|
||||
string regionName = scene.RegionInfo.RegionName;
|
||||
|
||||
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
|
||||
|
@ -249,9 +342,12 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
|||
protected string GetThrottlesReport(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();
|
||||
|
||||
|
@ -314,6 +410,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
|||
return;
|
||||
|
||||
string name = client.Name;
|
||||
if (pname != "" && name != pname)
|
||||
return;
|
||||
|
||||
string regionName = scene.RegionInfo.RegionName;
|
||||
|
||||
LLUDPClient llUdpClient = llClient.UDPClient;
|
||||
|
@ -352,7 +451,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
|||
int maxRegionNameLength = 14;
|
||||
int maxTypeLength = 4;
|
||||
|
||||
string name = "SERVER AGENT LIMITS";
|
||||
string name = "SERVER AGENT RATES";
|
||||
|
||||
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
|
||||
report.Append(GetColumnEntry("-", maxRegionNameLength, columnPadding));
|
||||
|
@ -362,13 +461,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
|
|||
report.AppendFormat(
|
||||
"{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}",
|
||||
(throttleRates.Total * 8) / 1000,
|
||||
(throttleRates.ResendLimit * 8) / 1000,
|
||||
(throttleRates.LandLimit * 8) / 1000,
|
||||
(throttleRates.WindLimit * 8) / 1000,
|
||||
(throttleRates.CloudLimit * 8) / 1000,
|
||||
(throttleRates.TaskLimit * 8) / 1000,
|
||||
(throttleRates.TextureLimit * 8) / 1000,
|
||||
(throttleRates.AssetLimit * 8) / 1000);
|
||||
(throttleRates.Resend * 8) / 1000,
|
||||
(throttleRates.Land * 8) / 1000,
|
||||
(throttleRates.Wind * 8) / 1000,
|
||||
(throttleRates.Cloud * 8) / 1000,
|
||||
(throttleRates.Task * 8) / 1000,
|
||||
(throttleRates.Texture * 8) / 1000,
|
||||
(throttleRates.Asset * 8) / 1000);
|
||||
|
||||
return report.ToString();
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace OpenSim.Server.Handlers.Simulation
|
|||
public class AgentHandler
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private ISimulationService m_SimulationService;
|
||||
|
||||
protected bool m_Proxy = false;
|
||||
|
@ -275,7 +276,7 @@ namespace OpenSim.Server.Handlers.Simulation
|
|||
AgentData agent = new AgentData();
|
||||
try
|
||||
{
|
||||
agent.Unpack(args);
|
||||
agent.Unpack(args, m_SimulationService.GetScene(destination.RegionHandle));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -295,7 +296,7 @@ namespace OpenSim.Server.Handlers.Simulation
|
|||
AgentPosition agent = new AgentPosition();
|
||||
try
|
||||
{
|
||||
agent.Unpack(args);
|
||||
agent.Unpack(args, m_SimulationService.GetScene(destination.RegionHandle));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -342,7 +343,8 @@ namespace OpenSim.Server.Handlers.Simulation
|
|||
destination.RegionID = regionID;
|
||||
|
||||
string reason;
|
||||
bool result = m_SimulationService.QueryAccess(destination, id, position, out reason);
|
||||
string version;
|
||||
bool result = m_SimulationService.QueryAccess(destination, id, position, out version, out reason);
|
||||
|
||||
responsedata["int_response_code"] = HttpStatusCode.OK;
|
||||
|
||||
|
@ -350,6 +352,7 @@ namespace OpenSim.Server.Handlers.Simulation
|
|||
|
||||
resp["success"] = OSD.FromBoolean(result);
|
||||
resp["reason"] = OSD.FromString(reason);
|
||||
resp["version"] = OSD.FromString(version);
|
||||
|
||||
responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
|
||||
}
|
||||
|
|
|
@ -158,6 +158,9 @@ namespace OpenSim.Services.Connectors
|
|||
public InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
|
||||
{
|
||||
InventoryCollection inventory = new InventoryCollection();
|
||||
inventory.Folders = new List<InventoryFolderBase>();
|
||||
inventory.Items = new List<InventoryItemBase>();
|
||||
inventory.UserID = principalID;
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -172,11 +175,6 @@ namespace OpenSim.Services.Connectors
|
|||
if (ret.Count == 0)
|
||||
return null;
|
||||
|
||||
|
||||
inventory.Folders = new List<InventoryFolderBase>();
|
||||
inventory.Items = new List<InventoryItemBase>();
|
||||
inventory.UserID = principalID;
|
||||
|
||||
Dictionary<string,object> folders =
|
||||
(Dictionary<string,object>)ret["FOLDERS"];
|
||||
Dictionary<string,object> items =
|
||||
|
|
|
@ -241,7 +241,7 @@ namespace OpenSim.Services.Connectors.Simulation
|
|||
if (args != null)
|
||||
{
|
||||
agent = new CompleteAgentData();
|
||||
agent.Unpack(args);
|
||||
agent.Unpack(args, null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -256,9 +256,10 @@ namespace OpenSim.Services.Connectors.Simulation
|
|||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason)
|
||||
public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
|
||||
{
|
||||
reason = "Failed to contact destination";
|
||||
version = "Unknown";
|
||||
|
||||
// m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess start, position={0}", position);
|
||||
|
||||
|
@ -274,23 +275,27 @@ namespace OpenSim.Services.Connectors.Simulation
|
|||
try
|
||||
{
|
||||
OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000);
|
||||
bool success = result["success"].AsBoolean();
|
||||
reason = result["reason"].AsString();
|
||||
OSDMap data = (OSDMap)result["_Result"];
|
||||
|
||||
//m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess to {0} returned {1}", uri, success);
|
||||
bool success = result["success"].AsBoolean();
|
||||
reason = data["reason"].AsString();
|
||||
if (data["version"] != null && data["version"].AsString() != string.Empty)
|
||||
version = data["version"].AsString();
|
||||
|
||||
m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess to {0} returned {1} version {2} ({3})", uri, success, version, data["version"].AsString());
|
||||
|
||||
if (!success)
|
||||
{
|
||||
if (result.ContainsKey("Message"))
|
||||
if (data.ContainsKey("Message"))
|
||||
{
|
||||
string message = result["Message"].AsString();
|
||||
string message = data["Message"].AsString();
|
||||
if (message == "Service request failed: [MethodNotAllowed] MethodNotAllowed") // Old style region
|
||||
{
|
||||
m_log.Info("[REMOTE SIMULATION CONNECTOR]: The above web util error was caused by a TP to a sim that doesn't support QUERYACCESS and can be ignored");
|
||||
return true;
|
||||
}
|
||||
|
||||
reason = result["Message"];
|
||||
reason = data["Message"];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Services.Interfaces;
|
||||
|
@ -57,6 +58,9 @@ namespace OpenSim.Services.HypergridService
|
|||
private static IUserAgentService m_UserAgentService;
|
||||
private static ISimulationService m_SimulationService;
|
||||
|
||||
protected string m_AllowedClients = string.Empty;
|
||||
protected string m_DeniedClients = string.Empty;
|
||||
|
||||
private static UUID m_ScopeID;
|
||||
private static bool m_AllowTeleportsToAnyRegion;
|
||||
private static string m_ExternalName;
|
||||
|
@ -104,6 +108,9 @@ namespace OpenSim.Services.HypergridService
|
|||
else if (simulationService != string.Empty)
|
||||
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)
|
||||
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;
|
||||
if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
|
||||
authURL = aCircuit.ServiceURLs["HomeURI"].ToString();
|
||||
m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to login foreign agent {0} {1} @ {2} ({3}) at destination {4}",
|
||||
aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName);
|
||||
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.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
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace OpenSim.Services.Interfaces
|
|||
|
||||
bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent);
|
||||
|
||||
bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason);
|
||||
bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason);
|
||||
|
||||
/// <summary>
|
||||
/// Message from receiving region to departing region, telling it got contacted by the client.
|
||||
|
|
|
@ -244,7 +244,7 @@ namespace OpenSim.Services.InventoryService
|
|||
// connector. So we disregard the principal and look
|
||||
// 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();
|
||||
inventory.UserID = principalID;
|
||||
inventory.Folders = new List<InventoryFolderBase>();
|
||||
|
|
|
@ -77,7 +77,11 @@ namespace OpenSim.Services.LLLoginService
|
|||
protected string m_MapTileURL;
|
||||
protected string m_SearchURL;
|
||||
|
||||
protected string m_AllowedClients;
|
||||
protected string m_DeniedClients;
|
||||
|
||||
IConfig m_LoginServerConfig;
|
||||
IConfig m_ClientsConfig;
|
||||
|
||||
public LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService)
|
||||
{
|
||||
|
@ -106,6 +110,9 @@ namespace OpenSim.Services.LLLoginService
|
|||
m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", 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
|
||||
if (accountService == string.Empty || authService == string.Empty)
|
||||
throw new Exception("LoginService is missing service specifications");
|
||||
|
@ -215,10 +222,37 @@ namespace OpenSim.Services.LLLoginService
|
|||
bool success = false;
|
||||
UUID session = UUID.Random();
|
||||
|
||||
m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} from {2} with user agent {3} starting in {4}",
|
||||
firstName, lastName, clientIP.Address.ToString(), clientVersion, startLocation);
|
||||
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, startLocation, clientVersion, channel, clientIP.Address.ToString(), mac, id0);
|
||||
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
|
||||
//
|
||||
|
|
|
@ -37,7 +37,7 @@ Now see the "Configuring OpenSim" section
|
|||
=== 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
|
||||
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.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue