diff options
author | John Hurliman | 2009-10-13 14:50:03 -0700 |
---|---|---|
committer | John Hurliman | 2009-10-13 14:50:03 -0700 |
commit | 23a334b9f54a1ef5df3b503c165e7b76b746a2b1 (patch) | |
tree | 93003db47fcd77af4085c0c49cbc1f2f0293b5eb /OpenSim/Region/ClientStack/LindenUDP | |
parent | * Unregister event handlers in LLUDPServer when a client logs out and disconn... (diff) | |
download | opensim-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/ClientStack/LindenUDP')
4 files changed, 107 insertions, 271 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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Net; | ||
31 | using OpenSim.Framework; | ||
32 | using OpenMetaverse; | ||
33 | using BclExtras.Collections; | ||
34 | |||
35 | using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim; | ||
36 | |||
37 | namespace 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 | { |