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(); m_capsActive.Reset();
} }
~Caps()
{
m_capsActive.Dispose();
}
/// <summary> /// <summary>
/// Register a handler. This allows modules to register handlers. /// Register a handler. This allows modules to register handlers.
/// </summary> /// </summary>

View File

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

View File

@ -34,6 +34,7 @@ using System.Reflection;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Timers;
using OpenMetaverse; using OpenMetaverse;
using Nini.Config; using Nini.Config;
using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers.HttpServer;
@ -41,51 +42,147 @@ using log4net;
namespace OpenSim.Framework.Console namespace OpenSim.Framework.Console
{ {
public class ConsoleConnection
{
public int last;
public long lastLineSeen;
public bool newConnection = true;
}
// A console that uses REST interfaces // A console that uses REST interfaces
// //
public class RemoteConsole : CommandConsole public class RemoteConsole : CommandConsole
{ {
private IHttpServer m_Server = null; // Connection specific data, indexed by a session ID
private IConfigSource m_Config = null; // 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>(); // Last line of scrollback posted to this client
private ManualResetEvent m_DataEvent = new ManualResetEvent(false); public long lastLineSeen;
private List<string> m_InputData = new List<string>();
private long m_LineNumber = 0; // True if this is a new connection, e.g. has never
private Dictionary<UUID, ConsoleConnection> m_Connections = // 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>(); new Dictionary<UUID, ConsoleConnection>();
private string m_UserName = String.Empty;
private string m_Password = String.Empty; // Timer to control expiration of sessions that have been
private string m_AllowedOrigin = String.Empty; // 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) 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) public void ReadConfig(IConfigSource config)
{ {
m_Config = 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"]; IConfig netConfig = m_Config.Configs["Network"];
if (netConfig == null) if (netConfig == null)
return; return;
// Get the username and password.
m_UserName = netConfig.GetString("ConsoleUser", String.Empty); m_UserName = netConfig.GetString("ConsoleUser", String.Empty);
m_Password = netConfig.GetString("ConsolePass", 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); m_AllowedOrigin = netConfig.GetString("ConsoleAllowedOrigin", String.Empty);
} }
public void SetServer(IHttpServer server) 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; m_Server = server;
// Add our handlers
m_Server.AddHTTPHandler("/StartSession/", HandleHttpStartSession); m_Server.AddHTTPHandler("/StartSession/", HandleHttpStartSession);
m_Server.AddHTTPHandler("/CloseSession/", HandleHttpCloseSession); m_Server.AddHTTPHandler("/CloseSession/", HandleHttpCloseSession);
m_Server.AddHTTPHandler("/SessionCommand/", HandleHttpSessionCommand); m_Server.AddHTTPHandler("/SessionCommand/", HandleHttpSessionCommand);
@ -93,38 +190,84 @@ namespace OpenSim.Framework.Console
public override void Output(string text, string level) 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) 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) while (m_Scrollback.Count >= 1000)
m_Scrollback.RemoveAt(0); 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()); FireOnOutput(text.Trim());
// Also display it for debugging.
System.Console.WriteLine(text.Trim()); System.Console.WriteLine(text.Trim());
} }
public override void Output(string text) 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) public override string ReadLine(string p, bool isCommand, bool e)
{ {
// 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) if (isCommand)
Output("+++"+p); {
m_expectingInput = true;
m_expectingCommand = true;
Output(p, String.Empty, true, true, false);
m_lastPromptUsed = p;
}
else else
Output("-++"+p); {
m_expectingInput = true;
Output(p, String.Empty, true, false, false);
}
// Here is where we wait for the user to input something.
m_DataEvent.WaitOne(); m_DataEvent.WaitOne();
string cmdinput; string cmdinput;
// Check for empty input. Read input if not empty.
lock (m_InputData) lock (m_InputData)
{ {
if (m_InputData.Count == 0) if (m_InputData.Count == 0)
{ {
m_DataEvent.Reset(); m_DataEvent.Reset();
m_expectingInput = false;
m_expectingCommand = false;
return ""; 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) 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)); string[] cmd = Commands.Resolve(Parser.Parse(cmdinput));
if (cmd.Length != 0) if (cmd.Length != 0)
@ -151,18 +305,23 @@ namespace OpenSim.Framework.Console
return String.Empty; return String.Empty;
} }
} }
// Return the raw input string if not a command.
return cmdinput; return cmdinput;
} }
private Hashtable CheckOrigin(Hashtable result) // Very simplistic static access control header.
protected Hashtable CheckOrigin(Hashtable result)
{ {
if (!string.IsNullOrEmpty(m_AllowedOrigin)) if (!string.IsNullOrEmpty(m_AllowedOrigin))
result["access_control_allow_origin"] = m_AllowedOrigin; result["access_control_allow_origin"] = m_AllowedOrigin;
return result; return result;
} }
/* TODO: Figure out how PollServiceHTTPHandler can access the request headers /* TODO: Figure out how PollServiceHTTPHandler can access the request headers
* in order to use m_AllowedOrigin as a regular expression * 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)) 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>(); List<UUID> expired = new List<UUID>();
lock (m_Connections) lock (m_Connections)
{ {
// Mark the expired ones
foreach (KeyValuePair<UUID, ConsoleConnection> kvp in m_Connections) foreach (KeyValuePair<UUID, ConsoleConnection> kvp in m_Connections)
{ {
if (System.Environment.TickCount - kvp.Value.last > 500000) if (System.Environment.TickCount - kvp.Value.last > 500000)
expired.Add(kvp.Key); expired.Add(kvp.Key);
} }
// Delete them
foreach (UUID id in expired) foreach (UUID id in expired)
{ {
m_Connections.Remove(id); 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 post = DecodePostString(request["body"].ToString());
Hashtable reply = new Hashtable(); Hashtable reply = new Hashtable();
@ -208,6 +372,7 @@ namespace OpenSim.Framework.Console
reply["int_response_code"] = 401; reply["int_response_code"] = 401;
reply["content_type"] = "text/plain"; reply["content_type"] = "text/plain";
// Check user name and password
if (m_UserName == String.Empty) if (m_UserName == String.Empty)
return reply; return reply;
@ -220,22 +385,28 @@ namespace OpenSim.Framework.Console
return reply; return reply;
} }
// Set up the new console connection record
ConsoleConnection c = new ConsoleConnection(); ConsoleConnection c = new ConsoleConnection();
c.last = System.Environment.TickCount; c.last = System.Environment.TickCount;
c.lastLineSeen = 0; c.lastLineSeen = 0;
// Assign session ID
UUID sessionID = UUID.Random(); UUID sessionID = UUID.Random();
// Add connection to list.
lock (m_Connections) lock (m_Connections)
{ {
m_Connections[sessionID] = c; m_Connections[sessionID] = c;
} }
// This call is a CAP. The URL is the authentication.
string uri = "/ReadResponses/" + sessionID.ToString() + "/"; string uri = "/ReadResponses/" + sessionID.ToString() + "/";
m_Server.AddPollServiceHTTPHandler( 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(); XmlDocument xmldoc = new XmlDocument();
XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
"", ""); "", "");
@ -252,12 +423,13 @@ namespace OpenSim.Framework.Console
rootElement.AppendChild(id); rootElement.AppendChild(id);
XmlElement prompt = xmldoc.CreateElement("", "Prompt", ""); XmlElement prompt = xmldoc.CreateElement("", "Prompt", "");
prompt.AppendChild(xmldoc.CreateTextNode(DefaultPrompt)); prompt.AppendChild(xmldoc.CreateTextNode(m_lastPromptUsed));
rootElement.AppendChild(prompt); rootElement.AppendChild(prompt);
rootElement.AppendChild(MainConsole.Instance.Commands.GetXml(xmldoc)); rootElement.AppendChild(MainConsole.Instance.Commands.GetXml(xmldoc));
// Set up the response and check origin
reply["str_response_string"] = xmldoc.InnerXml; reply["str_response_string"] = xmldoc.InnerXml;
reply["int_response_code"] = 200; reply["int_response_code"] = 200;
reply["content_type"] = "text/xml"; reply["content_type"] = "text/xml";
@ -266,10 +438,9 @@ namespace OpenSim.Framework.Console
return reply; 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 post = DecodePostString(request["body"].ToString());
Hashtable reply = new Hashtable(); Hashtable reply = new Hashtable();
@ -316,10 +487,9 @@ namespace OpenSim.Framework.Console
return reply; 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 post = DecodePostString(request["body"].ToString());
Hashtable reply = new Hashtable(); Hashtable reply = new Hashtable();
@ -327,6 +497,7 @@ namespace OpenSim.Framework.Console
reply["int_response_code"] = 404; reply["int_response_code"] = 404;
reply["content_type"] = "text/plain"; reply["content_type"] = "text/plain";
// Check the ID
if (post["ID"] == null) if (post["ID"] == null)
return reply; return reply;
@ -334,21 +505,25 @@ namespace OpenSim.Framework.Console
if (!UUID.TryParse(post["ID"].ToString(), out id)) if (!UUID.TryParse(post["ID"].ToString(), out id))
return reply; return reply;
// Find the connection for that ID.
lock (m_Connections) lock (m_Connections)
{ {
if (!m_Connections.ContainsKey(id)) if (!m_Connections.ContainsKey(id))
return reply; return reply;
} }
// Empty post. Just error out.
if (post["COMMAND"] == null) if (post["COMMAND"] == null)
return reply; return reply;
// Place the input data in the buffer.
lock (m_InputData) lock (m_InputData)
{ {
m_DataEvent.Set(); m_DataEvent.Set();
m_InputData.Add(post["COMMAND"].ToString()); m_InputData.Add(post["COMMAND"].ToString());
} }
// Create the XML reply document.
XmlDocument xmldoc = new XmlDocument(); XmlDocument xmldoc = new XmlDocument();
XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
"", ""); "", "");
@ -372,7 +547,8 @@ namespace OpenSim.Framework.Console
return reply; return reply;
} }
private Hashtable DecodePostString(string data) // Decode a HTTP form post to a Hashtable
protected Hashtable DecodePostString(string data)
{ {
Hashtable result = new Hashtable(); Hashtable result = new Hashtable();
@ -396,6 +572,7 @@ namespace OpenSim.Framework.Console
return result; return result;
} }
// Close the CAP receiver for the responses for a given client.
public void CloseConnection(UUID id) public void CloseConnection(UUID id)
{ {
try 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; ConsoleConnection c = null;
@ -420,22 +599,15 @@ namespace OpenSim.Framework.Console
c = m_Connections[sessionID]; c = m_Connections[sessionID];
} }
c.last = System.Environment.TickCount; c.last = System.Environment.TickCount;
if (c.lastLineSeen < m_LineNumber) if (c.lastLineSeen < m_lineNumber)
return true; return true;
return false; return false;
} }
private void Drop(UUID RequestID, UUID sessionID) // Send all pending output to the client.
{ protected Hashtable GetEvents(UUID RequestID, UUID sessionID)
lock (m_Connections)
{
if (m_Connections.ContainsKey(sessionID))
m_Connections.Remove(sessionID);
}
}
private Hashtable GetEvents(UUID RequestID, UUID sessionID)
{ {
// Find the connection that goes with this client.
ConsoleConnection c = null; ConsoleConnection c = null;
lock (m_Connections) lock (m_Connections)
@ -444,12 +616,15 @@ namespace OpenSim.Framework.Console
return NoEvents(RequestID, UUID.Zero); return NoEvents(RequestID, UUID.Zero);
c = m_Connections[sessionID]; c = m_Connections[sessionID];
} }
// If we have nothing to send, send the no events response.
c.last = System.Environment.TickCount; c.last = System.Environment.TickCount;
if (c.lastLineSeen >= m_LineNumber) if (c.lastLineSeen >= m_lineNumber)
return NoEvents(RequestID, UUID.Zero); return NoEvents(RequestID, UUID.Zero);
Hashtable result = new Hashtable(); Hashtable result = new Hashtable();
// Create the response document.
XmlDocument xmldoc = new XmlDocument(); XmlDocument xmldoc = new XmlDocument();
XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
"", ""); "", "");
@ -458,30 +633,53 @@ namespace OpenSim.Framework.Console
XmlElement rootElement = xmldoc.CreateElement("", "ConsoleSession", XmlElement rootElement = xmldoc.CreateElement("", "ConsoleSession",
""); "");
if (c.newConnection) //if (c.newConnection)
{ //{
c.newConnection = false; // c.newConnection = false;
Output("+++" + DefaultPrompt); // Output("+++" + DefaultPrompt);
} //}
lock (m_Scrollback) lock (m_Scrollback)
{ {
long startLine = m_LineNumber - m_Scrollback.Count; long startLine = m_lineNumber - m_Scrollback.Count;
long sendStart = startLine; long sendStart = startLine;
if (sendStart < c.lastLineSeen) if (sendStart < c.lastLineSeen)
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", ""); XmlElement res = xmldoc.CreateElement("", "Line", "");
long line = i + 1; res.SetAttribute("Number", e.lineNumber.ToString());
res.SetAttribute("Number", line.ToString()); res.SetAttribute("Level", e.level);
res.AppendChild(xmldoc.CreateTextNode(m_Scrollback[(int)(i - startLine)])); // 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); rootElement.AppendChild(res);
} }
} }
c.lastLineSeen = m_LineNumber;
c.lastLineSeen = m_lineNumber;
c.newConnection = false;
xmldoc.AppendChild(rootElement); xmldoc.AppendChild(rootElement);
@ -495,7 +693,9 @@ namespace OpenSim.Framework.Console
return result; 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(); Hashtable result = new Hashtable();

View File

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

View File

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

View File

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

View File

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

View File

@ -346,12 +346,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private bool m_VelocityInterpolate = false; private bool m_VelocityInterpolate = false;
private const uint MaxTransferBytesPerPacket = 600; 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> /// <value>
/// Maintain a record of all the objects killed. This allows us to stop an update being sent from the /// 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 /// 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_scene = scene;
m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
m_entityProps = 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_killRecord = new List<uint>();
// m_attachmentsSent = new HashSet<uint>(); // m_attachmentsSent = new HashSet<uint>();
@ -594,13 +587,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OutPacket(disable, ThrottleOutPacketType.Unknown); OutPacket(disable, ThrottleOutPacketType.Unknown);
} }
// Shutdown the image manager
ImageManager.Close();
// Fire the callback for this connection closing // Fire the callback for this connection closing
if (OnConnectionClosed != null) if (OnConnectionClosed != null)
OnConnectionClosed(this); OnConnectionClosed(this);
// Flush all of the packets out of the UDP server for this client // Flush all of the packets out of the UDP server for this client
if (m_udpServer != null) if (m_udpServer != null)
m_udpServer.Flush(m_udpClient); m_udpServer.Flush(m_udpClient);
@ -616,7 +608,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Disable UDP handling for this client // Disable UDP handling for this client
m_udpClient.Shutdown(); 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)); //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
//GC.Collect(); //GC.Collect();
//m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true)); //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
@ -4095,19 +4099,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
ResendPrimUpdate(update); 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) 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>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = 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>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = 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 (maxUpdatesBytes <= 0) if (maxUpdatesBytes <= 0)
{ {
@ -4328,7 +4331,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity); ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
else else
ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId); ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId);
objectUpdateBlocks.Value.Add(ablock); objectUpdateBlocks.Add(ablock);
objectUpdates.Value.Add(update); objectUpdates.Value.Add(update);
maxUpdatesBytes -= ablock.Length; maxUpdatesBytes -= ablock.Length;
@ -4337,7 +4340,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
ObjectUpdateCompressedPacket.ObjectDataBlock ablock = ObjectUpdateCompressedPacket.ObjectDataBlock ablock =
CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags); CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags);
compressedUpdateBlocks.Value.Add(ablock); compressedUpdateBlocks.Add(ablock);
compressedUpdates.Value.Add(update); compressedUpdates.Value.Add(update);
maxUpdatesBytes -= ablock.Length; maxUpdatesBytes -= ablock.Length;
} }
@ -4348,14 +4351,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
// ALL presence updates go into a special list // ALL presence updates go into a special list
ablock = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)); ablock = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures));
terseAgentUpdateBlocks.Value.Add(ablock); terseAgentUpdateBlocks.Add(ablock);
terseAgentUpdates.Value.Add(update); terseAgentUpdates.Value.Add(update);
} }
else else
{ {
// Everything else goes here // Everything else goes here
ablock = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)); ablock = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures));
terseUpdateBlocks.Value.Add(ablock); terseUpdateBlocks.Add(ablock);
terseUpdates.Value.Add(update); terseUpdates.Value.Add(update);
} }
maxUpdatesBytes -= ablock.Length; maxUpdatesBytes -= ablock.Length;
@ -4366,74 +4369,72 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Packet Sending #region Packet Sending
// const float TIME_DILATION = 1.0f;
ushort timeDilation; ushort timeDilation;
// if(updatesThisCall > 0)
// timeDilation = Utils.FloatToUInt16(avgTimeDilation/updatesThisCall, 0.0f, 1.0f); if(m_scene == null)
// else return;
// timeDilation = ushort.MaxValue; // 1.0;
timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); 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 packet
= (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
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[terseAgentUpdateBlocks.Count];
for (int i = 0; i < blocks.Count; i++) for (int i = 0; i < terseAgentUpdateBlocks.Count; i++)
packet.ObjectData[i] = blocks[i]; packet.ObjectData[i] = terseAgentUpdateBlocks[i];
terseAgentUpdateBlocks.Clear();
OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); }); 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); ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
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 ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[objectUpdateBlocks.Count];
for (int i = 0; i < blocks.Count; i++) for (int i = 0; i < objectUpdateBlocks.Count; i++)
packet.ObjectData[i] = blocks[i]; packet.ObjectData[i] = objectUpdateBlocks[i];
objectUpdateBlocks.Clear();
OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); }); 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); ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
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 ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count]; packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[compressedUpdateBlocks.Count];
for (int i = 0; i < blocks.Count; i++) for (int i = 0; i < compressedUpdateBlocks.Count; i++)
packet.ObjectData[i] = blocks[i]; packet.ObjectData[i] = compressedUpdateBlocks[i];
compressedUpdateBlocks.Clear();
OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); }); 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 packet
= (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
PacketType.ImprovedTerseObjectUpdate); PacketType.ImprovedTerseObjectUpdate);
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[terseUpdateBlocks.Count];
for (int i = 0; i < blocks.Count; i++) for (int i = 0; i < terseUpdateBlocks.Count; i++)
packet.ObjectData[i] = blocks[i]; packet.ObjectData[i] = terseUpdateBlocks[i];
terseUpdateBlocks.Clear();
OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); 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) void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
{ {
if(m_scene == null)
return;
if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
{ {
int maxUpdateBytes = m_udpClient.GetCatBytesCanSend(ThrottleOutPacketType.Task, 30); 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)); 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) private void ProcessEntityPropertyRequests(int maxUpdateBytes)
{ {
OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>> objectFamilyBlocks = // OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> familyUpdates =
new OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>>(); // new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks = // OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates =
new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>(); // new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> familyUpdates =
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; EntityUpdate iupdate;
Int32 timeinqueue; // this is just debugging code & can be dropped later 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; SceneObjectPart sop = (SceneObjectPart)update.Entity;
ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags); ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
objectFamilyBlocks.Value.Add(objPropDB); objectFamilyBlocks.Add(objPropDB);
familyUpdates.Value.Add(update); // familyUpdates.Value.Add(update);
maxUpdateBytes -= objPropDB.Length; maxUpdateBytes -= objPropDB.Length;
} }
} }
@ -4873,23 +4876,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
SceneObjectPart sop = (SceneObjectPart)update.Entity; SceneObjectPart sop = (SceneObjectPart)update.Entity;
needPhysics.Add(sop); needPhysics.Add(sop);
ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop); ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
objectPropertiesBlocks.Value.Add(objPropDB); objectPropertiesBlocks.Add(objPropDB);
propertyUpdates.Value.Add(update); // propertyUpdates.Value.Add(update);
maxUpdateBytes -= objPropDB.Length; 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); ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count]; packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[objectPropertiesBlocks.Count];
for (int i = 0; i < blocks.Count; i++) for (int i = 0; i < objectPropertiesBlocks.Count; i++)
packet.ObjectData[i] = blocks[i]; packet.ObjectData[i] = objectPropertiesBlocks[i];
objectPropertiesBlocks.Clear();
packet.Header.Zerocoded = true; packet.Header.Zerocoded = true;
// Pass in the delegate so that if this packet needs to be resent, we send the current properties // 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, //OutPacket(packet, ThrottleOutPacketType.Task, true,
// delegate(OutgoingPacket oPacket) // delegate(OutgoingPacket oPacket)
// { // {
// ResendPropertyUpdates(updates, oPacket); // ResendPropertyUpdates(propertyUpdates.Value, oPacket);
// }); // });
OutPacket(packet, ThrottleOutPacketType.Task, true); OutPacket(packet, ThrottleOutPacketType.Task, true);
@ -4909,23 +4911,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Int32 fpcnt = 0; // Int32 fpcnt = 0;
// Int32 fbcnt = 0; // Int32 fbcnt = 0;
if (objectFamilyBlocks.IsValueCreated) if (objectFamilyBlocks.Count > 0)
{ {
List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value;
// 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 < objectFamilyBlocks.Count; i++)
{ {
ObjectPropertiesFamilyPacket packet = ObjectPropertiesFamilyPacket packet =
(ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
packet.ObjectData = blocks[i]; packet.ObjectData = objectFamilyBlocks[i];
packet.Header.Zerocoded = true; packet.Header.Zerocoded = true;
// Pass in the delegate so that if this packet needs to be resent, we send the current properties // 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 // of the object rather than the properties when the packet was created
List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); // List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
updates.Add(familyUpdates.Value[i]); // updates.Add(familyUpdates.Value[i]);
// HACK : Remove intelligent resending until it's fixed in core // HACK : Remove intelligent resending until it's fixed in core
//OutPacket(packet, ThrottleOutPacketType.Task, true, //OutPacket(packet, ThrottleOutPacketType.Task, true,
// delegate(OutgoingPacket oPacket) // delegate(OutgoingPacket oPacket)
@ -4937,6 +4937,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// fpcnt++; // fpcnt++;
// fbcnt++; // fbcnt++;
} }
objectFamilyBlocks.Clear();
} }
if(needPhysics.Count > 0) if(needPhysics.Count > 0)
@ -4962,6 +4963,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
eq.Enqueue(BuildEvent("ObjectPhysicsProperties", llsdBody),AgentId); eq.Enqueue(BuildEvent("ObjectPhysicsProperties", llsdBody),AgentId);
} }
needPhysics.Clear();
} }
// m_log.WarnFormat("[PACKETCOUNTS] queued {0} property packets with {1} blocks",ppcnt,pbcnt); // m_log.WarnFormat("[PACKETCOUNTS] queued {0} property packets with {1} blocks",ppcnt,pbcnt);
@ -6251,9 +6253,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return false; return false;
} }
uint seq = packet.Header.Sequence;
TotalAgentUpdates++; TotalAgentUpdates++;
// dont let ignored updates pollute this throttles // 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() // throttle reset is done at MoveAgentIntoRegion()
// called by scenepresence on completemovement // called by scenepresence on completemovement
@ -6261,6 +6266,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return true; return true;
} }
m_thisAgentUpdateArgs.lastpacketSequence = seq;
bool movement = CheckAgentMovementUpdateSignificance(x); bool movement = CheckAgentMovementUpdateSignificance(x);
bool camera = CheckAgentCameraUpdateSignificance(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> /// <summary>Circuit code that this client is connected on</summary>
public readonly uint CircuitCode; public readonly uint CircuitCode;
/// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary> /// <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> /// <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> /// <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> /// <summary>Current packet sequence number</summary>
public int CurrentSequence; public int CurrentSequence;
@ -170,7 +170,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private double m_nextOnQueueEmpty = 0; private double m_nextOnQueueEmpty = 0;
/// <summary>Throttle bucket for this agent's connection</summary> /// <summary>Throttle bucket for this agent's connection</summary>
private readonly AdaptiveTokenBucket m_throttleClient; private AdaptiveTokenBucket m_throttleClient;
public AdaptiveTokenBucket FlowThrottle public AdaptiveTokenBucket FlowThrottle
{ {
get { return m_throttleClient; } get { return m_throttleClient; }
@ -179,10 +179,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary>Throttle buckets for each packet category</summary> /// <summary>Throttle buckets for each packet category</summary>
private readonly TokenBucket[] m_throttleCategories; private readonly TokenBucket[] m_throttleCategories;
/// <summary>Outgoing queues for throttled packets</summary> /// <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 /// <summary>A container that can hold one packet for each outbox, used to store
/// dequeued packets that are being held for throttling</summary> /// 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> /// <summary>A reference to the LLUDPServer that is managing this client</summary>
private readonly LLUDPServer m_udpServer; private readonly LLUDPServer m_udpServer;
@ -288,13 +288,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
{ {
m_packetOutboxes[i].Clear(); m_packetOutboxes[i].Clear();
m_throttleCategories[i] = null;
m_nextPackets[i] = null; m_nextPackets[i] = null;
} }
// pull the throttle out of the scene throttle // pull the throttle out of the scene throttle
m_throttleClient.Parent.UnregisterRequest(m_throttleClient); m_throttleClient.Parent.UnregisterRequest(m_throttleClient);
m_throttleClient = null;
OnPacketStats = null; OnPacketStats = null;
OnQueueEmpty = null; OnQueueEmpty = null;
PendingAcks.Clear();
NeedAcks.Clear();
NeedAcks = null;
PendingAcks = null;
m_nextPackets = null;
m_packetOutboxes = null;
} }
/// <summary> /// <summary>

View File

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

View File

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

View File

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

View File

@ -36,6 +36,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
{ {
public class UserAccountCache : IUserAccountCacheModule 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_EXPIRATION_SECONDS = 3600.0; // 1 hour!
private const double CACHE_NULL_EXPIRATION_SECONDS = 600; // 10minutes private const double CACHE_NULL_EXPIRATION_SECONDS = 600; // 10minutes
@ -60,21 +61,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
{ {
if (account == null) if (account == null)
m_UUIDCache.AddOrUpdate(userID, null, CACHE_NULL_EXPIRATION_SECONDS); m_UUIDCache.AddOrUpdate(userID, null, CACHE_NULL_EXPIRATION_SECONDS);
else else if(account.LocalToGrid)
{ {
m_UUIDCache.AddOrUpdate(userID, account, CACHE_EXPIRATION_SECONDS); m_UUIDCache.AddOrUpdate(userID, account, CACHE_EXPIRATION_SECONDS);
m_NameCache.AddOrUpdate(account.Name, account.PrincipalID, 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); //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) public UserAccount Get(UUID userID, out bool inCache)
{ {
@ -114,6 +114,25 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
return null; 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) public void Remove(string name)
{ {
lock(accessLock) lock(accessLock)

View File

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

View File

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

View File

@ -1104,7 +1104,7 @@ namespace OpenSim.Region.Framework.Scenes
AdjustKnownSeeds(); AdjustKnownSeeds();
RegisterToEvents(); RegisterToClientEvents();
SetDirectionVectors(); SetDirectionVectors();
Appearance = appearance; Appearance = appearance;
@ -1171,7 +1171,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
public void RegisterToEvents() public void RegisterToClientEvents()
{ {
ControllingClient.OnCompleteMovementToRegion += CompleteMovement; ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
ControllingClient.OnAgentUpdate += HandleAgentUpdate; ControllingClient.OnAgentUpdate += HandleAgentUpdate;
@ -1190,6 +1190,22 @@ namespace OpenSim.Region.Framework.Scenes
// ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); // 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() private void SetDirectionVectors()
{ {
Dir_Vectors[0] = new Vector3(AgentControlNormalVel,0,0); //FORWARD Dir_Vectors[0] = new Vector3(AgentControlNormalVel,0,0); //FORWARD
@ -2318,7 +2334,7 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 tocam = CameraPosition - posAdjusted; Vector3 tocam = CameraPosition - posAdjusted;
float distTocamlen = tocam.LengthSquared(); float distTocamlen = tocam.LengthSquared();
if (distTocamlen > 0.08f && distTocamlen < 400) if (distTocamlen > 0.01f && distTocamlen < 400)
{ {
distTocamlen = (float)Math.Sqrt(distTocamlen); distTocamlen = (float)Math.Sqrt(distTocamlen);
tocam *= (1.0f / distTocamlen); tocam *= (1.0f / distTocamlen);
@ -4378,16 +4394,12 @@ namespace OpenSim.Region.Framework.Scenes
m_log.DebugFormat( m_log.DebugFormat(
"[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}", "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}",
knownRegions.Count, Scene.RegionInfo.RegionName); knownRegions.Count, Scene.RegionInfo.RegionName);
//DumpKnownRegions();
Util.RegionHandleToRegionLoc(newRegionHandle, out newRegionX, out newRegionY); Util.RegionHandleToRegionLoc(newRegionHandle, out newRegionX, out newRegionY);
uint x, y; uint x, y;
spRegionSizeInfo regInfo; spRegionSizeInfo regInfo;
// this should not be here
IEventQueue eventQueue = Scene.RequestModuleInterface<IEventQueue>();
foreach (ulong handle in knownRegions) foreach (ulong handle in knownRegions)
{ {
// Don't close the agent on this region yet // 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); Util.RegionHandleToRegionLoc(handle, out x, out y);
if (m_knownChildRegionsSizeInfo.TryGetValue(handle, out regInfo)) 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, if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY,
regInfo.sizeX, regInfo.sizeY, newRegionSizeX, newRegionSizeY)) regInfo.sizeX, regInfo.sizeY, newRegionSizeX, newRegionSizeY))
{ {
byebyeRegions.Add(handle); byebyeRegions.Add(handle);
// this should not be here
// if(eventQueue != null)
/// eventQueue.DisableSimulator(handle,UUID);
} }
} }
else 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 #endregion
/// <summary> /// <summary>
@ -5000,12 +5032,16 @@ namespace OpenSim.Region.Framework.Scenes
RemoveFromPhysicalScene(); RemoveFromPhysicalScene();
m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
RemoveClientEvents();
// if (Animator != null) // if (Animator != null)
// Animator.Close(); // Animator.Close();
Animator = null; Animator = null;
scriptedcontrols.Clear();
ControllingClient = null;
LifecycleState = ScenePresenceState.Removed; LifecycleState = ScenePresenceState.Removed;
IsDeleted = true;
} }
public void AddAttachment(SceneObjectGroup gobj) public void AddAttachment(SceneObjectGroup gobj)

View File

@ -39,6 +39,24 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
{ {
public class MeshBuildingData 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 Dictionary<Vertex, int> m_vertices;
public List<Triangle> m_triangles; public List<Triangle> m_triangles;
public float m_obbXmin; public float m_obbXmin;
@ -49,6 +67,21 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
public float m_obbZmax; public float m_obbZmax;
public Vector3 m_centroid; public Vector3 m_centroid;
public int m_centroidDiv; 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()] [Serializable()]
@ -76,50 +109,20 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
public int RefCount { get; set; } public int RefCount { get; set; }
public AMeshKey Key { get; set; } public AMeshKey Key { get; set; }
private class vertexcomp : IEqualityComparer<Vertex> public Mesh(bool forbuild)
{ {
public bool Equals(Vertex v1, Vertex v2) if(forbuild)
{
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 = 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;
m_obb = new Vector3(0.5f, 0.5f, 0.5f); m_obb = new Vector3(0.5f, 0.5f, 0.5f);
m_obboffset = Vector3.Zero; m_obboffset = Vector3.Zero;
} }
public Mesh Scale(Vector3 scale) public Mesh Scale(Vector3 scale)
{ {
if (m_verticesPtr == null || m_indicesPtr == null) if (m_verticesPtr == null || m_indicesPtr == null)
return null; return null;
Mesh result = new Mesh(); Mesh result = new Mesh(false);
float x = scale.X; float x = scale.X;
float y = scale.Y; float y = scale.Y;
@ -167,7 +170,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
public Mesh Clone() public Mesh Clone()
{ {
Mesh result = new Mesh(); Mesh result = new Mesh(false);
if (m_bdata != null) if (m_bdata != null)
{ {
@ -514,8 +517,6 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
if (m_indicesPtr == IntPtr.Zero) if (m_indicesPtr == IntPtr.Zero)
indexes = getIndexListAsInt(); indexes = getIndexListAsInt();
pinMemory();
float x, y, z; float x, y, z;
if (m_bdata.m_centroidDiv > 0) if (m_bdata.m_centroidDiv > 0)
@ -543,18 +544,20 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
m_obb = new Vector3(x, y, z); m_obb = new Vector3(x, y, z);
releaseBuildingMeshData(); releaseBuildingMeshData();
pinMemory();
} }
public bool ToStream(Stream st) public bool ToStream(Stream st)
{ {
if (m_indicesPtr == IntPtr.Zero || m_verticesPtr == IntPtr.Zero) if (m_indicesPtr == IntPtr.Zero || m_verticesPtr == IntPtr.Zero)
return false; return false;
BinaryWriter bw = new BinaryWriter(st);
bool ok = true; bool ok = true;
try try
{ {
using(BinaryWriter bw = new BinaryWriter(st))
{
bw.Write(m_vertexCount); bw.Write(m_vertexCount);
bw.Write(m_indexCount); bw.Write(m_indexCount);
@ -568,30 +571,26 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
bw.Write(m_obboffset.X); bw.Write(m_obboffset.X);
bw.Write(m_obboffset.Y); bw.Write(m_obboffset.Y);
bw.Write(m_obboffset.Z); bw.Write(m_obboffset.Z);
bw.Flush();
bw.Close();
}
} }
catch catch
{ {
ok = false; ok = false;
} }
if (bw != null)
{
bw.Flush();
bw.Close();
}
return ok; return ok;
} }
public static Mesh FromStream(Stream st, AMeshKey key) public static Mesh FromStream(Stream st, AMeshKey key)
{ {
Mesh mesh = new Mesh(); Mesh mesh = new Mesh(false);
mesh.releaseBuildingMeshData();
bool ok = true; bool ok = true;
using(BinaryReader br = new BinaryReader(st))
{
try try
{
using(BinaryReader br = new BinaryReader(st))
{ {
mesh.m_vertexCount = br.ReadInt32(); mesh.m_vertexCount = br.ReadInt32();
mesh.m_indexCount = br.ReadInt32(); mesh.m_indexCount = br.ReadInt32();
@ -613,11 +612,11 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
mesh.m_obboffset.Y = br.ReadSingle(); mesh.m_obboffset.Y = br.ReadSingle();
mesh.m_obboffset.Z = br.ReadSingle(); mesh.m_obboffset.Z = br.ReadSingle();
} }
}
catch catch
{ {
ok = false; ok = false;
} }
}
if (ok) if (ok)
{ {

View File

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

View File

@ -579,13 +579,13 @@ namespace OpenSim.Server.Handlers.Grid
if (request.ContainsKey("SCOPEID")) if (request.ContainsKey("SCOPEID"))
UUID.TryParse(request["SCOPEID"].ToString(), out scopeID); UUID.TryParse(request["SCOPEID"].ToString(), out scopeID);
else 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; UUID regionID = UUID.Zero;
if (request.ContainsKey("REGIONID")) if (request.ContainsKey("REGIONID"))
UUID.TryParse(request["REGIONID"].ToString(), out regionID); UUID.TryParse(request["REGIONID"].ToString(), out regionID);
else 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); int flags = m_GridService.GetRegionFlags(scopeID, regionID);
// m_log.DebugFormat("[GRID HANDLER]: flags for region {0}: {1}", regionID, flags); // 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; 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); 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) if (data == null || data.Data == null)
{ {
@ -97,7 +100,53 @@ namespace OpenSim.Services.AuthenticationService
return GetToken(principalID, lifetime); 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; return String.Empty;
} }
} }

View File

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