merge conflits
commit
7cb3d583a9
|
@ -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>
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,90 +42,232 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
if (isCommand)
|
// Output the prompt an prepare to wait. This
|
||||||
Output("+++"+p);
|
// is called on a dedicated console thread and
|
||||||
else
|
// needs to be synchronous. Old architecture but
|
||||||
Output("-++"+p);
|
// 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();
|
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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -1062,11 +1062,10 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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,14 +288,22 @@ 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>
|
||||||
/// Gets information about this client connection
|
/// Gets information about this client connection
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
{
|
m_bdata = new MeshBuildingData();
|
||||||
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;
|
|
||||||
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,55 +544,53 @@ 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_indexCount);
|
||||||
|
|
||||||
bw.Write(m_vertexCount);
|
for (int i = 0; i < 3 * m_vertexCount; i++)
|
||||||
bw.Write(m_indexCount);
|
bw.Write(vertices[i]);
|
||||||
|
for (int i = 0; i < m_indexCount; i++)
|
||||||
for (int i = 0; i < 3 * m_vertexCount; i++)
|
bw.Write(indexes[i]);
|
||||||
bw.Write(vertices[i]);
|
bw.Write(m_obb.X);
|
||||||
for (int i = 0; i < m_indexCount; i++)
|
bw.Write(m_obb.Y);
|
||||||
bw.Write(indexes[i]);
|
bw.Write(m_obb.Z);
|
||||||
bw.Write(m_obb.X);
|
bw.Write(m_obboffset.X);
|
||||||
bw.Write(m_obb.Y);
|
bw.Write(m_obboffset.Y);
|
||||||
bw.Write(m_obb.Z);
|
bw.Write(m_obboffset.Z);
|
||||||
bw.Write(m_obboffset.X);
|
bw.Flush();
|
||||||
bw.Write(m_obboffset.Y);
|
bw.Close();
|
||||||
bw.Write(m_obboffset.Z);
|
}
|
||||||
}
|
}
|
||||||
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,10 +612,10 @@ 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)
|
||||||
|
|
|
@ -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,8 +1491,8 @@ 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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -625,6 +625,7 @@ namespace Amib.Threading.Internal
|
||||||
if (!_isDisposed)
|
if (!_isDisposed)
|
||||||
{
|
{
|
||||||
Cleanup();
|
Cleanup();
|
||||||
|
_headWaiterEntry.Close();
|
||||||
}
|
}
|
||||||
_isDisposed = true;
|
_isDisposed = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue