aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorJohn Hurliman2009-10-13 14:50:03 -0700
committerJohn Hurliman2009-10-13 14:50:03 -0700
commit23a334b9f54a1ef5df3b503c165e7b76b746a2b1 (patch)
tree93003db47fcd77af4085c0c49cbc1f2f0293b5eb /OpenSim/Region
parent* Unregister event handlers in LLUDPServer when a client logs out and disconn... (diff)
downloadopensim-SC_OLD-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.zip
opensim-SC_OLD-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.tar.gz
opensim-SC_OLD-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.tar.bz2
opensim-SC_OLD-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.tar.xz
* Rewrote ClientManager to remove Lindenisms from OpenSim core, improve performance by removing locks, and replace LLUDPClientCollection
* Removed the confusing (and LL-specific) shutdowncircuit parameter from IClientAPI.Close() * Updated the LLUDP code to only use ClientManager instead of trying to synchronize ClientManager and m_clients * Remove clients asynchronously since it is a very slow operation (including a 2000ms sleep)
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs77
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs1
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs137
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs163
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs18
-rw-r--r--OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs2
-rw-r--r--OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs6
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs8
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs10
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs14
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs2
14 files changed, 151 insertions, 293 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index bc9cfcf..86d0112 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -403,39 +403,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
403 #region Client Methods 403 #region Client Methods
404 404
405 /// <summary> 405 /// <summary>
406 /// Close down the client view. This *must* be the last method called, since the last # 406 /// Shut down the client view
407 /// statement of CloseCleanup() aborts the thread.
408 /// </summary> 407 /// </summary>
409 /// <param name="shutdownCircuit"></param> 408 public void Close()
410 public void Close(bool shutdownCircuit)
411 { 409 {
412 m_log.DebugFormat( 410 m_log.DebugFormat(
413 "[CLIENT]: Close has been called with shutdownCircuit = {0} for {1} attached to scene {2}", 411 "[CLIENT]: Close has been called for {0} attached to scene {1}",
414 shutdownCircuit, Name, m_scene.RegionInfo.RegionName); 412 Name, m_scene.RegionInfo.RegionName);
413
414 // Remove ourselves from the scene
415 m_scene.ClientManager.Remove(m_agentId, m_udpClient.RemoteEndPoint);
415 416
416 if (m_imageManager != null) 417 if (m_imageManager != null)
418 {
417 m_imageManager.Close(); 419 m_imageManager.Close();
420 m_imageManager = null;
421 }
418 422
419 if (m_udpServer != null) 423 if (m_udpServer != null)
420 m_udpServer.Flush();
421
422 // raise an event on the packet server to Shutdown the circuit
423 // Now, if we raise the event then the packet server will call this method itself, so don't try cleanup
424 // here otherwise we'll end up calling it twice.
425 // FIXME: In truth, I might be wrong but this whole business of calling this method twice (with different args) looks
426 // horribly tangly. Hopefully it should be possible to greatly simplify it.
427 if (shutdownCircuit)
428 { 424 {
429 if (OnConnectionClosed != null) 425 m_udpServer.Flush();
430 OnConnectionClosed(this);
431 }
432 else
433 {
434 CloseCleanup(shutdownCircuit);
435 } 426 }
427
428 if (OnConnectionClosed != null)
429 OnConnectionClosed(this);
430
431 CloseCleanup();
436 } 432 }
437 433
438 private void CloseCleanup(bool shutdownCircuit) 434 private void CloseCleanup()
439 { 435 {
440 m_scene.RemoveClient(AgentId); 436 m_scene.RemoveClient(AgentId);
441 437
@@ -459,43 +455,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
459 lock (m_primFullUpdateTimer) 455 lock (m_primFullUpdateTimer)
460 m_primFullUpdateTimer.Stop(); 456 m_primFullUpdateTimer.Stop();
461 457
462 // This is just to give the client a reasonable chance of
463 // flushing out all it's packets. There should probably
464 // be a better mechanism here
465
466 // We can't reach into other scenes and close the connection 458 // We can't reach into other scenes and close the connection
467 // We need to do this over grid communications 459 // We need to do this over grid communications
468 //m_scene.CloseAllAgents(CircuitCode); 460 //m_scene.CloseAllAgents(CircuitCode);
469 461
470 // If we're not shutting down the circuit, then this is the last time we'll go here.
471 // If we are shutting down the circuit, the UDP Server will come back here with
472 // ShutDownCircuit = false
473 if (!(shutdownCircuit))
474 {
475 GC.Collect();
476 m_imageManager = null;
477 // Sends a KillPacket object, with which, the
478 // blockingqueue dequeues and sees it's a killpacket
479 // and terminates within the context of the client thread.
480 // This ensures that it's done from within the context
481 // of the client thread regardless of where Close() is called.
482 KillEndDone();
483 }
484
485 IsActive = false; 462 IsActive = false;
486 463
487 m_avatarTerseUpdateTimer.Close(); 464 m_avatarTerseUpdateTimer.Dispose();
488 m_primTerseUpdateTimer.Close(); 465 m_primTerseUpdateTimer.Dispose();
489 m_primFullUpdateTimer.Close(); 466 m_primFullUpdateTimer.Dispose();
490 467
491 //m_udpServer.OnPacketStats -= PopulateStats; 468 // Disable UDP handling for this client
492 m_udpClient.Shutdown(); 469 m_udpClient.Shutdown();
493
494 // wait for thread stoped
495 // m_clientThread.Join();
496
497 // delete circuit code
498 //m_networkServer.CloseClient(this);
499 } 470 }
500 471
501 public void Kick(string message) 472 public void Kick(string message)
@@ -10225,7 +10196,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10225 10196
10226 public void KillEndDone() 10197 public void KillEndDone()
10227 { 10198 {
10228 m_udpClient.Shutdown();
10229 } 10199 }
10230 10200
10231 #region IClientCore 10201 #region IClientCore
@@ -10268,15 +10238,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10268 { 10238 {
10269 Kick(reason); 10239 Kick(reason);
10270 Thread.Sleep(1000); 10240 Thread.Sleep(1000);
10271 Close(true); 10241 Close();
10272 } 10242 }
10273 10243
10274 public void Disconnect() 10244 public void Disconnect()
10275 { 10245 {
10276 Close(true); 10246 Close();
10277 } 10247 }
10278 10248
10279
10280 #endregion 10249 #endregion
10281 10250
10282 public void RefreshGroupMembership() 10251 public void RefreshGroupMembership()
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 10e22d5..e5b2594 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -181,7 +181,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
181 /// </summary> 181 /// </summary>
182 public void Shutdown() 182 public void Shutdown()
183 { 183 {
184 // TODO: Do we need to invalidate the circuit?
185 IsConnected = false; 184 IsConnected = false;
186 } 185 }
187 186
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
deleted file mode 100644
index 4f375e4..0000000
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
+++ /dev/null
@@ -1,137 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using OpenSim.Framework;
32using OpenMetaverse;
33using BclExtras.Collections;
34
35using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim;
36
37namespace OpenSim.Region.ClientStack.LindenUDP
38{
39 /// <summary>
40 /// A thread safe mapping from endpoints to client references
41 /// </summary>
42 public sealed class UDPClientCollection
43 {
44 #region IComparers
45
46 private sealed class IPEndPointComparer : IComparer<IPEndPoint>
47 {
48 public int Compare(IPEndPoint x, IPEndPoint y)
49 {
50 int result = x.Address.Address.CompareTo(y.Address.Address);
51 if (result == 0) result = x.Port.CompareTo(y.Port);
52 return result;
53 }
54 }
55
56 #endregion IComparers
57
58 /// <summary>An immutable dictionary mapping from <seealso cref="IPEndPoint"/>
59 /// to <seealso cref="LLUDPClient"/> references</summary>
60 private ImmutableMap<IPEndPoint, LLUDPClient> m_dict;
61 /// <summary>Immutability grants thread safety for concurrent reads and
62 /// read-writes, but not concurrent writes</summary>
63 private object m_writeLock = new object();
64
65 /// <summary>Number of clients in the collection</summary>
66 public int Count { get { return m_dict.Count; } }
67
68 /// <summary>
69 /// Default constructor
70 /// </summary>
71 public UDPClientCollection()
72 {
73 m_dict = new ImmutableMap<IPEndPoint, LLUDPClient>(new IPEndPointComparer());
74 }
75
76 /// <summary>
77 /// Add a client reference to the collection
78 /// </summary>
79 /// <param name="key">Remote endpoint of the client</param>
80 /// <param name="value">Reference to the client object</param>
81 public void Add(IPEndPoint key, LLUDPClient value)
82 {
83 lock (m_writeLock)
84 m_dict = m_dict.Add(key, value);
85 }
86
87 /// <summary>
88 /// Remove a client from the collection
89 /// </summary>
90 /// <param name="key">Remote endpoint of the client</param>
91 public void Remove(IPEndPoint key)
92 {
93 lock (m_writeLock)
94 m_dict = m_dict.Delete(key);
95 }
96
97 /// <summary>
98 /// Resets the client collection
99 /// </summary>
100 public void Clear()
101 {
102 lock (m_writeLock)
103 m_dict = new ImmutableMap<IPEndPoint, LLUDPClient>(new IPEndPointComparer());
104 }
105
106 /// <summary>
107 /// Checks if an endpoint is in the collection
108 /// </summary>
109 /// <param name="key">Endpoint to check for</param>
110 /// <returns>True if the endpoint was found in the collection, otherwise false</returns>
111 public bool ContainsKey(IPEndPoint key)
112 {
113 return m_dict.ContainsKey(key);
114 }
115
116 /// <summary>
117 /// Attempts to fetch a value out of the collection
118 /// </summary>
119 /// <param name="key">Endpoint of the client to retrieve</param>
120 /// <param name="value">Retrieved client, or null on lookup failure</param>
121 /// <returns>True if the lookup succeeded, otherwise false</returns>
122 public bool TryGetValue(IPEndPoint key, out LLUDPClient value)
123 {
124 return m_dict.TryGetValue(key, out value);
125 }
126
127 /// <summary>
128 /// Performs a given task in parallel for each of the elements in the
129 /// collection
130 /// </summary>
131 /// <param name="action">Action to perform on each element</param>
132 public void ForEach(Action<LLUDPClient> action)
133 {
134 Parallel.ForEach<LLUDPClient>(m_dict.Values, action);
135 }
136 }
137}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 04c9cb1..8ec143a 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -96,7 +96,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
96 /// <summary>Incoming packets that are awaiting handling</summary> 96 /// <summary>Incoming packets that are awaiting handling</summary>
97 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 97 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
98 /// <summary></summary> 98 /// <summary></summary>
99 private UDPClientCollection m_clients = new UDPClientCollection(); 99 //private UDPClientCollection m_clients = new UDPClientCollection();
100 /// <summary>Bandwidth throttle for this UDP server</summary> 100 /// <summary>Bandwidth throttle for this UDP server</summary>
101 private TokenBucket m_throttle; 101 private TokenBucket m_throttle;
102 /// <summary>Bandwidth throttle rates for this UDP server</summary> 102 /// <summary>Bandwidth throttle rates for this UDP server</summary>
@@ -181,23 +181,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
181 return x == m_location; 181 return x == m_location;
182 } 182 }
183 183
184 public void RemoveClient(LLUDPClient udpClient)
185 {
186 m_log.Debug("[LLUDPSERVER]: Removing LLUDPClient for " + udpClient.AgentID);
187
188 // Shut down the IClientAPI and remove it from the scene
189 IClientAPI client;
190 if (m_scene.ClientManager.TryGetClient(udpClient.CircuitCode, out client))
191 {
192 client.Close(false);
193 m_scene.ClientManager.Remove(udpClient.CircuitCode);
194 }
195
196 // Shut down the LLUDPClient and remove it from the list of UDP clients
197 udpClient.Shutdown();
198 m_clients.Remove(udpClient.RemoteEndPoint);
199 }
200
201 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) 184 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
202 { 185 {
203 // CoarseLocationUpdate packets cannot be split in an automated way 186 // CoarseLocationUpdate packets cannot be split in an automated way
@@ -215,17 +198,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
215 for (int i = 0; i < packetCount; i++) 198 for (int i = 0; i < packetCount; i++)
216 { 199 {
217 byte[] data = datas[i]; 200 byte[] data = datas[i];
218 m_clients.ForEach( 201 m_scene.ClientManager.ForEach(
219 delegate(LLUDPClient client) 202 delegate(IClientAPI client)
220 { SendPacketData(client, data, packet.Type, category); }); 203 {
204 if (client is LLClientView)
205 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
206 }
207 );
221 } 208 }
222 } 209 }
223 else 210 else
224 { 211 {
225 byte[] data = packet.ToBytes(); 212 byte[] data = packet.ToBytes();
226 m_clients.ForEach( 213 m_scene.ClientManager.ForEach(
227 delegate(LLUDPClient client) 214 delegate(IClientAPI client)
228 { SendPacketData(client, data, packet.Type, category); }); 215 {
216 if (client is LLClientView)
217 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
218 }
219 );
229 } 220 }
230 } 221 }
231 222
@@ -475,7 +466,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
475 //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; } 466 //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; }
476 //catch (Exception) { } 467 //catch (Exception) { }
477 468
478 LLUDPClient client = null; 469 LLUDPClient udpClient = null;
479 Packet packet = null; 470 Packet packet = null;
480 int packetEnd = buffer.DataLength - 1; 471 int packetEnd = buffer.DataLength - 1;
481 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; 472 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint;
@@ -512,30 +503,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
512 } 503 }
513 504
514 // Determine which agent this packet came from 505 // Determine which agent this packet came from
515 if (!m_clients.TryGetValue(address, out client)) 506 IClientAPI client;
507 if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView))
516 { 508 {
517 m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + 509 m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address +
518 " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_clients.Count + " clients"); 510 " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_scene.ClientManager.Count + " clients");
519 return; 511 return;
520 } 512 }
521 513
514 udpClient = ((LLClientView)client).UDPClient;
515
522 #endregion Packet to Client Mapping 516 #endregion Packet to Client Mapping
523 517
524 // Stats tracking 518 // Stats tracking
525 Interlocked.Increment(ref client.PacketsReceived); 519 Interlocked.Increment(ref udpClient.PacketsReceived);
526 520
527 #region ACK Receiving 521 #region ACK Receiving
528 522
529 int now = Environment.TickCount; 523 int now = Environment.TickCount;
530 client.TickLastPacketReceived = now; 524 udpClient.TickLastPacketReceived = now;
531 525
532 // Handle appended ACKs 526 // Handle appended ACKs
533 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 527 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
534 { 528 {
535 lock (client.NeedAcks.SyncRoot) 529 lock (udpClient.NeedAcks.SyncRoot)
536 { 530 {
537 for (int i = 0; i < packet.Header.AckList.Length; i++) 531 for (int i = 0; i < packet.Header.AckList.Length; i++)
538 AcknowledgePacket(client, packet.Header.AckList[i], now, packet.Header.Resent); 532 AcknowledgePacket(udpClient, packet.Header.AckList[i], now, packet.Header.Resent);
539 } 533 }
540 } 534 }
541 535
@@ -544,10 +538,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
544 { 538 {
545 PacketAckPacket ackPacket = (PacketAckPacket)packet; 539 PacketAckPacket ackPacket = (PacketAckPacket)packet;
546 540
547 lock (client.NeedAcks.SyncRoot) 541 lock (udpClient.NeedAcks.SyncRoot)
548 { 542 {
549 for (int i = 0; i < ackPacket.Packets.Length; i++) 543 for (int i = 0; i < ackPacket.Packets.Length; i++)
550 AcknowledgePacket(client, ackPacket.Packets[i].ID, now, packet.Header.Resent); 544 AcknowledgePacket(udpClient, ackPacket.Packets[i].ID, now, packet.Header.Resent);
551 } 545 }
552 } 546 }
553 547
@@ -556,27 +550,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
556 #region ACK Sending 550 #region ACK Sending
557 551
558 if (packet.Header.Reliable) 552 if (packet.Header.Reliable)
559 client.PendingAcks.Enqueue(packet.Header.Sequence); 553 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
560 554
561 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 555 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
562 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove 556 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove
563 // 2*MTU bytes from the value and send ACKs, and finally add the local value back to 557 // 2*MTU bytes from the value and send ACKs, and finally add the local value back to
564 // client.BytesSinceLastACK. Lockless thread safety 558 // client.BytesSinceLastACK. Lockless thread safety
565 int bytesSinceLastACK = Interlocked.Exchange(ref client.BytesSinceLastACK, 0); 559 int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0);
566 bytesSinceLastACK += buffer.DataLength; 560 bytesSinceLastACK += buffer.DataLength;
567 if (bytesSinceLastACK > Packet.MTU * 2) 561 if (bytesSinceLastACK > Packet.MTU * 2)
568 { 562 {
569 bytesSinceLastACK -= Packet.MTU * 2; 563 bytesSinceLastACK -= Packet.MTU * 2;
570 SendAcks(client); 564 SendAcks(udpClient);
571 } 565 }
572 Interlocked.Add(ref client.BytesSinceLastACK, bytesSinceLastACK); 566 Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
573 567
574 #endregion ACK Sending 568 #endregion ACK Sending
575 569
576 #region Incoming Packet Accounting 570 #region Incoming Packet Accounting
577 571
578 // Check the archive of received reliable packet IDs to see whether we already received this packet 572 // Check the archive of received reliable packet IDs to see whether we already received this packet
579 if (packet.Header.Reliable && !client.PacketArchive.TryEnqueue(packet.Header.Sequence)) 573 if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence))
580 { 574 {
581 if (packet.Header.Resent) 575 if (packet.Header.Resent)
582 m_log.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type); 576 m_log.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type);
@@ -593,7 +587,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
593 if (packet.Type != PacketType.PacketAck) 587 if (packet.Type != PacketType.PacketAck)
594 { 588 {
595 // Inbox insertion 589 // Inbox insertion
596 packetInbox.Enqueue(new IncomingPacket(client, packet)); 590 packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
597 } 591 }
598 } 592 }
599 593
@@ -613,31 +607,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
613 607
614 private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint) 608 private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint)
615 { 609 {
610 UUID agentID = useCircuitCode.CircuitCode.ID;
611 UUID sessionID = useCircuitCode.CircuitCode.SessionID;
612 uint circuitCode = useCircuitCode.CircuitCode.Code;
613
616 if (m_scene.RegionStatus != RegionStatus.SlaveScene) 614 if (m_scene.RegionStatus != RegionStatus.SlaveScene)
617 { 615 {
618 if (!m_clients.ContainsKey(remoteEndPoint)) 616 AuthenticateResponse sessionInfo;
617 if (IsClientAuthorized(useCircuitCode, out sessionInfo))
619 { 618 {
620 AuthenticateResponse sessionInfo; 619 AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo);
621 if (IsClientAuthorized(useCircuitCode, out sessionInfo))
622 {
623 UUID agentID = useCircuitCode.CircuitCode.ID;
624 UUID sessionID = useCircuitCode.CircuitCode.SessionID;
625 uint circuitCode = useCircuitCode.CircuitCode.Code;
626
627 AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo);
628 }
629 else
630 {
631 // Don't create circuits for unauthorized clients
632 m_log.WarnFormat(
633 "[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}",
634 useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint);
635 }
636 } 620 }
637 else 621 else
638 { 622 {
639 // Ignore repeated UseCircuitCode packets 623 // Don't create circuits for unauthorized clients
640 m_log.Debug("[LLUDPSERVER]: Ignoring UseCircuitCode for already established circuit " + useCircuitCode.CircuitCode.Code); 624 m_log.WarnFormat(
625 "[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}",
626 useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint);
641 } 627 }
642 } 628 }
643 else 629 else
@@ -652,17 +638,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
652 // Create the LLUDPClient 638 // Create the LLUDPClient
653 LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); 639 LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint);
654 640
655 // Create the LLClientView 641 if (!m_scene.ClientManager.ContainsKey(agentID))
656 LLClientView clientApi = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 642 {
657 clientApi.OnLogout += LogoutHandler; 643 // Create the LLClientView
658 clientApi.OnConnectionClosed += ConnectionClosedHandler; 644 LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
645 client.OnLogout += LogoutHandler;
646 client.OnConnectionClosed += ConnectionClosedHandler;
659 647
660 // Start the IClientAPI 648 m_scene.ClientManager.Add(agentID, remoteEndPoint, client);
661 m_scene.ClientManager.Add(circuitCode, clientApi);
662 clientApi.Start();
663 649
664 // Add the new client to our list of tracked clients 650 // Start the IClientAPI
665 m_clients.Add(udpClient.RemoteEndPoint, udpClient); 651 m_scene.ClientManager.Add(agentID, remoteEndPoint, client);
652 client.Start();
653 }
654 else
655 {
656 m_log.Debug("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from " + udpClient.AgentID);
657 }
658 }
659
660 private void RemoveClient(LLUDPClient udpClient)
661 {
662 // Remove this client from the scene ClientManager
663 IClientAPI client;
664 if (m_scene.ClientManager.TryGetValue(udpClient.AgentID, out client))
665 Util.FireAndForget(delegate(object o) { client.Close(); });
666 } 666 }
667 667
668 private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend) 668 private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend)
@@ -740,20 +740,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
740 elapsed500MS = 0; 740 elapsed500MS = 0;
741 } 741 }
742 742
743 m_clients.ForEach( 743 m_scene.ClientManager.ForEach(
744 delegate(LLUDPClient client) 744 delegate(IClientAPI client)
745 { 745 {
746 if (client.DequeueOutgoing()) 746 if (client is LLClientView)
747 packetSent = true;
748 if (resendUnacked)
749 ResendUnacked(client);
750 if (sendAcks)
751 { 747 {
752 SendAcks(client); 748 LLUDPClient udpClient = ((LLClientView)client).UDPClient;
753 client.SendPacketStats(); 749
750 if (udpClient.DequeueOutgoing())
751 packetSent = true;
752 if (resendUnacked)
753 ResendUnacked(udpClient);
754 if (sendAcks)
755 {
756 SendAcks(udpClient);
757 udpClient.SendPacketStats();
758 }
759 if (sendPings)
760 SendPing(udpClient);
754 } 761 }
755 if (sendPings)
756 SendPing(client);
757 } 762 }
758 ); 763 );
759 764
@@ -777,7 +782,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
777 } 782 }
778 783
779 // Make sure this client is still alive 784 // Make sure this client is still alive
780 if (m_scene.ClientManager.TryGetClient(udpClient.CircuitCode, out client)) 785 if (m_scene.ClientManager.TryGetValue(udpClient.AgentID, out client))
781 { 786 {
782 try 787 try
783 { 788 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index f941728..7855862 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -36,6 +36,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
36{ 36{
37 public class GodsModule : IRegionModule, IGodsModule 37 public class GodsModule : IRegionModule, IGodsModule
38 { 38 {
39 /// <summary>Special UUID for actions that apply to all agents</summary>
40 private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb");
41
39 protected Scene m_scene; 42 protected Scene m_scene;
40 protected IDialogModule m_dialogModule; 43 protected IDialogModule m_dialogModule;
41 44
@@ -99,8 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
99 /// <param name="reason">The message to send to the user after it's been turned into a field</param> 102 /// <param name="reason">The message to send to the user after it's been turned into a field</param>
100 public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason) 103 public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason)
101 { 104 {
102 // For some reason the client sends this seemingly hard coded UUID for kicking everyone. Dun-know. 105 UUID kickUserID = ALL_AGENTS;
103 UUID kickUserID = new UUID("44e87126e7944ded05b37c42da3d5cdb");
104 106
105 ScenePresence sp = m_scene.GetScenePresence(agentID); 107 ScenePresence sp = m_scene.GetScenePresence(agentID);
106 108
@@ -110,15 +112,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
110 { 112 {
111 if (agentID == kickUserID) 113 if (agentID == kickUserID)
112 { 114 {
113 m_scene.ClientManager.ForEachClient( 115 string reasonStr = Utils.BytesToString(reason);
116
117 m_scene.ClientManager.ForEach(
114 delegate(IClientAPI controller) 118 delegate(IClientAPI controller)
115 { 119 {
116 if (controller.AgentId != godID) 120 if (controller.AgentId != godID)
117 controller.Kick(Utils.BytesToString(reason)); 121 controller.Kick(reasonStr);
118 } 122 }
119 ); 123 );
120 124
121 // This is a bit crude. It seems the client will be null before it actually stops the thread 125 // This is a bit crude. It seems the client will be null before it actually stops the thread
122 // The thread will kill itself eventually :/ 126 // The thread will kill itself eventually :/
123 // Is there another way to make sure *all* clients get this 'inter region' message? 127 // Is there another way to make sure *all* clients get this 'inter region' message?
124 m_scene.ForEachScenePresence( 128 m_scene.ForEachScenePresence(
@@ -128,7 +132,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
128 { 132 {
129 // Possibly this should really be p.Close() though that method doesn't send a close 133 // Possibly this should really be p.Close() though that method doesn't send a close
130 // to the client 134 // to the client
131 p.ControllingClient.Close(true); 135 p.ControllingClient.Close();
132 } 136 }
133 } 137 }
134 ); 138 );
@@ -138,7 +142,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
138 m_scene.SceneGraph.removeUserCount(!sp.IsChildAgent); 142 m_scene.SceneGraph.removeUserCount(!sp.IsChildAgent);
139 143
140 sp.ControllingClient.Kick(Utils.BytesToString(reason)); 144 sp.ControllingClient.Kick(Utils.BytesToString(reason));
141 sp.ControllingClient.Close(true); 145 sp.ControllingClient.Close();
142 } 146 }
143 } 147 }
144 else 148 else
diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
index 7d6f150..d636b1c 100644
--- a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
+++ b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
@@ -1267,7 +1267,7 @@ namespace OpenSim.Region.CoreModules.InterGrid
1267 if (avToBeKilled.IsChildAgent) 1267 if (avToBeKilled.IsChildAgent)
1268 { 1268 {
1269 m_mod.DeleteOGPState(avUUID); 1269 m_mod.DeleteOGPState(avUUID);
1270 avToBeKilled.ControllingClient.Close(true); 1270 avToBeKilled.ControllingClient.Close();
1271 } 1271 }
1272 } 1272 }
1273 } 1273 }
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index 8ad4844..dcee824 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -813,7 +813,7 @@ namespace OpenSim.Region.Examples.SimpleModule
813 { 813 {
814 } 814 }
815 815
816 public void Close(bool ShutdownCircuit) 816 public void Close()
817 { 817 {
818 } 818 }
819 819
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index dbbf679..ac89f7b 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -408,7 +408,7 @@ namespace OpenSim.Region.Framework.Scenes
408 } 408 }
409 ViewerEffectPacket.EffectBlock[] effectBlockArray = effectBlock.ToArray(); 409 ViewerEffectPacket.EffectBlock[] effectBlockArray = effectBlock.ToArray();
410 410
411 ClientManager.ForEachClient( 411 ClientManager.ForEach(
412 delegate(IClientAPI client) 412 delegate(IClientAPI client)
413 { 413 {
414 if (client.AgentId != remoteClient.AgentId) 414 if (client.AgentId != remoteClient.AgentId)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index e81b07b..bb71896 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -867,7 +867,7 @@ namespace OpenSim.Region.Framework.Scenes
867 Thread.Sleep(500); 867 Thread.Sleep(500);
868 868
869 // Stop all client threads. 869 // Stop all client threads.
870 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(true); }); 870 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); });
871 871
872 // Stop updating the scene objects and agents. 872 // Stop updating the scene objects and agents.
873 //m_heartbeatTimer.Close(); 873 //m_heartbeatTimer.Close();
@@ -3372,7 +3372,7 @@ namespace OpenSim.Region.Framework.Scenes
3372 loggingOffUser.ControllingClient.Kick(message); 3372 loggingOffUser.ControllingClient.Kick(message);
3373 // Give them a second to receive the message! 3373 // Give them a second to receive the message!
3374 Thread.Sleep(1000); 3374 Thread.Sleep(1000);
3375 loggingOffUser.ControllingClient.Close(true); 3375 loggingOffUser.ControllingClient.Close();
3376 } 3376 }
3377 else 3377 else
3378 { 3378 {
@@ -3543,7 +3543,7 @@ namespace OpenSim.Region.Framework.Scenes
3543 presence.ControllingClient.SendShutdownConnectionNotice(); 3543 presence.ControllingClient.SendShutdownConnectionNotice();
3544 } 3544 }
3545 3545
3546 presence.ControllingClient.Close(true); 3546 presence.ControllingClient.Close();
3547 return true; 3547 return true;
3548 } 3548 }
3549 3549
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs
index 4b199ac..c962329 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs
@@ -64,7 +64,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView
64 void user_OnIRCReady(IRCClientView cv) 64 void user_OnIRCReady(IRCClientView cv)
65 { 65 {
66 m_log.Info("[IRCd] Adding user..."); 66 m_log.Info("[IRCd] Adding user...");
67 m_scene.ClientManager.Add(cv.CircuitCode, cv); 67 m_scene.ClientManager.Add(cv.AgentId, cv.RemoteEndPoint, cv);
68 cv.Start(); 68 cv.Start();
69 m_log.Info("[IRCd] Added user to Scene"); 69 m_log.Info("[IRCd] Added user to Scene");
70 } 70 }
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 4364627..a8acf0d 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -634,6 +634,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
634 { 634 {
635 get { return (uint)Util.RandomClass.Next(0,int.MaxValue); } 635 get { return (uint)Util.RandomClass.Next(0,int.MaxValue); }
636 } 636 }
637
638 public IPEndPoint RemoteEndPoint
639 {
640 get { return (IPEndPoint)m_client.Client.RemoteEndPoint; }
641 }
642
637#pragma warning disable 67 643#pragma warning disable 67
638 public event GenericMessage OnGenericMessage; 644 public event GenericMessage OnGenericMessage;
639 public event ImprovedInstantMessage OnInstantMessage; 645 public event ImprovedInstantMessage OnInstantMessage;
@@ -843,7 +849,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
843 849
844 } 850 }
845 851
846 public void Close(bool ShutdownCircuit) 852 public void Close()
847 { 853 {
848 Disconnect(); 854 Disconnect();
849 } 855 }
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
index d6dacbc..b6513e2 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
@@ -183,8 +183,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
183 public virtual void HideFromAll() 183 public virtual void HideFromAll()
184 { 184 {
185 foreach (SceneObjectPart part in m_Entity.Children.Values) 185 foreach (SceneObjectPart part in m_Entity.Children.Values)
186 m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) 186 m_Entity.Scene.ClientManager.ForEach(
187 { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } 187 delegate(IClientAPI controller)
188 { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); }
188 ); 189 );
189 } 190 }
190 191
@@ -201,8 +202,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
201 202
202 public void SendFullUpdateToAll() 203 public void SendFullUpdateToAll()
203 { 204 {
204 m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) 205 m_Entity.Scene.ClientManager.ForEach(
205 { m_Entity.SendFullUpdateToClient(controller); } 206 delegate(IClientAPI controller)
207 { m_Entity.SendFullUpdateToClient(controller); }
206 ); 208 );
207 } 209 }
208 210
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index ac8b98c..f7c63ac 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -825,7 +825,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
825 { 825 {
826 } 826 }
827 827
828 public void Close(bool ShutdownCircuit) 828 public void Close()
829 { 829 {
830 } 830 }
831 831
@@ -838,11 +838,21 @@ namespace OpenSim.Region.OptionalModules.World.NPC
838 } 838 }
839 839
840 private uint m_circuitCode; 840 private uint m_circuitCode;
841 private IPEndPoint m_remoteEndPoint;
841 842
842 public uint CircuitCode 843 public uint CircuitCode
843 { 844 {
844 get { return m_circuitCode; } 845 get { return m_circuitCode; }
845 set { m_circuitCode = value; } 846 set
847 {
848 m_circuitCode = value;
849 m_remoteEndPoint = new IPEndPoint(IPAddress.Loopback, (ushort)m_circuitCode);
850 }
851 }
852
853 public IPEndPoint RemoteEndPoint
854 {
855 get { return m_remoteEndPoint; }
846 } 856 }
847 857
848 public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) 858 public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message)
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 30a2675..eb7b0d7 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -155,7 +155,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
155 NPCAvatar npcAvatar = new NPCAvatar(p_firstname, p_lastname, p_position, p_scene); 155 NPCAvatar npcAvatar = new NPCAvatar(p_firstname, p_lastname, p_position, p_scene);
156 npcAvatar.CircuitCode = (uint) Util.RandomClass.Next(0, int.MaxValue); 156 npcAvatar.CircuitCode = (uint) Util.RandomClass.Next(0, int.MaxValue);
157 157
158 p_scene.ClientManager.Add(npcAvatar.CircuitCode, npcAvatar); 158 p_scene.ClientManager.Add(npcAvatar.AgentId, npcAvatar.RemoteEndPoint, npcAvatar);
159 p_scene.AddNewClient(npcAvatar); 159 p_scene.AddNewClient(npcAvatar);
160 160
161 ScenePresence sp; 161 ScenePresence sp;