Merge branch 'master' into careminster

Conflicts:
	OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
	OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
avinationmerge
Melanie 2012-06-09 16:28:22 +01:00
commit 8c91e761c8
9 changed files with 151 additions and 159 deletions

View File

@ -34,14 +34,12 @@ namespace OpenSim.Framework.Statistics
{ {
private static AssetStatsCollector assetStats; private static AssetStatsCollector assetStats;
private static UserStatsCollector userStats; private static UserStatsCollector userStats;
private static SimExtraStatsCollector simExtraStats; private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
public static AssetStatsCollector AssetStats { get { return assetStats; } } public static AssetStatsCollector AssetStats { get { return assetStats; } }
public static UserStatsCollector UserStats { get { return userStats; } } public static UserStatsCollector UserStats { get { return userStats; } }
public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
private StatsManager() {}
/// <summary> /// <summary>
/// Start collecting statistics related to assets. /// Start collecting statistics related to assets.
/// Should only be called once. /// Should only be called once.
@ -63,16 +61,5 @@ namespace OpenSim.Framework.Statistics
return userStats; return userStats;
} }
/// <summary>
/// Start collecting extra sim statistics apart from those collected for the client.
/// Should only be called once.
/// </summary>
public static SimExtraStatsCollector StartCollectingSimExtraStats()
{
simExtraStats = new SimExtraStatsCollector();
return simExtraStats;
}
} }
} }

View File

@ -232,7 +232,7 @@ namespace OpenSim
base.StartupSpecific(); base.StartupSpecific();
m_stats = StatsManager.StartCollectingSimExtraStats(); m_stats = StatsManager.SimExtraStats;
// Create a ModuleLoader instance // Create a ModuleLoader instance
m_moduleLoader = new ModuleLoader(m_config.Source); m_moduleLoader = new ModuleLoader(m_config.Source);

View File

@ -39,7 +39,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public sealed class IncomingPacket public sealed class IncomingPacket
{ {
/// <summary>Client this packet came from</summary> /// <summary>Client this packet came from</summary>
public LLUDPClient Client; public LLClientView Client;
/// <summary>Packet data that has been received</summary> /// <summary>Packet data that has been received</summary>
public Packet Packet; public Packet Packet;
@ -48,7 +49,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// </summary> /// </summary>
/// <param name="client">Reference to the client this packet came from</param> /// <param name="client">Reference to the client this packet came from</param>
/// <param name="packet">Packet data</param> /// <param name="packet">Packet data</param>
public IncomingPacket(LLUDPClient client, Packet packet) public IncomingPacket(LLClientView client, Packet packet)
{ {
Client = client; Client = client;
Packet = packet; Packet = packet;

View File

@ -147,11 +147,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private int m_elapsed500MSOutgoingPacketHandler; private int m_elapsed500MSOutgoingPacketHandler;
/// <summary>Flag to signal when clients should check for resends</summary> /// <summary>Flag to signal when clients should check for resends</summary>
private bool m_resendUnacked; protected bool m_resendUnacked;
/// <summary>Flag to signal when clients should send ACKs</summary> /// <summary>Flag to signal when clients should send ACKs</summary>
private bool m_sendAcks; protected bool m_sendAcks;
/// <summary>Flag to signal when clients should send pings</summary> /// <summary>Flag to signal when clients should send pings</summary>
private bool m_sendPing; protected bool m_sendPing;
private int m_defaultRTO = 0; private int m_defaultRTO = 0;
private int m_maxRTO = 0; private int m_maxRTO = 0;
@ -537,8 +539,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null); SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null);
} }
public void HandleUnacked(LLUDPClient udpClient) public void HandleUnacked(LLClientView client)
{ {
LLUDPClient udpClient = client.UDPClient;
if (!udpClient.IsConnected) if (!udpClient.IsConnected)
return; return;
@ -551,12 +555,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (udpClient.IsPaused) if (udpClient.IsPaused)
timeoutTicks = m_pausedAckTimeout; timeoutTicks = m_pausedAckTimeout;
if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks) if (!client.IsLoggingOut &&
(Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks)
{ {
m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID); m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
RemoveClient(client);
RemoveClient(udpClient);
return; return;
} }
@ -879,7 +884,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion Ping Check Handling #endregion Ping Check Handling
// Inbox insertion // Inbox insertion
packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
} }
#region BinaryStats #region BinaryStats
@ -1105,21 +1110,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return client; return client;
} }
private void RemoveClient(LLUDPClient udpClient) private void RemoveClient(IClientAPI client)
{ {
// Remove this client from the scene client.IsLoggingOut = true;
IClientAPI client; Util.FireAndForget(o => client.Close());
if (m_scene.TryGetClient(udpClient.AgentID, out client))
{
client.IsLoggingOut = true;
client.Close(false);
}
else
{
m_log.WarnFormat(
"[LLUDPSERVER]: Tried to remove client with id {0} but not such client in {1}",
udpClient.AgentID, m_scene.RegionInfo.RegionName);
}
} }
private void IncomingPacketHandler() private void IncomingPacketHandler()
@ -1246,7 +1240,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Watchdog.RemoveThread(); Watchdog.RemoveThread();
} }
private void ClientOutgoingPacketHandler(IClientAPI client) protected void ClientOutgoingPacketHandler(IClientAPI client)
{ {
m_currentOutgoingClient = client; m_currentOutgoingClient = client;
@ -1254,12 +1248,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
if (client is LLClientView) if (client is LLClientView)
{ {
LLUDPClient udpClient = ((LLClientView)client).UDPClient; LLClientView llClient = (LLClientView)client;
LLUDPClient udpClient = llClient.UDPClient;
if (udpClient.IsConnected) if (udpClient.IsConnected)
{ {
if (m_resendUnacked) if (m_resendUnacked)
HandleUnacked(udpClient); HandleUnacked(llClient);
if (m_sendAcks) if (m_sendAcks)
SendAcks(udpClient); SendAcks(udpClient);
@ -1308,7 +1303,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
if (client is LLClientView) if (client is LLClientView)
{ {
LLUDPClient udpClient = ((LLClientView)client).UDPClient; LLClientView llClient = (LLClientView)client;
LLUDPClient udpClient = llClient.UDPClient;
if (udpClient.IsConnected) if (udpClient.IsConnected)
{ {
@ -1317,7 +1313,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
nticksUnack++; nticksUnack++;
watch2.Start(); watch2.Start();
HandleUnacked(udpClient); HandleUnacked(llClient);
watch2.Stop(); watch2.Stop();
avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack); avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
@ -1388,22 +1384,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion #endregion
private void ProcessInPacket(object state) private void ProcessInPacket(IncomingPacket incomingPacket)
{ {
IncomingPacket incomingPacket = (IncomingPacket)state;
Packet packet = incomingPacket.Packet; Packet packet = incomingPacket.Packet;
LLUDPClient udpClient = incomingPacket.Client; LLClientView client = incomingPacket.Client;
IClientAPI client;
// Sanity check if (client.IsActive)
if (packet == null || udpClient == null)
{
m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", UDPClient=\"{1}\"",
packet, udpClient);
}
// Make sure this client is still alive
if (m_scene.TryGetClient(udpClient.AgentID, out client))
{ {
m_currentIncomingClient = client; m_currentIncomingClient = client;
@ -1421,8 +1407,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
catch (Exception e) catch (Exception e)
{ {
// Don't let a failure in an individual client thread crash the whole sim. // Don't let a failure in an individual client thread crash the whole sim.
m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type); m_log.Error(
m_log.Error(e.Message, e); string.Format(
"[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw ",
client.Name, packet.Type),
e);
} }
finally finally
{ {
@ -1433,15 +1422,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
m_log.DebugFormat( m_log.DebugFormat(
"[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
packet.Type, udpClient.AgentID, m_scene.RegionInfo.RegionName); packet.Type, client.Name, m_scene.RegionInfo.RegionName);
} }
} }
protected void LogoutHandler(IClientAPI client) protected void LogoutHandler(IClientAPI client)
{ {
client.SendLogoutPacket(); client.SendLogoutPacket();
if (client.IsActive) if (!client.IsLoggingOut)
RemoveClient(((LLClientView)client).UDPClient); RemoveClient(client);
} }
} }
} }

View File

@ -45,6 +45,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
[TestFixture] [TestFixture]
public class BasicCircuitTests public class BasicCircuitTests
{ {
private Scene m_scene;
private TestLLUDPServer m_udpServer;
[TestFixtureSetUp] [TestFixtureSetUp]
public void FixtureInit() public void FixtureInit()
{ {
@ -61,83 +64,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
} }
// /// <summary> [SetUp]
// /// Add a client for testing public void SetUp()
// /// </summary> {
// /// <param name="scene"></param> m_scene = new SceneHelpers().SetupScene();
// /// <param name="testLLUDPServer"></param> }
// /// <param name="testPacketServer"></param>
// /// <param name="acm">Agent circuit manager used in setting up the stack</param>
// protected void SetupStack(
// IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
// out AgentCircuitManager acm)
// {
// IConfigSource configSource = new IniConfigSource();
// ClientStackUserSettings userSettings = new ClientStackUserSettings();
// testLLUDPServer = new TestLLUDPServer();
// acm = new AgentCircuitManager();
//
// uint port = 666;
// testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
// testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
// testLLUDPServer.LocalScene = scene;
// }
// /// <summary>
// /// Set up a client for tests which aren't concerned with this process itself and where only one client is being
// /// tested
// /// </summary>
// /// <param name="circuitCode"></param>
// /// <param name="epSender"></param>
// /// <param name="testLLUDPServer"></param>
// /// <param name="acm"></param>
// protected void AddClient(
// uint circuitCode, EndPoint epSender, TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
// {
// UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
// UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
//
// AddClient(circuitCode, epSender, myAgentUuid, mySessionUuid, testLLUDPServer, acm);
// }
// /// <summary>
// /// Set up a client for tests which aren't concerned with this process itself
// /// </summary>
// /// <param name="circuitCode"></param>
// /// <param name="epSender"></param>
// /// <param name="agentId"></param>
// /// <param name="sessionId"></param>
// /// <param name="testLLUDPServer"></param>
// /// <param name="acm"></param>
// protected void AddClient(
// uint circuitCode, EndPoint epSender, UUID agentId, UUID sessionId,
// TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
// {
// AgentCircuitData acd = new AgentCircuitData();
// acd.AgentID = agentId;
// acd.SessionID = sessionId;
//
// UseCircuitCodePacket uccp = new UseCircuitCodePacket();
//
// UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
// = new UseCircuitCodePacket.CircuitCodeBlock();
// uccpCcBlock.Code = circuitCode;
// uccpCcBlock.ID = agentId;
// uccpCcBlock.SessionID = sessionId;
// uccp.CircuitCode = uccpCcBlock;
//
// acm.AddNewCircuit(circuitCode, acd);
//
// testLLUDPServer.LoadReceive(uccp, epSender);
// testLLUDPServer.ReceiveData(null);
// }
/// <summary> /// <summary>
/// Build an object name packet for test purposes /// Build an object name packet for test purposes
/// </summary> /// </summary>
/// <param name="objectLocalId"></param> /// <param name="objectLocalId"></param>
/// <param name="objectName"></param> /// <param name="objectName"></param>
protected ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName) private ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName)
{ {
ObjectNamePacket onp = new ObjectNamePacket(); ObjectNamePacket onp = new ObjectNamePacket();
ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock(); ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock();
@ -148,29 +86,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
return onp; return onp;
} }
/// <summary>
/// Test adding a client to the stack
/// </summary>
[Test]
public void TestAddClient()
{
TestHelpers.InMethod();
// XmlConfigurator.Configure();
TestScene scene = new SceneHelpers().SetupScene(); private void AddUdpServer()
uint myCircuitCode = 123456; {
AddUdpServer(new IniConfigSource());
}
private void AddUdpServer(IniConfigSource configSource)
{
uint port = 0;
AgentCircuitManager acm = m_scene.AuthenticateHandler;
m_udpServer = new TestLLUDPServer(IPAddress.Any, ref port, 0, false, configSource, acm);
m_udpServer.AddScene(m_scene);
}
/// <summary>
/// Used by tests that aren't testing this stage.
/// </summary>
private ScenePresence AddClient()
{
UUID myAgentUuid = TestHelpers.ParseTail(0x1); UUID myAgentUuid = TestHelpers.ParseTail(0x1);
UUID mySessionUuid = TestHelpers.ParseTail(0x2); UUID mySessionUuid = TestHelpers.ParseTail(0x2);
uint myCircuitCode = 123456;
IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999); IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
uint port = 0;
AgentCircuitManager acm = scene.AuthenticateHandler;
TestLLUDPServer llUdpServer
= new TestLLUDPServer(IPAddress.Any, ref port, 0, false, new IniConfigSource(), acm);
llUdpServer.AddScene(scene);
UseCircuitCodePacket uccp = new UseCircuitCodePacket(); UseCircuitCodePacket uccp = new UseCircuitCodePacket();
UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
@ -185,26 +125,67 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor. upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor.
Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length); Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);
llUdpServer.PacketReceived(upb); AgentCircuitData acd = new AgentCircuitData();
acd.AgentID = myAgentUuid;
acd.SessionID = mySessionUuid;
m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);
m_udpServer.PacketReceived(upb);
return m_scene.GetScenePresence(myAgentUuid);
}
/// <summary>
/// Test adding a client to the stack
/// </summary>
[Test]
public void TestAddClient()
{
TestHelpers.InMethod();
// XmlConfigurator.Configure();
AddUdpServer();
UUID myAgentUuid = TestHelpers.ParseTail(0x1);
UUID mySessionUuid = TestHelpers.ParseTail(0x2);
uint myCircuitCode = 123456;
IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
UseCircuitCodePacket uccp = new UseCircuitCodePacket();
UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
= new UseCircuitCodePacket.CircuitCodeBlock();
uccpCcBlock.Code = myCircuitCode;
uccpCcBlock.ID = myAgentUuid;
uccpCcBlock.SessionID = mySessionUuid;
uccp.CircuitCode = uccpCcBlock;
byte[] uccpBytes = uccp.ToBytes();
UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length);
upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor.
Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);
m_udpServer.PacketReceived(upb);
// Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet
Assert.That(scene.GetScenePresence(myAgentUuid), Is.Null); Assert.That(m_scene.GetScenePresence(myAgentUuid), Is.Null);
AgentCircuitData acd = new AgentCircuitData(); AgentCircuitData acd = new AgentCircuitData();
acd.AgentID = myAgentUuid; acd.AgentID = myAgentUuid;
acd.SessionID = mySessionUuid; acd.SessionID = mySessionUuid;
acm.AddNewCircuit(myCircuitCode, acd); m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);
llUdpServer.PacketReceived(upb); m_udpServer.PacketReceived(upb);
// Should succeed now // Should succeed now
ScenePresence sp = scene.GetScenePresence(myAgentUuid); ScenePresence sp = m_scene.GetScenePresence(myAgentUuid);
Assert.That(sp.UUID, Is.EqualTo(myAgentUuid)); Assert.That(sp.UUID, Is.EqualTo(myAgentUuid));
Assert.That(llUdpServer.PacketsSent.Count, Is.EqualTo(1)); Assert.That(m_udpServer.PacketsSent.Count, Is.EqualTo(1));
Packet packet = llUdpServer.PacketsSent[0]; Packet packet = m_udpServer.PacketsSent[0];
Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket))); Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket)));
PacketAckPacket ackPacket = packet as PacketAckPacket; PacketAckPacket ackPacket = packet as PacketAckPacket;
@ -212,6 +193,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0)); Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0));
} }
[Test]
public void TestLogoutClientDueToAck()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
IniConfigSource ics = new IniConfigSource();
IConfig config = ics.AddConfig("ClientStack.LindenUDP");
config.Set("AckTimeout", -1);
AddUdpServer(ics);
ScenePresence sp = AddClient();
m_udpServer.ClientOutgoingPacketHandler(sp.ControllingClient, true, false, false);
ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
Assert.That(spAfterAckTimeout, Is.Null);
// TestHelpers.DisableLogging();
}
// /// <summary> // /// <summary>
// /// Test removing a client from the stack // /// Test removing a client from the stack
// /// </summary> // /// </summary>

View File

@ -59,6 +59,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
PacketsSent.Add(packet); PacketsSent.Add(packet);
} }
public void ClientOutgoingPacketHandler(IClientAPI client, bool resendUnacked, bool sendAcks, bool sendPing)
{
m_resendUnacked = resendUnacked;
m_sendAcks = sendAcks;
m_sendPing = sendPing;
ClientOutgoingPacketHandler(client);
}
//// /// <summary> //// /// <summary>
//// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive //// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive
//// /// </summary> //// /// </summary>

View File

@ -480,6 +480,9 @@ namespace pCampBot
public void Objects_NewPrim(object sender, PrimEventArgs args) public void Objects_NewPrim(object sender, PrimEventArgs args)
{ {
// if (Name.EndsWith("4"))
// throw new Exception("Aaargh");
Primitive prim = args.Prim; Primitive prim = args.Prim;
if (prim != null) if (prim != null)

View File

@ -1153,6 +1153,8 @@
; currently unused ; currently unused
; AllowosConsoleCommand=false ; AllowosConsoleCommand=false
; Are god functions such as llSetObjectPermMask() allowed? If true then gods and only gods have access to these functions.
; If false then gods cannot execute these functions either.
AllowGodFunctions = false AllowGodFunctions = false
; Maximum number of llListen events we allow over the entire region. ; Maximum number of llListen events we allow over the entire region.

View File

@ -166,7 +166,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
;; This switch creates the minimum set of body parts and avatar entries for a viewer 2 ;; This switch creates the minimum set of body parts and avatar entries for a viewer 2
;; to show a default "Ruth" avatar rather than a cloud for a newly created user. ;; to show a default "Ruth" avatar rather than a cloud for a newly created user.
;; Default is false ;; Default is false
; CreateDefaultAvatarEntries = false CreateDefaultAvatarEntries = true
;; Allow the service to process HTTP createuser calls. ;; Allow the service to process HTTP createuser calls.
;; Default is false. ;; Default is false.