merge conflits
commit
7cb3d583a9
|
@ -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>
|
||||
|
|
|
@ -82,6 +82,7 @@ namespace OpenSim.Framework
|
|||
public Vector3 ClientAgentPosition;
|
||||
public bool UseClientAgentPosition;
|
||||
public bool NeedsCameraCollision;
|
||||
public uint lastpacketSequence;
|
||||
|
||||
public AgentUpdateArgs()
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -26,8 +26,10 @@
|
|||
*/
|
||||
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenMetaverse;
|
||||
|
||||
public interface IUserAccountCacheModule
|
||||
{
|
||||
void Remove(string name);
|
||||
void Remove(UUID id);
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -625,6 +625,7 @@ namespace Amib.Threading.Internal
|
|||
if (!_isDisposed)
|
||||
{
|
||||
Cleanup();
|
||||
_headWaiterEntry.Close();
|
||||
}
|
||||
_isDisposed = true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue