aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP
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/ClientStack/LindenUDP
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/ClientStack/LindenUDP')
-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
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
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 {