Merge branch 'master' into dev

Conflicts:
	OpenSim/Client/MXP/ClientStack/MXPClientView.cs
	OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
	OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
	OpenSim/Region/Framework/Scenes/ScenePresence.cs
dsg
Dan Lake 2011-04-28 16:31:40 -07:00
commit 3e74a72d2e
122 changed files with 1570 additions and 4489 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

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

@ -574,34 +574,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;
@ -560,6 +561,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); }
@ -873,6 +879,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
// //
@ -937,6 +945,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());
@ -1023,6 +1034,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);
@ -1135,6 +1149,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

@ -430,7 +430,7 @@ namespace OpenSim.Framework.Servers.HttpServer
string path = request.RawUrl; string path = request.RawUrl;
string handlerKey = GetHandlerKey(request.HttpMethod, path); string handlerKey = GetHandlerKey(request.HttpMethod, path);
//m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); // m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path);
if (TryGetStreamHandler(handlerKey, out requestHandler)) if (TryGetStreamHandler(handlerKey, out requestHandler))
{ {

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

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

@ -455,6 +455,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>
@ -3635,6 +3640,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>>();
@ -3642,6 +3685,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)
{ {
@ -3659,7 +3707,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)
@ -3767,24 +3815,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
@ -3792,28 +3849,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;
@ -3825,8 +3877,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)
@ -3840,10 +3892,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;
@ -3855,8 +3907,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); });
} }
} }
@ -4048,7 +4100,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);
} }
} }
@ -4059,6 +4112,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
@ -4074,6 +4150,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
@ -4092,6 +4174,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);
} }
} }
@ -4102,6 +4185,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);
} }
} }
@ -4109,12 +4193,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];
@ -4122,28 +4207,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++)
{ {
@ -4152,10 +4235,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++;
} }
} }
@ -4192,7 +4284,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);
@ -4843,7 +4935,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();
@ -11433,7 +11533,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>
@ -11467,6 +11567,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)
{ {
@ -11493,7 +11609,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)

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,18 +339,16 @@ 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);
} }
} }
private int[] CatCounts = new int[9];
/// <summary> /// <summary>
/// Start the process of sending a packet to the client. /// Start the process of sending a packet to the client.
/// </summary> /// </summary>
@ -358,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;
@ -413,11 +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 (category == ThrottleOutPacketType.Unknown) // If we were not provided a method for handling unacked, use the UDPServer default method
Interlocked.Increment(ref CatCounts[8]); outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);
else
Interlocked.Increment(ref CatCounts[(int)category]);
// 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
@ -451,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);
} }
} }
@ -464,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;
@ -494,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?
@ -678,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
@ -687,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;
@ -1107,7 +1101,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);
@ -1163,7 +1157,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

@ -32,6 +32,8 @@ using System.Threading;
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
@ -53,6 +55,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
@ -61,11 +65,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

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

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

@ -1593,6 +1593,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)
{ {
@ -2241,6 +2245,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

@ -4254,6 +4254,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)
@ -5563,6 +5572,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

@ -832,6 +832,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

@ -81,16 +81,20 @@ namespace OpenSim.Region.Framework.Scenes
} }
/// <summary> /// <summary>
/// Add an inventory item to a prim in this group. /// Add an inventory item from a user's inventory to a prim in this scene object.
/// </summary> /// </summary>
/// <param name="remoteClient"></param> /// <param name="remoteClient">The client adding the item.</param>
/// <param name="localID"></param> /// <param name="localID">The local ID of the part receiving the add.</param>
/// <param name="item"></param> /// <param name="item">The user inventory item being added.</param>
/// <param name="copyItemID">The item UUID that should be used by the new item.</param> /// <param name="copyItemID">The item UUID that should be used by the new item.</param>
/// <returns></returns> /// <returns></returns>
public bool AddInventoryItem(IClientAPI remoteClient, uint localID, public bool AddInventoryItem(IClientAPI remoteClient, uint localID,
InventoryItemBase item, UUID copyItemID) InventoryItemBase item, UUID copyItemID)
{ {
// m_log.DebugFormat(
// "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}",
// item.Name, remoteClient.Name, localID);
UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID; UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID;
SceneObjectPart part = GetChildPart(localID); SceneObjectPart part = GetChildPart(localID);
@ -132,15 +136,20 @@ namespace OpenSim.Region.Framework.Scenes
taskItem.GroupPermissions = item.GroupPermissions; taskItem.GroupPermissions = item.GroupPermissions;
taskItem.NextPermissions = item.NextPermissions; taskItem.NextPermissions = item.NextPermissions;
} }
taskItem.Flags = item.Flags; taskItem.Flags = item.Flags;
// m_log.DebugFormat(
// "[PRIM INVENTORY]: Flags are 0x{0:X} for item {1} added to part {2} by {3}",
// taskItem.Flags, taskItem.Name, localID, remoteClient.Name);
// TODO: These are pending addition of those fields to TaskInventoryItem // TODO: These are pending addition of those fields to TaskInventoryItem
// taskItem.SalePrice = item.SalePrice; // taskItem.SalePrice = item.SalePrice;
// taskItem.SaleType = item.SaleType; // taskItem.SaleType = item.SaleType;
taskItem.CreationDate = (uint)item.CreationDate; taskItem.CreationDate = (uint)item.CreationDate;
bool addFromAllowedDrop = false; bool addFromAllowedDrop = false;
if (remoteClient!=null) if (remoteClient != null)
{ {
addFromAllowedDrop = remoteClient.AgentId != part.OwnerID; addFromAllowedDrop = remoteClient.AgentId != part.OwnerID;
} }

View File

@ -699,8 +699,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;
@ -717,14 +718,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

@ -2418,12 +2418,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)
@ -2436,8 +2438,8 @@ namespace OpenSim.Region.Framework.Scenes
//m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : 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));
@ -2445,6 +2447,11 @@ 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>
@ -2460,11 +2467,21 @@ namespace OpenSim.Region.Framework.Scenes
return; return;
} }
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)
@ -2742,18 +2759,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;
@ -3149,16 +3165,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;
@ -3381,10 +3395,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

@ -117,29 +117,40 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
{ {
using (XmlTextReader reader = new XmlTextReader(sr)) using (XmlTextReader reader = new XmlTextReader(sr))
{ {
reader.Read(); try
if (reader.Name != "CoalescedObject")
{ {
// m_log.DebugFormat( reader.Read();
// "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false", if (reader.Name != "CoalescedObject")
// reader.Name); {
// m_log.DebugFormat(
// "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false",
// reader.Name);
return false;
}
coa = new CoalescedSceneObjects(UUID.Zero);
reader.Read();
while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "CoalescedObject")
{
if (reader.Name == "SceneObjectGroup")
{
string soXml = reader.ReadOuterXml();
coa.Add(SceneObjectSerializer.FromOriginalXmlFormat(soXml));
}
}
reader.ReadEndElement(); // CoalescedObject
}
catch (Exception e)
{
m_log.ErrorFormat(
"[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml failed with {0} {1}",
e.Message, e.StackTrace);
return false; return false;
} }
coa = new CoalescedSceneObjects(UUID.Zero);
reader.Read();
while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "CoalescedObject")
{
if (reader.Name == "SceneObjectGroup")
{
string soXml = reader.ReadOuterXml();
coa.Add(SceneObjectSerializer.FromOriginalXmlFormat(soXml));
}
}
reader.ReadEndElement(); // CoalescedObject
} }
} }

View File

@ -298,10 +298,20 @@ namespace OpenSim.Region.Framework.Scenes
if (null != objectAsset) if (null != objectAsset)
{ {
string xml = Utils.BytesToString(objectAsset.Data); string xml = Utils.BytesToString(objectAsset.Data);
SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml);
CoalescedSceneObjects coa;
if (null != sog) if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa))
GatherAssetUuids(sog, assetUuids); {
foreach (SceneObjectGroup sog in coa.Objects)
GatherAssetUuids(sog, assetUuids);
}
else
{
SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml);
if (null != sog)
GatherAssetUuids(sog, assetUuids);
}
} }
} }

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

@ -118,7 +118,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
if (serviceDll == String.Empty) if (serviceDll == String.Empty)
{ {
m_log.Error("[FreeSwitchVoice]: No LocalServiceModule named in section FreeSwitchVoice"); m_log.Error("[FreeSwitchVoice]: No LocalServiceModule named in section FreeSwitchVoice. Not starting.");
return; return;
} }
@ -143,8 +143,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
if (String.IsNullOrEmpty(m_freeSwitchRealm) || if (String.IsNullOrEmpty(m_freeSwitchRealm) ||
String.IsNullOrEmpty(m_freeSwitchAPIPrefix)) String.IsNullOrEmpty(m_freeSwitchAPIPrefix))
{ {
m_log.Error("[FreeSwitchVoice] plugin mis-configured"); m_log.Error("[FreeSwitchVoice]: Freeswitch service mis-configured. Not starting.");
m_log.Info("[FreeSwitchVoice] plugin disabled: incomplete configuration");
return; return;
} }
@ -164,24 +163,24 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
// String.Format("{0}/viv_get_prelogin.php", m_freeSwitchAPIPrefix), FreeSwitchSLVoiceGetPreloginHTTPHandler); // String.Format("{0}/viv_get_prelogin.php", m_freeSwitchAPIPrefix), FreeSwitchSLVoiceGetPreloginHTTPHandler);
// MainServer.Instance.AddStreamHandler(h); // MainServer.Instance.AddStreamHandler(h);
MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_signin.php", m_freeSwitchAPIPrefix), MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_signin.php", m_freeSwitchAPIPrefix),
FreeSwitchSLVoiceSigninHTTPHandler); FreeSwitchSLVoiceSigninHTTPHandler);
MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_buddy.php", m_freeSwitchAPIPrefix), MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_buddy.php", m_freeSwitchAPIPrefix),
FreeSwitchSLVoiceBuddyHTTPHandler); FreeSwitchSLVoiceBuddyHTTPHandler);
MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_watcher.php", m_freeSwitchAPIPrefix),
FreeSwitchSLVoiceWatcherHTTPHandler);
m_log.InfoFormat("[FreeSwitchVoice] using FreeSwitch server {0}", m_freeSwitchRealm); m_log.InfoFormat("[FreeSwitchVoice]: using FreeSwitch server {0}", m_freeSwitchRealm);
m_Enabled = true; m_Enabled = true;
m_log.Info("[FreeSwitchVoice] plugin enabled"); m_log.Info("[FreeSwitchVoice]: plugin enabled");
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat("[FreeSwitchVoice] plugin initialization failed: {0}", e.Message); m_log.ErrorFormat("[FreeSwitchVoice]: plugin initialization failed: {0} {1}", e.Message, e.StackTrace);
m_log.DebugFormat("[FreeSwitchVoice] plugin initialization failed: {0}", e.ToString());
return; return;
} }
@ -240,7 +239,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
{ {
if (m_Enabled) if (m_Enabled)
{ {
m_log.Info("[FreeSwitchVoice] registering IVoiceModule with the scene"); m_log.Info("[FreeSwitchVoice]: registering IVoiceModule with the scene");
// register the voice interface for this module, so the script engine can call us // register the voice interface for this module, so the script engine can call us
scene.RegisterModuleInterface<IVoiceModule>(this); scene.RegisterModuleInterface<IVoiceModule>(this);
@ -302,7 +301,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
// </summary> // </summary>
public void OnRegisterCaps(Scene scene, UUID agentID, Caps caps) public void OnRegisterCaps(Scene scene, UUID agentID, Caps caps)
{ {
m_log.DebugFormat("[FreeSwitchVoice] OnRegisterCaps: agentID {0} caps {1}", agentID, caps); m_log.DebugFormat(
"[FreeSwitchVoice]: OnRegisterCaps() called with agentID {0} caps {1} in scene {2}",
agentID, caps, scene.RegionInfo.RegionName);
string capsBase = "/CAPS/" + caps.CapsObjectPath; string capsBase = "/CAPS/" + caps.CapsObjectPath;
caps.RegisterHandler("ProvisionVoiceAccountRequest", caps.RegisterHandler("ProvisionVoiceAccountRequest",
@ -344,6 +345,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
public string ProvisionVoiceAccountRequest(Scene scene, string request, string path, string param, public string ProvisionVoiceAccountRequest(Scene scene, string request, string path, string param,
UUID agentID, Caps caps) UUID agentID, Caps caps)
{ {
m_log.DebugFormat(
"[FreeSwitchVoice][PROVISIONVOICE]: ProvisionVoiceAccountRequest() request: {0}, path: {1}, param: {2}", request, path, param);
ScenePresence avatar = scene.GetScenePresence(agentID); ScenePresence avatar = scene.GetScenePresence(agentID);
if (avatar == null) if (avatar == null)
{ {
@ -357,9 +361,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
try try
{ {
//m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
// request, path, param);
//XmlElement resp; //XmlElement resp;
string agentname = "x" + Convert.ToBase64String(agentID.GetBytes()); string agentname = "x" + Convert.ToBase64String(agentID.GetBytes());
string password = "1234";//temp hack//new UUID(Guid.NewGuid()).ToString().Replace('-','Z').Substring(0,16); string password = "1234";//temp hack//new UUID(Guid.NewGuid()).ToString().Replace('-','Z').Substring(0,16);
@ -390,7 +391,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r); // m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r);
return r; return r;
} }
@ -416,6 +417,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
public string ParcelVoiceInfoRequest(Scene scene, string request, string path, string param, public string ParcelVoiceInfoRequest(Scene scene, string request, string path, string param,
UUID agentID, Caps caps) UUID agentID, Caps caps)
{ {
// m_log.DebugFormat(
// "[FreeSwitchVoice][PARCELVOICE]: ParcelVoiceInfoRequest() on {0} for {1}",
// scene.RegionInfo.RegionName, agentID);
ScenePresence avatar = scene.GetScenePresence(agentID); ScenePresence avatar = scene.GetScenePresence(agentID);
string avatarName = avatar.Name; string avatarName = avatar.Name;
@ -453,8 +458,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
if ((land.Flags & (uint)ParcelFlags.AllowVoiceChat) == 0) if ((land.Flags & (uint)ParcelFlags.AllowVoiceChat) == 0)
{ {
m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel", // m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel",
scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName); // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName);
channelUri = String.Empty; channelUri = String.Empty;
} }
else else
@ -469,8 +474,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds); parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds);
string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}", // m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}",
scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r); // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r);
return r; return r;
} }
catch (Exception e) catch (Exception e)
@ -502,6 +507,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
m_log.DebugFormat("[FreeSwitchVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}", m_log.DebugFormat("[FreeSwitchVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}",
avatarName, request, path, param); avatarName, request, path, param);
return "<llsd>true</llsd>"; return "<llsd>true</llsd>";
} }
@ -555,10 +561,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
return response; return response;
} }
public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request) public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request)
{ {
m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceGetPreloginHTTPHandler called"); m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceGetPreloginHTTPHandler called");
Hashtable response = new Hashtable(); Hashtable response = new Hashtable();
response["content_type"] = "text/xml"; response["content_type"] = "text/xml";
@ -592,6 +597,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
public Hashtable FreeSwitchSLVoiceBuddyHTTPHandler(Hashtable request) public Hashtable FreeSwitchSLVoiceBuddyHTTPHandler(Hashtable request)
{ {
m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceBuddyHTTPHandler called");
Hashtable response = new Hashtable(); Hashtable response = new Hashtable();
response["int_response_code"] = 200; response["int_response_code"] = 200;
response["str_response_string"] = string.Empty; response["str_response_string"] = string.Empty;
@ -650,21 +657,64 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
<bdy_status>A</bdy_status> <bdy_status>A</bdy_status>
<modified_ts>{3}</modified_ts> <modified_ts>{3}</modified_ts>
<b2g_group_id></b2g_group_id> <b2g_group_id></b2g_group_id>
</level3>", ids[i],i,m_freeSwitchRealm,dt)); </level3>", ids[i], i ,m_freeSwitchRealm, dt));
} }
resp.Append("</buddies><groups></groups></body></level0></response>"); resp.Append("</buddies><groups></groups></body></level0></response>");
response["str_response_string"] = resp.ToString(); response["str_response_string"] = resp.ToString();
// Regex normalizeEndLines = new Regex(@"\r\n", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline); // Regex normalizeEndLines = new Regex(@"(\r\n|\n)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline);
//
//m_log.DebugFormat("[FREESWITCH]: {0}", normalizeEndLines.Replace((string)response["str_response_string"],"")); // m_log.DebugFormat(
// "[FREESWITCH]: FreeSwitchSLVoiceBuddyHTTPHandler() response {0}",
// normalizeEndLines.Replace((string)response["str_response_string"],""));
return response; return response;
} }
public Hashtable FreeSwitchSLVoiceWatcherHTTPHandler(Hashtable request)
{
m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceWatcherHTTPHandler called");
Hashtable response = new Hashtable();
response["int_response_code"] = 200;
response["content-type"] = "text/xml";
Hashtable requestBody = ParseRequestBody((string)request["body"]);
string auth_token = (string)requestBody["auth_token"];
//string[] auth_tokenvals = auth_token.Split(':');
//string username = auth_tokenvals[0];
StringBuilder resp = new StringBuilder();
resp.Append("<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?><response xmlns=\"http://www.vivox.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation= \"/xsd/buddy_list.xsd\">");
// FIXME: This is enough of a response to stop viewer 2 complaining about a login failure and get voice to work. If we don't
// give an OK response, then viewer 2 engages in an continuous viv_signin.php, viv_buddy.php, viv_watcher.php loop
// Viewer 1 appeared happy to ignore the lack of reply and still works with this reply.
//
// However, really we need to fill in whatever watcher data should be here (whatever that is).
resp.Append(string.Format(@"<level0>
<status>OK</status>
<cookie_name>lib_session</cookie_name>
<cookie>{0}</cookie>
<auth_token>{0}</auth_token>
<body/></level0></response>", auth_token));
response["str_response_string"] = resp.ToString();
// Regex normalizeEndLines = new Regex(@"(\r\n|\n)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline);
//
// m_log.DebugFormat(
// "[FREESWITCH]: FreeSwitchSLVoiceWatcherHTTPHandler() response {0}",
// normalizeEndLines.Replace((string)response["str_response_string"],""));
return response;
}
public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request) public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request)
{ {
m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceSigninHTTPHandler called"); m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceSigninHTTPHandler called");
// string requestbody = (string)request["body"]; // string requestbody = (string)request["body"];
// string uri = (string)request["uri"]; // string uri = (string)request["uri"];
// string contenttype = (string)request["content-type"]; // string contenttype = (string)request["content-type"];
@ -709,7 +759,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
</level0> </level0>
</response>", userid, pos, avatarName); </response>", userid, pos, avatarName);
response["int_response_code"] = 200; response["int_response_code"] = 200;
// m_log.DebugFormat("[FreeSwitchVoice]: Sending FreeSwitchSLVoiceSigninHTTPHandler response");
return response; return response;
} }
@ -795,16 +848,27 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
response["keepalive"] = false; response["keepalive"] = false;
response["int_response_code"] = 500; response["int_response_code"] = 500;
Hashtable requestBody = ParseRequestBody((string) request["body"]); Hashtable requestBody = ParseRequestBody((string)request["body"]);
string section = (string) requestBody["section"]; string section = (string) requestBody["section"];
if (section == "directory") if (section == "directory")
{
string eventCallingFunction = (string)requestBody["Event-Calling-Function"];
m_log.DebugFormat(
"[FreeSwitchVoice]: Received request for config section directory, event calling function '{0}'",
eventCallingFunction);
response = m_FreeswitchService.HandleDirectoryRequest(requestBody); response = m_FreeswitchService.HandleDirectoryRequest(requestBody);
}
else if (section == "dialplan") else if (section == "dialplan")
{
m_log.DebugFormat("[FreeSwitchVoice]: Received request for config section dialplan");
response = m_FreeswitchService.HandleDialplanRequest(requestBody); response = m_FreeswitchService.HandleDialplanRequest(requestBody);
}
else else
m_log.WarnFormat("[FreeSwitchVoice]: section was {0}", section); m_log.WarnFormat("[FreeSwitchVoice]: Unknown section {0} was requested from config.", section);
return response; return response;
} }
@ -821,4 +885,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
#endregion #endregion
} }
} }

View File

@ -84,10 +84,11 @@ namespace OpenSim.Region.Physics.Meshing
public Meshmerizer(IConfigSource config) public Meshmerizer(IConfigSource config)
{ {
IConfig start_config = config.Configs["Startup"]; IConfig start_config = config.Configs["Startup"];
IConfig mesh_config = config.Configs["Mesh"];
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
useMeshiesPhysicsMesh = start_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
try try
{ {

View File

@ -62,6 +62,8 @@ namespace PrimMesher
bool needsScaling = false; bool needsScaling = false;
bool smallMap = bmW * bmH <= lod * lod;
width = bmW; width = bmW;
height = bmH; height = bmH;
while (width * height > numLodPixels) while (width * height > numLodPixels)
@ -104,9 +106,14 @@ namespace PrimMesher
{ {
for (int x = 0; x <= width; x++) for (int x = 0; x <= width; x++)
{ {
int bmY = y < height ? y * 2 : y * 2 - 1; Color c;
int bmX = x < width ? x * 2 : x * 2 - 1;
Color c = bm.GetPixel(bmX, bmY); if (smallMap)
c = bm.GetPixel(x < width ? x : x - 1,
y < height ? y : y - 1);
else
c = bm.GetPixel(x < width ? x * 2 : x * 2 - 1,
y < height ? y * 2 : y * 2 - 1);
redBytes[byteNdx] = c.R; redBytes[byteNdx] = c.R;
greenBytes[byteNdx] = c.G; greenBytes[byteNdx] = c.G;

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

@ -50,13 +50,13 @@ namespace OpenSim.Services.FreeswitchService
public Hashtable HandleDialplanRequest(Hashtable request) public Hashtable HandleDialplanRequest(Hashtable request)
{ {
m_log.DebugFormat("[FreeSwitchVoice] HandleDialplanRequest called with {0}",request.ToString()); m_log.DebugFormat("[FreeSwitchVoice]: HandleDialplanRequest called with {0}",request.ToString());
Hashtable response = new Hashtable(); Hashtable response = new Hashtable();
foreach (DictionaryEntry item in request) foreach (DictionaryEntry item in request)
{ {
m_log.InfoFormat("[FreeSwitchDirectory] requestBody item {0} {1}",item.Key, item.Value); // m_log.InfoFormat("[FreeSwitchDirectory]: requestBody item {0} {1}",item.Key, item.Value);
} }
string requestcontext = (string) request["Hunt-Context"]; string requestcontext = (string) request["Hunt-Context"];
@ -66,7 +66,7 @@ namespace OpenSim.Services.FreeswitchService
if (m_freeSwitchContext != String.Empty && m_freeSwitchContext != requestcontext) if (m_freeSwitchContext != String.Empty && m_freeSwitchContext != requestcontext)
{ {
m_log.Debug("[FreeSwitchDirectory] returning empty as it's for another context"); m_log.Debug("[FreeSwitchDirectory]: returning empty as it's for another context");
response["str_response_string"] = ""; response["str_response_string"] = "";
} }
else else
@ -116,13 +116,16 @@ namespace OpenSim.Services.FreeswitchService
{ {
Hashtable response = new Hashtable(); Hashtable response = new Hashtable();
string domain = (string) request["domain"]; string domain = (string) request["domain"];
if (domain != m_freeSwitchRealm) { if (domain != m_freeSwitchRealm)
{
response["content_type"] = "text/xml"; response["content_type"] = "text/xml";
response["keepalive"] = false; response["keepalive"] = false;
response["int_response_code"] = 200; response["int_response_code"] = 200;
response["str_response_string"] = ""; response["str_response_string"] = "";
} else { }
m_log.DebugFormat("[FreeSwitchDirectory] HandleDirectoryRequest called with {0}",request.ToString()); else
{
// m_log.DebugFormat("[FreeSwitchDirectory]: HandleDirectoryRequest called with {0}",request.ToString());
// information in the request we might be interested in // information in the request we might be interested in
@ -143,10 +146,8 @@ namespace OpenSim.Services.FreeswitchService
//domain=9.20.151.43 //domain=9.20.151.43
//ip=9.167.220.137 // this is the correct IP rather than sip_contact_host above when through a vpn or NAT setup //ip=9.167.220.137 // this is the correct IP rather than sip_contact_host above when through a vpn or NAT setup
foreach (DictionaryEntry item in request) // foreach (DictionaryEntry item in request)
{ // m_log.DebugFormat("[FreeSwitchDirectory]: requestBody item {0} {1}", item.Key, item.Value);
m_log.InfoFormat("[FreeSwitchDirectory] requestBody item {0} {1}", item.Key, item.Value);
}
string eventCallingFunction = (string) request["Event-Calling-Function"]; string eventCallingFunction = (string) request["Event-Calling-Function"];
if (eventCallingFunction == null) if (eventCallingFunction == null)
@ -173,7 +174,7 @@ namespace OpenSim.Services.FreeswitchService
} }
else else
{ {
m_log.ErrorFormat("[FreeSwitchVoice] HandleDirectoryRequest unknown sip_auth_method {0}",sipAuthMethod); m_log.ErrorFormat("[FreeSwitchVoice]: HandleDirectoryRequest unknown sip_auth_method {0}",sipAuthMethod);
response["int_response_code"] = 404; response["int_response_code"] = 404;
response["content_type"] = "text/xml"; response["content_type"] = "text/xml";
response["str_response_string"] = ""; response["str_response_string"] = "";
@ -205,7 +206,7 @@ namespace OpenSim.Services.FreeswitchService
} }
else else
{ {
m_log.ErrorFormat("[FreeSwitchVoice] HandleDirectoryRequest unknown Event-Calling-Function {0}",eventCallingFunction); m_log.ErrorFormat("[FreeSwitchVoice]: HandleDirectoryRequest unknown Event-Calling-Function {0}",eventCallingFunction);
response["int_response_code"] = 404; response["int_response_code"] = 404;
response["keepalive"] = false; response["keepalive"] = false;
response["content_type"] = "text/xml"; response["content_type"] = "text/xml";
@ -217,7 +218,7 @@ namespace OpenSim.Services.FreeswitchService
private Hashtable HandleRegister(string Context, string Realm, Hashtable request) private Hashtable HandleRegister(string Context, string Realm, Hashtable request)
{ {
m_log.Info("[FreeSwitchDirectory] HandleRegister called"); m_log.Info("[FreeSwitchDirectory]: HandleRegister called");
// TODO the password we return needs to match that sent in the request, this is hard coded for now // TODO the password we return needs to match that sent in the request, this is hard coded for now
string password = "1234"; string password = "1234";
@ -254,7 +255,7 @@ namespace OpenSim.Services.FreeswitchService
private Hashtable HandleInvite(string Context, string Realm, Hashtable request) private Hashtable HandleInvite(string Context, string Realm, Hashtable request)
{ {
m_log.Info("[FreeSwitchDirectory] HandleInvite called"); m_log.Info("[FreeSwitchDirectory]: HandleInvite called");
// TODO the password we return needs to match that sent in the request, this is hard coded for now // TODO the password we return needs to match that sent in the request, this is hard coded for now
string password = "1234"; string password = "1234";
@ -301,7 +302,7 @@ namespace OpenSim.Services.FreeswitchService
private Hashtable HandleLocateUser(String Realm, Hashtable request) private Hashtable HandleLocateUser(String Realm, Hashtable request)
{ {
m_log.Info("[FreeSwitchDirectory] HandleLocateUser called"); m_log.Info("[FreeSwitchDirectory]: HandleLocateUser called");
// TODO the password we return needs to match that sent in the request, this is hard coded for now // TODO the password we return needs to match that sent in the request, this is hard coded for now
string domain = (string) request["domain"]; string domain = (string) request["domain"];
@ -335,7 +336,7 @@ namespace OpenSim.Services.FreeswitchService
private Hashtable HandleConfigSofia(string Context, string Realm, Hashtable request) private Hashtable HandleConfigSofia(string Context, string Realm, Hashtable request)
{ {
m_log.Info("[FreeSwitchDirectory] HandleConfigSofia called"); m_log.Info("[FreeSwitchDirectory]: HandleConfigSofia called.");
// TODO the password we return needs to match that sent in the request, this is hard coded for now // TODO the password we return needs to match that sent in the request, this is hard coded for now
string domain = (string) request["domain"]; string domain = (string) request["domain"];

View File

@ -64,7 +64,7 @@ namespace OpenSim.Services.FreeswitchService
m_freeSwitchDefaultWellKnownIP = freeswitchConfig.GetString("ServerAddress", String.Empty); m_freeSwitchDefaultWellKnownIP = freeswitchConfig.GetString("ServerAddress", String.Empty);
if (m_freeSwitchDefaultWellKnownIP == String.Empty) if (m_freeSwitchDefaultWellKnownIP == String.Empty)
{ {
m_log.Error("[FREESWITCH]: No FreeswitchServerAddress given, can't continue"); m_log.Error("[FREESWITCH]: No ServerAddress given, cannot start service.");
return; return;
} }

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

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

View File

@ -621,31 +621,49 @@
;; You need to load a local service for a standalone, and a remote service ;; You need to load a local service for a standalone, and a remote service
;; for a grid region. Use one of the lines below, as appropriate ;; for a grid region. Use one of the lines below, as appropriate
;; If you're using Freeswitch on a standalone then you will also need to configure the [FreeswitchService] section
; LocalServiceModule = OpenSim.Services.FreeswitchService.dll:FreeswitchService ; LocalServiceModule = OpenSim.Services.FreeswitchService.dll:FreeswitchService
; LocalServiceModule = OpenSim.Services.Connectors.dll:RemoteFreeswitchConnector ; LocalServiceModule = OpenSim.Services.Connectors.dll:RemoteFreeswitchConnector
;; If using a remote module, specify the server URL ;; If using a remote connector, specify the server URL
; FreeswitchServiceURL = http://my.grid.server:8003/fsapi ; FreeswitchServiceURL = http://my.grid.server:8004/fsapi
[FreeswitchService] [FreeswitchService]
;; !!!!!!!!!!!!!!!!!!!!!!!!!!! ;; !!!!!!!!!!!!!!!!!!!!!!!!!!!
;; !!!!!!STANDALONE ONLY!!!!!! ;; !!!!!!STANDALONE ONLY!!!!!!
;; !!!!!!!!!!!!!!!!!!!!!!!!!!! ;; !!!!!!!!!!!!!!!!!!!!!!!!!!!
;; IP of your FS server ;; The IP address of your FreeSWITCH server. The common case is for this to be the same as the server running the OpenSim standalone
;ServerAddress = 85.25.142.92 ;; This has to be set for the FreeSWITCH service to work
;ServerAddress = 127.0.0.1
;; All other options are - well - optional ;; The following configuration parameters are optional
; Realm = "127.0.0.1"
; SIPProxy = "127.0.0.1:5060" ;; By default, this is the same as the ServerAddress
; EchoServer = "127.0.0.1" ; Realm = 127.0.0.1
; EchoPort = 50505
; AttemptSTUN = "false" ;; By default, this is the same as the ServerAddress on port 5060
; SIPProxy = 127.0.0.1:5060
;; Default is 5000ms
; DefaultTimeout = 5000 ; DefaultTimeout = 5000
; Context = "default"
; UserName = "freeswitch"
; Password = "password"
;; The dial plan context. Default is "default"
; Context = default
;; Currently unused
; UserName = freeswitch
;; Currently unused
; Password = password
;; The following parameters are for STUN = Simple Traversal of UDP through NATs
;; See http://wiki.freeswitch.org/wiki/NAT_Traversal
;; stun.freeswitch.org is not guaranteed to be running so use it in
;; production at your own risk
; EchoServer = 127.0.0.1
; EchoPort = 50505
; AttemptSTUN = false
[Groups] [Groups]
;# {Enabled} {} {Enable groups?} {true false} false ;# {Enabled} {} {Enable groups?} {true false} false

View File

@ -149,12 +149,6 @@
; to false if you have compatibility problems. ; to false if you have compatibility problems.
;CacheSculptMaps = true ;CacheSculptMaps = true
; if you use Meshmerizer and want collisions for meshies, setting this to true
; will cause OpenSim to attempt to decode meshies assets, extract the physics
; mesh, and use it for collisions. This is currently experimental code and enabling
; it may cause unexpected physics problems.
;UseMeshiesPhysicsMesh = false
; Choose one of the physics engines below ; Choose one of the physics engines below
; OpenDynamicsEngine is by some distance the most developed physics engine ; OpenDynamicsEngine is by some distance the most developed physics engine
; basicphysics effectively does not model physics at all, making all objects phantom ; basicphysics effectively does not model physics at all, making all objects phantom
@ -368,30 +362,24 @@
; ;
;client_throttle_max_bps = 196608 ;client_throttle_max_bps = 196608
; Per-client bytes per second rates for the various throttle categories. ; Adaptive throttling attempts to limit network overload when multiple
; These are default values that will be overriden by clients ; clients login by starting each connection more slowly. Disabled by
; default
; ;
;resend_default = 12500 ;enable_adaptive_throttles = true
;land_default = 1000
;wind_default = 1000
;cloud_default = 1000
;task_default = 1000
;texture_default = 1000
;asset_default = 1000
;state_default = 1000
; Per-client maximum burst rates in bytes per second for the various ; Per-client bytes per second rates for the various throttle categories.
; throttle categories. These are default values that will be overriden by ; These are default values that will be overriden by clients. These
; clients ; defaults are approximately equivalent to the throttles set by the Imprudence
; ; viewer when maximum bandwidth is set to 350kbps
;resend_limit = 18750
;land_limit = 29750 ;resend_default = 6625
;wind_limit = 18750 ;land_default = 9125
;cloud_limit = 18750 ;wind_default = 1750
;task_limit = 18750 ;cloud_default = 1750
;texture_limit = 55750 ;task_default = 18500
;asset_limit = 27500 ;texture_default = 18500
;state_limit = 37000 ;asset_default = 10500
; Configures how ObjectUpdates are aggregated. These numbers ; Configures how ObjectUpdates are aggregated. These numbers
; do not literally mean how many updates will be put in each ; do not literally mean how many updates will be put in each
@ -459,7 +447,13 @@
[Mesh] [Mesh]
; enable / disable Collada mesh support ; enable / disable Collada mesh support
; default is true ; default is true
; ColladaMesh = true ; AllowMeshUpload = true
; if you use Meshmerizer and want collisions for meshies, setting this to true
; will cause OpenSim to attempt to decode meshies assets, extract the physics
; mesh, and use it for collisions. This is currently experimental code and enabling
; it may cause unexpected physics problems.
;UseMeshiesPhysicsMesh = false
[ODEPhysicsSettings] [ODEPhysicsSettings]

0
bin/PhysX-wrapper.dll Normal file → Executable file
View File

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