diff options
Diffstat (limited to 'OpenSim')
36 files changed, 1063 insertions, 1566 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..ba9c653 100644 --- a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs +++ b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs | |||
@@ -339,12 +339,6 @@ namespace OpenSim.Client.MXP.PacketHandler | |||
339 | m_clients.Add(client); | 339 | m_clients.Add(client); |
340 | m_log.Debug("[MXP ClientStack]: Created ClientView."); | 340 | m_log.Debug("[MXP ClientStack]: Created ClientView."); |
341 | 341 | ||
342 | |||
343 | m_log.Debug("[MXP ClientStack]: Adding ClientView to Scene..."); | ||
344 | scene.ClientManager.Add(client.CircuitCode, client); | ||
345 | m_log.Debug("[MXP ClientStack]: Added ClientView to Scene."); | ||
346 | |||
347 | |||
348 | client.MXPSendSynchronizationBegin(m_scenes[new UUID(joinRequestMessage.BubbleId)].SceneContents.GetTotalObjectsCount()); | 342 | client.MXPSendSynchronizationBegin(m_scenes[new UUID(joinRequestMessage.BubbleId)].SceneContents.GetTotalObjectsCount()); |
349 | 343 | ||
350 | m_log.Debug("[MXP ClientStack]: Starting ClientView..."); | 344 | m_log.Debug("[MXP ClientStack]: Starting ClientView..."); |
diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index c649c5a..e3abcf5 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs | |||
@@ -207,6 +207,11 @@ namespace OpenSim.Client.VWoHTTP.ClientStack | |||
207 | get { throw new System.NotImplementedException(); } | 207 | get { throw new System.NotImplementedException(); } |
208 | } | 208 | } |
209 | 209 | ||
210 | public IPEndPoint RemoteEndPoint | ||
211 | { | ||
212 | get { throw new System.NotImplementedException(); } | ||
213 | } | ||
214 | |||
210 | public event GenericMessage OnGenericMessage = delegate { }; | 215 | public event GenericMessage OnGenericMessage = delegate { }; |
211 | public event ImprovedInstantMessage OnInstantMessage = delegate { }; | 216 | public event ImprovedInstantMessage OnInstantMessage = delegate { }; |
212 | public event ChatMessage OnChatFromClient = delegate { }; | 217 | public event ChatMessage OnChatFromClient = delegate { }; |
@@ -415,7 +420,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack | |||
415 | throw new System.NotImplementedException(); | 420 | throw new System.NotImplementedException(); |
416 | } | 421 | } |
417 | 422 | ||
418 | public void Close(bool ShutdownCircuit) | 423 | public void Close() |
419 | { | 424 | { |
420 | throw new System.NotImplementedException(); | 425 | throw new System.NotImplementedException(); |
421 | } | 426 | } |
diff --git a/OpenSim/Framework/ClientManager.cs b/OpenSim/Framework/ClientManager.cs index 094a3ff..367bc6a 100644 --- a/OpenSim/Framework/ClientManager.cs +++ b/OpenSim/Framework/ClientManager.cs | |||
@@ -28,193 +28,183 @@ | |||
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 | { |
37 | public delegate void ForEachClientDelegate(IClientAPI client); | 38 | /// <summary> |
38 | 39 | /// Maps from client AgentID and RemoteEndPoint values to IClientAPI | |
40 | /// references for all of the connected clients | ||
41 | /// </summary> | ||
39 | public class ClientManager | 42 | public class ClientManager |
40 | { | 43 | { |
41 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 44 | #region IComparers |
42 | |||
43 | private Dictionary<uint, IClientAPI> m_clients; | ||
44 | 45 | ||
45 | public ClientManager() | 46 | private sealed class UUIDComparer : IComparer<UUID> |
46 | { | 47 | { |
47 | m_clients = new Dictionary<uint, IClientAPI>(); | 48 | public int Compare(UUID x, UUID y) |
48 | } | ||
49 | |||
50 | public void ForEachClient(ForEachClientDelegate whatToDo) | ||
51 | { | ||
52 | IClientAPI[] LocalClients; | ||
53 | lock (m_clients) | ||
54 | { | ||
55 | LocalClients = new IClientAPI[m_clients.Count]; | ||
56 | m_clients.Values.CopyTo(LocalClients, 0); | ||
57 | } | ||
58 | |||
59 | for (int i = 0; i < LocalClients.Length; i++) | ||
60 | { | 49 | { |
61 | try | 50 | return x.CompareTo(y); |
62 | { | ||
63 | whatToDo(LocalClients[i]); | ||
64 | } | ||
65 | catch (Exception e) | ||
66 | { | ||
67 | m_log.Warn("[CLIENT]: Unable to do ForEachClient for one of the clients" + "\n Reason: " + e.ToString()); | ||
68 | } | ||
69 | } | 51 | } |
70 | } | 52 | } |
71 | 53 | ||
72 | public void Remove(uint id) | 54 | private sealed class IPEndPointComparer : IComparer<IPEndPoint> |
73 | { | 55 | { |
74 | lock (m_clients) | 56 | public int Compare(IPEndPoint x, IPEndPoint y) |
75 | { | 57 | { |
76 | m_clients.Remove(id); | 58 | if (x == null && y == null) |
77 | } | 59 | return 0; |
78 | } | 60 | else if (x == null) |
61 | return -1; | ||
62 | else if (y == null) | ||
63 | return 1; | ||
79 | 64 | ||
80 | public void Add(uint id, IClientAPI client) | 65 | int result = x.Address.Address.CompareTo(y.Address.Address); |
81 | { | 66 | if (result == 0) result = x.Port.CompareTo(y.Port); |
82 | lock (m_clients) | 67 | |
83 | { | 68 | return result; |
84 | m_clients.Add(id, client); | ||
85 | } | 69 | } |
86 | } | 70 | } |
87 | 71 | ||
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 | |||
88 | /// <summary> | 87 | /// <summary> |
89 | /// Pass incoming packet to client. | 88 | /// Default constructor |
90 | /// </summary> | 89 | /// </summary> |
91 | /// <param name="circuitCode">uint identifying the connection/client.</param> | 90 | public ClientManager() |
92 | /// <param name="packet">object containing the packet.</param> | ||
93 | public void InPacket(uint circuitCode, object packet) | ||
94 | { | 91 | { |
95 | IClientAPI client; | 92 | m_dict = new ImmutableMap<UUID, IClientAPI>(new UUIDComparer()); |
96 | bool tryGetRet = false; | 93 | m_dict2 = new ImmutableMap<IPEndPoint, IClientAPI>(new IPEndPointComparer()); |
97 | |||
98 | lock (m_clients) | ||
99 | tryGetRet = m_clients.TryGetValue(circuitCode, out client); | ||
100 | |||
101 | if (tryGetRet) | ||
102 | { | ||
103 | client.InPacket(packet); | ||
104 | } | ||
105 | } | 94 | } |
106 | 95 | ||
107 | public void CloseAllAgents(uint circuitCode) | 96 | /// <summary> |
108 | { | 97 | /// Add a client reference to the collection if it does not already |
109 | IClientAPI client; | 98 | /// exist |
110 | bool tryGetRet = false; | 99 | /// </summary> |
111 | lock (m_clients) | 100 | /// <param name="value">Reference to the client object</param> |
112 | tryGetRet = m_clients.TryGetValue(circuitCode, out client); | 101 | /// <returns>True if the client reference was successfully added, |
113 | if (tryGetRet) | 102 | /// otherwise false if the given key already existed in the collection</returns> |
114 | { | 103 | public bool Add(IClientAPI value) |
115 | CloseAllCircuits(client.AgentId); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | public void CloseAllCircuits(UUID agentId) | ||
120 | { | 104 | { |
121 | uint[] circuits = GetAllCircuits(agentId); | 105 | lock (m_writeLock) |
122 | // We're using a for loop here so changes to the circuits don't cause it to completely fail. | ||
123 | |||
124 | for (int i = 0; i < circuits.Length; i++) | ||
125 | { | 106 | { |
126 | IClientAPI client; | 107 | if (!m_dict.ContainsKey(value.AgentId) && !m_dict2.ContainsKey(value.RemoteEndPoint)) |
127 | try | ||
128 | { | 108 | { |
129 | bool tryGetRet = false; | 109 | m_dict = m_dict.Add(value.AgentId, value); |
130 | lock (m_clients) | 110 | m_dict2 = m_dict2.Add(value.RemoteEndPoint, value); |
131 | tryGetRet = m_clients.TryGetValue(circuits[i], out client); | 111 | |
132 | if (tryGetRet) | 112 | return true; |
133 | { | ||
134 | Remove(client.CircuitCode); | ||
135 | client.Close(false); | ||
136 | } | ||
137 | } | 113 | } |
138 | catch (Exception e) | 114 | else |
139 | { | 115 | { |
140 | m_log.Error(string.Format("[CLIENT]: Unable to shutdown circuit for: {0}\n Reason: {1}", agentId, e)); | 116 | return false; |
141 | } | 117 | } |
142 | } | 118 | } |
143 | } | 119 | } |
144 | 120 | ||
145 | // [Obsolete("Using Obsolete to drive development is invalid. Obsolete presumes that something new has already been created to replace this.")] | 121 | /// <summary> |
146 | public uint[] GetAllCircuits(UUID agentId) | 122 | /// Remove a client from the collection |
123 | /// </summary> | ||
124 | /// <param name="key">UUID of the client to remove</param> | ||
125 | /// <returns>True if a client was removed, or false if the given UUID | ||
126 | /// was not present in the collection</returns> | ||
127 | public bool Remove(UUID key) | ||
147 | { | 128 | { |
148 | List<uint> circuits = new List<uint>(); | 129 | lock (m_writeLock) |
149 | // Wasteful, I know | ||
150 | IClientAPI[] LocalClients = new IClientAPI[0]; | ||
151 | lock (m_clients) | ||
152 | { | 130 | { |
153 | LocalClients = new IClientAPI[m_clients.Count]; | 131 | IClientAPI client; |
154 | m_clients.Values.CopyTo(LocalClients, 0); | ||
155 | } | ||
156 | 132 | ||
157 | for (int i = 0; i < LocalClients.Length; i++) | 133 | if (m_dict.TryGetValue(key, out client)) |
158 | { | ||
159 | if (LocalClients[i].AgentId == agentId) | ||
160 | { | 134 | { |
161 | circuits.Add(LocalClients[i].CircuitCode); | 135 | m_dict = m_dict.Delete(key); |
136 | m_dict2 = m_dict2.Delete(client.RemoteEndPoint); | ||
137 | return true; | ||
138 | } | ||
139 | else | ||
140 | { | ||
141 | return false; | ||
162 | } | 142 | } |
163 | } | 143 | } |
164 | return circuits.ToArray(); | ||
165 | } | 144 | } |
166 | 145 | ||
167 | public List<uint> GetAllCircuitCodes() | 146 | /// <summary> |
147 | /// Resets the client collection | ||
148 | /// </summary> | ||
149 | public void Clear() | ||
168 | { | 150 | { |
169 | List<uint> circuits; | 151 | lock (m_writeLock) |
170 | |||
171 | lock (m_clients) | ||
172 | { | 152 | { |
173 | circuits = new List<uint>(m_clients.Keys); | 153 | m_dict = new ImmutableMap<UUID, IClientAPI>(new UUIDComparer()); |
154 | m_dict2 = new ImmutableMap<IPEndPoint, IClientAPI>(new IPEndPointComparer()); | ||
174 | } | 155 | } |
156 | } | ||
175 | 157 | ||
176 | return circuits; | 158 | /// <summary> |
159 | /// Checks if a UUID is in the collection | ||
160 | /// </summary> | ||
161 | /// <param name="key">UUID to check for</param> | ||
162 | /// <returns>True if the UUID was found in the collection, otherwise false</returns> | ||
163 | public bool ContainsKey(UUID key) | ||
164 | { | ||
165 | return m_dict.ContainsKey(key); | ||
177 | } | 166 | } |
178 | 167 | ||
179 | public void ViewerEffectHandler(IClientAPI sender, List<ViewerEffectEventHandlerArg> args) | 168 | /// <summary> |
169 | /// Checks if an endpoint is in the collection | ||
170 | /// </summary> | ||
171 | /// <param name="key">Endpoint to check for</param> | ||
172 | /// <returns>True if the endpoint was found in the collection, otherwise false</returns> | ||
173 | public bool ContainsKey(IPEndPoint key) | ||
180 | { | 174 | { |
181 | // TODO: don't create new blocks if recycling an old packet | 175 | return m_dict2.ContainsKey(key); |
182 | List<ViewerEffectPacket.EffectBlock> effectBlock = new List<ViewerEffectPacket.EffectBlock>(); | 176 | } |
183 | for (int i = 0; i < args.Count; i++) | ||
184 | { | ||
185 | ViewerEffectPacket.EffectBlock effect = new ViewerEffectPacket.EffectBlock(); | ||
186 | effect.AgentID = args[i].AgentID; | ||
187 | effect.Color = args[i].Color; | ||
188 | effect.Duration = args[i].Duration; | ||
189 | effect.ID = args[i].ID; | ||
190 | effect.Type = args[i].Type; | ||
191 | effect.TypeData = args[i].TypeData; | ||
192 | effectBlock.Add(effect); | ||
193 | } | ||
194 | ViewerEffectPacket.EffectBlock[] effectBlockArray = effectBlock.ToArray(); | ||
195 | 177 | ||
196 | IClientAPI[] LocalClients; | 178 | /// <summary> |
197 | lock (m_clients) | 179 | /// Attempts to fetch a value out of the collection |
198 | { | 180 | /// </summary> |
199 | LocalClients = new IClientAPI[m_clients.Count]; | 181 | /// <param name="key">UUID of the client to retrieve</param> |
200 | m_clients.Values.CopyTo(LocalClients, 0); | 182 | /// <param name="value">Retrieved client, or null on lookup failure</param> |
201 | } | 183 | /// <returns>True if the lookup succeeded, otherwise false</returns> |
184 | public bool TryGetValue(UUID key, out IClientAPI value) | ||
185 | { | ||
186 | return m_dict.TryGetValue(key, out value); | ||
187 | } | ||
202 | 188 | ||
203 | for (int i = 0; i < LocalClients.Length; i++) | 189 | /// <summary> |
204 | { | 190 | /// Attempts to fetch a value out of the collection |
205 | if (LocalClients[i].AgentId != sender.AgentId) | 191 | /// </summary> |
206 | { | 192 | /// <param name="key">Endpoint of the client to retrieve</param> |
207 | LocalClients[i].SendViewerEffect(effectBlockArray); | 193 | /// <param name="value">Retrieved client, or null on lookup failure</param> |
208 | } | 194 | /// <returns>True if the lookup succeeded, otherwise false</returns> |
209 | } | 195 | public bool TryGetValue(IPEndPoint key, out IClientAPI value) |
196 | { | ||
197 | return m_dict2.TryGetValue(key, out value); | ||
210 | } | 198 | } |
211 | 199 | ||
212 | public bool TryGetClient(uint circuitId, out IClientAPI user) | 200 | /// <summary> |
201 | /// Performs a given task in parallel for each of the elements in the | ||
202 | /// collection | ||
203 | /// </summary> | ||
204 | /// <param name="action">Action to perform on each element</param> | ||
205 | public void ForEach(Action<IClientAPI> action) | ||
213 | { | 206 | { |
214 | lock (m_clients) | 207 | Parallel.ForEach<IClientAPI>(m_dict.Values, action); |
215 | { | ||
216 | return m_clients.TryGetValue(circuitId, out user); | ||
217 | } | ||
218 | } | 208 | } |
219 | } | 209 | } |
220 | } | 210 | } |
diff --git a/OpenSim/Framework/Communications/GenericAsyncResult.cs b/OpenSim/Framework/Communications/GenericAsyncResult.cs index efd2f43..8e3f62b 100644 --- a/OpenSim/Framework/Communications/GenericAsyncResult.cs +++ b/OpenSim/Framework/Communications/GenericAsyncResult.cs | |||
@@ -146,6 +146,7 @@ namespace OpenSim.Framework.Communications | |||
146 | // If the operation isn't done, wait for it | 146 | // If the operation isn't done, wait for it |
147 | AsyncWaitHandle.WaitOne(); | 147 | AsyncWaitHandle.WaitOne(); |
148 | AsyncWaitHandle.Close(); | 148 | AsyncWaitHandle.Close(); |
149 | m_waitHandle.Close(); | ||
149 | m_waitHandle = null; // Allow early GC | 150 | m_waitHandle = null; // Allow early GC |
150 | } | 151 | } |
151 | 152 | ||
diff --git a/OpenSim/Framework/Communications/RestClient.cs b/OpenSim/Framework/Communications/RestClient.cs index d98f47d..a74169e 100644 --- a/OpenSim/Framework/Communications/RestClient.cs +++ b/OpenSim/Framework/Communications/RestClient.cs | |||
@@ -105,7 +105,7 @@ namespace OpenSim.Framework.Communications | |||
105 | /// <summary> | 105 | /// <summary> |
106 | /// This flag will help block the main synchroneous method, in case we run in synchroneous mode | 106 | /// This flag will help block the main synchroneous method, in case we run in synchroneous mode |
107 | /// </summary> | 107 | /// </summary> |
108 | public static ManualResetEvent _allDone = new ManualResetEvent(false); | 108 | //public static ManualResetEvent _allDone = new ManualResetEvent(false); |
109 | 109 | ||
110 | /// <summary> | 110 | /// <summary> |
111 | /// Default time out period | 111 | /// Default time out period |
@@ -282,12 +282,12 @@ namespace OpenSim.Framework.Communications | |||
282 | else | 282 | else |
283 | { | 283 | { |
284 | s.Close(); | 284 | s.Close(); |
285 | _allDone.Set(); | 285 | //_allDone.Set(); |
286 | } | 286 | } |
287 | } | 287 | } |
288 | catch (Exception e) | 288 | catch (Exception e) |
289 | { | 289 | { |
290 | _allDone.Set(); | 290 | //_allDone.Set(); |
291 | _asyncException = e; | 291 | _asyncException = e; |
292 | } | 292 | } |
293 | } | 293 | } |
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index d3bd9e7..29846f5 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs | |||
@@ -561,6 +561,8 @@ namespace OpenSim.Framework | |||
561 | // [Obsolete("LLClientView Specific - Circuits are unique to LLClientView")] | 561 | // [Obsolete("LLClientView Specific - Circuits are unique to LLClientView")] |
562 | uint CircuitCode { get; } | 562 | uint CircuitCode { get; } |
563 | 563 | ||
564 | IPEndPoint RemoteEndPoint { get; } | ||
565 | |||
564 | event GenericMessage OnGenericMessage; | 566 | event GenericMessage OnGenericMessage; |
565 | 567 | ||
566 | // [Obsolete("LLClientView Specific - Replace with more bare-bones arguments.")] | 568 | // [Obsolete("LLClientView Specific - Replace with more bare-bones arguments.")] |
@@ -802,7 +804,7 @@ namespace OpenSim.Framework | |||
802 | 804 | ||
803 | void InPacket(object NewPack); | 805 | void InPacket(object NewPack); |
804 | void ProcessInPacket(Packet NewPack); | 806 | void ProcessInPacket(Packet NewPack); |
805 | void Close(bool ShutdownCircuit); | 807 | void Close(); |
806 | void Kick(string message); | 808 | void Kick(string message); |
807 | 809 | ||
808 | /// <summary> | 810 | /// <summary> |
diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs index 489653f..f34027d 100644 --- a/OpenSim/Framework/IScene.cs +++ b/OpenSim/Framework/IScene.cs | |||
@@ -71,7 +71,6 @@ namespace OpenSim.Framework | |||
71 | 71 | ||
72 | void AddNewClient(IClientAPI client); | 72 | void AddNewClient(IClientAPI client); |
73 | void RemoveClient(UUID agentID); | 73 | void RemoveClient(UUID agentID); |
74 | void CloseAllAgents(uint circuitcode); | ||
75 | 74 | ||
76 | void Restart(int seconds); | 75 | void Restart(int seconds); |
77 | //RegionInfo OtherRegionUp(RegionInfo thisRegion); | 76 | //RegionInfo OtherRegionUp(RegionInfo thisRegion); |
diff --git a/OpenSim/Framework/LocklessQueue.cs b/OpenSim/Framework/LocklessQueue.cs new file mode 100644 index 0000000..dd3d201 --- /dev/null +++ b/OpenSim/Framework/LocklessQueue.cs | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2009, openmetaverse.org | ||
3 | * All rights reserved. | ||
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 | * | ||
8 | * - Redistributions of source code must retain the above copyright notice, this | ||
9 | * list of conditions and the following disclaimer. | ||
10 | * - Neither the name of the openmetaverse.org nor the names | ||
11 | * of its contributors may be used to endorse or promote products derived from | ||
12 | * this software without specific prior written permission. | ||
13 | * | ||
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
24 | * POSSIBILITY OF SUCH DAMAGE. | ||
25 | */ | ||
26 | |||
27 | using System; | ||
28 | using System.Threading; | ||
29 | |||
30 | namespace OpenSim.Framework | ||
31 | { | ||
32 | public sealed class LocklessQueue<T> | ||
33 | { | ||
34 | private sealed class SingleLinkNode | ||
35 | { | ||
36 | public SingleLinkNode Next; | ||
37 | public T Item; | ||
38 | } | ||
39 | |||
40 | SingleLinkNode head; | ||
41 | SingleLinkNode tail; | ||
42 | int count; | ||
43 | |||
44 | public int Count { get { return count; } } | ||
45 | |||
46 | public LocklessQueue() | ||
47 | { | ||
48 | Init(); | ||
49 | } | ||
50 | |||
51 | public void Enqueue(T item) | ||
52 | { | ||
53 | SingleLinkNode oldTail = null; | ||
54 | SingleLinkNode oldTailNext; | ||
55 | |||
56 | SingleLinkNode newNode = new SingleLinkNode(); | ||
57 | newNode.Item = item; | ||
58 | |||
59 | bool newNodeWasAdded = false; | ||
60 | |||
61 | while (!newNodeWasAdded) | ||
62 | { | ||
63 | oldTail = tail; | ||
64 | oldTailNext = oldTail.Next; | ||
65 | |||
66 | if (tail == oldTail) | ||
67 | { | ||
68 | if (oldTailNext == null) | ||
69 | newNodeWasAdded = CAS(ref tail.Next, null, newNode); | ||
70 | else | ||
71 | CAS(ref tail, oldTail, oldTailNext); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | CAS(ref tail, oldTail, newNode); | ||
76 | Interlocked.Increment(ref count); | ||
77 | } | ||
78 | |||
79 | public bool Dequeue(out T item) | ||
80 | { | ||
81 | item = default(T); | ||
82 | SingleLinkNode oldHead = null; | ||
83 | bool haveAdvancedHead = false; | ||
84 | |||
85 | while (!haveAdvancedHead) | ||
86 | { | ||
87 | oldHead = head; | ||
88 | SingleLinkNode oldTail = tail; | ||
89 | SingleLinkNode oldHeadNext = oldHead.Next; | ||
90 | |||
91 | if (oldHead == head) | ||
92 | { | ||
93 | if (oldHead == oldTail) | ||
94 | { | ||
95 | if (oldHeadNext == null) | ||
96 | return false; | ||
97 | |||
98 | CAS(ref tail, oldTail, oldHeadNext); | ||
99 | } | ||
100 | else | ||
101 | { | ||
102 | item = oldHeadNext.Item; | ||
103 | haveAdvancedHead = CAS(ref head, oldHead, oldHeadNext); | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | |||
108 | Interlocked.Decrement(ref count); | ||
109 | return true; | ||
110 | } | ||
111 | |||
112 | public void Clear() | ||
113 | { | ||
114 | Init(); | ||
115 | } | ||
116 | |||
117 | private void Init() | ||
118 | { | ||
119 | count = 0; | ||
120 | head = tail = new SingleLinkNode(); | ||
121 | } | ||
122 | |||
123 | private static bool CAS(ref SingleLinkNode location, SingleLinkNode comparand, SingleLinkNode newValue) | ||
124 | { | ||
125 | return | ||
126 | (object)comparand == | ||
127 | (object)Interlocked.CompareExchange<SingleLinkNode>(ref location, newValue, comparand); | ||
128 | } | ||
129 | } | ||
130 | } \ No newline at end of file | ||
diff --git a/OpenSim/Framework/Parallel.cs b/OpenSim/Framework/Parallel.cs index 74537ba..6efdad0 100644 --- a/OpenSim/Framework/Parallel.cs +++ b/OpenSim/Framework/Parallel.cs | |||
@@ -89,6 +89,7 @@ namespace OpenSim.Framework | |||
89 | } | 89 | } |
90 | 90 | ||
91 | threadFinishEvent.WaitOne(); | 91 | threadFinishEvent.WaitOne(); |
92 | threadFinishEvent.Close(); | ||
92 | 93 | ||
93 | if (exception != null) | 94 | if (exception != null) |
94 | throw new Exception(exception.Message, exception); | 95 | throw new Exception(exception.Message, exception); |
@@ -148,6 +149,7 @@ namespace OpenSim.Framework | |||
148 | } | 149 | } |
149 | 150 | ||
150 | threadFinishEvent.WaitOne(); | 151 | threadFinishEvent.WaitOne(); |
152 | threadFinishEvent.Close(); | ||
151 | 153 | ||
152 | if (exception != null) | 154 | if (exception != null) |
153 | throw new Exception(exception.Message, exception); | 155 | throw new Exception(exception.Message, exception); |
@@ -199,6 +201,7 @@ namespace OpenSim.Framework | |||
199 | } | 201 | } |
200 | 202 | ||
201 | threadFinishEvent.WaitOne(); | 203 | threadFinishEvent.WaitOne(); |
204 | threadFinishEvent.Close(); | ||
202 | 205 | ||
203 | if (exception != null) | 206 | if (exception != null) |
204 | throw new Exception(exception.Message, exception); | 207 | throw new Exception(exception.Message, exception); |
diff --git a/OpenSim/Framework/ThrottleOutPacketType.cs b/OpenSim/Framework/ThrottleOutPacketType.cs index fd490a5..eb42fea 100644 --- a/OpenSim/Framework/ThrottleOutPacketType.cs +++ b/OpenSim/Framework/ThrottleOutPacketType.cs | |||
@@ -31,13 +31,23 @@ namespace OpenSim.Framework | |||
31 | { | 31 | { |
32 | public enum ThrottleOutPacketType : int | 32 | public enum ThrottleOutPacketType : int |
33 | { | 33 | { |
34 | Unknown = -1, // Also doubles as 'do not throttle' | 34 | /// <summary>Unthrottled packets</summary> |
35 | Unknown = -1, | ||
36 | /// <summary>Packets that are being resent</summary> | ||
35 | Resend = 0, | 37 | Resend = 0, |
38 | /// <summary>Terrain data</summary> | ||
36 | Land = 1, | 39 | Land = 1, |
40 | /// <summary>Wind data</summary> | ||
37 | Wind = 2, | 41 | Wind = 2, |
42 | /// <summary>Cloud data</summary> | ||
38 | Cloud = 3, | 43 | Cloud = 3, |
39 | Task = 4, | 44 | /// <summary>Texture assets</summary> |
40 | Texture = 5, | 45 | Texture = 4, |
41 | Asset = 6, | 46 | /// <summary>Non-texture assets</summary> |
47 | Asset = 5, | ||
48 | /// <summary>Avatar and primitive data</summary> | ||
49 | State = 6, | ||
50 | /// <summary>Any packets that do not fit into the other throttles</summary> | ||
51 | Task = 7, | ||
42 | } | 52 | } |
43 | } | 53 | } |
diff --git a/OpenSim/Region/Application/OpenSimBackground.cs b/OpenSim/Region/Application/OpenSimBackground.cs index ac5e241..008c6b0 100644 --- a/OpenSim/Region/Application/OpenSimBackground.cs +++ b/OpenSim/Region/Application/OpenSimBackground.cs | |||
@@ -58,6 +58,7 @@ namespace OpenSim | |||
58 | m_clientServers.Count.ToString(), m_clientServers.Count > 1 ? "s" : ""); | 58 | m_clientServers.Count.ToString(), m_clientServers.Count > 1 ? "s" : ""); |
59 | 59 | ||
60 | WorldHasComeToAnEnd.WaitOne(); | 60 | WorldHasComeToAnEnd.WaitOne(); |
61 | WorldHasComeToAnEnd.Close(); | ||
61 | } | 62 | } |
62 | 63 | ||
63 | /// <summary> | 64 | /// <summary> |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index d64f655..cfc1ebc 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -59,6 +59,209 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
59 | /// </summary> | 59 | /// </summary> |
60 | public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector | 60 | public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector |
61 | { | 61 | { |
62 | #region Events | ||
63 | |||
64 | public event GenericMessage OnGenericMessage; | ||
65 | public event BinaryGenericMessage OnBinaryGenericMessage; | ||
66 | public event Action<IClientAPI> OnLogout; | ||
67 | public event ObjectPermissions OnObjectPermissions; | ||
68 | public event Action<IClientAPI> OnConnectionClosed; | ||
69 | public event ViewerEffectEventHandler OnViewerEffect; | ||
70 | public event ImprovedInstantMessage OnInstantMessage; | ||
71 | public event ChatMessage OnChatFromClient; | ||
72 | public event TextureRequest OnRequestTexture; | ||
73 | public event RezObject OnRezObject; | ||
74 | public event DeRezObject OnDeRezObject; | ||
75 | public event ModifyTerrain OnModifyTerrain; | ||
76 | public event Action<IClientAPI> OnRegionHandShakeReply; | ||
77 | public event GenericCall2 OnRequestWearables; | ||
78 | public event SetAppearance OnSetAppearance; | ||
79 | public event AvatarNowWearing OnAvatarNowWearing; | ||
80 | public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; | ||
81 | public event RezMultipleAttachmentsFromInv OnRezMultipleAttachmentsFromInv; | ||
82 | public event UUIDNameRequest OnDetachAttachmentIntoInv; | ||
83 | public event ObjectAttach OnObjectAttach; | ||
84 | public event ObjectDeselect OnObjectDetach; | ||
85 | public event ObjectDrop OnObjectDrop; | ||
86 | public event GenericCall2 OnCompleteMovementToRegion; | ||
87 | public event UpdateAgent OnAgentUpdate; | ||
88 | public event AgentRequestSit OnAgentRequestSit; | ||
89 | public event AgentSit OnAgentSit; | ||
90 | public event AvatarPickerRequest OnAvatarPickerRequest; | ||
91 | public event StartAnim OnStartAnim; | ||
92 | public event StopAnim OnStopAnim; | ||
93 | public event Action<IClientAPI> OnRequestAvatarsData; | ||
94 | public event LinkObjects OnLinkObjects; | ||
95 | public event DelinkObjects OnDelinkObjects; | ||
96 | public event GrabObject OnGrabObject; | ||
97 | public event DeGrabObject OnDeGrabObject; | ||
98 | public event SpinStart OnSpinStart; | ||
99 | public event SpinStop OnSpinStop; | ||
100 | public event ObjectDuplicate OnObjectDuplicate; | ||
101 | public event ObjectDuplicateOnRay OnObjectDuplicateOnRay; | ||
102 | public event MoveObject OnGrabUpdate; | ||
103 | public event SpinObject OnSpinUpdate; | ||
104 | public event AddNewPrim OnAddPrim; | ||
105 | public event RequestGodlikePowers OnRequestGodlikePowers; | ||
106 | public event GodKickUser OnGodKickUser; | ||
107 | public event ObjectExtraParams OnUpdateExtraParams; | ||
108 | public event UpdateShape OnUpdatePrimShape; | ||
109 | public event ObjectRequest OnObjectRequest; | ||
110 | public event ObjectSelect OnObjectSelect; | ||
111 | public event ObjectDeselect OnObjectDeselect; | ||
112 | public event GenericCall7 OnObjectDescription; | ||
113 | public event GenericCall7 OnObjectName; | ||
114 | public event GenericCall7 OnObjectClickAction; | ||
115 | public event GenericCall7 OnObjectMaterial; | ||
116 | public event ObjectIncludeInSearch OnObjectIncludeInSearch; | ||
117 | public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; | ||
118 | public event UpdatePrimFlags OnUpdatePrimFlags; | ||
119 | public event UpdatePrimTexture OnUpdatePrimTexture; | ||
120 | public event UpdateVector OnUpdatePrimGroupPosition; | ||
121 | public event UpdateVector OnUpdatePrimSinglePosition; | ||
122 | public event UpdatePrimRotation OnUpdatePrimGroupRotation; | ||
123 | public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation; | ||
124 | public event UpdatePrimSingleRotationPosition OnUpdatePrimSingleRotationPosition; | ||
125 | public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation; | ||
126 | public event UpdateVector OnUpdatePrimScale; | ||
127 | public event UpdateVector OnUpdatePrimGroupScale; | ||
128 | public event StatusChange OnChildAgentStatus; | ||
129 | public event GenericCall2 OnStopMovement; | ||
130 | public event Action<UUID> OnRemoveAvatar; | ||
131 | public event RequestMapBlocks OnRequestMapBlocks; | ||
132 | public event RequestMapName OnMapNameRequest; | ||
133 | public event TeleportLocationRequest OnTeleportLocationRequest; | ||
134 | public event TeleportLandmarkRequest OnTeleportLandmarkRequest; | ||
135 | public event DisconnectUser OnDisconnectUser; | ||
136 | public event RequestAvatarProperties OnRequestAvatarProperties; | ||
137 | public event SetAlwaysRun OnSetAlwaysRun; | ||
138 | public event FetchInventory OnAgentDataUpdateRequest; | ||
139 | public event TeleportLocationRequest OnSetStartLocationRequest; | ||
140 | public event UpdateAvatarProperties OnUpdateAvatarProperties; | ||
141 | public event CreateNewInventoryItem OnCreateNewInventoryItem; | ||
142 | public event CreateInventoryFolder OnCreateNewInventoryFolder; | ||
143 | public event UpdateInventoryFolder OnUpdateInventoryFolder; | ||
144 | public event MoveInventoryFolder OnMoveInventoryFolder; | ||
145 | public event FetchInventoryDescendents OnFetchInventoryDescendents; | ||
146 | public event PurgeInventoryDescendents OnPurgeInventoryDescendents; | ||
147 | public event FetchInventory OnFetchInventory; | ||
148 | public event RequestTaskInventory OnRequestTaskInventory; | ||
149 | public event UpdateInventoryItem OnUpdateInventoryItem; | ||
150 | public event CopyInventoryItem OnCopyInventoryItem; | ||
151 | public event MoveInventoryItem OnMoveInventoryItem; | ||
152 | public event RemoveInventoryItem OnRemoveInventoryItem; | ||
153 | public event RemoveInventoryFolder OnRemoveInventoryFolder; | ||
154 | public event UDPAssetUploadRequest OnAssetUploadRequest; | ||
155 | public event XferReceive OnXferReceive; | ||
156 | public event RequestXfer OnRequestXfer; | ||
157 | public event ConfirmXfer OnConfirmXfer; | ||
158 | public event AbortXfer OnAbortXfer; | ||
159 | public event RequestTerrain OnRequestTerrain; | ||
160 | public event RezScript OnRezScript; | ||
161 | public event UpdateTaskInventory OnUpdateTaskInventory; | ||
162 | public event MoveTaskInventory OnMoveTaskItem; | ||
163 | public event RemoveTaskInventory OnRemoveTaskItem; | ||
164 | public event RequestAsset OnRequestAsset; | ||
165 | public event UUIDNameRequest OnNameFromUUIDRequest; | ||
166 | public event ParcelAccessListRequest OnParcelAccessListRequest; | ||
167 | public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest; | ||
168 | public event ParcelPropertiesRequest OnParcelPropertiesRequest; | ||
169 | public event ParcelDivideRequest OnParcelDivideRequest; | ||
170 | public event ParcelJoinRequest OnParcelJoinRequest; | ||
171 | public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; | ||
172 | public event ParcelSelectObjects OnParcelSelectObjects; | ||
173 | public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest; | ||
174 | public event ParcelAbandonRequest OnParcelAbandonRequest; | ||
175 | public event ParcelGodForceOwner OnParcelGodForceOwner; | ||
176 | public event ParcelReclaim OnParcelReclaim; | ||
177 | public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest; | ||
178 | public event ParcelDeedToGroup OnParcelDeedToGroup; | ||
179 | public event RegionInfoRequest OnRegionInfoRequest; | ||
180 | public event EstateCovenantRequest OnEstateCovenantRequest; | ||
181 | public event FriendActionDelegate OnApproveFriendRequest; | ||
182 | public event FriendActionDelegate OnDenyFriendRequest; | ||
183 | public event FriendshipTermination OnTerminateFriendship; | ||
184 | public event MoneyTransferRequest OnMoneyTransferRequest; | ||
185 | public event EconomyDataRequest OnEconomyDataRequest; | ||
186 | public event MoneyBalanceRequest OnMoneyBalanceRequest; | ||
187 | public event ParcelBuy OnParcelBuy; | ||
188 | public event UUIDNameRequest OnTeleportHomeRequest; | ||
189 | public event UUIDNameRequest OnUUIDGroupNameRequest; | ||
190 | public event ScriptAnswer OnScriptAnswer; | ||
191 | public event RequestPayPrice OnRequestPayPrice; | ||
192 | public event ObjectSaleInfo OnObjectSaleInfo; | ||
193 | public event ObjectBuy OnObjectBuy; | ||
194 | public event BuyObjectInventory OnBuyObjectInventory; | ||
195 | public event AgentSit OnUndo; | ||
196 | public event ForceReleaseControls OnForceReleaseControls; | ||
197 | public event GodLandStatRequest OnLandStatRequest; | ||
198 | public event RequestObjectPropertiesFamily OnObjectGroupRequest; | ||
199 | public event DetailedEstateDataRequest OnDetailedEstateDataRequest; | ||
200 | public event SetEstateFlagsRequest OnSetEstateFlagsRequest; | ||
201 | public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture; | ||
202 | public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture; | ||
203 | public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights; | ||
204 | public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest; | ||
205 | public event SetRegionTerrainSettings OnSetRegionTerrainSettings; | ||
206 | public event BakeTerrain OnBakeTerrain; | ||
207 | public event RequestTerrain OnUploadTerrain; | ||
208 | public event EstateChangeInfo OnEstateChangeInfo; | ||
209 | public event EstateRestartSimRequest OnEstateRestartSimRequest; | ||
210 | public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest; | ||
211 | public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest; | ||
212 | public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest; | ||
213 | public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest; | ||
214 | public event EstateDebugRegionRequest OnEstateDebugRegionRequest; | ||
215 | public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest; | ||
216 | public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest; | ||
217 | public event RegionHandleRequest OnRegionHandleRequest; | ||
218 | public event ParcelInfoRequest OnParcelInfoRequest; | ||
219 | public event ScriptReset OnScriptReset; | ||
220 | public event GetScriptRunning OnGetScriptRunning; | ||
221 | public event SetScriptRunning OnSetScriptRunning; | ||
222 | public event UpdateVector OnAutoPilotGo; | ||
223 | public event TerrainUnacked OnUnackedTerrain; | ||
224 | public event ActivateGesture OnActivateGesture; | ||
225 | public event DeactivateGesture OnDeactivateGesture; | ||
226 | public event ObjectOwner OnObjectOwner; | ||
227 | public event DirPlacesQuery OnDirPlacesQuery; | ||
228 | public event DirFindQuery OnDirFindQuery; | ||
229 | public event DirLandQuery OnDirLandQuery; | ||
230 | public event DirPopularQuery OnDirPopularQuery; | ||
231 | public event DirClassifiedQuery OnDirClassifiedQuery; | ||
232 | public event EventInfoRequest OnEventInfoRequest; | ||
233 | public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime; | ||
234 | public event MapItemRequest OnMapItemRequest; | ||
235 | public event OfferCallingCard OnOfferCallingCard; | ||
236 | public event AcceptCallingCard OnAcceptCallingCard; | ||
237 | public event DeclineCallingCard OnDeclineCallingCard; | ||
238 | public event SoundTrigger OnSoundTrigger; | ||
239 | public event StartLure OnStartLure; | ||
240 | public event TeleportLureRequest OnTeleportLureRequest; | ||
241 | public event NetworkStats OnNetworkStatsUpdate; | ||
242 | public event ClassifiedInfoRequest OnClassifiedInfoRequest; | ||
243 | public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; | ||
244 | public event ClassifiedDelete OnClassifiedDelete; | ||
245 | public event ClassifiedDelete OnClassifiedGodDelete; | ||
246 | public event EventNotificationAddRequest OnEventNotificationAddRequest; | ||
247 | public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; | ||
248 | public event EventGodDelete OnEventGodDelete; | ||
249 | public event ParcelDwellRequest OnParcelDwellRequest; | ||
250 | public event UserInfoRequest OnUserInfoRequest; | ||
251 | public event UpdateUserInfo OnUpdateUserInfo; | ||
252 | public event RetrieveInstantMessages OnRetrieveInstantMessages; | ||
253 | public event PickDelete OnPickDelete; | ||
254 | public event PickGodDelete OnPickGodDelete; | ||
255 | public event PickInfoUpdate OnPickInfoUpdate; | ||
256 | public event AvatarNotesUpdate OnAvatarNotesUpdate; | ||
257 | public event MuteListRequest OnMuteListRequest; | ||
258 | public event AvatarInterestUpdate OnAvatarInterestUpdate; | ||
259 | public event PlacesQuery OnPlacesQuery; | ||
260 | |||
261 | #endregion Events | ||
262 | |||
263 | #region Class Members | ||
264 | |||
62 | // LLClientView Only | 265 | // LLClientView Only |
63 | public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args); | 266 | public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args); |
64 | 267 | ||
@@ -115,13 +318,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
115 | protected int m_textureDataLimit = 10; | 318 | protected int m_textureDataLimit = 10; |
116 | protected int m_avatarTerseUpdateRate = 50; | 319 | protected int m_avatarTerseUpdateRate = 50; |
117 | protected int m_avatarTerseUpdatesPerPacket = 5; | 320 | protected int m_avatarTerseUpdatesPerPacket = 5; |
118 | protected int m_packetMTU = 1400; | ||
119 | protected IAssetService m_assetService; | 321 | protected IAssetService m_assetService; |
120 | private IHyperAssetService m_hyperAssets; | 322 | private IHyperAssetService m_hyperAssets; |
121 | 323 | ||
122 | 324 | ||
325 | #endregion Class Members | ||
326 | |||
123 | #region Properties | 327 | #region Properties |
124 | 328 | ||
329 | public LLUDPClient UDPClient { get { return m_udpClient; } } | ||
330 | public IPEndPoint RemoteEndPoint { get { return m_udpClient.RemoteEndPoint; } } | ||
125 | public UUID SecureSessionId { get { return m_secureSessionId; } } | 331 | public UUID SecureSessionId { get { return m_secureSessionId; } } |
126 | public IScene Scene { get { return m_scene; } } | 332 | public IScene Scene { get { return m_scene; } } |
127 | public UUID SessionId { get { return m_sessionId; } } | 333 | public UUID SessionId { get { return m_sessionId; } } |
@@ -202,51 +408,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
202 | #region Client Methods | 408 | #region Client Methods |
203 | 409 | ||
204 | /// <summary> | 410 | /// <summary> |
205 | /// Close down the client view. This *must* be the last method called, since the last # | 411 | /// Shut down the client view |
206 | /// statement of CloseCleanup() aborts the thread. | ||
207 | /// </summary> | 412 | /// </summary> |
208 | /// <param name="shutdownCircuit"></param> | 413 | public void Close() |
209 | public void Close(bool shutdownCircuit) | ||
210 | { | 414 | { |
211 | m_log.DebugFormat( | 415 | m_log.DebugFormat( |
212 | "[CLIENT]: Close has been called with shutdownCircuit = {0} for {1} attached to scene {2}", | 416 | "[CLIENT]: Close has been called for {0} attached to scene {1}", |
213 | shutdownCircuit, Name, m_scene.RegionInfo.RegionName); | 417 | Name, m_scene.RegionInfo.RegionName); |
214 | 418 | ||
419 | // Send the STOP packet | ||
420 | DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); | ||
421 | OutPacket(disable, ThrottleOutPacketType.Unknown); | ||
422 | |||
423 | IsActive = false; | ||
424 | |||
425 | // Shutdown the image manager | ||
215 | if (m_imageManager != null) | 426 | if (m_imageManager != null) |
216 | m_imageManager.Close(); | 427 | m_imageManager.Close(); |
217 | 428 | ||
429 | // Fire the callback for this connection closing | ||
430 | if (OnConnectionClosed != null) | ||
431 | OnConnectionClosed(this); | ||
432 | |||
433 | // Flush all of the packets out of the UDP server for this client | ||
218 | if (m_udpServer != null) | 434 | if (m_udpServer != null) |
219 | m_udpServer.Flush(); | 435 | m_udpServer.Flush(m_udpClient); |
220 | |||
221 | // raise an event on the packet server to Shutdown the circuit | ||
222 | // Now, if we raise the event then the packet server will call this method itself, so don't try cleanup | ||
223 | // here otherwise we'll end up calling it twice. | ||
224 | // FIXME: In truth, I might be wrong but this whole business of calling this method twice (with different args) looks | ||
225 | // horribly tangly. Hopefully it should be possible to greatly simplify it. | ||
226 | if (shutdownCircuit) | ||
227 | { | ||
228 | if (OnConnectionClosed != null) | ||
229 | OnConnectionClosed(this); | ||
230 | } | ||
231 | else | ||
232 | { | ||
233 | CloseCleanup(shutdownCircuit); | ||
234 | } | ||
235 | } | ||
236 | 436 | ||
237 | private void CloseCleanup(bool shutdownCircuit) | 437 | // Remove ourselves from the scene |
238 | { | ||
239 | m_scene.RemoveClient(AgentId); | 438 | m_scene.RemoveClient(AgentId); |
240 | 439 | ||
241 | //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); | ||
242 | //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true)); | ||
243 | |||
244 | // Send the STOP packet | ||
245 | DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); | ||
246 | OutPacket(disable, ThrottleOutPacketType.Unknown); | ||
247 | |||
248 | Thread.Sleep(2000); | ||
249 | |||
250 | // Shut down timers. Thread Context of this method is murky. Lock all timers | 440 | // Shut down timers. Thread Context of this method is murky. Lock all timers |
251 | if (m_avatarTerseUpdateTimer.Enabled) | 441 | if (m_avatarTerseUpdateTimer.Enabled) |
252 | lock (m_avatarTerseUpdateTimer) | 442 | lock (m_avatarTerseUpdateTimer) |
@@ -258,43 +448,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
258 | lock (m_primFullUpdateTimer) | 448 | lock (m_primFullUpdateTimer) |
259 | m_primFullUpdateTimer.Stop(); | 449 | m_primFullUpdateTimer.Stop(); |
260 | 450 | ||
261 | // This is just to give the client a reasonable chance of | ||
262 | // flushing out all it's packets. There should probably | ||
263 | // be a better mechanism here | ||
264 | |||
265 | // We can't reach into other scenes and close the connection | 451 | // We can't reach into other scenes and close the connection |
266 | // We need to do this over grid communications | 452 | // We need to do this over grid communications |
267 | //m_scene.CloseAllAgents(CircuitCode); | 453 | //m_scene.CloseAllAgents(CircuitCode); |
268 | 454 | ||
269 | // If we're not shutting down the circuit, then this is the last time we'll go here. | 455 | m_avatarTerseUpdateTimer.Dispose(); |
270 | // If we are shutting down the circuit, the UDP Server will come back here with | 456 | m_primTerseUpdateTimer.Dispose(); |
271 | // ShutDownCircuit = false | 457 | m_primFullUpdateTimer.Dispose(); |
272 | if (!(shutdownCircuit)) | ||
273 | { | ||
274 | GC.Collect(); | ||
275 | m_imageManager = null; | ||
276 | // Sends a KillPacket object, with which, the | ||
277 | // blockingqueue dequeues and sees it's a killpacket | ||
278 | // and terminates within the context of the client thread. | ||
279 | // This ensures that it's done from within the context | ||
280 | // of the client thread regardless of where Close() is called. | ||
281 | KillEndDone(); | ||
282 | } | ||
283 | |||
284 | IsActive = false; | ||
285 | |||
286 | m_avatarTerseUpdateTimer.Close(); | ||
287 | m_primTerseUpdateTimer.Close(); | ||
288 | m_primFullUpdateTimer.Close(); | ||
289 | 458 | ||
290 | //m_udpServer.OnPacketStats -= PopulateStats; | 459 | // Disable UDP handling for this client |
291 | m_udpClient.Shutdown(); | 460 | m_udpClient.Shutdown(); |
292 | 461 | ||
293 | // wait for thread stoped | 462 | //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); |
294 | // m_clientThread.Join(); | 463 | //GC.Collect(); |
295 | 464 | //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true)); | |
296 | // delete circuit code | ||
297 | //m_networkServer.CloseClient(this); | ||
298 | } | 465 | } |
299 | 466 | ||
300 | public void Kick(string message) | 467 | public void Kick(string message) |
@@ -416,43 +583,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
416 | return result; | 583 | return result; |
417 | } | 584 | } |
418 | 585 | ||
419 | /*protected void DebugPacket(string direction, Packet packet) | ||
420 | { | ||
421 | string info; | ||
422 | |||
423 | if (m_debugPacketLevel < 255 && packet.Type == PacketType.AgentUpdate) | ||
424 | return; | ||
425 | if (m_debugPacketLevel < 254 && packet.Type == PacketType.ViewerEffect) | ||
426 | return; | ||
427 | if (m_debugPacketLevel < 253 && ( | ||
428 | packet.Type == PacketType.CompletePingCheck || | ||
429 | packet.Type == PacketType.StartPingCheck | ||
430 | )) | ||
431 | return; | ||
432 | if (m_debugPacketLevel < 252 && packet.Type == PacketType.PacketAck) | ||
433 | return; | ||
434 | |||
435 | if (m_debugPacketLevel > 1) | ||
436 | { | ||
437 | info = packet.ToString(); | ||
438 | } | ||
439 | else | ||
440 | { | ||
441 | info = packet.Type.ToString(); | ||
442 | } | ||
443 | |||
444 | Console.WriteLine(m_circuitCode + ":" + direction + ": " + info); | ||
445 | }*/ | ||
446 | |||
447 | #endregion Packet Handling | 586 | #endregion Packet Handling |
448 | 587 | ||
449 | # region Setup | 588 | # region Setup |
450 | 589 | ||
451 | /// <summary> | 590 | public virtual void Start() |
452 | /// Starts up the timers to check the client and resend unacked packets | ||
453 | /// Adds the client to the OpenSim.Region.Framework.Scenes.Scene | ||
454 | /// </summary> | ||
455 | protected virtual void InitNewClient() | ||
456 | { | 591 | { |
457 | m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); | 592 | m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); |
458 | m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); | 593 | m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); |
@@ -471,262 +606,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
471 | RefreshGroupMembership(); | 606 | RefreshGroupMembership(); |
472 | } | 607 | } |
473 | 608 | ||
474 | public virtual void Start() | ||
475 | { | ||
476 | // This sets up all the timers | ||
477 | InitNewClient(); | ||
478 | } | ||
479 | |||
480 | /// <summary> | ||
481 | /// Run a user session. This method lies at the base of the entire client thread. | ||
482 | /// </summary> | ||
483 | protected void RunUserSession() | ||
484 | { | ||
485 | try | ||
486 | { | ||
487 | |||
488 | } | ||
489 | catch (Exception e) | ||
490 | { | ||
491 | if (e is ThreadAbortException) | ||
492 | throw; | ||
493 | |||
494 | if (StatsManager.SimExtraStats != null) | ||
495 | StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); | ||
496 | |||
497 | // Don't let a failure in an individual client thread crash the whole sim. | ||
498 | m_log.ErrorFormat( | ||
499 | "[CLIENT]: Client thread for {0} {1} crashed. Logging them out.", Name, AgentId); | ||
500 | m_log.Error(e.ToString()); | ||
501 | |||
502 | try | ||
503 | { | ||
504 | // Make an attempt to alert the user that their session has crashed | ||
505 | AgentAlertMessagePacket packet | ||
506 | = BuildAgentAlertPacket( | ||
507 | "Unfortunately the session for this client on the server has crashed.\n" | ||
508 | + "Any further actions taken will not be processed.\n" | ||
509 | + "Please relog", true); | ||
510 | |||
511 | m_udpServer.SendPacket(m_agentId, packet, ThrottleOutPacketType.Unknown, false); | ||
512 | |||
513 | // There may be a better way to do this. Perhaps kick? Not sure this propogates notifications to | ||
514 | // listeners yet, though. | ||
515 | Logout(this); | ||
516 | } | ||
517 | catch (Exception e2) | ||
518 | { | ||
519 | if (e2 is ThreadAbortException) | ||
520 | throw; | ||
521 | |||
522 | m_log.ErrorFormat("[CLIENT]: Further exception thrown on forced session logout. {0}", e2); | ||
523 | } | ||
524 | } | ||
525 | } | ||
526 | |||
527 | # endregion | 609 | # endregion |
528 | 610 | ||
529 | #region Events | ||
530 | |||
531 | public event GenericMessage OnGenericMessage; | ||
532 | public event BinaryGenericMessage OnBinaryGenericMessage; | ||
533 | public event Action<IClientAPI> OnLogout; | ||
534 | public event ObjectPermissions OnObjectPermissions; | ||
535 | public event Action<IClientAPI> OnConnectionClosed; | ||
536 | public event ViewerEffectEventHandler OnViewerEffect; | ||
537 | public event ImprovedInstantMessage OnInstantMessage; | ||
538 | public event ChatMessage OnChatFromClient; | ||
539 | public event TextureRequest OnRequestTexture; | ||
540 | public event RezObject OnRezObject; | ||
541 | public event DeRezObject OnDeRezObject; | ||
542 | public event ModifyTerrain OnModifyTerrain; | ||
543 | public event Action<IClientAPI> OnRegionHandShakeReply; | ||
544 | public event GenericCall2 OnRequestWearables; | ||
545 | public event SetAppearance OnSetAppearance; | ||
546 | public event AvatarNowWearing OnAvatarNowWearing; | ||
547 | public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; | ||
548 | public event RezMultipleAttachmentsFromInv OnRezMultipleAttachmentsFromInv; | ||
549 | public event UUIDNameRequest OnDetachAttachmentIntoInv; | ||
550 | public event ObjectAttach OnObjectAttach; | ||
551 | public event ObjectDeselect OnObjectDetach; | ||
552 | public event ObjectDrop OnObjectDrop; | ||
553 | public event GenericCall2 OnCompleteMovementToRegion; | ||
554 | public event UpdateAgent OnAgentUpdate; | ||
555 | public event AgentRequestSit OnAgentRequestSit; | ||
556 | public event AgentSit OnAgentSit; | ||
557 | public event AvatarPickerRequest OnAvatarPickerRequest; | ||
558 | public event StartAnim OnStartAnim; | ||
559 | public event StopAnim OnStopAnim; | ||
560 | public event Action<IClientAPI> OnRequestAvatarsData; | ||
561 | public event LinkObjects OnLinkObjects; | ||
562 | public event DelinkObjects OnDelinkObjects; | ||
563 | public event GrabObject OnGrabObject; | ||
564 | public event DeGrabObject OnDeGrabObject; | ||
565 | public event SpinStart OnSpinStart; | ||
566 | public event SpinStop OnSpinStop; | ||
567 | public event ObjectDuplicate OnObjectDuplicate; | ||
568 | public event ObjectDuplicateOnRay OnObjectDuplicateOnRay; | ||
569 | public event MoveObject OnGrabUpdate; | ||
570 | public event SpinObject OnSpinUpdate; | ||
571 | public event AddNewPrim OnAddPrim; | ||
572 | public event RequestGodlikePowers OnRequestGodlikePowers; | ||
573 | public event GodKickUser OnGodKickUser; | ||
574 | public event ObjectExtraParams OnUpdateExtraParams; | ||
575 | public event UpdateShape OnUpdatePrimShape; | ||
576 | public event ObjectRequest OnObjectRequest; | ||
577 | public event ObjectSelect OnObjectSelect; | ||
578 | public event ObjectDeselect OnObjectDeselect; | ||
579 | public event GenericCall7 OnObjectDescription; | ||
580 | public event GenericCall7 OnObjectName; | ||
581 | public event GenericCall7 OnObjectClickAction; | ||
582 | public event GenericCall7 OnObjectMaterial; | ||
583 | public event ObjectIncludeInSearch OnObjectIncludeInSearch; | ||
584 | public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; | ||
585 | public event UpdatePrimFlags OnUpdatePrimFlags; | ||
586 | public event UpdatePrimTexture OnUpdatePrimTexture; | ||
587 | public event UpdateVector OnUpdatePrimGroupPosition; | ||
588 | public event UpdateVector OnUpdatePrimSinglePosition; | ||
589 | public event UpdatePrimRotation OnUpdatePrimGroupRotation; | ||
590 | public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation; | ||
591 | public event UpdatePrimSingleRotationPosition OnUpdatePrimSingleRotationPosition; | ||
592 | public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation; | ||
593 | public event UpdateVector OnUpdatePrimScale; | ||
594 | public event UpdateVector OnUpdatePrimGroupScale; | ||
595 | public event StatusChange OnChildAgentStatus; | ||
596 | public event GenericCall2 OnStopMovement; | ||
597 | public event Action<UUID> OnRemoveAvatar; | ||
598 | public event RequestMapBlocks OnRequestMapBlocks; | ||
599 | public event RequestMapName OnMapNameRequest; | ||
600 | public event TeleportLocationRequest OnTeleportLocationRequest; | ||
601 | public event TeleportLandmarkRequest OnTeleportLandmarkRequest; | ||
602 | public event DisconnectUser OnDisconnectUser; | ||
603 | public event RequestAvatarProperties OnRequestAvatarProperties; | ||
604 | public event SetAlwaysRun OnSetAlwaysRun; | ||
605 | public event FetchInventory OnAgentDataUpdateRequest; | ||
606 | public event TeleportLocationRequest OnSetStartLocationRequest; | ||
607 | public event UpdateAvatarProperties OnUpdateAvatarProperties; | ||
608 | public event CreateNewInventoryItem OnCreateNewInventoryItem; | ||
609 | public event CreateInventoryFolder OnCreateNewInventoryFolder; | ||
610 | public event UpdateInventoryFolder OnUpdateInventoryFolder; | ||
611 | public event MoveInventoryFolder OnMoveInventoryFolder; | ||
612 | public event FetchInventoryDescendents OnFetchInventoryDescendents; | ||
613 | public event PurgeInventoryDescendents OnPurgeInventoryDescendents; | ||
614 | public event FetchInventory OnFetchInventory; | ||
615 | public event RequestTaskInventory OnRequestTaskInventory; | ||
616 | public event UpdateInventoryItem OnUpdateInventoryItem; | ||
617 | public event CopyInventoryItem OnCopyInventoryItem; | ||
618 | public event MoveInventoryItem OnMoveInventoryItem; | ||
619 | public event RemoveInventoryItem OnRemoveInventoryItem; | ||
620 | public event RemoveInventoryFolder OnRemoveInventoryFolder; | ||
621 | public event UDPAssetUploadRequest OnAssetUploadRequest; | ||
622 | public event XferReceive OnXferReceive; | ||
623 | public event RequestXfer OnRequestXfer; | ||
624 | public event ConfirmXfer OnConfirmXfer; | ||
625 | public event AbortXfer OnAbortXfer; | ||
626 | public event RequestTerrain OnRequestTerrain; | ||
627 | public event RezScript OnRezScript; | ||
628 | public event UpdateTaskInventory OnUpdateTaskInventory; | ||
629 | public event MoveTaskInventory OnMoveTaskItem; | ||
630 | public event RemoveTaskInventory OnRemoveTaskItem; | ||
631 | public event RequestAsset OnRequestAsset; | ||
632 | public event UUIDNameRequest OnNameFromUUIDRequest; | ||
633 | public event ParcelAccessListRequest OnParcelAccessListRequest; | ||
634 | public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest; | ||
635 | public event ParcelPropertiesRequest OnParcelPropertiesRequest; | ||
636 | public event ParcelDivideRequest OnParcelDivideRequest; | ||
637 | public event ParcelJoinRequest OnParcelJoinRequest; | ||
638 | public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; | ||
639 | public event ParcelSelectObjects OnParcelSelectObjects; | ||
640 | public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest; | ||
641 | public event ParcelAbandonRequest OnParcelAbandonRequest; | ||
642 | public event ParcelGodForceOwner OnParcelGodForceOwner; | ||
643 | public event ParcelReclaim OnParcelReclaim; | ||
644 | public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest; | ||
645 | public event ParcelDeedToGroup OnParcelDeedToGroup; | ||
646 | public event RegionInfoRequest OnRegionInfoRequest; | ||
647 | public event EstateCovenantRequest OnEstateCovenantRequest; | ||
648 | public event FriendActionDelegate OnApproveFriendRequest; | ||
649 | public event FriendActionDelegate OnDenyFriendRequest; | ||
650 | public event FriendshipTermination OnTerminateFriendship; | ||
651 | public event MoneyTransferRequest OnMoneyTransferRequest; | ||
652 | public event EconomyDataRequest OnEconomyDataRequest; | ||
653 | public event MoneyBalanceRequest OnMoneyBalanceRequest; | ||
654 | public event ParcelBuy OnParcelBuy; | ||
655 | public event UUIDNameRequest OnTeleportHomeRequest; | ||
656 | public event UUIDNameRequest OnUUIDGroupNameRequest; | ||
657 | public event ScriptAnswer OnScriptAnswer; | ||
658 | public event RequestPayPrice OnRequestPayPrice; | ||
659 | public event ObjectSaleInfo OnObjectSaleInfo; | ||
660 | public event ObjectBuy OnObjectBuy; | ||
661 | public event BuyObjectInventory OnBuyObjectInventory; | ||
662 | public event AgentSit OnUndo; | ||
663 | public event ForceReleaseControls OnForceReleaseControls; | ||
664 | public event GodLandStatRequest OnLandStatRequest; | ||
665 | public event RequestObjectPropertiesFamily OnObjectGroupRequest; | ||
666 | public event DetailedEstateDataRequest OnDetailedEstateDataRequest; | ||
667 | public event SetEstateFlagsRequest OnSetEstateFlagsRequest; | ||
668 | public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture; | ||
669 | public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture; | ||
670 | public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights; | ||
671 | public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest; | ||
672 | public event SetRegionTerrainSettings OnSetRegionTerrainSettings; | ||
673 | public event BakeTerrain OnBakeTerrain; | ||
674 | public event RequestTerrain OnUploadTerrain; | ||
675 | public event EstateChangeInfo OnEstateChangeInfo; | ||
676 | public event EstateRestartSimRequest OnEstateRestartSimRequest; | ||
677 | public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest; | ||
678 | public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest; | ||
679 | public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest; | ||
680 | public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest; | ||
681 | public event EstateDebugRegionRequest OnEstateDebugRegionRequest; | ||
682 | public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest; | ||
683 | public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest; | ||
684 | public event RegionHandleRequest OnRegionHandleRequest; | ||
685 | public event ParcelInfoRequest OnParcelInfoRequest; | ||
686 | public event ScriptReset OnScriptReset; | ||
687 | public event GetScriptRunning OnGetScriptRunning; | ||
688 | public event SetScriptRunning OnSetScriptRunning; | ||
689 | public event UpdateVector OnAutoPilotGo; | ||
690 | public event TerrainUnacked OnUnackedTerrain; | ||
691 | public event ActivateGesture OnActivateGesture; | ||
692 | public event DeactivateGesture OnDeactivateGesture; | ||
693 | public event ObjectOwner OnObjectOwner; | ||
694 | public event DirPlacesQuery OnDirPlacesQuery; | ||
695 | public event DirFindQuery OnDirFindQuery; | ||
696 | public event DirLandQuery OnDirLandQuery; | ||
697 | public event DirPopularQuery OnDirPopularQuery; | ||
698 | public event DirClassifiedQuery OnDirClassifiedQuery; | ||
699 | public event EventInfoRequest OnEventInfoRequest; | ||
700 | public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime; | ||
701 | public event MapItemRequest OnMapItemRequest; | ||
702 | public event OfferCallingCard OnOfferCallingCard; | ||
703 | public event AcceptCallingCard OnAcceptCallingCard; | ||
704 | public event DeclineCallingCard OnDeclineCallingCard; | ||
705 | public event SoundTrigger OnSoundTrigger; | ||
706 | public event StartLure OnStartLure; | ||
707 | public event TeleportLureRequest OnTeleportLureRequest; | ||
708 | public event NetworkStats OnNetworkStatsUpdate; | ||
709 | public event ClassifiedInfoRequest OnClassifiedInfoRequest; | ||
710 | public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; | ||
711 | public event ClassifiedDelete OnClassifiedDelete; | ||
712 | public event ClassifiedDelete OnClassifiedGodDelete; | ||
713 | public event EventNotificationAddRequest OnEventNotificationAddRequest; | ||
714 | public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; | ||
715 | public event EventGodDelete OnEventGodDelete; | ||
716 | public event ParcelDwellRequest OnParcelDwellRequest; | ||
717 | public event UserInfoRequest OnUserInfoRequest; | ||
718 | public event UpdateUserInfo OnUpdateUserInfo; | ||
719 | public event RetrieveInstantMessages OnRetrieveInstantMessages; | ||
720 | public event PickDelete OnPickDelete; | ||
721 | public event PickGodDelete OnPickGodDelete; | ||
722 | public event PickInfoUpdate OnPickInfoUpdate; | ||
723 | public event AvatarNotesUpdate OnAvatarNotesUpdate; | ||
724 | public event MuteListRequest OnMuteListRequest; | ||
725 | public event AvatarInterestUpdate OnAvatarInterestUpdate; | ||
726 | public event PlacesQuery OnPlacesQuery; | ||
727 | |||
728 | #endregion Events | ||
729 | |||
730 | public void ActivateGesture(UUID assetId, UUID gestureId) | 611 | public void ActivateGesture(UUID assetId, UUID gestureId) |
731 | { | 612 | { |
732 | } | 613 | } |
@@ -1346,7 +1227,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1346 | kill.ObjectData[0].ID = localID; | 1227 | kill.ObjectData[0].ID = localID; |
1347 | kill.Header.Reliable = true; | 1228 | kill.Header.Reliable = true; |
1348 | kill.Header.Zerocoded = true; | 1229 | kill.Header.Zerocoded = true; |
1349 | OutPacket(kill, ThrottleOutPacketType.Task); | 1230 | OutPacket(kill, ThrottleOutPacketType.State); |
1350 | } | 1231 | } |
1351 | 1232 | ||
1352 | /// <summary> | 1233 | /// <summary> |
@@ -1940,7 +1821,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1940 | sendXfer.XferID.ID = xferID; | 1821 | sendXfer.XferID.ID = xferID; |
1941 | sendXfer.XferID.Packet = packet; | 1822 | sendXfer.XferID.Packet = packet; |
1942 | sendXfer.DataPacket.Data = data; | 1823 | sendXfer.DataPacket.Data = data; |
1943 | OutPacket(sendXfer, ThrottleOutPacketType.Task); | 1824 | OutPacket(sendXfer, ThrottleOutPacketType.Asset); |
1944 | } | 1825 | } |
1945 | 1826 | ||
1946 | public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, | 1827 | public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, |
@@ -2222,7 +2103,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2222 | packet.AgentData.SessionID = SessionId; | 2103 | packet.AgentData.SessionID = SessionId; |
2223 | packet.Header.Reliable = false; | 2104 | packet.Header.Reliable = false; |
2224 | packet.Header.Zerocoded = true; | 2105 | packet.Header.Zerocoded = true; |
2225 | OutPacket(packet, ThrottleOutPacketType.Task); | 2106 | OutPacket(packet, ThrottleOutPacketType.State); |
2226 | } | 2107 | } |
2227 | 2108 | ||
2228 | public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, | 2109 | public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, |
@@ -3245,7 +3126,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3245 | 3126 | ||
3246 | avp.Sender.IsTrial = false; | 3127 | avp.Sender.IsTrial = false; |
3247 | avp.Sender.ID = agentID; | 3128 | avp.Sender.ID = agentID; |
3248 | OutPacket(avp, ThrottleOutPacketType.Task); | 3129 | OutPacket(avp, ThrottleOutPacketType.State); |
3249 | } | 3130 | } |
3250 | 3131 | ||
3251 | public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) | 3132 | public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) |
@@ -3370,7 +3251,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3370 | int length = 0; | 3251 | int length = 0; |
3371 | m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length); | 3252 | m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length); |
3372 | length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); | 3253 | length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); |
3373 | if (size + length > m_packetMTU) | 3254 | if (size + length > Packet.MTU) |
3374 | break; | 3255 | break; |
3375 | size += length; | 3256 | size += length; |
3376 | } | 3257 | } |
@@ -3385,6 +3266,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3385 | 3266 | ||
3386 | terse.Header.Reliable = false; | 3267 | terse.Header.Reliable = false; |
3387 | terse.Header.Zerocoded = true; | 3268 | terse.Header.Zerocoded = true; |
3269 | // FIXME: Move this to ThrottleOutPacketType.State when the real prioritization code is committed | ||
3388 | OutPacket(terse, ThrottleOutPacketType.Task); | 3270 | OutPacket(terse, ThrottleOutPacketType.Task); |
3389 | 3271 | ||
3390 | if (m_avatarTerseUpdates.Count == 0) | 3272 | if (m_avatarTerseUpdates.Count == 0) |
@@ -3614,7 +3496,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3614 | int length = 0; | 3496 | int length = 0; |
3615 | m_primFullUpdates[count].ToBytes(blockbuffer, ref length); | 3497 | m_primFullUpdates[count].ToBytes(blockbuffer, ref length); |
3616 | length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); | 3498 | length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); |
3617 | if (size + length > m_packetMTU) | 3499 | if (size + length > Packet.MTU) |
3618 | break; | 3500 | break; |
3619 | size += length; | 3501 | size += length; |
3620 | } | 3502 | } |
@@ -3629,7 +3511,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3629 | } | 3511 | } |
3630 | 3512 | ||
3631 | outPacket.Header.Zerocoded = true; | 3513 | outPacket.Header.Zerocoded = true; |
3632 | OutPacket(outPacket, ThrottleOutPacketType.Task); | 3514 | OutPacket(outPacket, ThrottleOutPacketType.State); |
3633 | 3515 | ||
3634 | if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) | 3516 | if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) |
3635 | lock (m_primFullUpdateTimer) | 3517 | lock (m_primFullUpdateTimer) |
@@ -3702,7 +3584,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3702 | int length = 0; | 3584 | int length = 0; |
3703 | m_primTerseUpdates[count].ToBytes(blockbuffer, ref length); | 3585 | m_primTerseUpdates[count].ToBytes(blockbuffer, ref length); |
3704 | length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); | 3586 | length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); |
3705 | if (size + length > m_packetMTU) | 3587 | if (size + length > Packet.MTU) |
3706 | break; | 3588 | break; |
3707 | size += length; | 3589 | size += length; |
3708 | } | 3590 | } |
@@ -3719,7 +3601,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3719 | 3601 | ||
3720 | outPacket.Header.Reliable = false; | 3602 | outPacket.Header.Reliable = false; |
3721 | outPacket.Header.Zerocoded = true; | 3603 | outPacket.Header.Zerocoded = true; |
3722 | OutPacket(outPacket, ThrottleOutPacketType.Task); | 3604 | OutPacket(outPacket, ThrottleOutPacketType.State); |
3723 | 3605 | ||
3724 | if (m_primTerseUpdates.Count == 0) | 3606 | if (m_primTerseUpdates.Count == 0) |
3725 | lock (m_primTerseUpdateTimer) | 3607 | lock (m_primTerseUpdateTimer) |
@@ -4805,7 +4687,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4805 | 4687 | ||
4806 | public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack) | 4688 | public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack) |
4807 | { | 4689 | { |
4808 | |||
4809 | ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack; | 4690 | ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack; |
4810 | if (ogpack.AgentData.SessionID != SessionId) return false; | 4691 | if (ogpack.AgentData.SessionID != SessionId) return false; |
4811 | 4692 | ||
@@ -10252,7 +10133,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
10252 | 10133 | ||
10253 | public void KillEndDone() | 10134 | public void KillEndDone() |
10254 | { | 10135 | { |
10255 | m_udpClient.Shutdown(); | ||
10256 | } | 10136 | } |
10257 | 10137 | ||
10258 | #region IClientCore | 10138 | #region IClientCore |
@@ -10295,15 +10175,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
10295 | { | 10175 | { |
10296 | Kick(reason); | 10176 | Kick(reason); |
10297 | Thread.Sleep(1000); | 10177 | Thread.Sleep(1000); |
10298 | Close(true); | 10178 | Close(); |
10299 | } | 10179 | } |
10300 | 10180 | ||
10301 | public void Disconnect() | 10181 | public void Disconnect() |
10302 | { | 10182 | { |
10303 | Close(true); | 10183 | Close(); |
10304 | } | 10184 | } |
10305 | 10185 | ||
10306 | |||
10307 | #endregion | 10186 | #endregion |
10308 | 10187 | ||
10309 | public void RefreshGroupMembership() | 10188 | public void RefreshGroupMembership() |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs index 56d34e6..681562b 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs | |||
@@ -172,39 +172,39 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
172 | J2KImage imagereq; | 172 | J2KImage imagereq; |
173 | int numCollected = 0; | 173 | int numCollected = 0; |
174 | 174 | ||
175 | //lock (m_syncRoot) | 175 | m_lastloopprocessed = DateTime.Now.Ticks; |
176 | //{ | 176 | |
177 | m_lastloopprocessed = DateTime.Now.Ticks; | 177 | // This can happen during Close() |
178 | 178 | if (m_client == null) | |
179 | // This can happen during Close() | 179 | return false; |
180 | if (m_client == null) | 180 | |
181 | return false; | 181 | while ((imagereq = GetHighestPriorityImage()) != null) |
182 | 182 | { | |
183 | while ((imagereq = GetHighestPriorityImage()) != null) | 183 | if (imagereq.IsDecoded == true) |
184 | { | 184 | { |
185 | if (imagereq.IsDecoded == true) | 185 | ++numCollected; |
186 | { | ||
187 | ++numCollected; | ||
188 | 186 | ||
189 | if (imagereq.SendPackets(m_client, maxpack)) | 187 | if (imagereq.SendPackets(m_client, maxpack)) |
190 | { | 188 | { |
191 | // Send complete. Destroy any knowledge of this transfer | 189 | // Send complete. Destroy any knowledge of this transfer |
192 | RemoveImageFromQueue(imagereq); | 190 | RemoveImageFromQueue(imagereq); |
193 | } | ||
194 | } | 191 | } |
195 | |||
196 | if (numCollected == count) | ||
197 | break; | ||
198 | } | 192 | } |
199 | //} | 193 | |
194 | if (numCollected == count) | ||
195 | break; | ||
196 | } | ||
200 | 197 | ||
201 | return m_priorityQueue.Count > 0; | 198 | return m_priorityQueue.Count > 0; |
202 | } | 199 | } |
203 | 200 | ||
204 | //Faux destructor | 201 | /// <summary> |
202 | /// Faux destructor | ||
203 | /// </summary> | ||
205 | public void Close() | 204 | public void Close() |
206 | { | 205 | { |
207 | m_shuttingdown = true; | 206 | m_shuttingdown = true; |
207 | m_priorityQueue = null; | ||
208 | m_j2kDecodeModule = null; | 208 | m_j2kDecodeModule = null; |
209 | m_assetCache = null; | 209 | m_assetCache = null; |
210 | m_client = null; | 210 | m_client = null; |
@@ -218,13 +218,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
218 | 218 | ||
219 | lock (m_syncRoot) | 219 | lock (m_syncRoot) |
220 | { | 220 | { |
221 | |||
222 | if (m_priorityQueue.Count > 0) | 221 | if (m_priorityQueue.Count > 0) |
223 | { | 222 | { |
224 | try | 223 | try { image = m_priorityQueue.FindMax(); } |
225 | { | ||
226 | image = m_priorityQueue.FindMax(); | ||
227 | } | ||
228 | catch (Exception) { } | 224 | catch (Exception) { } |
229 | } | 225 | } |
230 | } | 226 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index 871e8e8..e7707a9 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs | |||
@@ -59,9 +59,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
59 | /// </summary> | 59 | /// </summary> |
60 | public sealed class LLUDPClient | 60 | public sealed class LLUDPClient |
61 | { | 61 | { |
62 | // FIXME: Make this a config setting | ||
63 | /// <summary>Percentage of the task throttle category that is allocated to avatar and prim | ||
64 | /// state updates</summary> | ||
65 | const float STATE_TASK_PERCENTAGE = 0.8f; | ||
66 | |||
62 | /// <summary>The number of packet categories to throttle on. If a throttle category is added | 67 | /// <summary>The number of packet categories to throttle on. If a throttle category is added |
63 | /// or removed, this number must also change</summary> | 68 | /// or removed, this number must also change</summary> |
64 | const int THROTTLE_CATEGORY_COUNT = 7; | 69 | const int THROTTLE_CATEGORY_COUNT = 8; |
65 | 70 | ||
66 | /// <summary>Fired when updated networking stats are produced for this client</summary> | 71 | /// <summary>Fired when updated networking stats are produced for this client</summary> |
67 | public event PacketStats OnPacketStats; | 72 | public event PacketStats OnPacketStats; |
@@ -80,10 +85,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
80 | /// <summary>Packets we have sent that need to be ACKed by the client</summary> | 85 | /// <summary>Packets we have sent that need to be ACKed by the client</summary> |
81 | public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); | 86 | public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); |
82 | /// <summary>ACKs that are queued up, waiting to be sent to the client</summary> | 87 | /// <summary>ACKs that are queued up, waiting to be sent to the client</summary> |
83 | public readonly LocklessQueue<uint> PendingAcks = new LocklessQueue<uint>(); | 88 | public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>(); |
84 | 89 | ||
85 | /// <summary>Reference to the IClientAPI for this client</summary> | ||
86 | public LLClientView ClientAPI; | ||
87 | /// <summary>Current packet sequence number</summary> | 90 | /// <summary>Current packet sequence number</summary> |
88 | public int CurrentSequence; | 91 | public int CurrentSequence; |
89 | /// <summary>Current ping sequence number</summary> | 92 | /// <summary>Current ping sequence number</summary> |
@@ -129,7 +132,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
129 | /// <summary>Throttle rate defaults and limits</summary> | 132 | /// <summary>Throttle rate defaults and limits</summary> |
130 | private readonly ThrottleRates defaultThrottleRates; | 133 | private readonly ThrottleRates defaultThrottleRates; |
131 | /// <summary>Outgoing queues for throttled packets</summary> | 134 | /// <summary>Outgoing queues for throttled packets</summary> |
132 | private readonly LocklessQueue<OutgoingPacket>[] packetOutboxes = new LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT]; | 135 | private readonly OpenSim.Framework.LocklessQueue<OutgoingPacket>[] packetOutboxes = new OpenSim.Framework.LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT]; |
133 | /// <summary>A container that can hold one packet for each outbox, used to store | 136 | /// <summary>A container that can hold one packet for each outbox, used to store |
134 | /// dequeued packets that are being held for throttling</summary> | 137 | /// dequeued packets that are being held for throttling</summary> |
135 | private readonly OutgoingPacket[] nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; | 138 | private readonly OutgoingPacket[] nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; |
@@ -158,7 +161,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
158 | defaultThrottleRates = rates; | 161 | defaultThrottleRates = rates; |
159 | 162 | ||
160 | for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) | 163 | for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) |
161 | packetOutboxes[i] = new LocklessQueue<OutgoingPacket>(); | 164 | packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); |
162 | 165 | ||
163 | throttle = new TokenBucket(parentThrottle, 0, 0); | 166 | throttle = new TokenBucket(parentThrottle, 0, 0); |
164 | throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; | 167 | throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; |
@@ -166,9 +169,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
166 | throttleCategories[(int)ThrottleOutPacketType.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land); | 169 | throttleCategories[(int)ThrottleOutPacketType.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land); |
167 | throttleCategories[(int)ThrottleOutPacketType.Wind] = new TokenBucket(throttle, rates.WindLimit, rates.Wind); | 170 | throttleCategories[(int)ThrottleOutPacketType.Wind] = new TokenBucket(throttle, rates.WindLimit, rates.Wind); |
168 | throttleCategories[(int)ThrottleOutPacketType.Cloud] = new TokenBucket(throttle, rates.CloudLimit, rates.Cloud); | 171 | throttleCategories[(int)ThrottleOutPacketType.Cloud] = new TokenBucket(throttle, rates.CloudLimit, rates.Cloud); |
169 | throttleCategories[(int)ThrottleOutPacketType.Task] = new TokenBucket(throttle, rates.TaskLimit, rates.Task); | ||
170 | throttleCategories[(int)ThrottleOutPacketType.Texture] = new TokenBucket(throttle, rates.TextureLimit, rates.Texture); | 172 | throttleCategories[(int)ThrottleOutPacketType.Texture] = new TokenBucket(throttle, rates.TextureLimit, rates.Texture); |
171 | throttleCategories[(int)ThrottleOutPacketType.Asset] = new TokenBucket(throttle, rates.AssetLimit, rates.Asset); | 173 | throttleCategories[(int)ThrottleOutPacketType.Asset] = new TokenBucket(throttle, rates.AssetLimit, rates.Asset); |
174 | // State and Transaction are actually sub-categories of the LLUDP generic "Task" category | ||
175 | TokenBucket stateBucket = new TokenBucket(throttle, (int)((float)rates.TaskLimit * STATE_TASK_PERCENTAGE), (int)((float)rates.Task * STATE_TASK_PERCENTAGE)); | ||
176 | throttleCategories[(int)ThrottleOutPacketType.State] = stateBucket; | ||
177 | throttleCategories[(int)ThrottleOutPacketType.Task] = new TokenBucket(throttle, rates.TaskLimit - stateBucket.MaxBurst, rates.Task - stateBucket.DripRate); | ||
172 | 178 | ||
173 | // Set the granularity variable used for retransmission calculations to | 179 | // Set the granularity variable used for retransmission calculations to |
174 | // the measured resolution of Environment.TickCount | 180 | // the measured resolution of Environment.TickCount |
@@ -176,6 +182,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
176 | 182 | ||
177 | // Default the retransmission timeout to three seconds | 183 | // Default the retransmission timeout to three seconds |
178 | RTO = 3000; | 184 | RTO = 3000; |
185 | |||
186 | // Initialize this to a sane value to prevent early disconnects | ||
187 | TickLastPacketReceived = Environment.TickCount; | ||
179 | } | 188 | } |
180 | 189 | ||
181 | /// <summary> | 190 | /// <summary> |
@@ -183,8 +192,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
183 | /// </summary> | 192 | /// </summary> |
184 | public void Shutdown() | 193 | public void Shutdown() |
185 | { | 194 | { |
186 | // TODO: Do we need to invalidate the circuit? | ||
187 | IsConnected = false; | 195 | IsConnected = false; |
196 | NeedAcks.Clear(); | ||
197 | for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) | ||
198 | { | ||
199 | packetOutboxes[i].Clear(); | ||
200 | nextPackets[i] = null; | ||
201 | } | ||
202 | OnPacketStats = null; | ||
203 | OnQueueEmpty = null; | ||
188 | } | 204 | } |
189 | 205 | ||
190 | /// <summary> | 206 | /// <summary> |
@@ -204,7 +220,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
204 | info.landThrottle = throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; | 220 | info.landThrottle = throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; |
205 | info.windThrottle = throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; | 221 | info.windThrottle = throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; |
206 | info.cloudThrottle = throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; | 222 | info.cloudThrottle = throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; |
207 | info.taskThrottle = throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; | 223 | info.taskThrottle = throttleCategories[(int)ThrottleOutPacketType.State].DripRate + throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; |
208 | info.assetThrottle = throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; | 224 | info.assetThrottle = throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; |
209 | info.textureThrottle = throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; | 225 | info.textureThrottle = throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; |
210 | info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + | 226 | info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + |
@@ -301,7 +317,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
301 | Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4; | 317 | Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4; |
302 | Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4; | 318 | Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4; |
303 | Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4; | 319 | Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4; |
304 | Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Task].DripRate), 0, data, i, 4); i += 4; | 320 | Buffer.BlockCopy(Utils.FloatToBytes((float)(throttleCategories[(int)ThrottleOutPacketType.Task].DripRate) + |
321 | throttleCategories[(int)ThrottleOutPacketType.State].DripRate), 0, data, i, 4); i += 4; | ||
305 | Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4; | 322 | Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4; |
306 | Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4; | 323 | Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4; |
307 | 324 | ||
@@ -310,12 +327,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
310 | 327 | ||
311 | public void SetThrottle(ThrottleOutPacketType category, int rate) | 328 | public void SetThrottle(ThrottleOutPacketType category, int rate) |
312 | { | 329 | { |
313 | int i = (int)category; | 330 | if (category == ThrottleOutPacketType.Task) |
314 | if (i >= 0 && i < throttleCategories.Length) | ||
315 | { | 331 | { |
316 | TokenBucket bucket = throttleCategories[(int)category]; | 332 | TokenBucket stateBucket = throttleCategories[(int)ThrottleOutPacketType.State]; |
317 | bucket.MaxBurst = rate; | 333 | TokenBucket taskBucket = throttleCategories[(int)ThrottleOutPacketType.Task]; |
318 | bucket.DripRate = rate; | 334 | |
335 | stateBucket.MaxBurst = (int)((float)rate * STATE_TASK_PERCENTAGE); | ||
336 | stateBucket.DripRate = (int)((float)rate * STATE_TASK_PERCENTAGE); | ||
337 | |||
338 | taskBucket.MaxBurst = rate - stateBucket.MaxBurst; | ||
339 | taskBucket.DripRate = rate - stateBucket.DripRate; | ||
340 | } | ||
341 | else | ||
342 | { | ||
343 | int i = (int)category; | ||
344 | if (i >= 0 && i < throttleCategories.Length) | ||
345 | { | ||
346 | TokenBucket bucket = throttleCategories[(int)category]; | ||
347 | bucket.MaxBurst = rate; | ||
348 | bucket.DripRate = rate; | ||
349 | } | ||
319 | } | 350 | } |
320 | } | 351 | } |
321 | 352 | ||
@@ -325,7 +356,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
325 | 356 | ||
326 | if (category >= 0 && category < packetOutboxes.Length) | 357 | if (category >= 0 && category < packetOutboxes.Length) |
327 | { | 358 | { |
328 | LocklessQueue<OutgoingPacket> queue = packetOutboxes[category]; | 359 | OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = packetOutboxes[category]; |
329 | TokenBucket bucket = throttleCategories[category]; | 360 | TokenBucket bucket = throttleCategories[category]; |
330 | 361 | ||
331 | if (throttleCategories[category].RemoveTokens(packet.Buffer.DataLength)) | 362 | if (throttleCategories[category].RemoveTokens(packet.Buffer.DataLength)) |
@@ -357,7 +388,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
357 | public bool DequeueOutgoing() | 388 | public bool DequeueOutgoing() |
358 | { | 389 | { |
359 | OutgoingPacket packet; | 390 | OutgoingPacket packet; |
360 | LocklessQueue<OutgoingPacket> queue; | 391 | OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; |
361 | TokenBucket bucket; | 392 | TokenBucket bucket; |
362 | bool packetSent = false; | 393 | bool packetSent = false; |
363 | 394 | ||
@@ -400,13 +431,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
400 | nextPackets[i] = packet; | 431 | nextPackets[i] = packet; |
401 | nextPacketLengths[i] = packet.Buffer.DataLength; | 432 | nextPacketLengths[i] = packet.Buffer.DataLength; |
402 | } | 433 | } |
434 | |||
435 | // If the queue is empty after this dequeue, fire the queue | ||
436 | // empty callback now so it has a chance to fill before we | ||
437 | // get back here | ||
438 | if (queue.Count == 0) | ||
439 | FireQueueEmpty(i); | ||
403 | } | 440 | } |
404 | else | 441 | else |
405 | { | 442 | { |
406 | // No packets in this queue. Fire the queue empty callback | 443 | // No packets in this queue. Fire the queue empty callback |
407 | QueueEmpty callback = OnQueueEmpty; | 444 | // if it has not been called recently |
408 | if (callback != null) | 445 | FireQueueEmpty(i); |
409 | callback((ThrottleOutPacketType)i); | ||
410 | } | 446 | } |
411 | } | 447 | } |
412 | } | 448 | } |
@@ -435,8 +471,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
435 | 471 | ||
436 | // Always round retransmission timeout up to two seconds | 472 | // Always round retransmission timeout up to two seconds |
437 | RTO = Math.Max(2000, (int)(SRTT + Math.Max(G, K * RTTVAR))); | 473 | RTO = Math.Max(2000, (int)(SRTT + Math.Max(G, K * RTTVAR))); |
438 | //Logger.Debug("Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " + | 474 | //m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " + |
439 | // RTTVAR + " based on new RTT of " + r + "ms"); | 475 | // RTTVAR + " based on new RTT of " + r + "ms"); |
440 | } | 476 | } |
477 | |||
478 | private void FireQueueEmpty(int queueIndex) | ||
479 | { | ||
480 | QueueEmpty callback = OnQueueEmpty; | ||
481 | if (callback != null) | ||
482 | Util.FireAndForget(delegate(object o) { callback((ThrottleOutPacketType)(int)o); }, queueIndex); | ||
483 | } | ||
441 | } | 484 | } |
442 | } | 485 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs deleted file mode 100644 index dbb9861..0000000 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs +++ /dev/null | |||
@@ -1,282 +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 | |||
34 | using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim; | ||
35 | |||
36 | namespace OpenSim.Region.ClientStack.LindenUDP | ||
37 | { | ||
38 | public sealed class UDPClientCollection | ||
39 | { | ||
40 | Dictionary<UUID, LLUDPClient> Dictionary1; | ||
41 | Dictionary<IPEndPoint, LLUDPClient> Dictionary2; | ||
42 | LLUDPClient[] Array; | ||
43 | ReaderWriterLockImpl rwLock = new ReaderWriterLockImpl(); | ||
44 | object m_sync = new object(); | ||
45 | |||
46 | public UDPClientCollection() | ||
47 | { | ||
48 | Dictionary1 = new Dictionary<UUID, LLUDPClient>(); | ||
49 | Dictionary2 = new Dictionary<IPEndPoint, LLUDPClient>(); | ||
50 | Array = new LLUDPClient[0]; | ||
51 | } | ||
52 | |||
53 | public UDPClientCollection(int capacity) | ||
54 | { | ||
55 | Dictionary1 = new Dictionary<UUID, LLUDPClient>(capacity); | ||
56 | Dictionary2 = new Dictionary<IPEndPoint, LLUDPClient>(capacity); | ||
57 | Array = new LLUDPClient[0]; | ||
58 | } | ||
59 | |||
60 | public void Add(UUID key1, IPEndPoint key2, LLUDPClient value) | ||
61 | { | ||
62 | //rwLock.EnterWriteLock(); | ||
63 | |||
64 | //try | ||
65 | //{ | ||
66 | // if (Dictionary1.ContainsKey(key1)) | ||
67 | // { | ||
68 | // if (!Dictionary2.ContainsKey(key2)) | ||
69 | // throw new ArgumentException("key1 exists in the dictionary but not key2"); | ||
70 | // } | ||
71 | // else if (Dictionary2.ContainsKey(key2)) | ||
72 | // { | ||
73 | // if (!Dictionary1.ContainsKey(key1)) | ||
74 | // throw new ArgumentException("key2 exists in the dictionary but not key1"); | ||
75 | // } | ||
76 | |||
77 | // Dictionary1[key1] = value; | ||
78 | // Dictionary2[key2] = value; | ||
79 | |||
80 | // LLUDPClient[] oldArray = Array; | ||
81 | // int oldLength = oldArray.Length; | ||
82 | |||
83 | // LLUDPClient[] newArray = new LLUDPClient[oldLength + 1]; | ||
84 | // for (int i = 0; i < oldLength; i++) | ||
85 | // newArray[i] = oldArray[i]; | ||
86 | // newArray[oldLength] = value; | ||
87 | |||
88 | // Array = newArray; | ||
89 | //} | ||
90 | //finally { rwLock.ExitWriteLock(); } | ||
91 | |||
92 | lock (m_sync) | ||
93 | { | ||
94 | if (Dictionary1.ContainsKey(key1)) | ||
95 | { | ||
96 | if (!Dictionary2.ContainsKey(key2)) | ||
97 | throw new ArgumentException("key1 exists in the dictionary but not key2"); | ||
98 | } | ||
99 | else if (Dictionary2.ContainsKey(key2)) | ||
100 | { | ||
101 | if (!Dictionary1.ContainsKey(key1)) | ||
102 | throw new ArgumentException("key2 exists in the dictionary but not key1"); | ||
103 | } | ||
104 | |||
105 | Dictionary1[key1] = value; | ||
106 | Dictionary2[key2] = value; | ||
107 | |||
108 | LLUDPClient[] oldArray = Array; | ||
109 | int oldLength = oldArray.Length; | ||
110 | |||
111 | LLUDPClient[] newArray = new LLUDPClient[oldLength + 1]; | ||
112 | for (int i = 0; i < oldLength; i++) | ||
113 | newArray[i] = oldArray[i]; | ||
114 | newArray[oldLength] = value; | ||
115 | |||
116 | Array = newArray; | ||
117 | } | ||
118 | |||
119 | } | ||
120 | |||
121 | public bool Remove(UUID key1, IPEndPoint key2) | ||
122 | { | ||
123 | //rwLock.EnterWriteLock(); | ||
124 | |||
125 | //try | ||
126 | //{ | ||
127 | // LLUDPClient value; | ||
128 | // if (Dictionary1.TryGetValue(key1, out value)) | ||
129 | // { | ||
130 | // Dictionary1.Remove(key1); | ||
131 | // Dictionary2.Remove(key2); | ||
132 | |||
133 | // LLUDPClient[] oldArray = Array; | ||
134 | // int oldLength = oldArray.Length; | ||
135 | |||
136 | // LLUDPClient[] newArray = new LLUDPClient[oldLength - 1]; | ||
137 | // int j = 0; | ||
138 | // for (int i = 0; i < oldLength; i++) | ||
139 | // { | ||
140 | // if (oldArray[i] != value) | ||
141 | // newArray[j++] = oldArray[i]; | ||
142 | // } | ||
143 | |||
144 | // Array = newArray; | ||
145 | // return true; | ||
146 | // } | ||
147 | //} | ||
148 | //finally { rwLock.ExitWriteLock(); } | ||
149 | |||
150 | //return false; | ||
151 | |||
152 | lock (m_sync) | ||
153 | { | ||
154 | LLUDPClient value; | ||
155 | if (Dictionary1.TryGetValue(key1, out value)) | ||
156 | { | ||
157 | Dictionary1.Remove(key1); | ||
158 | Dictionary2.Remove(key2); | ||
159 | |||
160 | LLUDPClient[] oldArray = Array; | ||
161 | int oldLength = oldArray.Length; | ||
162 | |||
163 | LLUDPClient[] newArray = new LLUDPClient[oldLength - 1]; | ||
164 | int j = 0; | ||
165 | for (int i = 0; i < oldLength; i++) | ||
166 | { | ||
167 | if (oldArray[i] != value) | ||
168 | newArray[j++] = oldArray[i]; | ||
169 | } | ||
170 | |||
171 | Array = newArray; | ||
172 | return true; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | return false; | ||
177 | |||
178 | } | ||
179 | |||
180 | public void Clear() | ||
181 | { | ||
182 | //rwLock.EnterWriteLock(); | ||
183 | |||
184 | //try | ||
185 | //{ | ||
186 | // Dictionary1.Clear(); | ||
187 | // Dictionary2.Clear(); | ||
188 | // Array = new LLUDPClient[0]; | ||
189 | //} | ||
190 | //finally { rwLock.ExitWriteLock(); } | ||
191 | |||
192 | lock (m_sync) | ||
193 | { | ||
194 | Dictionary1.Clear(); | ||
195 | Dictionary2.Clear(); | ||
196 | Array = new LLUDPClient[0]; | ||
197 | } | ||
198 | |||
199 | } | ||
200 | |||
201 | public int Count | ||
202 | { | ||
203 | get { return Array.Length; } | ||
204 | } | ||
205 | |||
206 | public bool ContainsKey(UUID key) | ||
207 | { | ||
208 | return Dictionary1.ContainsKey(key); | ||
209 | } | ||
210 | |||
211 | public bool ContainsKey(IPEndPoint key) | ||
212 | { | ||
213 | return Dictionary2.ContainsKey(key); | ||
214 | } | ||
215 | |||
216 | public bool TryGetValue(UUID key, out LLUDPClient value) | ||
217 | { | ||
218 | ////bool success; | ||
219 | ////bool doLock = !rwLock.IsUpgradeableReadLockHeld; | ||
220 | ////if (doLock) rwLock.EnterReadLock(); | ||
221 | |||
222 | ////try { success = Dictionary1.TryGetValue(key, out value); } | ||
223 | ////finally { if (doLock) rwLock.ExitReadLock(); } | ||
224 | |||
225 | ////return success; | ||
226 | |||
227 | lock (m_sync) | ||
228 | return Dictionary1.TryGetValue(key, out value); | ||
229 | |||
230 | //try | ||
231 | //{ | ||
232 | // return Dictionary1.TryGetValue(key, out value); | ||
233 | //} | ||
234 | //catch { } | ||
235 | //value = null; | ||
236 | //return false; | ||
237 | } | ||
238 | |||
239 | public bool TryGetValue(IPEndPoint key, out LLUDPClient value) | ||
240 | { | ||
241 | ////bool success; | ||
242 | ////bool doLock = !rwLock.IsUpgradeableReadLockHeld; | ||
243 | ////if (doLock) rwLock.EnterReadLock(); | ||
244 | |||
245 | ////try { success = Dictionary2.TryGetValue(key, out value); } | ||
246 | ////finally { if (doLock) rwLock.ExitReadLock(); } | ||
247 | |||
248 | ////return success; | ||
249 | |||
250 | lock (m_sync) | ||
251 | return Dictionary2.TryGetValue(key, out value); | ||
252 | |||
253 | //try | ||
254 | //{ | ||
255 | // return Dictionary2.TryGetValue(key, out value); | ||
256 | //} | ||
257 | //catch { } | ||
258 | //value = null; | ||
259 | //return false; | ||
260 | |||
261 | } | ||
262 | |||
263 | public void ForEach(Action<LLUDPClient> action) | ||
264 | { | ||
265 | //bool doLock = !rwLock.IsUpgradeableReadLockHeld; | ||
266 | //if (doLock) rwLock.EnterUpgradeableReadLock(); | ||
267 | |||
268 | //try { Parallel.ForEach<LLUDPClient>(Array, action); } | ||
269 | //finally { if (doLock) rwLock.ExitUpgradeableReadLock(); } | ||
270 | |||
271 | LLUDPClient[] localArray = null; | ||
272 | lock (m_sync) | ||
273 | { | ||
274 | localArray = new LLUDPClient[Array.Length]; | ||
275 | Array.CopyTo(localArray, 0); | ||
276 | } | ||
277 | |||
278 | Parallel.ForEach<LLUDPClient>(localArray, action); | ||
279 | |||
280 | } | ||
281 | } | ||
282 | } | ||
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index c356f02..57fee59 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 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> |
@@ -115,7 +115,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
115 | public Socket Server { get { return null; } } | 115 | public Socket Server { get { return null; } } |
116 | 116 | ||
117 | public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) | 117 | public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) |
118 | : base((int)port) | 118 | : base(listenIP, (int)port) |
119 | { | 119 | { |
120 | #region Environment.TickCount Measurement | 120 | #region Environment.TickCount Measurement |
121 | 121 | ||
@@ -143,7 +143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
143 | public new void Start() | 143 | public new void Start() |
144 | { | 144 | { |
145 | if (m_scene == null) | 145 | if (m_scene == null) |
146 | throw new InvalidOperationException("Cannot LLUDPServer.Start() without an IScene reference"); | 146 | throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); |
147 | 147 | ||
148 | base.Start(); | 148 | base.Start(); |
149 | 149 | ||
@@ -181,24 +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(IClientAPI client) | ||
185 | { | ||
186 | m_scene.ClientManager.Remove(client.CircuitCode); | ||
187 | client.Close(false); | ||
188 | |||
189 | LLUDPClient udpClient; | ||
190 | if (clients.TryGetValue(client.AgentId, out udpClient)) | ||
191 | { | ||
192 | m_log.Debug("[LLUDPSERVER]: Removing LLUDPClient for " + client.Name + " in " + m_scene.RegionInfo.RegionName); | ||
193 | udpClient.Shutdown(); | ||
194 | clients.Remove(client.AgentId, udpClient.RemoteEndPoint); | ||
195 | } | ||
196 | else | ||
197 | { | ||
198 | m_log.Warn("[LLUDPSERVER]: Failed to remove LLUDPClient for " + client.Name); | ||
199 | } | ||
200 | } | ||
201 | |||
202 | public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) | 184 | public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) |
203 | { | 185 | { |
204 | // CoarseLocationUpdate packets cannot be split in an automated way | 186 | // CoarseLocationUpdate packets cannot be split in an automated way |
@@ -216,30 +198,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
216 | for (int i = 0; i < packetCount; i++) | 198 | for (int i = 0; i < packetCount; i++) |
217 | { | 199 | { |
218 | byte[] data = datas[i]; | 200 | byte[] data = datas[i]; |
219 | clients.ForEach( | 201 | m_scene.ClientManager.ForEach( |
220 | delegate(LLUDPClient client) | 202 | delegate(IClientAPI client) |
221 | { SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); }); | 203 | { |
204 | if (client is LLClientView) | ||
205 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); | ||
206 | } | ||
207 | ); | ||
222 | } | 208 | } |
223 | } | 209 | } |
224 | else | 210 | else |
225 | { | 211 | { |
226 | byte[] data = packet.ToBytes(); | 212 | byte[] data = packet.ToBytes(); |
227 | clients.ForEach( | 213 | m_scene.ClientManager.ForEach( |
228 | delegate(LLUDPClient client) | 214 | delegate(IClientAPI client) |
229 | { SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); }); | 215 | { |
216 | if (client is LLClientView) | ||
217 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); | ||
218 | } | ||
219 | ); | ||
230 | } | 220 | } |
231 | } | 221 | } |
232 | 222 | ||
233 | public void SendPacket(UUID agentID, Packet packet, ThrottleOutPacketType category, bool allowSplitting) | 223 | public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting) |
234 | { | ||
235 | LLUDPClient client; | ||
236 | if (clients.TryGetValue(agentID, out client)) | ||
237 | SendPacket(client, packet, category, allowSplitting); | ||
238 | else | ||
239 | m_log.Warn("[LLUDPSERVER]: Attempted to send a packet to unknown agentID " + agentID); | ||
240 | } | ||
241 | |||
242 | public void SendPacket(LLUDPClient client, Packet packet, ThrottleOutPacketType category, bool allowSplitting) | ||
243 | { | 224 | { |
244 | // CoarseLocationUpdate packets cannot be split in an automated way | 225 | // CoarseLocationUpdate packets cannot be split in an automated way |
245 | if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) | 226 | if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) |
@@ -256,25 +237,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
256 | for (int i = 0; i < packetCount; i++) | 237 | for (int i = 0; i < packetCount; i++) |
257 | { | 238 | { |
258 | byte[] data = datas[i]; | 239 | byte[] data = datas[i]; |
259 | SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); | 240 | SendPacketData(udpClient, data, packet.Type, category); |
260 | } | 241 | } |
261 | } | 242 | } |
262 | else | 243 | else |
263 | { | 244 | { |
264 | byte[] data = packet.ToBytes(); | 245 | byte[] data = packet.ToBytes(); |
265 | SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); | 246 | SendPacketData(udpClient, data, packet.Type, category); |
266 | } | 247 | } |
267 | } | 248 | } |
268 | 249 | ||
269 | public void SendPacketData(LLUDPClient client, byte[] data, int dataLength, PacketType type, bool doZerocode, ThrottleOutPacketType category) | 250 | public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category) |
270 | { | 251 | { |
252 | int dataLength = data.Length; | ||
253 | bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; | ||
254 | |||
271 | // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum. | 255 | // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum. |
272 | // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting | 256 | // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting |
273 | // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here | 257 | // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here |
274 | // to accomodate for both common scenarios and provide ample room for ACK appending in both | 258 | // to accomodate for both common scenarios and provide ample room for ACK appending in both |
275 | int bufferSize = (dataLength > 180) ? Packet.MTU : 200; | 259 | int bufferSize = (dataLength > 180) ? Packet.MTU : 200; |
276 | 260 | ||
277 | UDPPacketBuffer buffer = new UDPPacketBuffer(client.RemoteEndPoint, bufferSize); | 261 | UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); |
278 | 262 | ||
279 | // Zerocode if needed | 263 | // Zerocode if needed |
280 | if (doZerocode) | 264 | if (doZerocode) |
@@ -285,17 +269,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
285 | // The packet grew larger than the bufferSize while zerocoding. | 269 | // The packet grew larger than the bufferSize while zerocoding. |
286 | // Remove the MSG_ZEROCODED flag and send the unencoded data | 270 | // Remove the MSG_ZEROCODED flag and send the unencoded data |
287 | // instead | 271 | // instead |
288 | m_log.Info("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding. Removing MSG_ZEROCODED flag"); | 272 | m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". Removing MSG_ZEROCODED flag"); |
289 | data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED); | 273 | data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED); |
290 | // | ||
291 | buffer = new UDPPacketBuffer(client.RemoteEndPoint, dataLength); | ||
292 | // | ||
293 | Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); | 274 | Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); |
294 | } | 275 | } |
295 | } | 276 | } |
296 | else | 277 | else |
297 | { | 278 | { |
298 | // ??? will it fit? | ||
299 | Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); | 279 | Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); |
300 | } | 280 | } |
301 | buffer.DataLength = dataLength; | 281 | buffer.DataLength = dataLength; |
@@ -303,7 +283,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
303 | #region Queue or Send | 283 | #region Queue or Send |
304 | 284 | ||
305 | // Look up the UDPClient this is going to | 285 | // Look up the UDPClient this is going to |
306 | OutgoingPacket outgoingPacket = new OutgoingPacket(client, buffer, category); | 286 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); |
307 | 287 | ||
308 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) | 288 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) |
309 | SendPacketFinal(outgoingPacket); | 289 | SendPacketFinal(outgoingPacket); |
@@ -311,18 +291,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
311 | #endregion Queue or Send | 291 | #endregion Queue or Send |
312 | } | 292 | } |
313 | 293 | ||
314 | public void SendAcks(LLUDPClient client) | 294 | public void SendAcks(LLUDPClient udpClient) |
315 | { | 295 | { |
316 | uint ack; | 296 | uint ack; |
317 | 297 | ||
318 | if (client.PendingAcks.Dequeue(out ack)) | 298 | if (udpClient.PendingAcks.Dequeue(out ack)) |
319 | { | 299 | { |
320 | List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>(); | 300 | List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>(); |
321 | PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); | 301 | PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); |
322 | block.ID = ack; | 302 | block.ID = ack; |
323 | blocks.Add(block); | 303 | blocks.Add(block); |
324 | 304 | ||
325 | while (client.PendingAcks.Dequeue(out ack)) | 305 | while (udpClient.PendingAcks.Dequeue(out ack)) |
326 | { | 306 | { |
327 | block = new PacketAckPacket.PacketsBlock(); | 307 | block = new PacketAckPacket.PacketsBlock(); |
328 | block.ID = ack; | 308 | block.ID = ack; |
@@ -333,22 +313,39 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
333 | packet.Header.Reliable = false; | 313 | packet.Header.Reliable = false; |
334 | packet.Packets = blocks.ToArray(); | 314 | packet.Packets = blocks.ToArray(); |
335 | 315 | ||
336 | SendPacket(client, packet, ThrottleOutPacketType.Unknown, true); | 316 | SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true); |
337 | } | 317 | } |
338 | } | 318 | } |
339 | 319 | ||
340 | public void SendPing(LLUDPClient client) | 320 | public void SendPing(LLUDPClient udpClient) |
341 | { | 321 | { |
342 | IClientAPI api = client.ClientAPI; | 322 | StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); |
343 | if (api != null) | 323 | pc.Header.Reliable = false; |
344 | api.SendStartPingCheck(client.CurrentPingSequence++); | 324 | |
325 | OutgoingPacket oldestPacket = udpClient.NeedAcks.GetOldest(); | ||
326 | |||
327 | pc.PingID.PingID = (byte)udpClient.CurrentPingSequence++; | ||
328 | pc.PingID.OldestUnacked = (oldestPacket != null) ? oldestPacket.SequenceNumber : 0; | ||
329 | |||
330 | SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false); | ||
345 | } | 331 | } |
346 | 332 | ||
347 | public void ResendUnacked(LLUDPClient client) | 333 | public void ResendUnacked(LLUDPClient udpClient) |
348 | { | 334 | { |
349 | if (client.NeedAcks.Count > 0) | 335 | if (udpClient.IsConnected && udpClient.NeedAcks.Count > 0) |
350 | { | 336 | { |
351 | List<OutgoingPacket> expiredPackets = client.NeedAcks.GetExpiredPackets(client.RTO); | 337 | // Disconnect an agent if no packets are received for some time |
338 | //FIXME: Make 60 an .ini setting | ||
339 | if (Environment.TickCount - udpClient.TickLastPacketReceived > 1000 * 60) | ||
340 | { | ||
341 | m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID); | ||
342 | |||
343 | RemoveClient(udpClient); | ||
344 | return; | ||
345 | } | ||
346 | |||
347 | // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO | ||
348 | List<OutgoingPacket> expiredPackets = udpClient.NeedAcks.GetExpiredPackets(udpClient.RTO); | ||
352 | 349 | ||
353 | if (expiredPackets != null) | 350 | if (expiredPackets != null) |
354 | { | 351 | { |
@@ -357,54 +354,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
357 | { | 354 | { |
358 | OutgoingPacket outgoingPacket = expiredPackets[i]; | 355 | OutgoingPacket outgoingPacket = expiredPackets[i]; |
359 | 356 | ||
360 | // FIXME: Make this an .ini setting | 357 | //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed", |
361 | if (outgoingPacket.ResendCount < 3) | 358 | // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount); |
362 | { | ||
363 | //Logger.Debug(String.Format("Resending packet #{0} (attempt {1}), {2}ms have passed", | ||
364 | // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount)); | ||
365 | |||
366 | // Set the resent flag | ||
367 | outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT); | ||
368 | outgoingPacket.Category = ThrottleOutPacketType.Resend; | ||
369 | |||
370 | // The TickCount will be set to the current time when the packet | ||
371 | // is actually sent out again | ||
372 | outgoingPacket.TickCount = 0; | ||
373 | |||
374 | // Bump up the resend count on this packet | ||
375 | Interlocked.Increment(ref outgoingPacket.ResendCount); | ||
376 | //Interlocked.Increment(ref Stats.ResentPackets); | ||
377 | |||
378 | // Queue or (re)send the packet | ||
379 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) | ||
380 | SendPacketFinal(outgoingPacket); | ||
381 | } | ||
382 | else | ||
383 | { | ||
384 | m_log.DebugFormat("[LLUDPSERVER]: Dropping packet #{0} for agent {1} after {2} failed attempts", | ||
385 | outgoingPacket.SequenceNumber, outgoingPacket.Client.RemoteEndPoint, outgoingPacket.ResendCount); | ||
386 | 359 | ||
387 | lock (client.NeedAcks.SyncRoot) | 360 | // Set the resent flag |
388 | client.NeedAcks.RemoveUnsafe(outgoingPacket.SequenceNumber); | 361 | outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT); |
362 | outgoingPacket.Category = ThrottleOutPacketType.Resend; | ||
389 | 363 | ||
390 | //Interlocked.Increment(ref Stats.DroppedPackets); | 364 | // The TickCount will be set to the current time when the packet |
365 | // is actually sent out again | ||
366 | outgoingPacket.TickCount = 0; | ||
391 | 367 | ||
392 | // Disconnect an agent if no packets are received for some time | 368 | // Bump up the resend count on this packet |
393 | //FIXME: Make 60 an .ini setting | 369 | Interlocked.Increment(ref outgoingPacket.ResendCount); |
394 | if (Environment.TickCount - client.TickLastPacketReceived > 1000 * 60) | 370 | //Interlocked.Increment(ref Stats.ResentPackets); |
395 | { | ||
396 | m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + client.ClientAPI.Name); | ||
397 | 371 | ||
398 | RemoveClient(client.ClientAPI); | 372 | // Requeue or resend the packet |
399 | return; | 373 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) |
400 | } | 374 | SendPacketFinal(outgoingPacket); |
401 | } | ||
402 | } | 375 | } |
403 | } | 376 | } |
404 | } | 377 | } |
405 | } | 378 | } |
406 | 379 | ||
407 | public void Flush() | 380 | public void Flush(LLUDPClient udpClient) |
408 | { | 381 | { |
409 | // FIXME: Implement? | 382 | // FIXME: Implement? |
410 | } | 383 | } |
@@ -415,7 +388,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
415 | byte flags = buffer.Data[0]; | 388 | byte flags = buffer.Data[0]; |
416 | bool isResend = (flags & Helpers.MSG_RESENT) != 0; | 389 | bool isResend = (flags & Helpers.MSG_RESENT) != 0; |
417 | bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; | 390 | bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; |
418 | LLUDPClient client = outgoingPacket.Client; | 391 | LLUDPClient udpClient = outgoingPacket.Client; |
392 | |||
393 | if (!udpClient.IsConnected) | ||
394 | return; | ||
419 | 395 | ||
420 | // Keep track of when this packet was sent out (right now) | 396 | // Keep track of when this packet was sent out (right now) |
421 | outgoingPacket.TickCount = Environment.TickCount; | 397 | outgoingPacket.TickCount = Environment.TickCount; |
@@ -424,11 +400,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
424 | 400 | ||
425 | int dataLength = buffer.DataLength; | 401 | int dataLength = buffer.DataLength; |
426 | 402 | ||
427 | // Keep appending ACKs until there is no room left in the packet or there are | 403 | // Keep appending ACKs until there is no room left in the buffer or there are |
428 | // no more ACKs to append | 404 | // no more ACKs to append |
429 | uint ackCount = 0; | 405 | uint ackCount = 0; |
430 | uint ack; | 406 | uint ack; |
431 | while (dataLength + 5 < buffer.Data.Length && client.PendingAcks.Dequeue(out ack)) | 407 | while (dataLength + 5 < buffer.Data.Length && udpClient.PendingAcks.Dequeue(out ack)) |
432 | { | 408 | { |
433 | Utils.UIntToBytesBig(ack, buffer.Data, dataLength); | 409 | Utils.UIntToBytesBig(ack, buffer.Data, dataLength); |
434 | dataLength += 4; | 410 | dataLength += 4; |
@@ -447,24 +423,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
447 | 423 | ||
448 | #endregion ACK Appending | 424 | #endregion ACK Appending |
449 | 425 | ||
426 | #region Sequence Number Assignment | ||
427 | |||
450 | if (!isResend) | 428 | if (!isResend) |
451 | { | 429 | { |
452 | // Not a resend, assign a new sequence number | 430 | // Not a resend, assign a new sequence number |
453 | uint sequenceNumber = (uint)Interlocked.Increment(ref client.CurrentSequence); | 431 | uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence); |
454 | Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); | 432 | Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); |
455 | outgoingPacket.SequenceNumber = sequenceNumber; | 433 | outgoingPacket.SequenceNumber = sequenceNumber; |
456 | 434 | ||
457 | if (isReliable) | 435 | if (isReliable) |
458 | { | 436 | { |
459 | // Add this packet to the list of ACK responses we are waiting on from the server | 437 | // Add this packet to the list of ACK responses we are waiting on from the server |
460 | client.NeedAcks.Add(outgoingPacket); | 438 | udpClient.NeedAcks.Add(outgoingPacket); |
461 | } | 439 | } |
462 | } | 440 | } |
463 | 441 | ||
442 | #endregion Sequence Number Assignment | ||
443 | |||
464 | // Stats tracking | 444 | // Stats tracking |
465 | Interlocked.Increment(ref client.PacketsSent); | 445 | Interlocked.Increment(ref udpClient.PacketsSent); |
466 | if (isReliable) | 446 | if (isReliable) |
467 | Interlocked.Add(ref client.UnackedBytes, outgoingPacket.Buffer.DataLength); | 447 | Interlocked.Add(ref udpClient.UnackedBytes, outgoingPacket.Buffer.DataLength); |
468 | 448 | ||
469 | // Put the UDP payload on the wire | 449 | // Put the UDP payload on the wire |
470 | AsyncBeginSend(buffer); | 450 | AsyncBeginSend(buffer); |
@@ -473,10 +453,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
473 | protected override void PacketReceived(UDPPacketBuffer buffer) | 453 | protected override void PacketReceived(UDPPacketBuffer buffer) |
474 | { | 454 | { |
475 | // Debugging/Profiling | 455 | // Debugging/Profiling |
476 | //try { Thread.CurrentThread.Name = "PacketReceived (" + scene.RegionName + ")"; } | 456 | //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; } |
477 | //catch (Exception) { } | 457 | //catch (Exception) { } |
478 | 458 | ||
479 | LLUDPClient client = null; | 459 | LLUDPClient udpClient = null; |
480 | Packet packet = null; | 460 | Packet packet = null; |
481 | int packetEnd = buffer.DataLength - 1; | 461 | int packetEnd = buffer.DataLength - 1; |
482 | IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; | 462 | IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; |
@@ -491,61 +471,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
491 | } | 471 | } |
492 | catch (MalformedDataException) | 472 | catch (MalformedDataException) |
493 | { | 473 | { |
494 | m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse packet:\n{0}", | 474 | m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse packet from {0}:\n{1}", |
495 | Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)); | 475 | buffer.RemoteEndPoint, Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)); |
496 | } | 476 | } |
497 | 477 | ||
498 | // Fail-safe check | 478 | // Fail-safe check |
499 | if (packet == null) | 479 | if (packet == null) |
500 | { | 480 | { |
501 | m_log.Warn("[LLUDPSERVER]: Couldn't build a message from the incoming data"); | 481 | m_log.Warn("[LLUDPSERVER]: Couldn't build a message from incoming data " + buffer.DataLength + |
482 | " bytes long from " + buffer.RemoteEndPoint); | ||
502 | return; | 483 | return; |
503 | } | 484 | } |
504 | 485 | ||
505 | //Stats.RecvBytes += (ulong)buffer.DataLength; | ||
506 | //++Stats.RecvPackets; | ||
507 | |||
508 | #endregion Decoding | 486 | #endregion Decoding |
509 | 487 | ||
510 | #region UseCircuitCode Handling | 488 | #region Packet to Client Mapping |
511 | 489 | ||
490 | // UseCircuitCode handling | ||
512 | if (packet.Type == PacketType.UseCircuitCode) | 491 | if (packet.Type == PacketType.UseCircuitCode) |
513 | { | 492 | { |
514 | UseCircuitCodePacket useCircuitCode = (UseCircuitCodePacket)packet; | 493 | AddNewClient((UseCircuitCodePacket)packet, (IPEndPoint)buffer.RemoteEndPoint); |
515 | IClientAPI newuser; | ||
516 | uint circuitCode = useCircuitCode.CircuitCode.Code; | ||
517 | |||
518 | // Check if the client is already established | ||
519 | if (!m_scene.ClientManager.TryGetClient(circuitCode, out newuser)) | ||
520 | { | ||
521 | AddNewClient(useCircuitCode, (IPEndPoint)buffer.RemoteEndPoint); | ||
522 | } | ||
523 | } | 494 | } |
524 | 495 | ||
525 | // Determine which agent this packet came from | 496 | // Determine which agent this packet came from |
526 | if (!clients.TryGetValue(address, out client)) | 497 | IClientAPI client; |
498 | if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView)) | ||
527 | { | 499 | { |
528 | m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); | 500 | m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + |
501 | " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_scene.ClientManager.Count + " clients"); | ||
529 | return; | 502 | return; |
530 | } | 503 | } |
531 | 504 | ||
532 | #endregion UseCircuitCode Handling | 505 | udpClient = ((LLClientView)client).UDPClient; |
506 | |||
507 | if (!udpClient.IsConnected) | ||
508 | return; | ||
509 | |||
510 | #endregion Packet to Client Mapping | ||
533 | 511 | ||
534 | // Stats tracking | 512 | // Stats tracking |
535 | Interlocked.Increment(ref client.PacketsReceived); | 513 | Interlocked.Increment(ref udpClient.PacketsReceived); |
536 | 514 | ||
537 | #region ACK Receiving | 515 | #region ACK Receiving |
538 | 516 | ||
539 | int now = Environment.TickCount; | 517 | int now = Environment.TickCount; |
540 | client.TickLastPacketReceived = now; | 518 | udpClient.TickLastPacketReceived = now; |
541 | 519 | ||
542 | // Handle appended ACKs | 520 | // Handle appended ACKs |
543 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) | 521 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) |
544 | { | 522 | { |
545 | lock (client.NeedAcks.SyncRoot) | 523 | lock (udpClient.NeedAcks.SyncRoot) |
546 | { | 524 | { |
547 | for (int i = 0; i < packet.Header.AckList.Length; i++) | 525 | for (int i = 0; i < packet.Header.AckList.Length; i++) |
548 | AcknowledgePacket(client, packet.Header.AckList[i], now, packet.Header.Resent); | 526 | AcknowledgePacket(udpClient, packet.Header.AckList[i], now, packet.Header.Resent); |
549 | } | 527 | } |
550 | } | 528 | } |
551 | 529 | ||
@@ -554,10 +532,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
554 | { | 532 | { |
555 | PacketAckPacket ackPacket = (PacketAckPacket)packet; | 533 | PacketAckPacket ackPacket = (PacketAckPacket)packet; |
556 | 534 | ||
557 | lock (client.NeedAcks.SyncRoot) | 535 | lock (udpClient.NeedAcks.SyncRoot) |
558 | { | 536 | { |
559 | for (int i = 0; i < ackPacket.Packets.Length; i++) | 537 | for (int i = 0; i < ackPacket.Packets.Length; i++) |
560 | AcknowledgePacket(client, ackPacket.Packets[i].ID, now, packet.Header.Resent); | 538 | AcknowledgePacket(udpClient, ackPacket.Packets[i].ID, now, packet.Header.Resent); |
561 | } | 539 | } |
562 | } | 540 | } |
563 | 541 | ||
@@ -566,27 +544,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
566 | #region ACK Sending | 544 | #region ACK Sending |
567 | 545 | ||
568 | if (packet.Header.Reliable) | 546 | if (packet.Header.Reliable) |
569 | client.PendingAcks.Enqueue((uint)packet.Header.Sequence); | 547 | udpClient.PendingAcks.Enqueue(packet.Header.Sequence); |
570 | 548 | ||
571 | // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, | 549 | // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, |
572 | // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove | 550 | // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove |
573 | // 2*MTU bytes from the value and send ACKs, and finally add the local value back to | 551 | // 2*MTU bytes from the value and send ACKs, and finally add the local value back to |
574 | // client.BytesSinceLastACK. Lockless thread safety | 552 | // client.BytesSinceLastACK. Lockless thread safety |
575 | int bytesSinceLastACK = Interlocked.Exchange(ref client.BytesSinceLastACK, 0); | 553 | int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0); |
576 | bytesSinceLastACK += buffer.DataLength; | 554 | bytesSinceLastACK += buffer.DataLength; |
577 | if (bytesSinceLastACK > Packet.MTU * 2) | 555 | if (bytesSinceLastACK > Packet.MTU * 2) |
578 | { | 556 | { |
579 | bytesSinceLastACK -= Packet.MTU * 2; | 557 | bytesSinceLastACK -= Packet.MTU * 2; |
580 | SendAcks(client); | 558 | SendAcks(udpClient); |
581 | } | 559 | } |
582 | Interlocked.Add(ref client.BytesSinceLastACK, bytesSinceLastACK); | 560 | Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK); |
583 | 561 | ||
584 | #endregion ACK Sending | 562 | #endregion ACK Sending |
585 | 563 | ||
586 | #region Incoming Packet Accounting | 564 | #region Incoming Packet Accounting |
587 | 565 | ||
588 | // Check the archive of received reliable packet IDs to see whether we already received this packet | 566 | // Check the archive of received reliable packet IDs to see whether we already received this packet |
589 | if (packet.Header.Reliable && !client.PacketArchive.TryEnqueue(packet.Header.Sequence)) | 567 | if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence)) |
590 | { | 568 | { |
591 | if (packet.Header.Resent) | 569 | if (packet.Header.Resent) |
592 | m_log.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type); | 570 | m_log.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type); |
@@ -603,7 +581,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
603 | if (packet.Type != PacketType.PacketAck) | 581 | if (packet.Type != PacketType.PacketAck) |
604 | { | 582 | { |
605 | // Inbox insertion | 583 | // Inbox insertion |
606 | packetInbox.Enqueue(new IncomingPacket(client, packet)); | 584 | packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); |
607 | } | 585 | } |
608 | } | 586 | } |
609 | 587 | ||
@@ -623,53 +601,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
623 | 601 | ||
624 | private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint) | 602 | private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint) |
625 | { | 603 | { |
626 | //Slave regions don't accept new clients | 604 | UUID agentID = useCircuitCode.CircuitCode.ID; |
605 | UUID sessionID = useCircuitCode.CircuitCode.SessionID; | ||
606 | uint circuitCode = useCircuitCode.CircuitCode.Code; | ||
607 | |||
627 | if (m_scene.RegionStatus != RegionStatus.SlaveScene) | 608 | if (m_scene.RegionStatus != RegionStatus.SlaveScene) |
628 | { | 609 | { |
629 | AuthenticateResponse sessionInfo; | 610 | AuthenticateResponse sessionInfo; |
630 | bool isNewCircuit = !clients.ContainsKey(remoteEndPoint); | 611 | if (IsClientAuthorized(useCircuitCode, out sessionInfo)) |
631 | |||
632 | if (!IsClientAuthorized(useCircuitCode, out sessionInfo)) | ||
633 | { | 612 | { |
634 | m_log.WarnFormat( | 613 | AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo); |
635 | "[CONNECTION FAILURE]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}", | ||
636 | useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint); | ||
637 | return; | ||
638 | } | 614 | } |
639 | 615 | else | |
640 | if (isNewCircuit) | ||
641 | { | 616 | { |
642 | UUID agentID = useCircuitCode.CircuitCode.ID; | 617 | // Don't create circuits for unauthorized clients |
643 | UUID sessionID = useCircuitCode.CircuitCode.SessionID; | 618 | m_log.WarnFormat( |
644 | uint circuitCode = useCircuitCode.CircuitCode.Code; | 619 | "[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}", |
645 | 620 | useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint); | |
646 | AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo); | ||
647 | } | 621 | } |
648 | } | 622 | } |
623 | else | ||
624 | { | ||
625 | // Slave regions don't accept new clients | ||
626 | m_log.Debug("[LLUDPSERVER]: Slave region " + m_scene.RegionInfo.RegionName + " ignoring UseCircuitCode packet"); | ||
627 | } | ||
649 | } | 628 | } |
650 | 629 | ||
651 | private void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) | 630 | private void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) |
652 | { | 631 | { |
653 | // Create the LLUDPClient | 632 | // Create the LLUDPClient |
654 | LLUDPClient client = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); | 633 | LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); |
655 | 634 | ||
656 | // Create the LLClientView | 635 | if (!m_scene.ClientManager.ContainsKey(agentID)) |
657 | LLClientView clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode); | 636 | { |
658 | clientApi.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler; | 637 | // Create the LLClientView |
659 | clientApi.OnLogout += LogoutHandler; | 638 | LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); |
660 | clientApi.OnConnectionClosed += RemoveClient; | 639 | client.OnLogout += LogoutHandler; |
661 | |||
662 | // Start the IClientAPI | ||
663 | m_scene.ClientManager.Add(circuitCode, clientApi); | ||
664 | clientApi.Start(); | ||
665 | |||
666 | // Give LLUDPClient a reference to IClientAPI | ||
667 | client.ClientAPI = clientApi; | ||
668 | 640 | ||
669 | // Add the new client to our list of tracked clients | 641 | // Start the IClientAPI |
670 | clients.Add(agentID, client.RemoteEndPoint, client); | 642 | client.Start(); |
643 | } | ||
644 | else | ||
645 | { | ||
646 | m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}", | ||
647 | udpClient.AgentID, remoteEndPoint, circuitCode); | ||
648 | } | ||
649 | } | ||
671 | 650 | ||
672 | m_log.DebugFormat("[LLUDPSERVER]: Added new client {0} to region {1}", agentID, m_scene.RegionInfo.RegionName); | 651 | private void RemoveClient(LLUDPClient udpClient) |
652 | { | ||
653 | // Remove this client from the scene | ||
654 | IClientAPI client; | ||
655 | if (m_scene.ClientManager.TryGetValue(udpClient.AgentID, out client)) | ||
656 | client.Close(); | ||
673 | } | 657 | } |
674 | 658 | ||
675 | private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend) | 659 | private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend) |
@@ -747,20 +731,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
747 | elapsed500MS = 0; | 731 | elapsed500MS = 0; |
748 | } | 732 | } |
749 | 733 | ||
750 | clients.ForEach( | 734 | m_scene.ClientManager.ForEach( |
751 | delegate(LLUDPClient client) | 735 | delegate(IClientAPI client) |
752 | { | 736 | { |
753 | if (client.DequeueOutgoing()) | 737 | if (client is LLClientView) |
754 | packetSent = true; | ||
755 | if (resendUnacked) | ||
756 | ResendUnacked(client); | ||
757 | if (sendAcks) | ||
758 | { | 738 | { |
759 | SendAcks(client); | 739 | LLUDPClient udpClient = ((LLClientView)client).UDPClient; |
760 | client.SendPacketStats(); | 740 | |
741 | if (udpClient.IsConnected) | ||
742 | { | ||
743 | if (udpClient.DequeueOutgoing()) | ||
744 | packetSent = true; | ||
745 | if (resendUnacked) | ||
746 | ResendUnacked(udpClient); | ||
747 | if (sendAcks) | ||
748 | { | ||
749 | SendAcks(udpClient); | ||
750 | udpClient.SendPacketStats(); | ||
751 | } | ||
752 | if (sendPings) | ||
753 | SendPing(udpClient); | ||
754 | } | ||
761 | } | 755 | } |
762 | if (sendPings) | ||
763 | SendPing(client); | ||
764 | } | 756 | } |
765 | ); | 757 | ); |
766 | 758 | ||
@@ -773,38 +765,46 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
773 | { | 765 | { |
774 | IncomingPacket incomingPacket = (IncomingPacket)state; | 766 | IncomingPacket incomingPacket = (IncomingPacket)state; |
775 | Packet packet = incomingPacket.Packet; | 767 | Packet packet = incomingPacket.Packet; |
776 | LLUDPClient client = incomingPacket.Client; | 768 | LLUDPClient udpClient = incomingPacket.Client; |
769 | IClientAPI client; | ||
777 | 770 | ||
778 | // Sanity check | 771 | // Sanity check |
779 | if (packet == null || client == null || client.ClientAPI == null) | 772 | if (packet == null || udpClient == null) |
780 | { | 773 | { |
781 | m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", Client=\"{1}\", Client.ClientAPI=\"{2}\"", | 774 | m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", UDPClient=\"{1}\"", |
782 | packet, client, (client != null) ? client.ClientAPI : null); | 775 | packet, udpClient); |
783 | } | 776 | } |
784 | 777 | ||
785 | try | 778 | // Make sure this client is still alive |
786 | { | 779 | if (m_scene.ClientManager.TryGetValue(udpClient.AgentID, out client)) |
787 | // Process this packet | ||
788 | client.ClientAPI.ProcessInPacket(packet); | ||
789 | } | ||
790 | catch (ThreadAbortException) | ||
791 | { | 780 | { |
792 | // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down | 781 | try |
793 | m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server"); | 782 | { |
794 | Stop(); | 783 | // Process this packet |
784 | client.ProcessInPacket(packet); | ||
785 | } | ||
786 | catch (ThreadAbortException) | ||
787 | { | ||
788 | // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down | ||
789 | m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server"); | ||
790 | Stop(); | ||
791 | } | ||
792 | catch (Exception e) | ||
793 | { | ||
794 | // Don't let a failure in an individual client thread crash the whole sim. | ||
795 | m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type); | ||
796 | m_log.Error(e.Message, e); | ||
797 | } | ||
795 | } | 798 | } |
796 | catch (Exception e) | 799 | else |
797 | { | 800 | { |
798 | // Don't let a failure in an individual client thread crash the whole sim. | 801 | m_log.DebugFormat("[LLUDPSERVER]: Dropping incoming {0} packet for dead client {1}", packet.Type, udpClient.AgentID); |
799 | m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", client.AgentID, packet.Type); | ||
800 | m_log.Error(e.Message, e); | ||
801 | } | 802 | } |
802 | } | 803 | } |
803 | 804 | ||
804 | private void LogoutHandler(IClientAPI client) | 805 | private void LogoutHandler(IClientAPI client) |
805 | { | 806 | { |
806 | client.SendLogoutPacket(); | 807 | client.SendLogoutPacket(); |
807 | RemoveClient(client); | ||
808 | } | 808 | } |
809 | } | 809 | } |
810 | } | 810 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs index 43a68ec..fad2ea8 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs | |||
@@ -1,402 +1,100 @@ | |||
1 | //--------- Modified Version ------------------- | 1 | /* |
2 | ///* | 2 | * Copyright (c) 2006, Clutch, Inc. |
3 | // * Copyright (c) 2006, Clutch, Inc. | 3 | * Original Author: Jeff Cesnik |
4 | // * Original Author: Jeff Cesnik | 4 | * All rights reserved. |
5 | // * All rights reserved. | 5 | * |
6 | // * | 6 | * - Redistribution and use in source and binary forms, with or without |
7 | // * - Redistribution and use in source and binary forms, with or without | 7 | * modification, are permitted provided that the following conditions are met: |
8 | // * modification, are permitted provided that the following conditions are met: | 8 | * |
9 | // * | 9 | * - Redistributions of source code must retain the above copyright notice, this |
10 | // * - Redistributions of source code must retain the above copyright notice, this | 10 | * list of conditions and the following disclaimer. |
11 | // * list of conditions and the following disclaimer. | 11 | * - Neither the name of the openmetaverse.org nor the names |
12 | // * - Neither the name of the openmetaverse.org nor the names | 12 | * of its contributors may be used to endorse or promote products derived from |
13 | // * of its contributors may be used to endorse or promote products derived from | 13 | * this software without specific prior written permission. |
14 | // * this software without specific prior written permission. | 14 | * |
15 | // * | 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
16 | // * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | // * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | // * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | // * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | // * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | // * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | // * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | // * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | // * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 | // * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 25 | * POSSIBILITY OF SUCH DAMAGE. |
26 | // * POSSIBILITY OF SUCH DAMAGE. | 26 | */ |
27 | // */ | ||
28 | 27 | ||
29 | using System; | 28 | using System; |
30 | using System.Net; | 29 | using System.Net; |
31 | using System.Net.Sockets; | 30 | using System.Net.Sockets; |
32 | using System.Threading; | 31 | using System.Threading; |
33 | using OpenMetaverse; | 32 | using log4net; |
34 | 33 | ||
35 | //namespace OpenSim.Region.ClientStack.LindenUDP | 34 | namespace OpenMetaverse |
36 | //{ | ||
37 | // /// <summary> | ||
38 | // /// | ||
39 | // /// </summary> | ||
40 | // public abstract class OpenSimUDPBase | ||
41 | // { | ||
42 | // // these abstract methods must be implemented in a derived class to actually do | ||
43 | // // something with the packets that are sent and received. | ||
44 | // protected abstract void PacketReceived(UDPPacketBuffer buffer); | ||
45 | // protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent); | ||
46 | |||
47 | // // the port to listen on | ||
48 | // internal int udpPort; | ||
49 | |||
50 | // // the UDP socket | ||
51 | // private Socket udpSocket; | ||
52 | |||
53 | // // the ReaderWriterLock is used solely for the purposes of shutdown (Stop()). | ||
54 | // // since there are potentially many "reader" threads in the internal .NET IOCP | ||
55 | // // thread pool, this is a cheaper synchronization primitive than using | ||
56 | // // a Mutex object. This allows many UDP socket "reads" concurrently - when | ||
57 | // // Stop() is called, it attempts to obtain a writer lock which will then | ||
58 | // // wait until all outstanding operations are completed before shutting down. | ||
59 | // // this avoids the problem of closing the socket with outstanding operations | ||
60 | // // and trying to catch the inevitable ObjectDisposedException. | ||
61 | // private ReaderWriterLock rwLock = new ReaderWriterLock(); | ||
62 | |||
63 | // // number of outstanding operations. This is a reference count | ||
64 | // // which we use to ensure that the threads exit cleanly. Note that | ||
65 | // // we need this because the threads will potentially still need to process | ||
66 | // // data even after the socket is closed. | ||
67 | // private int rwOperationCount = 0; | ||
68 | |||
69 | // // the all important shutdownFlag. This is synchronized through the ReaderWriterLock. | ||
70 | // private volatile bool shutdownFlag = true; | ||
71 | |||
72 | // // the remote endpoint to communicate with | ||
73 | // protected IPEndPoint remoteEndPoint = null; | ||
74 | |||
75 | |||
76 | // /// <summary> | ||
77 | // /// Initialize the UDP packet handler in server mode | ||
78 | // /// </summary> | ||
79 | // /// <param name="port">Port to listening for incoming UDP packets on</param> | ||
80 | // public OpenSimUDPBase(int port) | ||
81 | // { | ||
82 | // udpPort = port; | ||
83 | // } | ||
84 | |||
85 | // /// <summary> | ||
86 | // /// Initialize the UDP packet handler in client mode | ||
87 | // /// </summary> | ||
88 | // /// <param name="endPoint">Remote UDP server to connect to</param> | ||
89 | // public OpenSimUDPBase(IPEndPoint endPoint) | ||
90 | // { | ||
91 | // remoteEndPoint = endPoint; | ||
92 | // udpPort = 0; | ||
93 | // } | ||
94 | |||
95 | // /// <summary> | ||
96 | // /// | ||
97 | // /// </summary> | ||
98 | // public void Start() | ||
99 | // { | ||
100 | // if (shutdownFlag) | ||
101 | // { | ||
102 | // if (remoteEndPoint == null) | ||
103 | // { | ||
104 | // // Server mode | ||
105 | |||
106 | // // create and bind the socket | ||
107 | // IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort); | ||
108 | // udpSocket = new Socket( | ||
109 | // AddressFamily.InterNetwork, | ||
110 | // SocketType.Dgram, | ||
111 | // ProtocolType.Udp); | ||
112 | // udpSocket.Bind(ipep); | ||
113 | // } | ||
114 | // else | ||
115 | // { | ||
116 | // // Client mode | ||
117 | // IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort); | ||
118 | // udpSocket = new Socket( | ||
119 | // AddressFamily.InterNetwork, | ||
120 | // SocketType.Dgram, | ||
121 | // ProtocolType.Udp); | ||
122 | // udpSocket.Bind(ipep); | ||
123 | // //udpSocket.Connect(remoteEndPoint); | ||
124 | // } | ||
125 | |||
126 | // // we're not shutting down, we're starting up | ||
127 | // shutdownFlag = false; | ||
128 | |||
129 | // // kick off an async receive. The Start() method will return, the | ||
130 | // // actual receives will occur asynchronously and will be caught in | ||
131 | // // AsyncEndRecieve(). | ||
132 | // AsyncBeginReceive(); | ||
133 | // } | ||
134 | // } | ||
135 | |||
136 | // /// <summary> | ||
137 | // /// | ||
138 | // /// </summary> | ||
139 | // public void Stop() | ||
140 | // { | ||
141 | // if (!shutdownFlag) | ||
142 | // { | ||
143 | // // wait indefinitely for a writer lock. Once this is called, the .NET runtime | ||
144 | // // will deny any more reader locks, in effect blocking all other send/receive | ||
145 | // // threads. Once we have the lock, we set shutdownFlag to inform the other | ||
146 | // // threads that the socket is closed. | ||
147 | // rwLock.AcquireWriterLock(-1); | ||
148 | // shutdownFlag = true; | ||
149 | // udpSocket.Close(); | ||
150 | // rwLock.ReleaseWriterLock(); | ||
151 | |||
152 | // // wait for any pending operations to complete on other | ||
153 | // // threads before exiting. | ||
154 | // const int FORCE_STOP = 100; | ||
155 | // int i = 0; | ||
156 | // while (rwOperationCount > 0 && i < FORCE_STOP) | ||
157 | // { | ||
158 | // Thread.Sleep(10); | ||
159 | // ++i; | ||
160 | // } | ||
161 | |||
162 | // if (i >= FORCE_STOP) | ||
163 | // { | ||
164 | // Logger.Log("UDPBase.Stop() forced shutdown while waiting on pending operations", | ||
165 | // Helpers.LogLevel.Warning); | ||
166 | // } | ||
167 | // } | ||
168 | // } | ||
169 | |||
170 | // /// <summary> | ||
171 | // /// | ||
172 | // /// </summary> | ||
173 | // public bool IsRunning | ||
174 | // { | ||
175 | // get { return !shutdownFlag; } | ||
176 | // } | ||
177 | |||
178 | // private void AsyncBeginReceive() | ||
179 | // { | ||
180 | // // this method actually kicks off the async read on the socket. | ||
181 | // // we aquire a reader lock here to ensure that no other thread | ||
182 | // // is trying to set shutdownFlag and close the socket. | ||
183 | // rwLock.AcquireReaderLock(-1); | ||
184 | |||
185 | // if (!shutdownFlag) | ||
186 | // { | ||
187 | // // increment the count of pending operations | ||
188 | // Interlocked.Increment(ref rwOperationCount); | ||
189 | |||
190 | // // allocate a packet buffer | ||
191 | // //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); | ||
192 | // UDPPacketBuffer buf = new UDPPacketBuffer(); | ||
193 | |||
194 | // try | ||
195 | // { | ||
196 | // // kick off an async read | ||
197 | // udpSocket.BeginReceiveFrom( | ||
198 | // //wrappedBuffer.Instance.Data, | ||
199 | // buf.Data, | ||
200 | // 0, | ||
201 | // UDPPacketBuffer.BUFFER_SIZE, | ||
202 | // SocketFlags.None, | ||
203 | // //ref wrappedBuffer.Instance.RemoteEndPoint, | ||
204 | // ref buf.RemoteEndPoint, | ||
205 | // new AsyncCallback(AsyncEndReceive), | ||
206 | // //wrappedBuffer); | ||
207 | // buf); | ||
208 | // } | ||
209 | // catch (SocketException) | ||
210 | // { | ||
211 | // // something bad happened | ||
212 | // //Logger.Log( | ||
213 | // // "A SocketException occurred in UDPServer.AsyncBeginReceive()", | ||
214 | // // Helpers.LogLevel.Error, se); | ||
215 | |||
216 | // // an error occurred, therefore the operation is void. Decrement the reference count. | ||
217 | // Interlocked.Decrement(ref rwOperationCount); | ||
218 | // } | ||
219 | // } | ||
220 | |||
221 | // // we're done with the socket for now, release the reader lock. | ||
222 | // rwLock.ReleaseReaderLock(); | ||
223 | // } | ||
224 | |||
225 | // private void AsyncEndReceive(IAsyncResult iar) | ||
226 | // { | ||
227 | // // Asynchronous receive operations will complete here through the call | ||
228 | // // to AsyncBeginReceive | ||
229 | |||
230 | // // aquire a reader lock | ||
231 | // rwLock.AcquireReaderLock(-1); | ||
232 | |||
233 | // if (!shutdownFlag) | ||
234 | // { | ||
235 | // // get the buffer that was created in AsyncBeginReceive | ||
236 | // // this is the received data | ||
237 | // //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState; | ||
238 | // //UDPPacketBuffer buffer = wrappedBuffer.Instance; | ||
239 | // UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; | ||
240 | |||
241 | // try | ||
242 | // { | ||
243 | // // get the length of data actually read from the socket, store it with the | ||
244 | // // buffer | ||
245 | // buffer.DataLength = udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); | ||
246 | |||
247 | // // this operation is now complete, decrement the reference count | ||
248 | // Interlocked.Decrement(ref rwOperationCount); | ||
249 | |||
250 | // // we're done with the socket, release the reader lock | ||
251 | // rwLock.ReleaseReaderLock(); | ||
252 | |||
253 | // // call the abstract method PacketReceived(), passing the buffer that | ||
254 | // // has just been filled from the socket read. | ||
255 | // PacketReceived(buffer); | ||
256 | // } | ||
257 | // catch (SocketException) | ||
258 | // { | ||
259 | // // an error occurred, therefore the operation is void. Decrement the reference count. | ||
260 | // Interlocked.Decrement(ref rwOperationCount); | ||
261 | |||
262 | // // we're done with the socket for now, release the reader lock. | ||
263 | // rwLock.ReleaseReaderLock(); | ||
264 | // } | ||
265 | // finally | ||
266 | // { | ||
267 | // // start another receive - this keeps the server going! | ||
268 | // AsyncBeginReceive(); | ||
269 | |||
270 | // //wrappedBuffer.Dispose(); | ||
271 | // } | ||
272 | // } | ||
273 | // else | ||
274 | // { | ||
275 | // // nothing bad happened, but we are done with the operation | ||
276 | // // decrement the reference count and release the reader lock | ||
277 | // Interlocked.Decrement(ref rwOperationCount); | ||
278 | // rwLock.ReleaseReaderLock(); | ||
279 | // } | ||
280 | // } | ||
281 | |||
282 | // public void AsyncBeginSend(UDPPacketBuffer buf) | ||
283 | // { | ||
284 | // rwLock.AcquireReaderLock(-1); | ||
285 | |||
286 | // if (!shutdownFlag) | ||
287 | // { | ||
288 | // try | ||
289 | // { | ||
290 | // Interlocked.Increment(ref rwOperationCount); | ||
291 | // udpSocket.BeginSendTo( | ||
292 | // buf.Data, | ||
293 | // 0, | ||
294 | // buf.DataLength, | ||
295 | // SocketFlags.None, | ||
296 | // buf.RemoteEndPoint, | ||
297 | // new AsyncCallback(AsyncEndSend), | ||
298 | // buf); | ||
299 | // } | ||
300 | // catch (SocketException) | ||
301 | // { | ||
302 | // //Logger.Log( | ||
303 | // // "A SocketException occurred in UDPServer.AsyncBeginSend()", | ||
304 | // // Helpers.LogLevel.Error, se); | ||
305 | // } | ||
306 | // } | ||
307 | |||
308 | // rwLock.ReleaseReaderLock(); | ||
309 | // } | ||
310 | |||
311 | // private void AsyncEndSend(IAsyncResult iar) | ||
312 | // { | ||
313 | // rwLock.AcquireReaderLock(-1); | ||
314 | |||
315 | // if (!shutdownFlag) | ||
316 | // { | ||
317 | // UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; | ||
318 | |||
319 | // try | ||
320 | // { | ||
321 | // int bytesSent = udpSocket.EndSendTo(iar); | ||
322 | |||
323 | // // note that call to the abstract PacketSent() method - we are passing the number | ||
324 | // // of bytes sent in a separate parameter, since we can't use buffer.DataLength which | ||
325 | // // is the number of bytes to send (or bytes received depending upon whether this | ||
326 | // // buffer was part of a send or a receive). | ||
327 | // PacketSent(buffer, bytesSent); | ||
328 | // } | ||
329 | // catch (SocketException) | ||
330 | // { | ||
331 | // //Logger.Log( | ||
332 | // // "A SocketException occurred in UDPServer.AsyncEndSend()", | ||
333 | // // Helpers.LogLevel.Error, se); | ||
334 | // } | ||
335 | // } | ||
336 | |||
337 | // Interlocked.Decrement(ref rwOperationCount); | ||
338 | // rwLock.ReleaseReaderLock(); | ||
339 | // } | ||
340 | // } | ||
341 | //} | ||
342 | |||
343 | //--------- Original Version ------------------- | ||
344 | |||
345 | |||
346 | namespace OpenSim.Region.ClientStack.LindenUDP | ||
347 | { | 35 | { |
348 | /// <summary> | 36 | /// <summary> |
349 | /// | 37 | /// Base UDP server |
350 | /// </summary> | 38 | /// </summary> |
351 | public abstract class OpenSimUDPBase | 39 | public abstract class OpenSimUDPBase |
352 | { | 40 | { |
353 | // these abstract methods must be implemented in a derived class to actually do | 41 | private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
354 | // something with the packets that are sent and received. | 42 | |
43 | /// <summary> | ||
44 | /// This method is called when an incoming packet is received | ||
45 | /// </summary> | ||
46 | /// <param name="buffer">Incoming packet buffer</param> | ||
355 | protected abstract void PacketReceived(UDPPacketBuffer buffer); | 47 | protected abstract void PacketReceived(UDPPacketBuffer buffer); |
48 | |||
49 | /// <summary> | ||
50 | /// This method is called when an outgoing packet is sent | ||
51 | /// </summary> | ||
52 | /// <param name="buffer">Outgoing packet buffer</param> | ||
53 | /// <param name="bytesSent">Number of bytes written to the wire</param> | ||
356 | protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent); | 54 | protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent); |
357 | 55 | ||
358 | // the port to listen on | 56 | /// <summary>UDP port to bind to in server mode</summary> |
359 | internal int udpPort; | 57 | protected int m_udpPort; |
360 | 58 | ||
361 | // the UDP socket | 59 | /// <summary>Local IP address to bind to in server mode</summary> |
362 | private Socket udpSocket; | 60 | protected IPAddress m_localBindAddress; |
363 | 61 | ||
364 | // the all important shutdownFlag. | 62 | /// <summary>UDP socket, used in either client or server mode</summary> |
365 | private volatile bool shutdownFlag = true; | 63 | private Socket m_udpSocket; |
366 | 64 | ||
367 | // the remote endpoint to communicate with | 65 | /// <summary>The all important shutdown flag</summary> |
368 | protected IPEndPoint remoteEndPoint = null; | 66 | private volatile bool m_shutdownFlag = true; |
369 | 67 | ||
370 | /// <summary> | 68 | /// <summary>Returns true if the server is currently listening, otherwise false</summary> |
371 | /// Initialize the UDP packet handler in server mode | 69 | public bool IsRunning { get { return !m_shutdownFlag; } } |
372 | /// </summary> | ||
373 | /// <param name="port">Port to listening for incoming UDP packets on</param> | ||
374 | public OpenSimUDPBase(int port) | ||
375 | { | ||
376 | udpPort = port; | ||
377 | } | ||
378 | 70 | ||
379 | /// <summary> | 71 | /// <summary> |
380 | /// Initialize the UDP packet handler in client mode | 72 | /// Default constructor |
381 | /// </summary> | 73 | /// </summary> |
382 | /// <param name="endPoint">Remote UDP server to connect to</param> | 74 | /// <param name="bindAddress">Local IP address to bind the server to</param> |
383 | public OpenSimUDPBase(IPEndPoint endPoint) | 75 | /// <param name="port">Port to listening for incoming UDP packets on</param> |
76 | public OpenSimUDPBase(IPAddress bindAddress, int port) | ||
384 | { | 77 | { |
385 | remoteEndPoint = endPoint; | 78 | m_localBindAddress = bindAddress; |
386 | udpPort = 0; | 79 | m_udpPort = port; |
387 | } | 80 | } |
388 | 81 | ||
389 | /// <summary> | 82 | /// <summary> |
390 | /// | 83 | /// Start the UDP server |
391 | /// </summary> | 84 | /// </summary> |
85 | /// <remarks>This method will attempt to set the SIO_UDP_CONNRESET flag | ||
86 | /// on the socket to get newer versions of Windows to behave in a sane | ||
87 | /// manner (not throwing an exception when the remote side resets the | ||
88 | /// connection). This call is ignored on Mono where the flag is not | ||
89 | /// necessary</remarks> | ||
392 | public void Start() | 90 | public void Start() |
393 | { | 91 | { |
394 | if (shutdownFlag) | 92 | if (m_shutdownFlag) |
395 | { | 93 | { |
396 | const int SIO_UDP_CONNRESET = -1744830452; | 94 | const int SIO_UDP_CONNRESET = -1744830452; |
397 | 95 | ||
398 | IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort); | 96 | IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); |
399 | udpSocket = new Socket( | 97 | m_udpSocket = new Socket( |
400 | AddressFamily.InterNetwork, | 98 | AddressFamily.InterNetwork, |
401 | SocketType.Dgram, | 99 | SocketType.Dgram, |
402 | ProtocolType.Udp); | 100 | ProtocolType.Udp); |
@@ -404,16 +102,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
404 | { | 102 | { |
405 | // this udp socket flag is not supported under mono, | 103 | // this udp socket flag is not supported under mono, |
406 | // so we'll catch the exception and continue | 104 | // so we'll catch the exception and continue |
407 | udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null); | 105 | m_udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null); |
106 | m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag set"); | ||
408 | } | 107 | } |
409 | catch (SocketException) | 108 | catch (SocketException) |
410 | { | 109 | { |
411 | Logger.DebugLog("UDP SIO_UDP_CONNRESET flag not supported on this platform"); | 110 | m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag not supported on this platform, ignoring"); |
412 | } | 111 | } |
413 | udpSocket.Bind(ipep); | 112 | m_udpSocket.Bind(ipep); |
414 | 113 | ||
415 | // we're not shutting down, we're starting up | 114 | // we're not shutting down, we're starting up |
416 | shutdownFlag = false; | 115 | m_shutdownFlag = false; |
417 | 116 | ||
418 | // kick off an async receive. The Start() method will return, the | 117 | // kick off an async receive. The Start() method will return, the |
419 | // actual receives will occur asynchronously and will be caught in | 118 | // actual receives will occur asynchronously and will be caught in |
@@ -423,41 +122,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
423 | } | 122 | } |
424 | 123 | ||
425 | /// <summary> | 124 | /// <summary> |
426 | /// | 125 | /// Stops the UDP server |
427 | /// </summary> | 126 | /// </summary> |
428 | public void Stop() | 127 | public void Stop() |
429 | { | 128 | { |
430 | if (!shutdownFlag) | 129 | if (!m_shutdownFlag) |
431 | { | 130 | { |
432 | // wait indefinitely for a writer lock. Once this is called, the .NET runtime | 131 | // wait indefinitely for a writer lock. Once this is called, the .NET runtime |
433 | // will deny any more reader locks, in effect blocking all other send/receive | 132 | // will deny any more reader locks, in effect blocking all other send/receive |
434 | // threads. Once we have the lock, we set shutdownFlag to inform the other | 133 | // threads. Once we have the lock, we set shutdownFlag to inform the other |
435 | // threads that the socket is closed. | 134 | // threads that the socket is closed. |
436 | shutdownFlag = true; | 135 | m_shutdownFlag = true; |
437 | udpSocket.Close(); | 136 | m_udpSocket.Close(); |
438 | } | 137 | } |
439 | } | 138 | } |
440 | 139 | ||
441 | /// <summary> | ||
442 | /// | ||
443 | /// </summary> | ||
444 | public bool IsRunning | ||
445 | { | ||
446 | get { return !shutdownFlag; } | ||
447 | } | ||
448 | |||
449 | private void AsyncBeginReceive() | 140 | private void AsyncBeginReceive() |
450 | { | 141 | { |
451 | // allocate a packet buffer | 142 | // allocate a packet buffer |
452 | //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); | 143 | //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); |
453 | UDPPacketBuffer buf = new UDPPacketBuffer(); | 144 | UDPPacketBuffer buf = new UDPPacketBuffer(); |
454 | 145 | ||
455 | if (!shutdownFlag) | 146 | if (!m_shutdownFlag) |
456 | { | 147 | { |
457 | try | 148 | try |
458 | { | 149 | { |
459 | // kick off an async read | 150 | // kick off an async read |
460 | udpSocket.BeginReceiveFrom( | 151 | m_udpSocket.BeginReceiveFrom( |
461 | //wrappedBuffer.Instance.Data, | 152 | //wrappedBuffer.Instance.Data, |
462 | buf.Data, | 153 | buf.Data, |
463 | 0, | 154 | 0, |
@@ -472,13 +163,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
472 | { | 163 | { |
473 | if (e.SocketErrorCode == SocketError.ConnectionReset) | 164 | if (e.SocketErrorCode == SocketError.ConnectionReset) |
474 | { | 165 | { |
475 | Logger.Log("SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + udpPort, Helpers.LogLevel.Error); | 166 | m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort); |
476 | bool salvaged = false; | 167 | bool salvaged = false; |
477 | while (!salvaged) | 168 | while (!salvaged) |
478 | { | 169 | { |
479 | try | 170 | try |
480 | { | 171 | { |
481 | udpSocket.BeginReceiveFrom( | 172 | m_udpSocket.BeginReceiveFrom( |
482 | //wrappedBuffer.Instance.Data, | 173 | //wrappedBuffer.Instance.Data, |
483 | buf.Data, | 174 | buf.Data, |
484 | 0, | 175 | 0, |
@@ -494,7 +185,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
494 | catch (ObjectDisposedException) { return; } | 185 | catch (ObjectDisposedException) { return; } |
495 | } | 186 | } |
496 | 187 | ||
497 | Logger.Log("Salvaged the UDP listener on port " + udpPort, Helpers.LogLevel.Info); | 188 | m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort); |
498 | } | 189 | } |
499 | } | 190 | } |
500 | catch (ObjectDisposedException) { } | 191 | catch (ObjectDisposedException) { } |
@@ -505,7 +196,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
505 | { | 196 | { |
506 | // Asynchronous receive operations will complete here through the call | 197 | // Asynchronous receive operations will complete here through the call |
507 | // to AsyncBeginReceive | 198 | // to AsyncBeginReceive |
508 | if (!shutdownFlag) | 199 | if (!m_shutdownFlag) |
509 | { | 200 | { |
510 | // start another receive - this keeps the server going! | 201 | // start another receive - this keeps the server going! |
511 | AsyncBeginReceive(); | 202 | AsyncBeginReceive(); |
@@ -520,7 +211,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
520 | { | 211 | { |
521 | // get the length of data actually read from the socket, store it with the | 212 | // get the length of data actually read from the socket, store it with the |
522 | // buffer | 213 | // buffer |
523 | buffer.DataLength = udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); | 214 | buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); |
524 | 215 | ||
525 | // call the abstract method PacketReceived(), passing the buffer that | 216 | // call the abstract method PacketReceived(), passing the buffer that |
526 | // has just been filled from the socket read. | 217 | // has just been filled from the socket read. |
@@ -529,16 +220,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
529 | catch (SocketException) { } | 220 | catch (SocketException) { } |
530 | catch (ObjectDisposedException) { } | 221 | catch (ObjectDisposedException) { } |
531 | //finally { wrappedBuffer.Dispose(); } | 222 | //finally { wrappedBuffer.Dispose(); } |
223 | |||
532 | } | 224 | } |
533 | } | 225 | } |
534 | 226 | ||
535 | public void AsyncBeginSend(UDPPacketBuffer buf) | 227 | public void AsyncBeginSend(UDPPacketBuffer buf) |
536 | { | 228 | { |
537 | if (!shutdownFlag) | 229 | if (!m_shutdownFlag) |
538 | { | 230 | { |
539 | try | 231 | try |
540 | { | 232 | { |
541 | udpSocket.BeginSendTo( | 233 | m_udpSocket.BeginSendTo( |
542 | buf.Data, | 234 | buf.Data, |
543 | 0, | 235 | 0, |
544 | buf.DataLength, | 236 | buf.DataLength, |
@@ -557,7 +249,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
557 | try | 249 | try |
558 | { | 250 | { |
559 | UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; | 251 | UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; |
560 | int bytesSent = udpSocket.EndSendTo(result); | 252 | int bytesSent = m_udpSocket.EndSendTo(result); |
561 | 253 | ||
562 | PacketSent(buf, bytesSent); | 254 | PacketSent(buf, bytesSent); |
563 | } | 255 | } |
@@ -566,4 +258,3 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
566 | } | 258 | } |
567 | } | 259 | } |
568 | } | 260 | } |
569 | |||
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs index 195ca57..f3242c1 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs | |||
@@ -103,6 +103,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
103 | } | 103 | } |
104 | 104 | ||
105 | /// <summary> | 105 | /// <summary> |
106 | /// Removes all elements from the collection | ||
107 | /// </summary> | ||
108 | public void Clear() | ||
109 | { | ||
110 | lock (SyncRoot) | ||
111 | packets.Clear(); | ||
112 | } | ||
113 | |||
114 | /// <summary> | ||
106 | /// Gets the packet with the lowest sequence number | 115 | /// Gets the packet with the lowest sequence number |
107 | /// </summary> | 116 | /// </summary> |
108 | /// <returns>The packet with the lowest sequence number, or null if the | 117 | /// <returns>The packet with the lowest sequence number, or null if the |
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/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index b885420..9b565ed 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs | |||
@@ -57,7 +57,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
57 | public string body; | 57 | public string body; |
58 | public int responseCode; | 58 | public int responseCode; |
59 | public string responseBody; | 59 | public string responseBody; |
60 | public ManualResetEvent ev; | 60 | //public ManualResetEvent ev; |
61 | public bool requestDone; | 61 | public bool requestDone; |
62 | public int startTime; | 62 | public int startTime; |
63 | public string uri; | 63 | public string uri; |
@@ -456,7 +456,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
456 | requestData.headers["x-query-string"] = queryString; | 456 | requestData.headers["x-query-string"] = queryString; |
457 | requestData.headers["x-script-url"] = url.url; | 457 | requestData.headers["x-script-url"] = url.url; |
458 | 458 | ||
459 | requestData.ev = new ManualResetEvent(false); | 459 | //requestData.ev = new ManualResetEvent(false); |
460 | lock (url.requests) | 460 | lock (url.requests) |
461 | { | 461 | { |
462 | url.requests.Add(requestID, requestData); | 462 | url.requests.Add(requestID, requestData); |
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 8ad4844..d651fd4 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 | ||
@@ -833,6 +833,11 @@ namespace OpenSim.Region.Examples.SimpleModule | |||
833 | set { m_circuitCode = value; } | 833 | set { m_circuitCode = value; } |
834 | } | 834 | } |
835 | 835 | ||
836 | public IPEndPoint RemoteEndPoint | ||
837 | { | ||
838 | get { return new IPEndPoint(IPAddress.Loopback, (ushort)m_circuitCode); } | ||
839 | } | ||
840 | |||
836 | public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) | 841 | public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) |
837 | { | 842 | { |
838 | 843 | ||
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index 4ae4dc3..ac89f7b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs | |||
@@ -390,6 +390,32 @@ namespace OpenSim.Region.Framework.Scenes | |||
390 | EventManager.TriggerScriptReset(part.LocalId, itemID); | 390 | EventManager.TriggerScriptReset(part.LocalId, itemID); |
391 | } | 391 | } |
392 | } | 392 | } |
393 | |||
394 | void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args) | ||
395 | { | ||
396 | // TODO: don't create new blocks if recycling an old packet | ||
397 | List<ViewerEffectPacket.EffectBlock> effectBlock = new List<ViewerEffectPacket.EffectBlock>(); | ||
398 | for (int i = 0; i < args.Count; i++) | ||
399 | { | ||
400 | ViewerEffectPacket.EffectBlock effect = new ViewerEffectPacket.EffectBlock(); | ||
401 | effect.AgentID = args[i].AgentID; | ||
402 | effect.Color = args[i].Color; | ||
403 | effect.Duration = args[i].Duration; | ||
404 | effect.ID = args[i].ID; | ||
405 | effect.Type = args[i].Type; | ||
406 | effect.TypeData = args[i].TypeData; | ||
407 | effectBlock.Add(effect); | ||
408 | } | ||
409 | ViewerEffectPacket.EffectBlock[] effectBlockArray = effectBlock.ToArray(); | ||
410 | |||
411 | ClientManager.ForEach( | ||
412 | delegate(IClientAPI client) | ||
413 | { | ||
414 | if (client.AgentId != remoteClient.AgentId) | ||
415 | client.SendViewerEffect(effectBlockArray); | ||
416 | } | ||
417 | ); | ||
418 | } | ||
393 | 419 | ||
394 | /// <summary> | 420 | /// <summary> |
395 | /// Handle a fetch inventory request from the client | 421 | /// Handle a fetch inventory request from the client |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0f351ce..9f14761 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -117,6 +117,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
117 | private volatile bool m_backingup = false; | 117 | private volatile bool m_backingup = false; |
118 | 118 | ||
119 | private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); | 119 | private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); |
120 | |||
121 | private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>(); | ||
120 | 122 | ||
121 | protected string m_simulatorVersion = "OpenSimulator Server"; | 123 | protected string m_simulatorVersion = "OpenSimulator Server"; |
122 | 124 | ||
@@ -246,8 +248,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
246 | 248 | ||
247 | private int m_update_physics = 1; | 249 | private int m_update_physics = 1; |
248 | private int m_update_entitymovement = 1; | 250 | private int m_update_entitymovement = 1; |
249 | private int m_update_entities = 1; // Run through all objects checking for updates | 251 | private int m_update_objects = 1; // Update objects which have scheduled themselves for updates |
250 | private int m_update_entitiesquick = 200; // Run through objects that have scheduled updates checking for updates | ||
251 | private int m_update_presences = 1; // Update scene presence movements | 252 | private int m_update_presences = 1; // Update scene presence movements |
252 | private int m_update_events = 1; | 253 | private int m_update_events = 1; |
253 | private int m_update_backup = 200; | 254 | private int m_update_backup = 200; |
@@ -867,7 +868,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
867 | Thread.Sleep(500); | 868 | Thread.Sleep(500); |
868 | 869 | ||
869 | // Stop all client threads. | 870 | // Stop all client threads. |
870 | ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(true); }); | 871 | ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); |
871 | 872 | ||
872 | // Stop updating the scene objects and agents. | 873 | // Stop updating the scene objects and agents. |
873 | //m_heartbeatTimer.Close(); | 874 | //m_heartbeatTimer.Close(); |
@@ -979,28 +980,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
979 | maintc = Environment.TickCount; | 980 | maintc = Environment.TickCount; |
980 | 981 | ||
981 | TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate; | 982 | TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate; |
982 | // Aquire a lock so only one update call happens at once | ||
983 | //updateLock.WaitOne(); | ||
984 | float physicsFPS = 0; | 983 | float physicsFPS = 0; |
985 | //m_log.Info("sadfadf" + m_neighbours.Count.ToString()); | ||
986 | int agentsInScene = m_sceneGraph.GetRootAgentCount() + m_sceneGraph.GetChildAgentCount(); | ||
987 | |||
988 | if (agentsInScene > 21) | ||
989 | { | ||
990 | if (m_update_entities == 1) | ||
991 | { | ||
992 | m_update_entities = 5; | ||
993 | StatsReporter.SetUpdateMS(6000); | ||
994 | } | ||
995 | } | ||
996 | else | ||
997 | { | ||
998 | if (m_update_entities == 5) | ||
999 | { | ||
1000 | m_update_entities = 1; | ||
1001 | StatsReporter.SetUpdateMS(3000); | ||
1002 | } | ||
1003 | } | ||
1004 | 984 | ||
1005 | frameMS = Environment.TickCount; | 985 | frameMS = Environment.TickCount; |
1006 | try | 986 | try |
@@ -1013,30 +993,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1013 | m_frame = 0; | 993 | m_frame = 0; |
1014 | 994 | ||
1015 | otherMS = Environment.TickCount; | 995 | otherMS = Environment.TickCount; |
1016 | // run through all entities looking for updates (slow) | ||
1017 | if (m_frame % m_update_entities == 0) | ||
1018 | { | ||
1019 | /* // Adam Experimental | ||
1020 | if (m_updateEntitiesThread == null) | ||
1021 | { | ||
1022 | m_updateEntitiesThread = new Thread(m_sceneGraph.UpdateEntities); | ||
1023 | |||
1024 | ThreadTracker.Add(m_updateEntitiesThread); | ||
1025 | } | ||
1026 | |||
1027 | if (m_updateEntitiesThread.ThreadState == ThreadState.Stopped) | ||
1028 | m_updateEntitiesThread.Start(); | ||
1029 | */ | ||
1030 | 996 | ||
1031 | m_sceneGraph.UpdateEntities(); | 997 | // Check if any objects have reached their targets |
1032 | } | 998 | CheckAtTargets(); |
999 | |||
1000 | // Update SceneObjectGroups that have scheduled themselves for updates | ||
1001 | // Objects queue their updates onto all scene presences | ||
1002 | if (m_frame % m_update_objects == 0) | ||
1003 | m_sceneGraph.UpdateObjectGroups(); | ||
1033 | 1004 | ||
1034 | // run through entities that have scheduled themselves for | 1005 | // Run through all ScenePresences looking for updates |
1035 | // updates looking for updates(faster) | 1006 | // Presence updates and queued object updates for each presence are sent to clients |
1036 | if (m_frame % m_update_entitiesquick == 0) | ||
1037 | m_sceneGraph.ProcessUpdates(); | ||
1038 | |||
1039 | // Run through scenepresences looking for updates | ||
1040 | if (m_frame % m_update_presences == 0) | 1007 | if (m_frame % m_update_presences == 0) |
1041 | m_sceneGraph.UpdatePresences(); | 1008 | m_sceneGraph.UpdatePresences(); |
1042 | 1009 | ||
@@ -1140,6 +1107,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
1140 | } | 1107 | } |
1141 | } | 1108 | } |
1142 | 1109 | ||
1110 | |||
1111 | public void AddGroupTarget(SceneObjectGroup grp) | ||
1112 | { | ||
1113 | lock(m_groupsWithTargets) | ||
1114 | m_groupsWithTargets[grp.UUID] = grp; | ||
1115 | } | ||
1116 | |||
1117 | public void RemoveGroupTarget(SceneObjectGroup grp) | ||
1118 | { | ||
1119 | lock(m_groupsWithTargets) | ||
1120 | m_groupsWithTargets.Remove(grp.UUID); | ||
1121 | } | ||
1122 | |||
1123 | private void CheckAtTargets() | ||
1124 | { | ||
1125 | lock (m_groupsWithTargets) | ||
1126 | { | ||
1127 | foreach (KeyValuePair<UUID, SceneObjectGroup> kvp in m_groupsWithTargets) | ||
1128 | { | ||
1129 | kvp.Value.checkAtTargets(); | ||
1130 | } | ||
1131 | } | ||
1132 | } | ||
1133 | |||
1134 | |||
1143 | /// <summary> | 1135 | /// <summary> |
1144 | /// Send out simstats data to all clients | 1136 | /// Send out simstats data to all clients |
1145 | /// </summary> | 1137 | /// </summary> |
@@ -1186,10 +1178,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1186 | if (!m_backingup) | 1178 | if (!m_backingup) |
1187 | { | 1179 | { |
1188 | m_backingup = true; | 1180 | m_backingup = true; |
1189 | Thread backupthread = new Thread(Backup); | 1181 | |
1190 | backupthread.Name = "BackupWriter"; | 1182 | System.ComponentModel.BackgroundWorker backupWorker = new System.ComponentModel.BackgroundWorker(); |
1191 | backupthread.IsBackground = true; | 1183 | backupWorker.DoWork += delegate(object sender, System.ComponentModel.DoWorkEventArgs e) { Backup(); }; |
1192 | backupthread.Start(); | 1184 | backupWorker.RunWorkerAsync(); |
1193 | } | 1185 | } |
1194 | } | 1186 | } |
1195 | 1187 | ||
@@ -2435,6 +2427,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2435 | /// <param name="client"></param> | 2427 | /// <param name="client"></param> |
2436 | public override void AddNewClient(IClientAPI client) | 2428 | public override void AddNewClient(IClientAPI client) |
2437 | { | 2429 | { |
2430 | ClientManager.Add(client); | ||
2431 | |||
2438 | CheckHeartbeat(); | 2432 | CheckHeartbeat(); |
2439 | SubscribeToClientEvents(client); | 2433 | SubscribeToClientEvents(client); |
2440 | ScenePresence presence; | 2434 | ScenePresence presence; |
@@ -2644,6 +2638,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2644 | public virtual void SubscribeToClientNetworkEvents(IClientAPI client) | 2638 | public virtual void SubscribeToClientNetworkEvents(IClientAPI client) |
2645 | { | 2639 | { |
2646 | client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats; | 2640 | client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats; |
2641 | client.OnViewerEffect += ProcessViewerEffect; | ||
2647 | } | 2642 | } |
2648 | 2643 | ||
2649 | protected virtual void UnsubscribeToClientEvents(IClientAPI client) | 2644 | protected virtual void UnsubscribeToClientEvents(IClientAPI client) |
@@ -2798,11 +2793,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2798 | public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) | 2793 | public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) |
2799 | { | 2794 | { |
2800 | client.OnNetworkStatsUpdate -= StatsReporter.AddPacketsStats; | 2795 | client.OnNetworkStatsUpdate -= StatsReporter.AddPacketsStats; |
2796 | client.OnViewerEffect -= ProcessViewerEffect; | ||
2801 | } | 2797 | } |
2802 | 2798 | ||
2803 | |||
2804 | |||
2805 | |||
2806 | /// <summary> | 2799 | /// <summary> |
2807 | /// Teleport an avatar to their home region | 2800 | /// Teleport an avatar to their home region |
2808 | /// </summary> | 2801 | /// </summary> |
@@ -3075,7 +3068,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3075 | agentTransactions.RemoveAgentAssetTransactions(agentID); | 3068 | agentTransactions.RemoveAgentAssetTransactions(agentID); |
3076 | } | 3069 | } |
3077 | 3070 | ||
3071 | // Remove the avatar from the scene | ||
3078 | m_sceneGraph.RemoveScenePresence(agentID); | 3072 | m_sceneGraph.RemoveScenePresence(agentID); |
3073 | ClientManager.Remove(agentID); | ||
3079 | 3074 | ||
3080 | try | 3075 | try |
3081 | { | 3076 | { |
@@ -3125,16 +3120,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3125 | } | 3120 | } |
3126 | 3121 | ||
3127 | /// <summary> | 3122 | /// <summary> |
3128 | /// Closes all endpoints with the circuitcode provided. | ||
3129 | /// </summary> | ||
3130 | /// <param name="circuitcode">Circuit Code of the endpoint to close</param> | ||
3131 | public override void CloseAllAgents(uint circuitcode) | ||
3132 | { | ||
3133 | // Called by ClientView to kill all circuit codes | ||
3134 | ClientManager.CloseAllAgents(circuitcode); | ||
3135 | } | ||
3136 | |||
3137 | /// <summary> | ||
3138 | /// Inform all other ScenePresences on this Scene that someone else has changed position on the minimap. | 3123 | /// Inform all other ScenePresences on this Scene that someone else has changed position on the minimap. |
3139 | /// </summary> | 3124 | /// </summary> |
3140 | public void NotifyMyCoarseLocationChange() | 3125 | public void NotifyMyCoarseLocationChange() |
@@ -3455,7 +3440,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3455 | loggingOffUser.ControllingClient.Kick(message); | 3440 | loggingOffUser.ControllingClient.Kick(message); |
3456 | // Give them a second to receive the message! | 3441 | // Give them a second to receive the message! |
3457 | Thread.Sleep(1000); | 3442 | Thread.Sleep(1000); |
3458 | loggingOffUser.ControllingClient.Close(true); | 3443 | loggingOffUser.ControllingClient.Close(); |
3459 | } | 3444 | } |
3460 | else | 3445 | else |
3461 | { | 3446 | { |
@@ -3626,7 +3611,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3626 | presence.ControllingClient.SendShutdownConnectionNotice(); | 3611 | presence.ControllingClient.SendShutdownConnectionNotice(); |
3627 | } | 3612 | } |
3628 | 3613 | ||
3629 | presence.ControllingClient.Close(true); | 3614 | presence.ControllingClient.Close(); |
3630 | return true; | 3615 | return true; |
3631 | } | 3616 | } |
3632 | 3617 | ||
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index 0ac4ed4..cf5c3c8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs | |||
@@ -196,8 +196,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
196 | /// <param name="agentID"></param> | 196 | /// <param name="agentID"></param> |
197 | public abstract void RemoveClient(UUID agentID); | 197 | public abstract void RemoveClient(UUID agentID); |
198 | 198 | ||
199 | public abstract void CloseAllAgents(uint circuitcode); | ||
200 | |||
201 | #endregion | 199 | #endregion |
202 | 200 | ||
203 | /// <summary> | 201 | /// <summary> |
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 54ac792..9cd2247 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -77,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
77 | 77 | ||
78 | protected RegionInfo m_regInfo; | 78 | protected RegionInfo m_regInfo; |
79 | protected Scene m_parentScene; | 79 | protected Scene m_parentScene; |
80 | protected Dictionary<UUID, EntityBase> m_updateList = new Dictionary<UUID, EntityBase>(); | 80 | protected Dictionary<UUID, SceneObjectGroup> m_updateList = new Dictionary<UUID, SceneObjectGroup>(); |
81 | protected int m_numRootAgents = 0; | 81 | protected int m_numRootAgents = 0; |
82 | protected int m_numPrim = 0; | 82 | protected int m_numPrim = 0; |
83 | protected int m_numChildAgents = 0; | 83 | protected int m_numChildAgents = 0; |
@@ -155,16 +155,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
155 | } | 155 | } |
156 | } | 156 | } |
157 | 157 | ||
158 | protected internal void UpdateEntities() | ||
159 | { | ||
160 | List<EntityBase> updateEntities = GetEntities(); | ||
161 | |||
162 | foreach (EntityBase entity in updateEntities) | ||
163 | { | ||
164 | entity.Update(); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | protected internal void UpdatePresences() | 158 | protected internal void UpdatePresences() |
169 | { | 159 | { |
170 | List<ScenePresence> updateScenePresences = GetScenePresences(); | 160 | List<ScenePresence> updateScenePresences = GetScenePresences(); |
@@ -365,12 +355,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
365 | } | 355 | } |
366 | 356 | ||
367 | /// <summary> | 357 | /// <summary> |
368 | /// Add an entity to the list of prims to process on the next update | 358 | /// Add an object to the list of prims to process on the next update |
369 | /// </summary> | 359 | /// </summary> |
370 | /// <param name="obj"> | 360 | /// <param name="obj"> |
371 | /// A <see cref="EntityBase"/> | 361 | /// A <see cref="SceneObjectGroup"/> |
372 | /// </param> | 362 | /// </param> |
373 | protected internal void AddToUpdateList(EntityBase obj) | 363 | protected internal void AddToUpdateList(SceneObjectGroup obj) |
374 | { | 364 | { |
375 | lock (m_updateList) | 365 | lock (m_updateList) |
376 | { | 366 | { |
@@ -381,18 +371,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
381 | /// <summary> | 371 | /// <summary> |
382 | /// Process all pending updates | 372 | /// Process all pending updates |
383 | /// </summary> | 373 | /// </summary> |
384 | protected internal void ProcessUpdates() | 374 | protected internal void UpdateObjectGroups() |
385 | { | 375 | { |
386 | Dictionary<UUID, EntityBase> updates; | 376 | Dictionary<UUID, SceneObjectGroup> updates; |
387 | // Some updates add more updates to the updateList. | 377 | // Some updates add more updates to the updateList. |
388 | // Get the current list of updates and clear the list before iterating | 378 | // Get the current list of updates and clear the list before iterating |
389 | lock (m_updateList) | 379 | lock (m_updateList) |
390 | { | 380 | { |
391 | updates = new Dictionary<UUID, EntityBase>(m_updateList); | 381 | updates = new Dictionary<UUID, SceneObjectGroup>(m_updateList); |
392 | m_updateList.Clear(); | 382 | m_updateList.Clear(); |
393 | } | 383 | } |
394 | // Go through all timers | 384 | // Go through all updates |
395 | foreach (KeyValuePair<UUID, EntityBase> kvp in updates) | 385 | foreach (KeyValuePair<UUID, SceneObjectGroup> kvp in updates) |
396 | { | 386 | { |
397 | // Don't abort the whole update if one entity happens to give us an exception. | 387 | // Don't abort the whole update if one entity happens to give us an exception. |
398 | try | 388 | try |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 6a10618..d4cef7d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -1234,6 +1234,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1234 | { | 1234 | { |
1235 | lock (m_targets) | 1235 | lock (m_targets) |
1236 | m_targets.Clear(); | 1236 | m_targets.Clear(); |
1237 | m_scene.RemoveGroupTarget(this); | ||
1237 | } | 1238 | } |
1238 | 1239 | ||
1239 | ScheduleGroupForFullUpdate(); | 1240 | ScheduleGroupForFullUpdate(); |
@@ -1864,12 +1865,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1864 | m_rootPart.UpdateFlag = 1; | 1865 | m_rootPart.UpdateFlag = 1; |
1865 | lastPhysGroupPos = AbsolutePosition; | 1866 | lastPhysGroupPos = AbsolutePosition; |
1866 | } | 1867 | } |
1867 | //foreach (SceneObjectPart part in m_parts.Values) | ||
1868 | //{ | ||
1869 | //if (part.UpdateFlag == 0) part.UpdateFlag = 1; | ||
1870 | //} | ||
1871 | |||
1872 | checkAtTargets(); | ||
1873 | 1868 | ||
1874 | if (UsePhysics && ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1) | 1869 | if (UsePhysics && ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1) |
1875 | || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1) | 1870 | || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1) |
@@ -3114,6 +3109,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3114 | { | 3109 | { |
3115 | m_targets.Add(handle, waypoint); | 3110 | m_targets.Add(handle, waypoint); |
3116 | } | 3111 | } |
3112 | m_scene.AddGroupTarget(this); | ||
3117 | return (int)handle; | 3113 | return (int)handle; |
3118 | } | 3114 | } |
3119 | 3115 | ||
@@ -3121,12 +3117,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
3121 | { | 3117 | { |
3122 | lock (m_targets) | 3118 | lock (m_targets) |
3123 | { | 3119 | { |
3124 | if (m_targets.ContainsKey((uint)handle)) | 3120 | m_targets.Remove((uint)handle); |
3125 | m_targets.Remove((uint)handle); | 3121 | if (m_targets.Count == 0) |
3122 | m_scene.RemoveGroupTarget(this); | ||
3126 | } | 3123 | } |
3127 | } | 3124 | } |
3128 | 3125 | ||
3129 | private void checkAtTargets() | 3126 | public void checkAtTargets() |
3130 | { | 3127 | { |
3131 | if (m_scriptListens_atTarget || m_scriptListens_notAtTarget) | 3128 | if (m_scriptListens_atTarget || m_scriptListens_notAtTarget) |
3132 | { | 3129 | { |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneBaseTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneBaseTests.cs index 5c9e66f..8230f32 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneBaseTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneBaseTests.cs | |||
@@ -61,11 +61,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
61 | throw new NotImplementedException(); | 61 | throw new NotImplementedException(); |
62 | } | 62 | } |
63 | 63 | ||
64 | public override void CloseAllAgents(uint circuitcode) | ||
65 | { | ||
66 | throw new NotImplementedException(); | ||
67 | } | ||
68 | |||
69 | public override void OtherRegionUp(GridRegion otherRegion) | 64 | public override void OtherRegionUp(GridRegion otherRegion) |
70 | { | 65 | { |
71 | throw new NotImplementedException(); | 66 | throw new NotImplementedException(); |
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs index 4b199ac..4c2a4b9 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs | |||
@@ -64,7 +64,6 @@ 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); | ||
68 | cv.Start(); | 67 | cv.Start(); |
69 | m_log.Info("[IRCd] Added user to Scene"); | 68 | m_log.Info("[IRCd] Added user to Scene"); |
70 | } | 69 | } |
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..41a6255 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs | |||
@@ -155,7 +155,6 @@ 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); | ||
159 | p_scene.AddNewClient(npcAvatar); | 158 | p_scene.AddNewClient(npcAvatar); |
160 | 159 | ||
161 | ScenePresence sp; | 160 | ScenePresence sp; |
diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs index a283840..47ce615 100644 --- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs +++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs | |||
@@ -69,7 +69,7 @@ namespace PrimMesher | |||
69 | 69 | ||
70 | public Quat Identity() | 70 | public Quat Identity() |
71 | { | 71 | { |
72 | return new Quat(0.0f, 0.0f, 0.0f, 1.1f); | 72 | return new Quat(0.0f, 0.0f, 0.0f, 1.0f); |
73 | } | 73 | } |
74 | 74 | ||
75 | public float Length() | 75 | public float Length() |
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 2b54890..5c838c5 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs | |||
@@ -393,6 +393,11 @@ namespace OpenSim.Tests.Common.Mock | |||
393 | set { m_circuitCode = value; } | 393 | set { m_circuitCode = value; } |
394 | } | 394 | } |
395 | 395 | ||
396 | public IPEndPoint RemoteEndPoint | ||
397 | { | ||
398 | get { return new IPEndPoint(IPAddress.Loopback, (ushort)m_circuitCode); } | ||
399 | } | ||
400 | |||
396 | /// <summary> | 401 | /// <summary> |
397 | /// Constructor | 402 | /// Constructor |
398 | /// </summary> | 403 | /// </summary> |
@@ -865,7 +870,7 @@ namespace OpenSim.Tests.Common.Mock | |||
865 | { | 870 | { |
866 | } | 871 | } |
867 | 872 | ||
868 | public void Close(bool ShutdownCircuit) | 873 | public void Close() |
869 | { | 874 | { |
870 | m_scene.RemoveClient(AgentId); | 875 | m_scene.RemoveClient(AgentId); |
871 | } | 876 | } |