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 | |
parent | * Unregister event handlers in LLUDPServer when a client logs out and disconn... (diff) | |
download | opensim-SC-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.zip opensim-SC-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.tar.gz opensim-SC-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.tar.bz2 opensim-SC-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)
21 files changed, 311 insertions, 329 deletions
diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index bc1b2e5..bc02bc4 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs | |||
@@ -774,6 +774,11 @@ namespace OpenSim.Client.MXP.ClientStack | |||
774 | get { return m_sessionID.CRC(); } | 774 | get { return m_sessionID.CRC(); } |
775 | } | 775 | } |
776 | 776 | ||
777 | public IPEndPoint RemoteEndPoint | ||
778 | { | ||
779 | get { return Session.RemoteEndPoint; } | ||
780 | } | ||
781 | |||
777 | public void SetDebugPacketLevel(int newDebug) | 782 | public void SetDebugPacketLevel(int newDebug) |
778 | { | 783 | { |
779 | //m_debugLevel = newDebug; | 784 | //m_debugLevel = newDebug; |
@@ -798,9 +803,9 @@ namespace OpenSim.Client.MXP.ClientStack | |||
798 | OnConnectionClosed(this); | 803 | OnConnectionClosed(this); |
799 | } | 804 | } |
800 | 805 | ||
801 | public void Close(bool ShutdownCircuit) | 806 | public void Close() |
802 | { | 807 | { |
803 | m_log.Info("[MXP ClientStack] Close Called with SC=" + ShutdownCircuit); | 808 | m_log.Info("[MXP ClientStack] Close Called"); |
804 | 809 | ||
805 | // Tell the client to go | 810 | // Tell the client to go |
806 | SendLogoutPacket(); | 811 | SendLogoutPacket(); |
@@ -815,7 +820,7 @@ namespace OpenSim.Client.MXP.ClientStack | |||
815 | 820 | ||
816 | public void Kick(string message) | 821 | public void Kick(string message) |
817 | { | 822 | { |
818 | Close(false); | 823 | Close(); |
819 | } | 824 | } |
820 | 825 | ||
821 | public void Start() | 826 | public void Start() |
@@ -1448,7 +1453,7 @@ namespace OpenSim.Client.MXP.ClientStack | |||
1448 | 1453 | ||
1449 | public void Terminate() | 1454 | public void Terminate() |
1450 | { | 1455 | { |
1451 | Close(false); | 1456 | Close(); |
1452 | } | 1457 | } |
1453 | 1458 | ||
1454 | public void SendSetFollowCamProperties(UUID objectID, SortedDictionary<int, float> parameters) | 1459 | public void SendSetFollowCamProperties(UUID objectID, SortedDictionary<int, float> parameters) |
@@ -1615,12 +1620,12 @@ namespace OpenSim.Client.MXP.ClientStack | |||
1615 | public void Disconnect(string reason) | 1620 | public void Disconnect(string reason) |
1616 | { | 1621 | { |
1617 | Kick(reason); | 1622 | Kick(reason); |
1618 | Close(true); | 1623 | Close(); |
1619 | } | 1624 | } |
1620 | 1625 | ||
1621 | public void Disconnect() | 1626 | public void Disconnect() |
1622 | { | 1627 | { |
1623 | Close(true); | 1628 | Close(); |
1624 | } | 1629 | } |
1625 | 1630 | ||
1626 | #endregion | 1631 | #endregion |
diff --git a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs index 4910ab1..d5dc18f 100644 --- a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs +++ b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs | |||
@@ -341,7 +341,7 @@ namespace OpenSim.Client.MXP.PacketHandler | |||
341 | 341 | ||
342 | 342 | ||
343 | m_log.Debug("[MXP ClientStack]: Adding ClientView to Scene..."); | 343 | m_log.Debug("[MXP ClientStack]: Adding ClientView to Scene..."); |
344 | scene.ClientManager.Add(client.CircuitCode, client); | 344 | scene.ClientManager.Add(client.AgentId, client.RemoteEndPoint, client); |
345 | m_log.Debug("[MXP ClientStack]: Added ClientView to Scene."); | 345 | m_log.Debug("[MXP ClientStack]: Added ClientView to Scene."); |
346 | 346 | ||
347 | 347 | ||
diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index c649c5a..9c24da5 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs | |||
@@ -415,7 +415,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack | |||
415 | throw new System.NotImplementedException(); | 415 | throw new System.NotImplementedException(); |
416 | } | 416 | } |
417 | 417 | ||
418 | public void Close(bool ShutdownCircuit) | 418 | public void Close() |
419 | { | 419 | { |
420 | throw new System.NotImplementedException(); | 420 | throw new System.NotImplementedException(); |
421 | } | 421 | } |
diff --git a/OpenSim/Framework/ClientManager.cs b/OpenSim/Framework/ClientManager.cs index 5ebbbc1..4edfabe 100644 --- a/OpenSim/Framework/ClientManager.cs +++ b/OpenSim/Framework/ClientManager.cs | |||
@@ -28,56 +28,174 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Reflection; | 30 | using System.Reflection; |
31 | using log4net; | 31 | using System.Net; |
32 | using BclExtras.Collections; | ||
32 | using OpenMetaverse; | 33 | using OpenMetaverse; |
33 | using OpenMetaverse.Packets; | 34 | using OpenMetaverse.Packets; |
34 | 35 | ||
35 | namespace OpenSim.Framework | 36 | namespace OpenSim.Framework |
36 | { | 37 | { |
38 | /// <summary> | ||
39 | /// Maps from client AgentID and RemoteEndPoint values to IClientAPI | ||
40 | /// references for all of the connected clients | ||
41 | /// </summary> | ||
37 | public class ClientManager | 42 | public class ClientManager |
38 | { | 43 | { |
39 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 44 | #region IComparers |
40 | 45 | ||
41 | private Dictionary<uint, IClientAPI> m_clients = new Dictionary<uint, IClientAPI>(); | 46 | private sealed class UUIDComparer : IComparer<UUID> |
42 | |||
43 | public void Add(uint circuitCode, IClientAPI client) | ||
44 | { | 47 | { |
45 | lock (m_clients) | 48 | public int Compare(UUID x, UUID y) |
46 | m_clients.Add(circuitCode, client); | 49 | { |
50 | return x.CompareTo(y); | ||
51 | } | ||
47 | } | 52 | } |
48 | 53 | ||
49 | public bool Remove(uint circuitCode) | 54 | private sealed class IPEndPointComparer : IComparer<IPEndPoint> |
50 | { | 55 | { |
51 | lock (m_clients) | 56 | public int Compare(IPEndPoint x, IPEndPoint y) |
52 | return m_clients.Remove(circuitCode); | 57 | { |
58 | if (x == null && y == null) | ||
59 | return 0; | ||
60 | else if (x == null) | ||
61 | return -1; | ||
62 | else if (y == null) | ||
63 | return 1; | ||
64 | |||
65 | int result = x.Address.Address.CompareTo(y.Address.Address); | ||
66 | if (result == 0) result = x.Port.CompareTo(y.Port); | ||
67 | |||
68 | return result; | ||
69 | } | ||
53 | } | 70 | } |
54 | 71 | ||
55 | public bool TryGetClient(uint circuitCode, out IClientAPI user) | 72 | #endregion IComparers |
73 | |||
74 | /// <summary>An immutable dictionary mapping from <seealso cref="UUID"/> | ||
75 | /// to <seealso cref="IClientAPI"/> references</summary> | ||
76 | private ImmutableMap<UUID, IClientAPI> m_dict; | ||
77 | /// <summary>An immutable dictionary mapping from <seealso cref="IPEndPoint"/> | ||
78 | /// to <seealso cref="IClientAPI"/> references</summary> | ||
79 | private ImmutableMap<IPEndPoint, IClientAPI> m_dict2; | ||
80 | /// <summary>Immutability grants thread safety for concurrent reads and | ||
81 | /// read-writes, but not concurrent writes</summary> | ||
82 | private object m_writeLock = new object(); | ||
83 | |||
84 | /// <summary>Number of clients in the collection</summary> | ||
85 | public int Count { get { return m_dict.Count; } } | ||
86 | |||
87 | /// <summary> | ||
88 | /// Default constructor | ||
89 | /// </summary> | ||
90 | public ClientManager() | ||
56 | { | 91 | { |
57 | lock (m_clients) | 92 | m_dict = new ImmutableMap<UUID, IClientAPI>(new UUIDComparer()); |
58 | return m_clients.TryGetValue(circuitCode, out user); | 93 | m_dict2 = new ImmutableMap<IPEndPoint, IClientAPI>(new IPEndPointComparer()); |
59 | } | 94 | } |
60 | 95 | ||
61 | public void ForEachClient(Action<IClientAPI> action) | 96 | /// <summary> |
97 | /// Add a client reference to the collection if it does not already | ||
98 | /// exist | ||
99 | /// </summary> | ||
100 | /// <param name="key">UUID of the client</param> | ||
101 | /// <param name="key2">Remote endpoint of the client</param> | ||
102 | /// <param name="value">Reference to the client object</param> | ||
103 | /// <returns>True if the client reference was successfully added, | ||
104 | /// otherwise false if the given key already existed in the collection</returns> | ||
105 | public bool Add(UUID key, IPEndPoint key2, IClientAPI value) | ||
62 | { | 106 | { |
63 | IClientAPI[] LocalClients; | 107 | lock (m_writeLock) |
64 | lock (m_clients) | ||
65 | { | 108 | { |
66 | LocalClients = new IClientAPI[m_clients.Count]; | 109 | if (!m_dict.ContainsKey(key) && !m_dict2.ContainsKey(key2)) |
67 | m_clients.Values.CopyTo(LocalClients, 0); | ||
68 | } | ||
69 | |||
70 | for (int i = 0; i < LocalClients.Length; i++) | ||
71 | { | ||
72 | try | ||
73 | { | 110 | { |
74 | action(LocalClients[i]); | 111 | m_dict = m_dict.Add(key, value); |
112 | m_dict2 = m_dict2.Add(key2, value); | ||
113 | |||
114 | return true; | ||
75 | } | 115 | } |
76 | catch (Exception e) | 116 | else |
77 | { | 117 | { |
78 | m_log.Warn("[CLIENT]: Unable to do ForEachClient for one of the clients" + "\n Reason: " + e.ToString()); | 118 | return false; |
79 | } | 119 | } |
80 | } | 120 | } |
81 | } | 121 | } |
122 | |||
123 | /// <summary> | ||
124 | /// Remove a client from the collection | ||
125 | /// </summary> | ||
126 | /// <param name="key">UUID of the client</param> | ||
127 | /// <param name="key2">Remote endpoint of the client</param> | ||
128 | public void Remove(UUID key, IPEndPoint key2) | ||
129 | { | ||
130 | lock (m_writeLock) | ||
131 | { | ||
132 | m_dict = m_dict.Delete(key); | ||
133 | m_dict2 = m_dict2.Delete(key2); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | /// <summary> | ||
138 | /// Resets the client collection | ||
139 | /// </summary> | ||
140 | public void Clear() | ||
141 | { | ||
142 | lock (m_writeLock) | ||
143 | { | ||
144 | m_dict = new ImmutableMap<UUID, IClientAPI>(new UUIDComparer()); | ||
145 | m_dict2 = new ImmutableMap<IPEndPoint, IClientAPI>(new IPEndPointComparer()); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | /// <summary> | ||
150 | /// Checks if a UUID is in the collection | ||
151 | /// </summary> | ||
152 | /// <param name="key">UUID to check for</param> | ||
153 | /// <returns>True if the UUID was found in the collection, otherwise false</returns> | ||
154 | public bool ContainsKey(UUID key) | ||
155 | { | ||
156 | return m_dict.ContainsKey(key); | ||
157 | } | ||
158 | |||
159 | /// <summary> | ||
160 | /// Checks if an endpoint is in the collection | ||
161 | /// </summary> | ||
162 | /// <param name="key">Endpoint to check for</param> | ||
163 | /// <returns>True if the endpoint was found in the collection, otherwise false</returns> | ||
164 | public bool ContainsKey(IPEndPoint key) | ||
165 | { | ||
166 | return m_dict2.ContainsKey(key); | ||
167 | } | ||
168 | |||
169 | /// <summary> | ||
170 | /// Attempts to fetch a value out of the collection | ||
171 | /// </summary> | ||
172 | /// <param name="key">UUID of the client to retrieve</param> | ||
173 | /// <param name="value">Retrieved client, or null on lookup failure</param> | ||
174 | /// <returns>True if the lookup succeeded, otherwise false</returns> | ||
175 | public bool TryGetValue(UUID key, out IClientAPI value) | ||
176 | { | ||
177 | return m_dict.TryGetValue(key, out value); | ||
178 | } | ||
179 | |||
180 | /// <summary> | ||
181 | /// Attempts to fetch a value out of the collection | ||
182 | /// </summary> | ||
183 | /// <param name="key">Endpoint of the client to retrieve</param> | ||
184 | /// <param name="value">Retrieved client, or null on lookup failure</param> | ||
185 | /// <returns>True if the lookup succeeded, otherwise false</returns> | ||
186 | public bool TryGetValue(IPEndPoint key, out IClientAPI value) | ||
187 | { | ||
188 | return m_dict2.TryGetValue(key, out value); | ||
189 | } | ||
190 | |||
191 | /// <summary> | ||
192 | /// Performs a given task in parallel for each of the elements in the | ||
193 | /// collection | ||
194 | /// </summary> | ||
195 | /// <param name="action">Action to perform on each element</param> | ||
196 | public void ForEach(Action<IClientAPI> action) | ||
197 | { | ||
198 | Parallel.ForEach<IClientAPI>(m_dict.Values, action); | ||
199 | } | ||
82 | } | 200 | } |
83 | } | 201 | } |
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index d3bd9e7..99ea0d5 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs | |||
@@ -802,7 +802,7 @@ namespace OpenSim.Framework | |||
802 | 802 | ||
803 | void InPacket(object NewPack); | 803 | void InPacket(object NewPack); |
804 | void ProcessInPacket(Packet NewPack); | 804 | void ProcessInPacket(Packet NewPack); |
805 | void Close(bool ShutdownCircuit); | 805 | void Close(); |
806 | void Kick(string message); | 806 | void Kick(string message); |
807 | 807 | ||
808 | /// <summary> | 808 | /// <summary> |
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 | { |
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; |
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 2b54890..ad90817 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs | |||
@@ -865,7 +865,7 @@ namespace OpenSim.Tests.Common.Mock | |||
865 | { | 865 | { |
866 | } | 866 | } |
867 | 867 | ||
868 | public void Close(bool ShutdownCircuit) | 868 | public void Close() |
869 | { | 869 | { |
870 | m_scene.RemoveClient(AgentId); | 870 | m_scene.RemoveClient(AgentId); |
871 | } | 871 | } |
diff --git a/prebuild.xml b/prebuild.xml index 028e5e7..f15fadf 100644 --- a/prebuild.xml +++ b/prebuild.xml | |||
@@ -135,6 +135,7 @@ | |||
135 | <Reference name="System.Xml"/> | 135 | <Reference name="System.Xml"/> |
136 | <Reference name="System.Data"/> | 136 | <Reference name="System.Data"/> |
137 | <Reference name="System.Drawing"/> | 137 | <Reference name="System.Drawing"/> |
138 | <Reference name="BclExtras.dll"/> | ||
138 | <Reference name="OpenMetaverseTypes.dll"/> | 139 | <Reference name="OpenMetaverseTypes.dll"/> |
139 | <Reference name="OpenMetaverse.dll"/> | 140 | <Reference name="OpenMetaverse.dll"/> |
140 | <Reference name="OpenMetaverse.StructuredData.dll"/> | 141 | <Reference name="OpenMetaverse.StructuredData.dll"/> |