Merge branch 'master' of ssh://opensimulator.org/var/git/opensim

bulletsim
Dan Lake 2011-04-29 15:49:49 -07:00
commit 8f14c3f04f
125 changed files with 1447 additions and 4563 deletions

View File

@ -1,34 +1,36 @@
The following people have contributed to OpenSim (Thank you The following people have contributed to OpenSim (Thank you
for your effort!) for your effort!)
Add your name in here if you have committed to OpenSim
= Current OpenSim Developers (in very rough order of appearance) = = Current OpenSim Developers (in very rough order of appearance) =
These folks represent the current core team for OpenSim, and are the These folks represent the current core team for OpenSim, and are the
people that make the day to day of OpenSim happen. people that make the day to day of OpenSim happen.
* justincc
* chi11ken (Genkii)
* dahlia
* Melanie Thielker
* Diva (Crista Lopes, University of California, Irvine)
* Dan Lake (Intel)
* Marck
* Mic Bowman (Intel)
* BlueWall (James Hughes)
= Core Developers Following the White Rabbit =
Core developers who have temporarily (we hope) gone chasing the white rabbit.
They are in all similar to the active core developers, except that they haven't
been that active lately, so their voting rights are awaiting their come back.
* MW (Tribal Media AB) * MW (Tribal Media AB)
* Adam Frisby (DeepThink Pty Ltd) * Adam Frisby (DeepThink Pty Ltd)
* MingChen (DeepThink Pty Ltd)
* lbsa71 (Tribal Media AB) * lbsa71 (Tribal Media AB)
* Sean Dague / sdague (IBM)
* Tedd
* justincc
* Teravus (w3z) * Teravus (w3z)
* Johan Berntsson (3Di)
* Ckrinke (Charles Krinke) * Ckrinke (Charles Krinke)
* chi11ken (Genkii)
* adjohn (Genkii)
* Dr Scofield aka Dirk Husemann (IBM Research - Zurich) * Dr Scofield aka Dirk Husemann (IBM Research - Zurich)
* dahlia
* mikem (3Di) * mikem (3Di)
* Melanie Thielker
* Homer_Horwitz * Homer_Horwitz
* idb (Ian Brown)
* Diva (Crista Lopes, University of California, Irvine)
* nlin (3Di) * nlin (3Di)
* Arthur Rodrigo S Valadares (IBM) * Arthur Rodrigo S Valadares (IBM)
* BlueWall (James Hughes) * John Hurliman
= Past Open Sim Developers = = Past Open Sim Developers =
These folks are alumns of the OpenSim core group, but are now These folks are alumns of the OpenSim core group, but are now
@ -44,6 +46,12 @@ where we are today.
* Dalien * Dalien
* Darok * Darok
* Alondria * Alondria
* Sean Dague / sdague (IBM)
* Tedd
* MingChen (DeepThink Pty Ltd)
* adjohn (Genkii)
* idb (Ian Brown)
* Johan Berntsson (3Di)
= Additional OpenSim Contributors = = Additional OpenSim Contributors =
@ -102,6 +110,7 @@ what it is today.
* Misterblue (Intel) * Misterblue (Intel)
* Mircea Kitsune * Mircea Kitsune
* mpallari * mpallari
* MrMonkE
* nornalbion * nornalbion
* Omar Vera Ustariz (IBM) * Omar Vera Ustariz (IBM)
* openlifegrid.com * openlifegrid.com

File diff suppressed because it is too large Load Diff

View File

@ -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; }
}
}
}

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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
}
}

View File

@ -56,15 +56,15 @@ namespace OpenSim.Data.MSSQL
string realm, string storeName) string realm, string storeName)
{ {
m_Realm = realm; m_Realm = realm;
m_ConnectionString = connectionString;
if (storeName != String.Empty) if (storeName != String.Empty)
{ {
Assembly assem = GetType().Assembly;
m_ConnectionString = connectionString;
using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{ {
conn.Open(); conn.Open();
Migration m = new Migration(conn, assem, storeName); Migration m = new Migration(conn, GetType().Assembly, storeName);
m.Update(); m.Update();
} }

View File

@ -61,7 +61,8 @@ namespace OpenSim.Data.MSSQL
} }
catch catch
{ {
// Something went wrong, so we're version 0 // Return -1 to indicate table does not exist
return -1;
} }
} }
return version; return version;

View File

@ -492,12 +492,11 @@ ELSE
using (SqlConnection conn = new SqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
conn.Open();
foreach (TaskInventoryItem taskItem in items) foreach (TaskInventoryItem taskItem in items)
{ {
cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem)); cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem));
conn.Open();
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
cmd.Parameters.Clear(); cmd.Parameters.Clear();
} }
} }
@ -1154,9 +1153,9 @@ VALUES
PrimitiveBaseShape baseShape = new PrimitiveBaseShape(); PrimitiveBaseShape baseShape = new PrimitiveBaseShape();
baseShape.Scale = new Vector3( baseShape.Scale = new Vector3(
Convert.ToSingle(shapeRow["ScaleX"]), (float)Convert.ToDouble(shapeRow["ScaleX"]),
Convert.ToSingle(shapeRow["ScaleY"]), (float)Convert.ToDouble(shapeRow["ScaleY"]),
Convert.ToSingle(shapeRow["ScaleZ"])); (float)Convert.ToDouble(shapeRow["ScaleZ"]));
// paths // paths
baseShape.PCode = Convert.ToByte(shapeRow["PCode"]); baseShape.PCode = Convert.ToByte(shapeRow["PCode"]);
@ -1193,8 +1192,11 @@ VALUES
{ {
} }
if (!(shapeRow["Media"] is System.DBNull)) if (!(shapeRow["Media"] is System.DBNull) )
{
baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]); baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]);
}
return baseShape; return baseShape;
} }
@ -1573,7 +1575,16 @@ VALUES
parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry)); parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry));
parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams)); parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams));
parameters.Add(_Database.CreateParameter("State", s.State)); parameters.Add(_Database.CreateParameter("State", s.State));
parameters.Add(_Database.CreateParameter("Media", null == s.Media ? null : s.Media.ToXml()));
if(null == s.Media )
{
parameters.Add(_Database.CreateParameter("Media", DBNull.Value));
}
else
{
parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml()));
}
return parameters.ToArray(); return parameters.ToArray();
} }

View File

@ -22,7 +22,11 @@ COMMIT
BEGIN TRANSACTION BEGIN TRANSACTION
INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey, accountType) SELECT [UUID] AS UUID, [passwordHash] AS passwordHash, [passwordSalt] AS passwordSalt, [webLoginKey] AS webLoginKey, 'UserAccount' as [accountType] FROM users; IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[users]') AND type in (N'U'))
INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey, accountType) SELECT [UUID] AS UUID, [passwordHash] AS passwordHash, [passwordSalt] AS passwordSalt, [webLoginKey] AS webLoginKey, 'UserAccount' as [accountType] FROM users;
COMMIT
COMMIT

View File

@ -13,5 +13,28 @@ PRIMARY KEY CLUSTERED
) ON [PRIMARY] ) ON [PRIMARY]
COMMIT
:VERSION 2
BEGIN TRANSACTION
CREATE TABLE dbo.Tmp_Avatars
(
PrincipalID uniqueidentifier NOT NULL,
[Name] varchar(32) NOT NULL,
Value text NOT NULL DEFAULT '',
) ON [PRIMARY]
TEXTIMAGE_ON [PRIMARY]
IF EXISTS(SELECT * FROM dbo.Avatars)
EXEC('INSERT INTO dbo.Tmp_Avatars (PrincipalID, Name, Value)
SELECT PrincipalID, CONVERT(text, Name), Value FROM dbo.Avatars WITH (HOLDLOCK TABLOCKX)')
DROP TABLE dbo.Avatars
EXECUTE sp_rename N'dbo.Tmp_Avatars', N'Avatars', 'OBJECT'
COMMIT
COMMIT

View File

@ -15,6 +15,8 @@ COMMIT
BEGIN TRANSACTION BEGIN TRANSACTION
INSERT INTO Friends (PrincipalID, Friend, Flags, Offered) SELECT [ownerID], [friendID], [friendPerms], 0 FROM userfriends; IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[userfriends]') AND type in (N'U'))
INSERT INTO Friends (PrincipalID, Friend, Flags, Offered)
SELECT [ownerID], [friendID], [friendPerms], 0 FROM userfriends;
COMMIT COMMIT

View File

@ -222,4 +222,17 @@ ALTER TABLE [regions] ADD [Token] varchar(255) NOT NULL DEFAULT 0;
COMMIT COMMIT
:VERSION 8
BEGIN TRANSACTION
ALTER TABLE regions ALTER COLUMN regionName VarChar(128)
DROP INDEX IX_regions_name ON dbo.regions
ALTER TABLE regions ALTER COLUMN regionName VarChar(128) null
CREATE NONCLUSTERED INDEX IX_regions_name ON dbo.regions
(
regionName
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
COMMIT

View File

@ -238,7 +238,10 @@ alter table inventoryitems
COMMIT COMMIT
:VERSION 8
ALTER TABLE inventoryitems
ADD CONSTRAINT DF_inventoryitems_creatorID
DEFAULT '00000000-0000-0000-0000-000000000000' FOR creatorID
:GO

View File

@ -7,14 +7,7 @@ CREATE TABLE [Presence] (
[RegionID] uniqueidentifier NOT NULL, [RegionID] uniqueidentifier NOT NULL,
[SessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', [SessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
[SecureSessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', [SecureSessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
[Online] char(5) NOT NULL DEFAULT 'false',
[Login] char(16) NOT NULL DEFAULT '0',
[Logout] char(16) NOT NULL DEFAULT '0',
[Position] char(64) NOT NULL DEFAULT '<0,0,0>',
[LookAt] char(64) NOT NULL DEFAULT '<0,0,0>',
[HomeRegionID] uniqueidentifier NOT NULL,
[HomePosition] CHAR(64) NOT NULL DEFAULT '<0,0,0>',
[HomeLookAt] CHAR(64) NOT NULL DEFAULT '<0,0,0>',
) )
ON [PRIMARY] ON [PRIMARY]
@ -27,4 +20,12 @@ BEGIN TRANSACTION
CREATE UNIQUE INDEX SessionID ON Presence(SessionID); CREATE UNIQUE INDEX SessionID ON Presence(SessionID);
CREATE INDEX UserID ON Presence(UserID); CREATE INDEX UserID ON Presence(UserID);
COMMIT
:VERSION 2
BEGIN TRANSACTION
ALTER TABLE Presence ADD LastSeen DateTime
COMMIT COMMIT

View File

@ -1,4 +1,3 @@
:VERSION 1 :VERSION 1
CREATE TABLE [dbo].[prims]( CREATE TABLE [dbo].[prims](
@ -926,11 +925,121 @@ ALTER TABLE regionsettings ADD loaded_creation_datetime int NOT NULL default 0
COMMIT COMMIT
:VERSION 24 :VERSION 24
-- Added post 0.7
BEGIN TRANSACTION BEGIN TRANSACTION
ALTER TABLE prims ADD COLUMN MediaURL varchar(255) ALTER TABLE prims ADD MediaURL varchar(255)
ALTER TABLE primshapes ADD COLUMN Media TEXT ALTER TABLE primshapes ADD Media TEXT NULL
COMMIT COMMIT
:VERSION 25
BEGIN TRANSACTION
CREATE TABLE "regionwindlight" (
"region_id" varchar(36) NOT NULL DEFAULT '000000-0000-0000-0000-000000000000',
"water_color_r" [float] NOT NULL DEFAULT '4.000000',
"water_color_g" [float] NOT NULL DEFAULT '38.000000',
"water_color_b" [float] NOT NULL DEFAULT '64.000000',
"water_fog_density_exponent" [float] NOT NULL DEFAULT '4.0',
"underwater_fog_modifier" [float] NOT NULL DEFAULT '0.25',
"reflection_wavelet_scale_1" [float] NOT NULL DEFAULT '2.0',
"reflection_wavelet_scale_2" [float] NOT NULL DEFAULT '2.0',
"reflection_wavelet_scale_3" [float] NOT NULL DEFAULT '2.0',
"fresnel_scale" [float] NOT NULL DEFAULT '0.40',
"fresnel_offset" [float] NOT NULL DEFAULT '0.50',
"refract_scale_above" [float] NOT NULL DEFAULT '0.03',
"refract_scale_below" [float] NOT NULL DEFAULT '0.20',
"blur_multiplier" [float] NOT NULL DEFAULT '0.040',
"big_wave_direction_x" [float] NOT NULL DEFAULT '1.05',
"big_wave_direction_y" [float] NOT NULL DEFAULT '-0.42',
"little_wave_direction_x" [float] NOT NULL DEFAULT '1.11',
"little_wave_direction_y" [float] NOT NULL DEFAULT '-1.16',
"normal_map_texture" varchar(36) NOT NULL DEFAULT '822ded49-9a6c-f61c-cb89-6df54f42cdf4',
"horizon_r" [float] NOT NULL DEFAULT '0.25',
"horizon_g" [float] NOT NULL DEFAULT '0.25',
"horizon_b" [float] NOT NULL DEFAULT '0.32',
"horizon_i" [float] NOT NULL DEFAULT '0.32',
"haze_horizon" [float] NOT NULL DEFAULT '0.19',
"blue_density_r" [float] NOT NULL DEFAULT '0.12',
"blue_density_g" [float] NOT NULL DEFAULT '0.22',
"blue_density_b" [float] NOT NULL DEFAULT '0.38',
"blue_density_i" [float] NOT NULL DEFAULT '0.38',
"haze_density" [float] NOT NULL DEFAULT '0.70',
"density_multiplier" [float] NOT NULL DEFAULT '0.18',
"distance_multiplier" [float] NOT NULL DEFAULT '0.8',
"max_altitude" int NOT NULL DEFAULT '1605',
"sun_moon_color_r" [float] NOT NULL DEFAULT '0.24',
"sun_moon_color_g" [float] NOT NULL DEFAULT '0.26',
"sun_moon_color_b" [float] NOT NULL DEFAULT '0.30',
"sun_moon_color_i" [float] NOT NULL DEFAULT '0.30',
"sun_moon_position" [float] NOT NULL DEFAULT '0.317',
"ambient_r" [float] NOT NULL DEFAULT '0.35',
"ambient_g" [float] NOT NULL DEFAULT '0.35',
"ambient_b" [float] NOT NULL DEFAULT '0.35',
"ambient_i" [float] NOT NULL DEFAULT '0.35',
"east_angle" [float] NOT NULL DEFAULT '0.00',
"sun_glow_focus" [float] NOT NULL DEFAULT '0.10',
"sun_glow_size" [float] NOT NULL DEFAULT '1.75',
"scene_gamma" [float] NOT NULL DEFAULT '1.00',
"star_brightness" [float] NOT NULL DEFAULT '0.00',
"cloud_color_r" [float] NOT NULL DEFAULT '0.41',
"cloud_color_g" [float] NOT NULL DEFAULT '0.41',
"cloud_color_b" [float] NOT NULL DEFAULT '0.41',
"cloud_color_i" [float] NOT NULL DEFAULT '0.41',
"cloud_x" [float] NOT NULL DEFAULT '1.00',
"cloud_y" [float] NOT NULL DEFAULT '0.53',
"cloud_density" [float] NOT NULL DEFAULT '1.00',
"cloud_coverage" [float] NOT NULL DEFAULT '0.27',
"cloud_scale" [float] NOT NULL DEFAULT '0.42',
"cloud_detail_x" [float] NOT NULL DEFAULT '1.00',
"cloud_detail_y" [float] NOT NULL DEFAULT '0.53',
"cloud_detail_density" [float] NOT NULL DEFAULT '0.12',
"cloud_scroll_x" [float] NOT NULL DEFAULT '0.20',
"cloud_scroll_x_lock" tinyint NOT NULL DEFAULT '0',
"cloud_scroll_y" [float] NOT NULL DEFAULT '0.01',
"cloud_scroll_y_lock" tinyint NOT NULL DEFAULT '0',
"draw_classic_clouds" tinyint NOT NULL DEFAULT '1',
PRIMARY KEY ("region_id")
)
COMMIT TRANSACTION
:VERSION 26
BEGIN TRANSACTION
ALTER TABLE regionsettings ADD map_tile_ID CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'
COMMIT
:VERSION 27 #---------------------
BEGIN TRANSACTION
ALTER TABLE land ADD MediaType VARCHAR(32) NOT NULL DEFAULT 'none/none'
ALTER TABLE land ADD MediaDescription VARCHAR(255) NOT NULL DEFAULT ''
ALTER TABLE land ADD MediaSize VARCHAR(16) NOT NULL DEFAULT '0,0'
ALTER TABLE land ADD MediaLoop bit NOT NULL DEFAULT 0
ALTER TABLE land ADD ObscureMusic bit NOT NULL DEFAULT 0
ALTER TABLE land ADD ObscureMedia bit NOT NULL DEFAULT 0
COMMIT
:VERSION 28 #---------------------
BEGIN TRANSACTION
ALTER TABLE prims
ADD CONSTRAINT DF_prims_CreatorID
DEFAULT '00000000-0000-0000-0000-000000000000'
FOR CreatorID
ALTER TABLE prims ALTER COLUMN CreatorID uniqueidentifier NOT NULL
ALTER TABLE primitems
ADD CONSTRAINT DF_primitems_CreatorID
DEFAULT '00000000-0000-0000-0000-000000000000'
FOR CreatorID
ALTER TABLE primitems ALTER COLUMN CreatorID uniqueidentifier NOT NULL
COMMIT

View File

@ -19,7 +19,7 @@ CREATE TABLE [UserAccounts] (
:VERSION 2 :VERSION 2
BEGIN TRANSACTION BEGIN TRANSACTION
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[users]') AND type in (N'U'))
INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT [UUID] AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID, INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT [UUID] AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID,
username AS FirstName, username AS FirstName,
lastname AS LastName, lastname AS LastName,

View File

@ -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> /// <summary>
/// Pack AgentCircuitData into an OSDMap for transmission over LLSD XML or LLSD json /// Pack AgentCircuitData into an OSDMap for transmission over LLSD XML or LLSD json
/// </summary> /// </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;
}
}
} }

View File

@ -62,7 +62,7 @@ namespace OpenSim.Framework
UUID AgentID { get; set; } UUID AgentID { get; set; }
OSDMap Pack(); OSDMap Pack();
void Unpack(OSDMap map); void Unpack(OSDMap map, IScene scene);
} }
/// <summary> /// <summary>
@ -122,7 +122,7 @@ namespace OpenSim.Framework
return args; return args;
} }
public void Unpack(OSDMap args) public void Unpack(OSDMap args, IScene scene)
{ {
if (args.ContainsKey("region_handle")) if (args.ContainsKey("region_handle"))
UInt64.TryParse(args["region_handle"].AsString(), out RegionHandle); UInt64.TryParse(args["region_handle"].AsString(), out RegionHandle);
@ -329,6 +329,10 @@ namespace OpenSim.Framework
public string CallbackURI; public string CallbackURI;
// These two must have the same Count
public List<ISceneObject> AttachmentObjects;
public List<string> AttachmentObjectStates;
public virtual OSDMap Pack() public virtual OSDMap Pack()
{ {
m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data"); m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data");
@ -441,7 +445,30 @@ namespace OpenSim.Framework
if ((CallbackURI != null) && (!CallbackURI.Equals(""))) if ((CallbackURI != null) && (!CallbackURI.Equals("")))
args["callback_uri"] = OSD.FromString(CallbackURI); 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; return args;
} }
@ -450,7 +477,7 @@ namespace OpenSim.Framework
/// Avoiding reflection makes it painful to write, but that's the price! /// Avoiding reflection makes it painful to write, but that's the price!
/// </summary> /// </summary>
/// <param name="hash"></param> /// <param name="hash"></param>
public virtual void Unpack(OSDMap args) public virtual void Unpack(OSDMap args, IScene scene)
{ {
m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Unpack data"); m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Unpack data");
@ -628,6 +655,26 @@ namespace OpenSim.Framework
if (args["callback_uri"] != null) if (args["callback_uri"] != null)
CallbackURI = args["callback_uri"].AsString(); 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() public AgentData()
@ -655,9 +702,9 @@ namespace OpenSim.Framework
return base.Pack(); return base.Pack();
} }
public override void Unpack(OSDMap map) public override void Unpack(OSDMap map, IScene scene)
{ {
base.Unpack(map); base.Unpack(map, scene);
} }
} }
} }

View File

@ -31,10 +31,9 @@ using System.Net;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {
[Serializable]
public class ClientInfo public class ClientInfo
{ {
public sAgentCircuitData agentcircuit; public AgentCircuitData agentcircuit;
public Dictionary<uint, byte[]> needAck; public Dictionary<uint, byte[]> needAck;

View File

@ -592,9 +592,7 @@ namespace OpenSim.Framework.Console
string line = ReadLine(m_defaultPrompt + "# ", true, true); string line = ReadLine(m_defaultPrompt + "# ", true, true);
if (line != String.Empty) if (line != String.Empty)
{ Output("Invalid command");
m_log.Info("[CONSOLE] Invalid command");
}
} }
public void RunCommand(string cmd) public void RunCommand(string cmd)

View File

@ -572,34 +572,69 @@ namespace OpenSim.Framework
public class IEntityUpdate public class IEntityUpdate
{ {
public ISceneEntity Entity; private ISceneEntity m_entity;
public uint Flags; private uint m_flags;
private int m_updateTime;
public ISceneEntity Entity
{
get { return m_entity; }
}
public uint Flags
{
get { return m_flags; }
}
public int UpdateTime
{
get { return m_updateTime; }
}
public virtual void Update(IEntityUpdate update) public virtual void Update(IEntityUpdate update)
{ {
this.Flags |= update.Flags; m_flags |= update.Flags;
// Use the older of the updates as the updateTime
if (Util.EnvironmentTickCountCompare(UpdateTime, update.UpdateTime) > 0)
m_updateTime = update.UpdateTime;
} }
public IEntityUpdate(ISceneEntity entity, uint flags) public IEntityUpdate(ISceneEntity entity, uint flags)
{ {
Entity = entity; m_entity = entity;
Flags = flags; m_flags = flags;
m_updateTime = Util.EnvironmentTickCount();
}
public IEntityUpdate(ISceneEntity entity, uint flags, Int32 updateTime)
{
m_entity = entity;
m_flags = flags;
m_updateTime = updateTime;
} }
} }
public class EntityUpdate : IEntityUpdate public class EntityUpdate : IEntityUpdate
{ {
// public ISceneEntity Entity; private float m_timeDilation;
// public PrimUpdateFlags Flags;
public float TimeDilation; public float TimeDilation
{
get { return m_timeDilation; }
}
public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation) public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation)
: base(entity,(uint)flags) : base(entity, (uint)flags)
{ {
//Entity = entity;
// Flags = flags; // Flags = flags;
TimeDilation = timedilation; m_timeDilation = timedilation;
}
public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation, Int32 updateTime)
: base(entity,(uint)flags,updateTime)
{
m_timeDilation = timedilation;
} }
} }

View File

@ -34,50 +34,81 @@ using OpenSim.Framework;
using OpenSim.Framework.Client; using OpenSim.Framework.Client;
using log4net; using log4net;
namespace OpenSim.Region.ClientStack.LindenUDP namespace OpenSim.Framework
{ {
public class PriorityQueue public class PriorityQueue
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
internal delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity); public delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity);
// Heap[0] for self updates /// <summary>
// Heap[1..12] for entity updates /// Total number of queues (priorities) available
/// </summary>
public const uint NumberOfQueues = 12;
internal const uint m_numberOfQueues = 12; /// <summary>
/// Number of queuest (priorities) that are processed immediately
/// </summary.
public const uint NumberOfImmediateQueues = 2;
private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[m_numberOfQueues]; private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[NumberOfQueues];
private Dictionary<uint, LookupItem> m_lookupTable; private Dictionary<uint, LookupItem> m_lookupTable;
// internal state used to ensure the deqeues are spread across the priority
// queues "fairly". queuecounts is the amount to pull from each queue in
// each pass. weighted towards the higher priority queues
private uint m_nextQueue = 0; private uint m_nextQueue = 0;
private uint m_countFromQueue = 0;
private uint[] m_queueCounts = { 8, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1 };
// next request is a counter of the number of updates queued, it provides
// a total ordering on the updates coming through the queue and is more
// lightweight (and more discriminating) than tick count
private UInt64 m_nextRequest = 0; private UInt64 m_nextRequest = 0;
/// <summary>
/// Lock for enqueue and dequeue operations on the priority queue
/// </summary>
private object m_syncRoot = new object(); private object m_syncRoot = new object();
public object SyncRoot { public object SyncRoot {
get { return this.m_syncRoot; } get { return this.m_syncRoot; }
} }
internal PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { } #region constructor
public PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { }
internal PriorityQueue(int capacity) public PriorityQueue(int capacity)
{ {
m_lookupTable = new Dictionary<uint, LookupItem>(capacity); m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
for (int i = 0; i < m_heaps.Length; ++i) for (int i = 0; i < m_heaps.Length; ++i)
m_heaps[i] = new MinHeap<MinHeapItem>(capacity); m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
}
internal int Count m_nextQueue = NumberOfImmediateQueues;
m_countFromQueue = m_queueCounts[m_nextQueue];
}
#endregion Constructor
#region PublicMethods
/// <summary>
/// Return the number of items in the queues
/// </summary>
public int Count
{ {
get get
{ {
int count = 0; int count = 0;
for (int i = 0; i < m_heaps.Length; ++i) for (int i = 0; i < m_heaps.Length; ++i)
count += m_heaps[i].Count; count += m_heaps[i].Count;
return count; return count;
} }
} }
/// <summary>
/// Enqueue an item into the specified priority queue
/// </summary>
public bool Enqueue(uint pqueue, IEntityUpdate value) public bool Enqueue(uint pqueue, IEntityUpdate value)
{ {
LookupItem lookup; LookupItem lookup;
@ -91,7 +122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
lookup.Heap.Remove(lookup.Handle); lookup.Heap.Remove(lookup.Handle);
} }
pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1); pqueue = Util.Clamp<uint>(pqueue, 0, NumberOfQueues - 1);
lookup.Heap = m_heaps[pqueue]; lookup.Heap = m_heaps[pqueue];
lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle); lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle);
m_lookupTable[localid] = lookup; m_lookupTable[localid] = lookup;
@ -99,20 +130,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return true; return true;
} }
internal bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue) /// <summary>
/// Remove an item from one of the queues. Specifically, it removes the
/// oldest item from the next queue in order to provide fair access to
/// all of the queues
/// </summary>
public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue)
{ {
for (int i = 0; i < m_numberOfQueues; ++i) // If there is anything in priority queue 0, return it first no
// matter what else. Breaks fairness. But very useful.
for (int iq = 0; iq < NumberOfImmediateQueues; iq++)
{ {
// To get the fair queing, we cycle through each of the if (m_heaps[iq].Count > 0)
// queues when finding an element to dequeue, this code
// assumes that the distribution of updates in the queues
// is polynomial, probably quadractic (eg distance of PI * R^2)
uint h = (uint)((m_nextQueue + i) % m_numberOfQueues);
if (m_heaps[h].Count > 0)
{ {
m_nextQueue = (uint)((h + 1) % m_numberOfQueues); MinHeapItem item = m_heaps[iq].RemoveMin();
m_lookupTable.Remove(item.Value.Entity.LocalId);
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
value = item.Value;
MinHeapItem item = m_heaps[h].RemoveMin(); return true;
}
}
// To get the fair queing, we cycle through each of the
// queues when finding an element to dequeue.
// We pull (NumberOfQueues - QueueIndex) items from each queue in order
// to give lower numbered queues a higher priority and higher percentage
// of the bandwidth.
// Check for more items to be pulled from the current queue
if (m_heaps[m_nextQueue].Count > 0 && m_countFromQueue > 0)
{
m_countFromQueue--;
MinHeapItem item = m_heaps[m_nextQueue].RemoveMin();
m_lookupTable.Remove(item.Value.Entity.LocalId);
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
value = item.Value;
return true;
}
// Find the next non-immediate queue with updates in it
for (int i = 0; i < NumberOfQueues; ++i)
{
m_nextQueue = (uint)((m_nextQueue + 1) % NumberOfQueues);
m_countFromQueue = m_queueCounts[m_nextQueue];
// if this is one of the immediate queues, just skip it
if (m_nextQueue < NumberOfImmediateQueues)
continue;
if (m_heaps[m_nextQueue].Count > 0)
{
m_countFromQueue--;
MinHeapItem item = m_heaps[m_nextQueue].RemoveMin();
m_lookupTable.Remove(item.Value.Entity.LocalId); m_lookupTable.Remove(item.Value.Entity.LocalId);
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
value = item.Value; value = item.Value;
@ -126,7 +199,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return false; return false;
} }
internal void Reprioritize(UpdatePriorityHandler handler) /// <summary>
/// Reapply the prioritization function to each of the updates currently
/// stored in the priority queues.
/// </summary
public void Reprioritize(UpdatePriorityHandler handler)
{ {
MinHeapItem item; MinHeapItem item;
foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values)) foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
@ -140,7 +217,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
// unless the priority queue has changed, there is no need to modify // unless the priority queue has changed, there is no need to modify
// the entry // the entry
pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1); pqueue = Util.Clamp<uint>(pqueue, 0, NumberOfQueues - 1);
if (pqueue != item.PriorityQueue) if (pqueue != item.PriorityQueue)
{ {
lookup.Heap.Remove(lookup.Handle); lookup.Heap.Remove(lookup.Handle);
@ -161,17 +238,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
} }
/// <summary>
/// </summary>
public override string ToString() public override string ToString()
{ {
string s = ""; string s = "";
for (int i = 0; i < m_numberOfQueues; i++) for (int i = 0; i < NumberOfQueues; i++)
{ s += String.Format("{0,7} ",m_heaps[i].Count);
if (s != "") s += ",";
s += m_heaps[i].Count.ToString();
}
return s; return s;
} }
#endregion PublicMethods
#region MinHeapItem #region MinHeapItem
private struct MinHeapItem : IComparable<MinHeapItem> private struct MinHeapItem : IComparable<MinHeapItem>
{ {

View File

@ -369,6 +369,7 @@ namespace OpenSim.Framework
private int m_physPrimMax = 0; private int m_physPrimMax = 0;
private bool m_clampPrimSize = false; private bool m_clampPrimSize = false;
private int m_objectCapacity = 0; private int m_objectCapacity = 0;
private int m_agentCapacity = 0;
private string m_regionType = String.Empty; private string m_regionType = String.Empty;
private RegionLightShareData m_windlight = new RegionLightShareData(); private RegionLightShareData m_windlight = new RegionLightShareData();
protected uint m_httpPort; protected uint m_httpPort;
@ -547,6 +548,11 @@ namespace OpenSim.Framework
get { return m_objectCapacity; } get { return m_objectCapacity; }
} }
public int AgentCapacity
{
get { return m_agentCapacity; }
}
public byte AccessLevel public byte AccessLevel
{ {
get { return (byte)Util.ConvertMaturityToAccessLevel((uint)RegionSettings.Maturity); } get { return (byte)Util.ConvertMaturityToAccessLevel((uint)RegionSettings.Maturity); }
@ -821,6 +827,8 @@ namespace OpenSim.Framework
m_objectCapacity = config.GetInt("MaxPrims", 15000); m_objectCapacity = config.GetInt("MaxPrims", 15000);
m_agentCapacity = config.GetInt("MaxAgents", 100);
// Multi-tenancy // Multi-tenancy
// //
@ -857,6 +865,9 @@ namespace OpenSim.Framework
if (m_objectCapacity != 0) if (m_objectCapacity != 0)
config.Set("MaxPrims", m_objectCapacity); config.Set("MaxPrims", m_objectCapacity);
if (m_agentCapacity != 0)
config.Set("MaxAgents", m_agentCapacity);
if (ScopeID != UUID.Zero) if (ScopeID != UUID.Zero)
config.Set("ScopeID", ScopeID.ToString()); config.Set("ScopeID", ScopeID.ToString());
@ -943,6 +954,9 @@ namespace OpenSim.Framework
configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
"Max objects this sim will hold", m_objectCapacity.ToString(), true); "Max objects this sim will hold", m_objectCapacity.ToString(), true);
configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
"Max avatars this sim will hold", m_agentCapacity.ToString(), true);
configMember.addConfigurationOption("scope_id", ConfigurationOption.ConfigurationTypes.TYPE_UUID, configMember.addConfigurationOption("scope_id", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
"Scope ID for this region", ScopeID.ToString(), true); "Scope ID for this region", ScopeID.ToString(), true);
@ -1055,6 +1069,9 @@ namespace OpenSim.Framework
case "object_capacity": case "object_capacity":
m_objectCapacity = (int)configuration_result; m_objectCapacity = (int)configuration_result;
break; break;
case "agent_capacity":
m_agentCapacity = (int)configuration_result;
break;
case "scope_id": case "scope_id":
ScopeID = (UUID)configuration_result; ScopeID = (UUID)configuration_result;
break; break;

View File

@ -29,7 +29,7 @@ namespace OpenSim
{ {
public class VersionInfo public class VersionInfo
{ {
private const string VERSION_NUMBER = "0.7.1"; private const string VERSION_NUMBER = "0.7.2";
private const Flavour VERSION_FLAVOUR = Flavour.Dev; private const Flavour VERSION_FLAVOUR = Flavour.Dev;
public enum Flavour public enum Flavour

View File

@ -115,7 +115,7 @@ namespace OpenSim.Framework.Tests
position2 = new AgentPosition(); position2 = new AgentPosition();
Assert.IsFalse(position2.AgentID == position1.AgentID, "Test Error, position2 should be a blank uninitialized 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.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"); Assert.IsTrue(position2.Position == position1.Position, "Position didn't unpack the same way it packed");

View File

@ -1537,6 +1537,23 @@ namespace OpenSim.Framework
return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1); return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1);
} }
// Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount
// Assumes both tcA and tcB came from previous calls to Util.EnvironmentTickCount().
// A positive return value indicates A occured later than B
public static Int32 EnvironmentTickCountCompare(Int32 tcA, Int32 tcB)
{
// A, B and TC are all between 0 and 0x3fffffff
int tc = EnvironmentTickCount();
if (tc - tcA >= 0)
tcA += EnvironmentTickCountMask + 1;
if (tc - tcB >= 0)
tcB += EnvironmentTickCountMask + 1;
return tcA - tcB;
}
/// <summary> /// <summary>
/// Prints the call stack at any given point. Useful for debugging. /// Prints the call stack at any given point. Useful for debugging.
/// </summary> /// </summary>

View File

@ -384,6 +384,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } }
public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
/// <summary>
/// Entity update queues
/// </summary>
public PriorityQueue EntityUpdateQueue { get { return m_entityUpdates; } }
/// <summary> /// <summary>
/// First name of the agent/avatar represented by the client /// First name of the agent/avatar represented by the client
/// </summary> /// </summary>
@ -3561,6 +3566,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
} }
/// <summary>
/// Requeue an EntityUpdate when it was not acknowledged by the client.
/// We will update the priority and put it in the correct queue, merging update flags
/// with any other updates that may be queued for the same entity.
/// The original update time is used for the merged update.
/// </summary>
private void ResendPrimUpdate(EntityUpdate update)
{
// If the update exists in priority queue, it will be updated.
// If it does not exist then it will be added with the current (rather than its original) priority
uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity);
lock (m_entityUpdates.SyncRoot)
m_entityUpdates.Enqueue(priority, update);
}
/// <summary>
/// Requeue a list of EntityUpdates when they were not acknowledged by the client.
/// We will update the priority and put it in the correct queue, merging update flags
/// with any other updates that may be queued for the same entity.
/// The original update time is used for the merged update.
/// </summary>
private void ResendPrimUpdates(List<EntityUpdate> updates, OutgoingPacket oPacket)
{
// m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime);
// Remove the update packet from the list of packets waiting for acknowledgement
// because we are requeuing the list of updates. They will be resent in new packets
// with the most recent state and priority.
m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
// Count this as a resent packet since we are going to requeue all of the updates contained in it
Interlocked.Increment(ref m_udpClient.PacketsResent);
foreach (EntityUpdate update in updates)
ResendPrimUpdate(update);
}
private void ProcessEntityUpdates(int maxUpdates) private void ProcessEntityUpdates(int maxUpdates)
{ {
OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@ -3568,6 +3611,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
// Check to see if this is a flush // Check to see if this is a flush
if (maxUpdates <= 0) if (maxUpdates <= 0)
{ {
@ -3583,7 +3631,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
float avgTimeDilation = 1.0f; float avgTimeDilation = 1.0f;
IEntityUpdate iupdate; IEntityUpdate iupdate;
Int32 timeinqueue; // this is just debugging code & can be dropped later Int32 timeinqueue; // this is just debugging code & can be dropped later
while (updatesThisCall < maxUpdates) while (updatesThisCall < maxUpdates)
{ {
lock (m_entityUpdates.SyncRoot) lock (m_entityUpdates.SyncRoot)
@ -3688,24 +3736,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (update.Entity is ScenePresence) if (update.Entity is ScenePresence)
{ {
objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
objectUpdates.Value.Add(update);
} }
else else
{ {
objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
objectUpdates.Value.Add(update);
} }
} }
else if (!canUseImproved) else if (!canUseImproved)
{ {
compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
compressedUpdates.Value.Add(update);
} }
else else
{ {
if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
{
// Self updates go into a special list // Self updates go into a special list
terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
terseAgentUpdates.Value.Add(update);
}
else else
{
// Everything else goes here // Everything else goes here
terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
terseUpdates.Value.Add(update);
}
} }
#endregion Block Construction #endregion Block Construction
@ -3713,28 +3770,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Packet Sending #region Packet Sending
//const float TIME_DILATION = 1.0f;
ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
if (terseAgentUpdateBlocks.IsValueCreated) if (terseAgentUpdateBlocks.IsValueCreated)
{ {
List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
packet.RegionData.TimeDilation = timeDilation; packet.RegionData.TimeDilation = timeDilation;
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
for (int i = 0; i < blocks.Count; i++) for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i]; packet.ObjectData[i] = blocks[i];
// If any of the packets created from this call go unacknowledged, all of the updates will be resent
OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); });
OutPacket(packet, ThrottleOutPacketType.Unknown, true);
} }
if (objectUpdateBlocks.IsValueCreated) if (objectUpdateBlocks.IsValueCreated)
{ {
List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
@ -3746,8 +3798,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
for (int i = 0; i < blocks.Count; i++) for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i]; packet.ObjectData[i] = blocks[i];
// If any of the packets created from this call go unacknowledged, all of the updates will be resent
OutPacket(packet, ThrottleOutPacketType.Task, true); OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
} }
if (compressedUpdateBlocks.IsValueCreated) if (compressedUpdateBlocks.IsValueCreated)
@ -3761,10 +3813,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
for (int i = 0; i < blocks.Count; i++) for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i]; packet.ObjectData[i] = blocks[i];
// If any of the packets created from this call go unacknowledged, all of the updates will be resent
OutPacket(packet, ThrottleOutPacketType.Task, true); OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
} }
if (terseUpdateBlocks.IsValueCreated) if (terseUpdateBlocks.IsValueCreated)
{ {
List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
@ -3776,8 +3828,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
for (int i = 0; i < blocks.Count; i++) for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i]; packet.ObjectData[i] = blocks[i];
// If any of the packets created from this call go unacknowledged, all of the updates will be resent
OutPacket(packet, ThrottleOutPacketType.Task, true); OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
} }
} }
@ -3969,7 +4021,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
SendFamilyProps = SendFamilyProps || update.SendFamilyProps; SendFamilyProps = SendFamilyProps || update.SendFamilyProps;
SendObjectProps = SendObjectProps || update.SendObjectProps; SendObjectProps = SendObjectProps || update.SendObjectProps;
Flags |= update.Flags; // other properties may need to be updated by base class
base.Update(update);
} }
} }
@ -3980,6 +4033,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false));
} }
private void ResendPropertyUpdate(ObjectPropertyUpdate update)
{
uint priority = 0;
lock (m_entityProps.SyncRoot)
m_entityProps.Enqueue(priority, update);
}
private void ResendPropertyUpdates(List<ObjectPropertyUpdate> updates, OutgoingPacket oPacket)
{
// m_log.WarnFormat("[CLIENT] resending object property {0}",updates[0].UpdateTime);
// Remove the update packet from the list of packets waiting for acknowledgement
// because we are requeuing the list of updates. They will be resent in new packets
// with the most recent state.
m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
// Count this as a resent packet since we are going to requeue all of the updates contained in it
Interlocked.Increment(ref m_udpClient.PacketsResent);
foreach (ObjectPropertyUpdate update in updates)
ResendPropertyUpdate(update);
}
public void SendObjectPropertiesReply(ISceneEntity entity) public void SendObjectPropertiesReply(ISceneEntity entity)
{ {
uint priority = 0; // time based ordering only uint priority = 0; // time based ordering only
@ -3995,6 +4071,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks = OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks =
new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>(); new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>();
OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> familyUpdates =
new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates =
new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
IEntityUpdate iupdate; IEntityUpdate iupdate;
Int32 timeinqueue; // this is just debugging code & can be dropped later Int32 timeinqueue; // this is just debugging code & can be dropped later
@ -4013,6 +4095,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
SceneObjectPart sop = (SceneObjectPart)update.Entity; SceneObjectPart sop = (SceneObjectPart)update.Entity;
ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags); ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
objectFamilyBlocks.Value.Add(objPropDB); objectFamilyBlocks.Value.Add(objPropDB);
familyUpdates.Value.Add(update);
} }
} }
@ -4023,6 +4106,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
SceneObjectPart sop = (SceneObjectPart)update.Entity; SceneObjectPart sop = (SceneObjectPart)update.Entity;
ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop); ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
objectPropertiesBlocks.Value.Add(objPropDB); objectPropertiesBlocks.Value.Add(objPropDB);
propertyUpdates.Value.Add(update);
} }
} }
@ -4030,12 +4114,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
Int32 ppcnt = 0; // Int32 ppcnt = 0;
Int32 pbcnt = 0; // Int32 pbcnt = 0;
if (objectPropertiesBlocks.IsValueCreated) if (objectPropertiesBlocks.IsValueCreated)
{ {
List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value; List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value;
List<ObjectPropertyUpdate> updates = propertyUpdates.Value;
ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count]; packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count];
@ -4043,28 +4128,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
packet.ObjectData[i] = blocks[i]; packet.ObjectData[i] = blocks[i];
packet.Header.Zerocoded = true; packet.Header.Zerocoded = true;
OutPacket(packet, ThrottleOutPacketType.Task, true);
pbcnt += blocks.Count; // Pass in the delegate so that if this packet needs to be resent, we send the current properties
ppcnt++; // of the object rather than the properties when the packet was created
OutPacket(packet, ThrottleOutPacketType.Task, true,
delegate(OutgoingPacket oPacket)
{
ResendPropertyUpdates(updates, oPacket);
});
// pbcnt += blocks.Count;
// ppcnt++;
} }
Int32 fpcnt = 0; // Int32 fpcnt = 0;
Int32 fbcnt = 0; // Int32 fbcnt = 0;
if (objectFamilyBlocks.IsValueCreated) if (objectFamilyBlocks.IsValueCreated)
{ {
List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value; List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value;
// ObjectPropertiesFamilyPacket objPropFamilyPack =
// (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
//
// objPropFamilyPack.ObjectData = new ObjectPropertiesFamilyPacket.ObjectDataBlock[blocks.Count];
// for (int i = 0; i < blocks.Count; i++)
// objPropFamilyPack.ObjectData[i] = blocks[i];
//
// OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task, true);
// one packet per object block... uggh... // one packet per object block... uggh...
for (int i = 0; i < blocks.Count; i++) for (int i = 0; i < blocks.Count; i++)
{ {
@ -4073,10 +4156,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
packet.ObjectData = blocks[i]; packet.ObjectData = blocks[i];
packet.Header.Zerocoded = true; packet.Header.Zerocoded = true;
OutPacket(packet, ThrottleOutPacketType.Task);
fpcnt++; // Pass in the delegate so that if this packet needs to be resent, we send the current properties
fbcnt++; // of the object rather than the properties when the packet was created
List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
updates.Add(familyUpdates.Value[i]);
OutPacket(packet, ThrottleOutPacketType.Task, true,
delegate(OutgoingPacket oPacket)
{
ResendPropertyUpdates(updates, oPacket);
});
// fpcnt++;
// fbcnt++;
} }
} }
@ -4113,7 +4205,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return block; return block;
} }
private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop) private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop)
{ {
//ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
@ -4764,7 +4856,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
data.RelativePosition.ToBytes(objectData, 0); data.RelativePosition.ToBytes(objectData, 0);
data.Velocity.ToBytes(objectData, 12); data.Velocity.ToBytes(objectData, 12);
data.Acceleration.ToBytes(objectData, 24); data.Acceleration.ToBytes(objectData, 24);
data.RotationOffset.ToBytes(objectData, 36); try
{
data.RotationOffset.ToBytes(objectData, 36);
}
catch (Exception e)
{
m_log.Warn("[LLClientView]: exception converting quaternion to bytes, using Quaternion.Identity. Exception: " + e.ToString());
OpenMetaverse.Quaternion.Identity.ToBytes(objectData, 36);
}
data.AngularVelocity.ToBytes(objectData, 48); data.AngularVelocity.ToBytes(objectData, 48);
ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
@ -11328,7 +11428,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <returns></returns> /// <returns></returns>
public byte[] GetThrottlesPacked(float multiplier) public byte[] GetThrottlesPacked(float multiplier)
{ {
return m_udpClient.GetThrottlesPacked(); return m_udpClient.GetThrottlesPacked(multiplier);
} }
/// <summary> /// <summary>
@ -11362,6 +11462,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// packets (the default), or false to disable splitting if the calling code /// packets (the default), or false to disable splitting if the calling code
/// handles splitting manually</param> /// handles splitting manually</param>
protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting) protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting)
{
OutPacket(packet, throttlePacketType, doAutomaticSplitting, null);
}
/// <summary>
/// This is the starting point for sending a simulator packet out to the client
/// </summary>
/// <param name="packet">Packet to send</param>
/// <param name="throttlePacketType">Throttling category for the packet</param>
/// <param name="doAutomaticSplitting">True to automatically split oversized
/// packets (the default), or false to disable splitting if the calling code
/// handles splitting manually</param>
/// <param name="method">The method to be called in the event this packet is reliable
/// and unacknowledged. The server will provide normal resend capability if you do not
/// provide your own method.</param>
protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
{ {
if (m_debugPacketLevel > 0) if (m_debugPacketLevel > 0)
{ {
@ -11388,7 +11504,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type);
} }
m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting); m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method);
} }
public bool AddMoney(int debit) public bool AddMoney(int debit)
@ -11519,7 +11635,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
info.userEP = m_userEndPoint; info.userEP = m_userEndPoint;
info.proxyEP = null; info.proxyEP = null;
info.agentcircuit = new sAgentCircuitData(RequestClientInfo()); info.agentcircuit = RequestClientInfo();
return info; return info;
} }

View File

@ -135,7 +135,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private int m_nextOnQueueEmpty = 1; private int m_nextOnQueueEmpty = 1;
/// <summary>Throttle bucket for this agent's connection</summary> /// <summary>Throttle bucket for this agent's connection</summary>
private readonly TokenBucket m_throttleClient; private readonly AdaptiveTokenBucket m_throttleClient;
public AdaptiveTokenBucket FlowThrottle
{
get { return m_throttleClient; }
}
/// <summary>Throttle bucket for this agent's connection</summary> /// <summary>Throttle bucket for this agent's connection</summary>
private readonly TokenBucket m_throttleCategory; private readonly TokenBucket m_throttleCategory;
/// <summary>Throttle buckets for each packet category</summary> /// <summary>Throttle buckets for each packet category</summary>
@ -176,9 +181,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_maxRTO = maxRTO; m_maxRTO = maxRTO;
// Create a token bucket throttle for this client that has the scene token bucket as a parent // Create a token bucket throttle for this client that has the scene token bucket as a parent
m_throttleClient = new TokenBucket(parentThrottle, rates.TotalLimit); m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled);
// Create a token bucket throttle for the total categary with the client bucket as a throttle // Create a token bucket throttle for the total categary with the client bucket as a throttle
m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit); m_throttleCategory = new TokenBucket(m_throttleClient, 0);
// Create an array of token buckets for this clients different throttle categories // Create an array of token buckets for this clients different throttle categories
m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
@ -189,7 +194,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Initialize the packet outboxes, where packets sit while they are waiting for tokens // Initialize the packet outboxes, where packets sit while they are waiting for tokens
m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
// Initialize the token buckets that control the throttling for each category // Initialize the token buckets that control the throttling for each category
m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetLimit(type)); m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type));
} }
// Default the retransmission timeout to three seconds // Default the retransmission timeout to three seconds
@ -223,26 +228,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <returns>Information about the client connection</returns> /// <returns>Information about the client connection</returns>
public ClientInfo GetClientInfo() public ClientInfo GetClientInfo()
{ {
///<mic>
TokenBucket tb;
tb = m_throttleClient.Parent;
m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest,"ROOT");
tb = m_throttleClient;
m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CLIENT");
tb = m_throttleCategory;
m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CATEGORY");
for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
{
tb = m_throttleCategories[i];
m_log.WarnFormat("[TOKENS] {4} <{0}:{1}>: Actual={2},Requested={3}",AgentID,i,tb.DripRate,tb.RequestedDripRate," BUCKET");
}
///</mic>
// TODO: This data structure is wrong in so many ways. Locking and copying the entire lists // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
// of pending and needed ACKs for every client every time some method wants information about // of pending and needed ACKs for every client every time some method wants information about
// this connection is a recipe for poor performance // this connection is a recipe for poor performance
@ -254,12 +239,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
// info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + info.totalThrottle = (int)m_throttleCategory.DripRate;
info.taskThrottle + info.assetThrottle + info.textureThrottle;
return info; return info;
} }
@ -346,8 +329,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
// State is a subcategory of task that we allocate a percentage to // State is a subcategory of task that we allocate a percentage to
int state = 0; int state = 0;
// int state = (int)((float)task * STATE_TASK_PERCENTAGE);
// task -= state;
// Make sure none of the throttles are set below our packet MTU, // Make sure none of the throttles are set below our packet MTU,
// otherwise a throttle could become permanently clogged // otherwise a throttle could become permanently clogged
@ -358,19 +339,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
task = Math.Max(task, LLUDPServer.MTU); task = Math.Max(task, LLUDPServer.MTU);
texture = Math.Max(texture, LLUDPServer.MTU); texture = Math.Max(texture, LLUDPServer.MTU);
asset = Math.Max(asset, LLUDPServer.MTU); asset = Math.Max(asset, LLUDPServer.MTU);
state = Math.Max(state, LLUDPServer.MTU);
int total = resend + land + wind + cloud + task + texture + asset + state; //int total = resend + land + wind + cloud + task + texture + asset;
//m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
//m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}", // AgentID, resend, land, wind, cloud, task, texture, asset, total);
// AgentID, resend, land, wind, cloud, task, texture, asset, state, total);
// Update the token buckets with new throttle values // Update the token buckets with new throttle values
TokenBucket bucket; TokenBucket bucket;
bucket = m_throttleCategory;
bucket.RequestedDripRate = total;
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
bucket.RequestedDripRate = resend; bucket.RequestedDripRate = resend;
@ -399,22 +375,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_packedThrottles = null; m_packedThrottles = null;
} }
public byte[] GetThrottlesPacked() public byte[] GetThrottlesPacked(float multiplier)
{ {
byte[] data = m_packedThrottles; byte[] data = m_packedThrottles;
if (data == null) if (data == null)
{ {
float rate;
data = new byte[7 * 4]; data = new byte[7 * 4];
int i = 0; int i = 0;
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate), 0, data, i, 4); i += 4; // multiply by 8 to convert bytes back to bits
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate), 0, data, i, 4); i += 4; rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate), 0, data, i, 4); i += 4; Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate), 0, data, i, 4); i += 4;
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate), 0, data, i, 4); i += 4; rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate), 0, data, i, 4); i += 4; Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate), 0, data, i, 4); i += 4;
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
m_packedThrottles = data; m_packedThrottles = data;
} }

View File

@ -297,7 +297,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
delegate(IClientAPI client) delegate(IClientAPI client)
{ {
if (client is LLClientView) if (client is LLClientView)
SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
} }
); );
} }
@ -309,7 +309,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
delegate(IClientAPI client) delegate(IClientAPI client)
{ {
if (client is LLClientView) if (client is LLClientView)
SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
} }
); );
} }
@ -322,7 +322,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="packet"></param> /// <param name="packet"></param>
/// <param name="category"></param> /// <param name="category"></param>
/// <param name="allowSplitting"></param> /// <param name="allowSplitting"></param>
public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting) public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method)
{ {
// CoarseLocationUpdate packets cannot be split in an automated way // CoarseLocationUpdate packets cannot be split in an automated way
if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
@ -339,13 +339,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
for (int i = 0; i < packetCount; i++) for (int i = 0; i < packetCount; i++)
{ {
byte[] data = datas[i]; byte[] data = datas[i];
SendPacketData(udpClient, data, packet.Type, category); SendPacketData(udpClient, data, packet.Type, category, method);
} }
} }
else else
{ {
byte[] data = packet.ToBytes(); byte[] data = packet.ToBytes();
SendPacketData(udpClient, data, packet.Type, category); SendPacketData(udpClient, data, packet.Type, category, method);
} }
} }
@ -356,7 +356,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="category"></param> /// <param name="category"></param>
public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category) public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method)
{ {
int dataLength = data.Length; int dataLength = data.Length;
bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
@ -411,7 +411,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Queue or Send #region Queue or Send
OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
// If we were not provided a method for handling unacked, use the UDPServer default method
outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);
// If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
// continue to display the deleted object until relog. Therefore, we need to always queue a kill object // continue to display the deleted object until relog. Therefore, we need to always queue a kill object
@ -445,7 +447,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
packet.Header.Reliable = false; packet.Header.Reliable = false;
packet.Packets = blocks.ToArray(); packet.Packets = blocks.ToArray();
SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true); SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true, null);
} }
} }
@ -458,17 +460,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// We *could* get OldestUnacked, but it would hurt performance and not provide any benefit // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit
pc.PingID.OldestUnacked = 0; pc.PingID.OldestUnacked = 0;
SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false); SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null);
} }
public void CompletePing(LLUDPClient udpClient, byte pingID) public void CompletePing(LLUDPClient udpClient, byte pingID)
{ {
CompletePingCheckPacket completePing = new CompletePingCheckPacket(); CompletePingCheckPacket completePing = new CompletePingCheckPacket();
completePing.PingID.PingID = pingID; completePing.PingID.PingID = pingID;
SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false); SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null);
} }
public void ResendUnacked(LLUDPClient udpClient) public void HandleUnacked(LLUDPClient udpClient)
{ {
if (!udpClient.IsConnected) if (!udpClient.IsConnected)
return; return;
@ -488,33 +490,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (expiredPackets != null) if (expiredPackets != null)
{ {
//m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO); //m_log.Debug("[LLUDPSERVER]: Handling " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO);
// Exponential backoff of the retransmission timeout // Exponential backoff of the retransmission timeout
udpClient.BackoffRTO(); udpClient.BackoffRTO();
for (int i = 0; i < expiredPackets.Count; ++i)
// Resend packets expiredPackets[i].UnackedMethod(expiredPackets[i]);
for (int i = 0; i < expiredPackets.Count; i++)
{
OutgoingPacket outgoingPacket = expiredPackets[i];
//m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
// outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount);
// Set the resent flag
outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
outgoingPacket.Category = ThrottleOutPacketType.Resend;
// Bump up the resend count on this packet
Interlocked.Increment(ref outgoingPacket.ResendCount);
// Requeue or resend the packet
if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false))
SendPacketFinal(outgoingPacket);
}
} }
} }
public void ResendUnacked(OutgoingPacket outgoingPacket)
{
//m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
// outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount);
// Set the resent flag
outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
outgoingPacket.Category = ThrottleOutPacketType.Resend;
// Bump up the resend count on this packet
Interlocked.Increment(ref outgoingPacket.ResendCount);
// Requeue or resend the packet
if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false))
SendPacketFinal(outgoingPacket);
}
public void Flush(LLUDPClient udpClient) public void Flush(LLUDPClient udpClient)
{ {
// FIXME: Implement? // FIXME: Implement?
@ -672,7 +672,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (packet.Header.AppendedAcks && packet.Header.AckList != null) if (packet.Header.AppendedAcks && packet.Header.AckList != null)
{ {
for (int i = 0; i < packet.Header.AckList.Length; i++) for (int i = 0; i < packet.Header.AckList.Length; i++)
udpClient.NeedAcks.Remove(packet.Header.AckList[i], now, packet.Header.Resent); udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
} }
// Handle PacketAck packets // Handle PacketAck packets
@ -681,7 +681,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
PacketAckPacket ackPacket = (PacketAckPacket)packet; PacketAckPacket ackPacket = (PacketAckPacket)packet;
for (int i = 0; i < ackPacket.Packets.Length; i++) for (int i = 0; i < ackPacket.Packets.Length; i++)
udpClient.NeedAcks.Remove(ackPacket.Packets[i].ID, now, packet.Header.Resent); udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
// We don't need to do anything else with PacketAck packets // We don't need to do anything else with PacketAck packets
return; return;
@ -1096,7 +1096,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (udpClient.IsConnected) if (udpClient.IsConnected)
{ {
if (m_resendUnacked) if (m_resendUnacked)
ResendUnacked(udpClient); HandleUnacked(udpClient);
if (m_sendAcks) if (m_sendAcks)
SendAcks(udpClient); SendAcks(udpClient);
@ -1152,7 +1152,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
nticksUnack++; nticksUnack++;
watch2.Start(); watch2.Start();
ResendUnacked(udpClient); HandleUnacked(udpClient);
watch2.Stop(); watch2.Stop();
avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack); avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);

View File

@ -31,6 +31,8 @@ using OpenMetaverse;
namespace OpenSim.Region.ClientStack.LindenUDP namespace OpenSim.Region.ClientStack.LindenUDP
{ {
public delegate void UnackedPacketMethod(OutgoingPacket oPacket);
/// <summary> /// <summary>
/// Holds a reference to the <seealso cref="LLUDPClient"/> this packet is /// Holds a reference to the <seealso cref="LLUDPClient"/> this packet is
/// destined for, along with the serialized packet data, sequence number /// destined for, along with the serialized packet data, sequence number
@ -52,6 +54,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public int TickCount; public int TickCount;
/// <summary>Category this packet belongs to</summary> /// <summary>Category this packet belongs to</summary>
public ThrottleOutPacketType Category; public ThrottleOutPacketType Category;
/// <summary>The delegate to be called if this packet is determined to be unacknowledged</summary>
public UnackedPacketMethod UnackedMethod;
/// <summary> /// <summary>
/// Default constructor /// Default constructor
@ -60,11 +64,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="buffer">Serialized packet data. If the flags or sequence number /// <param name="buffer">Serialized packet data. If the flags or sequence number
/// need to be updated, they will be injected directly into this binary buffer</param> /// need to be updated, they will be injected directly into this binary buffer</param>
/// <param name="category">Throttling category for this packet</param> /// <param name="category">Throttling category for this packet</param>
public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category) public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method)
{ {
Client = client; Client = client;
Buffer = buffer; Buffer = buffer;
Category = category; Category = category;
UnackedMethod = method;
} }
} }
} }

View File

@ -52,30 +52,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public int Texture; public int Texture;
/// <summary>Drip rate for asset packets</summary> /// <summary>Drip rate for asset packets</summary>
public int Asset; public int Asset;
/// <summary>Drip rate for state packets</summary>
public int State;
/// <summary>Drip rate for the parent token bucket</summary> /// <summary>Drip rate for the parent token bucket</summary>
public int Total; public int Total;
/// <summary>Maximum burst rate for resent packets</summary> /// <summary>Flag used to enable adaptive throttles</summary>
public int ResendLimit; public bool AdaptiveThrottlesEnabled;
/// <summary>Maximum burst rate for land packets</summary>
public int LandLimit;
/// <summary>Maximum burst rate for wind packets</summary>
public int WindLimit;
/// <summary>Maximum burst rate for cloud packets</summary>
public int CloudLimit;
/// <summary>Maximum burst rate for task (state and transaction) packets</summary>
public int TaskLimit;
/// <summary>Maximum burst rate for texture packets</summary>
public int TextureLimit;
/// <summary>Maximum burst rate for asset packets</summary>
public int AssetLimit;
/// <summary>Maximum burst rate for state packets</summary>
public int StateLimit;
/// <summary>Burst rate for the parent token bucket</summary>
public int TotalLimit;
/// <summary> /// <summary>
/// Default constructor /// Default constructor
/// </summary> /// </summary>
@ -86,26 +69,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"];
Resend = throttleConfig.GetInt("resend_default", 12500); Resend = throttleConfig.GetInt("resend_default", 6625);
Land = throttleConfig.GetInt("land_default", 1000); Land = throttleConfig.GetInt("land_default", 9125);
Wind = throttleConfig.GetInt("wind_default", 1000); Wind = throttleConfig.GetInt("wind_default", 1750);
Cloud = throttleConfig.GetInt("cloud_default", 1000); Cloud = throttleConfig.GetInt("cloud_default", 1750);
Task = throttleConfig.GetInt("task_default", 1000); Task = throttleConfig.GetInt("task_default", 18500);
Texture = throttleConfig.GetInt("texture_default", 1000); Texture = throttleConfig.GetInt("texture_default", 18500);
Asset = throttleConfig.GetInt("asset_default", 1000); Asset = throttleConfig.GetInt("asset_default", 10500);
State = throttleConfig.GetInt("state_default", 1000);
ResendLimit = throttleConfig.GetInt("resend_limit", 18750);
LandLimit = throttleConfig.GetInt("land_limit", 29750);
WindLimit = throttleConfig.GetInt("wind_limit", 18750);
CloudLimit = throttleConfig.GetInt("cloud_limit", 18750);
TaskLimit = throttleConfig.GetInt("task_limit", 18750);
TextureLimit = throttleConfig.GetInt("texture_limit", 55750);
AssetLimit = throttleConfig.GetInt("asset_limit", 27500);
StateLimit = throttleConfig.GetInt("state_limit", 37000);
Total = throttleConfig.GetInt("client_throttle_max_bps", 0); Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
TotalLimit = Total;
AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
} }
catch (Exception) { } catch (Exception) { }
} }
@ -128,34 +102,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return Texture; return Texture;
case ThrottleOutPacketType.Asset: case ThrottleOutPacketType.Asset:
return Asset; return Asset;
case ThrottleOutPacketType.State:
return State;
case ThrottleOutPacketType.Unknown:
default:
return 0;
}
}
public int GetLimit(ThrottleOutPacketType type)
{
switch (type)
{
case ThrottleOutPacketType.Resend:
return ResendLimit;
case ThrottleOutPacketType.Land:
return LandLimit;
case ThrottleOutPacketType.Wind:
return WindLimit;
case ThrottleOutPacketType.Cloud:
return CloudLimit;
case ThrottleOutPacketType.Task:
return TaskLimit;
case ThrottleOutPacketType.Texture:
return TextureLimit;
case ThrottleOutPacketType.Asset:
return AssetLimit;
case ThrottleOutPacketType.State:
return StateLimit;
case ThrottleOutPacketType.Unknown: case ThrottleOutPacketType.Unknown:
default: default:
return 0; return 0;

View File

@ -29,6 +29,8 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using OpenSim.Framework;
using log4net; using log4net;
namespace OpenSim.Region.ClientStack.LindenUDP namespace OpenSim.Region.ClientStack.LindenUDP
@ -48,31 +50,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Number of ticks (ms) per quantum, drip rate and max burst /// Number of ticks (ms) per quantum, drip rate and max burst
/// are defined over this interval. /// are defined over this interval.
/// </summary> /// </summary>
private const Int32 m_ticksPerQuantum = 1000; protected const Int32 m_ticksPerQuantum = 1000;
/// <summary> /// <summary>
/// This is the number of quantums worth of packets that can /// This is the number of quantums worth of packets that can
/// be accommodated during a burst /// be accommodated during a burst
/// </summary> /// </summary>
private const Double m_quantumsPerBurst = 1.5; protected const Double m_quantumsPerBurst = 1.5;
/// <summary> /// <summary>
/// </summary> /// </summary>
private const Int32 m_minimumDripRate = 1400; protected const Int32 m_minimumDripRate = 1400;
/// <summary>Time of the last drip, in system ticks</summary> /// <summary>Time of the last drip, in system ticks</summary>
private Int32 m_lastDrip; protected Int32 m_lastDrip;
/// <summary> /// <summary>
/// The number of bytes that can be sent at this moment. This is the /// The number of bytes that can be sent at this moment. This is the
/// current number of tokens in the bucket /// current number of tokens in the bucket
/// </summary> /// </summary>
private Int64 m_tokenCount; protected Int64 m_tokenCount;
/// <summary> /// <summary>
/// Map of children buckets and their requested maximum burst rate /// Map of children buckets and their requested maximum burst rate
/// </summary> /// </summary>
private Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>(); protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>();
#region Properties #region Properties
@ -81,7 +83,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// parent. The parent bucket will limit the aggregate bandwidth of all /// parent. The parent bucket will limit the aggregate bandwidth of all
/// of its children buckets /// of its children buckets
/// </summary> /// </summary>
private TokenBucket m_parent; protected TokenBucket m_parent;
public TokenBucket Parent public TokenBucket Parent
{ {
get { return m_parent; } get { return m_parent; }
@ -93,7 +95,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// of tokens that can accumulate in the bucket at any one time. This /// of tokens that can accumulate in the bucket at any one time. This
/// also sets the total request for leaf nodes /// also sets the total request for leaf nodes
/// </summary> /// </summary>
private Int64 m_burstRate; protected Int64 m_burstRate;
public Int64 RequestedBurstRate public Int64 RequestedBurstRate
{ {
get { return m_burstRate; } get { return m_burstRate; }
@ -118,8 +120,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <remarks>Tokens are added to the bucket any time /// <remarks>Tokens are added to the bucket any time
/// <seealso cref="RemoveTokens"/> is called, at the granularity of /// <seealso cref="RemoveTokens"/> is called, at the granularity of
/// the system tick interval (typically around 15-22ms)</remarks> /// the system tick interval (typically around 15-22ms)</remarks>
private Int64 m_dripRate; protected Int64 m_dripRate;
public Int64 RequestedDripRate public virtual Int64 RequestedDripRate
{ {
get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); } get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
set { set {
@ -131,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
} }
public Int64 DripRate public virtual Int64 DripRate
{ {
get { get {
if (m_parent == null) if (m_parent == null)
@ -149,7 +151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// The current total of the requested maximum burst rates of /// The current total of the requested maximum burst rates of
/// this bucket's children buckets. /// this bucket's children buckets.
/// </summary> /// </summary>
private Int64 m_totalDripRequest; protected Int64 m_totalDripRequest;
public Int64 TotalDripRequest public Int64 TotalDripRequest
{ {
get { return m_totalDripRequest; } get { return m_totalDripRequest; }
@ -177,7 +179,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
RequestedDripRate = dripRate; RequestedDripRate = dripRate;
// TotalDripRequest = dripRate; // this will be overwritten when a child node registers // TotalDripRequest = dripRate; // this will be overwritten when a child node registers
// MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst);
m_lastDrip = Environment.TickCount & Int32.MaxValue; m_lastDrip = Util.EnvironmentTickCount();
} }
#endregion Constructor #endregion Constructor
@ -189,7 +191,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// hierarchy. However, if any of the parents is over-booked, then /// hierarchy. However, if any of the parents is over-booked, then
/// the modifier will be less than 1. /// the modifier will be less than 1.
/// </summary> /// </summary>
private double DripRateModifier() protected double DripRateModifier()
{ {
Int64 driprate = DripRate; Int64 driprate = DripRate;
return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest;
@ -197,7 +199,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary> /// <summary>
/// </summary> /// </summary>
private double BurstRateModifier() protected double BurstRateModifier()
{ {
// for now... burst rate is always m_quantumsPerBurst (constant) // for now... burst rate is always m_quantumsPerBurst (constant)
// larger than drip rate so the ratio of burst requests is the // larger than drip rate so the ratio of burst requests is the
@ -211,12 +213,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// </summary> /// </summary>
public void RegisterRequest(TokenBucket child, Int64 request) public void RegisterRequest(TokenBucket child, Int64 request)
{ {
m_children[child] = request; lock (m_children)
// m_totalDripRequest = m_children.Values.Sum(); {
m_children[child] = request;
// m_totalDripRequest = m_children.Values.Sum();
m_totalDripRequest = 0; m_totalDripRequest = 0;
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
m_totalDripRequest += cref.Value; m_totalDripRequest += cref.Value;
}
// Pass the new values up to the parent // Pass the new values up to the parent
if (m_parent != null) if (m_parent != null)
@ -229,12 +234,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// </summary> /// </summary>
public void UnregisterRequest(TokenBucket child) public void UnregisterRequest(TokenBucket child)
{ {
m_children.Remove(child); lock (m_children)
// m_totalDripRequest = m_children.Values.Sum(); {
m_children.Remove(child);
// m_totalDripRequest = m_children.Values.Sum();
m_totalDripRequest = 0; m_totalDripRequest = 0;
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
m_totalDripRequest += cref.Value; m_totalDripRequest += cref.Value;
}
// Pass the new values up to the parent // Pass the new values up to the parent
if (m_parent != null) if (m_parent != null)
@ -268,7 +277,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Deposit tokens into the bucket from a child bucket that did /// Deposit tokens into the bucket from a child bucket that did
/// not use all of its available tokens /// not use all of its available tokens
/// </summary> /// </summary>
private void Deposit(Int64 count) protected void Deposit(Int64 count)
{ {
m_tokenCount += count; m_tokenCount += count;
@ -285,7 +294,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// call to Drip /// call to Drip
/// </summary> /// </summary>
/// <returns>True if tokens were added to the bucket, otherwise false</returns> /// <returns>True if tokens were added to the bucket, otherwise false</returns>
private void Drip() protected void Drip()
{ {
// This should never happen... means we are a leaf node and were created // This should never happen... means we are a leaf node and were created
// with no drip rate... // with no drip rate...
@ -297,10 +306,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Determine the interval over which we are adding tokens, never add // Determine the interval over which we are adding tokens, never add
// more than a single quantum of tokens // more than a single quantum of tokens
Int32 now = Environment.TickCount & Int32.MaxValue; Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum);
Int32 deltaMS = Math.Min(now - m_lastDrip, m_ticksPerQuantum); m_lastDrip = Util.EnvironmentTickCount();
m_lastDrip = now;
// This can be 0 in the very unusual case that the timer wrapped // This can be 0 in the very unusual case that the timer wrapped
// It can be 0 if we try add tokens at a sub-tick rate // It can be 0 if we try add tokens at a sub-tick rate
@ -310,4 +317,77 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Deposit(deltaMS * DripRate / m_ticksPerQuantum); Deposit(deltaMS * DripRate / m_ticksPerQuantum);
} }
} }
public class AdaptiveTokenBucket : TokenBucket
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// The minimum rate for flow control. Minimum drip rate is one
/// packet per second. Open the throttle to 15 packets per second
/// or about 160kbps.
/// </summary>
protected const Int64 m_minimumFlow = m_minimumDripRate * 15;
// <summary>
// The maximum rate for flow control. Drip rate can never be
// greater than this.
// </summary>
protected Int64 m_maxDripRate = 0;
protected Int64 MaxDripRate
{
get { return (m_maxDripRate == 0 ? m_totalDripRequest : m_maxDripRate); }
set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); }
}
private bool m_enabled = false;
// <summary>
//
// </summary>
public virtual Int64 AdjustedDripRate
{
get { return m_dripRate; }
set {
m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value,m_minimumFlow,MaxDripRate);
m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst);
if (m_parent != null)
m_parent.RegisterRequest(this,m_dripRate);
}
}
// <summary>
//
// </summary>
public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate, bool enabled) : base(parent,maxDripRate)
{
m_enabled = enabled;
if (m_enabled)
{
// m_log.DebugFormat("[TOKENBUCKET] Adaptive throttle enabled");
MaxDripRate = maxDripRate;
AdjustedDripRate = m_minimumFlow;
}
}
// <summary>
//
// </summary>
public void ExpirePackets(Int32 count)
{
// m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count);
if (m_enabled)
AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count));
}
// <summary>
//
// </summary>
public void AcknowledgePackets(Int32 count)
{
if (m_enabled)
AdjustedDripRate = AdjustedDripRate + count;
}
}
} }

View File

@ -65,7 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary>Holds packets that need to be added to the unacknowledged list</summary> /// <summary>Holds packets that need to be added to the unacknowledged list</summary>
private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>(); private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>();
/// <summary>Holds information about pending acknowledgements</summary> /// <summary>Holds information about pending acknowledgements</summary>
private LocklessQueue<PendingAck> m_pendingRemoves = new LocklessQueue<PendingAck>(); private LocklessQueue<PendingAck> m_pendingAcknowledgements = new LocklessQueue<PendingAck>();
/// <summary>Holds information about pending removals</summary>
private LocklessQueue<uint> m_pendingRemoves = new LocklessQueue<uint>();
/// <summary> /// <summary>
/// Add an unacked packet to the collection /// Add an unacked packet to the collection
@ -83,15 +85,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary> /// <summary>
/// Marks a packet as acknowledged /// Marks a packet as acknowledged
/// This method is used when an acknowledgement is received from the network for a previously
/// sent packet. Effects of removal this way are to update unacked byte count, adjust RTT
/// and increase throttle to the coresponding client.
/// </summary> /// </summary>
/// <param name="sequenceNumber">Sequence number of the packet to /// <param name="sequenceNumber">Sequence number of the packet to
/// acknowledge</param> /// acknowledge</param>
/// <param name="currentTime">Current value of Environment.TickCount</param> /// <param name="currentTime">Current value of Environment.TickCount</param>
/// <remarks>This does not immediately acknowledge the packet, it only /// <remarks>This does not immediately acknowledge the packet, it only
/// queues the ack so it can be handled in a thread-safe way later</remarks> /// queues the ack so it can be handled in a thread-safe way later</remarks>
public void Remove(uint sequenceNumber, int currentTime, bool fromResend) public void Acknowledge(uint sequenceNumber, int currentTime, bool fromResend)
{ {
m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend)); m_pendingAcknowledgements.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend));
}
/// <summary>
/// Marks a packet as no longer needing acknowledgement without a received acknowledgement.
/// This method is called when a packet expires and we no longer need an acknowledgement.
/// When some reliable packet types expire, they are handled in a way other than simply
/// resending them. The only effect of removal this way is to update unacked byte count.
/// </summary>
/// <param name="sequenceNumber">Sequence number of the packet to
/// acknowledge</param>
/// <remarks>The does not immediately remove the packet, it only queues the removal
/// so it can be handled in a thread safe way later</remarks>
public void Remove(uint sequenceNumber)
{
m_pendingRemoves.Enqueue(sequenceNumber);
} }
/// <summary> /// <summary>
@ -130,6 +150,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// is actually sent out again // is actually sent out again
packet.TickCount = 0; packet.TickCount = 0;
// As with other network applications, assume that an expired packet is
// an indication of some network problem, slow transmission
packet.Client.FlowThrottle.ExpirePackets(1);
expiredPackets.Add(packet); expiredPackets.Add(packet);
} }
} }
@ -147,29 +171,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_packets[pendingAdd.SequenceNumber] = pendingAdd; m_packets[pendingAdd.SequenceNumber] = pendingAdd;
// Process all the pending removes, including updating statistics and round-trip times // Process all the pending removes, including updating statistics and round-trip times
PendingAck pendingRemove; PendingAck pendingAcknowledgement;
OutgoingPacket ackedPacket; while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement))
while (m_pendingRemoves.TryDequeue(out pendingRemove))
{ {
if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) OutgoingPacket ackedPacket;
if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket))
{ {
if (ackedPacket != null) if (ackedPacket != null)
{ {
m_packets.Remove(pendingRemove.SequenceNumber); m_packets.Remove(pendingAcknowledgement.SequenceNumber);
// As with other network applications, assume that an acknowledged packet is an
// indication that the network can handle a little more load, speed up the transmission
ackedPacket.Client.FlowThrottle.AcknowledgePackets(ackedPacket.Buffer.DataLength);
// Update stats // Update stats
Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
if (!pendingRemove.FromResend) if (!pendingAcknowledgement.FromResend)
{ {
// Calculate the round-trip time for this packet and its ACK // Calculate the round-trip time for this packet and its ACK
int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; int rtt = pendingAcknowledgement.RemoveTime - ackedPacket.TickCount;
if (rtt > 0) if (rtt > 0)
ackedPacket.Client.UpdateRoundTrip(rtt); ackedPacket.Client.UpdateRoundTrip(rtt);
} }
} }
} }
} }
uint pendingRemove;
while(m_pendingRemoves.TryDequeue(out pendingRemove))
{
OutgoingPacket removedPacket;
if (m_packets.TryGetValue(pendingRemove, out removedPacket))
{
if (removedPacket != null)
{
m_packets.Remove(pendingRemove);
// Update stats
Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
}
}
}
} }
} }
} }

View File

@ -41,8 +41,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
/// </summary> /// </summary>
public class AgentAssetTransactions public class AgentAssetTransactions
{ {
// private static readonly ILog m_log = LogManager.GetLogger( // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// MethodBase.GetCurrentMethod().DeclaringType);
// Fields // Fields
private bool m_dumpAssetsToFile; private bool m_dumpAssetsToFile;
@ -149,6 +148,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
if (asset != null) if (asset != null)
{ {
// m_log.DebugFormat(
// "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}",
// item.Name, part.Name, transactionID);
asset.FullID = UUID.Random(); asset.FullID = UUID.Random();
asset.Name = item.Name; asset.Name = item.Name;
asset.Description = item.Description; asset.Description = item.Description;
@ -156,8 +159,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
item.AssetID = asset.FullID; item.AssetID = asset.FullID;
m_Scene.AssetService.Store(asset); m_Scene.AssetService.Store(asset);
part.Inventory.UpdateInventoryItem(item);
} }
} }
} }

View File

@ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
if (meshConfig == null) if (meshConfig == null)
return; return;
m_enabled = meshConfig.GetBoolean("ColladaMesh", true); m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true);
} }
public void AddRegion(Scene pScene) public void AddRegion(Scene pScene)

View File

@ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
if (meshConfig == null) if (meshConfig == null)
return; return;
m_enabled = meshConfig.GetBoolean("ColladaMesh", true); m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true);
} }
public void AddRegion(Scene pScene) public void AddRegion(Scene pScene)

View File

@ -562,14 +562,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
/// <param name="sp"></param> /// <param name="sp"></param>
/// <param name="so"></param> /// <param name="so"></param>
/// <param name="attachmentpoint"></param> /// <param name="attachmentpoint"></param>
/// <param name="AttachOffset"></param> /// <param name="attachOffset"></param>
/// <param name="silent"></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(); so.DetachFromBackup();
@ -590,8 +589,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
so.RootPart.PhysActor = null; so.RootPart.PhysActor = null;
} }
so.AbsolutePosition = AttachOffset; so.AbsolutePosition = attachOffset;
so.RootPart.AttachedPos = AttachOffset; so.RootPart.AttachedPos = attachOffset;
so.RootPart.IsAttachment = true; so.RootPart.IsAttachment = true;
so.RootPart.SetParentLocalId(avatar.LocalId); so.RootPart.SetParentLocalId(avatar.LocalId);

View File

@ -285,11 +285,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
} }
string reason; 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); sp.ControllingClient.SendTeleportFailed("Teleport failed: " + reason);
return; return;
} }
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version);
sp.ControllingClient.SendTeleportStart(teleportFlags); sp.ControllingClient.SendTeleportStart(teleportFlags);
@ -371,20 +373,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); 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); SetInTransit(sp.UUID);
@ -426,7 +414,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which // 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 // 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)) if (!WaitForCallback(sp.UUID))
{ {
m_log.WarnFormat( m_log.WarnFormat(
@ -437,14 +425,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return; return;
} }
// CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it // For backwards compatibility
CrossAttachmentsIntoNewRegion(finalDestination, sp, true); 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. // Well, this is it. The agent is over there.
KillEntity(sp.Scene, sp.LocalId); 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 // Now let's make it officially a child agent
sp.MakeChildAgent(); 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) 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); GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
string reason; 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"); agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel");
if (r == null) if (r == null)
@ -804,7 +804,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
agent.InTransit(); agent.InTransit();
CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; 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; return true;
} }
@ -861,17 +861,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
icon.EndInvoke(iar); 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> /// <summary>
/// This Closes child agents on neighbouring regions /// This Closes child agents on neighbouring regions
/// Calls an asynchronous method to do so.. so it doesn't lag the sim. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
/// </summary> /// </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)); 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; Scene m_scene = agent.Scene;
@ -945,7 +945,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
agent.SendOtherAgentsAvatarDataToMe(); agent.SendOtherAgentsAvatarDataToMe();
agent.SendOtherAgentsAppearanceToMe(); 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, // the user may change their profile information in other region,
// so the userinfo in UserProfileCache is not reliable any more, delete it // so the userinfo in UserProfileCache is not reliable any more, delete it

View File

@ -142,11 +142,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return false; return false;
} }
protected override void AgentHasMovedAway(UUID sessionID, bool logout) protected override void AgentHasMovedAway(ScenePresence sp, bool logout)
{ {
base.AgentHasMovedAway(sp, logout);
if (logout) if (logout)
// Log them out of this grid // 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) protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout)

View File

@ -182,9 +182,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
public InventoryCollection GetFolderContent(UUID userID, UUID folderID) public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
{ {
InventoryCollection invCol = m_InventoryService.GetFolderContent(userID, folderID); InventoryCollection invCol = m_InventoryService.GetFolderContent(userID, folderID);
if (UserManager != null) Util.FireAndForget(delegate
foreach (InventoryItemBase item in invCol.Items) {
UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); if (UserManager != null)
foreach (InventoryItemBase item in invCol.Items)
UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
});
return invCol; return invCol;
} }

View File

@ -46,10 +46,22 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private bool m_Enabled = false; private bool m_Enabled = false;
private bool m_Initialized = false; private Scene m_Scene;
// private Scene m_Scene;
private XInventoryServicesConnector m_RemoteConnector; private XInventoryServicesConnector m_RemoteConnector;
private IUserManagement m_UserManager;
private IUserManagement UserManager
{
get
{
if (m_UserManager == null)
{
m_UserManager = m_Scene.RequestModuleInterface<IUserManagement>();
}
return m_UserManager;
}
}
public Type ReplaceableInterface public Type ReplaceableInterface
{ {
get { return null; } get { return null; }
@ -114,12 +126,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
if (!m_Enabled) if (!m_Enabled)
return; return;
if (!m_Initialized)
{
m_Initialized = true;
}
scene.RegisterModuleInterface<IInventoryService>(this); scene.RegisterModuleInterface<IInventoryService>(this);
if (m_Scene == null)
m_Scene = scene;
} }
public void RemoveRegion(Scene scene) public void RemoveRegion(Scene scene)
@ -173,7 +183,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
public InventoryCollection GetFolderContent(UUID userID, UUID folderID) public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
{ {
return m_RemoteConnector.GetFolderContent(userID, folderID); InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID);
Util.FireAndForget(delegate
{
if (UserManager != null)
foreach (InventoryItemBase item in invCol.Items)
UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
});
return invCol;
} }
public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID) public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)

View File

@ -41,6 +41,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
public class LocalSimulationConnectorModule : ISharedRegionModule, ISimulationService public class LocalSimulationConnectorModule : ISharedRegionModule, ISimulationService
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 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 List<Scene> m_sceneList = new List<Scene>();
private IEntityTransferModule m_AgentTransferModule; private IEntityTransferModule m_AgentTransferModule;
@ -257,9 +260,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false; 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"; reason = "Communications failure";
version = m_Version;
if (destination == null) if (destination == null)
return false; return false;

View File

@ -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"; reason = "Communications failure";
version = "Unknown";
if (destination == null) if (destination == null)
return false; return false;
// Try local first // 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; return true;
// else do the remote thing // else do the remote thing
if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) 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; return false;

View File

@ -125,7 +125,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
else else
Scene.RegionInfo.RegionSettings.AllowLandResell = true; Scene.RegionInfo.RegionSettings.AllowLandResell = true;
Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents; if((byte)maxAgents <= Scene.RegionInfo.AgentCapacity)
Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents;
else
Scene.RegionInfo.RegionSettings.AgentLimit = Scene.RegionInfo.AgentCapacity;
Scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor; Scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor;

View File

@ -119,16 +119,40 @@ namespace OpenSim.Region.Framework.Scenes
private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity) private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity)
{ {
return 1; // And anything attached to this avatar gets top priority as well
if (entity is SceneObjectPart)
{
SceneObjectPart sop = (SceneObjectPart)entity;
if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar)
return 1;
}
return PriorityQueue.NumberOfImmediateQueues; // first queue past the immediate queues
} }
private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity) private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity)
{ {
// And anything attached to this avatar gets top priority as well
if (entity is SceneObjectPart)
{
SceneObjectPart sop = (SceneObjectPart)entity;
if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar)
return 1;
}
return ComputeDistancePriority(client,entity,false); return ComputeDistancePriority(client,entity,false);
} }
private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
{ {
// And anything attached to this avatar gets top priority as well
if (entity is SceneObjectPart)
{
SceneObjectPart sop = (SceneObjectPart)entity;
if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar)
return 1;
}
return ComputeDistancePriority(client,entity,true); return ComputeDistancePriority(client,entity,true);
} }
@ -141,18 +165,20 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (!presence.IsChildAgent) if (!presence.IsChildAgent)
{ {
// All avatars other than our own go into pqueue 1
if (entity is ScenePresence)
return 1;
if (entity is SceneObjectPart) if (entity is SceneObjectPart)
{ {
// Attachments are high priority,
if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
return 1;
// Non physical prims are lower priority than physical prims // Non physical prims are lower priority than physical prims
PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
if (physActor == null || !physActor.IsPhysical) if (physActor == null || !physActor.IsPhysical)
pqueue++; pqueue++;
// Attachments are high priority,
// MIC: shouldn't these already be in the highest priority queue already
// since their root position is same as the avatars?
if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
pqueue = 1;
} }
} }
} }
@ -172,7 +198,7 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId); // m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId);
// throw new InvalidOperationException("Prioritization agent not defined"); // throw new InvalidOperationException("Prioritization agent not defined");
return Int32.MaxValue; return PriorityQueue.NumberOfQueues - 1;
} }
// Use group position for child prims, since we are putting child prims in // Use group position for child prims, since we are putting child prims in
@ -197,8 +223,10 @@ namespace OpenSim.Region.Framework.Scenes
// And convert the distance to a priority queue, this computation gives queues // And convert the distance to a priority queue, this computation gives queues
// at 10, 20, 40, 80, 160, 320, 640, and 1280m // at 10, 20, 40, 80, 160, 320, 640, and 1280m
uint pqueue = 1; uint pqueue = PriorityQueue.NumberOfImmediateQueues;
for (int i = 0; i < 8; i++) uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues;
for (int i = 0; i < queues - 1; i++)
{ {
if (distance < 10 * Math.Pow(2.0,i)) if (distance < 10 * Math.Pow(2.0,i))
break; break;

View File

@ -1430,6 +1430,10 @@ namespace OpenSim.Region.Framework.Scenes
} }
else // Updating existing item with new perms etc else // Updating existing item with new perms etc
{ {
// m_log.DebugFormat(
// "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()",
// currentItem.Name, part.Name);
IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>();
if (agentTransactions != null) if (agentTransactions != null)
{ {
@ -2039,6 +2043,12 @@ namespace OpenSim.Region.Framework.Scenes
if (rot != null) if (rot != null)
group.UpdateGroupRotationR((Quaternion)rot); group.UpdateGroupRotationR((Quaternion)rot);
// TODO: This needs to be refactored with the similar code in
// SceneGraph.AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel)
// possibly by allowing this method to take a null rotation.
if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero)
group.RootPart.ApplyImpulse((vel * group.GetMass()), false);
// We can only call this after adding the scene object, since the scene object references the scene // We can only call this after adding the scene object, since the scene object references the scene
// to find out if scripts should be activated at all. // to find out if scripts should be activated at all.
group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);

View File

@ -2316,7 +2316,9 @@ namespace OpenSim.Region.Framework.Scenes
/// <returns></returns> /// <returns></returns>
public bool IncomingCreateObject(ISceneObject sog) 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; SceneObjectGroup newObject;
try try
{ {
@ -3665,6 +3667,15 @@ namespace OpenSim.Region.Framework.Scenes
return false; return false;
} }
int num = m_sceneGraph.GetNumberOfScenePresences();
if (num >= RegionInfo.RegionSettings.AgentLimit)
{
if (!Permissions.IsAdministrator(cAgentData.AgentID))
return false;
}
ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
if (childAgentUpdate != null) if (childAgentUpdate != null)
@ -4966,6 +4977,17 @@ namespace OpenSim.Region.Framework.Scenes
// child agent creation, thereby emulating the SL behavior. // child agent creation, thereby emulating the SL behavior.
public bool QueryAccess(UUID agentID, Vector3 position, out string reason) public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
{ {
int num = m_sceneGraph.GetNumberOfScenePresences();
if (num >= RegionInfo.RegionSettings.AgentLimit)
{
if (!Permissions.IsAdministrator(agentID))
{
reason = "The region is full";
return false;
}
}
reason = String.Empty; reason = String.Empty;
return true; return true;
} }

View File

@ -800,6 +800,11 @@ namespace OpenSim.Region.Framework.Scenes
return m_scenePresenceArray; return m_scenePresenceArray;
} }
public int GetNumberOfScenePresences()
{
return m_scenePresenceArray.Count;
}
/// <summary> /// <summary>
/// Request a scene presence by UUID. Fast, indexed lookup. /// Request a scene presence by UUID. Fast, indexed lookup.
/// </summary> /// </summary>

View File

@ -693,8 +693,9 @@ namespace OpenSim.Region.Framework.Scenes
{ {
TaskInventoryItem it = GetInventoryItem(item.ItemID); TaskInventoryItem it = GetInventoryItem(item.ItemID);
if (it != null) if (it != null)
{ {
// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
item.ParentID = m_part.UUID; item.ParentID = m_part.UUID;
item.ParentPartID = m_part.UUID; item.ParentPartID = m_part.UUID;
@ -711,14 +712,16 @@ namespace OpenSim.Region.Framework.Scenes
m_items[item.ItemID] = item; m_items[item.ItemID] = item;
m_inventorySerial++; m_inventorySerial++;
} }
if (fireScriptEvents) if (fireScriptEvents)
m_part.TriggerScriptChangedEvent(Changed.INVENTORY); m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
if (considerChanged) if (considerChanged)
{ {
HasInventoryChanged = true; HasInventoryChanged = true;
m_part.ParentGroup.HasGroupChanged = true; m_part.ParentGroup.HasGroupChanged = true;
} }
return true; return true;
} }
else else

View File

@ -2340,12 +2340,14 @@ namespace OpenSim.Region.Framework.Scenes
#region Update Client(s) #region Update Client(s)
/// <summary> /// <summary>
/// Sends a location update to the client connected to this scenePresence /// Sends a location update to the client connected to this scenePresence
/// </summary> /// </summary>
/// <param name="remoteClient"></param> /// <param name="remoteClient"></param>
public void SendTerseUpdateToClient(IClientAPI remoteClient) public void SendTerseUpdateToClient(IClientAPI remoteClient)
{ {
// If the client is inactive, it's getting its updates from another // If the client is inactive, it's getting its updates from another
// server. // server.
if (remoteClient.IsActive) if (remoteClient.IsActive)
@ -2358,8 +2360,8 @@ namespace OpenSim.Region.Framework.Scenes
//m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
remoteClient.SendPrimUpdate( remoteClient.SendPrimUpdate(
this, this,
PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
| PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
@ -2367,16 +2369,31 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
// vars to support reduced update frequency when velocity is unchanged
private Vector3 lastVelocitySentToAllClients = Vector3.Zero;
private int lastTerseUpdateToAllClientsTick = Util.EnvironmentTickCount();
/// <summary> /// <summary>
/// Send a location/velocity/accelleration update to all agents in scene /// Send a location/velocity/accelleration update to all agents in scene
/// </summary> /// </summary>
public void SendTerseUpdateToAllClients() public void SendTerseUpdateToAllClients()
{ {
m_perfMonMS = Util.EnvironmentTickCount(); int currentTick = Util.EnvironmentTickCount();
m_scene.ForEachClient(SendTerseUpdateToClient);
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); // decrease update frequency when avatar is moving but velocity is not changing
if (m_velocity.Length() < 0.01f
|| Vector3.Distance(lastVelocitySentToAllClients, m_velocity) > 0.01f
|| currentTick - lastTerseUpdateToAllClientsTick > 1500)
{
m_perfMonMS = currentTick;
lastVelocitySentToAllClients = m_velocity;
lastTerseUpdateToAllClientsTick = currentTick;
m_scene.ForEachClient(SendTerseUpdateToClient);
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
}
} }
public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs) public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
@ -2632,18 +2649,17 @@ namespace OpenSim.Region.Framework.Scenes
cadu.GroupAccess = 0; cadu.GroupAccess = 0;
cadu.Position = AbsolutePosition; cadu.Position = AbsolutePosition;
cadu.regionHandle = m_rootRegionHandle; cadu.regionHandle = m_rootRegionHandle;
float multiplier = 1;
int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
if (innacurateNeighbors != 0)
{
multiplier = 1f / (float)innacurateNeighbors;
}
if (multiplier <= 0f)
{
multiplier = 0.25f;
}
//m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString()); // Throttles
float multiplier = 1;
int childRegions = m_knownChildRegions.Count;
if (childRegions != 0)
multiplier = 1f / childRegions;
// Minimum throttle for a child region is 1/4 of the root region throttle
if (multiplier <= 0.25f)
multiplier = 0.25f;
cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
cadu.Velocity = Velocity; cadu.Velocity = Velocity;
@ -3039,16 +3055,14 @@ namespace OpenSim.Region.Framework.Scenes
// Throttles // Throttles
float multiplier = 1; float multiplier = 1;
int innacurateNeighbors = m_scene.GetInaccurateNeighborCount(); int childRegions = m_knownChildRegions.Count;
if (innacurateNeighbors != 0) if (childRegions != 0)
{ multiplier = 1f / childRegions;
multiplier = 1f / innacurateNeighbors;
} // Minimum throttle for a child region is 1/4 of the root region throttle
if (multiplier <= 0f) if (multiplier <= 0.25f)
{
multiplier = 0.25f; multiplier = 0.25f;
}
//m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier); cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
cAgent.HeadRotation = m_headrotation; cAgent.HeadRotation = m_headrotation;
@ -3064,54 +3078,6 @@ namespace OpenSim.Region.Framework.Scenes
cAgent.Appearance = new AvatarAppearance(m_appearance); 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) lock (scriptedcontrols)
{ {
ControllerData[] controls = new ControllerData[scriptedcontrols.Count]; ControllerData[] controls = new ControllerData[scriptedcontrols.Count];
@ -3131,9 +3097,24 @@ namespace OpenSim.Region.Framework.Scenes
} }
catch { } catch { }
// cAgent.GroupID = ?? // Attachment objects
// Groups??? 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) public void CopyFrom(AgentData cAgent)
@ -3174,50 +3155,6 @@ namespace OpenSim.Region.Framework.Scenes
AddToPhysicalScene(isFlying); 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 try
{ {
lock (scriptedcontrols) lock (scriptedcontrols)
@ -3247,8 +3184,18 @@ namespace OpenSim.Region.Framework.Scenes
} }
catch { } catch { }
//cAgent.GroupID = ?? if (cAgent.AttachmentObjects != null && cAgent.AttachmentObjects.Count > 0)
//Groups??? {
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) public bool CopyAgent(out IAgentData agent)
@ -3271,10 +3218,7 @@ namespace OpenSim.Region.Framework.Scenes
m_updateflag = true; m_updateflag = true;
// The magic constant 0.95f seems to make walking feel less jerky, Velocity = force;
// probably because it hackishly accounts for the overall latency of
// these Velocity updates -- Diva
Velocity = force * .95F;
m_forceToApply = null; m_forceToApply = null;
} }

View File

@ -81,6 +81,14 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
lock (m_scenes) lock (m_scenes)
m_scenes[scene.RegionInfo.RegionID] = scene; m_scenes[scene.RegionInfo.RegionID] = scene;
scene.AddCommand(
this, "show pqueues",
"show pqueues [full]",
"Show priority queue data for each client",
"Without the 'full' option, only root agents are shown."
+ " With the 'full' option child agents are also shown.",
ShowPQueuesReport);
scene.AddCommand( scene.AddCommand(
this, "show queues", this, "show queues",
"show queues [full]", "show queues [full]",
@ -119,6 +127,11 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
// m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); // m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
} }
protected void ShowPQueuesReport(string module, string[] cmd)
{
MainConsole.Instance.Output(GetPQueuesReport(cmd));
}
protected void ShowQueuesReport(string module, string[] cmd) protected void ShowQueuesReport(string module, string[] cmd)
{ {
MainConsole.Instance.Output(GetQueuesReport(cmd)); MainConsole.Instance.Output(GetQueuesReport(cmd));
@ -155,6 +168,80 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
""); "");
} }
/// <summary>
/// Generate UDP Queue data report for each client
/// </summary>
/// <param name="showParams"></param>
/// <returns></returns>
protected string GetPQueuesReport(string[] showParams)
{
bool showChildren = false;
string pname = "";
if (showParams.Length > 2 && showParams[2] == "full")
showChildren = true;
else if (showParams.Length > 3)
pname = showParams[2] + " " + showParams[3];
StringBuilder report = new StringBuilder();
int columnPadding = 2;
int maxNameLength = 18;
int maxRegionNameLength = 14;
int maxTypeLength = 4;
int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding;
report.Append(GetColumnEntry("User", maxNameLength, columnPadding));
report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding));
report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding));
report.AppendFormat(
"{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7} {10,7} {11,7}\n",
"Pri 0",
"Pri 1",
"Pri 2",
"Pri 3",
"Pri 4",
"Pri 5",
"Pri 6",
"Pri 7",
"Pri 8",
"Pri 9",
"Pri 10",
"Pri 11");
lock (m_scenes)
{
foreach (Scene scene in m_scenes.Values)
{
scene.ForEachClient(
delegate(IClientAPI client)
{
if (client is LLClientView)
{
bool isChild = scene.PresenceChildStatus(client.AgentId);
if (isChild && !showChildren)
return;
string name = client.Name;
if (pname != "" && name != pname)
return;
string regionName = scene.RegionInfo.RegionName;
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
report.AppendLine(((LLClientView)client).EntityUpdateQueue.ToString());
}
});
}
}
return report.ToString();
}
/// <summary> /// <summary>
/// Generate UDP Queue data report for each client /// Generate UDP Queue data report for each client
/// </summary> /// </summary>
@ -163,10 +250,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
protected string GetQueuesReport(string[] showParams) protected string GetQueuesReport(string[] showParams)
{ {
bool showChildren = false; bool showChildren = false;
string pname = "";
if (showParams.Length > 2 && showParams[2] == "full") if (showParams.Length > 2 && showParams[2] == "full")
showChildren = true; showChildren = true;
else if (showParams.Length > 3)
pname = showParams[2] + " " + showParams[3];
StringBuilder report = new StringBuilder(); StringBuilder report = new StringBuilder();
int columnPadding = 2; int columnPadding = 2;
@ -224,6 +314,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
return; return;
string name = client.Name; string name = client.Name;
if (pname != "" && name != pname)
return;
string regionName = scene.RegionInfo.RegionName; string regionName = scene.RegionInfo.RegionName;
report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
@ -249,10 +342,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
protected string GetThrottlesReport(string[] showParams) protected string GetThrottlesReport(string[] showParams)
{ {
bool showChildren = false; bool showChildren = false;
string pname = "";
if (showParams.Length > 2 && showParams[2] == "full") if (showParams.Length > 2 && showParams[2] == "full")
showChildren = true; showChildren = true;
else if (showParams.Length > 3)
pname = showParams[2] + " " + showParams[3];
StringBuilder report = new StringBuilder(); StringBuilder report = new StringBuilder();
int columnPadding = 2; int columnPadding = 2;
@ -302,7 +398,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
if (client is LLClientView) if (client is LLClientView)
{ {
LLClientView llClient = client as LLClientView; LLClientView llClient = client as LLClientView;
if (firstClient) if (firstClient)
{ {
report.AppendLine(GetServerThrottlesReport(llClient.UDPServer)); report.AppendLine(GetServerThrottlesReport(llClient.UDPServer));
@ -314,6 +410,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
return; return;
string name = client.Name; string name = client.Name;
if (pname != "" && name != pname)
return;
string regionName = scene.RegionInfo.RegionName; string regionName = scene.RegionInfo.RegionName;
LLUDPClient llUdpClient = llClient.UDPClient; LLUDPClient llUdpClient = llClient.UDPClient;
@ -352,7 +451,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
int maxRegionNameLength = 14; int maxRegionNameLength = 14;
int maxTypeLength = 4; int maxTypeLength = 4;
string name = "SERVER AGENT LIMITS"; string name = "SERVER AGENT RATES";
report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
report.Append(GetColumnEntry("-", maxRegionNameLength, columnPadding)); report.Append(GetColumnEntry("-", maxRegionNameLength, columnPadding));
@ -362,13 +461,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
report.AppendFormat( report.AppendFormat(
"{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}", "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}",
(throttleRates.Total * 8) / 1000, (throttleRates.Total * 8) / 1000,
(throttleRates.ResendLimit * 8) / 1000, (throttleRates.Resend * 8) / 1000,
(throttleRates.LandLimit * 8) / 1000, (throttleRates.Land * 8) / 1000,
(throttleRates.WindLimit * 8) / 1000, (throttleRates.Wind * 8) / 1000,
(throttleRates.CloudLimit * 8) / 1000, (throttleRates.Cloud * 8) / 1000,
(throttleRates.TaskLimit * 8) / 1000, (throttleRates.Task * 8) / 1000,
(throttleRates.TextureLimit * 8) / 1000, (throttleRates.Texture * 8) / 1000,
(throttleRates.AssetLimit * 8) / 1000); (throttleRates.Asset * 8) / 1000);
return report.ToString(); return report.ToString();
} }

View File

@ -50,6 +50,7 @@ namespace OpenSim.Server.Handlers.Simulation
public class AgentHandler public class AgentHandler
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private ISimulationService m_SimulationService; private ISimulationService m_SimulationService;
protected bool m_Proxy = false; protected bool m_Proxy = false;
@ -275,7 +276,7 @@ namespace OpenSim.Server.Handlers.Simulation
AgentData agent = new AgentData(); AgentData agent = new AgentData();
try try
{ {
agent.Unpack(args); agent.Unpack(args, m_SimulationService.GetScene(destination.RegionHandle));
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -295,7 +296,7 @@ namespace OpenSim.Server.Handlers.Simulation
AgentPosition agent = new AgentPosition(); AgentPosition agent = new AgentPosition();
try try
{ {
agent.Unpack(args); agent.Unpack(args, m_SimulationService.GetScene(destination.RegionHandle));
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -342,7 +343,8 @@ namespace OpenSim.Server.Handlers.Simulation
destination.RegionID = regionID; destination.RegionID = regionID;
string reason; 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; responsedata["int_response_code"] = HttpStatusCode.OK;
@ -350,6 +352,7 @@ namespace OpenSim.Server.Handlers.Simulation
resp["success"] = OSD.FromBoolean(result); resp["success"] = OSD.FromBoolean(result);
resp["reason"] = OSD.FromString(reason); resp["reason"] = OSD.FromString(reason);
resp["version"] = OSD.FromString(version);
responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
} }

View File

@ -158,7 +158,10 @@ namespace OpenSim.Services.Connectors
public InventoryCollection GetFolderContent(UUID principalID, UUID folderID) public InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
{ {
InventoryCollection inventory = new InventoryCollection(); InventoryCollection inventory = new InventoryCollection();
inventory.Folders = new List<InventoryFolderBase>();
inventory.Items = new List<InventoryItemBase>();
inventory.UserID = principalID;
try try
{ {
Dictionary<string,object> ret = MakeRequest("GETFOLDERCONTENT", Dictionary<string,object> ret = MakeRequest("GETFOLDERCONTENT",
@ -172,11 +175,6 @@ namespace OpenSim.Services.Connectors
if (ret.Count == 0) if (ret.Count == 0)
return null; return null;
inventory.Folders = new List<InventoryFolderBase>();
inventory.Items = new List<InventoryItemBase>();
inventory.UserID = principalID;
Dictionary<string,object> folders = Dictionary<string,object> folders =
(Dictionary<string,object>)ret["FOLDERS"]; (Dictionary<string,object>)ret["FOLDERS"];
Dictionary<string,object> items = Dictionary<string,object> items =

View File

@ -241,7 +241,7 @@ namespace OpenSim.Services.Connectors.Simulation
if (args != null) if (args != null)
{ {
agent = new CompleteAgentData(); agent = new CompleteAgentData();
agent.Unpack(args); agent.Unpack(args, null);
return true; return true;
} }
} }
@ -256,9 +256,10 @@ namespace OpenSim.Services.Connectors.Simulation
/// <summary> /// <summary>
/// </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"; reason = "Failed to contact destination";
version = "Unknown";
// m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess start, position={0}", position); // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess start, position={0}", position);
@ -274,23 +275,27 @@ namespace OpenSim.Services.Connectors.Simulation
try try
{ {
OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000); OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000);
bool success = result["success"].AsBoolean(); OSDMap data = (OSDMap)result["_Result"];
reason = result["reason"].AsString();
//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 (!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 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"); 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; return true;
} }
reason = result["Message"]; reason = data["Message"];
} }
else else
{ {

View File

@ -29,6 +29,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Reflection; using System.Reflection;
using System.Text.RegularExpressions;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Services.Interfaces; using OpenSim.Services.Interfaces;
@ -57,6 +58,9 @@ namespace OpenSim.Services.HypergridService
private static IUserAgentService m_UserAgentService; private static IUserAgentService m_UserAgentService;
private static ISimulationService m_SimulationService; private static ISimulationService m_SimulationService;
protected string m_AllowedClients = string.Empty;
protected string m_DeniedClients = string.Empty;
private static UUID m_ScopeID; private static UUID m_ScopeID;
private static bool m_AllowTeleportsToAnyRegion; private static bool m_AllowTeleportsToAnyRegion;
private static string m_ExternalName; private static string m_ExternalName;
@ -104,6 +108,9 @@ namespace OpenSim.Services.HypergridService
else if (simulationService != string.Empty) else if (simulationService != string.Empty)
m_SimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args); m_SimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args);
m_AllowedClients = serverConfig.GetString("AllowedClients", string.Empty);
m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty);
if (m_GridService == null || m_PresenceService == null || m_SimulationService == null) if (m_GridService == null || m_PresenceService == null || m_SimulationService == null)
throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function."); throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function.");
@ -181,8 +188,36 @@ namespace OpenSim.Services.HypergridService
string authURL = string.Empty; string authURL = string.Empty;
if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
authURL = aCircuit.ServiceURLs["HomeURI"].ToString(); authURL = aCircuit.ServiceURLs["HomeURI"].ToString();
m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to login foreign agent {0} {1} @ {2} ({3}) at destination {4}", m_log.InfoFormat("[GATEKEEPER SERVICE]: Login request for {0} {1} @ {2} ({3}) at {4} using viewer {5}, channel {6}, IP {7}, Mac {8}, Id0 {9}",
aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName); aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName,
aCircuit.Viewer, aCircuit.Channel, aCircuit.IPAddress, aCircuit.Mac, aCircuit.Id0);
//
// Check client
//
if (m_AllowedClients != string.Empty)
{
Regex arx = new Regex(m_AllowedClients);
Match am = arx.Match(aCircuit.Viewer);
if (!am.Success)
{
m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is not allowed", aCircuit.Viewer);
return false;
}
}
if (m_DeniedClients != string.Empty)
{
Regex drx = new Regex(m_DeniedClients);
Match dm = drx.Match(aCircuit.Viewer);
if (dm.Success)
{
m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is denied", aCircuit.Viewer);
return false;
}
}
// //
// Authenticate the user // Authenticate the user

View File

@ -67,7 +67,7 @@ namespace OpenSim.Services.Interfaces
bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent); 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> /// <summary>
/// Message from receiving region to departing region, telling it got contacted by the client. /// Message from receiving region to departing region, telling it got contacted by the client.

View File

@ -244,7 +244,7 @@ namespace OpenSim.Services.InventoryService
// connector. So we disregard the principal and look // connector. So we disregard the principal and look
// by ID. // by ID.
// //
m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString()); //m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString());
InventoryCollection inventory = new InventoryCollection(); InventoryCollection inventory = new InventoryCollection();
inventory.UserID = principalID; inventory.UserID = principalID;
inventory.Folders = new List<InventoryFolderBase>(); inventory.Folders = new List<InventoryFolderBase>();

View File

@ -77,7 +77,11 @@ namespace OpenSim.Services.LLLoginService
protected string m_MapTileURL; protected string m_MapTileURL;
protected string m_SearchURL; protected string m_SearchURL;
protected string m_AllowedClients;
protected string m_DeniedClients;
IConfig m_LoginServerConfig; IConfig m_LoginServerConfig;
IConfig m_ClientsConfig;
public LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService) public LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService)
{ {
@ -105,7 +109,10 @@ namespace OpenSim.Services.LLLoginService
m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty); m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty);
m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty); m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty);
m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty); m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty);
m_AllowedClients = m_LoginServerConfig.GetString("AllowedClients", string.Empty);
m_DeniedClients = m_LoginServerConfig.GetString("DeniedClients", string.Empty);
// These are required; the others aren't // These are required; the others aren't
if (accountService == string.Empty || authService == string.Empty) if (accountService == string.Empty || authService == string.Empty)
throw new Exception("LoginService is missing service specifications"); throw new Exception("LoginService is missing service specifications");
@ -215,10 +222,37 @@ namespace OpenSim.Services.LLLoginService
bool success = false; bool success = false;
UUID session = UUID.Random(); UUID session = UUID.Random();
m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} from {2} with user agent {3} starting in {4}", m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} at {2} using viewer {3}, channel {4}, IP {5}, Mac {6}, Id0 {7}",
firstName, lastName, clientIP.Address.ToString(), clientVersion, startLocation); firstName, lastName, startLocation, clientVersion, channel, clientIP.Address.ToString(), mac, id0);
try try
{ {
//
// Check client
//
if (m_AllowedClients != string.Empty)
{
Regex arx = new Regex(m_AllowedClients);
Match am = arx.Match(clientVersion);
if (!am.Success)
{
m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is not allowed", clientVersion);
return LLFailedLoginResponse.LoginBlockedProblem;
}
}
if (m_DeniedClients != string.Empty)
{
Regex drx = new Regex(m_DeniedClients);
Match dm = drx.Match(clientVersion);
if (dm.Success)
{
m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is denied", clientVersion);
return LLFailedLoginResponse.LoginBlockedProblem;
}
}
// //
// Get the account and check that it exists // Get the account and check that it exists
// //

View File

@ -37,7 +37,7 @@ Now see the "Configuring OpenSim" section
=== Running OpenSim on Linux === === Running OpenSim on Linux ===
================================ ================================
You will need Mono >= 2.4.2 to run OpenSim. On some Linux distributions you You will need Mono >= 2.4.3 to run OpenSim. On some Linux distributions you
may need to install additional packages. See http://opensimulator.org/wiki/Dependencies may need to install additional packages. See http://opensimulator.org/wiki/Dependencies
for more information. for more information.

0
bin/Axiom.MathLib.dll Normal file → Executable file
View File

0
bin/BulletDotNET.dll Normal file → Executable file
View File

0
bin/C5.dll Normal file → Executable file
View File

0
bin/CSJ2K.dll Normal file → Executable file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

0
bin/Community.CsharpSqlite.Sqlite.dll Normal file → Executable file
View File

0
bin/Community.CsharpSqlite.dll Normal file → Executable file
View File

0
bin/CookComputing.XmlRpcV2.dll Normal file → Executable file
View File

0
bin/DotNetOpenId.dll Normal file → Executable file
View File

0
bin/DotNetOpenMail.dll Normal file → Executable file
View File

Binary file not shown.

0
bin/Fadd.Globalization.Yaml.dll Normal file → Executable file
View File

0
bin/Fadd.dll Normal file → Executable file
View File

0
bin/GlynnTucker.Cache.dll Normal file → Executable file
View File

0
bin/Google.ProtocolBuffers.dll Normal file → Executable file
View File

0
bin/HttpServer.dll Normal file → Executable file
View File

0
bin/HttpServer_OpenSim.dll Normal file → Executable file
View File

0
bin/Iesi.Collections.dll Normal file → Executable file
View File

0
bin/Kds.Serialization.dll Normal file → Executable file
View File

Binary file not shown.

0
bin/Modified.XnaDevRu.BulletX.dll Normal file → Executable file
View File

0
bin/Mono.Addins.CecilReflector.dll Normal file → Executable file
View File

0
bin/Mono.Addins.Setup.dll Normal file → Executable file
View File

0
bin/Mono.Addins.dll Normal file → Executable file
View File

0
bin/Mono.Data.Sqlite.dll Normal file → Executable file
View File

0
bin/Mono.Data.SqliteClient.dll Normal file → Executable file
View File

Binary file not shown.

0
bin/MonoXnaCompactMaths.dll Normal file → Executable file
View File

0
bin/MySql.Data.dll Normal file → Executable file
View File

0
bin/NDesk.Options.dll Normal file → Executable file
View File

0
bin/Newtonsoft.Json.Net20.dll Normal file → Executable file
View File

0
bin/Nini.dll Normal file → Executable file
View File

0
bin/Npgsql.dll Normal file → Executable file
View File

0
bin/Ode.NET.dll Normal file → Executable file
View File

0
bin/OpenMetaverse.StructuredData.dll Normal file → Executable file
View File

0
bin/OpenMetaverse.dll Normal file → Executable file
View File

0
bin/OpenMetaverseTypes.dll Normal file → Executable file
View File

Some files were not shown because too many files have changed in this diff Show More