merge conflits

httptests
UbitUmarov 2016-11-19 15:45:41 +00:00
commit 7cb3d583a9
21 changed files with 615 additions and 264 deletions

View File

@ -141,6 +141,11 @@ namespace OpenSim.Framework.Capabilities
m_capsActive.Reset();
}
~Caps()
{
m_capsActive.Dispose();
}
/// <summary>
/// Register a handler. This allows modules to register handlers.
/// </summary>

View File

@ -82,6 +82,7 @@ namespace OpenSim.Framework
public Vector3 ClientAgentPosition;
public bool UseClientAgentPosition;
public bool NeedsCameraCollision;
public uint lastpacketSequence;
public AgentUpdateArgs()
{

View File

@ -34,6 +34,7 @@ using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Timers;
using OpenMetaverse;
using Nini.Config;
using OpenSim.Framework.Servers.HttpServer;
@ -41,90 +42,232 @@ using log4net;
namespace OpenSim.Framework.Console
{
public class ConsoleConnection
{
public int last;
public long lastLineSeen;
public bool newConnection = true;
}
// A console that uses REST interfaces
//
public class RemoteConsole : CommandConsole
{
private IHttpServer m_Server = null;
private IConfigSource m_Config = null;
// Connection specific data, indexed by a session ID
// we create when a client connects.
protected class ConsoleConnection
{
// Last activity from the client
public int last;
private List<string> m_Scrollback = new List<string>();
private ManualResetEvent m_DataEvent = new ManualResetEvent(false);
private List<string> m_InputData = new List<string>();
private long m_LineNumber = 0;
private Dictionary<UUID, ConsoleConnection> m_Connections =
// Last line of scrollback posted to this client
public long lastLineSeen;
// True if this is a new connection, e.g. has never
// displayed a prompt to the user.
public bool newConnection = true;
}
// A line in the scrollback buffer.
protected class ScrollbackEntry
{
// The line number of this entry
public long lineNumber;
// The text to send to the client
public string text;
// The level this should be logged as. Omitted for
// prompts and input echo.
public string level;
// True if the text above is a prompt, e.g. the
// client should turn on the cursor / accept input
public bool isPrompt;
// True if the requested input is a command. A
// client may offer help or validate input if
// this is set. If false, input should be sent
// as typed.
public bool isCommand;
// True if this text represents a line of text that
// was input in response to a prompt. A client should
// turn off the cursor and refrain from sending commands
// until a new prompt is received.
public bool isInput;
}
// Data that is relevant to all connections
// The scrollback buffer
protected List<ScrollbackEntry> m_Scrollback = new List<ScrollbackEntry>();
// Monotonously incrementing line number. This may eventually
// wrap. No provision is made for that case because 64 bits
// is a long, long time.
protected long m_lineNumber = 0;
// These two variables allow us to send the correct
// information about the prompt status to the client,
// irrespective of what may have run off the top of the
// scrollback buffer;
protected bool m_expectingInput = false;
protected bool m_expectingCommand = true;
protected string m_lastPromptUsed;
// This is the list of things received from clients.
// Note: Race conditions can happen. If a client sends
// something while nothing is expected, it will be
// intepreted as input to the next prompt. For
// commands this is largely correct. For other prompts,
// YMMV.
// TODO: Find a better way to fix this
protected List<string> m_InputData = new List<string>();
// Event to allow ReadLine to wait synchronously even though
// everthing else is asynchronous here.
protected ManualResetEvent m_DataEvent = new ManualResetEvent(false);
// The list of sessions we maintain. Unlike other console types,
// multiple users on the same console are explicitly allowed.
protected Dictionary<UUID, ConsoleConnection> m_Connections =
new Dictionary<UUID, ConsoleConnection>();
private string m_UserName = String.Empty;
private string m_Password = String.Empty;
private string m_AllowedOrigin = String.Empty;
// Timer to control expiration of sessions that have been
// disconnected.
protected System.Timers.Timer m_expireTimer = new System.Timers.Timer(5000);
// The less interesting stuff that makes the actual server
// work.
protected IHttpServer m_Server = null;
protected IConfigSource m_Config = null;
protected string m_UserName = String.Empty;
protected string m_Password = String.Empty;
protected string m_AllowedOrigin = String.Empty;
public RemoteConsole(string defaultPrompt) : base(defaultPrompt)
{
// There is something wrong with this architecture.
// A prompt is sent on every single input, so why have this?
// TODO: Investigate and fix.
m_lastPromptUsed = defaultPrompt;
// Start expiration of sesssions.
m_expireTimer.Elapsed += DoExpire;
m_expireTimer.Start();
}
public void ReadConfig(IConfigSource config)
{
m_Config = config;
// We're pulling this from the 'Network' section for legacy
// compatibility. However, this is so essentially insecure
// that TLS and client certs should be used instead of
// a username / password.
IConfig netConfig = m_Config.Configs["Network"];
if (netConfig == null)
return;
// Get the username and password.
m_UserName = netConfig.GetString("ConsoleUser", String.Empty);
m_Password = netConfig.GetString("ConsolePass", String.Empty);
// Woefully underdocumented, this is what makes javascript
// console clients work. Set to "*" for anywhere or (better)
// to specific addresses.
m_AllowedOrigin = netConfig.GetString("ConsoleAllowedOrigin", String.Empty);
}
public void SetServer(IHttpServer server)
{
// This is called by the framework to give us the server
// instance (means: port) to work with.
m_Server = server;
// Add our handlers
m_Server.AddHTTPHandler("/StartSession/", HandleHttpStartSession);
m_Server.AddHTTPHandler("/CloseSession/", HandleHttpCloseSession);
m_Server.AddHTTPHandler("/SessionCommand/", HandleHttpSessionCommand);
}
public override void Output(string text, string level)
{
Output(text, level, false, false, false);
}
protected void Output(string text, string level, bool isPrompt, bool isCommand, bool isInput)
{
// Increment the line number. It was 0 and they start at 1
// so we need to pre-increment.
m_lineNumber++;
// Create and populate the new entry.
ScrollbackEntry newEntry = new ScrollbackEntry();
newEntry.lineNumber = m_lineNumber;
newEntry.text = text;
newEntry.level = level;
newEntry.isPrompt = isPrompt;
newEntry.isCommand = isCommand;
newEntry.isInput = isInput;
// Add a line to the scrollback. In some cases, that may not
// actually be a line of text.
lock (m_Scrollback)
{
// Prune the scrollback to the length se send as connect
// burst to give the user some context.
while (m_Scrollback.Count >= 1000)
m_Scrollback.RemoveAt(0);
m_LineNumber++;
m_Scrollback.Add(String.Format("{0}", m_LineNumber)+":"+level+":"+text);
m_Scrollback.Add(newEntry);
}
// Let the rest of the system know we have output something.
FireOnOutput(text.Trim());
// Also display it for debugging.
System.Console.WriteLine(text.Trim());
}
public override void Output(string text)
{
Output(text, "normal");
// Output plain (non-logging style) text.
Output(text, String.Empty, false, false, false);
}
public override string ReadLine(string p, bool isCommand, bool e)
{
if (isCommand)
Output("+++"+p);
else
Output("-++"+p);
// Output the prompt an prepare to wait. This
// is called on a dedicated console thread and
// needs to be synchronous. Old architecture but
// not worth upgrading.
if (isCommand)
{
m_expectingInput = true;
m_expectingCommand = true;
Output(p, String.Empty, true, true, false);
m_lastPromptUsed = p;
}
else
{
m_expectingInput = true;
Output(p, String.Empty, true, false, false);
}
// Here is where we wait for the user to input something.
m_DataEvent.WaitOne();
string cmdinput;
// Check for empty input. Read input if not empty.
lock (m_InputData)
{
if (m_InputData.Count == 0)
{
m_DataEvent.Reset();
m_expectingInput = false;
m_expectingCommand = false;
return "";
}
@ -135,8 +278,19 @@ namespace OpenSim.Framework.Console
}
m_expectingInput = false;
m_expectingCommand = false;
// Echo to all the other users what we have done. This
// will also go to ourselves.
Output (cmdinput, String.Empty, false, false, true);
// If this is a command, we need to resolve and execute it.
if (isCommand)
{
// This call will actually execute the command and create
// any output associated with it. The core just gets an
// empty string so it will call again immediately.
string[] cmd = Commands.Resolve(Parser.Parse(cmdinput));
if (cmd.Length != 0)
@ -151,18 +305,23 @@ namespace OpenSim.Framework.Console
return String.Empty;
}
}
// Return the raw input string if not a command.
return cmdinput;
}
private Hashtable CheckOrigin(Hashtable result)
// Very simplistic static access control header.
protected Hashtable CheckOrigin(Hashtable result)
{
if (!string.IsNullOrEmpty(m_AllowedOrigin))
result["access_control_allow_origin"] = m_AllowedOrigin;
return result;
}
/* TODO: Figure out how PollServiceHTTPHandler can access the request headers
* in order to use m_AllowedOrigin as a regular expression
private Hashtable CheckOrigin(Hashtable headers, Hashtable result)
protected Hashtable CheckOrigin(Hashtable headers, Hashtable result)
{
if (!string.IsNullOrEmpty(m_AllowedOrigin))
{
@ -177,18 +336,23 @@ namespace OpenSim.Framework.Console
}
*/
private void DoExpire()
protected void DoExpire(Object sender, ElapsedEventArgs e)
{
// Iterate the list of console connections and find those we
// haven't heard from for longer then the longpoll interval.
// Remove them.
List<UUID> expired = new List<UUID>();
lock (m_Connections)
{
// Mark the expired ones
foreach (KeyValuePair<UUID, ConsoleConnection> kvp in m_Connections)
{
if (System.Environment.TickCount - kvp.Value.last > 500000)
expired.Add(kvp.Key);
}
// Delete them
foreach (UUID id in expired)
{
m_Connections.Remove(id);
@ -197,10 +361,10 @@ namespace OpenSim.Framework.Console
}
}
private Hashtable HandleHttpStartSession(Hashtable request)
// Start a new session.
protected Hashtable HandleHttpStartSession(Hashtable request)
{
DoExpire();
// The login is in the form of a http form post
Hashtable post = DecodePostString(request["body"].ToString());
Hashtable reply = new Hashtable();
@ -208,6 +372,7 @@ namespace OpenSim.Framework.Console
reply["int_response_code"] = 401;
reply["content_type"] = "text/plain";
// Check user name and password
if (m_UserName == String.Empty)
return reply;
@ -220,22 +385,28 @@ namespace OpenSim.Framework.Console
return reply;
}
// Set up the new console connection record
ConsoleConnection c = new ConsoleConnection();
c.last = System.Environment.TickCount;
c.lastLineSeen = 0;
// Assign session ID
UUID sessionID = UUID.Random();
// Add connection to list.
lock (m_Connections)
{
m_Connections[sessionID] = c;
}
// This call is a CAP. The URL is the authentication.
string uri = "/ReadResponses/" + sessionID.ToString() + "/";
m_Server.AddPollServiceHTTPHandler(
uri, new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, Drop, sessionID, 25000)); // 25 secs timeout
uri, new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, sessionID,25000)); // 25 secs timeout
// Our reply is an XML document.
// TODO: Change this to Linq.Xml
XmlDocument xmldoc = new XmlDocument();
XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
"", "");
@ -252,12 +423,13 @@ namespace OpenSim.Framework.Console
rootElement.AppendChild(id);
XmlElement prompt = xmldoc.CreateElement("", "Prompt", "");
prompt.AppendChild(xmldoc.CreateTextNode(DefaultPrompt));
prompt.AppendChild(xmldoc.CreateTextNode(m_lastPromptUsed));
rootElement.AppendChild(prompt);
rootElement.AppendChild(MainConsole.Instance.Commands.GetXml(xmldoc));
// Set up the response and check origin
reply["str_response_string"] = xmldoc.InnerXml;
reply["int_response_code"] = 200;
reply["content_type"] = "text/xml";
@ -266,10 +438,9 @@ namespace OpenSim.Framework.Console
return reply;
}
private Hashtable HandleHttpCloseSession(Hashtable request)
// Client closes session. Clean up.
protected Hashtable HandleHttpCloseSession(Hashtable request)
{
DoExpire();
Hashtable post = DecodePostString(request["body"].ToString());
Hashtable reply = new Hashtable();
@ -316,10 +487,9 @@ namespace OpenSim.Framework.Console
return reply;
}
private Hashtable HandleHttpSessionCommand(Hashtable request)
// Command received from the client.
protected Hashtable HandleHttpSessionCommand(Hashtable request)
{
DoExpire();
Hashtable post = DecodePostString(request["body"].ToString());
Hashtable reply = new Hashtable();
@ -327,6 +497,7 @@ namespace OpenSim.Framework.Console
reply["int_response_code"] = 404;
reply["content_type"] = "text/plain";
// Check the ID
if (post["ID"] == null)
return reply;
@ -334,21 +505,25 @@ namespace OpenSim.Framework.Console
if (!UUID.TryParse(post["ID"].ToString(), out id))
return reply;
// Find the connection for that ID.
lock (m_Connections)
{
if (!m_Connections.ContainsKey(id))
return reply;
}
// Empty post. Just error out.
if (post["COMMAND"] == null)
return reply;
// Place the input data in the buffer.
lock (m_InputData)
{
m_DataEvent.Set();
m_InputData.Add(post["COMMAND"].ToString());
}
// Create the XML reply document.
XmlDocument xmldoc = new XmlDocument();
XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
"", "");
@ -372,7 +547,8 @@ namespace OpenSim.Framework.Console
return reply;
}
private Hashtable DecodePostString(string data)
// Decode a HTTP form post to a Hashtable
protected Hashtable DecodePostString(string data)
{
Hashtable result = new Hashtable();
@ -396,6 +572,7 @@ namespace OpenSim.Framework.Console
return result;
}
// Close the CAP receiver for the responses for a given client.
public void CloseConnection(UUID id)
{
try
@ -409,7 +586,9 @@ namespace OpenSim.Framework.Console
}
}
private bool HasEvents(UUID RequestID, UUID sessionID)
// Check if there is anything to send. Return true if this client has
// lines pending.
protected bool HasEvents(UUID RequestID, UUID sessionID)
{
ConsoleConnection c = null;
@ -420,22 +599,15 @@ namespace OpenSim.Framework.Console
c = m_Connections[sessionID];
}
c.last = System.Environment.TickCount;
if (c.lastLineSeen < m_LineNumber)
if (c.lastLineSeen < m_lineNumber)
return true;
return false;
}
private void Drop(UUID RequestID, UUID sessionID)
{
lock (m_Connections)
{
if (m_Connections.ContainsKey(sessionID))
m_Connections.Remove(sessionID);
}
}
private Hashtable GetEvents(UUID RequestID, UUID sessionID)
// Send all pending output to the client.
protected Hashtable GetEvents(UUID RequestID, UUID sessionID)
{
// Find the connection that goes with this client.
ConsoleConnection c = null;
lock (m_Connections)
@ -444,12 +616,15 @@ namespace OpenSim.Framework.Console
return NoEvents(RequestID, UUID.Zero);
c = m_Connections[sessionID];
}
// If we have nothing to send, send the no events response.
c.last = System.Environment.TickCount;
if (c.lastLineSeen >= m_LineNumber)
if (c.lastLineSeen >= m_lineNumber)
return NoEvents(RequestID, UUID.Zero);
Hashtable result = new Hashtable();
// Create the response document.
XmlDocument xmldoc = new XmlDocument();
XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
"", "");
@ -458,30 +633,53 @@ namespace OpenSim.Framework.Console
XmlElement rootElement = xmldoc.CreateElement("", "ConsoleSession",
"");
if (c.newConnection)
{
c.newConnection = false;
Output("+++" + DefaultPrompt);
}
//if (c.newConnection)
//{
// c.newConnection = false;
// Output("+++" + DefaultPrompt);
//}
lock (m_Scrollback)
{
long startLine = m_LineNumber - m_Scrollback.Count;
long startLine = m_lineNumber - m_Scrollback.Count;
long sendStart = startLine;
if (sendStart < c.lastLineSeen)
sendStart = c.lastLineSeen;
for (long i = sendStart ; i < m_LineNumber ; i++)
for (long i = sendStart ; i < m_lineNumber ; i++)
{
ScrollbackEntry e = m_Scrollback[(int)(i - startLine)];
XmlElement res = xmldoc.CreateElement("", "Line", "");
long line = i + 1;
res.SetAttribute("Number", line.ToString());
res.AppendChild(xmldoc.CreateTextNode(m_Scrollback[(int)(i - startLine)]));
res.SetAttribute("Number", e.lineNumber.ToString());
res.SetAttribute("Level", e.level);
// Don't include these for the scrollback, we'll send the
// real state later.
if (!c.newConnection)
{
res.SetAttribute("Prompt", e.isPrompt ? "true" : "false");
res.SetAttribute("Command", e.isCommand ? "true" : "false");
res.SetAttribute("Input", e.isInput ? "true" : "false");
}
else if (i == m_lineNumber - 1) // Last line for a new connection
{
res.SetAttribute("Prompt", m_expectingInput ? "true" : "false");
res.SetAttribute("Command", m_expectingCommand ? "true" : "false");
res.SetAttribute("Input", (!m_expectingInput) ? "true" : "false");
}
else
{
res.SetAttribute("Input", e.isInput ? "true" : "false");
}
res.AppendChild(xmldoc.CreateTextNode(e.text));
rootElement.AppendChild(res);
}
}
c.lastLineSeen = m_LineNumber;
c.lastLineSeen = m_lineNumber;
c.newConnection = false;
xmldoc.AppendChild(rootElement);
@ -495,7 +693,9 @@ namespace OpenSim.Framework.Console
return result;
}
private Hashtable NoEvents(UUID RequestID, UUID id)
// This is really just a no-op. It generates what is sent
// to the client if the poll times out without any events.
protected Hashtable NoEvents(UUID RequestID, UUID id)
{
Hashtable result = new Hashtable();

View File

@ -55,6 +55,11 @@ namespace OpenSim.Framework
Dictionary2 = new Dictionary<TKey2, TValue>(capacity);
}
~DoubleDictionaryThreadAbortSafe()
{
rwLock.Dispose();
}
public void Add(TKey1 key1, TKey2 key2, TValue value)
{
bool gotLock = false;

View File

@ -93,7 +93,10 @@ namespace OpenSim.Framework
if (oldHead == oldTail)
{
if (oldHeadNext == null)
{
count = 0;
return false;
}
CAS(ref tail, oldTail, oldHeadNext);
}
@ -118,8 +121,7 @@ namespace OpenSim.Framework
{
// ugly
T item;
while(count > 0)
Dequeue(out item);
while(Dequeue(out item));
Init();
}

View File

@ -64,6 +64,13 @@ namespace OpenSim.Framework
/// </value>
private volatile System.Threading.ReaderWriterLockSlim m_itemLock = new System.Threading.ReaderWriterLockSlim();
~TaskInventoryDictionary()
{
m_itemLock.Dispose();
m_itemLock = null;
}
/// <summary>
/// Are we readlocked by the calling thread?
/// </summary>

View File

@ -1062,11 +1062,10 @@ namespace OpenSim.Framework
if (WebUtil.DebugLevel >= 5)
WebUtil.LogOutgoingDetail("SEND", reqnum, System.Text.Encoding.UTF8.GetString(data));
Stream requestStream = null;
try
{
requestStream = request.GetRequestStream();
requestStream.Write(data, 0, length);
using(Stream requestStream = request.GetRequestStream())
requestStream.Write(data,0,length);
}
catch (Exception e)
{
@ -1076,9 +1075,6 @@ namespace OpenSim.Framework
}
finally
{
if (requestStream != null)
requestStream.Dispose();
// capture how much time was spent writing
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
}

View File

@ -346,12 +346,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private bool m_VelocityInterpolate = false;
private const uint MaxTransferBytesPerPacket = 600;
/// <value>
/// List used in construction of data blocks for an object update packet. This is to stop us having to
/// continually recreate it.
/// </value>
protected List<ObjectUpdatePacket.ObjectDataBlock> m_fullUpdateDataBlocksBuilder;
/// <value>
/// Maintain a record of all the objects killed. This allows us to stop an update being sent from the
/// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
@ -511,7 +505,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_scene = scene;
m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
m_entityProps = new PriorityQueue(m_scene.Entities.Count);
m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
m_killRecord = new List<uint>();
// m_attachmentsSent = new HashSet<uint>();
@ -594,13 +587,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OutPacket(disable, ThrottleOutPacketType.Unknown);
}
// Shutdown the image manager
ImageManager.Close();
// Fire the callback for this connection closing
if (OnConnectionClosed != null)
OnConnectionClosed(this);
// Flush all of the packets out of the UDP server for this client
if (m_udpServer != null)
m_udpServer.Flush(m_udpClient);
@ -615,8 +607,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Disable UDP handling for this client
m_udpClient.Shutdown();
m_udpClient.OnQueueEmpty -= HandleQueueEmpty;
m_udpClient.HasUpdates -= HandleHasUpdates;
m_udpClient.OnPacketStats -= PopulateStats;
// Shutdown the image manager
ImageManager.Close();
ImageManager = null;
m_entityUpdates = null;
m_entityProps = null;
m_killRecord.Clear();
GroupsInView.Clear();
m_scene = null;
//m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
//GC.Collect();
//m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
@ -814,7 +818,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void ProcessSpecificPacketAsync(object state)
{
AsyncPacketProcess packetObject = (AsyncPacketProcess)state;
try
{
packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack);
@ -4095,19 +4099,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
ResendPrimUpdate(update);
}
private List<ObjectUpdatePacket.ObjectDataBlock> objectUpdateBlocks = new List<ObjectUpdatePacket.ObjectDataBlock>();
private List<ObjectUpdateCompressedPacket.ObjectDataBlock> compressedUpdateBlocks = new List<ObjectUpdateCompressedPacket.ObjectDataBlock>();
private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> terseUpdateBlocks = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> terseAgentUpdateBlocks = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
private void ProcessEntityUpdates(int maxUpdatesBytes)
{
OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.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<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
// Check to see if this is a flush
if (maxUpdatesBytes <= 0)
{
@ -4328,7 +4331,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
else
ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId);
objectUpdateBlocks.Value.Add(ablock);
objectUpdateBlocks.Add(ablock);
objectUpdates.Value.Add(update);
maxUpdatesBytes -= ablock.Length;
@ -4337,7 +4340,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
ObjectUpdateCompressedPacket.ObjectDataBlock ablock =
CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags);
compressedUpdateBlocks.Value.Add(ablock);
compressedUpdateBlocks.Add(ablock);
compressedUpdates.Value.Add(update);
maxUpdatesBytes -= ablock.Length;
}
@ -4348,14 +4351,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
// ALL presence updates go into a special list
ablock = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures));
terseAgentUpdateBlocks.Value.Add(ablock);
terseAgentUpdateBlocks.Add(ablock);
terseAgentUpdates.Value.Add(update);
}
else
{
// Everything else goes here
ablock = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures));
terseUpdateBlocks.Value.Add(ablock);
terseUpdateBlocks.Add(ablock);
terseUpdates.Value.Add(update);
}
maxUpdatesBytes -= ablock.Length;
@ -4366,74 +4369,72 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Packet Sending
// const float TIME_DILATION = 1.0f;
ushort timeDilation;
// if(updatesThisCall > 0)
// timeDilation = Utils.FloatToUInt16(avgTimeDilation/updatesThisCall, 0.0f, 1.0f);
// else
// timeDilation = ushort.MaxValue; // 1.0;
if(m_scene == null)
return;
timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
if (terseAgentUpdateBlocks.IsValueCreated)
if (terseAgentUpdateBlocks.Count > 0)
{
List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
ImprovedTerseObjectUpdatePacket packet
= (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
packet.RegionData.TimeDilation = timeDilation;
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[terseAgentUpdateBlocks.Count];
for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i];
for (int i = 0; i < terseAgentUpdateBlocks.Count; i++)
packet.ObjectData[i] = terseAgentUpdateBlocks[i];
terseAgentUpdateBlocks.Clear();
OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); });
}
if (objectUpdateBlocks.IsValueCreated)
if (objectUpdateBlocks.Count > 0)
{
List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
packet.RegionData.TimeDilation = timeDilation;
packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[objectUpdateBlocks.Count];
for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i];
for (int i = 0; i < objectUpdateBlocks.Count; i++)
packet.ObjectData[i] = objectUpdateBlocks[i];
objectUpdateBlocks.Clear();
OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
}
if (compressedUpdateBlocks.IsValueCreated)
if (compressedUpdateBlocks.Count > 0)
{
List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
packet.RegionData.TimeDilation = timeDilation;
packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[compressedUpdateBlocks.Count];
for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i];
for (int i = 0; i < compressedUpdateBlocks.Count; i++)
packet.ObjectData[i] = compressedUpdateBlocks[i];
compressedUpdateBlocks.Clear();
OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
}
if (terseUpdateBlocks.IsValueCreated)
if (terseUpdateBlocks.Count > 0)
{
List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
ImprovedTerseObjectUpdatePacket packet
= (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
PacketType.ImprovedTerseObjectUpdate);
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
packet.RegionData.TimeDilation = timeDilation;
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[terseUpdateBlocks.Count];
for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i];
for (int i = 0; i < terseUpdateBlocks.Count; i++)
packet.ObjectData[i] = terseUpdateBlocks[i];
terseUpdateBlocks.Clear();
OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
}
@ -4634,6 +4635,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
{
if(m_scene == null)
return;
if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
{
int maxUpdateBytes = m_udpClient.GetCatBytesCanSend(ThrottleOutPacketType.Task, 30);
@ -4828,21 +4832,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,0,false,true));
}
List<ObjectPropertiesFamilyPacket.ObjectDataBlock> objectFamilyBlocks = new
List<ObjectPropertiesFamilyPacket.ObjectDataBlock>();
List<ObjectPropertiesPacket.ObjectDataBlock> objectPropertiesBlocks =
new List<ObjectPropertiesPacket.ObjectDataBlock>();
List<SceneObjectPart> needPhysics = new List<SceneObjectPart>();
private void ProcessEntityPropertyRequests(int maxUpdateBytes)
{
OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>> objectFamilyBlocks =
new OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>>();
// OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> familyUpdates =
// new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks =
new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>();
OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> familyUpdates =
new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates =
new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
// OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates =
// new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
List<SceneObjectPart> needPhysics = new List<SceneObjectPart>();
EntityUpdate iupdate;
Int32 timeinqueue; // this is just debugging code & can be dropped later
@ -4860,8 +4863,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
SceneObjectPart sop = (SceneObjectPart)update.Entity;
ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
objectFamilyBlocks.Value.Add(objPropDB);
familyUpdates.Value.Add(update);
objectFamilyBlocks.Add(objPropDB);
// familyUpdates.Value.Add(update);
maxUpdateBytes -= objPropDB.Length;
}
}
@ -4873,23 +4876,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
SceneObjectPart sop = (SceneObjectPart)update.Entity;
needPhysics.Add(sop);
ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
objectPropertiesBlocks.Value.Add(objPropDB);
propertyUpdates.Value.Add(update);
objectPropertiesBlocks.Add(objPropDB);
// propertyUpdates.Value.Add(update);
maxUpdateBytes -= objPropDB.Length;
}
}
}
if (objectPropertiesBlocks.IsValueCreated)
if (objectPropertiesBlocks.Count > 0)
{
List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value;
List<ObjectPropertyUpdate> updates = propertyUpdates.Value;
ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count];
for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i];
packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[objectPropertiesBlocks.Count];
for (int i = 0; i < objectPropertiesBlocks.Count; i++)
packet.ObjectData[i] = objectPropertiesBlocks[i];
objectPropertiesBlocks.Clear();
packet.Header.Zerocoded = true;
// Pass in the delegate so that if this packet needs to be resent, we send the current properties
@ -4898,7 +4900,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
//OutPacket(packet, ThrottleOutPacketType.Task, true,
// delegate(OutgoingPacket oPacket)
// {
// ResendPropertyUpdates(updates, oPacket);
// ResendPropertyUpdates(propertyUpdates.Value, oPacket);
// });
OutPacket(packet, ThrottleOutPacketType.Task, true);
@ -4909,23 +4911,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Int32 fpcnt = 0;
// Int32 fbcnt = 0;
if (objectFamilyBlocks.IsValueCreated)
{
List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value;
if (objectFamilyBlocks.Count > 0)
{
// one packet per object block... uggh...
for (int i = 0; i < blocks.Count; i++)
for (int i = 0; i < objectFamilyBlocks.Count; i++)
{
ObjectPropertiesFamilyPacket packet =
(ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
packet.ObjectData = blocks[i];
packet.ObjectData = objectFamilyBlocks[i];
packet.Header.Zerocoded = true;
// Pass in the delegate so that if this packet needs to be resent, we send the current properties
// of the object rather than the properties when the packet was created
List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
updates.Add(familyUpdates.Value[i]);
// List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
// updates.Add(familyUpdates.Value[i]);
// HACK : Remove intelligent resending until it's fixed in core
//OutPacket(packet, ThrottleOutPacketType.Task, true,
// delegate(OutgoingPacket oPacket)
@ -4937,6 +4937,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// fpcnt++;
// fbcnt++;
}
objectFamilyBlocks.Clear();
}
if(needPhysics.Count > 0)
@ -4962,6 +4963,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
eq.Enqueue(BuildEvent("ObjectPhysicsProperties", llsdBody),AgentId);
}
needPhysics.Clear();
}
// m_log.WarnFormat("[PACKETCOUNTS] queued {0} property packets with {1} blocks",ppcnt,pbcnt);
@ -6251,9 +6253,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return false;
}
uint seq = packet.Header.Sequence;
TotalAgentUpdates++;
// dont let ignored updates pollute this throttles
if(SceneAgent == null || SceneAgent.IsChildAgent || SceneAgent.IsInTransit)
if(SceneAgent == null || SceneAgent.IsChildAgent ||
SceneAgent.IsInTransit || seq <= m_thisAgentUpdateArgs.lastpacketSequence )
{
// throttle reset is done at MoveAgentIntoRegion()
// called by scenepresence on completemovement
@ -6261,6 +6266,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return true;
}
m_thisAgentUpdateArgs.lastpacketSequence = seq;
bool movement = CheckAgentMovementUpdateSignificance(x);
bool camera = CheckAgentCameraUpdateSignificance(x);

View File

@ -120,13 +120,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary>Circuit code that this client is connected on</summary>
public readonly uint CircuitCode;
/// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200);
public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200);
/// <summary>Packets we have sent that need to be ACKed by the client</summary>
public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
public UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
/// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
public readonly DoubleLocklessQueue<uint> PendingAcks = new DoubleLocklessQueue<uint>();
public DoubleLocklessQueue<uint> PendingAcks = new DoubleLocklessQueue<uint>();
/// <summary>Current packet sequence number</summary>
public int CurrentSequence;
@ -170,7 +170,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private double m_nextOnQueueEmpty = 0;
/// <summary>Throttle bucket for this agent's connection</summary>
private readonly AdaptiveTokenBucket m_throttleClient;
private AdaptiveTokenBucket m_throttleClient;
public AdaptiveTokenBucket FlowThrottle
{
get { return m_throttleClient; }
@ -179,10 +179,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary>Throttle buckets for each packet category</summary>
private readonly TokenBucket[] m_throttleCategories;
/// <summary>Outgoing queues for throttled packets</summary>
private readonly DoubleLocklessQueue<OutgoingPacket>[] m_packetOutboxes = new DoubleLocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT];
private DoubleLocklessQueue<OutgoingPacket>[] m_packetOutboxes = new DoubleLocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT];
/// <summary>A container that can hold one packet for each outbox, used to store
/// dequeued packets that are being held for throttling</summary>
private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT];
private OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT];
/// <summary>A reference to the LLUDPServer that is managing this client</summary>
private readonly LLUDPServer m_udpServer;
@ -288,14 +288,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
{
m_packetOutboxes[i].Clear();
m_throttleCategories[i] = null;
m_nextPackets[i] = null;
}
// pull the throttle out of the scene throttle
m_throttleClient.Parent.UnregisterRequest(m_throttleClient);
m_throttleClient = null;
OnPacketStats = null;
OnQueueEmpty = null;
}
PendingAcks.Clear();
NeedAcks.Clear();
NeedAcks = null;
PendingAcks = null;
m_nextPackets = null;
m_packetOutboxes = null;
}
/// <summary>
/// Gets information about this client connection

View File

@ -326,7 +326,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
protected double m_tickLastOutgoingPacketHandler;
/// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary>
protected int m_elapsedMSOutgoingPacketHandler;
protected double m_elapsedMSOutgoingPacketHandler;
/// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary>
protected int m_elapsed100MSOutgoingPacketHandler;
@ -2074,18 +2074,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Update elapsed time
double thisTick = Util.GetTimeStampMS();
int deltaMS = (int)(thisTick - m_tickLastOutgoingPacketHandler);
m_tickLastOutgoingPacketHandler = thisTick;
// update some 1ms resolution chained timers
m_elapsedMSOutgoingPacketHandler += deltaMS;
m_elapsedMSOutgoingPacketHandler += thisTick - m_tickLastOutgoingPacketHandler;
m_tickLastOutgoingPacketHandler = thisTick;
// Check for pending outgoing resends every 100ms
if (m_elapsedMSOutgoingPacketHandler >= 100)
if (m_elapsedMSOutgoingPacketHandler >= 100.0)
{
m_resendUnacked = true;
m_elapsedMSOutgoingPacketHandler = 0;
m_elapsedMSOutgoingPacketHandler = 0.0;
m_elapsed100MSOutgoingPacketHandler += 1;
}

View File

@ -193,7 +193,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Parent = parent;
RequestedDripRate = dripRate;
RequestedBurst = MaxBurst;
m_lastDrip = Util.GetTimeStampMS() + 50.0;
m_lastDrip = Util.GetTimeStampMS() + 100000.0; // skip first drip
}
#endregion Constructor

View File

@ -74,6 +74,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary>Holds information about pending removals</summary>
private LocklessQueue<uint> m_pendingRemoves = new LocklessQueue<uint>();
public void Clear()
{
m_packets.Clear();
m_pendingAdds = null;
m_pendingAcknowledgements = null;
m_pendingRemoves = null;
}
/// <summary>
/// Add an unacked packet to the collection
/// </summary>

View File

@ -36,6 +36,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
{
public class UserAccountCache : IUserAccountCacheModule
{
private const double CACHE_ALIEN_EXPIRATION_SECONDS = 172800; // 48 hours
private const double CACHE_EXPIRATION_SECONDS = 3600.0; // 1 hour!
private const double CACHE_NULL_EXPIRATION_SECONDS = 600; // 10minutes
@ -60,21 +61,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
{
if (account == null)
m_UUIDCache.AddOrUpdate(userID, null, CACHE_NULL_EXPIRATION_SECONDS);
else
else if(account.LocalToGrid)
{
m_UUIDCache.AddOrUpdate(userID, account, CACHE_EXPIRATION_SECONDS);
m_NameCache.AddOrUpdate(account.Name, account.PrincipalID, CACHE_EXPIRATION_SECONDS);
}
else
{
m_UUIDCache.AddOrUpdate(userID, account, CACHE_ALIEN_EXPIRATION_SECONDS);
m_NameCache.AddOrUpdate(account.Name, account.PrincipalID, CACHE_ALIEN_EXPIRATION_SECONDS);
}
//m_log.DebugFormat("[USER CACHE]: cached user {0}", userID);
}
}
public void Invalidate(UUID userID)
{
lock(accessLock)
m_UUIDCache.Remove(userID);
}
public UserAccount Get(UUID userID, out bool inCache)
{
@ -114,6 +114,25 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
return null;
}
public void Invalidate(UUID userID)
{
m_UUIDCache.Remove(userID);
}
public void Remove(UUID id)
{
lock(accessLock)
{
if (!m_UUIDCache.Contains(id))
return;
UserAccount account = null;
if (m_UUIDCache.TryGetValue(id, out account) && account != null)
m_NameCache.Remove(account.Name);
m_UUIDCache.Remove(id);
}
}
public void Remove(string name)
{
lock(accessLock)

View File

@ -26,8 +26,10 @@
*/
using OpenSim.Region.Framework.Scenes;
using OpenMetaverse;
public interface IUserAccountCacheModule
{
void Remove(string name);
void Remove(UUID id);
}

View File

@ -4141,7 +4141,8 @@ namespace OpenSim.Region.Framework.Scenes
{
IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
if (cache != null)
cache.Remove(acd.firstname + " " + acd.lastname);
// cache.Remove(acd.firstname + " " + acd.lastname);
cache.Remove(acd.AgentID);
// Remove any preexisting circuit - we don't want duplicates
// This is a stab at preventing avatar "ghosting"

View File

@ -1104,7 +1104,7 @@ namespace OpenSim.Region.Framework.Scenes
AdjustKnownSeeds();
RegisterToEvents();
RegisterToClientEvents();
SetDirectionVectors();
Appearance = appearance;
@ -1171,7 +1171,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void RegisterToEvents()
public void RegisterToClientEvents()
{
ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
ControllingClient.OnAgentUpdate += HandleAgentUpdate;
@ -1189,6 +1189,22 @@ namespace OpenSim.Region.Framework.Scenes
// ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
// ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
}
public void RemoveClientEvents()
{
ControllingClient.OnCompleteMovementToRegion -= CompleteMovement;
ControllingClient.OnAgentUpdate -= HandleAgentUpdate;
ControllingClient.OnAgentCameraUpdate -= HandleAgentCamerasUpdate;
ControllingClient.OnAgentRequestSit -= HandleAgentRequestSit;
ControllingClient.OnAgentSit -= HandleAgentSit;
ControllingClient.OnSetAlwaysRun -= HandleSetAlwaysRun;
ControllingClient.OnStartAnim -= HandleStartAnim;
ControllingClient.OnStopAnim -= HandleStopAnim;
ControllingClient.OnChangeAnim -= avnHandleChangeAnim;
ControllingClient.OnForceReleaseControls -= HandleForceReleaseControls;
ControllingClient.OnAutoPilotGo -= MoveToTarget;
ControllingClient.OnUpdateThrottles -= RaiseUpdateThrottles;
}
private void SetDirectionVectors()
{
@ -2318,7 +2334,7 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 tocam = CameraPosition - posAdjusted;
float distTocamlen = tocam.LengthSquared();
if (distTocamlen > 0.08f && distTocamlen < 400)
if (distTocamlen > 0.01f && distTocamlen < 400)
{
distTocamlen = (float)Math.Sqrt(distTocamlen);
tocam *= (1.0f / distTocamlen);
@ -4378,16 +4394,12 @@ namespace OpenSim.Region.Framework.Scenes
m_log.DebugFormat(
"[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}",
knownRegions.Count, Scene.RegionInfo.RegionName);
//DumpKnownRegions();
Util.RegionHandleToRegionLoc(newRegionHandle, out newRegionX, out newRegionY);
uint x, y;
spRegionSizeInfo regInfo;
// this should not be here
IEventQueue eventQueue = Scene.RequestModuleInterface<IEventQueue>();
foreach (ulong handle in knownRegions)
{
// Don't close the agent on this region yet
@ -4400,16 +4412,10 @@ namespace OpenSim.Region.Framework.Scenes
Util.RegionHandleToRegionLoc(handle, out x, out y);
if (m_knownChildRegionsSizeInfo.TryGetValue(handle, out regInfo))
{
// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY,
regInfo.sizeX, regInfo.sizeY, newRegionSizeX, newRegionSizeY))
{
byebyeRegions.Add(handle);
// this should not be here
// if(eventQueue != null)
/// eventQueue.DisableSimulator(handle,UUID);
}
}
else
@ -4445,6 +4451,32 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void closeAllChildAgents()
{
List<ulong> byebyeRegions = new List<ulong>();
List<ulong> knownRegions = KnownRegionHandles;
foreach (ulong handle in knownRegions)
{
if (handle != Scene.RegionInfo.RegionHandle)
{
byebyeRegions.Add(handle);
RemoveNeighbourRegion(handle);
Scene.CapsModule.DropChildSeed(UUID, handle);
}
}
if (byebyeRegions.Count > 0)
{
m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID);
string auth = string.Empty;
if (acd != null)
auth = acd.SessionID.ToString();
m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
}
}
#endregion
/// <summary>
@ -5000,12 +5032,16 @@ namespace OpenSim.Region.Framework.Scenes
RemoveFromPhysicalScene();
m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
RemoveClientEvents();
// if (Animator != null)
// Animator.Close();
Animator = null;
scriptedcontrols.Clear();
ControllingClient = null;
LifecycleState = ScenePresenceState.Removed;
IsDeleted = true;
}
public void AddAttachment(SceneObjectGroup gobj)

View File

@ -39,6 +39,24 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
{
public class MeshBuildingData
{
private class vertexcomp : IEqualityComparer<Vertex>
{
public bool Equals(Vertex v1, Vertex v2)
{
if (v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z)
return true;
else
return false;
}
public int GetHashCode(Vertex v)
{
int a = v.X.GetHashCode();
int b = v.Y.GetHashCode();
int c = v.Z.GetHashCode();
return (a << 16) ^ (b << 8) ^ c;
}
}
public Dictionary<Vertex, int> m_vertices;
public List<Triangle> m_triangles;
public float m_obbXmin;
@ -49,6 +67,21 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
public float m_obbZmax;
public Vector3 m_centroid;
public int m_centroidDiv;
public MeshBuildingData()
{
vertexcomp vcomp = new vertexcomp();
m_vertices = new Dictionary<Vertex, int>(vcomp);
m_triangles = new List<Triangle>();
m_centroid = Vector3.Zero;
m_centroidDiv = 0;
m_obbXmin = float.MaxValue;
m_obbXmax = float.MinValue;
m_obbYmin = float.MaxValue;
m_obbYmax = float.MinValue;
m_obbZmin = float.MaxValue;
m_obbZmax = float.MinValue;
}
}
[Serializable()]
@ -76,50 +109,20 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
public int RefCount { get; set; }
public AMeshKey Key { get; set; }
private class vertexcomp : IEqualityComparer<Vertex>
public Mesh(bool forbuild)
{
public bool Equals(Vertex v1, Vertex v2)
{
if (v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z)
return true;
else
return false;
}
public int GetHashCode(Vertex v)
{
int a = v.X.GetHashCode();
int b = v.Y.GetHashCode();
int c = v.Z.GetHashCode();
return (a << 16) ^ (b << 8) ^ c;
}
}
public Mesh()
{
vertexcomp vcomp = new vertexcomp();
m_bdata = new MeshBuildingData();
m_bdata.m_vertices = new Dictionary<Vertex, int>(vcomp);
m_bdata.m_triangles = new List<Triangle>();
m_bdata.m_centroid = Vector3.Zero;
m_bdata.m_centroidDiv = 0;
m_bdata.m_obbXmin = float.MaxValue;
m_bdata.m_obbXmax = float.MinValue;
m_bdata.m_obbYmin = float.MaxValue;
m_bdata.m_obbYmax = float.MinValue;
m_bdata.m_obbZmin = float.MaxValue;
m_bdata.m_obbZmax = float.MinValue;
if(forbuild)
m_bdata = new MeshBuildingData();
m_obb = new Vector3(0.5f, 0.5f, 0.5f);
m_obboffset = Vector3.Zero;
}
public Mesh Scale(Vector3 scale)
{
if (m_verticesPtr == null || m_indicesPtr == null)
return null;
Mesh result = new Mesh();
Mesh result = new Mesh(false);
float x = scale.X;
float y = scale.Y;
@ -167,7 +170,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
public Mesh Clone()
{
Mesh result = new Mesh();
Mesh result = new Mesh(false);
if (m_bdata != null)
{
@ -514,8 +517,6 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
if (m_indicesPtr == IntPtr.Zero)
indexes = getIndexListAsInt();
pinMemory();
float x, y, z;
if (m_bdata.m_centroidDiv > 0)
@ -543,55 +544,53 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
m_obb = new Vector3(x, y, z);
releaseBuildingMeshData();
pinMemory();
}
public bool ToStream(Stream st)
{
if (m_indicesPtr == IntPtr.Zero || m_verticesPtr == IntPtr.Zero)
return false;
BinaryWriter bw = new BinaryWriter(st);
bool ok = true;
try
{
using(BinaryWriter bw = new BinaryWriter(st))
{
bw.Write(m_vertexCount);
bw.Write(m_indexCount);
bw.Write(m_vertexCount);
bw.Write(m_indexCount);
for (int i = 0; i < 3 * m_vertexCount; i++)
bw.Write(vertices[i]);
for (int i = 0; i < m_indexCount; i++)
bw.Write(indexes[i]);
bw.Write(m_obb.X);
bw.Write(m_obb.Y);
bw.Write(m_obb.Z);
bw.Write(m_obboffset.X);
bw.Write(m_obboffset.Y);
bw.Write(m_obboffset.Z);
for (int i = 0; i < 3 * m_vertexCount; i++)
bw.Write(vertices[i]);
for (int i = 0; i < m_indexCount; i++)
bw.Write(indexes[i]);
bw.Write(m_obb.X);
bw.Write(m_obb.Y);
bw.Write(m_obb.Z);
bw.Write(m_obboffset.X);
bw.Write(m_obboffset.Y);
bw.Write(m_obboffset.Z);
bw.Flush();
bw.Close();
}
}
catch
{
ok = false;
}
if (bw != null)
{
bw.Flush();
bw.Close();
}
return ok;
}
public static Mesh FromStream(Stream st, AMeshKey key)
{
Mesh mesh = new Mesh();
mesh.releaseBuildingMeshData();
Mesh mesh = new Mesh(false);
bool ok = true;
using(BinaryReader br = new BinaryReader(st))
try
{
try
using(BinaryReader br = new BinaryReader(st))
{
mesh.m_vertexCount = br.ReadInt32();
mesh.m_indexCount = br.ReadInt32();
@ -613,10 +612,10 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
mesh.m_obboffset.Y = br.ReadSingle();
mesh.m_obboffset.Z = br.ReadSingle();
}
catch
{
ok = false;
}
}
catch
{
ok = false;
}
if (ok)

View File

@ -182,7 +182,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
/// <returns></returns>
private static Mesh CreateSimpleBoxMesh(float minX, float maxX, float minY, float maxY, float minZ, float maxZ)
{
Mesh box = new Mesh();
Mesh box = new Mesh(true);
List<Vertex> vertices = new List<Vertex>();
// bottom
@ -357,7 +357,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
int numCoords = coords.Count;
int numFaces = faces.Count;
Mesh mesh = new Mesh();
Mesh mesh = new Mesh(true);
// Add the corresponding triangles to the mesh
for (int i = 0; i < numFaces; i++)
{
@ -1483,6 +1483,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
lock (diskLock)
{
Stream stream = null;
try
{
if (!Directory.Exists(dir))
@ -1490,8 +1491,8 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
Directory.CreateDirectory(dir);
}
using(Stream stream = File.Open(filename, FileMode.Create))
ok = mesh.ToStream(stream);
stream = File.Open(filename, FileMode.Create);
ok = mesh.ToStream(stream);
}
catch (IOException e)
{
@ -1500,6 +1501,11 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
filename, e.Message, e.StackTrace);
ok = false;
}
finally
{
if(stream != null)
stream.Dispose();
}
if (!ok && File.Exists(filename))
{

View File

@ -579,13 +579,13 @@ namespace OpenSim.Server.Handlers.Grid
if (request.ContainsKey("SCOPEID"))
UUID.TryParse(request["SCOPEID"].ToString(), out scopeID);
else
m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get neighbours");
m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get RegionFlags");
UUID regionID = UUID.Zero;
if (request.ContainsKey("REGIONID"))
UUID.TryParse(request["REGIONID"].ToString(), out regionID);
else
m_log.WarnFormat("[GRID HANDLER]: no regionID in request to get neighbours");
m_log.WarnFormat("[GRID HANDLER]: no regionID in request to get RegionFlags");
int flags = m_GridService.GetRegionFlags(scopeID, regionID);
// m_log.DebugFormat("[GRID HANDLER]: flags for region {0}: {1}", regionID, flags);

View File

@ -72,8 +72,11 @@ namespace OpenSim.Services.AuthenticationService
{
realID = UUID.Zero;
m_log.DebugFormat("[AUTH SERVICE]: Authenticating for {0}", principalID);
m_log.DebugFormat("[AUTH SERVICE]: Authenticating for {0}, user account service present: {1}", principalID, m_UserAccountService != null);
AuthenticationData data = m_Database.Get(principalID);
UserAccount user = null;
if (m_UserAccountService != null)
user = m_UserAccountService.GetUserAccount(UUID.Zero, principalID);
if (data == null || data.Data == null)
{
@ -97,7 +100,53 @@ namespace OpenSim.Services.AuthenticationService
return GetToken(principalID, lifetime);
}
m_log.DebugFormat("[AUTH SERVICE]: Authenticating FAIL for {0} ", principalID);
if (user == null)
{
m_log.DebugFormat("[PASS AUTH]: No user record for {0}", principalID);
return String.Empty;
}
int impersonateFlag = 1 << 6;
if ((user.UserFlags & impersonateFlag) == 0)
return String.Empty;
m_log.DebugFormat("[PASS AUTH]: Attempting impersonation");
List<UserAccount> accounts = m_UserAccountService.GetUserAccountsWhere(UUID.Zero, "UserLevel >= 200");
if (accounts == null || accounts.Count == 0)
return String.Empty;
foreach (UserAccount a in accounts)
{
data = m_Database.Get(a.PrincipalID);
if (data == null || data.Data == null ||
!data.Data.ContainsKey("passwordHash") ||
!data.Data.ContainsKey("passwordSalt"))
{
continue;
}
// m_log.DebugFormat("[PASS AUTH]: Trying {0}", data.PrincipalID);
hashed = Util.Md5Hash(password + ":" +
data.Data["passwordSalt"].ToString());
if (data.Data["passwordHash"].ToString() == hashed)
{
m_log.DebugFormat("[PASS AUTH]: {0} {1} impersonating {2}, proceeding with login", a.FirstName, a.LastName, principalID);
realID = a.PrincipalID;
return GetToken(principalID, lifetime);
}
// else
// {
// m_log.DebugFormat(
// "[AUTH SERVICE]: Salted hash {0} of given password did not match salted hash of {1} for PrincipalID {2}. Authentication failure.",
// hashed, data.Data["passwordHash"], data.PrincipalID);
// }
}
m_log.DebugFormat("[PASS AUTH]: Impersonation of {0} failed", principalID);
return String.Empty;
}
}

View File

@ -625,6 +625,7 @@ namespace Amib.Threading.Internal
if (!_isDisposed)
{
Cleanup();
_headWaiterEntry.Close();
}
_isDisposed = true;
}