aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP
diff options
context:
space:
mode:
authorDiva Canto2011-04-30 09:24:15 -0700
committerDiva Canto2011-04-30 09:24:15 -0700
commitd8ee0cbe1cf93ca521f52ce39aa2a15cb5784e48 (patch)
tree4958279e2c75dcfa50021a8e559fb6ddc0a76725 /OpenSim/Region/ClientStack/Linden/UDP
parentDelaying starting the scripts on TPs and crossings until the agent is root. (diff)
downloadopensim-SC_OLD-d8ee0cbe1cf93ca521f52ce39aa2a15cb5784e48.zip
opensim-SC_OLD-d8ee0cbe1cf93ca521f52ce39aa2a15cb5784e48.tar.gz
opensim-SC_OLD-d8ee0cbe1cf93ca521f52ce39aa2a15cb5784e48.tar.bz2
opensim-SC_OLD-d8ee0cbe1cf93ca521f52ce39aa2a15cb5784e48.tar.xz
First stab at cleaning up Caps. Compiles. Untested.
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs57
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/IncomingPacketHistoryCollection.cs73
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs398
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs12123
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs257
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs697
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs1274
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs284
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OutgoingPacket.cs75
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs299
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs72
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs106
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLPacketServer.cs72
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs153
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs111
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs393
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs219
17 files changed, 16663 insertions, 0 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
new file mode 100644
index 0000000..90b3ede
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
@@ -0,0 +1,57 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenSim.Framework;
30using OpenMetaverse;
31using OpenMetaverse.Packets;
32
33namespace OpenSim.Region.ClientStack.LindenUDP
34{
35 /// <summary>
36 /// Holds a reference to a <seealso cref="LLUDPClient"/> and a <seealso cref="Packet"/>
37 /// for incoming packets
38 /// </summary>
39 public sealed class IncomingPacket
40 {
41 /// <summary>Client this packet came from</summary>
42 public LLUDPClient Client;
43 /// <summary>Packet data that has been received</summary>
44 public Packet Packet;
45
46 /// <summary>
47 /// Default constructor
48 /// </summary>
49 /// <param name="client">Reference to the client this packet came from</param>
50 /// <param name="packet">Packet data</param>
51 public IncomingPacket(LLUDPClient client, Packet packet)
52 {
53 Client = client;
54 Packet = packet;
55 }
56 }
57}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacketHistoryCollection.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacketHistoryCollection.cs
new file mode 100644
index 0000000..1f73a1d
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacketHistoryCollection.cs
@@ -0,0 +1,73 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30
31namespace OpenSim.Region.ClientStack.LindenUDP
32{
33 /// <summary>
34 /// A circular buffer and hashset for tracking incoming packet sequence
35 /// numbers
36 /// </summary>
37 public sealed class IncomingPacketHistoryCollection
38 {
39 private readonly uint[] m_items;
40 private HashSet<uint> m_hashSet;
41 private int m_first;
42 private int m_next;
43 private int m_capacity;
44
45 public IncomingPacketHistoryCollection(int capacity)
46 {
47 this.m_capacity = capacity;
48 m_items = new uint[capacity];
49 m_hashSet = new HashSet<uint>();
50 }
51
52 public bool TryEnqueue(uint ack)
53 {
54 lock (m_hashSet)
55 {
56 if (m_hashSet.Add(ack))
57 {
58 m_items[m_next] = ack;
59 m_next = (m_next + 1) % m_capacity;
60 if (m_next == m_first)
61 {
62 m_hashSet.Remove(m_items[m_first]);
63 m_first = (m_first + 1) % m_capacity;
64 }
65
66 return true;
67 }
68 }
69
70 return false;
71 }
72 }
73}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
new file mode 100644
index 0000000..e9e2dca
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
@@ -0,0 +1,398 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenMetaverse.Imaging;
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Services.Interfaces;
35using log4net;
36using System.Reflection;
37
38namespace OpenSim.Region.ClientStack.LindenUDP
39{
40 /// <summary>
41 /// Stores information about a current texture download and a reference to the texture asset
42 /// </summary>
43 public class J2KImage
44 {
45 private const int IMAGE_PACKET_SIZE = 1000;
46 private const int FIRST_PACKET_SIZE = 600;
47
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 public uint LastSequence;
51 public float Priority;
52 public uint StartPacket;
53 public sbyte DiscardLevel;
54 public UUID TextureID;
55 public IJ2KDecoder J2KDecoder;
56 public IAssetService AssetService;
57 public UUID AgentID;
58 public IInventoryAccessModule InventoryAccessModule;
59 public OpenJPEG.J2KLayerInfo[] Layers;
60 public bool IsDecoded;
61 public bool HasAsset;
62 public C5.IPriorityQueueHandle<J2KImage> PriorityQueueHandle;
63
64 private uint m_currentPacket;
65 private bool m_decodeRequested;
66 private bool m_assetRequested;
67 private bool m_sentInfo;
68 private uint m_stopPacket;
69 private byte[] m_asset;
70 private LLImageManager m_imageManager;
71
72 public J2KImage(LLImageManager imageManager)
73 {
74 m_imageManager = imageManager;
75 }
76
77 /// <summary>
78 /// Sends packets for this texture to a client until packetsToSend is
79 /// hit or the transfer completes
80 /// </summary>
81 /// <param name="client">Reference to the client that the packets are destined for</param>
82 /// <param name="packetsToSend">Maximum number of packets to send during this call</param>
83 /// <param name="packetsSent">Number of packets sent during this call</param>
84 /// <returns>True if the transfer completes at the current discard level, otherwise false</returns>
85 public bool SendPackets(LLClientView client, int packetsToSend, out int packetsSent)
86 {
87 packetsSent = 0;
88
89 if (m_currentPacket <= m_stopPacket)
90 {
91 bool sendMore = true;
92
93 if (!m_sentInfo || (m_currentPacket == 0))
94 {
95 sendMore = !SendFirstPacket(client);
96
97 m_sentInfo = true;
98 ++m_currentPacket;
99 ++packetsSent;
100 }
101 if (m_currentPacket < 2)
102 {
103 m_currentPacket = 2;
104 }
105
106 while (sendMore && packetsSent < packetsToSend && m_currentPacket <= m_stopPacket)
107 {
108 sendMore = SendPacket(client);
109 ++m_currentPacket;
110 ++packetsSent;
111 }
112 }
113
114 return (m_currentPacket > m_stopPacket);
115 }
116
117 public void RunUpdate()
118 {
119 //This is where we decide what we need to update
120 //and assign the real discardLevel and packetNumber
121 //assuming of course that the connected client might be bonkers
122
123 if (!HasAsset)
124 {
125 if (!m_assetRequested)
126 {
127 m_assetRequested = true;
128 AssetService.Get(TextureID.ToString(), this, AssetReceived);
129 }
130 }
131 else
132 {
133 if (!IsDecoded)
134 {
135 //We need to decode the requested image first
136 if (!m_decodeRequested)
137 {
138 //Request decode
139 m_decodeRequested = true;
140 // Do we have a jpeg decoder?
141 if (J2KDecoder != null)
142 {
143 if (m_asset == null)
144 {
145 J2KDecodedCallback(TextureID, new OpenJPEG.J2KLayerInfo[0]);
146 }
147 else
148 {
149 // Send it off to the jpeg decoder
150 J2KDecoder.BeginDecode(TextureID, m_asset, J2KDecodedCallback);
151 }
152
153 }
154 else
155 {
156 J2KDecodedCallback(TextureID, new OpenJPEG.J2KLayerInfo[0]);
157 }
158 }
159 }
160 else
161 {
162 // Check for missing image asset data
163 if (m_asset == null)
164 {
165 m_log.Warn("[J2KIMAGE]: RunUpdate() called with missing asset data (no missing image texture?). Canceling texture transfer");
166 m_currentPacket = m_stopPacket;
167 return;
168 }
169
170 if (DiscardLevel >= 0 || m_stopPacket == 0)
171 {
172 // This shouldn't happen, but if it does, we really can't proceed
173 if (Layers == null)
174 {
175 m_log.Warn("[J2KIMAGE]: RunUpdate() called with missing Layers. Canceling texture transfer");
176 m_currentPacket = m_stopPacket;
177 return;
178 }
179
180 int maxDiscardLevel = Math.Max(0, Layers.Length - 1);
181
182 // Treat initial texture downloads with a DiscardLevel of -1 a request for the highest DiscardLevel
183 if (DiscardLevel < 0 && m_stopPacket == 0)
184 DiscardLevel = (sbyte)maxDiscardLevel;
185
186 // Clamp at the highest discard level
187 DiscardLevel = (sbyte)Math.Min(DiscardLevel, maxDiscardLevel);
188
189 //Calculate the m_stopPacket
190 if (Layers.Length > 0)
191 {
192 m_stopPacket = (uint)GetPacketForBytePosition(Layers[(Layers.Length - 1) - DiscardLevel].End);
193 //I don't know why, but the viewer seems to expect the final packet if the file
194 //is just one packet bigger.
195 if (TexturePacketCount() == m_stopPacket + 1)
196 {
197 m_stopPacket = TexturePacketCount();
198 }
199 }
200 else
201 {
202 m_stopPacket = TexturePacketCount();
203 }
204
205 m_currentPacket = StartPacket;
206 }
207 }
208 }
209 }
210
211 private bool SendFirstPacket(LLClientView client)
212 {
213 if (client == null)
214 return false;
215
216 if (m_asset == null)
217 {
218 m_log.Warn("[J2KIMAGE]: Sending ImageNotInDatabase for texture " + TextureID);
219 client.SendImageNotFound(TextureID);
220 return true;
221 }
222 else if (m_asset.Length <= FIRST_PACKET_SIZE)
223 {
224 // We have less then one packet's worth of data
225 client.SendImageFirstPart(1, TextureID, (uint)m_asset.Length, m_asset, 2);
226 m_stopPacket = 0;
227 return true;
228 }
229 else
230 {
231 // This is going to be a multi-packet texture download
232 byte[] firstImageData = new byte[FIRST_PACKET_SIZE];
233
234 try { Buffer.BlockCopy(m_asset, 0, firstImageData, 0, FIRST_PACKET_SIZE); }
235 catch (Exception)
236 {
237 m_log.ErrorFormat("[J2KIMAGE]: Texture block copy for the first packet failed. textureid={0}, assetlength={1}", TextureID, m_asset.Length);
238 return true;
239 }
240
241 client.SendImageFirstPart(TexturePacketCount(), TextureID, (uint)m_asset.Length, firstImageData, (byte)ImageCodec.J2C);
242 }
243 return false;
244 }
245
246 private bool SendPacket(LLClientView client)
247 {
248 if (client == null)
249 return false;
250
251 bool complete = false;
252 int imagePacketSize = ((int)m_currentPacket == (TexturePacketCount())) ? LastPacketSize() : IMAGE_PACKET_SIZE;
253
254 try
255 {
256 if ((CurrentBytePosition() + IMAGE_PACKET_SIZE) > m_asset.Length)
257 {
258 imagePacketSize = LastPacketSize();
259 complete = true;
260 if ((CurrentBytePosition() + imagePacketSize) > m_asset.Length)
261 {
262 imagePacketSize = m_asset.Length - CurrentBytePosition();
263 complete = true;
264 }
265 }
266
267 // It's concievable that the client might request packet one
268 // from a one packet image, which is really packet 0,
269 // which would leave us with a negative imagePacketSize..
270 if (imagePacketSize > 0)
271 {
272 byte[] imageData = new byte[imagePacketSize];
273 int currentPosition = CurrentBytePosition();
274
275 try { Buffer.BlockCopy(m_asset, currentPosition, imageData, 0, imagePacketSize); }
276 catch (Exception e)
277 {
278 m_log.ErrorFormat("[J2KIMAGE]: Texture block copy for the first packet failed. textureid={0}, assetlength={1}, currentposition={2}, imagepacketsize={3}, exception={4}",
279 TextureID, m_asset.Length, currentPosition, imagePacketSize, e.Message);
280 return false;
281 }
282
283 //Send the packet
284 client.SendImageNextPart((ushort)(m_currentPacket - 1), TextureID, imageData);
285 }
286
287 return !complete;
288 }
289 catch (Exception)
290 {
291 return false;
292 }
293 }
294
295 private ushort TexturePacketCount()
296 {
297 if (!IsDecoded)
298 return 0;
299
300 if (m_asset == null)
301 return 0;
302
303 if (m_asset.Length <= FIRST_PACKET_SIZE)
304 return 1;
305
306 return (ushort)(((m_asset.Length - FIRST_PACKET_SIZE + IMAGE_PACKET_SIZE - 1) / IMAGE_PACKET_SIZE) + 1);
307 }
308
309 private int GetPacketForBytePosition(int bytePosition)
310 {
311 return ((bytePosition - FIRST_PACKET_SIZE + IMAGE_PACKET_SIZE - 1) / IMAGE_PACKET_SIZE) + 1;
312 }
313
314 private int LastPacketSize()
315 {
316 if (m_currentPacket == 1)
317 return m_asset.Length;
318 int lastsize = (m_asset.Length - FIRST_PACKET_SIZE) % IMAGE_PACKET_SIZE;
319 //If the last packet size is zero, it's really cImagePacketSize, it sits on the boundary
320 if (lastsize == 0)
321 {
322 lastsize = IMAGE_PACKET_SIZE;
323 }
324 return lastsize;
325 }
326
327 private int CurrentBytePosition()
328 {
329 if (m_currentPacket == 0)
330 return 0;
331 if (m_currentPacket == 1)
332 return FIRST_PACKET_SIZE;
333
334 int result = FIRST_PACKET_SIZE + ((int)m_currentPacket - 2) * IMAGE_PACKET_SIZE;
335 if (result < 0)
336 {
337 result = FIRST_PACKET_SIZE;
338 }
339 return result;
340 }
341
342 private void J2KDecodedCallback(UUID AssetId, OpenJPEG.J2KLayerInfo[] layers)
343 {
344 Layers = layers;
345 IsDecoded = true;
346 RunUpdate();
347 }
348
349 private void AssetDataCallback(UUID AssetID, AssetBase asset)
350 {
351 HasAsset = true;
352
353 if (asset == null || asset.Data == null)
354 {
355 if (m_imageManager.MissingImage != null)
356 {
357 m_asset = m_imageManager.MissingImage.Data;
358 }
359 else
360 {
361 m_asset = null;
362 IsDecoded = true;
363 }
364 }
365 else
366 {
367 m_asset = asset.Data;
368 }
369
370 RunUpdate();
371 }
372
373 private void AssetReceived(string id, Object sender, AssetBase asset)
374 {
375 UUID assetID = UUID.Zero;
376 if (asset != null)
377 assetID = asset.FullID;
378 else if ((InventoryAccessModule != null) && (sender != InventoryAccessModule))
379 {
380 // Unfortunately we need this here, there's no other way.
381 // This is due to the fact that textures opened directly from the agent's inventory
382 // don't have any distinguishing feature. As such, in order to serve those when the
383 // foreign user is visiting, we need to try again after the first fail to the local
384 // asset service.
385 string assetServerURL = string.Empty;
386 if (InventoryAccessModule.IsForeignUser(AgentID, out assetServerURL))
387 {
388 m_log.DebugFormat("[J2KIMAGE]: texture {0} not found in local asset storage. Trying user's storage.", id);
389 AssetService.Get(assetServerURL + "/" + id, InventoryAccessModule, AssetReceived);
390 return;
391 }
392 }
393
394 AssetDataCallback(assetID, asset);
395
396 }
397 }
398}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
new file mode 100644
index 0000000..43903ce
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -0,0 +1,12123 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33using System.Text;
34using System.Threading;
35using System.Timers;
36using System.Xml;
37using log4net;
38using OpenMetaverse;
39using OpenMetaverse.Packets;
40using OpenMetaverse.Messages.Linden;
41using OpenMetaverse.StructuredData;
42using OpenSim.Framework;
43using OpenSim.Framework.Client;
44using OpenSim.Framework.Statistics;
45using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes;
47using OpenSim.Services.Interfaces;
48using Timer = System.Timers.Timer;
49using AssetLandmark = OpenSim.Framework.AssetLandmark;
50using Nini.Config;
51
52using System.IO;
53
54namespace OpenSim.Region.ClientStack.LindenUDP
55{
56 public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
57
58 /// <summary>
59 /// Handles new client connections
60 /// Constructor takes a single Packet and authenticates everything
61 /// </summary>
62 public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector
63 {
64 /// <value>
65 /// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details.
66 /// </value>
67 protected int m_debugPacketLevel = 0;
68
69 #region Events
70
71 public event GenericMessage OnGenericMessage;
72 public event BinaryGenericMessage OnBinaryGenericMessage;
73 public event Action<IClientAPI> OnLogout;
74 public event ObjectPermissions OnObjectPermissions;
75 public event Action<IClientAPI> OnConnectionClosed;
76 public event ViewerEffectEventHandler OnViewerEffect;
77 public event ImprovedInstantMessage OnInstantMessage;
78 public event ChatMessage OnChatFromClient;
79 public event TextureRequest OnRequestTexture;
80 public event RezObject OnRezObject;
81 public event DeRezObject OnDeRezObject;
82 public event ModifyTerrain OnModifyTerrain;
83 public event Action<IClientAPI> OnRegionHandShakeReply;
84 public event GenericCall1 OnRequestWearables;
85 public event SetAppearance OnSetAppearance;
86 public event AvatarNowWearing OnAvatarNowWearing;
87 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
88 public event RezMultipleAttachmentsFromInv OnRezMultipleAttachmentsFromInv;
89 public event UUIDNameRequest OnDetachAttachmentIntoInv;
90 public event ObjectAttach OnObjectAttach;
91 public event ObjectDeselect OnObjectDetach;
92 public event ObjectDrop OnObjectDrop;
93 public event GenericCall1 OnCompleteMovementToRegion;
94 public event UpdateAgent OnPreAgentUpdate;
95 public event UpdateAgent OnAgentUpdate;
96 public event AgentRequestSit OnAgentRequestSit;
97 public event AgentSit OnAgentSit;
98 public event AvatarPickerRequest OnAvatarPickerRequest;
99 public event StartAnim OnStartAnim;
100 public event StopAnim OnStopAnim;
101 public event Action<IClientAPI> OnRequestAvatarsData;
102 public event LinkObjects OnLinkObjects;
103 public event DelinkObjects OnDelinkObjects;
104 public event GrabObject OnGrabObject;
105 public event DeGrabObject OnDeGrabObject;
106 public event SpinStart OnSpinStart;
107 public event SpinStop OnSpinStop;
108 public event ObjectDuplicate OnObjectDuplicate;
109 public event ObjectDuplicateOnRay OnObjectDuplicateOnRay;
110 public event MoveObject OnGrabUpdate;
111 public event SpinObject OnSpinUpdate;
112 public event AddNewPrim OnAddPrim;
113 public event RequestGodlikePowers OnRequestGodlikePowers;
114 public event GodKickUser OnGodKickUser;
115 public event ObjectExtraParams OnUpdateExtraParams;
116 public event UpdateShape OnUpdatePrimShape;
117 public event ObjectRequest OnObjectRequest;
118 public event ObjectSelect OnObjectSelect;
119 public event ObjectDeselect OnObjectDeselect;
120 public event GenericCall7 OnObjectDescription;
121 public event GenericCall7 OnObjectName;
122 public event GenericCall7 OnObjectClickAction;
123 public event GenericCall7 OnObjectMaterial;
124 public event ObjectIncludeInSearch OnObjectIncludeInSearch;
125 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
126 public event UpdatePrimFlags OnUpdatePrimFlags;
127 public event UpdatePrimTexture OnUpdatePrimTexture;
128 public event UpdateVector OnUpdatePrimGroupPosition;
129 public event UpdateVector OnUpdatePrimSinglePosition;
130 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
131 public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation;
132 public event UpdatePrimSingleRotationPosition OnUpdatePrimSingleRotationPosition;
133 public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation;
134 public event UpdateVector OnUpdatePrimScale;
135 public event UpdateVector OnUpdatePrimGroupScale;
136 public event StatusChange OnChildAgentStatus;
137 public event GenericCall2 OnStopMovement;
138 public event Action<UUID> OnRemoveAvatar;
139 public event RequestMapBlocks OnRequestMapBlocks;
140 public event RequestMapName OnMapNameRequest;
141 public event TeleportLocationRequest OnTeleportLocationRequest;
142 public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
143 public event DisconnectUser OnDisconnectUser;
144 public event RequestAvatarProperties OnRequestAvatarProperties;
145 public event SetAlwaysRun OnSetAlwaysRun;
146 public event FetchInventory OnAgentDataUpdateRequest;
147 public event TeleportLocationRequest OnSetStartLocationRequest;
148 public event UpdateAvatarProperties OnUpdateAvatarProperties;
149 public event CreateNewInventoryItem OnCreateNewInventoryItem;
150 public event LinkInventoryItem OnLinkInventoryItem;
151 public event CreateInventoryFolder OnCreateNewInventoryFolder;
152 public event UpdateInventoryFolder OnUpdateInventoryFolder;
153 public event MoveInventoryFolder OnMoveInventoryFolder;
154 public event FetchInventoryDescendents OnFetchInventoryDescendents;
155 public event PurgeInventoryDescendents OnPurgeInventoryDescendents;
156 public event FetchInventory OnFetchInventory;
157 public event RequestTaskInventory OnRequestTaskInventory;
158 public event UpdateInventoryItem OnUpdateInventoryItem;
159 public event CopyInventoryItem OnCopyInventoryItem;
160 public event MoveInventoryItem OnMoveInventoryItem;
161 public event RemoveInventoryItem OnRemoveInventoryItem;
162 public event RemoveInventoryFolder OnRemoveInventoryFolder;
163 public event UDPAssetUploadRequest OnAssetUploadRequest;
164 public event XferReceive OnXferReceive;
165 public event RequestXfer OnRequestXfer;
166 public event ConfirmXfer OnConfirmXfer;
167 public event AbortXfer OnAbortXfer;
168 public event RequestTerrain OnRequestTerrain;
169 public event RezScript OnRezScript;
170 public event UpdateTaskInventory OnUpdateTaskInventory;
171 public event MoveTaskInventory OnMoveTaskItem;
172 public event RemoveTaskInventory OnRemoveTaskItem;
173 public event RequestAsset OnRequestAsset;
174 public event UUIDNameRequest OnNameFromUUIDRequest;
175 public event ParcelAccessListRequest OnParcelAccessListRequest;
176 public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest;
177 public event ParcelPropertiesRequest OnParcelPropertiesRequest;
178 public event ParcelDivideRequest OnParcelDivideRequest;
179 public event ParcelJoinRequest OnParcelJoinRequest;
180 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
181 public event ParcelSelectObjects OnParcelSelectObjects;
182 public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest;
183 public event ParcelAbandonRequest OnParcelAbandonRequest;
184 public event ParcelGodForceOwner OnParcelGodForceOwner;
185 public event ParcelReclaim OnParcelReclaim;
186 public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest;
187 public event ParcelDeedToGroup OnParcelDeedToGroup;
188 public event RegionInfoRequest OnRegionInfoRequest;
189 public event EstateCovenantRequest OnEstateCovenantRequest;
190 public event FriendActionDelegate OnApproveFriendRequest;
191 public event FriendActionDelegate OnDenyFriendRequest;
192 public event FriendshipTermination OnTerminateFriendship;
193 public event GrantUserFriendRights OnGrantUserRights;
194 public event MoneyTransferRequest OnMoneyTransferRequest;
195 public event EconomyDataRequest OnEconomyDataRequest;
196 public event MoneyBalanceRequest OnMoneyBalanceRequest;
197 public event ParcelBuy OnParcelBuy;
198 public event UUIDNameRequest OnTeleportHomeRequest;
199 public event UUIDNameRequest OnUUIDGroupNameRequest;
200 public event ScriptAnswer OnScriptAnswer;
201 public event RequestPayPrice OnRequestPayPrice;
202 public event ObjectSaleInfo OnObjectSaleInfo;
203 public event ObjectBuy OnObjectBuy;
204 public event BuyObjectInventory OnBuyObjectInventory;
205 public event AgentSit OnUndo;
206 public event AgentSit OnRedo;
207 public event LandUndo OnLandUndo;
208 public event ForceReleaseControls OnForceReleaseControls;
209 public event GodLandStatRequest OnLandStatRequest;
210 public event RequestObjectPropertiesFamily OnObjectGroupRequest;
211 public event DetailedEstateDataRequest OnDetailedEstateDataRequest;
212 public event SetEstateFlagsRequest OnSetEstateFlagsRequest;
213 public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture;
214 public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture;
215 public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights;
216 public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest;
217 public event SetRegionTerrainSettings OnSetRegionTerrainSettings;
218 public event BakeTerrain OnBakeTerrain;
219 public event RequestTerrain OnUploadTerrain;
220 public event EstateChangeInfo OnEstateChangeInfo;
221 public event EstateRestartSimRequest OnEstateRestartSimRequest;
222 public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest;
223 public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest;
224 public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest;
225 public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest;
226 public event EstateDebugRegionRequest OnEstateDebugRegionRequest;
227 public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest;
228 public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest;
229 public event RegionHandleRequest OnRegionHandleRequest;
230 public event ParcelInfoRequest OnParcelInfoRequest;
231 public event ScriptReset OnScriptReset;
232 public event GetScriptRunning OnGetScriptRunning;
233 public event SetScriptRunning OnSetScriptRunning;
234 public event UpdateVector OnAutoPilotGo;
235 public event TerrainUnacked OnUnackedTerrain;
236 public event ActivateGesture OnActivateGesture;
237 public event DeactivateGesture OnDeactivateGesture;
238 public event ObjectOwner OnObjectOwner;
239 public event DirPlacesQuery OnDirPlacesQuery;
240 public event DirFindQuery OnDirFindQuery;
241 public event DirLandQuery OnDirLandQuery;
242 public event DirPopularQuery OnDirPopularQuery;
243 public event DirClassifiedQuery OnDirClassifiedQuery;
244 public event EventInfoRequest OnEventInfoRequest;
245 public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime;
246 public event MapItemRequest OnMapItemRequest;
247 public event OfferCallingCard OnOfferCallingCard;
248 public event AcceptCallingCard OnAcceptCallingCard;
249 public event DeclineCallingCard OnDeclineCallingCard;
250 public event SoundTrigger OnSoundTrigger;
251 public event StartLure OnStartLure;
252 public event TeleportLureRequest OnTeleportLureRequest;
253 public event NetworkStats OnNetworkStatsUpdate;
254 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
255 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
256 public event ClassifiedDelete OnClassifiedDelete;
257 public event ClassifiedDelete OnClassifiedGodDelete;
258 public event EventNotificationAddRequest OnEventNotificationAddRequest;
259 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
260 public event EventGodDelete OnEventGodDelete;
261 public event ParcelDwellRequest OnParcelDwellRequest;
262 public event UserInfoRequest OnUserInfoRequest;
263 public event UpdateUserInfo OnUpdateUserInfo;
264 public event RetrieveInstantMessages OnRetrieveInstantMessages;
265 public event PickDelete OnPickDelete;
266 public event PickGodDelete OnPickGodDelete;
267 public event PickInfoUpdate OnPickInfoUpdate;
268 public event AvatarNotesUpdate OnAvatarNotesUpdate;
269 public event MuteListRequest OnMuteListRequest;
270 public event AvatarInterestUpdate OnAvatarInterestUpdate;
271 public event PlacesQuery OnPlacesQuery;
272 public event AgentFOV OnAgentFOV;
273 public event FindAgentUpdate OnFindAgent;
274 public event TrackAgentUpdate OnTrackAgent;
275 public event NewUserReport OnUserReport;
276 public event SaveStateHandler OnSaveState;
277 public event GroupAccountSummaryRequest OnGroupAccountSummaryRequest;
278 public event GroupAccountDetailsRequest OnGroupAccountDetailsRequest;
279 public event GroupAccountTransactionsRequest OnGroupAccountTransactionsRequest;
280 public event FreezeUserUpdate OnParcelFreezeUser;
281 public event EjectUserUpdate OnParcelEjectUser;
282 public event ParcelBuyPass OnParcelBuyPass;
283 public event ParcelGodMark OnParcelGodMark;
284 public event GroupActiveProposalsRequest OnGroupActiveProposalsRequest;
285 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
286 public event SimWideDeletesDelegate OnSimWideDeletes;
287 public event SendPostcard OnSendPostcard;
288 public event MuteListEntryUpdate OnUpdateMuteListEntry;
289 public event MuteListEntryRemove OnRemoveMuteListEntry;
290 public event GodlikeMessage onGodlikeMessage;
291 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
292
293 #endregion Events
294
295 #region Class Members
296
297 // LLClientView Only
298 public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args);
299
300 /// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary>
301 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
302
303 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
304 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
305
306 private readonly LLUDPServer m_udpServer;
307 private readonly LLUDPClient m_udpClient;
308 private readonly UUID m_sessionId;
309 private readonly UUID m_secureSessionId;
310 protected readonly UUID m_agentId;
311 private readonly uint m_circuitCode;
312 private readonly byte[] m_channelVersion = Utils.EmptyBytes;
313 private readonly Dictionary<string, UUID> m_defaultAnimations = new Dictionary<string, UUID>();
314 private readonly IGroupsModule m_GroupsModule;
315
316 private int m_cachedTextureSerial;
317 private PriorityQueue m_entityUpdates;
318 private PriorityQueue m_entityProps;
319 private Prioritizer m_prioritizer;
320 private bool m_disableFacelights = false;
321
322 /// <value>
323 /// List used in construction of data blocks for an object update packet. This is to stop us having to
324 /// continually recreate it.
325 /// </value>
326 protected List<ObjectUpdatePacket.ObjectDataBlock> m_fullUpdateDataBlocksBuilder;
327
328 /// <value>
329 /// Maintain a record of all the objects killed. This allows us to stop an update being sent from the
330 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
331 /// ownerless phantom.
332 ///
333 /// All manipulation of this set has to occur under a lock
334 ///
335 /// </value>
336 protected HashSet<uint> m_killRecord;
337
338// protected HashSet<uint> m_attachmentsSent;
339
340 private int m_moneyBalance;
341 private int m_animationSequenceNumber = 1;
342 private bool m_SendLogoutPacketWhenClosing = true;
343 private AgentUpdateArgs lastarg;
344 private bool m_IsActive = true;
345 private bool m_IsLoggingOut = false;
346
347 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
348 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
349 protected Scene m_scene;
350 protected LLImageManager m_imageManager;
351 protected string m_firstName;
352 protected string m_lastName;
353 protected Thread m_clientThread;
354 protected Vector3 m_startpos;
355 protected EndPoint m_userEndPoint;
356 protected UUID m_activeGroupID;
357 protected string m_activeGroupName = String.Empty;
358 protected ulong m_activeGroupPowers;
359 protected Dictionary<UUID, ulong> m_groupPowers = new Dictionary<UUID, ulong>();
360 protected int m_terrainCheckerCount;
361 protected uint m_agentFOVCounter;
362
363 protected IAssetService m_assetService;
364 private const bool m_checkPackets = true;
365
366 #endregion Class Members
367
368 #region Properties
369
370 public LLUDPClient UDPClient { get { return m_udpClient; } }
371 public LLUDPServer UDPServer { get { return m_udpServer; } }
372 public IPEndPoint RemoteEndPoint { get { return m_udpClient.RemoteEndPoint; } }
373 public UUID SecureSessionId { get { return m_secureSessionId; } }
374 public IScene Scene { get { return m_scene; } }
375 public UUID SessionId { get { return m_sessionId; } }
376 public Vector3 StartPos
377 {
378 get { return m_startpos; }
379 set { m_startpos = value; }
380 }
381 public UUID AgentId { get { return m_agentId; } }
382 public UUID ActiveGroupId { get { return m_activeGroupID; } }
383 public string ActiveGroupName { get { return m_activeGroupName; } }
384 public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } }
385 public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
386
387 /// <summary>
388 /// Entity update queues
389 /// </summary>
390 public PriorityQueue EntityUpdateQueue { get { return m_entityUpdates; } }
391
392 /// <summary>
393 /// First name of the agent/avatar represented by the client
394 /// </summary>
395 public string FirstName { get { return m_firstName; } }
396
397 /// <summary>
398 /// Last name of the agent/avatar represented by the client
399 /// </summary>
400 public string LastName { get { return m_lastName; } }
401
402 /// <summary>
403 /// Full name of the client (first name and last name)
404 /// </summary>
405 public string Name { get { return FirstName + " " + LastName; } }
406
407 public uint CircuitCode { get { return m_circuitCode; } }
408 public int MoneyBalance { get { return m_moneyBalance; } }
409 public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } }
410 public bool IsActive
411 {
412 get { return m_IsActive; }
413 set { m_IsActive = value; }
414 }
415 public bool IsLoggingOut
416 {
417 get { return m_IsLoggingOut; }
418 set { m_IsLoggingOut = value; }
419 }
420
421 public bool DisableFacelights
422 {
423 get { return m_disableFacelights; }
424 set { m_disableFacelights = value; }
425 }
426
427 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
428
429 #endregion Properties
430
431 /// <summary>
432 /// Constructor
433 /// </summary>
434 public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
435 UUID agentId, UUID sessionId, uint circuitCode)
436 {
437 RegisterInterface<IClientIM>(this);
438 RegisterInterface<IClientChat>(this);
439 RegisterInterface<IClientIPEndpoint>(this);
440
441 InitDefaultAnimations();
442
443 m_scene = scene;
444
445 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
446 m_entityProps = new PriorityQueue(m_scene.Entities.Count);
447 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
448 m_killRecord = new HashSet<uint>();
449// m_attachmentsSent = new HashSet<uint>();
450
451 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
452 m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>();
453 m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>());
454 m_channelVersion = Util.StringToBytes256(scene.GetSimulatorVersion());
455 m_agentId = agentId;
456 m_sessionId = sessionId;
457 m_secureSessionId = sessionInfo.LoginInfo.SecureSession;
458 m_circuitCode = circuitCode;
459 m_userEndPoint = remoteEP;
460 m_firstName = sessionInfo.LoginInfo.First;
461 m_lastName = sessionInfo.LoginInfo.Last;
462 m_startpos = sessionInfo.LoginInfo.StartPos;
463 m_moneyBalance = 1000;
464
465 m_udpServer = udpServer;
466 m_udpClient = udpClient;
467 m_udpClient.OnQueueEmpty += HandleQueueEmpty;
468 m_udpClient.OnPacketStats += PopulateStats;
469
470 m_prioritizer = new Prioritizer(m_scene);
471
472 RegisterLocalPacketHandlers();
473 }
474
475 public void SetDebugPacketLevel(int newDebug)
476 {
477 m_debugPacketLevel = newDebug;
478 }
479
480 #region Client Methods
481
482 /// <summary>
483 /// Shut down the client view
484 /// </summary>
485 public void Close()
486 {
487 m_log.DebugFormat(
488 "[CLIENT]: Close has been called for {0} attached to scene {1}",
489 Name, m_scene.RegionInfo.RegionName);
490
491 // Send the STOP packet
492 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
493 OutPacket(disable, ThrottleOutPacketType.Unknown);
494
495 IsActive = false;
496
497 // Shutdown the image manager
498 if (m_imageManager != null)
499 m_imageManager.Close();
500
501 // Fire the callback for this connection closing
502 if (OnConnectionClosed != null)
503 OnConnectionClosed(this);
504
505 // Flush all of the packets out of the UDP server for this client
506 if (m_udpServer != null)
507 m_udpServer.Flush(m_udpClient);
508
509 // Remove ourselves from the scene
510 m_scene.RemoveClient(AgentId);
511
512 // We can't reach into other scenes and close the connection
513 // We need to do this over grid communications
514 //m_scene.CloseAllAgents(CircuitCode);
515
516 // Disable UDP handling for this client
517 m_udpClient.Shutdown();
518
519 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
520 //GC.Collect();
521 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
522 }
523
524 public void Kick(string message)
525 {
526 if (!ChildAgentStatus())
527 {
528 KickUserPacket kupack = (KickUserPacket)PacketPool.Instance.GetPacket(PacketType.KickUser);
529 kupack.UserInfo.AgentID = AgentId;
530 kupack.UserInfo.SessionID = SessionId;
531 kupack.TargetBlock.TargetIP = 0;
532 kupack.TargetBlock.TargetPort = 0;
533 kupack.UserInfo.Reason = Util.StringToBytes256(message);
534 OutPacket(kupack, ThrottleOutPacketType.Task);
535 // You must sleep here or users get no message!
536 Thread.Sleep(500);
537 }
538 }
539
540 public void Stop()
541 {
542
543 }
544
545 #endregion Client Methods
546
547 #region Packet Handling
548
549 public void PopulateStats(int inPackets, int outPackets, int unAckedBytes)
550 {
551 NetworkStats handlerNetworkStatsUpdate = OnNetworkStatsUpdate;
552 if (handlerNetworkStatsUpdate != null)
553 {
554 handlerNetworkStatsUpdate(inPackets, outPackets, unAckedBytes);
555 }
556 }
557
558 public static bool AddPacketHandler(PacketType packetType, PacketMethod handler)
559 {
560 bool result = false;
561 lock (PacketHandlers)
562 {
563 if (!PacketHandlers.ContainsKey(packetType))
564 {
565 PacketHandlers.Add(packetType, handler);
566 result = true;
567 }
568 }
569 return result;
570 }
571
572 public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler)
573 {
574 return AddLocalPacketHandler(packetType, handler, true);
575 }
576
577 public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool async)
578 {
579 bool result = false;
580 lock (m_packetHandlers)
581 {
582 if (!m_packetHandlers.ContainsKey(packetType))
583 {
584 m_packetHandlers.Add(packetType, new PacketProcessor() { method = handler, Async = async });
585 result = true;
586 }
587 }
588 return result;
589 }
590
591 public bool AddGenericPacketHandler(string MethodName, GenericMessage handler)
592 {
593 MethodName = MethodName.ToLower().Trim();
594
595 bool result = false;
596 lock (m_genericPacketHandlers)
597 {
598 if (!m_genericPacketHandlers.ContainsKey(MethodName))
599 {
600 m_genericPacketHandlers.Add(MethodName, handler);
601 result = true;
602 }
603 }
604 return result;
605 }
606
607 /// <summary>
608 /// Try to process a packet using registered packet handlers
609 /// </summary>
610 /// <param name="packet"></param>
611 /// <returns>True if a handler was found which successfully processed the packet.</returns>
612 protected virtual bool ProcessPacketMethod(Packet packet)
613 {
614 bool result = false;
615 PacketProcessor pprocessor;
616 if (m_packetHandlers.TryGetValue(packet.Type, out pprocessor))
617 {
618 //there is a local handler for this packet type
619 if (pprocessor.Async)
620 {
621 object obj = new AsyncPacketProcess(this, pprocessor.method, packet);
622 Util.FireAndForget(ProcessSpecificPacketAsync, obj);
623 result = true;
624 }
625 else
626 {
627 result = pprocessor.method(this, packet);
628 }
629 }
630 else
631 {
632 //there is not a local handler so see if there is a Global handler
633 PacketMethod method = null;
634 bool found;
635 lock (PacketHandlers)
636 {
637 found = PacketHandlers.TryGetValue(packet.Type, out method);
638 }
639 if (found)
640 {
641 result = method(this, packet);
642 }
643 }
644 return result;
645 }
646
647 public void ProcessSpecificPacketAsync(object state)
648 {
649 AsyncPacketProcess packetObject = (AsyncPacketProcess)state;
650
651 try
652 {
653 packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack);
654 }
655 catch (Exception e)
656 {
657 // Make sure that we see any exception caused by the asynchronous operation.
658 m_log.ErrorFormat(
659 "[LLCLIENTVIEW]: Caught exception while processing {0} for {1}, {2} {3}",
660 packetObject.Pack, Name, e.Message, e.StackTrace);
661 }
662 }
663
664 #endregion Packet Handling
665
666 # region Setup
667
668 public virtual void Start()
669 {
670 m_scene.AddNewClient(this);
671
672 RefreshGroupMembership();
673 }
674
675 # endregion
676
677 public void ActivateGesture(UUID assetId, UUID gestureId)
678 {
679 }
680
681 public void DeactivateGesture(UUID assetId, UUID gestureId)
682 {
683 }
684
685 // Sound
686 public void SoundTrigger(UUID soundId, UUID owerid, UUID Objectid, UUID ParentId, float Gain, Vector3 Position, UInt64 Handle)
687 {
688 }
689
690 #region Scene/Avatar to Client
691
692 public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args)
693 {
694 RegionHandshakePacket handshake = (RegionHandshakePacket)PacketPool.Instance.GetPacket(PacketType.RegionHandshake);
695 handshake.RegionInfo = new RegionHandshakePacket.RegionInfoBlock();
696 handshake.RegionInfo.BillableFactor = args.billableFactor;
697 handshake.RegionInfo.IsEstateManager = args.isEstateManager;
698 handshake.RegionInfo.TerrainHeightRange00 = args.terrainHeightRange0;
699 handshake.RegionInfo.TerrainHeightRange01 = args.terrainHeightRange1;
700 handshake.RegionInfo.TerrainHeightRange10 = args.terrainHeightRange2;
701 handshake.RegionInfo.TerrainHeightRange11 = args.terrainHeightRange3;
702 handshake.RegionInfo.TerrainStartHeight00 = args.terrainStartHeight0;
703 handshake.RegionInfo.TerrainStartHeight01 = args.terrainStartHeight1;
704 handshake.RegionInfo.TerrainStartHeight10 = args.terrainStartHeight2;
705 handshake.RegionInfo.TerrainStartHeight11 = args.terrainStartHeight3;
706 handshake.RegionInfo.SimAccess = args.simAccess;
707 handshake.RegionInfo.WaterHeight = args.waterHeight;
708
709 handshake.RegionInfo.RegionFlags = args.regionFlags;
710 handshake.RegionInfo.SimName = Util.StringToBytes256(args.regionName);
711 handshake.RegionInfo.SimOwner = args.SimOwner;
712 handshake.RegionInfo.TerrainBase0 = args.terrainBase0;
713 handshake.RegionInfo.TerrainBase1 = args.terrainBase1;
714 handshake.RegionInfo.TerrainBase2 = args.terrainBase2;
715 handshake.RegionInfo.TerrainBase3 = args.terrainBase3;
716 handshake.RegionInfo.TerrainDetail0 = args.terrainDetail0;
717 handshake.RegionInfo.TerrainDetail1 = args.terrainDetail1;
718 handshake.RegionInfo.TerrainDetail2 = args.terrainDetail2;
719 handshake.RegionInfo.TerrainDetail3 = args.terrainDetail3;
720 handshake.RegionInfo.CacheID = UUID.Random(); //I guess this is for the client to remember an old setting?
721 handshake.RegionInfo2 = new RegionHandshakePacket.RegionInfo2Block();
722 handshake.RegionInfo2.RegionID = regionInfo.RegionID;
723
724 handshake.RegionInfo3 = new RegionHandshakePacket.RegionInfo3Block();
725 handshake.RegionInfo3.CPUClassID = 9;
726 handshake.RegionInfo3.CPURatio = 1;
727
728 handshake.RegionInfo3.ColoName = Utils.EmptyBytes;
729 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType);
730 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes;
731
732 OutPacket(handshake, ThrottleOutPacketType.Task);
733 }
734
735 /// <summary>
736 ///
737 /// </summary>
738 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
739 {
740 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete);
741 mov.SimData.ChannelVersion = m_channelVersion;
742 mov.AgentData.SessionID = m_sessionId;
743 mov.AgentData.AgentID = AgentId;
744 mov.Data.RegionHandle = regInfo.RegionHandle;
745 mov.Data.Timestamp = (uint)Util.UnixTimeSinceEpoch();
746
747 if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0))
748 {
749 mov.Data.Position = m_startpos;
750 }
751 else
752 {
753 mov.Data.Position = pos;
754 }
755 mov.Data.LookAt = look;
756
757 // Hack to get this out immediately and skip the throttles
758 OutPacket(mov, ThrottleOutPacketType.Unknown);
759 }
760
761 public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName,
762 UUID fromAgentID, byte source, byte audible)
763 {
764 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
765 reply.ChatData.Audible = audible;
766 reply.ChatData.Message = Util.StringToBytes1024(message);
767 reply.ChatData.ChatType = type;
768 reply.ChatData.SourceType = source;
769 reply.ChatData.Position = fromPos;
770 reply.ChatData.FromName = Util.StringToBytes256(fromName);
771 reply.ChatData.OwnerID = fromAgentID;
772 reply.ChatData.SourceID = fromAgentID;
773
774 OutPacket(reply, ThrottleOutPacketType.Task);
775 }
776
777 /// <summary>
778 /// Send an instant message to this client
779 /// </summary>
780 //
781 // Don't remove transaction ID! Groups and item gives need to set it!
782 public void SendInstantMessage(GridInstantMessage im)
783 {
784 if (((Scene)(m_scene)).Permissions.CanInstantMessage(new UUID(im.fromAgentID), new UUID(im.toAgentID)))
785 {
786 ImprovedInstantMessagePacket msg
787 = (ImprovedInstantMessagePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedInstantMessage);
788
789 msg.AgentData.AgentID = new UUID(im.fromAgentID);
790 msg.AgentData.SessionID = UUID.Zero;
791 msg.MessageBlock.FromAgentName = Util.StringToBytes256(im.fromAgentName);
792 msg.MessageBlock.Dialog = im.dialog;
793 msg.MessageBlock.FromGroup = im.fromGroup;
794 if (im.imSessionID == UUID.Zero.Guid)
795 msg.MessageBlock.ID = new UUID(im.fromAgentID) ^ new UUID(im.toAgentID);
796 else
797 msg.MessageBlock.ID = new UUID(im.imSessionID);
798 msg.MessageBlock.Offline = im.offline;
799 msg.MessageBlock.ParentEstateID = im.ParentEstateID;
800 msg.MessageBlock.Position = im.Position;
801 msg.MessageBlock.RegionID = new UUID(im.RegionID);
802 msg.MessageBlock.Timestamp = im.timestamp;
803 msg.MessageBlock.ToAgentID = new UUID(im.toAgentID);
804 msg.MessageBlock.Message = Util.StringToBytes1024(im.message);
805 msg.MessageBlock.BinaryBucket = im.binaryBucket;
806
807 if (im.message.StartsWith("[grouptest]"))
808 { // this block is test code for implementing group IM - delete when group IM is finished
809 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
810 if (eq != null)
811 {
812 im.dialog = 17;
813
814 //eq.ChatterboxInvitation(
815 // new UUID("00000000-68f9-1111-024e-222222111123"),
816 // "OpenSimulator Testing", im.fromAgentID, im.message, im.toAgentID, im.fromAgentName, im.dialog, 0,
817 // false, 0, new Vector3(), 1, im.imSessionID, im.fromGroup, im.binaryBucket);
818
819 eq.ChatterboxInvitation(
820 new UUID("00000000-68f9-1111-024e-222222111123"),
821 "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0,
822 false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Util.StringToBytes256("OpenSimulator Testing"));
823
824 eq.ChatterBoxSessionAgentListUpdates(
825 new UUID("00000000-68f9-1111-024e-222222111123"),
826 new UUID(im.fromAgentID), new UUID(im.toAgentID), false, false, false);
827 }
828
829 Console.WriteLine("SendInstantMessage: " + msg);
830 }
831 else
832 OutPacket(msg, ThrottleOutPacketType.Task);
833 }
834 }
835
836 public void SendGenericMessage(string method, List<string> message)
837 {
838 GenericMessagePacket gmp = new GenericMessagePacket();
839 gmp.MethodData.Method = Util.StringToBytes256(method);
840 gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count];
841 int i = 0;
842 foreach (string val in message)
843 {
844 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock();
845 gmp.ParamList[i++].Parameter = Util.StringToBytes256(val);
846 }
847
848 OutPacket(gmp, ThrottleOutPacketType.Task);
849 }
850
851 public void SendGenericMessage(string method, List<byte[]> message)
852 {
853 GenericMessagePacket gmp = new GenericMessagePacket();
854 gmp.MethodData.Method = Util.StringToBytes256(method);
855 gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count];
856 int i = 0;
857 foreach (byte[] val in message)
858 {
859 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock();
860 gmp.ParamList[i++].Parameter = val;
861 }
862
863 OutPacket(gmp, ThrottleOutPacketType.Task);
864 }
865
866 public void SendGroupActiveProposals(UUID groupID, UUID transactionID, GroupActiveProposals[] Proposals)
867 {
868 int i = 0;
869 foreach (GroupActiveProposals Proposal in Proposals)
870 {
871 GroupActiveProposalItemReplyPacket GAPIRP = new GroupActiveProposalItemReplyPacket();
872
873 GAPIRP.AgentData.AgentID = AgentId;
874 GAPIRP.AgentData.GroupID = groupID;
875 GAPIRP.TransactionData.TransactionID = transactionID;
876 GAPIRP.TransactionData.TotalNumItems = ((uint)i+1);
877 GroupActiveProposalItemReplyPacket.ProposalDataBlock ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock();
878 GAPIRP.ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock[1];
879 ProposalData.VoteCast = Utils.StringToBytes("false");
880 ProposalData.VoteID = new UUID(Proposal.VoteID);
881 ProposalData.VoteInitiator = new UUID(Proposal.VoteInitiator);
882 ProposalData.Majority = (float)Convert.ToInt32(Proposal.Majority);
883 ProposalData.Quorum = Convert.ToInt32(Proposal.Quorum);
884 ProposalData.TerseDateID = Utils.StringToBytes(Proposal.TerseDateID);
885 ProposalData.StartDateTime = Utils.StringToBytes(Proposal.StartDateTime);
886 ProposalData.EndDateTime = Utils.StringToBytes(Proposal.EndDateTime);
887 ProposalData.ProposalText = Utils.StringToBytes(Proposal.ProposalText);
888 ProposalData.AlreadyVoted = false;
889 GAPIRP.ProposalData[i] = ProposalData;
890 OutPacket(GAPIRP, ThrottleOutPacketType.Task);
891 i++;
892 }
893 if (Proposals.Length == 0)
894 {
895 GroupActiveProposalItemReplyPacket GAPIRP = new GroupActiveProposalItemReplyPacket();
896
897 GAPIRP.AgentData.AgentID = AgentId;
898 GAPIRP.AgentData.GroupID = groupID;
899 GAPIRP.TransactionData.TransactionID = transactionID;
900 GAPIRP.TransactionData.TotalNumItems = 1;
901 GroupActiveProposalItemReplyPacket.ProposalDataBlock ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock();
902 GAPIRP.ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock[1];
903 ProposalData.VoteCast = Utils.StringToBytes("false");
904 ProposalData.VoteID = UUID.Zero;
905 ProposalData.VoteInitiator = UUID.Zero;
906 ProposalData.Majority = 0;
907 ProposalData.Quorum = 0;
908 ProposalData.TerseDateID = Utils.StringToBytes("");
909 ProposalData.StartDateTime = Utils.StringToBytes("");
910 ProposalData.EndDateTime = Utils.StringToBytes("");
911 ProposalData.ProposalText = Utils.StringToBytes("");
912 ProposalData.AlreadyVoted = false;
913 GAPIRP.ProposalData[0] = ProposalData;
914 OutPacket(GAPIRP, ThrottleOutPacketType.Task);
915 }
916 }
917
918 public void SendGroupVoteHistory(UUID groupID, UUID transactionID, GroupVoteHistory[] Votes)
919 {
920 int i = 0;
921 foreach (GroupVoteHistory Vote in Votes)
922 {
923 GroupVoteHistoryItemReplyPacket GVHIRP = new GroupVoteHistoryItemReplyPacket();
924
925 GVHIRP.AgentData.AgentID = AgentId;
926 GVHIRP.AgentData.GroupID = groupID;
927 GVHIRP.TransactionData.TransactionID = transactionID;
928 GVHIRP.TransactionData.TotalNumItems = ((uint)i+1);
929 GVHIRP.HistoryItemData.VoteID = new UUID(Vote.VoteID);
930 GVHIRP.HistoryItemData.VoteInitiator = new UUID(Vote.VoteInitiator);
931 GVHIRP.HistoryItemData.Majority = (float)Convert.ToInt32(Vote.Majority);
932 GVHIRP.HistoryItemData.Quorum = Convert.ToInt32(Vote.Quorum);
933 GVHIRP.HistoryItemData.TerseDateID = Utils.StringToBytes(Vote.TerseDateID);
934 GVHIRP.HistoryItemData.StartDateTime = Utils.StringToBytes(Vote.StartDateTime);
935 GVHIRP.HistoryItemData.EndDateTime = Utils.StringToBytes(Vote.EndDateTime);
936 GVHIRP.HistoryItemData.VoteType = Utils.StringToBytes(Vote.VoteType);
937 GVHIRP.HistoryItemData.VoteResult = Utils.StringToBytes(Vote.VoteResult);
938 GVHIRP.HistoryItemData.ProposalText = Utils.StringToBytes(Vote.ProposalText);
939 GroupVoteHistoryItemReplyPacket.VoteItemBlock VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock();
940 GVHIRP.VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock[1];
941 VoteItem.CandidateID = UUID.Zero;
942 VoteItem.NumVotes = 0; //TODO: FIX THIS!!!
943 VoteItem.VoteCast = Utils.StringToBytes("Yes");
944 GVHIRP.VoteItem[i] = VoteItem;
945 OutPacket(GVHIRP, ThrottleOutPacketType.Task);
946 i++;
947 }
948 if (Votes.Length == 0)
949 {
950 GroupVoteHistoryItemReplyPacket GVHIRP = new GroupVoteHistoryItemReplyPacket();
951
952 GVHIRP.AgentData.AgentID = AgentId;
953 GVHIRP.AgentData.GroupID = groupID;
954 GVHIRP.TransactionData.TransactionID = transactionID;
955 GVHIRP.TransactionData.TotalNumItems = 0;
956 GVHIRP.HistoryItemData.VoteID = UUID.Zero;
957 GVHIRP.HistoryItemData.VoteInitiator = UUID.Zero;
958 GVHIRP.HistoryItemData.Majority = 0;
959 GVHIRP.HistoryItemData.Quorum = 0;
960 GVHIRP.HistoryItemData.TerseDateID = Utils.StringToBytes("");
961 GVHIRP.HistoryItemData.StartDateTime = Utils.StringToBytes("");
962 GVHIRP.HistoryItemData.EndDateTime = Utils.StringToBytes("");
963 GVHIRP.HistoryItemData.VoteType = Utils.StringToBytes("");
964 GVHIRP.HistoryItemData.VoteResult = Utils.StringToBytes("");
965 GVHIRP.HistoryItemData.ProposalText = Utils.StringToBytes("");
966 GroupVoteHistoryItemReplyPacket.VoteItemBlock VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock();
967 GVHIRP.VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock[1];
968 VoteItem.CandidateID = UUID.Zero;
969 VoteItem.NumVotes = 0; //TODO: FIX THIS!!!
970 VoteItem.VoteCast = Utils.StringToBytes("No");
971 GVHIRP.VoteItem[0] = VoteItem;
972 OutPacket(GVHIRP, ThrottleOutPacketType.Task);
973 }
974 }
975
976 public void SendGroupAccountingDetails(IClientAPI sender,UUID groupID, UUID transactionID, UUID sessionID, int amt)
977 {
978 GroupAccountDetailsReplyPacket GADRP = new GroupAccountDetailsReplyPacket();
979 GADRP.AgentData = new GroupAccountDetailsReplyPacket.AgentDataBlock();
980 GADRP.AgentData.AgentID = sender.AgentId;
981 GADRP.AgentData.GroupID = groupID;
982 GADRP.HistoryData = new GroupAccountDetailsReplyPacket.HistoryDataBlock[1];
983 GroupAccountDetailsReplyPacket.HistoryDataBlock History = new GroupAccountDetailsReplyPacket.HistoryDataBlock();
984 GADRP.MoneyData = new GroupAccountDetailsReplyPacket.MoneyDataBlock();
985 GADRP.MoneyData.CurrentInterval = 0;
986 GADRP.MoneyData.IntervalDays = 7;
987 GADRP.MoneyData.RequestID = transactionID;
988 GADRP.MoneyData.StartDate = Utils.StringToBytes(DateTime.Today.ToString());
989 History.Amount = amt;
990 History.Description = Utils.StringToBytes("");
991 GADRP.HistoryData[0] = History;
992 OutPacket(GADRP, ThrottleOutPacketType.Task);
993 }
994
995 public void SendGroupAccountingSummary(IClientAPI sender,UUID groupID, uint moneyAmt, int totalTier, int usedTier)
996 {
997 GroupAccountSummaryReplyPacket GASRP =
998 (GroupAccountSummaryReplyPacket)PacketPool.Instance.GetPacket(
999 PacketType.GroupAccountSummaryReply);
1000
1001 GASRP.AgentData = new GroupAccountSummaryReplyPacket.AgentDataBlock();
1002 GASRP.AgentData.AgentID = sender.AgentId;
1003 GASRP.AgentData.GroupID = groupID;
1004 GASRP.MoneyData = new GroupAccountSummaryReplyPacket.MoneyDataBlock();
1005 GASRP.MoneyData.Balance = (int)moneyAmt;
1006 GASRP.MoneyData.TotalCredits = totalTier;
1007 GASRP.MoneyData.TotalDebits = usedTier;
1008 GASRP.MoneyData.StartDate = new byte[1];
1009 GASRP.MoneyData.CurrentInterval = 1;
1010 GASRP.MoneyData.GroupTaxCurrent = 0;
1011 GASRP.MoneyData.GroupTaxEstimate = 0;
1012 GASRP.MoneyData.IntervalDays = 0;
1013 GASRP.MoneyData.LandTaxCurrent = 0;
1014 GASRP.MoneyData.LandTaxEstimate = 0;
1015 GASRP.MoneyData.LastTaxDate = new byte[1];
1016 GASRP.MoneyData.LightTaxCurrent = 0;
1017 GASRP.MoneyData.TaxDate = new byte[1];
1018 GASRP.MoneyData.RequestID = sender.AgentId;
1019 GASRP.MoneyData.ParcelDirFeeEstimate = 0;
1020 GASRP.MoneyData.ParcelDirFeeCurrent = 0;
1021 GASRP.MoneyData.ObjectTaxEstimate = 0;
1022 GASRP.MoneyData.NonExemptMembers = 0;
1023 GASRP.MoneyData.ObjectTaxCurrent = 0;
1024 GASRP.MoneyData.LightTaxEstimate = 0;
1025 OutPacket(GASRP, ThrottleOutPacketType.Task);
1026 }
1027
1028 public void SendGroupTransactionsSummaryDetails(IClientAPI sender,UUID groupID, UUID transactionID, UUID sessionID, int amt)
1029 {
1030 GroupAccountTransactionsReplyPacket GATRP =
1031 (GroupAccountTransactionsReplyPacket)PacketPool.Instance.GetPacket(
1032 PacketType.GroupAccountTransactionsReply);
1033
1034 GATRP.AgentData = new GroupAccountTransactionsReplyPacket.AgentDataBlock();
1035 GATRP.AgentData.AgentID = sender.AgentId;
1036 GATRP.AgentData.GroupID = groupID;
1037 GATRP.MoneyData = new GroupAccountTransactionsReplyPacket.MoneyDataBlock();
1038 GATRP.MoneyData.CurrentInterval = 0;
1039 GATRP.MoneyData.IntervalDays = 7;
1040 GATRP.MoneyData.RequestID = transactionID;
1041 GATRP.MoneyData.StartDate = Utils.StringToBytes(DateTime.Today.ToString());
1042 GATRP.HistoryData = new GroupAccountTransactionsReplyPacket.HistoryDataBlock[1];
1043 GroupAccountTransactionsReplyPacket.HistoryDataBlock History = new GroupAccountTransactionsReplyPacket.HistoryDataBlock();
1044 History.Amount = 0;
1045 History.Item = Utils.StringToBytes("");
1046 History.Time = Utils.StringToBytes("");
1047 History.Type = 0;
1048 History.User = Utils.StringToBytes("");
1049 GATRP.HistoryData[0] = History;
1050 OutPacket(GATRP, ThrottleOutPacketType.Task);
1051 }
1052
1053 /// <summary>
1054 /// Send the region heightmap to the client
1055 /// </summary>
1056 /// <param name="map">heightmap</param>
1057 public virtual void SendLayerData(float[] map)
1058 {
1059 Util.FireAndForget(DoSendLayerData, map);
1060 }
1061
1062 /// <summary>
1063 /// Send terrain layer information to the client.
1064 /// </summary>
1065 /// <param name="o"></param>
1066 private void DoSendLayerData(object o)
1067 {
1068 float[] map = LLHeightFieldMoronize((float[])o);
1069
1070 try
1071 {
1072 //for (int y = 0; y < 16; y++)
1073 //{
1074 // for (int x = 0; x < 16; x++)
1075 // {
1076 // SendLayerData(x, y, map);
1077 // }
1078 //}
1079
1080 // Send LayerData in a spiral pattern. Fun!
1081 SendLayerTopRight(map, 0, 0, 15, 15);
1082 }
1083 catch (Exception e)
1084 {
1085 m_log.Error("[CLIENT]: SendLayerData() Failed with exception: " + e.Message, e);
1086 }
1087 }
1088
1089 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1090 {
1091 // Row
1092 for (int i = x1; i <= x2; i++)
1093 SendLayerData(i, y1, map);
1094
1095 // Column
1096 for (int j = y1 + 1; j <= y2; j++)
1097 SendLayerData(x2, j, map);
1098
1099 if (x2 - x1 > 0)
1100 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1101 }
1102
1103 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1104 {
1105 // Row in reverse
1106 for (int i = x2; i >= x1; i--)
1107 SendLayerData(i, y2, map);
1108
1109 // Column in reverse
1110 for (int j = y2 - 1; j >= y1; j--)
1111 SendLayerData(x1, j, map);
1112
1113 if (x2 - x1 > 0)
1114 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1115 }
1116
1117 /// <summary>
1118 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1119 /// </summary>
1120 /// <param name="map">heightmap</param>
1121 /// <param name="px">X coordinate for patches 0..12</param>
1122 /// <param name="py">Y coordinate for patches 0..15</param>
1123 // private void SendLayerPacket(float[] map, int y, int x)
1124 // {
1125 // int[] patches = new int[4];
1126 // patches[0] = x + 0 + y * 16;
1127 // patches[1] = x + 1 + y * 16;
1128 // patches[2] = x + 2 + y * 16;
1129 // patches[3] = x + 3 + y * 16;
1130
1131 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches);
1132 // OutPacket(layerpack, ThrottleOutPacketType.Land);
1133 // }
1134
1135 /// <summary>
1136 /// Sends a specified patch to a client
1137 /// </summary>
1138 /// <param name="px">Patch coordinate (x) 0..15</param>
1139 /// <param name="py">Patch coordinate (y) 0..15</param>
1140 /// <param name="map">heightmap</param>
1141 public void SendLayerData(int px, int py, float[] map)
1142 {
1143 try
1144 {
1145 int[] patches = new int[] { py * 16 + px };
1146 float[] heightmap = (map.Length == 65536) ?
1147 map :
1148 LLHeightFieldMoronize(map);
1149
1150 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1151 layerpack.Header.Reliable = true;
1152
1153 OutPacket(layerpack, ThrottleOutPacketType.Land);
1154 }
1155 catch (Exception e)
1156 {
1157 m_log.Error("[CLIENT]: SendLayerData() Failed with exception: " + e.Message, e);
1158 }
1159 }
1160
1161 /// <summary>
1162 /// Munges heightfield into the LLUDP backed in restricted heightfield.
1163 /// </summary>
1164 /// <param name="map">float array in the base; Constants.RegionSize</param>
1165 /// <returns>float array in the base 256</returns>
1166 internal float[] LLHeightFieldMoronize(float[] map)
1167 {
1168 if (map.Length == 65536)
1169 return map;
1170 else
1171 {
1172 float[] returnmap = new float[65536];
1173
1174 if (map.Length < 65535)
1175 {
1176 // rebase the vector stride to 256
1177 for (int i = 0; i < Constants.RegionSize; i++)
1178 Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, (int)Constants.RegionSize);
1179 }
1180 else
1181 {
1182 for (int i = 0; i < 256; i++)
1183 Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256);
1184 }
1185
1186 //Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536);
1187
1188 return returnmap;
1189 }
1190
1191 }
1192
1193 /// <summary>
1194 /// Send the wind matrix to the client
1195 /// </summary>
1196 /// <param name="windSpeeds">16x16 array of wind speeds</param>
1197 public virtual void SendWindData(Vector2[] windSpeeds)
1198 {
1199 Util.FireAndForget(DoSendWindData, windSpeeds);
1200 }
1201
1202 /// <summary>
1203 /// Send the cloud matrix to the client
1204 /// </summary>
1205 /// <param name="windSpeeds">16x16 array of cloud densities</param>
1206 public virtual void SendCloudData(float[] cloudDensity)
1207 {
1208 Util.FireAndForget(DoSendCloudData, cloudDensity);
1209 }
1210
1211 /// <summary>
1212 /// Send wind layer information to the client.
1213 /// </summary>
1214 /// <param name="o"></param>
1215 private void DoSendWindData(object o)
1216 {
1217 Vector2[] windSpeeds = (Vector2[])o;
1218 TerrainPatch[] patches = new TerrainPatch[2];
1219 patches[0] = new TerrainPatch();
1220 patches[0].Data = new float[16 * 16];
1221 patches[1] = new TerrainPatch();
1222 patches[1].Data = new float[16 * 16];
1223
1224 for (int y = 0; y < 16; y++)
1225 {
1226 for (int x = 0; x < 16; x++)
1227 {
1228 patches[0].Data[y * 16 + x] = windSpeeds[y * 16 + x].X;
1229 patches[1].Data[y * 16 + x] = windSpeeds[y * 16 + x].Y;
1230 }
1231 }
1232
1233 LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Wind);
1234 layerpack.Header.Zerocoded = true;
1235 OutPacket(layerpack, ThrottleOutPacketType.Wind);
1236 }
1237
1238 /// <summary>
1239 /// Send cloud layer information to the client.
1240 /// </summary>
1241 /// <param name="o"></param>
1242 private void DoSendCloudData(object o)
1243 {
1244 float[] cloudCover = (float[])o;
1245 TerrainPatch[] patches = new TerrainPatch[1];
1246 patches[0] = new TerrainPatch();
1247 patches[0].Data = new float[16 * 16];
1248
1249 for (int y = 0; y < 16; y++)
1250 {
1251 for (int x = 0; x < 16; x++)
1252 {
1253 patches[0].Data[y * 16 + x] = cloudCover[y * 16 + x];
1254 }
1255 }
1256
1257 LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Cloud);
1258 layerpack.Header.Zerocoded = true;
1259 OutPacket(layerpack, ThrottleOutPacketType.Cloud);
1260 }
1261
1262 /// <summary>
1263 /// Tell the client that the given neighbour region is ready to receive a child agent.
1264 /// </summary>
1265 public virtual void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourEndPoint)
1266 {
1267 IPAddress neighbourIP = neighbourEndPoint.Address;
1268 ushort neighbourPort = (ushort)neighbourEndPoint.Port;
1269
1270 EnableSimulatorPacket enablesimpacket = (EnableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.EnableSimulator);
1271 // TODO: don't create new blocks if recycling an old packet
1272 enablesimpacket.SimulatorInfo = new EnableSimulatorPacket.SimulatorInfoBlock();
1273 enablesimpacket.SimulatorInfo.Handle = neighbourHandle;
1274
1275 byte[] byteIP = neighbourIP.GetAddressBytes();
1276 enablesimpacket.SimulatorInfo.IP = (uint)byteIP[3] << 24;
1277 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[2] << 16;
1278 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[1] << 8;
1279 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[0];
1280 enablesimpacket.SimulatorInfo.Port = neighbourPort;
1281
1282 enablesimpacket.Header.Reliable = true; // ESP's should be reliable.
1283
1284 OutPacket(enablesimpacket, ThrottleOutPacketType.Task);
1285 }
1286
1287 public AgentCircuitData RequestClientInfo()
1288 {
1289 AgentCircuitData agentData = new AgentCircuitData();
1290 agentData.AgentID = AgentId;
1291 agentData.SessionID = m_sessionId;
1292 agentData.SecureSessionID = SecureSessionId;
1293 agentData.circuitcode = m_circuitCode;
1294 agentData.child = false;
1295 agentData.firstname = m_firstName;
1296 agentData.lastname = m_lastName;
1297
1298 ICapabilitiesModule capsModule = m_scene.RequestModuleInterface<ICapabilitiesModule>();
1299
1300 if (capsModule == null) // can happen when shutting down.
1301 return agentData;
1302
1303 agentData.CapsPath = capsModule.GetCapsPath(m_agentId);
1304 agentData.ChildrenCapSeeds = new Dictionary<ulong, string>(capsModule.GetChildrenSeeds(m_agentId));
1305
1306 return agentData;
1307 }
1308
1309 public virtual void CrossRegion(ulong newRegionHandle, Vector3 pos, Vector3 lookAt, IPEndPoint externalIPEndPoint,
1310 string capsURL)
1311 {
1312 Vector3 look = new Vector3(lookAt.X * 10, lookAt.Y * 10, lookAt.Z * 10);
1313
1314 //CrossedRegionPacket newSimPack = (CrossedRegionPacket)PacketPool.Instance.GetPacket(PacketType.CrossedRegion);
1315 CrossedRegionPacket newSimPack = new CrossedRegionPacket();
1316 // TODO: don't create new blocks if recycling an old packet
1317 newSimPack.AgentData = new CrossedRegionPacket.AgentDataBlock();
1318 newSimPack.AgentData.AgentID = AgentId;
1319 newSimPack.AgentData.SessionID = m_sessionId;
1320 newSimPack.Info = new CrossedRegionPacket.InfoBlock();
1321 newSimPack.Info.Position = pos;
1322 newSimPack.Info.LookAt = look;
1323 newSimPack.RegionData = new CrossedRegionPacket.RegionDataBlock();
1324 newSimPack.RegionData.RegionHandle = newRegionHandle;
1325 byte[] byteIP = externalIPEndPoint.Address.GetAddressBytes();
1326 newSimPack.RegionData.SimIP = (uint)byteIP[3] << 24;
1327 newSimPack.RegionData.SimIP += (uint)byteIP[2] << 16;
1328 newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8;
1329 newSimPack.RegionData.SimIP += (uint)byteIP[0];
1330 newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port;
1331 newSimPack.RegionData.SeedCapability = Util.StringToBytes256(capsURL);
1332
1333 // Hack to get this out immediately and skip throttles
1334 OutPacket(newSimPack, ThrottleOutPacketType.Unknown);
1335 }
1336
1337 internal void SendMapBlockSplit(List<MapBlockData> mapBlocks, uint flag)
1338 {
1339 MapBlockReplyPacket mapReply = (MapBlockReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapBlockReply);
1340 // TODO: don't create new blocks if recycling an old packet
1341
1342 MapBlockData[] mapBlocks2 = mapBlocks.ToArray();
1343
1344 mapReply.AgentData.AgentID = AgentId;
1345 mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length];
1346 mapReply.AgentData.Flags = flag;
1347
1348 for (int i = 0; i < mapBlocks2.Length; i++)
1349 {
1350 mapReply.Data[i] = new MapBlockReplyPacket.DataBlock();
1351 mapReply.Data[i].MapImageID = mapBlocks2[i].MapImageId;
1352 //m_log.Warn(mapBlocks2[i].MapImageId.ToString());
1353 mapReply.Data[i].X = mapBlocks2[i].X;
1354 mapReply.Data[i].Y = mapBlocks2[i].Y;
1355 mapReply.Data[i].WaterHeight = mapBlocks2[i].WaterHeight;
1356 mapReply.Data[i].Name = Utils.StringToBytes(mapBlocks2[i].Name);
1357 mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags;
1358 mapReply.Data[i].Access = mapBlocks2[i].Access;
1359 mapReply.Data[i].Agents = mapBlocks2[i].Agents;
1360 }
1361 OutPacket(mapReply, ThrottleOutPacketType.Land);
1362 }
1363
1364 public void SendMapBlock(List<MapBlockData> mapBlocks, uint flag)
1365 {
1366
1367 MapBlockData[] mapBlocks2 = mapBlocks.ToArray();
1368
1369 int maxsend = 10;
1370
1371 //int packets = Math.Ceiling(mapBlocks2.Length / maxsend);
1372
1373 List<MapBlockData> sendingBlocks = new List<MapBlockData>();
1374
1375 for (int i = 0; i < mapBlocks2.Length; i++)
1376 {
1377 sendingBlocks.Add(mapBlocks2[i]);
1378 if (((i + 1) == mapBlocks2.Length) || (((i + 1) % maxsend) == 0))
1379 {
1380 SendMapBlockSplit(sendingBlocks, flag);
1381 sendingBlocks = new List<MapBlockData>();
1382 }
1383 }
1384 }
1385
1386 public void SendLocalTeleport(Vector3 position, Vector3 lookAt, uint flags)
1387 {
1388 TeleportLocalPacket tpLocal = (TeleportLocalPacket)PacketPool.Instance.GetPacket(PacketType.TeleportLocal);
1389 tpLocal.Info.AgentID = AgentId;
1390 tpLocal.Info.TeleportFlags = flags;
1391 tpLocal.Info.LocationID = 2;
1392 tpLocal.Info.LookAt = lookAt;
1393 tpLocal.Info.Position = position;
1394
1395 // Hack to get this out immediately and skip throttles
1396 OutPacket(tpLocal, ThrottleOutPacketType.Unknown);
1397 }
1398
1399 public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint newRegionEndPoint, uint locationID,
1400 uint flags, string capsURL)
1401 {
1402 //TeleportFinishPacket teleport = (TeleportFinishPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFinish);
1403
1404 TeleportFinishPacket teleport = new TeleportFinishPacket();
1405 teleport.Info.AgentID = AgentId;
1406 teleport.Info.RegionHandle = regionHandle;
1407 teleport.Info.SimAccess = simAccess;
1408
1409 teleport.Info.SeedCapability = Util.StringToBytes256(capsURL);
1410
1411 IPAddress oIP = newRegionEndPoint.Address;
1412 byte[] byteIP = oIP.GetAddressBytes();
1413 uint ip = (uint)byteIP[3] << 24;
1414 ip += (uint)byteIP[2] << 16;
1415 ip += (uint)byteIP[1] << 8;
1416 ip += (uint)byteIP[0];
1417
1418 teleport.Info.SimIP = ip;
1419 teleport.Info.SimPort = (ushort)newRegionEndPoint.Port;
1420 teleport.Info.LocationID = 4;
1421 teleport.Info.TeleportFlags = 1 << 4;
1422
1423 // Hack to get this out immediately and skip throttles.
1424 OutPacket(teleport, ThrottleOutPacketType.Unknown);
1425 }
1426
1427 /// <summary>
1428 /// Inform the client that a teleport attempt has failed
1429 /// </summary>
1430 public void SendTeleportFailed(string reason)
1431 {
1432 TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed);
1433 tpFailed.Info.AgentID = AgentId;
1434 tpFailed.Info.Reason = Util.StringToBytes256(reason);
1435 tpFailed.AlertInfo = new TeleportFailedPacket.AlertInfoBlock[0];
1436
1437 // Hack to get this out immediately and skip throttles
1438 OutPacket(tpFailed, ThrottleOutPacketType.Unknown);
1439 }
1440
1441 /// <summary>
1442 ///
1443 /// </summary>
1444 public void SendTeleportStart(uint flags)
1445 {
1446 TeleportStartPacket tpStart = (TeleportStartPacket)PacketPool.Instance.GetPacket(PacketType.TeleportStart);
1447 //TeleportStartPacket tpStart = new TeleportStartPacket();
1448 tpStart.Info.TeleportFlags = flags; //16; // Teleport via location
1449
1450 // Hack to get this out immediately and skip throttles
1451 OutPacket(tpStart, ThrottleOutPacketType.Unknown);
1452 }
1453
1454 public void SendTeleportProgress(uint flags, string message)
1455 {
1456 TeleportProgressPacket tpProgress = (TeleportProgressPacket)PacketPool.Instance.GetPacket(PacketType.TeleportProgress);
1457 tpProgress.AgentData.AgentID = this.AgentId;
1458 tpProgress.Info.TeleportFlags = flags;
1459 tpProgress.Info.Message = Util.StringToBytes256(message);
1460
1461 // Hack to get this out immediately and skip throttles
1462 OutPacket(tpProgress, ThrottleOutPacketType.Unknown);
1463 }
1464
1465 public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance)
1466 {
1467 MoneyBalanceReplyPacket money = (MoneyBalanceReplyPacket)PacketPool.Instance.GetPacket(PacketType.MoneyBalanceReply);
1468 money.MoneyData.AgentID = AgentId;
1469 money.MoneyData.TransactionID = transaction;
1470 money.MoneyData.TransactionSuccess = success;
1471 money.MoneyData.Description = description;
1472 money.MoneyData.MoneyBalance = balance;
1473 OutPacket(money, ThrottleOutPacketType.Task);
1474 }
1475
1476 public void SendPayPrice(UUID objectID, int[] payPrice)
1477 {
1478 if (payPrice[0] == 0 &&
1479 payPrice[1] == 0 &&
1480 payPrice[2] == 0 &&
1481 payPrice[3] == 0 &&
1482 payPrice[4] == 0)
1483 return;
1484
1485 PayPriceReplyPacket payPriceReply = (PayPriceReplyPacket)PacketPool.Instance.GetPacket(PacketType.PayPriceReply);
1486 payPriceReply.ObjectData.ObjectID = objectID;
1487 payPriceReply.ObjectData.DefaultPayPrice = payPrice[0];
1488
1489 payPriceReply.ButtonData = new PayPriceReplyPacket.ButtonDataBlock[4];
1490 payPriceReply.ButtonData[0] = new PayPriceReplyPacket.ButtonDataBlock();
1491 payPriceReply.ButtonData[0].PayButton = payPrice[1];
1492 payPriceReply.ButtonData[1] = new PayPriceReplyPacket.ButtonDataBlock();
1493 payPriceReply.ButtonData[1].PayButton = payPrice[2];
1494 payPriceReply.ButtonData[2] = new PayPriceReplyPacket.ButtonDataBlock();
1495 payPriceReply.ButtonData[2].PayButton = payPrice[3];
1496 payPriceReply.ButtonData[3] = new PayPriceReplyPacket.ButtonDataBlock();
1497 payPriceReply.ButtonData[3].PayButton = payPrice[4];
1498
1499 OutPacket(payPriceReply, ThrottleOutPacketType.Task);
1500 }
1501
1502 public void SendStartPingCheck(byte seq)
1503 {
1504 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck);
1505 pc.Header.Reliable = false;
1506
1507 pc.PingID.PingID = seq;
1508 // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit
1509 pc.PingID.OldestUnacked = 0;
1510
1511 OutPacket(pc, ThrottleOutPacketType.Unknown);
1512 }
1513
1514 public void SendKillObject(ulong regionHandle, uint localID)
1515 {
1516// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle);
1517
1518 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1519 // TODO: don't create new blocks if recycling an old packet
1520 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1];
1521 kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock();
1522 kill.ObjectData[0].ID = localID;
1523 kill.Header.Reliable = true;
1524 kill.Header.Zerocoded = true;
1525
1526 if (m_scene.GetScenePresence(localID) == null)
1527 {
1528 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
1529 // condition where a kill can be processed before an out-of-date update for the same object.
1530 lock (m_killRecord)
1531 {
1532 m_killRecord.Add(localID);
1533
1534 // The throttle queue used here must match that being used for updates. Otherwise, there is a
1535 // chance that a kill packet put on a separate queue will be sent to the client before an existing
1536 // update packet on another queue. Receiving updates after kills results in unowned and undeletable
1537 // scene objects in a viewer until that viewer is relogged in.
1538 OutPacket(kill, ThrottleOutPacketType.Task);
1539 }
1540 }
1541 else
1542 {
1543 // OutPacket(kill, ThrottleOutPacketType.State);
1544 OutPacket(kill, ThrottleOutPacketType.Task);
1545 }
1546 }
1547
1548 /// <summary>
1549 /// Send information about the items contained in a folder to the client.
1550 ///
1551 /// XXX This method needs some refactoring loving
1552 /// </summary>
1553 /// <param name="ownerID">The owner of the folder</param>
1554 /// <param name="folderID">The id of the folder</param>
1555 /// <param name="items">The items contained in the folder identified by folderID</param>
1556 /// <param name="folders"></param>
1557 /// <param name="fetchFolders">Do we need to send folder information?</param>
1558 /// <param name="fetchItems">Do we need to send item information?</param>
1559 public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items,
1560 List<InventoryFolderBase> folders, int version,
1561 bool fetchFolders, bool fetchItems)
1562 {
1563 // An inventory descendents packet consists of a single agent section and an inventory details
1564 // section for each inventory item. The size of each inventory item is approximately 550 bytes.
1565 // In theory, UDP has a maximum packet size of 64k, so it should be possible to send descendent
1566 // packets containing metadata for in excess of 100 items. But in practice, there may be other
1567 // factors (e.g. firewalls) restraining the maximum UDP packet size. See,
1568 //
1569 // http://opensimulator.org/mantis/view.php?id=226
1570 //
1571 // for one example of this kind of thing. In fact, the Linden servers appear to only send about
1572 // 6 to 7 items at a time, so let's stick with 6
1573 int MAX_ITEMS_PER_PACKET = 5;
1574 int MAX_FOLDERS_PER_PACKET = 6;
1575
1576 int totalItems = fetchItems ? items.Count : 0;
1577 int totalFolders = fetchFolders ? folders.Count : 0;
1578 int itemsSent = 0;
1579 int foldersSent = 0;
1580 int foldersToSend = 0;
1581 int itemsToSend = 0;
1582
1583 InventoryDescendentsPacket currentPacket = null;
1584
1585 // Handle empty folders
1586 //
1587 if (totalItems == 0 && totalFolders == 0)
1588 currentPacket = CreateInventoryDescendentsPacket(ownerID, folderID, version, items.Count + folders.Count, 0, 0);
1589
1590 // To preserve SL compatibility, we will NOT combine folders and items in one packet
1591 //
1592 while (itemsSent < totalItems || foldersSent < totalFolders)
1593 {
1594 if (currentPacket == null) // Start a new packet
1595 {
1596 foldersToSend = totalFolders - foldersSent;
1597 if (foldersToSend > MAX_FOLDERS_PER_PACKET)
1598 foldersToSend = MAX_FOLDERS_PER_PACKET;
1599
1600 if (foldersToSend == 0)
1601 {
1602 itemsToSend = totalItems - itemsSent;
1603 if (itemsToSend > MAX_ITEMS_PER_PACKET)
1604 itemsToSend = MAX_ITEMS_PER_PACKET;
1605 }
1606
1607 currentPacket = CreateInventoryDescendentsPacket(ownerID, folderID, version, items.Count + folders.Count, foldersToSend, itemsToSend);
1608 }
1609
1610 if (foldersToSend-- > 0)
1611 currentPacket.FolderData[foldersSent % MAX_FOLDERS_PER_PACKET] = CreateFolderDataBlock(folders[foldersSent++]);
1612 else if (itemsToSend-- > 0)
1613 currentPacket.ItemData[itemsSent % MAX_ITEMS_PER_PACKET] = CreateItemDataBlock(items[itemsSent++]);
1614 else
1615 {
1616 OutPacket(currentPacket, ThrottleOutPacketType.Asset, false);
1617 currentPacket = null;
1618 }
1619
1620 }
1621
1622 if (currentPacket != null)
1623 OutPacket(currentPacket, ThrottleOutPacketType.Asset, false);
1624 }
1625
1626 private InventoryDescendentsPacket.FolderDataBlock CreateFolderDataBlock(InventoryFolderBase folder)
1627 {
1628 InventoryDescendentsPacket.FolderDataBlock newBlock = new InventoryDescendentsPacket.FolderDataBlock();
1629 newBlock.FolderID = folder.ID;
1630 newBlock.Name = Util.StringToBytes256(folder.Name);
1631 newBlock.ParentID = folder.ParentID;
1632 newBlock.Type = (sbyte)folder.Type;
1633
1634 return newBlock;
1635 }
1636
1637 private InventoryDescendentsPacket.ItemDataBlock CreateItemDataBlock(InventoryItemBase item)
1638 {
1639 InventoryDescendentsPacket.ItemDataBlock newBlock = new InventoryDescendentsPacket.ItemDataBlock();
1640 newBlock.ItemID = item.ID;
1641 newBlock.AssetID = item.AssetID;
1642 newBlock.CreatorID = item.CreatorIdAsUuid;
1643 newBlock.BaseMask = item.BasePermissions;
1644 newBlock.Description = Util.StringToBytes256(item.Description);
1645 newBlock.EveryoneMask = item.EveryOnePermissions;
1646 newBlock.OwnerMask = item.CurrentPermissions;
1647 newBlock.FolderID = item.Folder;
1648 newBlock.InvType = (sbyte)item.InvType;
1649 newBlock.Name = Util.StringToBytes256(item.Name);
1650 newBlock.NextOwnerMask = item.NextPermissions;
1651 newBlock.OwnerID = item.Owner;
1652 newBlock.Type = (sbyte)item.AssetType;
1653
1654 newBlock.GroupID = item.GroupID;
1655 newBlock.GroupOwned = item.GroupOwned;
1656 newBlock.GroupMask = item.GroupPermissions;
1657 newBlock.CreationDate = item.CreationDate;
1658 newBlock.SalePrice = item.SalePrice;
1659 newBlock.SaleType = item.SaleType;
1660 newBlock.Flags = item.Flags;
1661
1662 newBlock.CRC =
1663 Helpers.InventoryCRC(newBlock.CreationDate, newBlock.SaleType,
1664 newBlock.InvType, newBlock.Type,
1665 newBlock.AssetID, newBlock.GroupID,
1666 newBlock.SalePrice,
1667 newBlock.OwnerID, newBlock.CreatorID,
1668 newBlock.ItemID, newBlock.FolderID,
1669 newBlock.EveryoneMask,
1670 newBlock.Flags, newBlock.OwnerMask,
1671 newBlock.GroupMask, newBlock.NextOwnerMask);
1672
1673 return newBlock;
1674 }
1675
1676 private void AddNullFolderBlockToDecendentsPacket(ref InventoryDescendentsPacket packet)
1677 {
1678 packet.FolderData = new InventoryDescendentsPacket.FolderDataBlock[1];
1679 packet.FolderData[0] = new InventoryDescendentsPacket.FolderDataBlock();
1680 packet.FolderData[0].FolderID = UUID.Zero;
1681 packet.FolderData[0].ParentID = UUID.Zero;
1682 packet.FolderData[0].Type = -1;
1683 packet.FolderData[0].Name = new byte[0];
1684 }
1685
1686 private void AddNullItemBlockToDescendentsPacket(ref InventoryDescendentsPacket packet)
1687 {
1688 packet.ItemData = new InventoryDescendentsPacket.ItemDataBlock[1];
1689 packet.ItemData[0] = new InventoryDescendentsPacket.ItemDataBlock();
1690 packet.ItemData[0].ItemID = UUID.Zero;
1691 packet.ItemData[0].AssetID = UUID.Zero;
1692 packet.ItemData[0].CreatorID = UUID.Zero;
1693 packet.ItemData[0].BaseMask = 0;
1694 packet.ItemData[0].Description = new byte[0];
1695 packet.ItemData[0].EveryoneMask = 0;
1696 packet.ItemData[0].OwnerMask = 0;
1697 packet.ItemData[0].FolderID = UUID.Zero;
1698 packet.ItemData[0].InvType = (sbyte)0;
1699 packet.ItemData[0].Name = new byte[0];
1700 packet.ItemData[0].NextOwnerMask = 0;
1701 packet.ItemData[0].OwnerID = UUID.Zero;
1702 packet.ItemData[0].Type = -1;
1703
1704 packet.ItemData[0].GroupID = UUID.Zero;
1705 packet.ItemData[0].GroupOwned = false;
1706 packet.ItemData[0].GroupMask = 0;
1707 packet.ItemData[0].CreationDate = 0;
1708 packet.ItemData[0].SalePrice = 0;
1709 packet.ItemData[0].SaleType = 0;
1710 packet.ItemData[0].Flags = 0;
1711
1712 // No need to add CRC
1713 }
1714
1715 private InventoryDescendentsPacket CreateInventoryDescendentsPacket(UUID ownerID, UUID folderID, int version, int descendents, int folders, int items)
1716 {
1717 InventoryDescendentsPacket descend = (InventoryDescendentsPacket)PacketPool.Instance.GetPacket(PacketType.InventoryDescendents);
1718 descend.Header.Zerocoded = true;
1719 descend.AgentData.AgentID = AgentId;
1720 descend.AgentData.OwnerID = ownerID;
1721 descend.AgentData.FolderID = folderID;
1722 descend.AgentData.Version = version;
1723 descend.AgentData.Descendents = descendents;
1724
1725 if (folders > 0)
1726 descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[folders];
1727 else
1728 AddNullFolderBlockToDecendentsPacket(ref descend);
1729
1730 if (items > 0)
1731 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items];
1732 else
1733 AddNullItemBlockToDescendentsPacket(ref descend);
1734
1735 return descend;
1736 }
1737
1738 public void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item)
1739 {
1740 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
1741
1742 FetchInventoryReplyPacket inventoryReply = (FetchInventoryReplyPacket)PacketPool.Instance.GetPacket(PacketType.FetchInventoryReply);
1743 // TODO: don't create new blocks if recycling an old packet
1744 inventoryReply.AgentData.AgentID = AgentId;
1745 inventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[1];
1746 inventoryReply.InventoryData[0] = new FetchInventoryReplyPacket.InventoryDataBlock();
1747 inventoryReply.InventoryData[0].ItemID = item.ID;
1748 inventoryReply.InventoryData[0].AssetID = item.AssetID;
1749 inventoryReply.InventoryData[0].CreatorID = item.CreatorIdAsUuid;
1750 inventoryReply.InventoryData[0].BaseMask = item.BasePermissions;
1751 inventoryReply.InventoryData[0].CreationDate = item.CreationDate;
1752
1753 inventoryReply.InventoryData[0].Description = Util.StringToBytes256(item.Description);
1754 inventoryReply.InventoryData[0].EveryoneMask = item.EveryOnePermissions;
1755 inventoryReply.InventoryData[0].FolderID = item.Folder;
1756 inventoryReply.InventoryData[0].InvType = (sbyte)item.InvType;
1757 inventoryReply.InventoryData[0].Name = Util.StringToBytes256(item.Name);
1758 inventoryReply.InventoryData[0].NextOwnerMask = item.NextPermissions;
1759 inventoryReply.InventoryData[0].OwnerID = item.Owner;
1760 inventoryReply.InventoryData[0].OwnerMask = item.CurrentPermissions;
1761 inventoryReply.InventoryData[0].Type = (sbyte)item.AssetType;
1762
1763 inventoryReply.InventoryData[0].GroupID = item.GroupID;
1764 inventoryReply.InventoryData[0].GroupOwned = item.GroupOwned;
1765 inventoryReply.InventoryData[0].GroupMask = item.GroupPermissions;
1766 inventoryReply.InventoryData[0].Flags = item.Flags;
1767 inventoryReply.InventoryData[0].SalePrice = item.SalePrice;
1768 inventoryReply.InventoryData[0].SaleType = item.SaleType;
1769
1770 inventoryReply.InventoryData[0].CRC =
1771 Helpers.InventoryCRC(
1772 1000, 0, inventoryReply.InventoryData[0].InvType,
1773 inventoryReply.InventoryData[0].Type, inventoryReply.InventoryData[0].AssetID,
1774 inventoryReply.InventoryData[0].GroupID, 100,
1775 inventoryReply.InventoryData[0].OwnerID, inventoryReply.InventoryData[0].CreatorID,
1776 inventoryReply.InventoryData[0].ItemID, inventoryReply.InventoryData[0].FolderID,
1777 FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
1778 FULL_MASK_PERMISSIONS);
1779 inventoryReply.Header.Zerocoded = true;
1780 OutPacket(inventoryReply, ThrottleOutPacketType.Asset);
1781 }
1782
1783 protected void SendBulkUpdateInventoryFolder(InventoryFolderBase folderBase)
1784 {
1785 // We will use the same transaction id for all the separate packets to be sent out in this update.
1786 UUID transactionId = UUID.Random();
1787
1788 List<BulkUpdateInventoryPacket.FolderDataBlock> folderDataBlocks
1789 = new List<BulkUpdateInventoryPacket.FolderDataBlock>();
1790
1791 SendBulkUpdateInventoryFolderRecursive(folderBase, ref folderDataBlocks, transactionId);
1792
1793 if (folderDataBlocks.Count > 0)
1794 {
1795 // We'll end up with some unsent folder blocks if there were some empty folders at the end of the list
1796 // Send these now
1797 BulkUpdateInventoryPacket bulkUpdate
1798 = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory);
1799 bulkUpdate.Header.Zerocoded = true;
1800
1801 bulkUpdate.AgentData.AgentID = AgentId;
1802 bulkUpdate.AgentData.TransactionID = transactionId;
1803 bulkUpdate.FolderData = folderDataBlocks.ToArray();
1804 List<BulkUpdateInventoryPacket.ItemDataBlock> foo = new List<BulkUpdateInventoryPacket.ItemDataBlock>();
1805 bulkUpdate.ItemData = foo.ToArray();
1806
1807 //m_log.Debug("SendBulkUpdateInventory :" + bulkUpdate);
1808 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
1809 }
1810 }
1811
1812 /// <summary>
1813 /// Recursively construct bulk update packets to send folders and items
1814 /// </summary>
1815 /// <param name="folder"></param>
1816 /// <param name="folderDataBlocks"></param>
1817 /// <param name="transactionId"></param>
1818 private void SendBulkUpdateInventoryFolderRecursive(
1819 InventoryFolderBase folder, ref List<BulkUpdateInventoryPacket.FolderDataBlock> folderDataBlocks,
1820 UUID transactionId)
1821 {
1822 folderDataBlocks.Add(GenerateBulkUpdateFolderDataBlock(folder));
1823
1824 const int MAX_ITEMS_PER_PACKET = 5;
1825
1826 IInventoryService invService = m_scene.RequestModuleInterface<IInventoryService>();
1827 // If there are any items then we have to start sending them off in this packet - the next folder will have
1828 // to be in its own bulk update packet. Also, we can only fit 5 items in a packet (at least this was the limit
1829 // being used on the Linden grid at 20081203).
1830 InventoryCollection contents = invService.GetFolderContent(AgentId, folder.ID); // folder.RequestListOfItems();
1831 List<InventoryItemBase> items = contents.Items;
1832 while (items.Count > 0)
1833 {
1834 BulkUpdateInventoryPacket bulkUpdate
1835 = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory);
1836 bulkUpdate.Header.Zerocoded = true;
1837
1838 bulkUpdate.AgentData.AgentID = AgentId;
1839 bulkUpdate.AgentData.TransactionID = transactionId;
1840 bulkUpdate.FolderData = folderDataBlocks.ToArray();
1841
1842 int itemsToSend = (items.Count > MAX_ITEMS_PER_PACKET ? MAX_ITEMS_PER_PACKET : items.Count);
1843 bulkUpdate.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[itemsToSend];
1844
1845 for (int i = 0; i < itemsToSend; i++)
1846 {
1847 // Remove from the end of the list so that we don't incur a performance penalty
1848 bulkUpdate.ItemData[i] = GenerateBulkUpdateItemDataBlock(items[items.Count - 1]);
1849 items.RemoveAt(items.Count - 1);
1850 }
1851
1852 //m_log.Debug("SendBulkUpdateInventoryRecursive :" + bulkUpdate);
1853 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
1854
1855 folderDataBlocks = new List<BulkUpdateInventoryPacket.FolderDataBlock>();
1856
1857 // If we're going to be sending another items packet then it needs to contain just the folder to which those
1858 // items belong.
1859 if (items.Count > 0)
1860 folderDataBlocks.Add(GenerateBulkUpdateFolderDataBlock(folder));
1861 }
1862
1863 List<InventoryFolderBase> subFolders = contents.Folders;
1864 foreach (InventoryFolderBase subFolder in subFolders)
1865 {
1866 SendBulkUpdateInventoryFolderRecursive(subFolder, ref folderDataBlocks, transactionId);
1867 }
1868 }
1869
1870 /// <summary>
1871 /// Generate a bulk update inventory data block for the given folder
1872 /// </summary>
1873 /// <param name="folder"></param>
1874 /// <returns></returns>
1875 private BulkUpdateInventoryPacket.FolderDataBlock GenerateBulkUpdateFolderDataBlock(InventoryFolderBase folder)
1876 {
1877 BulkUpdateInventoryPacket.FolderDataBlock folderBlock = new BulkUpdateInventoryPacket.FolderDataBlock();
1878
1879 folderBlock.FolderID = folder.ID;
1880 folderBlock.ParentID = folder.ParentID;
1881 folderBlock.Type = -1;
1882 folderBlock.Name = Util.StringToBytes256(folder.Name);
1883
1884 return folderBlock;
1885 }
1886
1887 /// <summary>
1888 /// Generate a bulk update inventory data block for the given item
1889 /// </summary>
1890 /// <param name="item"></param>
1891 /// <returns></returns>
1892 private BulkUpdateInventoryPacket.ItemDataBlock GenerateBulkUpdateItemDataBlock(InventoryItemBase item)
1893 {
1894 BulkUpdateInventoryPacket.ItemDataBlock itemBlock = new BulkUpdateInventoryPacket.ItemDataBlock();
1895
1896 itemBlock.ItemID = item.ID;
1897 itemBlock.AssetID = item.AssetID;
1898 itemBlock.CreatorID = item.CreatorIdAsUuid;
1899 itemBlock.BaseMask = item.BasePermissions;
1900 itemBlock.Description = Util.StringToBytes256(item.Description);
1901 itemBlock.EveryoneMask = item.EveryOnePermissions;
1902 itemBlock.FolderID = item.Folder;
1903 itemBlock.InvType = (sbyte)item.InvType;
1904 itemBlock.Name = Util.StringToBytes256(item.Name);
1905 itemBlock.NextOwnerMask = item.NextPermissions;
1906 itemBlock.OwnerID = item.Owner;
1907 itemBlock.OwnerMask = item.CurrentPermissions;
1908 itemBlock.Type = (sbyte)item.AssetType;
1909 itemBlock.GroupID = item.GroupID;
1910 itemBlock.GroupOwned = item.GroupOwned;
1911 itemBlock.GroupMask = item.GroupPermissions;
1912 itemBlock.Flags = item.Flags;
1913 itemBlock.SalePrice = item.SalePrice;
1914 itemBlock.SaleType = item.SaleType;
1915 itemBlock.CreationDate = item.CreationDate;
1916
1917 itemBlock.CRC =
1918 Helpers.InventoryCRC(
1919 1000, 0, itemBlock.InvType,
1920 itemBlock.Type, itemBlock.AssetID,
1921 itemBlock.GroupID, 100,
1922 itemBlock.OwnerID, itemBlock.CreatorID,
1923 itemBlock.ItemID, itemBlock.FolderID,
1924 (uint)PermissionMask.All, 1, (uint)PermissionMask.All, (uint)PermissionMask.All,
1925 (uint)PermissionMask.All);
1926
1927 return itemBlock;
1928 }
1929
1930 public void SendBulkUpdateInventory(InventoryNodeBase node)
1931 {
1932 if (node is InventoryItemBase)
1933 SendBulkUpdateInventoryItem((InventoryItemBase)node);
1934 else if (node is InventoryFolderBase)
1935 SendBulkUpdateInventoryFolder((InventoryFolderBase)node);
1936 else
1937 m_log.ErrorFormat("[CLIENT]: Client for {0} sent unknown inventory node named {1}", Name, node.Name);
1938 }
1939
1940 protected void SendBulkUpdateInventoryItem(InventoryItemBase item)
1941 {
1942 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
1943
1944 BulkUpdateInventoryPacket bulkUpdate
1945 = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory);
1946
1947 bulkUpdate.AgentData.AgentID = AgentId;
1948 bulkUpdate.AgentData.TransactionID = UUID.Random();
1949
1950 bulkUpdate.FolderData = new BulkUpdateInventoryPacket.FolderDataBlock[1];
1951 bulkUpdate.FolderData[0] = new BulkUpdateInventoryPacket.FolderDataBlock();
1952 bulkUpdate.FolderData[0].FolderID = UUID.Zero;
1953 bulkUpdate.FolderData[0].ParentID = UUID.Zero;
1954 bulkUpdate.FolderData[0].Type = -1;
1955 bulkUpdate.FolderData[0].Name = new byte[0];
1956
1957 bulkUpdate.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[1];
1958 bulkUpdate.ItemData[0] = new BulkUpdateInventoryPacket.ItemDataBlock();
1959 bulkUpdate.ItemData[0].ItemID = item.ID;
1960 bulkUpdate.ItemData[0].AssetID = item.AssetID;
1961 bulkUpdate.ItemData[0].CreatorID = item.CreatorIdAsUuid;
1962 bulkUpdate.ItemData[0].BaseMask = item.BasePermissions;
1963 bulkUpdate.ItemData[0].CreationDate = item.CreationDate;
1964 bulkUpdate.ItemData[0].Description = Util.StringToBytes256(item.Description);
1965 bulkUpdate.ItemData[0].EveryoneMask = item.EveryOnePermissions;
1966 bulkUpdate.ItemData[0].FolderID = item.Folder;
1967 bulkUpdate.ItemData[0].InvType = (sbyte)item.InvType;
1968 bulkUpdate.ItemData[0].Name = Util.StringToBytes256(item.Name);
1969 bulkUpdate.ItemData[0].NextOwnerMask = item.NextPermissions;
1970 bulkUpdate.ItemData[0].OwnerID = item.Owner;
1971 bulkUpdate.ItemData[0].OwnerMask = item.CurrentPermissions;
1972 bulkUpdate.ItemData[0].Type = (sbyte)item.AssetType;
1973
1974 bulkUpdate.ItemData[0].GroupID = item.GroupID;
1975 bulkUpdate.ItemData[0].GroupOwned = item.GroupOwned;
1976 bulkUpdate.ItemData[0].GroupMask = item.GroupPermissions;
1977 bulkUpdate.ItemData[0].Flags = item.Flags;
1978 bulkUpdate.ItemData[0].SalePrice = item.SalePrice;
1979 bulkUpdate.ItemData[0].SaleType = item.SaleType;
1980
1981 bulkUpdate.ItemData[0].CRC =
1982 Helpers.InventoryCRC(1000, 0, bulkUpdate.ItemData[0].InvType,
1983 bulkUpdate.ItemData[0].Type, bulkUpdate.ItemData[0].AssetID,
1984 bulkUpdate.ItemData[0].GroupID, 100,
1985 bulkUpdate.ItemData[0].OwnerID, bulkUpdate.ItemData[0].CreatorID,
1986 bulkUpdate.ItemData[0].ItemID, bulkUpdate.ItemData[0].FolderID,
1987 FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
1988 FULL_MASK_PERMISSIONS);
1989 bulkUpdate.Header.Zerocoded = true;
1990 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
1991 }
1992
1993 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
1994 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
1995 {
1996 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
1997
1998 UpdateCreateInventoryItemPacket InventoryReply
1999 = (UpdateCreateInventoryItemPacket)PacketPool.Instance.GetPacket(
2000 PacketType.UpdateCreateInventoryItem);
2001
2002 // TODO: don't create new blocks if recycling an old packet
2003 InventoryReply.AgentData.AgentID = AgentId;
2004 InventoryReply.AgentData.SimApproved = true;
2005 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
2006 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
2007 InventoryReply.InventoryData[0].ItemID = Item.ID;
2008 InventoryReply.InventoryData[0].AssetID = Item.AssetID;
2009 InventoryReply.InventoryData[0].CreatorID = Item.CreatorIdAsUuid;
2010 InventoryReply.InventoryData[0].BaseMask = Item.BasePermissions;
2011 InventoryReply.InventoryData[0].Description = Util.StringToBytes256(Item.Description);
2012 InventoryReply.InventoryData[0].EveryoneMask = Item.EveryOnePermissions;
2013 InventoryReply.InventoryData[0].FolderID = Item.Folder;
2014 InventoryReply.InventoryData[0].InvType = (sbyte)Item.InvType;
2015 InventoryReply.InventoryData[0].Name = Util.StringToBytes256(Item.Name);
2016 InventoryReply.InventoryData[0].NextOwnerMask = Item.NextPermissions;
2017 InventoryReply.InventoryData[0].OwnerID = Item.Owner;
2018 InventoryReply.InventoryData[0].OwnerMask = Item.CurrentPermissions;
2019 InventoryReply.InventoryData[0].Type = (sbyte)Item.AssetType;
2020 InventoryReply.InventoryData[0].CallbackID = callbackId;
2021
2022 InventoryReply.InventoryData[0].GroupID = Item.GroupID;
2023 InventoryReply.InventoryData[0].GroupOwned = Item.GroupOwned;
2024 InventoryReply.InventoryData[0].GroupMask = Item.GroupPermissions;
2025 InventoryReply.InventoryData[0].Flags = Item.Flags;
2026 InventoryReply.InventoryData[0].SalePrice = Item.SalePrice;
2027 InventoryReply.InventoryData[0].SaleType = Item.SaleType;
2028 InventoryReply.InventoryData[0].CreationDate = Item.CreationDate;
2029
2030 InventoryReply.InventoryData[0].CRC =
2031 Helpers.InventoryCRC(1000, 0, InventoryReply.InventoryData[0].InvType,
2032 InventoryReply.InventoryData[0].Type, InventoryReply.InventoryData[0].AssetID,
2033 InventoryReply.InventoryData[0].GroupID, 100,
2034 InventoryReply.InventoryData[0].OwnerID, InventoryReply.InventoryData[0].CreatorID,
2035 InventoryReply.InventoryData[0].ItemID, InventoryReply.InventoryData[0].FolderID,
2036 FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
2037 FULL_MASK_PERMISSIONS);
2038 InventoryReply.Header.Zerocoded = true;
2039 OutPacket(InventoryReply, ThrottleOutPacketType.Asset);
2040 }
2041
2042 public void SendRemoveInventoryItem(UUID itemID)
2043 {
2044 RemoveInventoryItemPacket remove = (RemoveInventoryItemPacket)PacketPool.Instance.GetPacket(PacketType.RemoveInventoryItem);
2045 // TODO: don't create new blocks if recycling an old packet
2046 remove.AgentData.AgentID = AgentId;
2047 remove.AgentData.SessionID = m_sessionId;
2048 remove.InventoryData = new RemoveInventoryItemPacket.InventoryDataBlock[1];
2049 remove.InventoryData[0] = new RemoveInventoryItemPacket.InventoryDataBlock();
2050 remove.InventoryData[0].ItemID = itemID;
2051 remove.Header.Zerocoded = true;
2052 OutPacket(remove, ThrottleOutPacketType.Asset);
2053 }
2054
2055 public void SendTakeControls(int controls, bool passToAgent, bool TakeControls)
2056 {
2057 ScriptControlChangePacket scriptcontrol = (ScriptControlChangePacket)PacketPool.Instance.GetPacket(PacketType.ScriptControlChange);
2058 ScriptControlChangePacket.DataBlock[] data = new ScriptControlChangePacket.DataBlock[1];
2059 ScriptControlChangePacket.DataBlock ddata = new ScriptControlChangePacket.DataBlock();
2060 ddata.Controls = (uint)controls;
2061 ddata.PassToAgent = passToAgent;
2062 ddata.TakeControls = TakeControls;
2063 data[0] = ddata;
2064 scriptcontrol.Data = data;
2065 OutPacket(scriptcontrol, ThrottleOutPacketType.Task);
2066 }
2067
2068 public void SendTaskInventory(UUID taskID, short serial, byte[] fileName)
2069 {
2070 ReplyTaskInventoryPacket replytask = (ReplyTaskInventoryPacket)PacketPool.Instance.GetPacket(PacketType.ReplyTaskInventory);
2071 replytask.InventoryData.TaskID = taskID;
2072 replytask.InventoryData.Serial = serial;
2073 replytask.InventoryData.Filename = fileName;
2074 OutPacket(replytask, ThrottleOutPacketType.Asset);
2075 }
2076
2077 public void SendXferPacket(ulong xferID, uint packet, byte[] data)
2078 {
2079 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket);
2080 sendXfer.XferID.ID = xferID;
2081 sendXfer.XferID.Packet = packet;
2082 sendXfer.DataPacket.Data = data;
2083 OutPacket(sendXfer, ThrottleOutPacketType.Asset);
2084 }
2085
2086 public void SendAbortXferPacket(ulong xferID)
2087 {
2088 AbortXferPacket xferItem = (AbortXferPacket)PacketPool.Instance.GetPacket(PacketType.AbortXfer);
2089 xferItem.XferID.ID = xferID;
2090 OutPacket(xferItem, ThrottleOutPacketType.Asset);
2091 }
2092
2093 public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit,
2094 int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor,
2095 int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay,
2096 int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent)
2097 {
2098 EconomyDataPacket economyData = (EconomyDataPacket)PacketPool.Instance.GetPacket(PacketType.EconomyData);
2099 economyData.Info.EnergyEfficiency = EnergyEfficiency;
2100 economyData.Info.ObjectCapacity = ObjectCapacity;
2101 economyData.Info.ObjectCount = ObjectCount;
2102 economyData.Info.PriceEnergyUnit = PriceEnergyUnit;
2103 economyData.Info.PriceGroupCreate = PriceGroupCreate;
2104 economyData.Info.PriceObjectClaim = PriceObjectClaim;
2105 economyData.Info.PriceObjectRent = PriceObjectRent;
2106 economyData.Info.PriceObjectScaleFactor = PriceObjectScaleFactor;
2107 economyData.Info.PriceParcelClaim = PriceParcelClaim;
2108 economyData.Info.PriceParcelClaimFactor = PriceParcelClaimFactor;
2109 economyData.Info.PriceParcelRent = PriceParcelRent;
2110 economyData.Info.PricePublicObjectDecay = PricePublicObjectDecay;
2111 economyData.Info.PricePublicObjectDelete = PricePublicObjectDelete;
2112 economyData.Info.PriceRentLight = PriceRentLight;
2113 economyData.Info.PriceUpload = PriceUpload;
2114 economyData.Info.TeleportMinPrice = TeleportMinPrice;
2115 economyData.Info.TeleportPriceExponent = TeleportPriceExponent;
2116 economyData.Header.Reliable = true;
2117 OutPacket(economyData, ThrottleOutPacketType.Task);
2118 }
2119
2120 public void SendAvatarPickerReply(AvatarPickerReplyAgentDataArgs AgentData, List<AvatarPickerReplyDataArgs> Data)
2121 {
2122 //construct the AvatarPickerReply packet.
2123 AvatarPickerReplyPacket replyPacket = new AvatarPickerReplyPacket();
2124 replyPacket.AgentData.AgentID = AgentData.AgentID;
2125 replyPacket.AgentData.QueryID = AgentData.QueryID;
2126 //int i = 0;
2127 List<AvatarPickerReplyPacket.DataBlock> data_block = new List<AvatarPickerReplyPacket.DataBlock>();
2128 foreach (AvatarPickerReplyDataArgs arg in Data)
2129 {
2130 AvatarPickerReplyPacket.DataBlock db = new AvatarPickerReplyPacket.DataBlock();
2131 db.AvatarID = arg.AvatarID;
2132 db.FirstName = arg.FirstName;
2133 db.LastName = arg.LastName;
2134 data_block.Add(db);
2135 }
2136 replyPacket.Data = data_block.ToArray();
2137 OutPacket(replyPacket, ThrottleOutPacketType.Task);
2138 }
2139
2140 public void SendAgentDataUpdate(UUID agentid, UUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle)
2141 {
2142 m_activeGroupID = activegroupid;
2143 m_activeGroupName = groupname;
2144 m_activeGroupPowers = grouppowers;
2145
2146 AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate);
2147 sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid;
2148 sendAgentDataUpdate.AgentData.AgentID = agentid;
2149 sendAgentDataUpdate.AgentData.FirstName = Util.StringToBytes256(firstname);
2150 sendAgentDataUpdate.AgentData.GroupName = Util.StringToBytes256(groupname);
2151 sendAgentDataUpdate.AgentData.GroupPowers = grouppowers;
2152 sendAgentDataUpdate.AgentData.GroupTitle = Util.StringToBytes256(grouptitle);
2153 sendAgentDataUpdate.AgentData.LastName = Util.StringToBytes256(lastname);
2154 OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task);
2155 }
2156
2157 /// <summary>
2158 /// Send an alert message to the client. On the Linden client (tested 1.19.1.4), this pops up a brief duration
2159 /// blue information box in the bottom right hand corner.
2160 /// </summary>
2161 /// <param name="message"></param>
2162 public void SendAlertMessage(string message)
2163 {
2164 AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage);
2165 alertPack.AlertData = new AlertMessagePacket.AlertDataBlock();
2166 alertPack.AlertData.Message = Util.StringToBytes256(message);
2167 alertPack.AlertInfo = new AlertMessagePacket.AlertInfoBlock[0];
2168 OutPacket(alertPack, ThrottleOutPacketType.Task);
2169 }
2170
2171 /// <summary>
2172 /// Send an agent alert message to the client.
2173 /// </summary>
2174 /// <param name="message"></param>
2175 /// <param name="modal">On the linden client, if this true then it displays a one button text box placed in the
2176 /// middle of the window. If false, the message is displayed in a brief duration blue information box (as for
2177 /// the AlertMessage packet).</param>
2178 public void SendAgentAlertMessage(string message, bool modal)
2179 {
2180 OutPacket(BuildAgentAlertPacket(message, modal), ThrottleOutPacketType.Task);
2181 }
2182
2183 /// <summary>
2184 /// Construct an agent alert packet
2185 /// </summary>
2186 /// <param name="message"></param>
2187 /// <param name="modal"></param>
2188 /// <returns></returns>
2189 public AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal)
2190 {
2191 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage);
2192 alertPack.AgentData.AgentID = AgentId;
2193 alertPack.AlertData.Message = Util.StringToBytes256(message);
2194 alertPack.AlertData.Modal = modal;
2195
2196 return alertPack;
2197 }
2198
2199 public void SendLoadURL(string objectname, UUID objectID, UUID ownerID, bool groupOwned, string message,
2200 string url)
2201 {
2202 LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL);
2203 loadURL.Data.ObjectName = Util.StringToBytes256(objectname);
2204 loadURL.Data.ObjectID = objectID;
2205 loadURL.Data.OwnerID = ownerID;
2206 loadURL.Data.OwnerIsGroup = groupOwned;
2207 loadURL.Data.Message = Util.StringToBytes256(message);
2208 loadURL.Data.URL = Util.StringToBytes256(url);
2209 OutPacket(loadURL, ThrottleOutPacketType.Task);
2210 }
2211
2212 public void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels)
2213 {
2214 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog);
2215 dialog.Data.ObjectID = objectID;
2216 dialog.Data.ObjectName = Util.StringToBytes256(objectname);
2217 // this is the username of the *owner*
2218 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
2219 dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
2220 dialog.Data.Message = Util.StringToBytes1024(msg);
2221 dialog.Data.ImageID = textureID;
2222 dialog.Data.ChatChannel = ch;
2223 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length];
2224 for (int i = 0; i < buttonlabels.Length; i++)
2225 {
2226 buttons[i] = new ScriptDialogPacket.ButtonsBlock();
2227 buttons[i].ButtonLabel = Util.StringToBytes256(buttonlabels[i]);
2228 }
2229 dialog.Buttons = buttons;
2230 OutPacket(dialog, ThrottleOutPacketType.Task);
2231 }
2232
2233 public void SendPreLoadSound(UUID objectID, UUID ownerID, UUID soundID)
2234 {
2235 PreloadSoundPacket preSound = (PreloadSoundPacket)PacketPool.Instance.GetPacket(PacketType.PreloadSound);
2236 // TODO: don't create new blocks if recycling an old packet
2237 preSound.DataBlock = new PreloadSoundPacket.DataBlockBlock[1];
2238 preSound.DataBlock[0] = new PreloadSoundPacket.DataBlockBlock();
2239 preSound.DataBlock[0].ObjectID = objectID;
2240 preSound.DataBlock[0].OwnerID = ownerID;
2241 preSound.DataBlock[0].SoundID = soundID;
2242 preSound.Header.Zerocoded = true;
2243 OutPacket(preSound, ThrottleOutPacketType.Task);
2244 }
2245
2246 public void SendPlayAttachedSound(UUID soundID, UUID objectID, UUID ownerID, float gain, byte flags)
2247 {
2248 AttachedSoundPacket sound = (AttachedSoundPacket)PacketPool.Instance.GetPacket(PacketType.AttachedSound);
2249 sound.DataBlock.SoundID = soundID;
2250 sound.DataBlock.ObjectID = objectID;
2251 sound.DataBlock.OwnerID = ownerID;
2252 sound.DataBlock.Gain = gain;
2253 sound.DataBlock.Flags = flags;
2254
2255 OutPacket(sound, ThrottleOutPacketType.Task);
2256 }
2257
2258 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2259 {
2260 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
2261 sound.SoundData.SoundID = soundID;
2262 sound.SoundData.OwnerID = ownerID;
2263 sound.SoundData.ObjectID = objectID;
2264 sound.SoundData.ParentID = parentID;
2265 sound.SoundData.Handle = handle;
2266 sound.SoundData.Position = position;
2267 sound.SoundData.Gain = gain;
2268
2269 OutPacket(sound, ThrottleOutPacketType.Task);
2270 }
2271
2272 public void SendAttachedSoundGainChange(UUID objectID, float gain)
2273 {
2274 AttachedSoundGainChangePacket sound = (AttachedSoundGainChangePacket)PacketPool.Instance.GetPacket(PacketType.AttachedSoundGainChange);
2275 sound.DataBlock.ObjectID = objectID;
2276 sound.DataBlock.Gain = gain;
2277
2278 OutPacket(sound, ThrottleOutPacketType.Task);
2279 }
2280
2281 public void SendSunPos(Vector3 Position, Vector3 Velocity, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, float OrbitalPosition)
2282 {
2283 // Viewers based on the Linden viwer code, do wacky things for oribital positions from Midnight to Sunrise
2284 // So adjust for that
2285 // Contributed by: Godfrey
2286
2287 if (OrbitalPosition > m_sunPainDaHalfOrbitalCutoff) // things get weird from midnight to sunrise
2288 {
2289 OrbitalPosition = (OrbitalPosition - m_sunPainDaHalfOrbitalCutoff) * 0.6666666667f + m_sunPainDaHalfOrbitalCutoff;
2290 }
2291
2292
2293
2294 SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage);
2295 viewertime.TimeInfo.SunDirection = Position;
2296 viewertime.TimeInfo.SunAngVelocity = Velocity;
2297
2298 // Sun module used to add 6 hours to adjust for linden sun hour, adding here
2299 // to prevent existing code from breaking if it assumed that 6 hours were included.
2300 // 21600 == 6 hours * 60 minutes * 60 Seconds
2301 viewertime.TimeInfo.UsecSinceStart = CurrentTime + 21600;
2302
2303 viewertime.TimeInfo.SecPerDay = SecondsPerSunCycle;
2304 viewertime.TimeInfo.SecPerYear = SecondsPerYear;
2305 viewertime.TimeInfo.SunPhase = OrbitalPosition;
2306 viewertime.Header.Reliable = false;
2307 viewertime.Header.Zerocoded = true;
2308 OutPacket(viewertime, ThrottleOutPacketType.Task);
2309 }
2310
2311 // Currently Deprecated
2312 public void SendViewerTime(int phase)
2313 {
2314 /*
2315 Console.WriteLine("SunPhase: {0}", phase);
2316 SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage);
2317 //viewertime.TimeInfo.SecPerDay = 86400;
2318 //viewertime.TimeInfo.SecPerYear = 31536000;
2319 viewertime.TimeInfo.SecPerDay = 1000;
2320 viewertime.TimeInfo.SecPerYear = 365000;
2321 viewertime.TimeInfo.SunPhase = 1;
2322 int sunPhase = (phase + 2) / 2;
2323 if ((sunPhase < 6) || (sunPhase > 36))
2324 {
2325 viewertime.TimeInfo.SunDirection = new Vector3(0f, 0.8f, -0.8f);
2326 Console.WriteLine("sending night");
2327 }
2328 else
2329 {
2330 if (sunPhase < 12)
2331 {
2332 sunPhase = 12;
2333 }
2334 sunPhase = sunPhase - 12;
2335
2336 float yValue = 0.1f * (sunPhase);
2337 Console.WriteLine("Computed SunPhase: {0}, yValue: {1}", sunPhase, yValue);
2338 if (yValue > 1.2f)
2339 {
2340 yValue = yValue - 1.2f;
2341 }
2342
2343 yValue = Util.Clip(yValue, 0, 1);
2344
2345 if (sunPhase < 14)
2346 {
2347 yValue = 1 - yValue;
2348 }
2349 if (sunPhase < 12)
2350 {
2351 yValue *= -1;
2352 }
2353 viewertime.TimeInfo.SunDirection = new Vector3(0f, yValue, 0.3f);
2354 Console.WriteLine("sending sun update " + yValue);
2355 }
2356 viewertime.TimeInfo.SunAngVelocity = new Vector3(0, 0.0f, 10.0f);
2357 viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch();
2358 viewertime.Header.Reliable = false;
2359 OutPacket(viewertime, ThrottleOutPacketType.Task);
2360 */
2361 }
2362
2363 public void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks)
2364 {
2365 ViewerEffectPacket packet = (ViewerEffectPacket)PacketPool.Instance.GetPacket(PacketType.ViewerEffect);
2366 packet.Header.Reliable = false;
2367 packet.Header.Zerocoded = true;
2368
2369 packet.AgentData.AgentID = AgentId;
2370 packet.AgentData.SessionID = SessionId;
2371
2372 packet.Effect = effectBlocks;
2373
2374 // OutPacket(packet, ThrottleOutPacketType.State);
2375 OutPacket(packet, ThrottleOutPacketType.Task);
2376 }
2377
2378 public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember,
2379 string flAbout, uint flags, UUID flImageID, UUID imageID, string profileURL,
2380 UUID partnerID)
2381 {
2382 AvatarPropertiesReplyPacket avatarReply = (AvatarPropertiesReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPropertiesReply);
2383 avatarReply.AgentData.AgentID = AgentId;
2384 avatarReply.AgentData.AvatarID = avatarID;
2385 if (aboutText != null)
2386 avatarReply.PropertiesData.AboutText = Util.StringToBytes1024(aboutText);
2387 else
2388 avatarReply.PropertiesData.AboutText = Utils.EmptyBytes;
2389 avatarReply.PropertiesData.BornOn = Util.StringToBytes256(bornOn);
2390 avatarReply.PropertiesData.CharterMember = charterMember;
2391 if (flAbout != null)
2392 avatarReply.PropertiesData.FLAboutText = Util.StringToBytes256(flAbout);
2393 else
2394 avatarReply.PropertiesData.FLAboutText = Utils.EmptyBytes;
2395 avatarReply.PropertiesData.Flags = flags;
2396 avatarReply.PropertiesData.FLImageID = flImageID;
2397 avatarReply.PropertiesData.ImageID = imageID;
2398 avatarReply.PropertiesData.ProfileURL = Util.StringToBytes256(profileURL);
2399 avatarReply.PropertiesData.PartnerID = partnerID;
2400 OutPacket(avatarReply, ThrottleOutPacketType.Task);
2401 }
2402
2403 /// <summary>
2404 /// Send the client an Estate message blue box pop-down with a single OK button
2405 /// </summary>
2406 /// <param name="FromAvatarID"></param>
2407 /// <param name="fromSessionID"></param>
2408 /// <param name="FromAvatarName"></param>
2409 /// <param name="Message"></param>
2410 public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message)
2411 {
2412 if (!ChildAgentStatus())
2413 SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3()));
2414
2415 //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch());
2416 }
2417
2418 public void SendLogoutPacket()
2419 {
2420 // I know this is a bit of a hack, however there are times when you don't
2421 // want to send this, but still need to do the rest of the shutdown process
2422 // this method gets called from the packet server.. which makes it practically
2423 // impossible to do any other way.
2424
2425 if (m_SendLogoutPacketWhenClosing)
2426 {
2427 LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply);
2428 // TODO: don't create new blocks if recycling an old packet
2429 logReply.AgentData.AgentID = AgentId;
2430 logReply.AgentData.SessionID = SessionId;
2431 logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
2432 logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
2433 logReply.InventoryData[0].ItemID = UUID.Zero;
2434
2435 OutPacket(logReply, ThrottleOutPacketType.Task);
2436 }
2437 }
2438
2439 public void SendHealth(float health)
2440 {
2441 HealthMessagePacket healthpacket = (HealthMessagePacket)PacketPool.Instance.GetPacket(PacketType.HealthMessage);
2442 healthpacket.HealthData.Health = health;
2443 OutPacket(healthpacket, ThrottleOutPacketType.Task);
2444 }
2445
2446 public void SendAgentOnline(UUID[] agentIDs)
2447 {
2448 OnlineNotificationPacket onp = new OnlineNotificationPacket();
2449 OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[agentIDs.Length];
2450 for (int i = 0; i < agentIDs.Length; i++)
2451 {
2452 OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock();
2453 onpbl.AgentID = agentIDs[i];
2454 onpb[i] = onpbl;
2455 }
2456 onp.AgentBlock = onpb;
2457 onp.Header.Reliable = true;
2458 OutPacket(onp, ThrottleOutPacketType.Task);
2459 }
2460
2461 public void SendAgentOffline(UUID[] agentIDs)
2462 {
2463 OfflineNotificationPacket offp = new OfflineNotificationPacket();
2464 OfflineNotificationPacket.AgentBlockBlock[] offpb = new OfflineNotificationPacket.AgentBlockBlock[agentIDs.Length];
2465 for (int i = 0; i < agentIDs.Length; i++)
2466 {
2467 OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock();
2468 onpbl.AgentID = agentIDs[i];
2469 offpb[i] = onpbl;
2470 }
2471 offp.AgentBlock = offpb;
2472 offp.Header.Reliable = true;
2473 OutPacket(offp, ThrottleOutPacketType.Task);
2474 }
2475
2476 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot,
2477 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
2478 {
2479 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket();
2480 avatarSitResponse.SitObject.ID = TargetID;
2481 if (CameraAtOffset != Vector3.Zero)
2482 {
2483 avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
2484 avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
2485 }
2486 avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook;
2487 avatarSitResponse.SitTransform.AutoPilot = autopilot;
2488 avatarSitResponse.SitTransform.SitPosition = OffsetPos;
2489 avatarSitResponse.SitTransform.SitRotation = SitOrientation;
2490
2491 OutPacket(avatarSitResponse, ThrottleOutPacketType.Task);
2492 }
2493
2494 public void SendAdminResponse(UUID Token, uint AdminLevel)
2495 {
2496 GrantGodlikePowersPacket respondPacket = new GrantGodlikePowersPacket();
2497 GrantGodlikePowersPacket.GrantDataBlock gdb = new GrantGodlikePowersPacket.GrantDataBlock();
2498 GrantGodlikePowersPacket.AgentDataBlock adb = new GrantGodlikePowersPacket.AgentDataBlock();
2499
2500 adb.AgentID = AgentId;
2501 adb.SessionID = SessionId; // More security
2502 gdb.GodLevel = (byte)AdminLevel;
2503 gdb.Token = Token;
2504 //respondPacket.AgentData = (GrantGodlikePowersPacket.AgentDataBlock)ablock;
2505 respondPacket.GrantData = gdb;
2506 respondPacket.AgentData = adb;
2507 OutPacket(respondPacket, ThrottleOutPacketType.Task);
2508 }
2509
2510 public void SendGroupMembership(GroupMembershipData[] GroupMembership)
2511 {
2512 m_groupPowers.Clear();
2513
2514 AgentGroupDataUpdatePacket Groupupdate = new AgentGroupDataUpdatePacket();
2515 AgentGroupDataUpdatePacket.GroupDataBlock[] Groups = new AgentGroupDataUpdatePacket.GroupDataBlock[GroupMembership.Length];
2516 for (int i = 0; i < GroupMembership.Length; i++)
2517 {
2518 m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers;
2519
2520 AgentGroupDataUpdatePacket.GroupDataBlock Group = new AgentGroupDataUpdatePacket.GroupDataBlock();
2521 Group.AcceptNotices = GroupMembership[i].AcceptNotices;
2522 Group.Contribution = GroupMembership[i].Contribution;
2523 Group.GroupID = GroupMembership[i].GroupID;
2524 Group.GroupInsigniaID = GroupMembership[i].GroupPicture;
2525 Group.GroupName = Util.StringToBytes256(GroupMembership[i].GroupName);
2526 Group.GroupPowers = GroupMembership[i].GroupPowers;
2527 Groups[i] = Group;
2528
2529
2530 }
2531 Groupupdate.GroupData = Groups;
2532 Groupupdate.AgentData = new AgentGroupDataUpdatePacket.AgentDataBlock();
2533 Groupupdate.AgentData.AgentID = AgentId;
2534 OutPacket(Groupupdate, ThrottleOutPacketType.Task);
2535
2536 try
2537 {
2538 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
2539 if (eq != null)
2540 {
2541 eq.GroupMembership(Groupupdate, this.AgentId);
2542 }
2543 }
2544 catch (Exception ex)
2545 {
2546 m_log.Error("Unable to send group membership data via eventqueue - exception: " + ex.ToString());
2547 m_log.Warn("sending group membership data via UDP");
2548 OutPacket(Groupupdate, ThrottleOutPacketType.Task);
2549 }
2550 }
2551
2552
2553 public void SendGroupNameReply(UUID groupLLUID, string GroupName)
2554 {
2555 UUIDGroupNameReplyPacket pack = new UUIDGroupNameReplyPacket();
2556 UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1];
2557 UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock();
2558 uidnamebloc.ID = groupLLUID;
2559 uidnamebloc.GroupName = Util.StringToBytes256(GroupName);
2560 uidnameblock[0] = uidnamebloc;
2561 pack.UUIDNameBlock = uidnameblock;
2562 OutPacket(pack, ThrottleOutPacketType.Task);
2563 }
2564
2565 public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia)
2566 {
2567 LandStatReplyPacket lsrp = new LandStatReplyPacket();
2568 // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock();
2569 LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length];
2570 //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock();
2571 // lsrepdb.
2572 lsrp.RequestData.ReportType = reportType;
2573 lsrp.RequestData.RequestFlags = requestFlags;
2574 lsrp.RequestData.TotalObjectCount = resultCount;
2575 for (int i = 0; i < lsrpia.Length; i++)
2576 {
2577 LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock();
2578 lsrepdb.LocationX = lsrpia[i].LocationX;
2579 lsrepdb.LocationY = lsrpia[i].LocationY;
2580 lsrepdb.LocationZ = lsrpia[i].LocationZ;
2581 lsrepdb.Score = lsrpia[i].Score;
2582 lsrepdb.TaskID = lsrpia[i].TaskID;
2583 lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID;
2584 lsrepdb.TaskName = Util.StringToBytes256(lsrpia[i].TaskName);
2585 lsrepdb.OwnerName = Util.StringToBytes256(lsrpia[i].OwnerName);
2586 lsrepdba[i] = lsrepdb;
2587 }
2588 lsrp.ReportData = lsrepdba;
2589 OutPacket(lsrp, ThrottleOutPacketType.Task);
2590 }
2591
2592 public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running)
2593 {
2594 ScriptRunningReplyPacket scriptRunningReply = new ScriptRunningReplyPacket();
2595 scriptRunningReply.Script.ObjectID = objectID;
2596 scriptRunningReply.Script.ItemID = itemID;
2597 scriptRunningReply.Script.Running = running;
2598
2599 OutPacket(scriptRunningReply, ThrottleOutPacketType.Task);
2600 }
2601
2602 public void SendAsset(AssetRequestToClient req)
2603 {
2604 if (req.AssetInf.Data == null)
2605 {
2606 m_log.ErrorFormat("Cannot send asset {0} ({1}), asset data is null",
2607 req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
2608 return;
2609 }
2610
2611 //m_log.Debug("sending asset " + req.RequestAssetID);
2612 TransferInfoPacket Transfer = new TransferInfoPacket();
2613 Transfer.TransferInfo.ChannelType = 2;
2614 Transfer.TransferInfo.Status = 0;
2615 Transfer.TransferInfo.TargetType = 0;
2616 if (req.AssetRequestSource == 2)
2617 {
2618 Transfer.TransferInfo.Params = new byte[20];
2619 Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
2620 int assType = req.AssetInf.Type;
2621 Array.Copy(Utils.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4);
2622 }
2623 else if (req.AssetRequestSource == 3)
2624 {
2625 Transfer.TransferInfo.Params = req.Params;
2626 // Transfer.TransferInfo.Params = new byte[100];
2627 //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
2628 //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16);
2629 }
2630 Transfer.TransferInfo.Size = req.AssetInf.Data.Length;
2631 Transfer.TransferInfo.TransferID = req.TransferRequestID;
2632 Transfer.Header.Zerocoded = true;
2633 OutPacket(Transfer, ThrottleOutPacketType.Asset);
2634
2635 if (req.NumPackets == 1)
2636 {
2637 TransferPacketPacket TransferPacket = new TransferPacketPacket();
2638 TransferPacket.TransferData.Packet = 0;
2639 TransferPacket.TransferData.ChannelType = 2;
2640 TransferPacket.TransferData.TransferID = req.TransferRequestID;
2641 TransferPacket.TransferData.Data = req.AssetInf.Data;
2642 TransferPacket.TransferData.Status = 1;
2643 TransferPacket.Header.Zerocoded = true;
2644 OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
2645 }
2646 else
2647 {
2648 int processedLength = 0;
2649 int maxChunkSize = Settings.MAX_PACKET_SIZE - 100;
2650 int packetNumber = 0;
2651
2652 while (processedLength < req.AssetInf.Data.Length)
2653 {
2654 TransferPacketPacket TransferPacket = new TransferPacketPacket();
2655 TransferPacket.TransferData.Packet = packetNumber;
2656 TransferPacket.TransferData.ChannelType = 2;
2657 TransferPacket.TransferData.TransferID = req.TransferRequestID;
2658
2659 int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize);
2660 byte[] chunk = new byte[chunkSize];
2661 Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length);
2662
2663 TransferPacket.TransferData.Data = chunk;
2664
2665 // 0 indicates more packets to come, 1 indicates last packet
2666 if (req.AssetInf.Data.Length - processedLength > maxChunkSize)
2667 {
2668 TransferPacket.TransferData.Status = 0;
2669 }
2670 else
2671 {
2672 TransferPacket.TransferData.Status = 1;
2673 }
2674 TransferPacket.Header.Zerocoded = true;
2675 OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
2676
2677 processedLength += chunkSize;
2678 packetNumber++;
2679 }
2680 }
2681 }
2682
2683 public void SendTexture(AssetBase TextureAsset)
2684 {
2685
2686 }
2687
2688 public void SendRegionHandle(UUID regionID, ulong handle)
2689 {
2690 RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)PacketPool.Instance.GetPacket(PacketType.RegionIDAndHandleReply);
2691 reply.ReplyBlock.RegionID = regionID;
2692 reply.ReplyBlock.RegionHandle = handle;
2693 OutPacket(reply, ThrottleOutPacketType.Land);
2694 }
2695
2696 public void SendParcelInfo(RegionInfo info, LandData land, UUID parcelID, uint x, uint y)
2697 {
2698 float dwell = 0.0f;
2699 IDwellModule dwellModule = m_scene.RequestModuleInterface<IDwellModule>();
2700 if (dwellModule != null)
2701 dwell = dwellModule.GetDwell(land.GlobalID);
2702 ParcelInfoReplyPacket reply = (ParcelInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelInfoReply);
2703 reply.AgentData.AgentID = m_agentId;
2704 reply.Data.ParcelID = parcelID;
2705 reply.Data.OwnerID = land.OwnerID;
2706 reply.Data.Name = Utils.StringToBytes(land.Name);
2707 reply.Data.Desc = Utils.StringToBytes(land.Description);
2708 reply.Data.ActualArea = land.Area;
2709 reply.Data.BillableArea = land.Area; // TODO: what is this?
2710
2711 // Bit 0: Mature, bit 7: on sale, other bits: no idea
2712 reply.Data.Flags = (byte)(
2713 (info.AccessLevel > 13 ? (1 << 0) : 0) +
2714 ((land.Flags & (uint)ParcelFlags.ForSale) != 0 ? (1 << 7) : 0));
2715
2716 Vector3 pos = land.UserLocation;
2717 if (pos.Equals(Vector3.Zero))
2718 {
2719 pos = (land.AABBMax + land.AABBMin) * 0.5f;
2720 }
2721 reply.Data.GlobalX = info.RegionLocX + x;
2722 reply.Data.GlobalY = info.RegionLocY + y;
2723 reply.Data.GlobalZ = pos.Z;
2724 reply.Data.SimName = Utils.StringToBytes(info.RegionName);
2725 reply.Data.SnapshotID = land.SnapshotID;
2726 reply.Data.Dwell = dwell;
2727 reply.Data.SalePrice = land.SalePrice;
2728 reply.Data.AuctionID = (int)land.AuctionID;
2729
2730 OutPacket(reply, ThrottleOutPacketType.Land);
2731 }
2732
2733 public void SendScriptTeleportRequest(string objName, string simName, Vector3 pos, Vector3 lookAt)
2734 {
2735 ScriptTeleportRequestPacket packet = (ScriptTeleportRequestPacket)PacketPool.Instance.GetPacket(PacketType.ScriptTeleportRequest);
2736
2737 packet.Data.ObjectName = Utils.StringToBytes(objName);
2738 packet.Data.SimName = Utils.StringToBytes(simName);
2739 packet.Data.SimPosition = pos;
2740 packet.Data.LookAt = lookAt;
2741
2742 OutPacket(packet, ThrottleOutPacketType.Task);
2743 }
2744
2745 public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data)
2746 {
2747 DirPlacesReplyPacket packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply);
2748
2749 packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock();
2750
2751 packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1];
2752 packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock();
2753
2754 packet.AgentData.AgentID = AgentId;
2755
2756 packet.QueryData[0].QueryID = queryID;
2757
2758 DirPlacesReplyPacket.QueryRepliesBlock[] replies =
2759 new DirPlacesReplyPacket.QueryRepliesBlock[0];
2760 DirPlacesReplyPacket.StatusDataBlock[] status =
2761 new DirPlacesReplyPacket.StatusDataBlock[0];
2762
2763 packet.QueryReplies = replies;
2764 packet.StatusData = status;
2765
2766 foreach (DirPlacesReplyData d in data)
2767 {
2768 int idx = replies.Length;
2769 Array.Resize(ref replies, idx + 1);
2770 Array.Resize(ref status, idx + 1);
2771
2772 replies[idx] = new DirPlacesReplyPacket.QueryRepliesBlock();
2773 status[idx] = new DirPlacesReplyPacket.StatusDataBlock();
2774 replies[idx].ParcelID = d.parcelID;
2775 replies[idx].Name = Utils.StringToBytes(d.name);
2776 replies[idx].ForSale = d.forSale;
2777 replies[idx].Auction = d.auction;
2778 replies[idx].Dwell = d.dwell;
2779 status[idx].Status = d.Status;
2780
2781 packet.QueryReplies = replies;
2782 packet.StatusData = status;
2783
2784 if (packet.Length >= 1000)
2785 {
2786 OutPacket(packet, ThrottleOutPacketType.Task);
2787
2788 packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply);
2789
2790 packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock();
2791
2792 packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1];
2793 packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock();
2794
2795 packet.AgentData.AgentID = AgentId;
2796
2797 packet.QueryData[0].QueryID = queryID;
2798
2799 replies = new DirPlacesReplyPacket.QueryRepliesBlock[0];
2800 status = new DirPlacesReplyPacket.StatusDataBlock[0];
2801 }
2802 }
2803
2804 if (replies.Length > 0 || data.Length == 0)
2805 OutPacket(packet, ThrottleOutPacketType.Task);
2806 }
2807
2808 public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data)
2809 {
2810 DirPeopleReplyPacket packet = (DirPeopleReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPeopleReply);
2811
2812 packet.AgentData = new DirPeopleReplyPacket.AgentDataBlock();
2813 packet.AgentData.AgentID = AgentId;
2814
2815 packet.QueryData = new DirPeopleReplyPacket.QueryDataBlock();
2816 packet.QueryData.QueryID = queryID;
2817
2818 packet.QueryReplies = new DirPeopleReplyPacket.QueryRepliesBlock[
2819 data.Length];
2820
2821 int i = 0;
2822 foreach (DirPeopleReplyData d in data)
2823 {
2824 packet.QueryReplies[i] = new DirPeopleReplyPacket.QueryRepliesBlock();
2825 packet.QueryReplies[i].AgentID = d.agentID;
2826 packet.QueryReplies[i].FirstName =
2827 Utils.StringToBytes(d.firstName);
2828 packet.QueryReplies[i].LastName =
2829 Utils.StringToBytes(d.lastName);
2830 packet.QueryReplies[i].Group =
2831 Utils.StringToBytes(d.group);
2832 packet.QueryReplies[i].Online = d.online;
2833 packet.QueryReplies[i].Reputation = d.reputation;
2834 i++;
2835 }
2836
2837 OutPacket(packet, ThrottleOutPacketType.Task);
2838 }
2839
2840 public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data)
2841 {
2842 DirEventsReplyPacket packet = (DirEventsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirEventsReply);
2843
2844 packet.AgentData = new DirEventsReplyPacket.AgentDataBlock();
2845 packet.AgentData.AgentID = AgentId;
2846
2847 packet.QueryData = new DirEventsReplyPacket.QueryDataBlock();
2848 packet.QueryData.QueryID = queryID;
2849
2850 packet.QueryReplies = new DirEventsReplyPacket.QueryRepliesBlock[
2851 data.Length];
2852
2853 packet.StatusData = new DirEventsReplyPacket.StatusDataBlock[
2854 data.Length];
2855
2856 int i = 0;
2857 foreach (DirEventsReplyData d in data)
2858 {
2859 packet.QueryReplies[i] = new DirEventsReplyPacket.QueryRepliesBlock();
2860 packet.StatusData[i] = new DirEventsReplyPacket.StatusDataBlock();
2861 packet.QueryReplies[i].OwnerID = d.ownerID;
2862 packet.QueryReplies[i].Name =
2863 Utils.StringToBytes(d.name);
2864 packet.QueryReplies[i].EventID = d.eventID;
2865 packet.QueryReplies[i].Date =
2866 Utils.StringToBytes(d.date);
2867 packet.QueryReplies[i].UnixTime = d.unixTime;
2868 packet.QueryReplies[i].EventFlags = d.eventFlags;
2869 packet.StatusData[i].Status = d.Status;
2870 i++;
2871 }
2872
2873 OutPacket(packet, ThrottleOutPacketType.Task);
2874 }
2875
2876 public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data)
2877 {
2878 DirGroupsReplyPacket packet = (DirGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirGroupsReply);
2879
2880 packet.AgentData = new DirGroupsReplyPacket.AgentDataBlock();
2881 packet.AgentData.AgentID = AgentId;
2882
2883 packet.QueryData = new DirGroupsReplyPacket.QueryDataBlock();
2884 packet.QueryData.QueryID = queryID;
2885
2886 packet.QueryReplies = new DirGroupsReplyPacket.QueryRepliesBlock[
2887 data.Length];
2888
2889 int i = 0;
2890 foreach (DirGroupsReplyData d in data)
2891 {
2892 packet.QueryReplies[i] = new DirGroupsReplyPacket.QueryRepliesBlock();
2893 packet.QueryReplies[i].GroupID = d.groupID;
2894 packet.QueryReplies[i].GroupName =
2895 Utils.StringToBytes(d.groupName);
2896 packet.QueryReplies[i].Members = d.members;
2897 packet.QueryReplies[i].SearchOrder = d.searchOrder;
2898 i++;
2899 }
2900
2901 OutPacket(packet, ThrottleOutPacketType.Task);
2902 }
2903
2904 public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data)
2905 {
2906 DirClassifiedReplyPacket packet = (DirClassifiedReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirClassifiedReply);
2907
2908 packet.AgentData = new DirClassifiedReplyPacket.AgentDataBlock();
2909 packet.AgentData.AgentID = AgentId;
2910
2911 packet.QueryData = new DirClassifiedReplyPacket.QueryDataBlock();
2912 packet.QueryData.QueryID = queryID;
2913
2914 packet.QueryReplies = new DirClassifiedReplyPacket.QueryRepliesBlock[
2915 data.Length];
2916 packet.StatusData = new DirClassifiedReplyPacket.StatusDataBlock[
2917 data.Length];
2918
2919 int i = 0;
2920 foreach (DirClassifiedReplyData d in data)
2921 {
2922 packet.QueryReplies[i] = new DirClassifiedReplyPacket.QueryRepliesBlock();
2923 packet.StatusData[i] = new DirClassifiedReplyPacket.StatusDataBlock();
2924 packet.QueryReplies[i].ClassifiedID = d.classifiedID;
2925 packet.QueryReplies[i].Name =
2926 Utils.StringToBytes(d.name);
2927 packet.QueryReplies[i].ClassifiedFlags = d.classifiedFlags;
2928 packet.QueryReplies[i].CreationDate = d.creationDate;
2929 packet.QueryReplies[i].ExpirationDate = d.expirationDate;
2930 packet.QueryReplies[i].PriceForListing = d.price;
2931 packet.StatusData[i].Status = d.Status;
2932 i++;
2933 }
2934
2935 OutPacket(packet, ThrottleOutPacketType.Task);
2936 }
2937
2938 public void SendDirLandReply(UUID queryID, DirLandReplyData[] data)
2939 {
2940 DirLandReplyPacket packet = (DirLandReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirLandReply);
2941
2942 packet.AgentData = new DirLandReplyPacket.AgentDataBlock();
2943 packet.AgentData.AgentID = AgentId;
2944
2945 packet.QueryData = new DirLandReplyPacket.QueryDataBlock();
2946 packet.QueryData.QueryID = queryID;
2947
2948 packet.QueryReplies = new DirLandReplyPacket.QueryRepliesBlock[
2949 data.Length];
2950
2951 int i = 0;
2952 foreach (DirLandReplyData d in data)
2953 {
2954 packet.QueryReplies[i] = new DirLandReplyPacket.QueryRepliesBlock();
2955 packet.QueryReplies[i].ParcelID = d.parcelID;
2956 packet.QueryReplies[i].Name =
2957 Utils.StringToBytes(d.name);
2958 packet.QueryReplies[i].Auction = d.auction;
2959 packet.QueryReplies[i].ForSale = d.forSale;
2960 packet.QueryReplies[i].SalePrice = d.salePrice;
2961 packet.QueryReplies[i].ActualArea = d.actualArea;
2962 i++;
2963 }
2964
2965 OutPacket(packet, ThrottleOutPacketType.Task);
2966 }
2967
2968 public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data)
2969 {
2970 DirPopularReplyPacket packet = (DirPopularReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPopularReply);
2971
2972 packet.AgentData = new DirPopularReplyPacket.AgentDataBlock();
2973 packet.AgentData.AgentID = AgentId;
2974
2975 packet.QueryData = new DirPopularReplyPacket.QueryDataBlock();
2976 packet.QueryData.QueryID = queryID;
2977
2978 packet.QueryReplies = new DirPopularReplyPacket.QueryRepliesBlock[
2979 data.Length];
2980
2981 int i = 0;
2982 foreach (DirPopularReplyData d in data)
2983 {
2984 packet.QueryReplies[i] = new DirPopularReplyPacket.QueryRepliesBlock();
2985 packet.QueryReplies[i].ParcelID = d.parcelID;
2986 packet.QueryReplies[i].Name =
2987 Utils.StringToBytes(d.name);
2988 packet.QueryReplies[i].Dwell = d.dwell;
2989 i++;
2990 }
2991
2992 OutPacket(packet, ThrottleOutPacketType.Task);
2993 }
2994
2995 public void SendEventInfoReply(EventData data)
2996 {
2997 EventInfoReplyPacket packet = (EventInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.EventInfoReply);
2998
2999 packet.AgentData = new EventInfoReplyPacket.AgentDataBlock();
3000 packet.AgentData.AgentID = AgentId;
3001
3002 packet.EventData = new EventInfoReplyPacket.EventDataBlock();
3003 packet.EventData.EventID = data.eventID;
3004 packet.EventData.Creator = Utils.StringToBytes(data.creator);
3005 packet.EventData.Name = Utils.StringToBytes(data.name);
3006 packet.EventData.Category = Utils.StringToBytes(data.category);
3007 packet.EventData.Desc = Utils.StringToBytes(data.description);
3008 packet.EventData.Date = Utils.StringToBytes(data.date);
3009 packet.EventData.DateUTC = data.dateUTC;
3010 packet.EventData.Duration = data.duration;
3011 packet.EventData.Cover = data.cover;
3012 packet.EventData.Amount = data.amount;
3013 packet.EventData.SimName = Utils.StringToBytes(data.simName);
3014 packet.EventData.GlobalPos = new Vector3d(data.globalPos);
3015 packet.EventData.EventFlags = data.eventFlags;
3016
3017 OutPacket(packet, ThrottleOutPacketType.Task);
3018 }
3019
3020 public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags)
3021 {
3022 MapItemReplyPacket mirplk = new MapItemReplyPacket();
3023 mirplk.AgentData.AgentID = AgentId;
3024 mirplk.RequestData.ItemType = mapitemtype;
3025 mirplk.Data = new MapItemReplyPacket.DataBlock[replies.Length];
3026 for (int i = 0; i < replies.Length; i++)
3027 {
3028 MapItemReplyPacket.DataBlock mrdata = new MapItemReplyPacket.DataBlock();
3029 mrdata.X = replies[i].x;
3030 mrdata.Y = replies[i].y;
3031 mrdata.ID = replies[i].id;
3032 mrdata.Extra = replies[i].Extra;
3033 mrdata.Extra2 = replies[i].Extra2;
3034 mrdata.Name = Utils.StringToBytes(replies[i].name);
3035 mirplk.Data[i] = mrdata;
3036 }
3037 //m_log.Debug(mirplk.ToString());
3038 OutPacket(mirplk, ThrottleOutPacketType.Task);
3039
3040 }
3041
3042 public void SendOfferCallingCard(UUID srcID, UUID transactionID)
3043 {
3044 // a bit special, as this uses AgentID to store the source instead
3045 // of the destination. The destination (the receiver) goes into destID
3046 OfferCallingCardPacket p = (OfferCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.OfferCallingCard);
3047 p.AgentData.AgentID = srcID;
3048 p.AgentData.SessionID = UUID.Zero;
3049 p.AgentBlock.DestID = AgentId;
3050 p.AgentBlock.TransactionID = transactionID;
3051 OutPacket(p, ThrottleOutPacketType.Task);
3052 }
3053
3054 public void SendAcceptCallingCard(UUID transactionID)
3055 {
3056 AcceptCallingCardPacket p = (AcceptCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.AcceptCallingCard);
3057 p.AgentData.AgentID = AgentId;
3058 p.AgentData.SessionID = UUID.Zero;
3059 p.FolderData = new AcceptCallingCardPacket.FolderDataBlock[1];
3060 p.FolderData[0] = new AcceptCallingCardPacket.FolderDataBlock();
3061 p.FolderData[0].FolderID = UUID.Zero;
3062 OutPacket(p, ThrottleOutPacketType.Task);
3063 }
3064
3065 public void SendDeclineCallingCard(UUID transactionID)
3066 {
3067 DeclineCallingCardPacket p = (DeclineCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.DeclineCallingCard);
3068 p.AgentData.AgentID = AgentId;
3069 p.AgentData.SessionID = UUID.Zero;
3070 p.TransactionBlock.TransactionID = transactionID;
3071 OutPacket(p, ThrottleOutPacketType.Task);
3072 }
3073
3074 public void SendTerminateFriend(UUID exFriendID)
3075 {
3076 TerminateFriendshipPacket p = (TerminateFriendshipPacket)PacketPool.Instance.GetPacket(PacketType.TerminateFriendship);
3077 p.AgentData.AgentID = AgentId;
3078 p.AgentData.SessionID = SessionId;
3079 p.ExBlock.OtherID = exFriendID;
3080 OutPacket(p, ThrottleOutPacketType.Task);
3081 }
3082
3083 public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data)
3084 {
3085 OSDMap llsd = new OSDMap(3);
3086 OSDArray AgentData = new OSDArray(1);
3087 OSDMap AgentDataMap = new OSDMap(1);
3088 AgentDataMap.Add("AgentID", OSD.FromUUID(this.AgentId));
3089 AgentDataMap.Add("AvatarID", OSD.FromUUID(avatarID));
3090 AgentData.Add(AgentDataMap);
3091 llsd.Add("AgentData", AgentData);
3092 OSDArray GroupData = new OSDArray(data.Length);
3093 OSDArray NewGroupData = new OSDArray(data.Length);
3094 foreach (GroupMembershipData m in data)
3095 {
3096 OSDMap GroupDataMap = new OSDMap(6);
3097 OSDMap NewGroupDataMap = new OSDMap(1);
3098 GroupDataMap.Add("GroupPowers", OSD.FromULong(m.GroupPowers));
3099 GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(m.AcceptNotices));
3100 GroupDataMap.Add("GroupTitle", OSD.FromString(m.GroupTitle));
3101 GroupDataMap.Add("GroupID", OSD.FromUUID(m.GroupID));
3102 GroupDataMap.Add("GroupName", OSD.FromString(m.GroupName));
3103 GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(m.GroupPicture));
3104 NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(m.ListInProfile));
3105 GroupData.Add(GroupDataMap);
3106 NewGroupData.Add(NewGroupDataMap);
3107 }
3108 llsd.Add("GroupData", GroupData);
3109 llsd.Add("NewGroupData", NewGroupData);
3110
3111 IEventQueue eq = this.Scene.RequestModuleInterface<IEventQueue>();
3112 if (eq != null)
3113 {
3114 eq.Enqueue(BuildEvent("AvatarGroupsReply", llsd), this.AgentId);
3115 }
3116 }
3117
3118 public void SendJoinGroupReply(UUID groupID, bool success)
3119 {
3120 JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply);
3121
3122 p.AgentData = new JoinGroupReplyPacket.AgentDataBlock();
3123 p.AgentData.AgentID = AgentId;
3124
3125 p.GroupData = new JoinGroupReplyPacket.GroupDataBlock();
3126 p.GroupData.GroupID = groupID;
3127 p.GroupData.Success = success;
3128
3129 OutPacket(p, ThrottleOutPacketType.Task);
3130 }
3131
3132 public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success)
3133 {
3134 EjectGroupMemberReplyPacket p = (EjectGroupMemberReplyPacket)PacketPool.Instance.GetPacket(PacketType.EjectGroupMemberReply);
3135
3136 p.AgentData = new EjectGroupMemberReplyPacket.AgentDataBlock();
3137 p.AgentData.AgentID = agentID;
3138
3139 p.GroupData = new EjectGroupMemberReplyPacket.GroupDataBlock();
3140 p.GroupData.GroupID = groupID;
3141
3142 p.EjectData = new EjectGroupMemberReplyPacket.EjectDataBlock();
3143 p.EjectData.Success = success;
3144
3145 OutPacket(p, ThrottleOutPacketType.Task);
3146 }
3147
3148 public void SendLeaveGroupReply(UUID groupID, bool success)
3149 {
3150 LeaveGroupReplyPacket p = (LeaveGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.LeaveGroupReply);
3151
3152 p.AgentData = new LeaveGroupReplyPacket.AgentDataBlock();
3153 p.AgentData.AgentID = AgentId;
3154
3155 p.GroupData = new LeaveGroupReplyPacket.GroupDataBlock();
3156 p.GroupData.GroupID = groupID;
3157 p.GroupData.Success = success;
3158
3159 OutPacket(p, ThrottleOutPacketType.Task);
3160 }
3161
3162 public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name)
3163 {
3164 if (classifiedID.Length != name.Length)
3165 return;
3166
3167 AvatarClassifiedReplyPacket ac =
3168 (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket(
3169 PacketType.AvatarClassifiedReply);
3170
3171 ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock();
3172 ac.AgentData.AgentID = AgentId;
3173 ac.AgentData.TargetID = targetID;
3174
3175 ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifiedID.Length];
3176 int i;
3177 for (i = 0; i < classifiedID.Length; i++)
3178 {
3179 ac.Data[i].ClassifiedID = classifiedID[i];
3180 ac.Data[i].Name = Utils.StringToBytes(name[i]);
3181 }
3182
3183 OutPacket(ac, ThrottleOutPacketType.Task);
3184 }
3185
3186 public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price)
3187 {
3188 ClassifiedInfoReplyPacket cr =
3189 (ClassifiedInfoReplyPacket)PacketPool.Instance.GetPacket(
3190 PacketType.ClassifiedInfoReply);
3191
3192 cr.AgentData = new ClassifiedInfoReplyPacket.AgentDataBlock();
3193 cr.AgentData.AgentID = AgentId;
3194
3195 cr.Data = new ClassifiedInfoReplyPacket.DataBlock();
3196 cr.Data.ClassifiedID = classifiedID;
3197 cr.Data.CreatorID = creatorID;
3198 cr.Data.CreationDate = creationDate;
3199 cr.Data.ExpirationDate = expirationDate;
3200 cr.Data.Category = category;
3201 cr.Data.Name = Utils.StringToBytes(name);
3202 cr.Data.Desc = Utils.StringToBytes(description);
3203 cr.Data.ParcelID = parcelID;
3204 cr.Data.ParentEstate = parentEstate;
3205 cr.Data.SnapshotID = snapshotID;
3206 cr.Data.SimName = Utils.StringToBytes(simName);
3207 cr.Data.PosGlobal = new Vector3d(globalPos);
3208 cr.Data.ParcelName = Utils.StringToBytes(parcelName);
3209 cr.Data.ClassifiedFlags = classifiedFlags;
3210 cr.Data.PriceForListing = price;
3211
3212 OutPacket(cr, ThrottleOutPacketType.Task);
3213 }
3214
3215 public void SendAgentDropGroup(UUID groupID)
3216 {
3217 AgentDropGroupPacket dg =
3218 (AgentDropGroupPacket)PacketPool.Instance.GetPacket(
3219 PacketType.AgentDropGroup);
3220
3221 dg.AgentData = new AgentDropGroupPacket.AgentDataBlock();
3222 dg.AgentData.AgentID = AgentId;
3223 dg.AgentData.GroupID = groupID;
3224
3225 OutPacket(dg, ThrottleOutPacketType.Task);
3226 }
3227
3228 public void SendAvatarNotesReply(UUID targetID, string text)
3229 {
3230 AvatarNotesReplyPacket an =
3231 (AvatarNotesReplyPacket)PacketPool.Instance.GetPacket(
3232 PacketType.AvatarNotesReply);
3233
3234 an.AgentData = new AvatarNotesReplyPacket.AgentDataBlock();
3235 an.AgentData.AgentID = AgentId;
3236
3237 an.Data = new AvatarNotesReplyPacket.DataBlock();
3238 an.Data.TargetID = targetID;
3239 an.Data.Notes = Utils.StringToBytes(text);
3240
3241 OutPacket(an, ThrottleOutPacketType.Task);
3242 }
3243
3244 public void SendAvatarPicksReply(UUID targetID, Dictionary<UUID, string> picks)
3245 {
3246 AvatarPicksReplyPacket ap =
3247 (AvatarPicksReplyPacket)PacketPool.Instance.GetPacket(
3248 PacketType.AvatarPicksReply);
3249
3250 ap.AgentData = new AvatarPicksReplyPacket.AgentDataBlock();
3251 ap.AgentData.AgentID = AgentId;
3252 ap.AgentData.TargetID = targetID;
3253
3254 ap.Data = new AvatarPicksReplyPacket.DataBlock[picks.Count];
3255
3256 int i = 0;
3257 foreach (KeyValuePair<UUID, string> pick in picks)
3258 {
3259 ap.Data[i] = new AvatarPicksReplyPacket.DataBlock();
3260 ap.Data[i].PickID = pick.Key;
3261 ap.Data[i].PickName = Utils.StringToBytes(pick.Value);
3262 i++;
3263 }
3264
3265 OutPacket(ap, ThrottleOutPacketType.Task);
3266 }
3267
3268 public void SendAvatarClassifiedReply(UUID targetID, Dictionary<UUID, string> classifieds)
3269 {
3270 AvatarClassifiedReplyPacket ac =
3271 (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket(
3272 PacketType.AvatarClassifiedReply);
3273
3274 ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock();
3275 ac.AgentData.AgentID = AgentId;
3276 ac.AgentData.TargetID = targetID;
3277
3278 ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifieds.Count];
3279
3280 int i = 0;
3281 foreach (KeyValuePair<UUID, string> classified in classifieds)
3282 {
3283 ac.Data[i] = new AvatarClassifiedReplyPacket.DataBlock();
3284 ac.Data[i].ClassifiedID = classified.Key;
3285 ac.Data[i].Name = Utils.StringToBytes(classified.Value);
3286 i++;
3287 }
3288
3289 OutPacket(ac, ThrottleOutPacketType.Task);
3290 }
3291
3292 public void SendParcelDwellReply(int localID, UUID parcelID, float dwell)
3293 {
3294 ParcelDwellReplyPacket pd =
3295 (ParcelDwellReplyPacket)PacketPool.Instance.GetPacket(
3296 PacketType.ParcelDwellReply);
3297
3298 pd.AgentData = new ParcelDwellReplyPacket.AgentDataBlock();
3299 pd.AgentData.AgentID = AgentId;
3300
3301 pd.Data = new ParcelDwellReplyPacket.DataBlock();
3302 pd.Data.LocalID = localID;
3303 pd.Data.ParcelID = parcelID;
3304 pd.Data.Dwell = dwell;
3305
3306 OutPacket(pd, ThrottleOutPacketType.Land);
3307 }
3308
3309 public void SendUserInfoReply(bool imViaEmail, bool visible, string email)
3310 {
3311 UserInfoReplyPacket ur =
3312 (UserInfoReplyPacket)PacketPool.Instance.GetPacket(
3313 PacketType.UserInfoReply);
3314
3315 string Visible = "hidden";
3316 if (visible)
3317 Visible = "default";
3318
3319 ur.AgentData = new UserInfoReplyPacket.AgentDataBlock();
3320 ur.AgentData.AgentID = AgentId;
3321
3322 ur.UserData = new UserInfoReplyPacket.UserDataBlock();
3323 ur.UserData.IMViaEMail = imViaEmail;
3324 ur.UserData.DirectoryVisibility = Utils.StringToBytes(Visible);
3325 ur.UserData.EMail = Utils.StringToBytes(email);
3326
3327 OutPacket(ur, ThrottleOutPacketType.Task);
3328 }
3329
3330 public void SendCreateGroupReply(UUID groupID, bool success, string message)
3331 {
3332 CreateGroupReplyPacket createGroupReply = (CreateGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.CreateGroupReply);
3333
3334 createGroupReply.AgentData =
3335 new CreateGroupReplyPacket.AgentDataBlock();
3336 createGroupReply.ReplyData =
3337 new CreateGroupReplyPacket.ReplyDataBlock();
3338
3339 createGroupReply.AgentData.AgentID = AgentId;
3340 createGroupReply.ReplyData.GroupID = groupID;
3341
3342 createGroupReply.ReplyData.Success = success;
3343 createGroupReply.ReplyData.Message = Utils.StringToBytes(message);
3344 OutPacket(createGroupReply, ThrottleOutPacketType.Task);
3345 }
3346
3347 public void SendUseCachedMuteList()
3348 {
3349 UseCachedMuteListPacket useCachedMuteList = (UseCachedMuteListPacket)PacketPool.Instance.GetPacket(PacketType.UseCachedMuteList);
3350
3351 useCachedMuteList.AgentData = new UseCachedMuteListPacket.AgentDataBlock();
3352 useCachedMuteList.AgentData.AgentID = AgentId;
3353
3354 OutPacket(useCachedMuteList, ThrottleOutPacketType.Task);
3355 }
3356
3357 public void SendMuteListUpdate(string filename)
3358 {
3359 MuteListUpdatePacket muteListUpdate = (MuteListUpdatePacket)PacketPool.Instance.GetPacket(PacketType.MuteListUpdate);
3360
3361 muteListUpdate.MuteData = new MuteListUpdatePacket.MuteDataBlock();
3362 muteListUpdate.MuteData.AgentID = AgentId;
3363 muteListUpdate.MuteData.Filename = Utils.StringToBytes(filename);
3364
3365 OutPacket(muteListUpdate, ThrottleOutPacketType.Task);
3366 }
3367
3368 public void SendPickInfoReply(UUID pickID, UUID creatorID, bool topPick, UUID parcelID, string name, string desc, UUID snapshotID, string user, string originalName, string simName, Vector3 posGlobal, int sortOrder, bool enabled)
3369 {
3370 PickInfoReplyPacket pickInfoReply = (PickInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.PickInfoReply);
3371
3372 pickInfoReply.AgentData = new PickInfoReplyPacket.AgentDataBlock();
3373 pickInfoReply.AgentData.AgentID = AgentId;
3374
3375 pickInfoReply.Data = new PickInfoReplyPacket.DataBlock();
3376 pickInfoReply.Data.PickID = pickID;
3377 pickInfoReply.Data.CreatorID = creatorID;
3378 pickInfoReply.Data.TopPick = topPick;
3379 pickInfoReply.Data.ParcelID = parcelID;
3380 pickInfoReply.Data.Name = Utils.StringToBytes(name);
3381 pickInfoReply.Data.Desc = Utils.StringToBytes(desc);
3382 pickInfoReply.Data.SnapshotID = snapshotID;
3383 pickInfoReply.Data.User = Utils.StringToBytes(user);
3384 pickInfoReply.Data.OriginalName = Utils.StringToBytes(originalName);
3385 pickInfoReply.Data.SimName = Utils.StringToBytes(simName);
3386 pickInfoReply.Data.PosGlobal = new Vector3d(posGlobal);
3387 pickInfoReply.Data.SortOrder = sortOrder;
3388 pickInfoReply.Data.Enabled = enabled;
3389
3390 OutPacket(pickInfoReply, ThrottleOutPacketType.Task);
3391 }
3392
3393 #endregion Scene/Avatar to Client
3394
3395 // Gesture
3396
3397 #region Appearance/ Wearables Methods
3398
3399 public void SendWearables(AvatarWearable[] wearables, int serial)
3400 {
3401 AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate);
3402 aw.AgentData.AgentID = AgentId;
3403 aw.AgentData.SerialNum = (uint)serial;
3404 aw.AgentData.SessionID = m_sessionId;
3405
3406 int count = 0;
3407 for (int i = 0; i < wearables.Length; i++)
3408 count += wearables[i].Count;
3409
3410 // TODO: don't create new blocks if recycling an old packet
3411 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count];
3412 AgentWearablesUpdatePacket.WearableDataBlock awb;
3413 int idx = 0;
3414 for (int i = 0; i < wearables.Length; i++)
3415 {
3416 for (int j = 0; j < wearables[i].Count; j++)
3417 {
3418 awb = new AgentWearablesUpdatePacket.WearableDataBlock();
3419 awb.WearableType = (byte)i;
3420 awb.AssetID = wearables[i][j].AssetID;
3421 awb.ItemID = wearables[i][j].ItemID;
3422 aw.WearableData[idx] = awb;
3423 idx++;
3424
3425// m_log.DebugFormat(
3426// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}",
3427// awb.ItemID, awb.AssetID, i, Name);
3428 }
3429 }
3430
3431 OutPacket(aw, ThrottleOutPacketType.Task);
3432 }
3433
3434 public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry)
3435 {
3436 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance);
3437 // TODO: don't create new blocks if recycling an old packet
3438 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218];
3439 avp.ObjectData.TextureEntry = textureEntry;
3440
3441 AvatarAppearancePacket.VisualParamBlock avblock = null;
3442 for (int i = 0; i < visualParams.Length; i++)
3443 {
3444 avblock = new AvatarAppearancePacket.VisualParamBlock();
3445 avblock.ParamValue = visualParams[i];
3446 avp.VisualParam[i] = avblock;
3447 }
3448
3449 avp.Sender.IsTrial = false;
3450 avp.Sender.ID = agentID;
3451 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString());
3452 OutPacket(avp, ThrottleOutPacketType.Task);
3453 }
3454
3455 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
3456 {
3457 //m_log.DebugFormat("[CLIENT]: Sending animations to {0}", Name);
3458
3459 AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation);
3460 // TODO: don't create new blocks if recycling an old packet
3461 ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[animations.Length];
3462 ani.Sender = new AvatarAnimationPacket.SenderBlock();
3463 ani.Sender.ID = sourceAgentId;
3464 ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length];
3465 ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0];
3466
3467 for (int i = 0; i < animations.Length; ++i)
3468 {
3469 ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock();
3470 ani.AnimationList[i].AnimID = animations[i];
3471 ani.AnimationList[i].AnimSequenceID = seqs[i];
3472
3473 ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock();
3474 if (objectIDs[i].Equals(sourceAgentId))
3475 ani.AnimationSourceList[i].ObjectID = UUID.Zero;
3476 else
3477 ani.AnimationSourceList[i].ObjectID = objectIDs[i];
3478 }
3479 ani.Header.Reliable = false;
3480 OutPacket(ani, ThrottleOutPacketType.Task);
3481 }
3482
3483 #endregion
3484
3485 #region Avatar Packet/Data Sending Methods
3486
3487 /// <summary>
3488 /// Send an ObjectUpdate packet with information about an avatar
3489 /// </summary>
3490 public void SendAvatarDataImmediate(ISceneEntity avatar)
3491 {
3492 ScenePresence presence = avatar as ScenePresence;
3493 if (presence == null)
3494 return;
3495
3496 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3497 objupdate.Header.Zerocoded = true;
3498
3499 objupdate.RegionData.RegionHandle = presence.RegionHandle;
3500 objupdate.RegionData.TimeDilation = ushort.MaxValue;
3501
3502 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3503 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence);
3504
3505 OutPacket(objupdate, ThrottleOutPacketType.Task);
3506
3507 // We need to record the avatar local id since the root prim of an attachment points to this.
3508// m_attachmentsSent.Add(avatar.LocalId);
3509 }
3510
3511 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
3512 {
3513 if (!IsActive) return; // We don't need to update inactive clients.
3514
3515 CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate);
3516 loc.Header.Reliable = false;
3517
3518 // Each packet can only hold around 60 avatar positions and the client clears the mini-map each time
3519 // a CoarseLocationUpdate packet is received. Oh well.
3520 int total = Math.Min(CoarseLocations.Count, 60);
3521
3522 CoarseLocationUpdatePacket.IndexBlock ib = new CoarseLocationUpdatePacket.IndexBlock();
3523
3524 loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total];
3525 loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total];
3526
3527 int selfindex = -1;
3528 for (int i = 0; i < total; i++)
3529 {
3530 CoarseLocationUpdatePacket.LocationBlock lb =
3531 new CoarseLocationUpdatePacket.LocationBlock();
3532
3533 lb.X = (byte)CoarseLocations[i].X;
3534 lb.Y = (byte)CoarseLocations[i].Y;
3535
3536 lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25f);
3537 loc.Location[i] = lb;
3538 loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock();
3539 loc.AgentData[i].AgentID = users[i];
3540 if (users[i] == AgentId)
3541 selfindex = i;
3542 }
3543
3544 ib.You = (short)selfindex;
3545 ib.Prey = -1;
3546 loc.Index = ib;
3547
3548 OutPacket(loc, ThrottleOutPacketType.Task);
3549 }
3550
3551 #endregion Avatar Packet/Data Sending Methods
3552
3553 #region Primitive Packet/Data Sending Methods
3554
3555
3556 /// <summary>
3557 /// Generate one of the object update packets based on PrimUpdateFlags
3558 /// and broadcast the packet to clients
3559 /// </summary>
3560 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3561 {
3562 //double priority = m_prioritizer.GetUpdatePriority(this, entity);
3563 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3564
3565 lock (m_entityUpdates.SyncRoot)
3566 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
3567 }
3568
3569 /// <summary>
3570 /// Requeue an EntityUpdate when it was not acknowledged by the client.
3571 /// We will update the priority and put it in the correct queue, merging update flags
3572 /// with any other updates that may be queued for the same entity.
3573 /// The original update time is used for the merged update.
3574 /// </summary>
3575 private void ResendPrimUpdate(EntityUpdate update)
3576 {
3577 // If the update exists in priority queue, it will be updated.
3578 // If it does not exist then it will be added with the current (rather than its original) priority
3579 uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity);
3580
3581 lock (m_entityUpdates.SyncRoot)
3582 m_entityUpdates.Enqueue(priority, update);
3583 }
3584
3585 /// <summary>
3586 /// Requeue a list of EntityUpdates when they were not acknowledged by the client.
3587 /// We will update the priority and put it in the correct queue, merging update flags
3588 /// with any other updates that may be queued for the same entity.
3589 /// The original update time is used for the merged update.
3590 /// </summary>
3591 private void ResendPrimUpdates(List<EntityUpdate> updates, OutgoingPacket oPacket)
3592 {
3593 // m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime);
3594
3595 // Remove the update packet from the list of packets waiting for acknowledgement
3596 // because we are requeuing the list of updates. They will be resent in new packets
3597 // with the most recent state and priority.
3598 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
3599
3600 // Count this as a resent packet since we are going to requeue all of the updates contained in it
3601 Interlocked.Increment(ref m_udpClient.PacketsResent);
3602
3603 foreach (EntityUpdate update in updates)
3604 ResendPrimUpdate(update);
3605 }
3606
3607 private void ProcessEntityUpdates(int maxUpdates)
3608 {
3609 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
3610 OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
3611 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3612 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3613
3614 OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3615 OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3616 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3617 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3618
3619 // Check to see if this is a flush
3620 if (maxUpdates <= 0)
3621 {
3622 maxUpdates = Int32.MaxValue;
3623 }
3624
3625 int updatesThisCall = 0;
3626
3627 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3628 // condition where a kill can be processed before an out-of-date update for the same object.
3629 lock (m_killRecord)
3630 {
3631 float avgTimeDilation = 1.0f;
3632 IEntityUpdate iupdate;
3633 Int32 timeinqueue; // this is just debugging code & can be dropped later
3634
3635 while (updatesThisCall < maxUpdates)
3636 {
3637 lock (m_entityUpdates.SyncRoot)
3638 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3639 break;
3640
3641 EntityUpdate update = (EntityUpdate)iupdate;
3642
3643 avgTimeDilation += update.TimeDilation;
3644 avgTimeDilation *= 0.5f;
3645
3646 if (update.Entity is SceneObjectPart)
3647 {
3648 SceneObjectPart part = (SceneObjectPart)update.Entity;
3649
3650 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3651 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3652 // safety measure.
3653 //
3654 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3655 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3656 // updates and kills on different threads with different scheduling strategies, hence this protection.
3657 //
3658 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3659 // after the root prim has been deleted.
3660 if (m_killRecord.Contains(part.LocalId))
3661 {
3662 // m_log.WarnFormat(
3663 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted",
3664 // part.LocalId, Name);
3665 continue;
3666 }
3667
3668 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3669 {
3670 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3671 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3672 {
3673 part.Shape.LightEntry = false;
3674 }
3675 }
3676 }
3677
3678 ++updatesThisCall;
3679
3680 #region UpdateFlags to packet type conversion
3681
3682 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3683
3684 bool canUseCompressed = true;
3685 bool canUseImproved = true;
3686
3687 // Compressed object updates only make sense for LL primitives
3688 if (!(update.Entity is SceneObjectPart))
3689 {
3690 canUseCompressed = false;
3691 }
3692
3693 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3694 {
3695 canUseCompressed = false;
3696 canUseImproved = false;
3697 }
3698 else
3699 {
3700 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3701 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3702 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3703 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3704 {
3705 canUseCompressed = false;
3706 }
3707
3708 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3709 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3710 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3711 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3712 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3713 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3714 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3715 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3716 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3717 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3718 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3719 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3720 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3721 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3722 {
3723 canUseImproved = false;
3724 }
3725 }
3726
3727 #endregion UpdateFlags to packet type conversion
3728
3729 #region Block Construction
3730
3731 // TODO: Remove this once we can build compressed updates
3732 canUseCompressed = false;
3733
3734 if (!canUseImproved && !canUseCompressed)
3735 {
3736 if (update.Entity is ScenePresence)
3737 {
3738 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3739 objectUpdates.Value.Add(update);
3740 }
3741 else
3742 {
3743 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3744 objectUpdates.Value.Add(update);
3745 }
3746 }
3747 else if (!canUseImproved)
3748 {
3749 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3750 compressedUpdates.Value.Add(update);
3751 }
3752 else
3753 {
3754 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3755 {
3756 // Self updates go into a special list
3757 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3758 terseAgentUpdates.Value.Add(update);
3759 }
3760 else
3761 {
3762 // Everything else goes here
3763 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3764 terseUpdates.Value.Add(update);
3765 }
3766 }
3767
3768 #endregion Block Construction
3769 }
3770
3771
3772 #region Packet Sending
3773 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3774
3775 if (terseAgentUpdateBlocks.IsValueCreated)
3776 {
3777 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3778
3779 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3780 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3781 packet.RegionData.TimeDilation = timeDilation;
3782 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3783
3784 for (int i = 0; i < blocks.Count; i++)
3785 packet.ObjectData[i] = blocks[i];
3786 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3787 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); });
3788 }
3789
3790 if (objectUpdateBlocks.IsValueCreated)
3791 {
3792 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3793
3794 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3795 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3796 packet.RegionData.TimeDilation = timeDilation;
3797 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3798
3799 for (int i = 0; i < blocks.Count; i++)
3800 packet.ObjectData[i] = blocks[i];
3801 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3802 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
3803 }
3804
3805 if (compressedUpdateBlocks.IsValueCreated)
3806 {
3807 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3808
3809 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3810 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3811 packet.RegionData.TimeDilation = timeDilation;
3812 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3813
3814 for (int i = 0; i < blocks.Count; i++)
3815 packet.ObjectData[i] = blocks[i];
3816 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3817 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
3818 }
3819
3820 if (terseUpdateBlocks.IsValueCreated)
3821 {
3822 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3823
3824 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3825 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3826 packet.RegionData.TimeDilation = timeDilation;
3827 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3828
3829 for (int i = 0; i < blocks.Count; i++)
3830 packet.ObjectData[i] = blocks[i];
3831 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3832 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
3833 }
3834 }
3835
3836 #endregion Packet Sending
3837 }
3838
3839 public void ReprioritizeUpdates()
3840 {
3841 lock (m_entityUpdates.SyncRoot)
3842 m_entityUpdates.Reprioritize(UpdatePriorityHandler);
3843 }
3844
3845 private bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity)
3846 {
3847 if (entity != null)
3848 {
3849 priority = m_prioritizer.GetUpdatePriority(this, entity);
3850 return true;
3851 }
3852
3853 return false;
3854 }
3855
3856 public void FlushPrimUpdates()
3857 {
3858 m_log.WarnFormat("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName);
3859
3860 while (m_entityUpdates.Count > 0)
3861 ProcessEntityUpdates(-1);
3862 }
3863
3864 #endregion Primitive Packet/Data Sending Methods
3865
3866 // These are used to implement an adaptive backoff in the number
3867 // of updates converted to packets. Since we don't want packets
3868 // to sit in the queue with old data, only convert enough updates
3869 // to packets that can be sent in 200ms.
3870 private Int32 m_LastQueueFill = 0;
3871 private Int32 m_maxUpdates = 0;
3872
3873 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
3874 {
3875 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
3876 {
3877 if (m_maxUpdates == 0 || m_LastQueueFill == 0)
3878 {
3879 m_maxUpdates = m_udpServer.PrimUpdatesPerCallback;
3880 }
3881 else
3882 {
3883 if (Util.EnvironmentTickCountSubtract(m_LastQueueFill) < 200)
3884 m_maxUpdates += 5;
3885 else
3886 m_maxUpdates = m_maxUpdates >> 1;
3887 }
3888 m_maxUpdates = Util.Clamp<Int32>(m_maxUpdates,10,500);
3889 m_LastQueueFill = Util.EnvironmentTickCount();
3890
3891 if (m_entityUpdates.Count > 0)
3892 ProcessEntityUpdates(m_maxUpdates);
3893
3894 if (m_entityProps.Count > 0)
3895 ProcessEntityPropertyRequests(m_maxUpdates);
3896 }
3897
3898 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
3899 {
3900 ProcessTextureRequests();
3901 }
3902 }
3903
3904 void ProcessTextureRequests()
3905 {
3906 if (m_imageManager != null)
3907 m_imageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
3908 }
3909
3910 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
3911 {
3912 AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
3913 newPack.AssetBlock.Type = AssetType;
3914 newPack.AssetBlock.Success = Success;
3915 newPack.AssetBlock.UUID = AssetFullID;
3916 newPack.Header.Zerocoded = true;
3917 OutPacket(newPack, ThrottleOutPacketType.Asset);
3918 }
3919
3920 public void SendXferRequest(ulong XferID, short AssetType, UUID vFileID, byte FilePath, byte[] FileName)
3921 {
3922 RequestXferPacket newPack = new RequestXferPacket();
3923 newPack.XferID.ID = XferID;
3924 newPack.XferID.VFileType = AssetType;
3925 newPack.XferID.VFileID = vFileID;
3926 newPack.XferID.FilePath = FilePath;
3927 newPack.XferID.Filename = FileName;
3928 newPack.Header.Zerocoded = true;
3929 OutPacket(newPack, ThrottleOutPacketType.Asset);
3930 }
3931
3932 public void SendConfirmXfer(ulong xferID, uint PacketID)
3933 {
3934 ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket();
3935 newPack.XferID.ID = xferID;
3936 newPack.XferID.Packet = PacketID;
3937 newPack.Header.Zerocoded = true;
3938 OutPacket(newPack, ThrottleOutPacketType.Asset);
3939 }
3940
3941 public void SendInitiateDownload(string simFileName, string clientFileName)
3942 {
3943 InitiateDownloadPacket newPack = new InitiateDownloadPacket();
3944 newPack.AgentData.AgentID = AgentId;
3945 newPack.FileData.SimFilename = Utils.StringToBytes(simFileName);
3946 newPack.FileData.ViewerFilename = Utils.StringToBytes(clientFileName);
3947 OutPacket(newPack, ThrottleOutPacketType.Asset);
3948 }
3949
3950 public void SendImageFirstPart(
3951 ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec)
3952 {
3953 ImageDataPacket im = new ImageDataPacket();
3954 im.Header.Reliable = false;
3955 im.ImageID.Packets = numParts;
3956 im.ImageID.ID = ImageUUID;
3957
3958 if (ImageSize > 0)
3959 im.ImageID.Size = ImageSize;
3960
3961 im.ImageData.Data = ImageData;
3962 im.ImageID.Codec = imageCodec;
3963 im.Header.Zerocoded = true;
3964 OutPacket(im, ThrottleOutPacketType.Texture);
3965 }
3966
3967 public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData)
3968 {
3969 ImagePacketPacket im = new ImagePacketPacket();
3970 im.Header.Reliable = false;
3971 im.ImageID.Packet = partNumber;
3972 im.ImageID.ID = imageUuid;
3973 im.ImageData.Data = imageData;
3974
3975 OutPacket(im, ThrottleOutPacketType.Texture);
3976 }
3977
3978 public void SendImageNotFound(UUID imageid)
3979 {
3980 ImageNotInDatabasePacket notFoundPacket
3981 = (ImageNotInDatabasePacket)PacketPool.Instance.GetPacket(PacketType.ImageNotInDatabase);
3982
3983 notFoundPacket.ImageID.ID = imageid;
3984
3985 OutPacket(notFoundPacket, ThrottleOutPacketType.Texture);
3986 }
3987
3988 public void SendShutdownConnectionNotice()
3989 {
3990 OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown);
3991 }
3992
3993 public void SendSimStats(SimStats stats)
3994 {
3995 SimStatsPacket pack = new SimStatsPacket();
3996 pack.Region = new SimStatsPacket.RegionBlock();
3997 pack.Region.RegionX = stats.RegionX;
3998 pack.Region.RegionY = stats.RegionY;
3999 pack.Region.RegionFlags = stats.RegionFlags;
4000 pack.Region.ObjectCapacity = stats.ObjectCapacity;
4001 //pack.Region = //stats.RegionBlock;
4002 pack.Stat = stats.StatsBlock;
4003
4004 pack.Header.Reliable = false;
4005
4006 OutPacket(pack, ThrottleOutPacketType.Task);
4007 }
4008
4009 private class ObjectPropertyUpdate : IEntityUpdate
4010 {
4011 internal bool SendFamilyProps;
4012 internal bool SendObjectProps;
4013
4014 public ObjectPropertyUpdate(ISceneEntity entity, uint flags, bool sendfam, bool sendobj)
4015 : base(entity,flags)
4016 {
4017 SendFamilyProps = sendfam;
4018 SendObjectProps = sendobj;
4019 }
4020 public void Update(ObjectPropertyUpdate update)
4021 {
4022 SendFamilyProps = SendFamilyProps || update.SendFamilyProps;
4023 SendObjectProps = SendObjectProps || update.SendObjectProps;
4024 // other properties may need to be updated by base class
4025 base.Update(update);
4026 }
4027 }
4028
4029 public void SendObjectPropertiesFamilyData(ISceneEntity entity, uint requestFlags)
4030 {
4031 uint priority = 0; // time based ordering only
4032 lock (m_entityProps.SyncRoot)
4033 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false));
4034 }
4035
4036 private void ResendPropertyUpdate(ObjectPropertyUpdate update)
4037 {
4038 uint priority = 0;
4039 lock (m_entityProps.SyncRoot)
4040 m_entityProps.Enqueue(priority, update);
4041 }
4042
4043 private void ResendPropertyUpdates(List<ObjectPropertyUpdate> updates, OutgoingPacket oPacket)
4044 {
4045 // m_log.WarnFormat("[CLIENT] resending object property {0}",updates[0].UpdateTime);
4046
4047 // Remove the update packet from the list of packets waiting for acknowledgement
4048 // because we are requeuing the list of updates. They will be resent in new packets
4049 // with the most recent state.
4050 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
4051
4052 // Count this as a resent packet since we are going to requeue all of the updates contained in it
4053 Interlocked.Increment(ref m_udpClient.PacketsResent);
4054
4055 foreach (ObjectPropertyUpdate update in updates)
4056 ResendPropertyUpdate(update);
4057 }
4058
4059 public void SendObjectPropertiesReply(ISceneEntity entity)
4060 {
4061 uint priority = 0; // time based ordering only
4062 lock (m_entityProps.SyncRoot)
4063 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,0,false,true));
4064 }
4065
4066 private void ProcessEntityPropertyRequests(int maxUpdates)
4067 {
4068 OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>> objectFamilyBlocks =
4069 new OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>>();
4070
4071 OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks =
4072 new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>();
4073
4074 OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> familyUpdates =
4075 new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
4076
4077 OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates =
4078 new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
4079
4080 IEntityUpdate iupdate;
4081 Int32 timeinqueue; // this is just debugging code & can be dropped later
4082
4083 int updatesThisCall = 0;
4084 while (updatesThisCall < m_maxUpdates)
4085 {
4086 lock (m_entityProps.SyncRoot)
4087 if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue))
4088 break;
4089
4090 ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate;
4091 if (update.SendFamilyProps)
4092 {
4093 if (update.Entity is SceneObjectPart)
4094 {
4095 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4096 ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
4097 objectFamilyBlocks.Value.Add(objPropDB);
4098 familyUpdates.Value.Add(update);
4099 }
4100 }
4101
4102 if (update.SendObjectProps)
4103 {
4104 if (update.Entity is SceneObjectPart)
4105 {
4106 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4107 ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
4108 objectPropertiesBlocks.Value.Add(objPropDB);
4109 propertyUpdates.Value.Add(update);
4110 }
4111 }
4112
4113 updatesThisCall++;
4114 }
4115
4116
4117 // Int32 ppcnt = 0;
4118 // Int32 pbcnt = 0;
4119
4120 if (objectPropertiesBlocks.IsValueCreated)
4121 {
4122 List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value;
4123 List<ObjectPropertyUpdate> updates = propertyUpdates.Value;
4124
4125 ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
4126 packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count];
4127 for (int i = 0; i < blocks.Count; i++)
4128 packet.ObjectData[i] = blocks[i];
4129
4130 packet.Header.Zerocoded = true;
4131
4132 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4133 // of the object rather than the properties when the packet was created
4134 OutPacket(packet, ThrottleOutPacketType.Task, true,
4135 delegate(OutgoingPacket oPacket)
4136 {
4137 ResendPropertyUpdates(updates, oPacket);
4138 });
4139
4140 // pbcnt += blocks.Count;
4141 // ppcnt++;
4142 }
4143
4144 // Int32 fpcnt = 0;
4145 // Int32 fbcnt = 0;
4146
4147 if (objectFamilyBlocks.IsValueCreated)
4148 {
4149 List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value;
4150
4151 // one packet per object block... uggh...
4152 for (int i = 0; i < blocks.Count; i++)
4153 {
4154 ObjectPropertiesFamilyPacket packet =
4155 (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
4156
4157 packet.ObjectData = blocks[i];
4158 packet.Header.Zerocoded = true;
4159
4160 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4161 // of the object rather than the properties when the packet was created
4162 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
4163 updates.Add(familyUpdates.Value[i]);
4164 OutPacket(packet, ThrottleOutPacketType.Task, true,
4165 delegate(OutgoingPacket oPacket)
4166 {
4167 ResendPropertyUpdates(updates, oPacket);
4168 });
4169
4170 // fpcnt++;
4171 // fbcnt++;
4172 }
4173
4174 }
4175
4176 // m_log.WarnFormat("[PACKETCOUNTS] queued {0} property packets with {1} blocks",ppcnt,pbcnt);
4177 // m_log.WarnFormat("[PACKETCOUNTS] queued {0} family property packets with {1} blocks",fpcnt,fbcnt);
4178 }
4179
4180 private ObjectPropertiesFamilyPacket.ObjectDataBlock CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, uint requestFlags)
4181 {
4182 ObjectPropertiesFamilyPacket.ObjectDataBlock block = new ObjectPropertiesFamilyPacket.ObjectDataBlock();
4183
4184 block.RequestFlags = requestFlags;
4185 block.ObjectID = sop.UUID;
4186 if (sop.OwnerID == sop.GroupID)
4187 block.OwnerID = UUID.Zero;
4188 else
4189 block.OwnerID = sop.OwnerID;
4190 block.GroupID = sop.GroupID;
4191 block.BaseMask = sop.BaseMask;
4192 block.OwnerMask = sop.OwnerMask;
4193 block.GroupMask = sop.GroupMask;
4194 block.EveryoneMask = sop.EveryoneMask;
4195 block.NextOwnerMask = sop.NextOwnerMask;
4196
4197 // TODO: More properties are needed in SceneObjectPart!
4198 block.OwnershipCost = sop.OwnershipCost;
4199 block.SaleType = sop.ObjectSaleType;
4200 block.SalePrice = sop.SalePrice;
4201 block.Category = sop.Category;
4202 block.LastOwnerID = sop.CreatorID; // copied from old SOG call... is this right?
4203 block.Name = Util.StringToBytes256(sop.Name);
4204 block.Description = Util.StringToBytes256(sop.Description);
4205
4206 return block;
4207 }
4208
4209 private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop)
4210 {
4211 //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
4212 // TODO: don't create new blocks if recycling an old packet
4213
4214 ObjectPropertiesPacket.ObjectDataBlock block =
4215 new ObjectPropertiesPacket.ObjectDataBlock();
4216
4217 block.ObjectID = sop.UUID;
4218 block.Name = Util.StringToBytes256(sop.Name);
4219 block.Description = Util.StringToBytes256(sop.Description);
4220
4221 block.CreationDate = (ulong)sop.CreationDate * 1000000; // viewer wants date in microseconds
4222 block.CreatorID = sop.CreatorID;
4223 block.GroupID = sop.GroupID;
4224 block.LastOwnerID = sop.LastOwnerID;
4225 if (sop.OwnerID == sop.GroupID)
4226 block.OwnerID = UUID.Zero;
4227 else
4228 block.OwnerID = sop.OwnerID;
4229
4230 block.ItemID = sop.FromUserInventoryItemID;
4231 block.FolderID = UUID.Zero; // sop.FromFolderID ??
4232 block.FromTaskID = UUID.Zero; // ???
4233 block.InventorySerial = (short)sop.InventorySerial;
4234
4235 SceneObjectPart root = sop.ParentGroup.RootPart;
4236
4237 block.TouchName = Util.StringToBytes256(root.TouchName);
4238 block.TextureID = new byte[0]; // TextureID ???
4239 block.SitName = Util.StringToBytes256(root.SitName);
4240 block.OwnerMask = root.OwnerMask;
4241 block.NextOwnerMask = root.NextOwnerMask;
4242 block.GroupMask = root.GroupMask;
4243 block.EveryoneMask = root.EveryoneMask;
4244 block.BaseMask = root.BaseMask;
4245 block.SaleType = root.ObjectSaleType;
4246 block.SalePrice = root.SalePrice;
4247
4248 return block;
4249 }
4250
4251 #region Estate Data Sending Methods
4252
4253 private static bool convertParamStringToBool(byte[] field)
4254 {
4255 string s = Utils.BytesToString(field);
4256 if (s == "1" || s.ToLower() == "y" || s.ToLower() == "yes" || s.ToLower() == "t" || s.ToLower() == "true")
4257 {
4258 return true;
4259 }
4260 return false;
4261 }
4262
4263 public void SendEstateList(UUID invoice, int code, UUID[] Data, uint estateID)
4264
4265 {
4266 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
4267 packet.AgentData.TransactionID = UUID.Random();
4268 packet.AgentData.AgentID = AgentId;
4269 packet.AgentData.SessionID = SessionId;
4270 packet.MethodData.Invoice = invoice;
4271 packet.MethodData.Method = Utils.StringToBytes("setaccess");
4272
4273 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + Data.Length];
4274
4275 for (int i = 0; i < (6 + Data.Length); i++)
4276 {
4277 returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock();
4278 }
4279 int j = 0;
4280
4281 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4282 returnblock[j].Parameter = Utils.StringToBytes(code.ToString()); j++;
4283 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4284 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4285 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4286 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4287
4288 j = 2; // Agents
4289 if ((code & 2) != 0)
4290 j = 3; // Groups
4291 if ((code & 8) != 0)
4292 j = 5; // Managers
4293
4294 returnblock[j].Parameter = Utils.StringToBytes(Data.Length.ToString());
4295 j = 6;
4296
4297 for (int i = 0; i < Data.Length; i++)
4298 {
4299 returnblock[j].Parameter = Data[i].GetBytes(); j++;
4300 }
4301 packet.ParamList = returnblock;
4302 packet.Header.Reliable = true;
4303 OutPacket(packet, ThrottleOutPacketType.Task);
4304 }
4305
4306 public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID)
4307 {
4308 List<UUID> BannedUsers = new List<UUID>();
4309
4310 for (int i = 0; i < bl.Length; i++)
4311 {
4312 if (bl[i] == null)
4313 continue;
4314 if (bl[i].BannedUserID == UUID.Zero)
4315 continue;
4316 BannedUsers.Add(bl[i].BannedUserID);
4317 }
4318
4319 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
4320 packet.AgentData.TransactionID = UUID.Random();
4321 packet.AgentData.AgentID = AgentId;
4322 packet.AgentData.SessionID = SessionId;
4323 packet.MethodData.Invoice = invoice;
4324 packet.MethodData.Method = Utils.StringToBytes("setaccess");
4325
4326 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count];
4327
4328 for (int i = 0; i < (6 + BannedUsers.Count); i++)
4329 {
4330 returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock();
4331 }
4332 int j = 0;
4333
4334 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4335 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
4336 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4337 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4338 returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++;
4339 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4340
4341 foreach (UUID banned in BannedUsers)
4342 {
4343 returnblock[j].Parameter = banned.GetBytes(); j++;
4344 }
4345 packet.ParamList = returnblock;
4346 packet.Header.Reliable = false;
4347 OutPacket(packet, ThrottleOutPacketType.Task);
4348 }
4349
4350 public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args)
4351 {
4352 RegionInfoPacket rinfopack = new RegionInfoPacket();
4353 RegionInfoPacket.RegionInfoBlock rinfoblk = new RegionInfoPacket.RegionInfoBlock();
4354 rinfopack.AgentData.AgentID = AgentId;
4355 rinfopack.AgentData.SessionID = SessionId;
4356 rinfoblk.BillableFactor = args.billableFactor;
4357 rinfoblk.EstateID = args.estateID;
4358 rinfoblk.MaxAgents = args.maxAgents;
4359 rinfoblk.ObjectBonusFactor = args.objectBonusFactor;
4360 rinfoblk.ParentEstateID = args.parentEstateID;
4361 rinfoblk.PricePerMeter = args.pricePerMeter;
4362 rinfoblk.RedirectGridX = args.redirectGridX;
4363 rinfoblk.RedirectGridY = args.redirectGridY;
4364 rinfoblk.RegionFlags = args.regionFlags;
4365 rinfoblk.SimAccess = args.simAccess;
4366 rinfoblk.SunHour = args.sunHour;
4367 rinfoblk.TerrainLowerLimit = args.terrainLowerLimit;
4368 rinfoblk.TerrainRaiseLimit = args.terrainRaiseLimit;
4369 rinfoblk.UseEstateSun = args.useEstateSun;
4370 rinfoblk.WaterHeight = args.waterHeight;
4371 rinfoblk.SimName = Utils.StringToBytes(args.simName);
4372
4373 rinfopack.RegionInfo2 = new RegionInfoPacket.RegionInfo2Block();
4374 rinfopack.RegionInfo2.HardMaxAgents = uint.MaxValue;
4375 rinfopack.RegionInfo2.HardMaxObjects = uint.MaxValue;
4376 rinfopack.RegionInfo2.MaxAgents32 = uint.MaxValue;
4377 rinfopack.RegionInfo2.ProductName = Util.StringToBytes256(args.regionType);
4378 rinfopack.RegionInfo2.ProductSKU = Utils.EmptyBytes;
4379
4380 rinfopack.HasVariableBlocks = true;
4381 rinfopack.RegionInfo = rinfoblk;
4382 rinfopack.AgentData = new RegionInfoPacket.AgentDataBlock();
4383 rinfopack.AgentData.AgentID = AgentId;
4384 rinfopack.AgentData.SessionID = SessionId;
4385
4386
4387 OutPacket(rinfopack, ThrottleOutPacketType.Task);
4388 }
4389
4390 public void SendEstateCovenantInformation(UUID covenant)
4391 {
4392// m_log.DebugFormat("[LLCLIENTVIEW]: Sending estate covenant asset id of {0} to {1}", covenant, Name);
4393
4394 EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket();
4395 EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock();
4396 edata.CovenantID = covenant;
4397 edata.CovenantTimestamp = 0;
4398 edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
4399 edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName);
4400 einfopack.Data = edata;
4401 OutPacket(einfopack, ThrottleOutPacketType.Task);
4402 }
4403
4404 public void SendDetailedEstateData(
4405 UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition,
4406 UUID covenant, string abuseEmail, UUID estateOwner)
4407 {
4408// m_log.DebugFormat(
4409// "[LLCLIENTVIEW]: Sending detailed estate data to {0} with covenant asset id {1}", Name, covenant);
4410
4411 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
4412 packet.MethodData.Invoice = invoice;
4413 packet.AgentData.TransactionID = UUID.Random();
4414 packet.MethodData.Method = Utils.StringToBytes("estateupdateinfo");
4415 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[10];
4416
4417 for (int i = 0; i < 10; i++)
4418 {
4419 returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock();
4420 }
4421
4422 //Sending Estate Settings
4423 returnblock[0].Parameter = Utils.StringToBytes(estateName);
4424 returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString());
4425 returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString());
4426
4427 returnblock[3].Parameter = Utils.StringToBytes(estateFlags.ToString());
4428 returnblock[4].Parameter = Utils.StringToBytes(sunPosition.ToString());
4429 returnblock[5].Parameter = Utils.StringToBytes(parentEstate.ToString());
4430 returnblock[6].Parameter = Utils.StringToBytes(covenant.ToString());
4431 returnblock[7].Parameter = Utils.StringToBytes("1160895077"); // what is this?
4432 returnblock[8].Parameter = Utils.StringToBytes("1"); // what is this?
4433 returnblock[9].Parameter = Utils.StringToBytes(abuseEmail);
4434
4435 packet.ParamList = returnblock;
4436 packet.Header.Reliable = false;
4437 //m_log.Debug("[ESTATE]: SIM--->" + packet.ToString());
4438 OutPacket(packet, ThrottleOutPacketType.Task);
4439 }
4440
4441 #endregion
4442
4443 #region Land Data Sending Methods
4444
4445 public void SendLandParcelOverlay(byte[] data, int sequence_id)
4446 {
4447 ParcelOverlayPacket packet = (ParcelOverlayPacket)PacketPool.Instance.GetPacket(PacketType.ParcelOverlay);
4448 packet.ParcelData.Data = data;
4449 packet.ParcelData.SequenceID = sequence_id;
4450 packet.Header.Zerocoded = true;
4451 OutPacket(packet, ThrottleOutPacketType.Task);
4452 }
4453
4454 public void SendLandProperties(
4455 int sequence_id, bool snap_selection, int request_result, ILandObject lo,
4456 float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags)
4457 {
4458// m_log.DebugFormat("[LLCLIENTVIEW]: Sending land properties for {0} to {1}", lo.LandData.GlobalID, Name);
4459
4460 LandData landData = lo.LandData;
4461
4462 ParcelPropertiesMessage updateMessage = new ParcelPropertiesMessage();
4463
4464 updateMessage.AABBMax = landData.AABBMax;
4465 updateMessage.AABBMin = landData.AABBMin;
4466 updateMessage.Area = landData.Area;
4467 updateMessage.AuctionID = landData.AuctionID;
4468 updateMessage.AuthBuyerID = landData.AuthBuyerID;
4469 updateMessage.Bitmap = landData.Bitmap;
4470 updateMessage.Desc = landData.Description;
4471 updateMessage.Category = landData.Category;
4472 updateMessage.ClaimDate = Util.ToDateTime(landData.ClaimDate);
4473 updateMessage.ClaimPrice = landData.ClaimPrice;
4474 updateMessage.GroupID = landData.GroupID;
4475 updateMessage.IsGroupOwned = landData.IsGroupOwned;
4476 updateMessage.LandingType = (LandingType) landData.LandingType;
4477 updateMessage.LocalID = landData.LocalID;
4478
4479 if (landData.Area > 0)
4480 {
4481 updateMessage.MaxPrims = parcelObjectCapacity;
4482 }
4483 else
4484 {
4485 updateMessage.MaxPrims = 0;
4486 }
4487
4488 updateMessage.MediaAutoScale = Convert.ToBoolean(landData.MediaAutoScale);
4489 updateMessage.MediaID = landData.MediaID;
4490 updateMessage.MediaURL = landData.MediaURL;
4491 updateMessage.MusicURL = landData.MusicURL;
4492 updateMessage.Name = landData.Name;
4493 updateMessage.OtherCleanTime = landData.OtherCleanTime;
4494 updateMessage.OtherCount = 0; //TODO: Unimplemented
4495 updateMessage.OwnerID = landData.OwnerID;
4496 updateMessage.ParcelFlags = (ParcelFlags) landData.Flags;
4497 updateMessage.ParcelPrimBonus = simObjectBonusFactor;
4498 updateMessage.PassHours = landData.PassHours;
4499 updateMessage.PassPrice = landData.PassPrice;
4500 updateMessage.PublicCount = 0; //TODO: Unimplemented
4501
4502 updateMessage.RegionPushOverride = (regionFlags & (uint)RegionFlags.RestrictPushObject) > 0;
4503 updateMessage.RegionDenyAnonymous = (regionFlags & (uint)RegionFlags.DenyAnonymous) > 0;
4504
4505 //updateMessage.RegionDenyIdentified = (regionFlags & (uint)RegionFlags.DenyIdentified) > 0;
4506 //updateMessage.RegionDenyTransacted = (regionFlags & (uint)RegionFlags.DenyTransacted) > 0;
4507
4508 updateMessage.RentPrice = 0;
4509 updateMessage.RequestResult = (ParcelResult) request_result;
4510 updateMessage.SalePrice = landData.SalePrice;
4511 updateMessage.SelfCount = 0; //TODO: Unimplemented
4512 updateMessage.SequenceID = sequence_id;
4513
4514 if (landData.SimwideArea > 0)
4515 {
4516 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus);
4517 updateMessage.SimWideMaxPrims = simulatorCapacity;
4518 }
4519 else
4520 {
4521 updateMessage.SimWideMaxPrims = 0;
4522 }
4523
4524 updateMessage.SnapSelection = snap_selection;
4525 updateMessage.SnapshotID = landData.SnapshotID;
4526 updateMessage.Status = (ParcelStatus) landData.Status;
4527 updateMessage.UserLocation = landData.UserLocation;
4528 updateMessage.UserLookAt = landData.UserLookAt;
4529
4530 updateMessage.MediaType = landData.MediaType;
4531 updateMessage.MediaDesc = landData.MediaDescription;
4532 updateMessage.MediaWidth = landData.MediaWidth;
4533 updateMessage.MediaHeight = landData.MediaHeight;
4534 updateMessage.MediaLoop = landData.MediaLoop;
4535 updateMessage.ObscureMusic = landData.ObscureMusic;
4536 updateMessage.ObscureMedia = landData.ObscureMedia;
4537
4538 IPrimCounts pc = lo.PrimCounts;
4539 updateMessage.OwnerPrims = pc.Owner;
4540 updateMessage.GroupPrims = pc.Group;
4541 updateMessage.OtherPrims = pc.Others;
4542 updateMessage.SelectedPrims = pc.Selected;
4543 updateMessage.TotalPrims = pc.Total;
4544 updateMessage.SimWideTotalPrims = pc.Simulator;
4545
4546 try
4547 {
4548 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
4549 if (eq != null)
4550 {
4551 eq.ParcelProperties(updateMessage, this.AgentId);
4552 }
4553 else
4554 {
4555 m_log.Warn("[LLCLIENTVIEW]: No EQ Interface when sending parcel data.");
4556 }
4557 }
4558 catch (Exception ex)
4559 {
4560 m_log.Error("[LLCLIENTVIEW]: Unable to send parcel data via eventqueue - exception: " + ex.ToString());
4561 }
4562 }
4563
4564 public void SendLandAccessListData(List<UUID> avatars, uint accessFlag, int localLandID)
4565 {
4566 ParcelAccessListReplyPacket replyPacket = (ParcelAccessListReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply);
4567 replyPacket.Data.AgentID = AgentId;
4568 replyPacket.Data.Flags = accessFlag;
4569 replyPacket.Data.LocalID = localLandID;
4570 replyPacket.Data.SequenceID = 0;
4571
4572 List<ParcelAccessListReplyPacket.ListBlock> list = new List<ParcelAccessListReplyPacket.ListBlock>();
4573 foreach (UUID avatar in avatars)
4574 {
4575 ParcelAccessListReplyPacket.ListBlock block = new ParcelAccessListReplyPacket.ListBlock();
4576 block.Flags = accessFlag;
4577 block.ID = avatar;
4578 block.Time = 0;
4579 list.Add(block);
4580 }
4581
4582 replyPacket.List = list.ToArray();
4583 replyPacket.Header.Zerocoded = true;
4584 OutPacket(replyPacket, ThrottleOutPacketType.Task);
4585 }
4586
4587 public void SendForceClientSelectObjects(List<uint> ObjectIDs)
4588 {
4589 m_log.WarnFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count);
4590
4591 bool firstCall = true;
4592 const int MAX_OBJECTS_PER_PACKET = 251;
4593 ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect);
4594 ForceObjectSelectPacket.DataBlock[] data;
4595 while (ObjectIDs.Count > 0)
4596 {
4597 if (firstCall)
4598 {
4599 pack._Header.ResetList = true;
4600 firstCall = false;
4601 }
4602 else
4603 {
4604 pack._Header.ResetList = false;
4605 }
4606
4607 if (ObjectIDs.Count > MAX_OBJECTS_PER_PACKET)
4608 {
4609 data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET];
4610 }
4611 else
4612 {
4613 data = new ForceObjectSelectPacket.DataBlock[ObjectIDs.Count];
4614 }
4615
4616 int i;
4617 for (i = 0; i < MAX_OBJECTS_PER_PACKET && ObjectIDs.Count > 0; i++)
4618 {
4619 data[i] = new ForceObjectSelectPacket.DataBlock();
4620 data[i].LocalID = Convert.ToUInt32(ObjectIDs[0]);
4621 ObjectIDs.RemoveAt(0);
4622 }
4623 pack.Data = data;
4624 pack.Header.Zerocoded = true;
4625 OutPacket(pack, ThrottleOutPacketType.Task);
4626 }
4627 }
4628
4629 public void SendCameraConstraint(Vector4 ConstraintPlane)
4630 {
4631 CameraConstraintPacket cpack = (CameraConstraintPacket)PacketPool.Instance.GetPacket(PacketType.CameraConstraint);
4632 cpack.CameraCollidePlane = new CameraConstraintPacket.CameraCollidePlaneBlock();
4633 cpack.CameraCollidePlane.Plane = ConstraintPlane;
4634 //m_log.DebugFormat("[CLIENTVIEW]: Constraint {0}", ConstraintPlane);
4635 OutPacket(cpack, ThrottleOutPacketType.Task);
4636 }
4637
4638 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount)
4639 {
4640 int notifyCount = ownersAndCount.Count;
4641 ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply);
4642
4643 if (notifyCount > 0)
4644 {
4645 if (notifyCount > 32)
4646 {
4647 m_log.InfoFormat(
4648 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4649 + " - a developer might want to investigate whether this is a hard limit", 32);
4650
4651 notifyCount = 32;
4652 }
4653
4654 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4655 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
4656
4657 int num = 0;
4658 foreach (UUID owner in ownersAndCount.Keys)
4659 {
4660 dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock();
4661 dataBlock[num].Count = ownersAndCount[owner];
4662
4663 if (land.GroupID == owner || groups.Contains(owner))
4664 dataBlock[num].IsGroupOwned = true;
4665
4666 dataBlock[num].OnlineStatus = true; //TODO: fix me later
4667 dataBlock[num].OwnerID = owner;
4668
4669 num++;
4670
4671 if (num >= notifyCount)
4672 {
4673 break;
4674 }
4675 }
4676
4677 pack.Data = dataBlock;
4678 }
4679 else
4680 {
4681 pack.Data = new ParcelObjectOwnersReplyPacket.DataBlock[0];
4682 }
4683 pack.Header.Zerocoded = true;
4684 this.OutPacket(pack, ThrottleOutPacketType.Task);
4685 }
4686
4687 #endregion
4688
4689 #region Helper Methods
4690
4691 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(ISceneEntity entity, bool sendTexture)
4692 {
4693 #region ScenePresence/SOP Handling
4694
4695 bool avatar = (entity is ScenePresence);
4696 uint localID = entity.LocalId;
4697 uint attachPoint;
4698 Vector4 collisionPlane;
4699 Vector3 position, velocity, acceleration, angularVelocity;
4700 Quaternion rotation;
4701 byte[] textureEntry;
4702
4703 if (entity is ScenePresence)
4704 {
4705 ScenePresence presence = (ScenePresence)entity;
4706
4707 attachPoint = 0;
4708 collisionPlane = presence.CollisionPlane;
4709 position = presence.OffsetPosition;
4710 velocity = presence.Velocity;
4711 acceleration = Vector3.Zero;
4712 angularVelocity = Vector3.Zero;
4713 rotation = presence.Rotation;
4714
4715 if (sendTexture)
4716 textureEntry = presence.Appearance.Texture.GetBytes();
4717 else
4718 textureEntry = null;
4719 }
4720 else
4721 {
4722 SceneObjectPart part = (SceneObjectPart)entity;
4723
4724 attachPoint = part.AttachmentPoint;
4725 collisionPlane = Vector4.Zero;
4726 position = part.RelativePosition;
4727 velocity = part.Velocity;
4728 acceleration = part.Acceleration;
4729 angularVelocity = part.AngularVelocity;
4730 rotation = part.RotationOffset;
4731
4732 if (sendTexture)
4733 textureEntry = part.Shape.TextureEntry;
4734 else
4735 textureEntry = null;
4736 }
4737
4738 #endregion ScenePresence/SOP Handling
4739
4740 int pos = 0;
4741 byte[] data = new byte[(avatar ? 60 : 44)];
4742
4743 // LocalID
4744 Utils.UIntToBytes(localID, data, pos);
4745 pos += 4;
4746
4747 // Avatar/CollisionPlane
4748 data[pos++] = (byte)((attachPoint % 16) * 16 + (attachPoint / 16)); ;
4749 if (avatar)
4750 {
4751 data[pos++] = 1;
4752
4753 if (collisionPlane == Vector4.Zero)
4754 collisionPlane = Vector4.UnitW;
4755 //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane);
4756 collisionPlane.ToBytes(data, pos);
4757 pos += 16;
4758 }
4759 else
4760 {
4761 ++pos;
4762 }
4763
4764 // Position
4765 position.ToBytes(data, pos);
4766 pos += 12;
4767
4768 // Velocity
4769 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.X, -128.0f, 128.0f), data, pos); pos += 2;
4770 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Y, -128.0f, 128.0f), data, pos); pos += 2;
4771 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Z, -128.0f, 128.0f), data, pos); pos += 2;
4772
4773 // Acceleration
4774 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.X, -64.0f, 64.0f), data, pos); pos += 2;
4775 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Y, -64.0f, 64.0f), data, pos); pos += 2;
4776 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Z, -64.0f, 64.0f), data, pos); pos += 2;
4777
4778 // Rotation
4779 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.X, -1.0f, 1.0f), data, pos); pos += 2;
4780 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.Y, -1.0f, 1.0f), data, pos); pos += 2;
4781 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.Z, -1.0f, 1.0f), data, pos); pos += 2;
4782 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.W, -1.0f, 1.0f), data, pos); pos += 2;
4783
4784 // Angular Velocity
4785 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.X, -64.0f, 64.0f), data, pos); pos += 2;
4786 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
4787 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
4788
4789 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
4790 block.Data = data;
4791
4792 if (textureEntry != null && textureEntry.Length > 0)
4793 {
4794 byte[] teBytesFinal = new byte[textureEntry.Length + 4];
4795
4796 // Texture Length
4797 Utils.IntToBytes(textureEntry.Length, textureEntry, 0);
4798 // Texture
4799 Buffer.BlockCopy(textureEntry, 0, teBytesFinal, 4, textureEntry.Length);
4800
4801 block.TextureEntry = teBytesFinal;
4802 }
4803 else
4804 {
4805 block.TextureEntry = Utils.EmptyBytes;
4806 }
4807
4808 return block;
4809 }
4810
4811 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
4812 {
4813 byte[] objectData = new byte[76];
4814
4815 data.CollisionPlane.ToBytes(objectData, 0);
4816 data.OffsetPosition.ToBytes(objectData, 16);
4817 //data.Velocity.ToBytes(objectData, 28);
4818 //data.Acceleration.ToBytes(objectData, 40);
4819 data.Rotation.ToBytes(objectData, 52);
4820 //data.AngularVelocity.ToBytes(objectData, 64);
4821
4822 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
4823
4824 update.Data = Utils.EmptyBytes;
4825 update.ExtraParams = new byte[1];
4826 update.FullID = data.UUID;
4827 update.ID = data.LocalId;
4828 update.Material = (byte)Material.Flesh;
4829 update.MediaURL = Utils.EmptyBytes;
4830 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
4831 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
4832 update.ObjectData = objectData;
4833 update.ParentID = data.ParentID;
4834 update.PathCurve = 16;
4835 update.PathScaleX = 100;
4836 update.PathScaleY = 100;
4837 update.PCode = (byte)PCode.Avatar;
4838 update.ProfileCurve = 1;
4839 update.PSBlock = Utils.EmptyBytes;
4840 update.Scale = new Vector3(0.45f, 0.6f, 1.9f);
4841 update.Text = Utils.EmptyBytes;
4842 update.TextColor = new byte[4];
4843 update.TextureAnim = Utils.EmptyBytes;
4844 update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
4845 update.UpdateFlags = (uint)(
4846 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
4847 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
4848 PrimFlags.ObjectOwnerModify);
4849
4850 return update;
4851 }
4852
4853 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID)
4854 {
4855 byte[] objectData = new byte[60];
4856 data.RelativePosition.ToBytes(objectData, 0);
4857 data.Velocity.ToBytes(objectData, 12);
4858 data.Acceleration.ToBytes(objectData, 24);
4859 try
4860 {
4861 data.RotationOffset.ToBytes(objectData, 36);
4862 }
4863 catch (Exception e)
4864 {
4865 m_log.Warn("[LLClientView]: exception converting quaternion to bytes, using Quaternion.Identity. Exception: " + e.ToString());
4866 OpenMetaverse.Quaternion.Identity.ToBytes(objectData, 36);
4867 }
4868 data.AngularVelocity.ToBytes(objectData, 48);
4869
4870 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
4871 update.ClickAction = (byte)data.ClickAction;
4872 update.CRC = 0;
4873 update.ExtraParams = data.Shape.ExtraParams ?? Utils.EmptyBytes;
4874 update.FullID = data.UUID;
4875 update.ID = data.LocalId;
4876 //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated
4877 //update.JointPivot = Vector3.Zero;
4878 //update.JointType = 0;
4879 update.Material = data.Material;
4880 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
4881 if (data.IsAttachment)
4882 {
4883 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID);
4884 update.State = (byte)((data.AttachmentPoint % 16) * 16 + (data.AttachmentPoint / 16));
4885 }
4886 else
4887 {
4888 update.NameValue = Utils.EmptyBytes;
4889 update.State = data.Shape.State;
4890 }
4891
4892 update.ObjectData = objectData;
4893 update.ParentID = data.ParentID;
4894 update.PathBegin = data.Shape.PathBegin;
4895 update.PathCurve = data.Shape.PathCurve;
4896 update.PathEnd = data.Shape.PathEnd;
4897 update.PathRadiusOffset = data.Shape.PathRadiusOffset;
4898 update.PathRevolutions = data.Shape.PathRevolutions;
4899 update.PathScaleX = data.Shape.PathScaleX;
4900 update.PathScaleY = data.Shape.PathScaleY;
4901 update.PathShearX = data.Shape.PathShearX;
4902 update.PathShearY = data.Shape.PathShearY;
4903 update.PathSkew = data.Shape.PathSkew;
4904 update.PathTaperX = data.Shape.PathTaperX;
4905 update.PathTaperY = data.Shape.PathTaperY;
4906 update.PathTwist = data.Shape.PathTwist;
4907 update.PathTwistBegin = data.Shape.PathTwistBegin;
4908 update.PCode = data.Shape.PCode;
4909 update.ProfileBegin = data.Shape.ProfileBegin;
4910 update.ProfileCurve = data.Shape.ProfileCurve;
4911 update.ProfileEnd = data.Shape.ProfileEnd;
4912 update.ProfileHollow = data.Shape.ProfileHollow;
4913 update.PSBlock = data.ParticleSystem ?? Utils.EmptyBytes;
4914 update.TextColor = data.GetTextColor().GetBytes(false);
4915 update.TextureAnim = data.TextureAnimation ?? Utils.EmptyBytes;
4916 update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes;
4917 update.Scale = data.Shape.Scale;
4918 update.Text = Util.StringToBytes256(data.Text);
4919 update.MediaURL = Util.StringToBytes256(data.MediaUrl);
4920
4921 #region PrimFlags
4922
4923 PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(recipientID, data.UUID);
4924
4925 // Don't send the CreateSelected flag to everyone
4926 flags &= ~PrimFlags.CreateSelected;
4927
4928 if (recipientID == data.OwnerID)
4929 {
4930 if (data.CreateSelected)
4931 {
4932 // Only send this flag once, then unset it
4933 flags |= PrimFlags.CreateSelected;
4934 data.CreateSelected = false;
4935 }
4936 }
4937
4938// m_log.DebugFormat(
4939// "[LLCLIENTVIEW]: Constructing client update for part {0} {1} with flags {2}, localId {3}",
4940// data.Name, update.FullID, flags, update.ID);
4941
4942 update.UpdateFlags = (uint)flags;
4943
4944 #endregion PrimFlags
4945
4946 if (data.Sound != UUID.Zero)
4947 {
4948 update.Sound = data.Sound;
4949 update.OwnerID = data.OwnerID;
4950 update.Gain = (float)data.SoundGain;
4951 update.Radius = (float)data.SoundRadius;
4952 update.Flags = data.SoundFlags;
4953 }
4954
4955 switch ((PCode)data.Shape.PCode)
4956 {
4957 case PCode.Grass:
4958 case PCode.Tree:
4959 case PCode.NewTree:
4960 update.Data = new byte[] { data.Shape.State };
4961 break;
4962 default:
4963 update.Data = Utils.EmptyBytes;
4964 break;
4965 }
4966
4967 return update;
4968 }
4969
4970 protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags)
4971 {
4972 // TODO: Implement this
4973 return null;
4974 }
4975
4976 public void SendNameReply(UUID profileId, string firstname, string lastname)
4977 {
4978 UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply);
4979 // TODO: don't create new blocks if recycling an old packet
4980 packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1];
4981 packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock();
4982 packet.UUIDNameBlock[0].ID = profileId;
4983 packet.UUIDNameBlock[0].FirstName = Util.StringToBytes256(firstname);
4984 packet.UUIDNameBlock[0].LastName = Util.StringToBytes256(lastname);
4985
4986 OutPacket(packet, ThrottleOutPacketType.Task);
4987 }
4988
4989 public ulong GetGroupPowers(UUID groupID)
4990 {
4991 if (groupID == m_activeGroupID)
4992 return m_activeGroupPowers;
4993
4994 if (m_groupPowers.ContainsKey(groupID))
4995 return m_groupPowers[groupID];
4996
4997 return 0;
4998 }
4999
5000 /// <summary>
5001 /// This is a utility method used by single states to not duplicate kicks and blue card of death messages.
5002 /// </summary>
5003 public bool ChildAgentStatus()
5004 {
5005 return m_scene.PresenceChildStatus(AgentId);
5006 }
5007
5008 #endregion
5009
5010 /// <summary>
5011 /// This is a different way of processing packets then ProcessInPacket
5012 /// </summary>
5013 protected virtual void RegisterLocalPacketHandlers()
5014 {
5015 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout);
5016 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
5017 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
5018 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
5019 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
5020 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false);
5021 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false);
5022 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false);
5023 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false);
5024 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage);
5025 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest);
5026 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
5027 AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate);
5028 AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply);
5029 AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage, false);
5030 AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship);
5031 AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship);
5032 AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFrendship);
5033 AddLocalPacketHandler(PacketType.RezObject, HandlerRezObject);
5034 AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject);
5035 AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand);
5036 AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply);
5037 AddLocalPacketHandler(PacketType.AgentWearablesRequest, HandlerAgentWearablesRequest);
5038 AddLocalPacketHandler(PacketType.AgentSetAppearance, HandlerAgentSetAppearance);
5039 AddLocalPacketHandler(PacketType.AgentIsNowWearing, HandlerAgentIsNowWearing);
5040 AddLocalPacketHandler(PacketType.RezSingleAttachmentFromInv, HandlerRezSingleAttachmentFromInv);
5041 AddLocalPacketHandler(PacketType.RezMultipleAttachmentsFromInv, HandleRezMultipleAttachmentsFromInv);
5042 AddLocalPacketHandler(PacketType.DetachAttachmentIntoInv, HandleDetachAttachmentIntoInv);
5043 AddLocalPacketHandler(PacketType.ObjectAttach, HandleObjectAttach);
5044 AddLocalPacketHandler(PacketType.ObjectDetach, HandleObjectDetach);
5045 AddLocalPacketHandler(PacketType.ObjectDrop, HandleObjectDrop);
5046 AddLocalPacketHandler(PacketType.SetAlwaysRun, HandleSetAlwaysRun, false);
5047 AddLocalPacketHandler(PacketType.CompleteAgentMovement, HandleCompleteAgentMovement);
5048 AddLocalPacketHandler(PacketType.AgentAnimation, HandleAgentAnimation, false);
5049 AddLocalPacketHandler(PacketType.AgentRequestSit, HandleAgentRequestSit);
5050 AddLocalPacketHandler(PacketType.AgentSit, HandleAgentSit);
5051 AddLocalPacketHandler(PacketType.SoundTrigger, HandleSoundTrigger);
5052 AddLocalPacketHandler(PacketType.AvatarPickerRequest, HandleAvatarPickerRequest);
5053 AddLocalPacketHandler(PacketType.AgentDataUpdateRequest, HandleAgentDataUpdateRequest);
5054 AddLocalPacketHandler(PacketType.UserInfoRequest, HandleUserInfoRequest);
5055 AddLocalPacketHandler(PacketType.UpdateUserInfo, HandleUpdateUserInfo);
5056 AddLocalPacketHandler(PacketType.SetStartLocationRequest, HandleSetStartLocationRequest);
5057 AddLocalPacketHandler(PacketType.AgentThrottle, HandleAgentThrottle, false);
5058 AddLocalPacketHandler(PacketType.AgentPause, HandleAgentPause, false);
5059 AddLocalPacketHandler(PacketType.AgentResume, HandleAgentResume, false);
5060 AddLocalPacketHandler(PacketType.ForceScriptControlRelease, HandleForceScriptControlRelease);
5061 AddLocalPacketHandler(PacketType.ObjectLink, HandleObjectLink);
5062 AddLocalPacketHandler(PacketType.ObjectDelink, HandleObjectDelink);
5063 AddLocalPacketHandler(PacketType.ObjectAdd, HandleObjectAdd);
5064 AddLocalPacketHandler(PacketType.ObjectShape, HandleObjectShape);
5065 AddLocalPacketHandler(PacketType.ObjectExtraParams, HandleObjectExtraParams);
5066 AddLocalPacketHandler(PacketType.ObjectDuplicate, HandleObjectDuplicate);
5067 AddLocalPacketHandler(PacketType.RequestMultipleObjects, HandleRequestMultipleObjects);
5068 AddLocalPacketHandler(PacketType.ObjectSelect, HandleObjectSelect);
5069 AddLocalPacketHandler(PacketType.ObjectDeselect, HandleObjectDeselect);
5070 AddLocalPacketHandler(PacketType.ObjectPosition, HandleObjectPosition);
5071 AddLocalPacketHandler(PacketType.ObjectScale, HandleObjectScale);
5072 AddLocalPacketHandler(PacketType.ObjectRotation, HandleObjectRotation);
5073 AddLocalPacketHandler(PacketType.ObjectFlagUpdate, HandleObjectFlagUpdate);
5074
5075 // Handle ObjectImage (TextureEntry) updates synchronously, since when updating multiple prim faces at once,
5076 // some clients will send out a separate ObjectImage packet for each face
5077 AddLocalPacketHandler(PacketType.ObjectImage, HandleObjectImage, false);
5078
5079 AddLocalPacketHandler(PacketType.ObjectGrab, HandleObjectGrab, false);
5080 AddLocalPacketHandler(PacketType.ObjectGrabUpdate, HandleObjectGrabUpdate, false);
5081 AddLocalPacketHandler(PacketType.ObjectDeGrab, HandleObjectDeGrab);
5082 AddLocalPacketHandler(PacketType.ObjectSpinStart, HandleObjectSpinStart, false);
5083 AddLocalPacketHandler(PacketType.ObjectSpinUpdate, HandleObjectSpinUpdate, false);
5084 AddLocalPacketHandler(PacketType.ObjectSpinStop, HandleObjectSpinStop, false);
5085 AddLocalPacketHandler(PacketType.ObjectDescription, HandleObjectDescription, false);
5086 AddLocalPacketHandler(PacketType.ObjectName, HandleObjectName, false);
5087 AddLocalPacketHandler(PacketType.ObjectPermissions, HandleObjectPermissions, false);
5088 AddLocalPacketHandler(PacketType.Undo, HandleUndo, false);
5089 AddLocalPacketHandler(PacketType.UndoLand, HandleLandUndo, false);
5090 AddLocalPacketHandler(PacketType.Redo, HandleRedo, false);
5091 AddLocalPacketHandler(PacketType.ObjectDuplicateOnRay, HandleObjectDuplicateOnRay);
5092 AddLocalPacketHandler(PacketType.RequestObjectPropertiesFamily, HandleRequestObjectPropertiesFamily, false);
5093 AddLocalPacketHandler(PacketType.ObjectIncludeInSearch, HandleObjectIncludeInSearch);
5094 AddLocalPacketHandler(PacketType.ScriptAnswerYes, HandleScriptAnswerYes, false);
5095 AddLocalPacketHandler(PacketType.ObjectClickAction, HandleObjectClickAction, false);
5096 AddLocalPacketHandler(PacketType.ObjectMaterial, HandleObjectMaterial, false);
5097 AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage);
5098 AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest);
5099 AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest);
5100 AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer);
5101 AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket);
5102 AddLocalPacketHandler(PacketType.ConfirmXferPacket, HandleConfirmXferPacket);
5103 AddLocalPacketHandler(PacketType.AbortXfer, HandleAbortXfer);
5104 AddLocalPacketHandler(PacketType.CreateInventoryFolder, HandleCreateInventoryFolder);
5105 AddLocalPacketHandler(PacketType.UpdateInventoryFolder, HandleUpdateInventoryFolder);
5106 AddLocalPacketHandler(PacketType.MoveInventoryFolder, HandleMoveInventoryFolder);
5107 AddLocalPacketHandler(PacketType.CreateInventoryItem, HandleCreateInventoryItem);
5108 AddLocalPacketHandler(PacketType.LinkInventoryItem, HandleLinkInventoryItem);
5109 AddLocalPacketHandler(PacketType.FetchInventory, HandleFetchInventory);
5110 AddLocalPacketHandler(PacketType.FetchInventoryDescendents, HandleFetchInventoryDescendents);
5111 AddLocalPacketHandler(PacketType.PurgeInventoryDescendents, HandlePurgeInventoryDescendents);
5112 AddLocalPacketHandler(PacketType.UpdateInventoryItem, HandleUpdateInventoryItem);
5113 AddLocalPacketHandler(PacketType.CopyInventoryItem, HandleCopyInventoryItem);
5114 AddLocalPacketHandler(PacketType.MoveInventoryItem, HandleMoveInventoryItem);
5115 AddLocalPacketHandler(PacketType.RemoveInventoryItem, HandleRemoveInventoryItem);
5116 AddLocalPacketHandler(PacketType.RemoveInventoryFolder, HandleRemoveInventoryFolder);
5117 AddLocalPacketHandler(PacketType.RemoveInventoryObjects, HandleRemoveInventoryObjects);
5118 AddLocalPacketHandler(PacketType.RequestTaskInventory, HandleRequestTaskInventory);
5119 AddLocalPacketHandler(PacketType.UpdateTaskInventory, HandleUpdateTaskInventory);
5120 AddLocalPacketHandler(PacketType.RemoveTaskInventory, HandleRemoveTaskInventory);
5121 AddLocalPacketHandler(PacketType.MoveTaskInventory, HandleMoveTaskInventory);
5122 AddLocalPacketHandler(PacketType.RezScript, HandleRezScript);
5123 AddLocalPacketHandler(PacketType.MapLayerRequest, HandleMapLayerRequest, false);
5124 AddLocalPacketHandler(PacketType.MapBlockRequest, HandleMapBlockRequest, false);
5125 AddLocalPacketHandler(PacketType.MapNameRequest, HandleMapNameRequest, false);
5126 AddLocalPacketHandler(PacketType.TeleportLandmarkRequest, HandleTeleportLandmarkRequest);
5127 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest);
5128 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false);
5129 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest);
5130 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest);
5131 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false);
5132 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false);
5133 AddLocalPacketHandler(PacketType.ParcelPropertiesRequest, HandleParcelPropertiesRequest, false);
5134 AddLocalPacketHandler(PacketType.ParcelDivide, HandleParcelDivide);
5135 AddLocalPacketHandler(PacketType.ParcelJoin, HandleParcelJoin);
5136 AddLocalPacketHandler(PacketType.ParcelPropertiesUpdate, HandleParcelPropertiesUpdate);
5137 AddLocalPacketHandler(PacketType.ParcelSelectObjects, HandleParcelSelectObjects);
5138 AddLocalPacketHandler(PacketType.ParcelObjectOwnersRequest, HandleParcelObjectOwnersRequest);
5139 AddLocalPacketHandler(PacketType.ParcelGodForceOwner, HandleParcelGodForceOwner);
5140 AddLocalPacketHandler(PacketType.ParcelRelease, HandleParcelRelease);
5141 AddLocalPacketHandler(PacketType.ParcelReclaim, HandleParcelReclaim);
5142 AddLocalPacketHandler(PacketType.ParcelReturnObjects, HandleParcelReturnObjects);
5143 AddLocalPacketHandler(PacketType.ParcelSetOtherCleanTime, HandleParcelSetOtherCleanTime);
5144 AddLocalPacketHandler(PacketType.LandStatRequest, HandleLandStatRequest);
5145 AddLocalPacketHandler(PacketType.ParcelDwellRequest, HandleParcelDwellRequest);
5146 AddLocalPacketHandler(PacketType.EstateOwnerMessage, HandleEstateOwnerMessage);
5147 AddLocalPacketHandler(PacketType.RequestRegionInfo, HandleRequestRegionInfo, false);
5148 AddLocalPacketHandler(PacketType.EstateCovenantRequest, HandleEstateCovenantRequest);
5149 AddLocalPacketHandler(PacketType.RequestGodlikePowers, HandleRequestGodlikePowers);
5150 AddLocalPacketHandler(PacketType.GodKickUser, HandleGodKickUser);
5151 AddLocalPacketHandler(PacketType.MoneyBalanceRequest, HandleMoneyBalanceRequest);
5152 AddLocalPacketHandler(PacketType.EconomyDataRequest, HandleEconomyDataRequest);
5153 AddLocalPacketHandler(PacketType.RequestPayPrice, HandleRequestPayPrice);
5154 AddLocalPacketHandler(PacketType.ObjectSaleInfo, HandleObjectSaleInfo);
5155 AddLocalPacketHandler(PacketType.ObjectBuy, HandleObjectBuy);
5156 AddLocalPacketHandler(PacketType.GetScriptRunning, HandleGetScriptRunning);
5157 AddLocalPacketHandler(PacketType.SetScriptRunning, HandleSetScriptRunning);
5158 AddLocalPacketHandler(PacketType.ScriptReset, HandleScriptReset);
5159 AddLocalPacketHandler(PacketType.ActivateGestures, HandleActivateGestures);
5160 AddLocalPacketHandler(PacketType.DeactivateGestures, HandleDeactivateGestures);
5161 AddLocalPacketHandler(PacketType.ObjectOwner, HandleObjectOwner);
5162 AddLocalPacketHandler(PacketType.AgentFOV, HandleAgentFOV, false);
5163 AddLocalPacketHandler(PacketType.ViewerStats, HandleViewerStats);
5164 AddLocalPacketHandler(PacketType.MapItemRequest, HandleMapItemRequest, false);
5165 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5166 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5167 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5168 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5169 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5170 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
5171 AddLocalPacketHandler(PacketType.DirFindQuery, HandleDirFindQuery);
5172 AddLocalPacketHandler(PacketType.DirLandQuery, HandleDirLandQuery);
5173 AddLocalPacketHandler(PacketType.DirPopularQuery, HandleDirPopularQuery);
5174 AddLocalPacketHandler(PacketType.DirClassifiedQuery, HandleDirClassifiedQuery);
5175 AddLocalPacketHandler(PacketType.EventInfoRequest, HandleEventInfoRequest);
5176 AddLocalPacketHandler(PacketType.OfferCallingCard, HandleOfferCallingCard);
5177 AddLocalPacketHandler(PacketType.AcceptCallingCard, HandleAcceptCallingCard);
5178 AddLocalPacketHandler(PacketType.DeclineCallingCard, HandleDeclineCallingCard);
5179 AddLocalPacketHandler(PacketType.ActivateGroup, HandleActivateGroup);
5180 AddLocalPacketHandler(PacketType.GroupTitlesRequest, HandleGroupTitlesRequest);
5181 AddLocalPacketHandler(PacketType.GroupProfileRequest, HandleGroupProfileRequest);
5182 AddLocalPacketHandler(PacketType.GroupMembersRequest, HandleGroupMembersRequest);
5183 AddLocalPacketHandler(PacketType.GroupRoleDataRequest, HandleGroupRoleDataRequest);
5184 AddLocalPacketHandler(PacketType.GroupRoleMembersRequest, HandleGroupRoleMembersRequest);
5185 AddLocalPacketHandler(PacketType.CreateGroupRequest, HandleCreateGroupRequest);
5186 AddLocalPacketHandler(PacketType.UpdateGroupInfo, HandleUpdateGroupInfo);
5187 AddLocalPacketHandler(PacketType.SetGroupAcceptNotices, HandleSetGroupAcceptNotices);
5188 AddLocalPacketHandler(PacketType.GroupTitleUpdate, HandleGroupTitleUpdate);
5189 AddLocalPacketHandler(PacketType.ParcelDeedToGroup, HandleParcelDeedToGroup);
5190 AddLocalPacketHandler(PacketType.GroupNoticesListRequest, HandleGroupNoticesListRequest);
5191 AddLocalPacketHandler(PacketType.GroupNoticeRequest, HandleGroupNoticeRequest);
5192 AddLocalPacketHandler(PacketType.GroupRoleUpdate, HandleGroupRoleUpdate);
5193 AddLocalPacketHandler(PacketType.GroupRoleChanges, HandleGroupRoleChanges);
5194 AddLocalPacketHandler(PacketType.JoinGroupRequest, HandleJoinGroupRequest);
5195 AddLocalPacketHandler(PacketType.LeaveGroupRequest, HandleLeaveGroupRequest);
5196 AddLocalPacketHandler(PacketType.EjectGroupMemberRequest, HandleEjectGroupMemberRequest);
5197 AddLocalPacketHandler(PacketType.InviteGroupRequest, HandleInviteGroupRequest);
5198 AddLocalPacketHandler(PacketType.StartLure, HandleStartLure);
5199 AddLocalPacketHandler(PacketType.TeleportLureRequest, HandleTeleportLureRequest);
5200 AddLocalPacketHandler(PacketType.ClassifiedInfoRequest, HandleClassifiedInfoRequest);
5201 AddLocalPacketHandler(PacketType.ClassifiedInfoUpdate, HandleClassifiedInfoUpdate);
5202 AddLocalPacketHandler(PacketType.ClassifiedDelete, HandleClassifiedDelete);
5203 AddLocalPacketHandler(PacketType.ClassifiedGodDelete, HandleClassifiedGodDelete);
5204 AddLocalPacketHandler(PacketType.EventGodDelete, HandleEventGodDelete);
5205 AddLocalPacketHandler(PacketType.EventNotificationAddRequest, HandleEventNotificationAddRequest);
5206 AddLocalPacketHandler(PacketType.EventNotificationRemoveRequest, HandleEventNotificationRemoveRequest);
5207 AddLocalPacketHandler(PacketType.RetrieveInstantMessages, HandleRetrieveInstantMessages);
5208 AddLocalPacketHandler(PacketType.PickDelete, HandlePickDelete);
5209 AddLocalPacketHandler(PacketType.PickGodDelete, HandlePickGodDelete);
5210 AddLocalPacketHandler(PacketType.PickInfoUpdate, HandlePickInfoUpdate);
5211 AddLocalPacketHandler(PacketType.AvatarNotesUpdate, HandleAvatarNotesUpdate);
5212 AddLocalPacketHandler(PacketType.AvatarInterestsUpdate, HandleAvatarInterestsUpdate);
5213 AddLocalPacketHandler(PacketType.GrantUserRights, HandleGrantUserRights);
5214 AddLocalPacketHandler(PacketType.PlacesQuery, HandlePlacesQuery);
5215 AddLocalPacketHandler(PacketType.UpdateMuteListEntry, HandleUpdateMuteListEntry);
5216 AddLocalPacketHandler(PacketType.RemoveMuteListEntry, HandleRemoveMuteListEntry);
5217 AddLocalPacketHandler(PacketType.UserReport, HandleUserReport);
5218 AddLocalPacketHandler(PacketType.FindAgent, HandleFindAgent);
5219 AddLocalPacketHandler(PacketType.TrackAgent, HandleTrackAgent);
5220 AddLocalPacketHandler(PacketType.GodUpdateRegionInfo, HandleGodUpdateRegionInfoUpdate);
5221 AddLocalPacketHandler(PacketType.GodlikeMessage, HandleGodlikeMessage);
5222 AddLocalPacketHandler(PacketType.StateSave, HandleSaveStatePacket);
5223 AddLocalPacketHandler(PacketType.GroupAccountDetailsRequest, HandleGroupAccountDetailsRequest);
5224 AddLocalPacketHandler(PacketType.GroupAccountSummaryRequest, HandleGroupAccountSummaryRequest);
5225 AddLocalPacketHandler(PacketType.GroupAccountTransactionsRequest, HandleGroupTransactionsDetailsRequest);
5226 AddLocalPacketHandler(PacketType.FreezeUser, HandleFreezeUser);
5227 AddLocalPacketHandler(PacketType.EjectUser, HandleEjectUser);
5228 AddLocalPacketHandler(PacketType.ParcelBuyPass, HandleParcelBuyPass);
5229 AddLocalPacketHandler(PacketType.ParcelGodMarkAsContent, HandleParcelGodMarkAsContent);
5230 AddLocalPacketHandler(PacketType.GroupActiveProposalsRequest, HandleGroupActiveProposalsRequest);
5231 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest);
5232 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes);
5233 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard);
5234 }
5235
5236 #region Packet Handlers
5237
5238 #region Scene/Avatar
5239
5240 private bool HandleAgentUpdate(IClientAPI sener, Packet Pack)
5241 {
5242 if (OnAgentUpdate != null)
5243 {
5244 bool update = false;
5245 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
5246
5247 #region Packet Session and User Check
5248 if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId)
5249 return false;
5250 #endregion
5251
5252 AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData;
5253
5254 // We can only check when we have something to check
5255 // against.
5256
5257 if (lastarg != null)
5258 {
5259 update =
5260 (
5261 (x.BodyRotation != lastarg.BodyRotation) ||
5262 (x.CameraAtAxis != lastarg.CameraAtAxis) ||
5263 (x.CameraCenter != lastarg.CameraCenter) ||
5264 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5265 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5266 (x.ControlFlags != lastarg.ControlFlags) ||
5267 (x.Far != lastarg.Far) ||
5268 (x.Flags != lastarg.Flags) ||
5269 (x.State != lastarg.State) ||
5270 (x.HeadRotation != lastarg.HeadRotation) ||
5271 (x.SessionID != lastarg.SessionID) ||
5272 (x.AgentID != lastarg.AgentID)
5273 );
5274 }
5275 else
5276 update = true;
5277
5278 // These should be ordered from most-likely to
5279 // least likely to change. I've made an initial
5280 // guess at that.
5281
5282 if (update)
5283 {
5284 AgentUpdateArgs arg = new AgentUpdateArgs();
5285 arg.AgentID = x.AgentID;
5286 arg.BodyRotation = x.BodyRotation;
5287 arg.CameraAtAxis = x.CameraAtAxis;
5288 arg.CameraCenter = x.CameraCenter;
5289 arg.CameraLeftAxis = x.CameraLeftAxis;
5290 arg.CameraUpAxis = x.CameraUpAxis;
5291 arg.ControlFlags = x.ControlFlags;
5292 arg.Far = x.Far;
5293 arg.Flags = x.Flags;
5294 arg.HeadRotation = x.HeadRotation;
5295 arg.SessionID = x.SessionID;
5296 arg.State = x.State;
5297 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5298 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5299 lastarg = arg; // save this set of arguments for nexttime
5300 if (handlerPreAgentUpdate != null)
5301 OnPreAgentUpdate(this, arg);
5302 if (handlerAgentUpdate != null)
5303 OnAgentUpdate(this, arg);
5304
5305 handlerAgentUpdate = null;
5306 handlerPreAgentUpdate = null;
5307 }
5308 }
5309
5310 return true;
5311 }
5312
5313 private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack)
5314 {
5315 MoneyTransferRequestPacket money = (MoneyTransferRequestPacket)Pack;
5316 // validate the agent owns the agentID and sessionID
5317 if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId &&
5318 money.AgentData.SessionID == sender.SessionId)
5319 {
5320 MoneyTransferRequest handlerMoneyTransferRequest = OnMoneyTransferRequest;
5321 if (handlerMoneyTransferRequest != null)
5322 {
5323 handlerMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID,
5324 money.MoneyData.Amount, money.MoneyData.TransactionType,
5325 Util.FieldToString(money.MoneyData.Description));
5326 }
5327
5328 return true;
5329 }
5330
5331 return false;
5332 }
5333
5334 private bool HandleParcelGodMarkAsContent(IClientAPI client, Packet Packet)
5335 {
5336 ParcelGodMarkAsContentPacket ParcelGodMarkAsContent =
5337 (ParcelGodMarkAsContentPacket)Packet;
5338
5339 ParcelGodMark ParcelGodMarkAsContentHandler = OnParcelGodMark;
5340 if (ParcelGodMarkAsContentHandler != null)
5341 {
5342 ParcelGodMarkAsContentHandler(this,
5343 ParcelGodMarkAsContent.AgentData.AgentID,
5344 ParcelGodMarkAsContent.ParcelData.LocalID);
5345 return true;
5346 }
5347 return false;
5348 }
5349
5350 private bool HandleFreezeUser(IClientAPI client, Packet Packet)
5351 {
5352 FreezeUserPacket FreezeUser = (FreezeUserPacket)Packet;
5353
5354 FreezeUserUpdate FreezeUserHandler = OnParcelFreezeUser;
5355 if (FreezeUserHandler != null)
5356 {
5357 FreezeUserHandler(this,
5358 FreezeUser.AgentData.AgentID,
5359 FreezeUser.Data.Flags,
5360 FreezeUser.Data.TargetID);
5361 return true;
5362 }
5363 return false;
5364 }
5365
5366 private bool HandleEjectUser(IClientAPI client, Packet Packet)
5367 {
5368 EjectUserPacket EjectUser =
5369 (EjectUserPacket)Packet;
5370
5371 EjectUserUpdate EjectUserHandler = OnParcelEjectUser;
5372 if (EjectUserHandler != null)
5373 {
5374 EjectUserHandler(this,
5375 EjectUser.AgentData.AgentID,
5376 EjectUser.Data.Flags,
5377 EjectUser.Data.TargetID);
5378 return true;
5379 }
5380 return false;
5381 }
5382
5383 private bool HandleParcelBuyPass(IClientAPI client, Packet Packet)
5384 {
5385 ParcelBuyPassPacket ParcelBuyPass =
5386 (ParcelBuyPassPacket)Packet;
5387
5388 ParcelBuyPass ParcelBuyPassHandler = OnParcelBuyPass;
5389 if (ParcelBuyPassHandler != null)
5390 {
5391 ParcelBuyPassHandler(this,
5392 ParcelBuyPass.AgentData.AgentID,
5393 ParcelBuyPass.ParcelData.LocalID);
5394 return true;
5395 }
5396 return false;
5397 }
5398
5399 private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack)
5400 {
5401 ParcelBuyPacket parcel = (ParcelBuyPacket)Pack;
5402 if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId)
5403 {
5404 ParcelBuy handlerParcelBuy = OnParcelBuy;
5405 if (handlerParcelBuy != null)
5406 {
5407 handlerParcelBuy(parcel.AgentData.AgentID, parcel.Data.GroupID, parcel.Data.Final,
5408 parcel.Data.IsGroupOwned,
5409 parcel.Data.RemoveContribution, parcel.Data.LocalID, parcel.ParcelData.Area,
5410 parcel.ParcelData.Price,
5411 false);
5412 }
5413 return true;
5414 }
5415 return false;
5416 }
5417
5418 private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack)
5419 {
5420 UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack;
5421
5422
5423 for (int i = 0; i < upack.UUIDNameBlock.Length; i++)
5424 {
5425 UUIDNameRequest handlerUUIDGroupNameRequest = OnUUIDGroupNameRequest;
5426 if (handlerUUIDGroupNameRequest != null)
5427 {
5428 handlerUUIDGroupNameRequest(upack.UUIDNameBlock[i].ID, this);
5429 }
5430 }
5431
5432 return true;
5433 }
5434
5435 public bool HandleGenericMessage(IClientAPI sender, Packet pack)
5436 {
5437 GenericMessagePacket gmpack = (GenericMessagePacket)pack;
5438 if (m_genericPacketHandlers.Count == 0) return false;
5439 if (gmpack.AgentData.SessionID != SessionId) return false;
5440
5441 GenericMessage handlerGenericMessage = null;
5442
5443 string method = Util.FieldToString(gmpack.MethodData.Method).ToLower().Trim();
5444
5445 if (m_genericPacketHandlers.TryGetValue(method, out handlerGenericMessage))
5446 {
5447 List<string> msg = new List<string>();
5448 List<byte[]> msgBytes = new List<byte[]>();
5449
5450 if (handlerGenericMessage != null)
5451 {
5452 foreach (GenericMessagePacket.ParamListBlock block in gmpack.ParamList)
5453 {
5454 msg.Add(Util.FieldToString(block.Parameter));
5455 msgBytes.Add(block.Parameter);
5456 }
5457 try
5458 {
5459 if (OnBinaryGenericMessage != null)
5460 {
5461 OnBinaryGenericMessage(this, method, msgBytes.ToArray());
5462 }
5463 handlerGenericMessage(sender, method, msg);
5464 return true;
5465 }
5466 catch (Exception e)
5467 {
5468 m_log.ErrorFormat(
5469 "[LLCLIENTVIEW]: Exeception when handling generic message {0}{1}", e.Message, e.StackTrace);
5470 }
5471 }
5472 }
5473
5474 //m_log.Debug("[LLCLIENTVIEW]: Not handling GenericMessage with method-type of: " + method);
5475 return false;
5476 }
5477
5478 public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack)
5479 {
5480 ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack;
5481 if (ogpack.AgentData.SessionID != SessionId) return false;
5482
5483 RequestObjectPropertiesFamily handlerObjectGroupRequest = OnObjectGroupRequest;
5484 if (handlerObjectGroupRequest != null)
5485 {
5486 for (int i = 0; i < ogpack.ObjectData.Length; i++)
5487 {
5488 handlerObjectGroupRequest(this, ogpack.AgentData.GroupID, ogpack.ObjectData[i].ObjectLocalID, UUID.Zero);
5489 }
5490 }
5491 return true;
5492 }
5493
5494 private bool HandleViewerEffect(IClientAPI sender, Packet Pack)
5495 {
5496 ViewerEffectPacket viewer = (ViewerEffectPacket)Pack;
5497 if (viewer.AgentData.SessionID != SessionId) return false;
5498 ViewerEffectEventHandler handlerViewerEffect = OnViewerEffect;
5499 if (handlerViewerEffect != null)
5500 {
5501 int length = viewer.Effect.Length;
5502 List<ViewerEffectEventHandlerArg> args = new List<ViewerEffectEventHandlerArg>(length);
5503 for (int i = 0; i < length; i++)
5504 {
5505 //copy the effects block arguments into the event handler arg.
5506 ViewerEffectEventHandlerArg argument = new ViewerEffectEventHandlerArg();
5507 argument.AgentID = viewer.Effect[i].AgentID;
5508 argument.Color = viewer.Effect[i].Color;
5509 argument.Duration = viewer.Effect[i].Duration;
5510 argument.ID = viewer.Effect[i].ID;
5511 argument.Type = viewer.Effect[i].Type;
5512 argument.TypeData = viewer.Effect[i].TypeData;
5513 args.Add(argument);
5514 }
5515
5516 handlerViewerEffect(sender, args);
5517 }
5518
5519 return true;
5520 }
5521
5522 private bool HandleAvatarPropertiesRequest(IClientAPI sender, Packet Pack)
5523 {
5524 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack;
5525
5526 #region Packet Session and User Check
5527 if (m_checkPackets)
5528 {
5529 if (avatarProperties.AgentData.SessionID != SessionId ||
5530 avatarProperties.AgentData.AgentID != AgentId)
5531 return true;
5532 }
5533 #endregion
5534
5535 RequestAvatarProperties handlerRequestAvatarProperties = OnRequestAvatarProperties;
5536 if (handlerRequestAvatarProperties != null)
5537 {
5538 handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID);
5539 }
5540 return true;
5541 }
5542
5543 private bool HandleChatFromViewer(IClientAPI sender, Packet Pack)
5544 {
5545 ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack;
5546
5547 #region Packet Session and User Check
5548 if (m_checkPackets)
5549 {
5550 if (inchatpack.AgentData.SessionID != SessionId ||
5551 inchatpack.AgentData.AgentID != AgentId)
5552 return true;
5553 }
5554 #endregion
5555
5556 string fromName = String.Empty; //ClientAvatar.firstname + " " + ClientAvatar.lastname;
5557 byte[] message = inchatpack.ChatData.Message;
5558 byte type = inchatpack.ChatData.Type;
5559 Vector3 fromPos = new Vector3(); // ClientAvatar.Pos;
5560 // UUID fromAgentID = AgentId;
5561
5562 int channel = inchatpack.ChatData.Channel;
5563
5564 if (OnChatFromClient != null)
5565 {
5566 OSChatMessage args = new OSChatMessage();
5567 args.Channel = channel;
5568 args.From = fromName;
5569 args.Message = Utils.BytesToString(message);
5570 args.Type = (ChatTypeEnum)type;
5571 args.Position = fromPos;
5572
5573 args.Scene = Scene;
5574 args.Sender = this;
5575 args.SenderUUID = this.AgentId;
5576
5577 ChatMessage handlerChatFromClient = OnChatFromClient;
5578 if (handlerChatFromClient != null)
5579 handlerChatFromClient(this, args);
5580 }
5581 return true;
5582 }
5583
5584 private bool HandlerAvatarPropertiesUpdate(IClientAPI sender, Packet Pack)
5585 {
5586 AvatarPropertiesUpdatePacket avatarProps = (AvatarPropertiesUpdatePacket)Pack;
5587
5588 #region Packet Session and User Check
5589 if (m_checkPackets)
5590 {
5591 if (avatarProps.AgentData.SessionID != SessionId ||
5592 avatarProps.AgentData.AgentID != AgentId)
5593 return true;
5594 }
5595 #endregion
5596
5597 UpdateAvatarProperties handlerUpdateAvatarProperties = OnUpdateAvatarProperties;
5598 if (handlerUpdateAvatarProperties != null)
5599 {
5600 AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = avatarProps.PropertiesData;
5601 UserProfileData UserProfile = new UserProfileData();
5602 UserProfile.ID = AgentId;
5603 UserProfile.AboutText = Utils.BytesToString(Properties.AboutText);
5604 UserProfile.FirstLifeAboutText = Utils.BytesToString(Properties.FLAboutText);
5605 UserProfile.FirstLifeImage = Properties.FLImageID;
5606 UserProfile.Image = Properties.ImageID;
5607 UserProfile.ProfileUrl = Utils.BytesToString(Properties.ProfileURL);
5608 UserProfile.UserFlags &= ~3;
5609 UserProfile.UserFlags |= Properties.AllowPublish ? 1 : 0;
5610 UserProfile.UserFlags |= Properties.MaturePublish ? 2 : 0;
5611
5612 handlerUpdateAvatarProperties(this, UserProfile);
5613 }
5614 return true;
5615 }
5616
5617 private bool HandlerScriptDialogReply(IClientAPI sender, Packet Pack)
5618 {
5619 ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack;
5620
5621 //m_log.DebugFormat("[CLIENT]: Received ScriptDialogReply from {0}", rdialog.Data.ObjectID);
5622
5623 #region Packet Session and User Check
5624 if (m_checkPackets)
5625 {
5626 if (rdialog.AgentData.SessionID != SessionId ||
5627 rdialog.AgentData.AgentID != AgentId)
5628 return true;
5629 }
5630 #endregion
5631
5632 int ch = rdialog.Data.ChatChannel;
5633 byte[] msg = rdialog.Data.ButtonLabel;
5634 if (OnChatFromClient != null)
5635 {
5636 OSChatMessage args = new OSChatMessage();
5637 args.Channel = ch;
5638 args.From = String.Empty;
5639 args.Message = Utils.BytesToString(msg);
5640 args.Type = ChatTypeEnum.Shout;
5641 args.Position = new Vector3();
5642 args.Scene = Scene;
5643 args.Sender = this;
5644 ChatMessage handlerChatFromClient2 = OnChatFromClient;
5645 if (handlerChatFromClient2 != null)
5646 handlerChatFromClient2(this, args);
5647 }
5648
5649 return true;
5650 }
5651
5652 private bool HandlerImprovedInstantMessage(IClientAPI sender, Packet Pack)
5653 {
5654 ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack;
5655
5656 #region Packet Session and User Check
5657 if (m_checkPackets)
5658 {
5659 if (msgpack.AgentData.SessionID != SessionId ||
5660 msgpack.AgentData.AgentID != AgentId)
5661 return true;
5662 }
5663 #endregion
5664
5665 string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName);
5666 string IMmessage = Utils.BytesToString(msgpack.MessageBlock.Message);
5667 ImprovedInstantMessage handlerInstantMessage = OnInstantMessage;
5668
5669 if (handlerInstantMessage != null)
5670 {
5671 GridInstantMessage im = new GridInstantMessage(Scene,
5672 msgpack.AgentData.AgentID,
5673 IMfromName,
5674 msgpack.MessageBlock.ToAgentID,
5675 msgpack.MessageBlock.Dialog,
5676 msgpack.MessageBlock.FromGroup,
5677 IMmessage,
5678 msgpack.MessageBlock.ID,
5679 msgpack.MessageBlock.Offline != 0 ? true : false,
5680 msgpack.MessageBlock.Position,
5681 msgpack.MessageBlock.BinaryBucket);
5682
5683 handlerInstantMessage(this, im);
5684 }
5685 return true;
5686
5687 }
5688
5689 private bool HandlerAcceptFriendship(IClientAPI sender, Packet Pack)
5690 {
5691 AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack;
5692
5693 #region Packet Session and User Check
5694 if (m_checkPackets)
5695 {
5696 if (afriendpack.AgentData.SessionID != SessionId ||
5697 afriendpack.AgentData.AgentID != AgentId)
5698 return true;
5699 }
5700 #endregion
5701
5702 // My guess is this is the folder to stick the calling card into
5703 List<UUID> callingCardFolders = new List<UUID>();
5704
5705 UUID agentID = afriendpack.AgentData.AgentID;
5706 UUID transactionID = afriendpack.TransactionBlock.TransactionID;
5707
5708 for (int fi = 0; fi < afriendpack.FolderData.Length; fi++)
5709 {
5710 callingCardFolders.Add(afriendpack.FolderData[fi].FolderID);
5711 }
5712
5713 FriendActionDelegate handlerApproveFriendRequest = OnApproveFriendRequest;
5714 if (handlerApproveFriendRequest != null)
5715 {
5716 handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders);
5717 }
5718 return true;
5719
5720 }
5721
5722 private bool HandlerDeclineFriendship(IClientAPI sender, Packet Pack)
5723 {
5724 DeclineFriendshipPacket dfriendpack = (DeclineFriendshipPacket)Pack;
5725
5726 #region Packet Session and User Check
5727 if (m_checkPackets)
5728 {
5729 if (dfriendpack.AgentData.SessionID != SessionId ||
5730 dfriendpack.AgentData.AgentID != AgentId)
5731 return true;
5732 }
5733 #endregion
5734
5735 if (OnDenyFriendRequest != null)
5736 {
5737 OnDenyFriendRequest(this,
5738 dfriendpack.AgentData.AgentID,
5739 dfriendpack.TransactionBlock.TransactionID,
5740 null);
5741 }
5742 return true;
5743 }
5744
5745 private bool HandlerTerminateFrendship(IClientAPI sender, Packet Pack)
5746 {
5747 TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack;
5748
5749 #region Packet Session and User Check
5750 if (m_checkPackets)
5751 {
5752 if (tfriendpack.AgentData.SessionID != SessionId ||
5753 tfriendpack.AgentData.AgentID != AgentId)
5754 return true;
5755 }
5756 #endregion
5757
5758 UUID listOwnerAgentID = tfriendpack.AgentData.AgentID;
5759 UUID exFriendID = tfriendpack.ExBlock.OtherID;
5760
5761 FriendshipTermination handlerTerminateFriendship = OnTerminateFriendship;
5762 if (handlerTerminateFriendship != null)
5763 {
5764 handlerTerminateFriendship(this, listOwnerAgentID, exFriendID);
5765 }
5766 return true;
5767 }
5768
5769 private bool HandleFindAgent(IClientAPI client, Packet Packet)
5770 {
5771 FindAgentPacket FindAgent =
5772 (FindAgentPacket)Packet;
5773
5774 FindAgentUpdate FindAgentHandler = OnFindAgent;
5775 if (FindAgentHandler != null)
5776 {
5777 FindAgentHandler(this,FindAgent.AgentBlock.Hunter,FindAgent.AgentBlock.Prey);
5778 return true;
5779 }
5780 return false;
5781 }
5782
5783 private bool HandleTrackAgent(IClientAPI client, Packet Packet)
5784 {
5785 TrackAgentPacket TrackAgent =
5786 (TrackAgentPacket)Packet;
5787
5788 TrackAgentUpdate TrackAgentHandler = OnTrackAgent;
5789 if (TrackAgentHandler != null)
5790 {
5791 TrackAgentHandler(this,
5792 TrackAgent.AgentData.AgentID,
5793 TrackAgent.TargetData.PreyID);
5794 return true;
5795 }
5796 return false;
5797 }
5798
5799 private bool HandlerRezObject(IClientAPI sender, Packet Pack)
5800 {
5801 RezObjectPacket rezPacket = (RezObjectPacket)Pack;
5802
5803 #region Packet Session and User Check
5804 if (m_checkPackets)
5805 {
5806 if (rezPacket.AgentData.SessionID != SessionId ||
5807 rezPacket.AgentData.AgentID != AgentId)
5808 return true;
5809 }
5810 #endregion
5811
5812 RezObject handlerRezObject = OnRezObject;
5813 if (handlerRezObject != null)
5814 {
5815 handlerRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd,
5816 rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID,
5817 rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection,
5818 rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem,
5819 rezPacket.RezData.FromTaskID);
5820 }
5821 return true;
5822 }
5823
5824 private bool HandlerDeRezObject(IClientAPI sender, Packet Pack)
5825 {
5826 DeRezObjectPacket DeRezPacket = (DeRezObjectPacket)Pack;
5827
5828 #region Packet Session and User Check
5829 if (m_checkPackets)
5830 {
5831 if (DeRezPacket.AgentData.SessionID != SessionId ||
5832 DeRezPacket.AgentData.AgentID != AgentId)
5833 return true;
5834 }
5835 #endregion
5836
5837 DeRezObject handlerDeRezObject = OnDeRezObject;
5838 if (handlerDeRezObject != null)
5839 {
5840 List<uint> deRezIDs = new List<uint>();
5841
5842 foreach (DeRezObjectPacket.ObjectDataBlock data in
5843 DeRezPacket.ObjectData)
5844 {
5845 deRezIDs.Add(data.ObjectLocalID);
5846 }
5847 // It just so happens that the values on the DeRezAction enumerator match the Destination
5848 // values given by a Second Life client
5849 handlerDeRezObject(this, deRezIDs,
5850 DeRezPacket.AgentBlock.GroupID,
5851 (DeRezAction)DeRezPacket.AgentBlock.Destination,
5852 DeRezPacket.AgentBlock.DestinationID);
5853
5854 }
5855 return true;
5856 }
5857
5858 private bool HandlerModifyLand(IClientAPI sender, Packet Pack)
5859 {
5860 ModifyLandPacket modify = (ModifyLandPacket)Pack;
5861
5862 #region Packet Session and User Check
5863 if (m_checkPackets)
5864 {
5865 if (modify.AgentData.SessionID != SessionId ||
5866 modify.AgentData.AgentID != AgentId)
5867 return true;
5868 }
5869
5870 #endregion
5871 //m_log.Info("[LAND]: LAND:" + modify.ToString());
5872 if (modify.ParcelData.Length > 0)
5873 {
5874 if (OnModifyTerrain != null)
5875 {
5876 for (int i = 0; i < modify.ParcelData.Length; i++)
5877 {
5878 ModifyTerrain handlerModifyTerrain = OnModifyTerrain;
5879 if (handlerModifyTerrain != null)
5880 {
5881 handlerModifyTerrain(AgentId, modify.ModifyBlock.Height, modify.ModifyBlock.Seconds,
5882 modify.ModifyBlock.BrushSize,
5883 modify.ModifyBlock.Action, modify.ParcelData[i].North,
5884 modify.ParcelData[i].West, modify.ParcelData[i].South,
5885 modify.ParcelData[i].East, AgentId);
5886 }
5887 }
5888 }
5889 }
5890
5891 return true;
5892 }
5893
5894 private bool HandlerRegionHandshakeReply(IClientAPI sender, Packet Pack)
5895 {
5896 Action<IClientAPI> handlerRegionHandShakeReply = OnRegionHandShakeReply;
5897 if (handlerRegionHandShakeReply != null)
5898 {
5899 handlerRegionHandShakeReply(this);
5900 }
5901
5902 return true;
5903 }
5904
5905 private bool HandlerAgentWearablesRequest(IClientAPI sender, Packet Pack)
5906 {
5907 GenericCall1 handlerRequestWearables = OnRequestWearables;
5908
5909 if (handlerRequestWearables != null)
5910 {
5911 handlerRequestWearables(sender);
5912 }
5913
5914 Action<IClientAPI> handlerRequestAvatarsData = OnRequestAvatarsData;
5915
5916 if (handlerRequestAvatarsData != null)
5917 {
5918 handlerRequestAvatarsData(this);
5919 }
5920
5921 return true;
5922 }
5923
5924 private bool HandlerAgentSetAppearance(IClientAPI sender, Packet Pack)
5925 {
5926 AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack;
5927
5928 #region Packet Session and User Check
5929 if (m_checkPackets)
5930 {
5931 if (appear.AgentData.SessionID != SessionId ||
5932 appear.AgentData.AgentID != AgentId)
5933 return true;
5934 }
5935 #endregion
5936
5937 SetAppearance handlerSetAppearance = OnSetAppearance;
5938 if (handlerSetAppearance != null)
5939 {
5940 // Temporarily protect ourselves from the mantis #951 failure.
5941 // However, we could do this for several other handlers where a failure isn't terminal
5942 // for the client session anyway, in order to protect ourselves against bad code in plugins
5943 try
5944 {
5945
5946 byte[] visualparams = new byte[appear.VisualParam.Length];
5947 for (int i = 0; i < appear.VisualParam.Length; i++)
5948 visualparams[i] = appear.VisualParam[i].ParamValue;
5949
5950 Primitive.TextureEntry te = null;
5951 if (appear.ObjectData.TextureEntry.Length > 1)
5952 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length);
5953
5954 handlerSetAppearance(sender, te, visualparams);
5955 }
5956 catch (Exception e)
5957 {
5958 m_log.ErrorFormat(
5959 "[CLIENT VIEW]: AgentSetApperance packet handler threw an exception, {0}",
5960 e);
5961 }
5962 }
5963
5964 return true;
5965 }
5966
5967 private bool HandlerAgentIsNowWearing(IClientAPI sender, Packet Pack)
5968 {
5969 if (OnAvatarNowWearing != null)
5970 {
5971 AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack;
5972
5973 #region Packet Session and User Check
5974 if (m_checkPackets)
5975 {
5976 if (nowWearing.AgentData.SessionID != SessionId ||
5977 nowWearing.AgentData.AgentID != AgentId)
5978 return true;
5979 }
5980 #endregion
5981
5982 AvatarWearingArgs wearingArgs = new AvatarWearingArgs();
5983 for (int i = 0; i < nowWearing.WearableData.Length; i++)
5984 {
5985 m_log.DebugFormat("[XXX]: Wearable type {0} item {1}", nowWearing.WearableData[i].WearableType, nowWearing.WearableData[i].ItemID);
5986 AvatarWearingArgs.Wearable wearable =
5987 new AvatarWearingArgs.Wearable(nowWearing.WearableData[i].ItemID,
5988 nowWearing.WearableData[i].WearableType);
5989 wearingArgs.NowWearing.Add(wearable);
5990 }
5991
5992 AvatarNowWearing handlerAvatarNowWearing = OnAvatarNowWearing;
5993 if (handlerAvatarNowWearing != null)
5994 {
5995 handlerAvatarNowWearing(this, wearingArgs);
5996 }
5997 }
5998 return true;
5999 }
6000
6001 private bool HandlerRezSingleAttachmentFromInv(IClientAPI sender, Packet Pack)
6002 {
6003 RezSingleAttachmentFromInv handlerRezSingleAttachment = OnRezSingleAttachmentFromInv;
6004 if (handlerRezSingleAttachment != null)
6005 {
6006 RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack;
6007
6008 #region Packet Session and User Check
6009 if (m_checkPackets)
6010 {
6011 if (rez.AgentData.SessionID != SessionId ||
6012 rez.AgentData.AgentID != AgentId)
6013 return true;
6014 }
6015 #endregion
6016
6017 handlerRezSingleAttachment(this, rez.ObjectData.ItemID,
6018 rez.ObjectData.AttachmentPt);
6019 }
6020
6021 return true;
6022 }
6023
6024 private bool HandleRezMultipleAttachmentsFromInv(IClientAPI sender, Packet Pack)
6025 {
6026 RezMultipleAttachmentsFromInv handlerRezMultipleAttachments = OnRezMultipleAttachmentsFromInv;
6027 if (handlerRezMultipleAttachments != null)
6028 {
6029 RezMultipleAttachmentsFromInvPacket rez = (RezMultipleAttachmentsFromInvPacket)Pack;
6030 handlerRezMultipleAttachments(this, rez.HeaderData,
6031 rez.ObjectData);
6032 }
6033
6034 return true;
6035 }
6036
6037 private bool HandleDetachAttachmentIntoInv(IClientAPI sender, Packet Pack)
6038 {
6039 UUIDNameRequest handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv;
6040 if (handlerDetachAttachmentIntoInv != null)
6041 {
6042 DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack;
6043
6044 #region Packet Session and User Check
6045 // UNSUPPORTED ON THIS PACKET
6046 #endregion
6047
6048 UUID itemID = detachtoInv.ObjectData.ItemID;
6049 // UUID ATTACH_agentID = detachtoInv.ObjectData.AgentID;
6050
6051 handlerDetachAttachmentIntoInv(itemID, this);
6052 }
6053 return true;
6054 }
6055
6056 private bool HandleObjectAttach(IClientAPI sender, Packet Pack)
6057 {
6058 if (OnObjectAttach != null)
6059 {
6060 ObjectAttachPacket att = (ObjectAttachPacket)Pack;
6061
6062 #region Packet Session and User Check
6063 if (m_checkPackets)
6064 {
6065 if (att.AgentData.SessionID != SessionId ||
6066 att.AgentData.AgentID != AgentId)
6067 return true;
6068 }
6069 #endregion
6070
6071 ObjectAttach handlerObjectAttach = OnObjectAttach;
6072
6073 if (handlerObjectAttach != null)
6074 {
6075 if (att.ObjectData.Length > 0)
6076 {
6077 handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, false);
6078 }
6079 }
6080 }
6081 return true;
6082 }
6083
6084 private bool HandleObjectDetach(IClientAPI sender, Packet Pack)
6085 {
6086 ObjectDetachPacket dett = (ObjectDetachPacket)Pack;
6087
6088 #region Packet Session and User Check
6089 if (m_checkPackets)
6090 {
6091 if (dett.AgentData.SessionID != SessionId ||
6092 dett.AgentData.AgentID != AgentId)
6093 return true;
6094 }
6095 #endregion
6096
6097 for (int j = 0; j < dett.ObjectData.Length; j++)
6098 {
6099 uint obj = dett.ObjectData[j].ObjectLocalID;
6100 ObjectDeselect handlerObjectDetach = OnObjectDetach;
6101 if (handlerObjectDetach != null)
6102 {
6103 handlerObjectDetach(obj, this);
6104 }
6105
6106 }
6107 return true;
6108 }
6109
6110 private bool HandleObjectDrop(IClientAPI sender, Packet Pack)
6111 {
6112 ObjectDropPacket dropp = (ObjectDropPacket)Pack;
6113
6114 #region Packet Session and User Check
6115 if (m_checkPackets)
6116 {
6117 if (dropp.AgentData.SessionID != SessionId ||
6118 dropp.AgentData.AgentID != AgentId)
6119 return true;
6120 }
6121 #endregion
6122
6123 for (int j = 0; j < dropp.ObjectData.Length; j++)
6124 {
6125 uint obj = dropp.ObjectData[j].ObjectLocalID;
6126 ObjectDrop handlerObjectDrop = OnObjectDrop;
6127 if (handlerObjectDrop != null)
6128 {
6129 handlerObjectDrop(obj, this);
6130 }
6131 }
6132 return true;
6133 }
6134
6135 private bool HandleSetAlwaysRun(IClientAPI sender, Packet Pack)
6136 {
6137 SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack;
6138
6139 #region Packet Session and User Check
6140 if (m_checkPackets)
6141 {
6142 if (run.AgentData.SessionID != SessionId ||
6143 run.AgentData.AgentID != AgentId)
6144 return true;
6145 }
6146 #endregion
6147
6148 SetAlwaysRun handlerSetAlwaysRun = OnSetAlwaysRun;
6149 if (handlerSetAlwaysRun != null)
6150 handlerSetAlwaysRun(this, run.AgentData.AlwaysRun);
6151
6152 return true;
6153 }
6154
6155 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack)
6156 {
6157 GenericCall1 handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
6158 if (handlerCompleteMovementToRegion != null)
6159 {
6160 handlerCompleteMovementToRegion(sender);
6161 }
6162 handlerCompleteMovementToRegion = null;
6163
6164 return true;
6165 }
6166
6167 private bool HandleAgentAnimation(IClientAPI sender, Packet Pack)
6168 {
6169 AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack;
6170
6171 #region Packet Session and User Check
6172 if (m_checkPackets)
6173 {
6174 if (AgentAni.AgentData.SessionID != SessionId ||
6175 AgentAni.AgentData.AgentID != AgentId)
6176 return true;
6177 }
6178 #endregion
6179
6180 StartAnim handlerStartAnim = null;
6181 StopAnim handlerStopAnim = null;
6182
6183 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
6184 {
6185 if (AgentAni.AnimationList[i].StartAnim)
6186 {
6187 handlerStartAnim = OnStartAnim;
6188 if (handlerStartAnim != null)
6189 {
6190 handlerStartAnim(this, AgentAni.AnimationList[i].AnimID);
6191 }
6192 }
6193 else
6194 {
6195 handlerStopAnim = OnStopAnim;
6196 if (handlerStopAnim != null)
6197 {
6198 handlerStopAnim(this, AgentAni.AnimationList[i].AnimID);
6199 }
6200 }
6201 }
6202 return true;
6203 }
6204
6205 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack)
6206 {
6207 if (OnAgentRequestSit != null)
6208 {
6209 AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket)Pack;
6210
6211 #region Packet Session and User Check
6212 if (m_checkPackets)
6213 {
6214 if (agentRequestSit.AgentData.SessionID != SessionId ||
6215 agentRequestSit.AgentData.AgentID != AgentId)
6216 return true;
6217 }
6218 #endregion
6219
6220 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit;
6221 if (handlerAgentRequestSit != null)
6222 handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID,
6223 agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset);
6224 }
6225 return true;
6226 }
6227
6228 private bool HandleAgentSit(IClientAPI sender, Packet Pack)
6229 {
6230 if (OnAgentSit != null)
6231 {
6232 AgentSitPacket agentSit = (AgentSitPacket)Pack;
6233
6234 #region Packet Session and User Check
6235 if (m_checkPackets)
6236 {
6237 if (agentSit.AgentData.SessionID != SessionId ||
6238 agentSit.AgentData.AgentID != AgentId)
6239 return true;
6240 }
6241 #endregion
6242
6243 AgentSit handlerAgentSit = OnAgentSit;
6244 if (handlerAgentSit != null)
6245 {
6246 OnAgentSit(this, agentSit.AgentData.AgentID);
6247 }
6248 }
6249 return true;
6250 }
6251
6252 private bool HandleSoundTrigger(IClientAPI sender, Packet Pack)
6253 {
6254 SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack;
6255
6256 #region Packet Session and User Check
6257 if (m_checkPackets)
6258 {
6259 // UNSUPPORTED ON THIS PACKET
6260 }
6261 #endregion
6262
6263 SoundTrigger handlerSoundTrigger = OnSoundTrigger;
6264 if (handlerSoundTrigger != null)
6265 {
6266 // UUIDS are sent as zeroes by the client, substitute agent's id
6267 handlerSoundTrigger(soundTriggerPacket.SoundData.SoundID, AgentId,
6268 AgentId, AgentId,
6269 soundTriggerPacket.SoundData.Gain, soundTriggerPacket.SoundData.Position,
6270 soundTriggerPacket.SoundData.Handle, 0);
6271
6272 }
6273 return true;
6274 }
6275
6276 private bool HandleAvatarPickerRequest(IClientAPI sender, Packet Pack)
6277 {
6278 AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack;
6279
6280 #region Packet Session and User Check
6281 if (m_checkPackets)
6282 {
6283 if (avRequestQuery.AgentData.SessionID != SessionId ||
6284 avRequestQuery.AgentData.AgentID != AgentId)
6285 return true;
6286 }
6287 #endregion
6288
6289 AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData;
6290 AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data;
6291 //m_log.Debug("Agent Sends:" + Utils.BytesToString(querydata.Name));
6292
6293 AvatarPickerRequest handlerAvatarPickerRequest = OnAvatarPickerRequest;
6294 if (handlerAvatarPickerRequest != null)
6295 {
6296 handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID,
6297 Utils.BytesToString(querydata.Name));
6298 }
6299 return true;
6300 }
6301
6302 private bool HandleAgentDataUpdateRequest(IClientAPI sender, Packet Pack)
6303 {
6304 AgentDataUpdateRequestPacket avRequestDataUpdatePacket = (AgentDataUpdateRequestPacket)Pack;
6305
6306 #region Packet Session and User Check
6307 if (m_checkPackets)
6308 {
6309 if (avRequestDataUpdatePacket.AgentData.SessionID != SessionId ||
6310 avRequestDataUpdatePacket.AgentData.AgentID != AgentId)
6311 return true;
6312 }
6313 #endregion
6314
6315 FetchInventory handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest;
6316
6317 if (handlerAgentDataUpdateRequest != null)
6318 {
6319 handlerAgentDataUpdateRequest(this, avRequestDataUpdatePacket.AgentData.AgentID, avRequestDataUpdatePacket.AgentData.SessionID);
6320 }
6321
6322 return true;
6323 }
6324
6325 private bool HandleUserInfoRequest(IClientAPI sender, Packet Pack)
6326 {
6327 UserInfoRequest handlerUserInfoRequest = OnUserInfoRequest;
6328 if (handlerUserInfoRequest != null)
6329 {
6330 handlerUserInfoRequest(this);
6331 }
6332 else
6333 {
6334 SendUserInfoReply(false, true, "");
6335 }
6336 return true;
6337
6338 }
6339
6340 private bool HandleUpdateUserInfo(IClientAPI sender, Packet Pack)
6341 {
6342 UpdateUserInfoPacket updateUserInfo = (UpdateUserInfoPacket)Pack;
6343
6344 #region Packet Session and User Check
6345 if (m_checkPackets)
6346 {
6347 if (updateUserInfo.AgentData.SessionID != SessionId ||
6348 updateUserInfo.AgentData.AgentID != AgentId)
6349 return true;
6350 }
6351 #endregion
6352
6353 UpdateUserInfo handlerUpdateUserInfo = OnUpdateUserInfo;
6354 if (handlerUpdateUserInfo != null)
6355 {
6356 bool visible = true;
6357 string DirectoryVisibility =
6358 Utils.BytesToString(updateUserInfo.UserData.DirectoryVisibility);
6359 if (DirectoryVisibility == "hidden")
6360 visible = false;
6361
6362 handlerUpdateUserInfo(
6363 updateUserInfo.UserData.IMViaEMail,
6364 visible, this);
6365 }
6366 return true;
6367 }
6368
6369 private bool HandleSetStartLocationRequest(IClientAPI sender, Packet Pack)
6370 {
6371 SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack;
6372
6373 #region Packet Session and User Check
6374 if (m_checkPackets)
6375 {
6376 if (avSetStartLocationRequestPacket.AgentData.SessionID != SessionId ||
6377 avSetStartLocationRequestPacket.AgentData.AgentID != AgentId)
6378 return true;
6379 }
6380 #endregion
6381
6382 if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId)
6383 {
6384 // Linden Client limitation..
6385 if (avSetStartLocationRequestPacket.StartLocationData.LocationPos.X == 255.5f
6386 || avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y == 255.5f)
6387 {
6388 ScenePresence avatar = null;
6389 if (((Scene)m_scene).TryGetScenePresence(AgentId, out avatar))
6390 {
6391 if (avSetStartLocationRequestPacket.StartLocationData.LocationPos.X == 255.5f)
6392 {
6393 avSetStartLocationRequestPacket.StartLocationData.LocationPos.X = avatar.AbsolutePosition.X;
6394 }
6395 if (avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y == 255.5f)
6396 {
6397 avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y = avatar.AbsolutePosition.Y;
6398 }
6399 }
6400
6401 }
6402 TeleportLocationRequest handlerSetStartLocationRequest = OnSetStartLocationRequest;
6403 if (handlerSetStartLocationRequest != null)
6404 {
6405 handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos,
6406 avSetStartLocationRequestPacket.StartLocationData.LocationLookAt,
6407 avSetStartLocationRequestPacket.StartLocationData.LocationID);
6408 }
6409 }
6410 return true;
6411 }
6412
6413 private bool HandleAgentThrottle(IClientAPI sender, Packet Pack)
6414 {
6415 AgentThrottlePacket atpack = (AgentThrottlePacket)Pack;
6416
6417 #region Packet Session and User Check
6418 if (m_checkPackets)
6419 {
6420 if (atpack.AgentData.SessionID != SessionId ||
6421 atpack.AgentData.AgentID != AgentId)
6422 return true;
6423 }
6424 #endregion
6425
6426 m_udpClient.SetThrottles(atpack.Throttle.Throttles);
6427 return true;
6428 }
6429
6430 private bool HandleAgentPause(IClientAPI sender, Packet Pack)
6431 {
6432 m_udpClient.IsPaused = true;
6433 return true;
6434 }
6435
6436 private bool HandleAgentResume(IClientAPI sender, Packet Pack)
6437 {
6438 m_udpClient.IsPaused = false;
6439 SendStartPingCheck(m_udpClient.CurrentPingSequence++);
6440 return true;
6441 }
6442
6443 private bool HandleForceScriptControlRelease(IClientAPI sender, Packet Pack)
6444 {
6445 ForceReleaseControls handlerForceReleaseControls = OnForceReleaseControls;
6446 if (handlerForceReleaseControls != null)
6447 {
6448 handlerForceReleaseControls(this, AgentId);
6449 }
6450 return true;
6451 }
6452
6453 #endregion Scene/Avatar
6454
6455 #region Objects/m_sceneObjects
6456
6457 private bool HandleObjectLink(IClientAPI sender, Packet Pack)
6458 {
6459 ObjectLinkPacket link = (ObjectLinkPacket)Pack;
6460
6461 #region Packet Session and User Check
6462 if (m_checkPackets)
6463 {
6464 if (link.AgentData.SessionID != SessionId ||
6465 link.AgentData.AgentID != AgentId)
6466 return true;
6467 }
6468 #endregion
6469
6470 uint parentprimid = 0;
6471 List<uint> childrenprims = new List<uint>();
6472 if (link.ObjectData.Length > 1)
6473 {
6474 parentprimid = link.ObjectData[0].ObjectLocalID;
6475
6476 for (int i = 1; i < link.ObjectData.Length; i++)
6477 {
6478 childrenprims.Add(link.ObjectData[i].ObjectLocalID);
6479 }
6480 }
6481 LinkObjects handlerLinkObjects = OnLinkObjects;
6482 if (handlerLinkObjects != null)
6483 {
6484 handlerLinkObjects(this, parentprimid, childrenprims);
6485 }
6486 return true;
6487 }
6488
6489 private bool HandleObjectDelink(IClientAPI sender, Packet Pack)
6490 {
6491 ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack;
6492
6493 #region Packet Session and User Check
6494 if (m_checkPackets)
6495 {
6496 if (delink.AgentData.SessionID != SessionId ||
6497 delink.AgentData.AgentID != AgentId)
6498 return true;
6499 }
6500 #endregion
6501
6502 // It appears the prim at index 0 is not always the root prim (for
6503 // instance, when one prim of a link set has been edited independently
6504 // of the others). Therefore, we'll pass all the ids onto the delink
6505 // method for it to decide which is the root.
6506 List<uint> prims = new List<uint>();
6507 for (int i = 0; i < delink.ObjectData.Length; i++)
6508 {
6509 prims.Add(delink.ObjectData[i].ObjectLocalID);
6510 }
6511 DelinkObjects handlerDelinkObjects = OnDelinkObjects;
6512 if (handlerDelinkObjects != null)
6513 {
6514 handlerDelinkObjects(prims, this);
6515 }
6516
6517 return true;
6518 }
6519
6520 private bool HandleObjectAdd(IClientAPI sender, Packet Pack)
6521 {
6522 if (OnAddPrim != null)
6523 {
6524 ObjectAddPacket addPacket = (ObjectAddPacket)Pack;
6525
6526 #region Packet Session and User Check
6527 if (m_checkPackets)
6528 {
6529 if (addPacket.AgentData.SessionID != SessionId ||
6530 addPacket.AgentData.AgentID != AgentId)
6531 return true;
6532 }
6533 #endregion
6534
6535 PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket);
6536 // m_log.Info("[REZData]: " + addPacket.ToString());
6537 //BypassRaycast: 1
6538 //RayStart: <69.79469, 158.2652, 98.40343>
6539 //RayEnd: <61.97724, 141.995, 92.58341>
6540 //RayTargetID: 00000000-0000-0000-0000-000000000000
6541
6542 //Check to see if adding the prim is allowed; useful for any module wanting to restrict the
6543 //object from rezing initially
6544
6545 AddNewPrim handlerAddPrim = OnAddPrim;
6546 if (handlerAddPrim != null)
6547 handlerAddPrim(AgentId, ActiveGroupId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection);
6548 }
6549 return true;
6550 }
6551
6552 private bool HandleObjectShape(IClientAPI sender, Packet Pack)
6553 {
6554 ObjectShapePacket shapePacket = (ObjectShapePacket)Pack;
6555
6556 #region Packet Session and User Check
6557 if (m_checkPackets)
6558 {
6559 if (shapePacket.AgentData.SessionID != SessionId ||
6560 shapePacket.AgentData.AgentID != AgentId)
6561 return true;
6562 }
6563 #endregion
6564
6565 UpdateShape handlerUpdatePrimShape = null;
6566 for (int i = 0; i < shapePacket.ObjectData.Length; i++)
6567 {
6568 handlerUpdatePrimShape = OnUpdatePrimShape;
6569 if (handlerUpdatePrimShape != null)
6570 {
6571 UpdateShapeArgs shapeData = new UpdateShapeArgs();
6572 shapeData.ObjectLocalID = shapePacket.ObjectData[i].ObjectLocalID;
6573 shapeData.PathBegin = shapePacket.ObjectData[i].PathBegin;
6574 shapeData.PathCurve = shapePacket.ObjectData[i].PathCurve;
6575 shapeData.PathEnd = shapePacket.ObjectData[i].PathEnd;
6576 shapeData.PathRadiusOffset = shapePacket.ObjectData[i].PathRadiusOffset;
6577 shapeData.PathRevolutions = shapePacket.ObjectData[i].PathRevolutions;
6578 shapeData.PathScaleX = shapePacket.ObjectData[i].PathScaleX;
6579 shapeData.PathScaleY = shapePacket.ObjectData[i].PathScaleY;
6580 shapeData.PathShearX = shapePacket.ObjectData[i].PathShearX;
6581 shapeData.PathShearY = shapePacket.ObjectData[i].PathShearY;
6582 shapeData.PathSkew = shapePacket.ObjectData[i].PathSkew;
6583 shapeData.PathTaperX = shapePacket.ObjectData[i].PathTaperX;
6584 shapeData.PathTaperY = shapePacket.ObjectData[i].PathTaperY;
6585 shapeData.PathTwist = shapePacket.ObjectData[i].PathTwist;
6586 shapeData.PathTwistBegin = shapePacket.ObjectData[i].PathTwistBegin;
6587 shapeData.ProfileBegin = shapePacket.ObjectData[i].ProfileBegin;
6588 shapeData.ProfileCurve = shapePacket.ObjectData[i].ProfileCurve;
6589 shapeData.ProfileEnd = shapePacket.ObjectData[i].ProfileEnd;
6590 shapeData.ProfileHollow = shapePacket.ObjectData[i].ProfileHollow;
6591
6592 handlerUpdatePrimShape(m_agentId, shapePacket.ObjectData[i].ObjectLocalID,
6593 shapeData);
6594 }
6595 }
6596 return true;
6597 }
6598
6599 private bool HandleObjectExtraParams(IClientAPI sender, Packet Pack)
6600 {
6601 ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack;
6602
6603 #region Packet Session and User Check
6604 if (m_checkPackets)
6605 {
6606 if (extraPar.AgentData.SessionID != SessionId ||
6607 extraPar.AgentData.AgentID != AgentId)
6608 return true;
6609 }
6610 #endregion
6611
6612 ObjectExtraParams handlerUpdateExtraParams = OnUpdateExtraParams;
6613 if (handlerUpdateExtraParams != null)
6614 {
6615 for (int i = 0; i < extraPar.ObjectData.Length; i++)
6616 {
6617 handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[i].ObjectLocalID,
6618 extraPar.ObjectData[i].ParamType,
6619 extraPar.ObjectData[i].ParamInUse, extraPar.ObjectData[i].ParamData);
6620 }
6621 }
6622 return true;
6623 }
6624
6625 private bool HandleObjectDuplicate(IClientAPI sender, Packet Pack)
6626 {
6627 ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack;
6628
6629 #region Packet Session and User Check
6630 if (m_checkPackets)
6631 {
6632 if (dupe.AgentData.SessionID != SessionId ||
6633 dupe.AgentData.AgentID != AgentId)
6634 return true;
6635 }
6636 #endregion
6637
6638// ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData;
6639
6640 ObjectDuplicate handlerObjectDuplicate = null;
6641
6642 for (int i = 0; i < dupe.ObjectData.Length; i++)
6643 {
6644 handlerObjectDuplicate = OnObjectDuplicate;
6645 if (handlerObjectDuplicate != null)
6646 {
6647 handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset,
6648 dupe.SharedData.DuplicateFlags, AgentId,
6649 m_activeGroupID);
6650 }
6651 }
6652
6653 return true;
6654 }
6655
6656 private bool HandleRequestMultipleObjects(IClientAPI sender, Packet Pack)
6657 {
6658 RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack;
6659
6660 #region Packet Session and User Check
6661 if (m_checkPackets)
6662 {
6663 if (incomingRequest.AgentData.SessionID != SessionId ||
6664 incomingRequest.AgentData.AgentID != AgentId)
6665 return true;
6666 }
6667 #endregion
6668
6669 ObjectRequest handlerObjectRequest = null;
6670
6671 for (int i = 0; i < incomingRequest.ObjectData.Length; i++)
6672 {
6673 handlerObjectRequest = OnObjectRequest;
6674 if (handlerObjectRequest != null)
6675 {
6676 handlerObjectRequest(incomingRequest.ObjectData[i].ID, this);
6677 }
6678 }
6679 return true;
6680 }
6681
6682 private bool HandleObjectSelect(IClientAPI sender, Packet Pack)
6683 {
6684 ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack;
6685
6686 #region Packet Session and User Check
6687 if (m_checkPackets)
6688 {
6689 if (incomingselect.AgentData.SessionID != SessionId ||
6690 incomingselect.AgentData.AgentID != AgentId)
6691 return true;
6692 }
6693 #endregion
6694
6695 ObjectSelect handlerObjectSelect = null;
6696
6697 for (int i = 0; i < incomingselect.ObjectData.Length; i++)
6698 {
6699 handlerObjectSelect = OnObjectSelect;
6700 if (handlerObjectSelect != null)
6701 {
6702 handlerObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this);
6703 }
6704 }
6705 return true;
6706 }
6707
6708 private bool HandleObjectDeselect(IClientAPI sender, Packet Pack)
6709 {
6710 ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack;
6711
6712 #region Packet Session and User Check
6713 if (m_checkPackets)
6714 {
6715 if (incomingdeselect.AgentData.SessionID != SessionId ||
6716 incomingdeselect.AgentData.AgentID != AgentId)
6717 return true;
6718 }
6719 #endregion
6720
6721 ObjectDeselect handlerObjectDeselect = null;
6722
6723 for (int i = 0; i < incomingdeselect.ObjectData.Length; i++)
6724 {
6725 handlerObjectDeselect = OnObjectDeselect;
6726 if (handlerObjectDeselect != null)
6727 {
6728 OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this);
6729 }
6730 }
6731 return true;
6732 }
6733
6734 private bool HandleObjectPosition(IClientAPI sender, Packet Pack)
6735 {
6736 // DEPRECATED: but till libsecondlife removes it, people will use it
6737 ObjectPositionPacket position = (ObjectPositionPacket)Pack;
6738
6739 #region Packet Session and User Check
6740 if (m_checkPackets)
6741 {
6742 if (position.AgentData.SessionID != SessionId ||
6743 position.AgentData.AgentID != AgentId)
6744 return true;
6745 }
6746 #endregion
6747
6748
6749 for (int i = 0; i < position.ObjectData.Length; i++)
6750 {
6751 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition;
6752 if (handlerUpdateVector != null)
6753 handlerUpdateVector(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, this);
6754 }
6755
6756 return true;
6757 }
6758
6759 private bool HandleObjectScale(IClientAPI sender, Packet Pack)
6760 {
6761 // DEPRECATED: but till libsecondlife removes it, people will use it
6762 ObjectScalePacket scale = (ObjectScalePacket)Pack;
6763
6764 #region Packet Session and User Check
6765 if (m_checkPackets)
6766 {
6767 if (scale.AgentData.SessionID != SessionId ||
6768 scale.AgentData.AgentID != AgentId)
6769 return true;
6770 }
6771 #endregion
6772
6773 for (int i = 0; i < scale.ObjectData.Length; i++)
6774 {
6775 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
6776 if (handlerUpdatePrimGroupScale != null)
6777 handlerUpdatePrimGroupScale(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, this);
6778 }
6779
6780 return true;
6781 }
6782
6783 private bool HandleObjectRotation(IClientAPI sender, Packet Pack)
6784 {
6785 // DEPRECATED: but till libsecondlife removes it, people will use it
6786 ObjectRotationPacket rotation = (ObjectRotationPacket)Pack;
6787
6788 #region Packet Session and User Check
6789 if (m_checkPackets)
6790 {
6791 if (rotation.AgentData.SessionID != SessionId ||
6792 rotation.AgentData.AgentID != AgentId)
6793 return true;
6794 }
6795 #endregion
6796
6797 for (int i = 0; i < rotation.ObjectData.Length; i++)
6798 {
6799 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation;
6800 if (handlerUpdatePrimRotation != null)
6801 handlerUpdatePrimRotation(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, this);
6802 }
6803
6804 return true;
6805 }
6806
6807 private bool HandleObjectFlagUpdate(IClientAPI sender, Packet Pack)
6808 {
6809 ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack;
6810
6811 #region Packet Session and User Check
6812 if (m_checkPackets)
6813 {
6814 if (flags.AgentData.SessionID != SessionId ||
6815 flags.AgentData.AgentID != AgentId)
6816 return true;
6817 }
6818 #endregion
6819
6820 UpdatePrimFlags handlerUpdatePrimFlags = OnUpdatePrimFlags;
6821
6822 if (handlerUpdatePrimFlags != null)
6823 {
6824 byte[] data = Pack.ToBytes();
6825 // 46,47,48 are special positions within the packet
6826 // This may change so perhaps we need a better way
6827 // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?)
6828 bool UsePhysics = (data[46] != 0) ? true : false;
6829 bool IsTemporary = (data[47] != 0) ? true : false;
6830 bool IsPhantom = (data[48] != 0) ? true : false;
6831 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this);
6832 }
6833 return true;
6834 }
6835
6836 private bool HandleObjectImage(IClientAPI sender, Packet Pack)
6837 {
6838 ObjectImagePacket imagePack = (ObjectImagePacket)Pack;
6839
6840 UpdatePrimTexture handlerUpdatePrimTexture = null;
6841 for (int i = 0; i < imagePack.ObjectData.Length; i++)
6842 {
6843 handlerUpdatePrimTexture = OnUpdatePrimTexture;
6844 if (handlerUpdatePrimTexture != null)
6845 {
6846 handlerUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID,
6847 imagePack.ObjectData[i].TextureEntry, this);
6848 }
6849 }
6850 return true;
6851 }
6852
6853 private bool HandleObjectGrab(IClientAPI sender, Packet Pack)
6854 {
6855 ObjectGrabPacket grab = (ObjectGrabPacket)Pack;
6856
6857 #region Packet Session and User Check
6858 if (m_checkPackets)
6859 {
6860 if (grab.AgentData.SessionID != SessionId ||
6861 grab.AgentData.AgentID != AgentId)
6862 return true;
6863 }
6864 #endregion
6865
6866 GrabObject handlerGrabObject = OnGrabObject;
6867
6868 if (handlerGrabObject != null)
6869 {
6870 List<SurfaceTouchEventArgs> touchArgs = new List<SurfaceTouchEventArgs>();
6871 if ((grab.SurfaceInfo != null) && (grab.SurfaceInfo.Length > 0))
6872 {
6873 foreach (ObjectGrabPacket.SurfaceInfoBlock surfaceInfo in grab.SurfaceInfo)
6874 {
6875 SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs();
6876 arg.Binormal = surfaceInfo.Binormal;
6877 arg.FaceIndex = surfaceInfo.FaceIndex;
6878 arg.Normal = surfaceInfo.Normal;
6879 arg.Position = surfaceInfo.Position;
6880 arg.STCoord = surfaceInfo.STCoord;
6881 arg.UVCoord = surfaceInfo.UVCoord;
6882 touchArgs.Add(arg);
6883 }
6884 }
6885 handlerGrabObject(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, this, touchArgs);
6886 }
6887 return true;
6888 }
6889
6890 private bool HandleObjectGrabUpdate(IClientAPI sender, Packet Pack)
6891 {
6892 ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack;
6893
6894 #region Packet Session and User Check
6895 if (m_checkPackets)
6896 {
6897 if (grabUpdate.AgentData.SessionID != SessionId ||
6898 grabUpdate.AgentData.AgentID != AgentId)
6899 return true;
6900 }
6901 #endregion
6902
6903 MoveObject handlerGrabUpdate = OnGrabUpdate;
6904
6905 if (handlerGrabUpdate != null)
6906 {
6907 List<SurfaceTouchEventArgs> touchArgs = new List<SurfaceTouchEventArgs>();
6908 if ((grabUpdate.SurfaceInfo != null) && (grabUpdate.SurfaceInfo.Length > 0))
6909 {
6910 foreach (ObjectGrabUpdatePacket.SurfaceInfoBlock surfaceInfo in grabUpdate.SurfaceInfo)
6911 {
6912 SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs();
6913 arg.Binormal = surfaceInfo.Binormal;
6914 arg.FaceIndex = surfaceInfo.FaceIndex;
6915 arg.Normal = surfaceInfo.Normal;
6916 arg.Position = surfaceInfo.Position;
6917 arg.STCoord = surfaceInfo.STCoord;
6918 arg.UVCoord = surfaceInfo.UVCoord;
6919 touchArgs.Add(arg);
6920 }
6921 }
6922 handlerGrabUpdate(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial,
6923 grabUpdate.ObjectData.GrabPosition, this, touchArgs);
6924 }
6925 return true;
6926 }
6927
6928 private bool HandleObjectDeGrab(IClientAPI sender, Packet Pack)
6929 {
6930 ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack;
6931
6932 #region Packet Session and User Check
6933 if (m_checkPackets)
6934 {
6935 if (deGrab.AgentData.SessionID != SessionId ||
6936 deGrab.AgentData.AgentID != AgentId)
6937 return true;
6938 }
6939 #endregion
6940
6941 DeGrabObject handlerDeGrabObject = OnDeGrabObject;
6942 if (handlerDeGrabObject != null)
6943 {
6944 List<SurfaceTouchEventArgs> touchArgs = new List<SurfaceTouchEventArgs>();
6945 if ((deGrab.SurfaceInfo != null) && (deGrab.SurfaceInfo.Length > 0))
6946 {
6947 foreach (ObjectDeGrabPacket.SurfaceInfoBlock surfaceInfo in deGrab.SurfaceInfo)
6948 {
6949 SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs();
6950 arg.Binormal = surfaceInfo.Binormal;
6951 arg.FaceIndex = surfaceInfo.FaceIndex;
6952 arg.Normal = surfaceInfo.Normal;
6953 arg.Position = surfaceInfo.Position;
6954 arg.STCoord = surfaceInfo.STCoord;
6955 arg.UVCoord = surfaceInfo.UVCoord;
6956 touchArgs.Add(arg);
6957 }
6958 }
6959 handlerDeGrabObject(deGrab.ObjectData.LocalID, this, touchArgs);
6960 }
6961 return true;
6962 }
6963
6964 private bool HandleObjectSpinStart(IClientAPI sender, Packet Pack)
6965 {
6966 //m_log.Warn("[CLIENT]: unhandled ObjectSpinStart packet");
6967 ObjectSpinStartPacket spinStart = (ObjectSpinStartPacket)Pack;
6968
6969 #region Packet Session and User Check
6970 if (m_checkPackets)
6971 {
6972 if (spinStart.AgentData.SessionID != SessionId ||
6973 spinStart.AgentData.AgentID != AgentId)
6974 return true;
6975 }
6976 #endregion
6977
6978 SpinStart handlerSpinStart = OnSpinStart;
6979 if (handlerSpinStart != null)
6980 {
6981 handlerSpinStart(spinStart.ObjectData.ObjectID, this);
6982 }
6983 return true;
6984 }
6985
6986 private bool HandleObjectSpinUpdate(IClientAPI sender, Packet Pack)
6987 {
6988 //m_log.Warn("[CLIENT]: unhandled ObjectSpinUpdate packet");
6989 ObjectSpinUpdatePacket spinUpdate = (ObjectSpinUpdatePacket)Pack;
6990
6991 #region Packet Session and User Check
6992 if (m_checkPackets)
6993 {
6994 if (spinUpdate.AgentData.SessionID != SessionId ||
6995 spinUpdate.AgentData.AgentID != AgentId)
6996 return true;
6997 }
6998 #endregion
6999
7000 Vector3 axis;
7001 float angle;
7002 spinUpdate.ObjectData.Rotation.GetAxisAngle(out axis, out angle);
7003 //m_log.Warn("[CLIENT]: ObjectSpinUpdate packet rot axis:" + axis + " angle:" + angle);
7004
7005 SpinObject handlerSpinUpdate = OnSpinUpdate;
7006 if (handlerSpinUpdate != null)
7007 {
7008 handlerSpinUpdate(spinUpdate.ObjectData.ObjectID, spinUpdate.ObjectData.Rotation, this);
7009 }
7010 return true;
7011 }
7012
7013 private bool HandleObjectSpinStop(IClientAPI sender, Packet Pack)
7014 {
7015 //m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet");
7016 ObjectSpinStopPacket spinStop = (ObjectSpinStopPacket)Pack;
7017
7018 #region Packet Session and User Check
7019 if (m_checkPackets)
7020 {
7021 if (spinStop.AgentData.SessionID != SessionId ||
7022 spinStop.AgentData.AgentID != AgentId)
7023 return true;
7024 }
7025 #endregion
7026
7027 SpinStop handlerSpinStop = OnSpinStop;
7028 if (handlerSpinStop != null)
7029 {
7030 handlerSpinStop(spinStop.ObjectData.ObjectID, this);
7031 }
7032 return true;
7033 }
7034
7035 private bool HandleObjectDescription(IClientAPI sender, Packet Pack)
7036 {
7037 ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack;
7038
7039 #region Packet Session and User Check
7040 if (m_checkPackets)
7041 {
7042 if (objDes.AgentData.SessionID != SessionId ||
7043 objDes.AgentData.AgentID != AgentId)
7044 return true;
7045 }
7046 #endregion
7047
7048 GenericCall7 handlerObjectDescription = null;
7049
7050 for (int i = 0; i < objDes.ObjectData.Length; i++)
7051 {
7052 handlerObjectDescription = OnObjectDescription;
7053 if (handlerObjectDescription != null)
7054 {
7055 handlerObjectDescription(this, objDes.ObjectData[i].LocalID,
7056 Util.FieldToString(objDes.ObjectData[i].Description));
7057 }
7058 }
7059 return true;
7060 }
7061
7062 private bool HandleObjectName(IClientAPI sender, Packet Pack)
7063 {
7064 ObjectNamePacket objName = (ObjectNamePacket)Pack;
7065
7066 #region Packet Session and User Check
7067 if (m_checkPackets)
7068 {
7069 if (objName.AgentData.SessionID != SessionId ||
7070 objName.AgentData.AgentID != AgentId)
7071 return true;
7072 }
7073 #endregion
7074
7075 GenericCall7 handlerObjectName = null;
7076 for (int i = 0; i < objName.ObjectData.Length; i++)
7077 {
7078 handlerObjectName = OnObjectName;
7079 if (handlerObjectName != null)
7080 {
7081 handlerObjectName(this, objName.ObjectData[i].LocalID,
7082 Util.FieldToString(objName.ObjectData[i].Name));
7083 }
7084 }
7085 return true;
7086 }
7087
7088 private bool HandleObjectPermissions(IClientAPI sender, Packet Pack)
7089 {
7090 if (OnObjectPermissions != null)
7091 {
7092 ObjectPermissionsPacket newobjPerms = (ObjectPermissionsPacket)Pack;
7093
7094 #region Packet Session and User Check
7095 if (m_checkPackets)
7096 {
7097 if (newobjPerms.AgentData.SessionID != SessionId ||
7098 newobjPerms.AgentData.AgentID != AgentId)
7099 return true;
7100 }
7101 #endregion
7102
7103 UUID AgentID = newobjPerms.AgentData.AgentID;
7104 UUID SessionID = newobjPerms.AgentData.SessionID;
7105
7106 ObjectPermissions handlerObjectPermissions = null;
7107
7108 for (int i = 0; i < newobjPerms.ObjectData.Length; i++)
7109 {
7110 ObjectPermissionsPacket.ObjectDataBlock permChanges = newobjPerms.ObjectData[i];
7111
7112 byte field = permChanges.Field;
7113 uint localID = permChanges.ObjectLocalID;
7114 uint mask = permChanges.Mask;
7115 byte set = permChanges.Set;
7116
7117 handlerObjectPermissions = OnObjectPermissions;
7118
7119 if (handlerObjectPermissions != null)
7120 handlerObjectPermissions(this, AgentID, SessionID, field, localID, mask, set);
7121 }
7122 }
7123
7124 // Here's our data,
7125 // PermField contains the field the info goes into
7126 // PermField determines which mask we're changing
7127 //
7128 // chmask is the mask of the change
7129 // setTF is whether we're adding it or taking it away
7130 //
7131 // objLocalID is the localID of the object.
7132
7133 // Unfortunately, we have to pass the event the packet because objData is an array
7134 // That means multiple object perms may be updated in a single packet.
7135
7136 return true;
7137 }
7138
7139 private bool HandleUndo(IClientAPI sender, Packet Pack)
7140 {
7141 UndoPacket undoitem = (UndoPacket)Pack;
7142
7143 #region Packet Session and User Check
7144 if (m_checkPackets)
7145 {
7146 if (undoitem.AgentData.SessionID != SessionId ||
7147 undoitem.AgentData.AgentID != AgentId)
7148 return true;
7149 }
7150 #endregion
7151
7152 if (undoitem.ObjectData.Length > 0)
7153 {
7154 for (int i = 0; i < undoitem.ObjectData.Length; i++)
7155 {
7156 UUID objiD = undoitem.ObjectData[i].ObjectID;
7157 AgentSit handlerOnUndo = OnUndo;
7158 if (handlerOnUndo != null)
7159 {
7160 handlerOnUndo(this, objiD);
7161 }
7162
7163 }
7164 }
7165 return true;
7166 }
7167
7168 private bool HandleLandUndo(IClientAPI sender, Packet Pack)
7169 {
7170 UndoLandPacket undolanditem = (UndoLandPacket)Pack;
7171
7172 #region Packet Session and User Check
7173 if (m_checkPackets)
7174 {
7175 if (undolanditem.AgentData.SessionID != SessionId ||
7176 undolanditem.AgentData.AgentID != AgentId)
7177 return true;
7178 }
7179 #endregion
7180
7181 LandUndo handlerOnUndo = OnLandUndo;
7182 if (handlerOnUndo != null)
7183 {
7184 handlerOnUndo(this);
7185 }
7186 return true;
7187 }
7188
7189 private bool HandleRedo(IClientAPI sender, Packet Pack)
7190 {
7191 RedoPacket redoitem = (RedoPacket)Pack;
7192
7193 #region Packet Session and User Check
7194 if (m_checkPackets)
7195 {
7196 if (redoitem.AgentData.SessionID != SessionId ||
7197 redoitem.AgentData.AgentID != AgentId)
7198 return true;
7199 }
7200 #endregion
7201
7202 if (redoitem.ObjectData.Length > 0)
7203 {
7204 for (int i = 0; i < redoitem.ObjectData.Length; i++)
7205 {
7206 UUID objiD = redoitem.ObjectData[i].ObjectID;
7207 AgentSit handlerOnRedo = OnRedo;
7208 if (handlerOnRedo != null)
7209 {
7210 handlerOnRedo(this, objiD);
7211 }
7212
7213 }
7214 }
7215 return true;
7216 }
7217
7218 private bool HandleObjectDuplicateOnRay(IClientAPI sender, Packet Pack)
7219 {
7220 ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack;
7221
7222 #region Packet Session and User Check
7223 if (m_checkPackets)
7224 {
7225 if (dupeOnRay.AgentData.SessionID != SessionId ||
7226 dupeOnRay.AgentData.AgentID != AgentId)
7227 return true;
7228 }
7229 #endregion
7230
7231 ObjectDuplicateOnRay handlerObjectDuplicateOnRay = null;
7232
7233 for (int i = 0; i < dupeOnRay.ObjectData.Length; i++)
7234 {
7235 handlerObjectDuplicateOnRay = OnObjectDuplicateOnRay;
7236 if (handlerObjectDuplicateOnRay != null)
7237 {
7238 handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags,
7239 AgentId, m_activeGroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd,
7240 dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection,
7241 dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates);
7242 }
7243 }
7244
7245 return true;
7246 }
7247
7248 private bool HandleRequestObjectPropertiesFamily(IClientAPI sender, Packet Pack)
7249 {
7250 //This powers the little tooltip that appears when you move your mouse over an object
7251 RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack;
7252
7253 #region Packet Session and User Check
7254 if (m_checkPackets)
7255 {
7256 if (packToolTip.AgentData.SessionID != SessionId ||
7257 packToolTip.AgentData.AgentID != AgentId)
7258 return true;
7259 }
7260 #endregion
7261
7262 RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData;
7263
7264 RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily;
7265
7266 if (handlerRequestObjectPropertiesFamily != null)
7267 {
7268 handlerRequestObjectPropertiesFamily(this, m_agentId, packObjBlock.RequestFlags,
7269 packObjBlock.ObjectID);
7270 }
7271
7272 return true;
7273 }
7274
7275 private bool HandleObjectIncludeInSearch(IClientAPI sender, Packet Pack)
7276 {
7277 //This lets us set objects to appear in search (stuff like DataSnapshot, etc)
7278 ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack;
7279 ObjectIncludeInSearch handlerObjectIncludeInSearch = null;
7280
7281 #region Packet Session and User Check
7282 if (m_checkPackets)
7283 {
7284 if (packInSearch.AgentData.SessionID != SessionId ||
7285 packInSearch.AgentData.AgentID != AgentId)
7286 return true;
7287 }
7288 #endregion
7289
7290 foreach (ObjectIncludeInSearchPacket.ObjectDataBlock objData in packInSearch.ObjectData)
7291 {
7292 bool inSearch = objData.IncludeInSearch;
7293 uint localID = objData.ObjectLocalID;
7294
7295 handlerObjectIncludeInSearch = OnObjectIncludeInSearch;
7296
7297 if (handlerObjectIncludeInSearch != null)
7298 {
7299 handlerObjectIncludeInSearch(this, inSearch, localID);
7300 }
7301 }
7302 return true;
7303 }
7304
7305 private bool HandleScriptAnswerYes(IClientAPI sender, Packet Pack)
7306 {
7307 ScriptAnswerYesPacket scriptAnswer = (ScriptAnswerYesPacket)Pack;
7308
7309 #region Packet Session and User Check
7310 if (m_checkPackets)
7311 {
7312 if (scriptAnswer.AgentData.SessionID != SessionId ||
7313 scriptAnswer.AgentData.AgentID != AgentId)
7314 return true;
7315 }
7316 #endregion
7317
7318 ScriptAnswer handlerScriptAnswer = OnScriptAnswer;
7319 if (handlerScriptAnswer != null)
7320 {
7321 handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions);
7322 }
7323 return true;
7324 }
7325
7326 private bool HandleObjectClickAction(IClientAPI sender, Packet Pack)
7327 {
7328 ObjectClickActionPacket ocpacket = (ObjectClickActionPacket)Pack;
7329
7330 #region Packet Session and User Check
7331 if (m_checkPackets)
7332 {
7333 if (ocpacket.AgentData.SessionID != SessionId ||
7334 ocpacket.AgentData.AgentID != AgentId)
7335 return true;
7336 }
7337 #endregion
7338
7339 GenericCall7 handlerObjectClickAction = OnObjectClickAction;
7340 if (handlerObjectClickAction != null)
7341 {
7342 foreach (ObjectClickActionPacket.ObjectDataBlock odata in ocpacket.ObjectData)
7343 {
7344 byte action = odata.ClickAction;
7345 uint localID = odata.ObjectLocalID;
7346 handlerObjectClickAction(this, localID, action.ToString());
7347 }
7348 }
7349 return true;
7350 }
7351
7352 private bool HandleObjectMaterial(IClientAPI sender, Packet Pack)
7353 {
7354 ObjectMaterialPacket ompacket = (ObjectMaterialPacket)Pack;
7355
7356 #region Packet Session and User Check
7357 if (m_checkPackets)
7358 {
7359 if (ompacket.AgentData.SessionID != SessionId ||
7360 ompacket.AgentData.AgentID != AgentId)
7361 return true;
7362 }
7363 #endregion
7364
7365 GenericCall7 handlerObjectMaterial = OnObjectMaterial;
7366 if (handlerObjectMaterial != null)
7367 {
7368 foreach (ObjectMaterialPacket.ObjectDataBlock odata in ompacket.ObjectData)
7369 {
7370 byte material = odata.Material;
7371 uint localID = odata.ObjectLocalID;
7372 handlerObjectMaterial(this, localID, material.ToString());
7373 }
7374 }
7375 return true;
7376 }
7377
7378 #endregion Objects/m_sceneObjects
7379
7380 #region Inventory/Asset/Other related packets
7381
7382 private bool HandleRequestImage(IClientAPI sender, Packet Pack)
7383 {
7384 RequestImagePacket imageRequest = (RequestImagePacket)Pack;
7385 //m_log.Debug("image request: " + Pack.ToString());
7386
7387 #region Packet Session and User Check
7388 if (m_checkPackets)
7389 {
7390 if (imageRequest.AgentData.SessionID != SessionId ||
7391 imageRequest.AgentData.AgentID != AgentId)
7392 return true;
7393 }
7394 #endregion
7395
7396 //handlerTextureRequest = null;
7397 for (int i = 0; i < imageRequest.RequestImage.Length; i++)
7398 {
7399 TextureRequestArgs args = new TextureRequestArgs();
7400
7401 RequestImagePacket.RequestImageBlock block = imageRequest.RequestImage[i];
7402
7403 args.RequestedAssetID = block.Image;
7404 args.DiscardLevel = block.DiscardLevel;
7405 args.PacketNumber = block.Packet;
7406 args.Priority = block.DownloadPriority;
7407 args.requestSequence = imageRequest.Header.Sequence;
7408
7409 // NOTE: This is not a built in part of the LLUDP protocol, but we double the
7410 // priority of avatar textures to get avatars rezzing in faster than the
7411 // surrounding scene
7412 if ((ImageType)block.Type == ImageType.Baked)
7413 args.Priority *= 2.0f;
7414
7415 // in the end, we null this, so we have to check if it's null
7416 if (m_imageManager != null)
7417 {
7418 m_imageManager.EnqueueReq(args);
7419 }
7420 }
7421 return true;
7422 }
7423
7424 /// <summary>
7425 /// This is the entry point for the UDP route by which the client can retrieve asset data. If the request
7426 /// is successful then a TransferInfo packet will be sent back, followed by one or more TransferPackets
7427 /// </summary>
7428 /// <param name="sender"></param>
7429 /// <param name="Pack"></param>
7430 /// <returns>This parameter may be ignored since we appear to return true whatever happens</returns>
7431 private bool HandleTransferRequest(IClientAPI sender, Packet Pack)
7432 {
7433 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request");
7434
7435 TransferRequestPacket transfer = (TransferRequestPacket)Pack;
7436 //m_log.Debug("Transfer Request: " + transfer.ToString());
7437 // Validate inventory transfers
7438 // Has to be done here, because AssetCache can't do it
7439 //
7440 UUID taskID = UUID.Zero;
7441 if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
7442 {
7443 taskID = new UUID(transfer.TransferInfo.Params, 48);
7444 UUID itemID = new UUID(transfer.TransferInfo.Params, 64);
7445 UUID requestID = new UUID(transfer.TransferInfo.Params, 80);
7446
7447// m_log.DebugFormat(
7448// "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}",
7449// requestID, itemID, taskID, Name);
7450
7451 if (!(((Scene)m_scene).Permissions.BypassPermissions()))
7452 {
7453 if (taskID != UUID.Zero) // Prim
7454 {
7455 SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID);
7456
7457 if (part == null)
7458 {
7459 m_log.WarnFormat(
7460 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist",
7461 Name, requestID, itemID, taskID);
7462 return true;
7463 }
7464
7465 TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID);
7466 if (tii == null)
7467 {
7468 m_log.WarnFormat(
7469 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist",
7470 Name, requestID, itemID, taskID);
7471 return true;
7472 }
7473
7474 if (tii.Type == (int)AssetType.LSLText)
7475 {
7476 if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId))
7477 return true;
7478 }
7479 else if (tii.Type == (int)AssetType.Notecard)
7480 {
7481 if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId))
7482 return true;
7483 }
7484 else
7485 {
7486 // TODO: Change this code to allow items other than notecards and scripts to be successfully
7487 // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule
7488 if (part.OwnerID != AgentId)
7489 {
7490 m_log.WarnFormat(
7491 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}",
7492 Name, requestID, itemID, taskID, part.OwnerID);
7493 return true;
7494 }
7495
7496 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
7497 {
7498 m_log.WarnFormat(
7499 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set",
7500 Name, requestID, itemID, taskID);
7501 return true;
7502 }
7503
7504 if (tii.OwnerID != AgentId)
7505 {
7506 m_log.WarnFormat(
7507 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}",
7508 Name, requestID, itemID, taskID, tii.OwnerID);
7509 return true;
7510 }
7511
7512 if ((
7513 tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
7514 != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
7515 {
7516 m_log.WarnFormat(
7517 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer",
7518 Name, requestID, itemID, taskID);
7519 return true;
7520 }
7521
7522 if (tii.AssetID != requestID)
7523 {
7524 m_log.WarnFormat(
7525 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}",
7526 Name, requestID, itemID, taskID, tii.AssetID);
7527 return true;
7528 }
7529 }
7530 }
7531 else // Agent
7532 {
7533 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
7534 if (invAccess != null)
7535 {
7536 if (!invAccess.GetAgentInventoryItem(this, itemID, requestID))
7537 return false;
7538
7539 }
7540 else
7541 return false;
7542
7543 }
7544 }
7545 }
7546
7547 MakeAssetRequest(transfer, taskID);
7548
7549 return true;
7550 }
7551
7552 private bool HandleAssetUploadRequest(IClientAPI sender, Packet Pack)
7553 {
7554 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
7555
7556
7557 // m_log.Debug("upload request " + request.ToString());
7558 // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString());
7559 UUID temp = UUID.Combine(request.AssetBlock.TransactionID, SecureSessionId);
7560
7561 UDPAssetUploadRequest handlerAssetUploadRequest = OnAssetUploadRequest;
7562
7563 if (handlerAssetUploadRequest != null)
7564 {
7565 handlerAssetUploadRequest(this, temp,
7566 request.AssetBlock.TransactionID, request.AssetBlock.Type,
7567 request.AssetBlock.AssetData, request.AssetBlock.StoreLocal,
7568 request.AssetBlock.Tempfile);
7569 }
7570 return true;
7571 }
7572
7573 private bool HandleRequestXfer(IClientAPI sender, Packet Pack)
7574 {
7575 RequestXferPacket xferReq = (RequestXferPacket)Pack;
7576
7577 RequestXfer handlerRequestXfer = OnRequestXfer;
7578
7579 if (handlerRequestXfer != null)
7580 {
7581 handlerRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename));
7582 }
7583 return true;
7584 }
7585
7586 private bool HandleSendXferPacket(IClientAPI sender, Packet Pack)
7587 {
7588 SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack;
7589
7590 XferReceive handlerXferReceive = OnXferReceive;
7591 if (handlerXferReceive != null)
7592 {
7593 handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data);
7594 }
7595 return true;
7596 }
7597
7598 private bool HandleConfirmXferPacket(IClientAPI sender, Packet Pack)
7599 {
7600 ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack;
7601
7602 ConfirmXfer handlerConfirmXfer = OnConfirmXfer;
7603 if (handlerConfirmXfer != null)
7604 {
7605 handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet);
7606 }
7607 return true;
7608 }
7609
7610 private bool HandleAbortXfer(IClientAPI sender, Packet Pack)
7611 {
7612 AbortXferPacket abortXfer = (AbortXferPacket)Pack;
7613 AbortXfer handlerAbortXfer = OnAbortXfer;
7614 if (handlerAbortXfer != null)
7615 {
7616 handlerAbortXfer(this, abortXfer.XferID.ID);
7617 }
7618
7619 return true;
7620 }
7621
7622 private bool HandleCreateInventoryFolder(IClientAPI sender, Packet Pack)
7623 {
7624 CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack;
7625
7626 #region Packet Session and User Check
7627 if (m_checkPackets)
7628 {
7629 if (invFolder.AgentData.SessionID != SessionId ||
7630 invFolder.AgentData.AgentID != AgentId)
7631 return true;
7632 }
7633 #endregion
7634
7635 CreateInventoryFolder handlerCreateInventoryFolder = OnCreateNewInventoryFolder;
7636 if (handlerCreateInventoryFolder != null)
7637 {
7638 handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID,
7639 (ushort)invFolder.FolderData.Type,
7640 Util.FieldToString(invFolder.FolderData.Name),
7641 invFolder.FolderData.ParentID);
7642 }
7643 return true;
7644 }
7645
7646 private bool HandleUpdateInventoryFolder(IClientAPI sender, Packet Pack)
7647 {
7648 if (OnUpdateInventoryFolder != null)
7649 {
7650 UpdateInventoryFolderPacket invFolderx = (UpdateInventoryFolderPacket)Pack;
7651
7652 #region Packet Session and User Check
7653 if (m_checkPackets)
7654 {
7655 if (invFolderx.AgentData.SessionID != SessionId ||
7656 invFolderx.AgentData.AgentID != AgentId)
7657 return true;
7658 }
7659 #endregion
7660
7661 UpdateInventoryFolder handlerUpdateInventoryFolder = null;
7662
7663 for (int i = 0; i < invFolderx.FolderData.Length; i++)
7664 {
7665 handlerUpdateInventoryFolder = OnUpdateInventoryFolder;
7666 if (handlerUpdateInventoryFolder != null)
7667 {
7668 OnUpdateInventoryFolder(this, invFolderx.FolderData[i].FolderID,
7669 (ushort)invFolderx.FolderData[i].Type,
7670 Util.FieldToString(invFolderx.FolderData[i].Name),
7671 invFolderx.FolderData[i].ParentID);
7672 }
7673 }
7674 }
7675 return true;
7676 }
7677
7678 private bool HandleMoveInventoryFolder(IClientAPI sender, Packet Pack)
7679 {
7680 if (OnMoveInventoryFolder != null)
7681 {
7682 MoveInventoryFolderPacket invFoldery = (MoveInventoryFolderPacket)Pack;
7683
7684 #region Packet Session and User Check
7685 if (m_checkPackets)
7686 {
7687 if (invFoldery.AgentData.SessionID != SessionId ||
7688 invFoldery.AgentData.AgentID != AgentId)
7689 return true;
7690 }
7691 #endregion
7692
7693 MoveInventoryFolder handlerMoveInventoryFolder = null;
7694
7695 for (int i = 0; i < invFoldery.InventoryData.Length; i++)
7696 {
7697 handlerMoveInventoryFolder = OnMoveInventoryFolder;
7698 if (handlerMoveInventoryFolder != null)
7699 {
7700 OnMoveInventoryFolder(this, invFoldery.InventoryData[i].FolderID,
7701 invFoldery.InventoryData[i].ParentID);
7702 }
7703 }
7704 }
7705 return true;
7706 }
7707
7708 private bool HandleCreateInventoryItem(IClientAPI sender, Packet Pack)
7709 {
7710 CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack;
7711
7712 #region Packet Session and User Check
7713 if (m_checkPackets)
7714 {
7715 if (createItem.AgentData.SessionID != SessionId ||
7716 createItem.AgentData.AgentID != AgentId)
7717 return true;
7718 }
7719 #endregion
7720
7721 CreateNewInventoryItem handlerCreateNewInventoryItem = OnCreateNewInventoryItem;
7722 if (handlerCreateNewInventoryItem != null)
7723 {
7724 handlerCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID,
7725 createItem.InventoryBlock.FolderID,
7726 createItem.InventoryBlock.CallbackID,
7727 Util.FieldToString(createItem.InventoryBlock.Description),
7728 Util.FieldToString(createItem.InventoryBlock.Name),
7729 createItem.InventoryBlock.InvType,
7730 createItem.InventoryBlock.Type,
7731 createItem.InventoryBlock.WearableType,
7732 createItem.InventoryBlock.NextOwnerMask,
7733 Util.UnixTimeSinceEpoch());
7734 }
7735 return true;
7736 }
7737
7738 private bool HandleLinkInventoryItem(IClientAPI sender, Packet Pack)
7739 {
7740 LinkInventoryItemPacket createLink = (LinkInventoryItemPacket)Pack;
7741
7742 #region Packet Session and User Check
7743 if (m_checkPackets)
7744 {
7745 if (createLink.AgentData.SessionID != SessionId ||
7746 createLink.AgentData.AgentID != AgentId)
7747 return true;
7748 }
7749 #endregion
7750
7751 LinkInventoryItem linkInventoryItem = OnLinkInventoryItem;
7752
7753 if (linkInventoryItem != null)
7754 {
7755 linkInventoryItem(
7756 this,
7757 createLink.InventoryBlock.TransactionID,
7758 createLink.InventoryBlock.FolderID,
7759 createLink.InventoryBlock.CallbackID,
7760 Util.FieldToString(createLink.InventoryBlock.Description),
7761 Util.FieldToString(createLink.InventoryBlock.Name),
7762 createLink.InventoryBlock.InvType,
7763 createLink.InventoryBlock.Type,
7764 createLink.InventoryBlock.OldItemID);
7765 }
7766
7767 return true;
7768 }
7769
7770 private bool HandleFetchInventory(IClientAPI sender, Packet Pack)
7771 {
7772 if (OnFetchInventory != null)
7773 {
7774 FetchInventoryPacket FetchInventoryx = (FetchInventoryPacket)Pack;
7775
7776 #region Packet Session and User Check
7777 if (m_checkPackets)
7778 {
7779 if (FetchInventoryx.AgentData.SessionID != SessionId ||
7780 FetchInventoryx.AgentData.AgentID != AgentId)
7781 return true;
7782 }
7783 #endregion
7784
7785 FetchInventory handlerFetchInventory = null;
7786
7787 for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++)
7788 {
7789 handlerFetchInventory = OnFetchInventory;
7790
7791 if (handlerFetchInventory != null)
7792 {
7793 OnFetchInventory(this, FetchInventoryx.InventoryData[i].ItemID,
7794 FetchInventoryx.InventoryData[i].OwnerID);
7795 }
7796 }
7797 }
7798 return true;
7799 }
7800
7801 private bool HandleFetchInventoryDescendents(IClientAPI sender, Packet Pack)
7802 {
7803 FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack;
7804
7805 #region Packet Session and User Check
7806 if (m_checkPackets)
7807 {
7808 if (Fetch.AgentData.SessionID != SessionId ||
7809 Fetch.AgentData.AgentID != AgentId)
7810 return true;
7811 }
7812 #endregion
7813
7814 FetchInventoryDescendents handlerFetchInventoryDescendents = OnFetchInventoryDescendents;
7815 if (handlerFetchInventoryDescendents != null)
7816 {
7817 handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID,
7818 Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems,
7819 Fetch.InventoryData.SortOrder);
7820 }
7821 return true;
7822 }
7823
7824 private bool HandlePurgeInventoryDescendents(IClientAPI sender, Packet Pack)
7825 {
7826 PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack;
7827
7828 #region Packet Session and User Check
7829 if (m_checkPackets)
7830 {
7831 if (Purge.AgentData.SessionID != SessionId ||
7832 Purge.AgentData.AgentID != AgentId)
7833 return true;
7834 }
7835 #endregion
7836
7837 PurgeInventoryDescendents handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents;
7838 if (handlerPurgeInventoryDescendents != null)
7839 {
7840 handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID);
7841 }
7842 return true;
7843 }
7844
7845 private bool HandleUpdateInventoryItem(IClientAPI sender, Packet Pack)
7846 {
7847 UpdateInventoryItemPacket inventoryItemUpdate = (UpdateInventoryItemPacket)Pack;
7848
7849 #region Packet Session and User Check
7850 if (m_checkPackets)
7851 {
7852 if (inventoryItemUpdate.AgentData.SessionID != SessionId ||
7853 inventoryItemUpdate.AgentData.AgentID != AgentId)
7854 return true;
7855 }
7856 #endregion
7857
7858 if (OnUpdateInventoryItem != null)
7859 {
7860 UpdateInventoryItem handlerUpdateInventoryItem = null;
7861 for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++)
7862 {
7863 handlerUpdateInventoryItem = OnUpdateInventoryItem;
7864
7865 if (handlerUpdateInventoryItem != null)
7866 {
7867 InventoryItemBase itemUpd = new InventoryItemBase();
7868 itemUpd.ID = inventoryItemUpdate.InventoryData[i].ItemID;
7869 itemUpd.Name = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Name);
7870 itemUpd.Description = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Description);
7871 itemUpd.GroupID = inventoryItemUpdate.InventoryData[i].GroupID;
7872 itemUpd.GroupOwned = inventoryItemUpdate.InventoryData[i].GroupOwned;
7873 itemUpd.GroupPermissions = inventoryItemUpdate.InventoryData[i].GroupMask;
7874 itemUpd.NextPermissions = inventoryItemUpdate.InventoryData[i].NextOwnerMask;
7875 itemUpd.EveryOnePermissions = inventoryItemUpdate.InventoryData[i].EveryoneMask;
7876 itemUpd.CreationDate = inventoryItemUpdate.InventoryData[i].CreationDate;
7877 itemUpd.Folder = inventoryItemUpdate.InventoryData[i].FolderID;
7878 itemUpd.InvType = inventoryItemUpdate.InventoryData[i].InvType;
7879 itemUpd.SalePrice = inventoryItemUpdate.InventoryData[i].SalePrice;
7880 itemUpd.SaleType = inventoryItemUpdate.InventoryData[i].SaleType;
7881 itemUpd.Flags = inventoryItemUpdate.InventoryData[i].Flags;
7882
7883 OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID,
7884 inventoryItemUpdate.InventoryData[i].ItemID,
7885 itemUpd);
7886 }
7887 }
7888 }
7889 return true;
7890 }
7891
7892 private bool HandleCopyInventoryItem(IClientAPI sender, Packet Pack)
7893 {
7894 CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack;
7895
7896 #region Packet Session and User Check
7897 if (m_checkPackets)
7898 {
7899 if (copyitem.AgentData.SessionID != SessionId ||
7900 copyitem.AgentData.AgentID != AgentId)
7901 return true;
7902 }
7903 #endregion
7904
7905 CopyInventoryItem handlerCopyInventoryItem = null;
7906 if (OnCopyInventoryItem != null)
7907 {
7908 foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData)
7909 {
7910 handlerCopyInventoryItem = OnCopyInventoryItem;
7911 if (handlerCopyInventoryItem != null)
7912 {
7913 handlerCopyInventoryItem(this, datablock.CallbackID, datablock.OldAgentID,
7914 datablock.OldItemID, datablock.NewFolderID,
7915 Util.FieldToString(datablock.NewName));
7916 }
7917 }
7918 }
7919 return true;
7920 }
7921
7922 private bool HandleMoveInventoryItem(IClientAPI sender, Packet Pack)
7923 {
7924 MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack;
7925
7926 #region Packet Session and User Check
7927 if (m_checkPackets)
7928 {
7929 if (moveitem.AgentData.SessionID != SessionId ||
7930 moveitem.AgentData.AgentID != AgentId)
7931 return true;
7932 }
7933 #endregion
7934
7935 if (OnMoveInventoryItem != null)
7936 {
7937 MoveInventoryItem handlerMoveInventoryItem = null;
7938 InventoryItemBase itm = null;
7939 List<InventoryItemBase> items = new List<InventoryItemBase>();
7940 foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData)
7941 {
7942 itm = new InventoryItemBase(datablock.ItemID, AgentId);
7943 itm.Folder = datablock.FolderID;
7944 itm.Name = Util.FieldToString(datablock.NewName);
7945 // weird, comes out as empty string
7946 //m_log.DebugFormat("[XXX] new name: {0}", itm.Name);
7947 items.Add(itm);
7948 }
7949 handlerMoveInventoryItem = OnMoveInventoryItem;
7950 if (handlerMoveInventoryItem != null)
7951 {
7952 handlerMoveInventoryItem(this, items);
7953 }
7954 }
7955 return true;
7956 }
7957
7958 private bool HandleRemoveInventoryItem(IClientAPI sender, Packet Pack)
7959 {
7960 RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack;
7961
7962 #region Packet Session and User Check
7963 if (m_checkPackets)
7964 {
7965 if (removeItem.AgentData.SessionID != SessionId ||
7966 removeItem.AgentData.AgentID != AgentId)
7967 return true;
7968 }
7969 #endregion
7970
7971 if (OnRemoveInventoryItem != null)
7972 {
7973 RemoveInventoryItem handlerRemoveInventoryItem = null;
7974 List<UUID> uuids = new List<UUID>();
7975 foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData)
7976 {
7977 uuids.Add(datablock.ItemID);
7978 }
7979 handlerRemoveInventoryItem = OnRemoveInventoryItem;
7980 if (handlerRemoveInventoryItem != null)
7981 {
7982 handlerRemoveInventoryItem(this, uuids);
7983 }
7984
7985 }
7986 return true;
7987 }
7988
7989 private bool HandleRemoveInventoryFolder(IClientAPI sender, Packet Pack)
7990 {
7991 RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack;
7992
7993 #region Packet Session and User Check
7994 if (m_checkPackets)
7995 {
7996 if (removeFolder.AgentData.SessionID != SessionId ||
7997 removeFolder.AgentData.AgentID != AgentId)
7998 return true;
7999 }
8000 #endregion
8001
8002 if (OnRemoveInventoryFolder != null)
8003 {
8004 RemoveInventoryFolder handlerRemoveInventoryFolder = null;
8005 List<UUID> uuids = new List<UUID>();
8006 foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData)
8007 {
8008 uuids.Add(datablock.FolderID);
8009 }
8010 handlerRemoveInventoryFolder = OnRemoveInventoryFolder;
8011 if (handlerRemoveInventoryFolder != null)
8012 {
8013 handlerRemoveInventoryFolder(this, uuids);
8014 }
8015 }
8016 return true;
8017 }
8018
8019 private bool HandleRemoveInventoryObjects(IClientAPI sender, Packet Pack)
8020 {
8021 RemoveInventoryObjectsPacket removeObject = (RemoveInventoryObjectsPacket)Pack;
8022 #region Packet Session and User Check
8023 if (m_checkPackets)
8024 {
8025 if (removeObject.AgentData.SessionID != SessionId ||
8026 removeObject.AgentData.AgentID != AgentId)
8027 return true;
8028 }
8029 #endregion
8030 if (OnRemoveInventoryFolder != null)
8031 {
8032 RemoveInventoryFolder handlerRemoveInventoryFolder = null;
8033 List<UUID> uuids = new List<UUID>();
8034 foreach (RemoveInventoryObjectsPacket.FolderDataBlock datablock in removeObject.FolderData)
8035 {
8036 uuids.Add(datablock.FolderID);
8037 }
8038 handlerRemoveInventoryFolder = OnRemoveInventoryFolder;
8039 if (handlerRemoveInventoryFolder != null)
8040 {
8041 handlerRemoveInventoryFolder(this, uuids);
8042 }
8043 }
8044
8045 if (OnRemoveInventoryItem != null)
8046 {
8047 RemoveInventoryItem handlerRemoveInventoryItem = null;
8048 List<UUID> uuids = new List<UUID>();
8049 foreach (RemoveInventoryObjectsPacket.ItemDataBlock datablock in removeObject.ItemData)
8050 {
8051 uuids.Add(datablock.ItemID);
8052 }
8053 handlerRemoveInventoryItem = OnRemoveInventoryItem;
8054 if (handlerRemoveInventoryItem != null)
8055 {
8056 handlerRemoveInventoryItem(this, uuids);
8057 }
8058 }
8059 return true;
8060 }
8061
8062 private bool HandleRequestTaskInventory(IClientAPI sender, Packet Pack)
8063 {
8064 RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack;
8065
8066 #region Packet Session and User Check
8067 if (m_checkPackets)
8068 {
8069 if (requesttask.AgentData.SessionID != SessionId ||
8070 requesttask.AgentData.AgentID != AgentId)
8071 return true;
8072 }
8073 #endregion
8074
8075 RequestTaskInventory handlerRequestTaskInventory = OnRequestTaskInventory;
8076 if (handlerRequestTaskInventory != null)
8077 {
8078 handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID);
8079 }
8080 return true;
8081 }
8082
8083 private bool HandleUpdateTaskInventory(IClientAPI sender, Packet Pack)
8084 {
8085 UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack;
8086
8087 #region Packet Session and User Check
8088 if (m_checkPackets)
8089 {
8090 if (updatetask.AgentData.SessionID != SessionId ||
8091 updatetask.AgentData.AgentID != AgentId)
8092 return true;
8093 }
8094 #endregion
8095
8096 if (OnUpdateTaskInventory != null)
8097 {
8098 if (updatetask.UpdateData.Key == 0)
8099 {
8100 UpdateTaskInventory handlerUpdateTaskInventory = OnUpdateTaskInventory;
8101 if (handlerUpdateTaskInventory != null)
8102 {
8103 TaskInventoryItem newTaskItem = new TaskInventoryItem();
8104 newTaskItem.ItemID = updatetask.InventoryData.ItemID;
8105 newTaskItem.ParentID = updatetask.InventoryData.FolderID;
8106 newTaskItem.CreatorID = updatetask.InventoryData.CreatorID;
8107 newTaskItem.OwnerID = updatetask.InventoryData.OwnerID;
8108 newTaskItem.GroupID = updatetask.InventoryData.GroupID;
8109 newTaskItem.BasePermissions = updatetask.InventoryData.BaseMask;
8110 newTaskItem.CurrentPermissions = updatetask.InventoryData.OwnerMask;
8111 newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask;
8112 newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask;
8113 newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask;
8114
8115 // Unused? Clicking share with group sets GroupPermissions instead, so perhaps this is something
8116 // different
8117 //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned;
8118 newTaskItem.Type = updatetask.InventoryData.Type;
8119 newTaskItem.InvType = updatetask.InventoryData.InvType;
8120 newTaskItem.Flags = updatetask.InventoryData.Flags;
8121 //newTaskItem.SaleType=updatetask.InventoryData.SaleType;
8122 //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;
8123 newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name);
8124 newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description);
8125 newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate;
8126 handlerUpdateTaskInventory(this, updatetask.InventoryData.TransactionID,
8127 newTaskItem, updatetask.UpdateData.LocalID);
8128 }
8129 }
8130 }
8131
8132 return true;
8133 }
8134
8135 private bool HandleRemoveTaskInventory(IClientAPI sender, Packet Pack)
8136 {
8137 RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack;
8138
8139 #region Packet Session and User Check
8140 if (m_checkPackets)
8141 {
8142 if (removeTask.AgentData.SessionID != SessionId ||
8143 removeTask.AgentData.AgentID != AgentId)
8144 return true;
8145 }
8146 #endregion
8147
8148 RemoveTaskInventory handlerRemoveTaskItem = OnRemoveTaskItem;
8149
8150 if (handlerRemoveTaskItem != null)
8151 {
8152 handlerRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID);
8153 }
8154
8155 return true;
8156 }
8157
8158 private bool HandleMoveTaskInventory(IClientAPI sender, Packet Pack)
8159 {
8160 MoveTaskInventoryPacket moveTaskInventoryPacket = (MoveTaskInventoryPacket)Pack;
8161
8162 #region Packet Session and User Check
8163 if (m_checkPackets)
8164 {
8165 if (moveTaskInventoryPacket.AgentData.SessionID != SessionId ||
8166 moveTaskInventoryPacket.AgentData.AgentID != AgentId)
8167 return true;
8168 }
8169 #endregion
8170
8171 MoveTaskInventory handlerMoveTaskItem = OnMoveTaskItem;
8172
8173 if (handlerMoveTaskItem != null)
8174 {
8175 handlerMoveTaskItem(
8176 this, moveTaskInventoryPacket.AgentData.FolderID,
8177 moveTaskInventoryPacket.InventoryData.LocalID,
8178 moveTaskInventoryPacket.InventoryData.ItemID);
8179 }
8180
8181 return true;
8182 }
8183
8184 private bool HandleRezScript(IClientAPI sender, Packet Pack)
8185 {
8186 //m_log.Debug(Pack.ToString());
8187 RezScriptPacket rezScriptx = (RezScriptPacket)Pack;
8188
8189 #region Packet Session and User Check
8190 if (m_checkPackets)
8191 {
8192 if (rezScriptx.AgentData.SessionID != SessionId ||
8193 rezScriptx.AgentData.AgentID != AgentId)
8194 return true;
8195 }
8196 #endregion
8197
8198 RezScript handlerRezScript = OnRezScript;
8199 InventoryItemBase item = new InventoryItemBase();
8200 item.ID = rezScriptx.InventoryBlock.ItemID;
8201 item.Folder = rezScriptx.InventoryBlock.FolderID;
8202 item.CreatorId = rezScriptx.InventoryBlock.CreatorID.ToString();
8203 item.Owner = rezScriptx.InventoryBlock.OwnerID;
8204 item.BasePermissions = rezScriptx.InventoryBlock.BaseMask;
8205 item.CurrentPermissions = rezScriptx.InventoryBlock.OwnerMask;
8206 item.EveryOnePermissions = rezScriptx.InventoryBlock.EveryoneMask;
8207 item.NextPermissions = rezScriptx.InventoryBlock.NextOwnerMask;
8208 item.GroupPermissions = rezScriptx.InventoryBlock.GroupMask;
8209 item.GroupOwned = rezScriptx.InventoryBlock.GroupOwned;
8210 item.GroupID = rezScriptx.InventoryBlock.GroupID;
8211 item.AssetType = rezScriptx.InventoryBlock.Type;
8212 item.InvType = rezScriptx.InventoryBlock.InvType;
8213 item.Flags = rezScriptx.InventoryBlock.Flags;
8214 item.SaleType = rezScriptx.InventoryBlock.SaleType;
8215 item.SalePrice = rezScriptx.InventoryBlock.SalePrice;
8216 item.Name = Util.FieldToString(rezScriptx.InventoryBlock.Name);
8217 item.Description = Util.FieldToString(rezScriptx.InventoryBlock.Description);
8218 item.CreationDate = rezScriptx.InventoryBlock.CreationDate;
8219
8220 if (handlerRezScript != null)
8221 {
8222 handlerRezScript(this, item, rezScriptx.InventoryBlock.TransactionID, rezScriptx.UpdateBlock.ObjectLocalID);
8223 }
8224 return true;
8225 }
8226
8227 private bool HandleMapLayerRequest(IClientAPI sender, Packet Pack)
8228 {
8229 RequestMapLayer();
8230 return true;
8231 }
8232
8233 private bool HandleMapBlockRequest(IClientAPI sender, Packet Pack)
8234 {
8235 MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack;
8236
8237 #region Packet Session and User Check
8238 if (m_checkPackets)
8239 {
8240 if (MapRequest.AgentData.SessionID != SessionId ||
8241 MapRequest.AgentData.AgentID != AgentId)
8242 return true;
8243 }
8244 #endregion
8245
8246 RequestMapBlocks handlerRequestMapBlocks = OnRequestMapBlocks;
8247 if (handlerRequestMapBlocks != null)
8248 {
8249 handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY,
8250 MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY, MapRequest.AgentData.Flags);
8251 }
8252 return true;
8253 }
8254
8255 private bool HandleMapNameRequest(IClientAPI sender, Packet Pack)
8256 {
8257 MapNameRequestPacket map = (MapNameRequestPacket)Pack;
8258
8259 #region Packet Session and User Check
8260 if (m_checkPackets)
8261 {
8262 if (map.AgentData.SessionID != SessionId ||
8263 map.AgentData.AgentID != AgentId)
8264 return true;
8265 }
8266 #endregion
8267
8268 string mapName = Util.UTF8.GetString(map.NameData.Name, 0,
8269 map.NameData.Name.Length - 1);
8270 RequestMapName handlerMapNameRequest = OnMapNameRequest;
8271 if (handlerMapNameRequest != null)
8272 {
8273 handlerMapNameRequest(this, mapName);
8274 }
8275 return true;
8276 }
8277
8278 private bool HandleTeleportLandmarkRequest(IClientAPI sender, Packet Pack)
8279 {
8280 TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack;
8281
8282 #region Packet Session and User Check
8283 if (m_checkPackets)
8284 {
8285 if (tpReq.Info.SessionID != SessionId ||
8286 tpReq.Info.AgentID != AgentId)
8287 return true;
8288 }
8289 #endregion
8290
8291 UUID lmid = tpReq.Info.LandmarkID;
8292 AssetLandmark lm;
8293 if (lmid != UUID.Zero)
8294 {
8295 //AssetBase lma = m_assetCache.GetAsset(lmid, false);
8296 AssetBase lma = m_assetService.Get(lmid.ToString());
8297
8298 if (lma == null)
8299 {
8300 // Failed to find landmark
8301 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
8302 tpCancel.Info.SessionID = tpReq.Info.SessionID;
8303 tpCancel.Info.AgentID = tpReq.Info.AgentID;
8304 OutPacket(tpCancel, ThrottleOutPacketType.Task);
8305 }
8306
8307 try
8308 {
8309 lm = new AssetLandmark(lma);
8310 }
8311 catch (NullReferenceException)
8312 {
8313 // asset not found generates null ref inside the assetlandmark constructor.
8314 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
8315 tpCancel.Info.SessionID = tpReq.Info.SessionID;
8316 tpCancel.Info.AgentID = tpReq.Info.AgentID;
8317 OutPacket(tpCancel, ThrottleOutPacketType.Task);
8318 return true;
8319 }
8320 }
8321 else
8322 {
8323 // Teleport home request
8324 UUIDNameRequest handlerTeleportHomeRequest = OnTeleportHomeRequest;
8325 if (handlerTeleportHomeRequest != null)
8326 {
8327 handlerTeleportHomeRequest(AgentId, this);
8328 }
8329 return true;
8330 }
8331
8332 TeleportLandmarkRequest handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest;
8333 if (handlerTeleportLandmarkRequest != null)
8334 {
8335 handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position);
8336 }
8337 else
8338 {
8339 //no event handler so cancel request
8340
8341
8342 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
8343 tpCancel.Info.AgentID = tpReq.Info.AgentID;
8344 tpCancel.Info.SessionID = tpReq.Info.SessionID;
8345 OutPacket(tpCancel, ThrottleOutPacketType.Task);
8346
8347 }
8348 return true;
8349 }
8350
8351 private bool HandleTeleportLocationRequest(IClientAPI sender, Packet Pack)
8352 {
8353 TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack;
8354 // m_log.Debug(tpLocReq.ToString());
8355
8356 #region Packet Session and User Check
8357 if (m_checkPackets)
8358 {
8359 if (tpLocReq.AgentData.SessionID != SessionId ||
8360 tpLocReq.AgentData.AgentID != AgentId)
8361 return true;
8362 }
8363 #endregion
8364
8365 TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest;
8366 if (handlerTeleportLocationRequest != null)
8367 {
8368 handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position,
8369 tpLocReq.Info.LookAt, 16);
8370 }
8371 else
8372 {
8373 //no event handler so cancel request
8374 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
8375 tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID;
8376 tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID;
8377 OutPacket(tpCancel, ThrottleOutPacketType.Task);
8378 }
8379 return true;
8380 }
8381
8382 #endregion Inventory/Asset/Other related packets
8383
8384 private bool HandleUUIDNameRequest(IClientAPI sender, Packet Pack)
8385 {
8386 UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack;
8387
8388 foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock)
8389 {
8390 UUIDNameRequest handlerNameRequest = OnNameFromUUIDRequest;
8391 if (handlerNameRequest != null)
8392 {
8393 handlerNameRequest(UUIDBlock.ID, this);
8394 }
8395 }
8396 return true;
8397 }
8398
8399 #region Parcel related packets
8400
8401 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack)
8402 {
8403 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack;
8404
8405 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest;
8406 if (handlerRegionHandleRequest != null)
8407 {
8408 handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID);
8409 }
8410 return true;
8411 }
8412
8413 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack)
8414 {
8415 ParcelInfoRequestPacket pirPack = (ParcelInfoRequestPacket)Pack;
8416
8417 #region Packet Session and User Check
8418 if (m_checkPackets)
8419 {
8420 if (pirPack.AgentData.SessionID != SessionId ||
8421 pirPack.AgentData.AgentID != AgentId)
8422 return true;
8423 }
8424 #endregion
8425
8426 ParcelInfoRequest handlerParcelInfoRequest = OnParcelInfoRequest;
8427 if (handlerParcelInfoRequest != null)
8428 {
8429 handlerParcelInfoRequest(this, pirPack.Data.ParcelID);
8430 }
8431 return true;
8432 }
8433
8434 private bool HandleParcelAccessListRequest(IClientAPI sender, Packet Pack)
8435 {
8436 ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack;
8437
8438 #region Packet Session and User Check
8439 if (m_checkPackets)
8440 {
8441 if (requestPacket.AgentData.SessionID != SessionId ||
8442 requestPacket.AgentData.AgentID != AgentId)
8443 return true;
8444 }
8445 #endregion
8446
8447 ParcelAccessListRequest handlerParcelAccessListRequest = OnParcelAccessListRequest;
8448
8449 if (handlerParcelAccessListRequest != null)
8450 {
8451 handlerParcelAccessListRequest(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID,
8452 requestPacket.Data.Flags, requestPacket.Data.SequenceID,
8453 requestPacket.Data.LocalID, this);
8454 }
8455 return true;
8456 }
8457
8458 private bool HandleParcelAccessListUpdate(IClientAPI sender, Packet Pack)
8459 {
8460 ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack;
8461
8462 #region Packet Session and User Check
8463 if (m_checkPackets)
8464 {
8465 if (updatePacket.AgentData.SessionID != SessionId ||
8466 updatePacket.AgentData.AgentID != AgentId)
8467 return true;
8468 }
8469 #endregion
8470
8471 List<ParcelManager.ParcelAccessEntry> entries = new List<ParcelManager.ParcelAccessEntry>();
8472 foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List)
8473 {
8474 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
8475 entry.AgentID = block.ID;
8476 entry.Flags = (AccessList)block.Flags;
8477 entry.Time = Util.ToDateTime(block.Time);
8478 entries.Add(entry);
8479 }
8480
8481 ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest;
8482 if (handlerParcelAccessListUpdateRequest != null)
8483 {
8484 handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID,
8485 updatePacket.Data.Flags,
8486 updatePacket.Data.LocalID,
8487 updatePacket.Data.TransactionID,
8488 updatePacket.Data.SequenceID,
8489 updatePacket.Data.Sections,
8490 entries, this);
8491 }
8492 return true;
8493 }
8494
8495 private bool HandleParcelPropertiesRequest(IClientAPI sender, Packet Pack)
8496 {
8497 ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack;
8498
8499 #region Packet Session and User Check
8500 if (m_checkPackets)
8501 {
8502 if (propertiesRequest.AgentData.SessionID != SessionId ||
8503 propertiesRequest.AgentData.AgentID != AgentId)
8504 return true;
8505 }
8506 #endregion
8507
8508 ParcelPropertiesRequest handlerParcelPropertiesRequest = OnParcelPropertiesRequest;
8509 if (handlerParcelPropertiesRequest != null)
8510 {
8511 handlerParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West),
8512 (int)Math.Round(propertiesRequest.ParcelData.South),
8513 (int)Math.Round(propertiesRequest.ParcelData.East),
8514 (int)Math.Round(propertiesRequest.ParcelData.North),
8515 propertiesRequest.ParcelData.SequenceID,
8516 propertiesRequest.ParcelData.SnapSelection, this);
8517 }
8518 return true;
8519 }
8520
8521 private bool HandleParcelDivide(IClientAPI sender, Packet Pack)
8522 {
8523 ParcelDividePacket landDivide = (ParcelDividePacket)Pack;
8524
8525 #region Packet Session and User Check
8526 if (m_checkPackets)
8527 {
8528 if (landDivide.AgentData.SessionID != SessionId ||
8529 landDivide.AgentData.AgentID != AgentId)
8530 return true;
8531 }
8532 #endregion
8533
8534 ParcelDivideRequest handlerParcelDivideRequest = OnParcelDivideRequest;
8535 if (handlerParcelDivideRequest != null)
8536 {
8537 handlerParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West),
8538 (int)Math.Round(landDivide.ParcelData.South),
8539 (int)Math.Round(landDivide.ParcelData.East),
8540 (int)Math.Round(landDivide.ParcelData.North), this);
8541 }
8542 return true;
8543 }
8544
8545 private bool HandleParcelJoin(IClientAPI sender, Packet Pack)
8546 {
8547 ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack;
8548
8549 #region Packet Session and User Check
8550 if (m_checkPackets)
8551 {
8552 if (landJoin.AgentData.SessionID != SessionId ||
8553 landJoin.AgentData.AgentID != AgentId)
8554 return true;
8555 }
8556 #endregion
8557
8558 ParcelJoinRequest handlerParcelJoinRequest = OnParcelJoinRequest;
8559
8560 if (handlerParcelJoinRequest != null)
8561 {
8562 handlerParcelJoinRequest((int)Math.Round(landJoin.ParcelData.West),
8563 (int)Math.Round(landJoin.ParcelData.South),
8564 (int)Math.Round(landJoin.ParcelData.East),
8565 (int)Math.Round(landJoin.ParcelData.North), this);
8566 }
8567 return true;
8568 }
8569
8570 private bool HandleParcelPropertiesUpdate(IClientAPI sender, Packet Pack)
8571 {
8572 ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack;
8573
8574 #region Packet Session and User Check
8575 if (m_checkPackets)
8576 {
8577 if (parcelPropertiesPacket.AgentData.SessionID != SessionId ||
8578 parcelPropertiesPacket.AgentData.AgentID != AgentId)
8579 return true;
8580 }
8581 #endregion
8582
8583 ParcelPropertiesUpdateRequest handlerParcelPropertiesUpdateRequest = OnParcelPropertiesUpdateRequest;
8584
8585 if (handlerParcelPropertiesUpdateRequest != null)
8586 {
8587 LandUpdateArgs args = new LandUpdateArgs();
8588
8589 args.AuthBuyerID = parcelPropertiesPacket.ParcelData.AuthBuyerID;
8590 args.Category = (ParcelCategory)parcelPropertiesPacket.ParcelData.Category;
8591 args.Desc = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Desc);
8592 args.GroupID = parcelPropertiesPacket.ParcelData.GroupID;
8593 args.LandingType = parcelPropertiesPacket.ParcelData.LandingType;
8594 args.MediaAutoScale = parcelPropertiesPacket.ParcelData.MediaAutoScale;
8595 args.MediaID = parcelPropertiesPacket.ParcelData.MediaID;
8596 args.MediaURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MediaURL);
8597 args.MusicURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MusicURL);
8598 args.Name = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Name);
8599 args.ParcelFlags = parcelPropertiesPacket.ParcelData.ParcelFlags;
8600 args.PassHours = parcelPropertiesPacket.ParcelData.PassHours;
8601 args.PassPrice = parcelPropertiesPacket.ParcelData.PassPrice;
8602 args.SalePrice = parcelPropertiesPacket.ParcelData.SalePrice;
8603 args.SnapshotID = parcelPropertiesPacket.ParcelData.SnapshotID;
8604 args.UserLocation = parcelPropertiesPacket.ParcelData.UserLocation;
8605 args.UserLookAt = parcelPropertiesPacket.ParcelData.UserLookAt;
8606 handlerParcelPropertiesUpdateRequest(args, parcelPropertiesPacket.ParcelData.LocalID, this);
8607 }
8608 return true;
8609 }
8610
8611 private bool HandleParcelSelectObjects(IClientAPI sender, Packet Pack)
8612 {
8613 ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack;
8614
8615 #region Packet Session and User Check
8616 if (m_checkPackets)
8617 {
8618 if (selectPacket.AgentData.SessionID != SessionId ||
8619 selectPacket.AgentData.AgentID != AgentId)
8620 return true;
8621 }
8622 #endregion
8623
8624 List<UUID> returnIDs = new List<UUID>();
8625
8626 foreach (ParcelSelectObjectsPacket.ReturnIDsBlock rb in
8627 selectPacket.ReturnIDs)
8628 {
8629 returnIDs.Add(rb.ReturnID);
8630 }
8631
8632 ParcelSelectObjects handlerParcelSelectObjects = OnParcelSelectObjects;
8633
8634 if (handlerParcelSelectObjects != null)
8635 {
8636 handlerParcelSelectObjects(selectPacket.ParcelData.LocalID,
8637 Convert.ToInt32(selectPacket.ParcelData.ReturnType), returnIDs, this);
8638 }
8639 return true;
8640 }
8641
8642 private bool HandleParcelObjectOwnersRequest(IClientAPI sender, Packet Pack)
8643 {
8644 ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack;
8645
8646 #region Packet Session and User Check
8647 if (m_checkPackets)
8648 {
8649 if (reqPacket.AgentData.SessionID != SessionId ||
8650 reqPacket.AgentData.AgentID != AgentId)
8651 return true;
8652 }
8653 #endregion
8654
8655 ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest;
8656
8657 if (handlerParcelObjectOwnerRequest != null)
8658 {
8659 handlerParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this);
8660 }
8661 return true;
8662
8663 }
8664
8665 private bool HandleParcelGodForceOwner(IClientAPI sender, Packet Pack)
8666 {
8667 ParcelGodForceOwnerPacket godForceOwnerPacket = (ParcelGodForceOwnerPacket)Pack;
8668
8669 #region Packet Session and User Check
8670 if (m_checkPackets)
8671 {
8672 if (godForceOwnerPacket.AgentData.SessionID != SessionId ||
8673 godForceOwnerPacket.AgentData.AgentID != AgentId)
8674 return true;
8675 }
8676 #endregion
8677
8678 ParcelGodForceOwner handlerParcelGodForceOwner = OnParcelGodForceOwner;
8679 if (handlerParcelGodForceOwner != null)
8680 {
8681 handlerParcelGodForceOwner(godForceOwnerPacket.Data.LocalID, godForceOwnerPacket.Data.OwnerID, this);
8682 }
8683 return true;
8684 }
8685
8686 private bool HandleParcelRelease(IClientAPI sender, Packet Pack)
8687 {
8688 ParcelReleasePacket releasePacket = (ParcelReleasePacket)Pack;
8689
8690 #region Packet Session and User Check
8691 if (m_checkPackets)
8692 {
8693 if (releasePacket.AgentData.SessionID != SessionId ||
8694 releasePacket.AgentData.AgentID != AgentId)
8695 return true;
8696 }
8697 #endregion
8698
8699 ParcelAbandonRequest handlerParcelAbandonRequest = OnParcelAbandonRequest;
8700 if (handlerParcelAbandonRequest != null)
8701 {
8702 handlerParcelAbandonRequest(releasePacket.Data.LocalID, this);
8703 }
8704 return true;
8705 }
8706
8707 private bool HandleParcelReclaim(IClientAPI sender, Packet Pack)
8708 {
8709 ParcelReclaimPacket reclaimPacket = (ParcelReclaimPacket)Pack;
8710
8711 #region Packet Session and User Check
8712 if (m_checkPackets)
8713 {
8714 if (reclaimPacket.AgentData.SessionID != SessionId ||
8715 reclaimPacket.AgentData.AgentID != AgentId)
8716 return true;
8717 }
8718 #endregion
8719
8720 ParcelReclaim handlerParcelReclaim = OnParcelReclaim;
8721 if (handlerParcelReclaim != null)
8722 {
8723 handlerParcelReclaim(reclaimPacket.Data.LocalID, this);
8724 }
8725 return true;
8726 }
8727
8728 private bool HandleParcelReturnObjects(IClientAPI sender, Packet Pack)
8729 {
8730 ParcelReturnObjectsPacket parcelReturnObjects = (ParcelReturnObjectsPacket)Pack;
8731
8732 #region Packet Session and User Check
8733 if (m_checkPackets)
8734 {
8735 if (parcelReturnObjects.AgentData.SessionID != SessionId ||
8736 parcelReturnObjects.AgentData.AgentID != AgentId)
8737 return true;
8738 }
8739 #endregion
8740
8741 UUID[] puserselectedOwnerIDs = new UUID[parcelReturnObjects.OwnerIDs.Length];
8742 for (int parceliterator = 0; parceliterator < parcelReturnObjects.OwnerIDs.Length; parceliterator++)
8743 puserselectedOwnerIDs[parceliterator] = parcelReturnObjects.OwnerIDs[parceliterator].OwnerID;
8744
8745 UUID[] puserselectedTaskIDs = new UUID[parcelReturnObjects.TaskIDs.Length];
8746
8747 for (int parceliterator = 0; parceliterator < parcelReturnObjects.TaskIDs.Length; parceliterator++)
8748 puserselectedTaskIDs[parceliterator] = parcelReturnObjects.TaskIDs[parceliterator].TaskID;
8749
8750 ParcelReturnObjectsRequest handlerParcelReturnObjectsRequest = OnParcelReturnObjectsRequest;
8751 if (handlerParcelReturnObjectsRequest != null)
8752 {
8753 handlerParcelReturnObjectsRequest(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, this);
8754
8755 }
8756 return true;
8757 }
8758
8759 private bool HandleParcelSetOtherCleanTime(IClientAPI sender, Packet Pack)
8760 {
8761 ParcelSetOtherCleanTimePacket parcelSetOtherCleanTimePacket = (ParcelSetOtherCleanTimePacket)Pack;
8762
8763 #region Packet Session and User Check
8764 if (m_checkPackets)
8765 {
8766 if (parcelSetOtherCleanTimePacket.AgentData.SessionID != SessionId ||
8767 parcelSetOtherCleanTimePacket.AgentData.AgentID != AgentId)
8768 return true;
8769 }
8770 #endregion
8771
8772 ParcelSetOtherCleanTime handlerParcelSetOtherCleanTime = OnParcelSetOtherCleanTime;
8773 if (handlerParcelSetOtherCleanTime != null)
8774 {
8775 handlerParcelSetOtherCleanTime(this,
8776 parcelSetOtherCleanTimePacket.ParcelData.LocalID,
8777 parcelSetOtherCleanTimePacket.ParcelData.OtherCleanTime);
8778 }
8779 return true;
8780 }
8781
8782 private bool HandleLandStatRequest(IClientAPI sender, Packet Pack)
8783 {
8784 LandStatRequestPacket lsrp = (LandStatRequestPacket)Pack;
8785
8786 #region Packet Session and User Check
8787 if (m_checkPackets)
8788 {
8789 if (lsrp.AgentData.SessionID != SessionId ||
8790 lsrp.AgentData.AgentID != AgentId)
8791 return true;
8792 }
8793 #endregion
8794
8795 GodLandStatRequest handlerLandStatRequest = OnLandStatRequest;
8796 if (handlerLandStatRequest != null)
8797 {
8798 handlerLandStatRequest(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Utils.BytesToString(lsrp.RequestData.Filter), this);
8799 }
8800 return true;
8801 }
8802
8803 private bool HandleParcelDwellRequest(IClientAPI sender, Packet Pack)
8804 {
8805 ParcelDwellRequestPacket dwellrq =
8806 (ParcelDwellRequestPacket)Pack;
8807
8808 #region Packet Session and User Check
8809 if (m_checkPackets)
8810 {
8811 if (dwellrq.AgentData.SessionID != SessionId ||
8812 dwellrq.AgentData.AgentID != AgentId)
8813 return true;
8814 }
8815 #endregion
8816
8817 ParcelDwellRequest handlerParcelDwellRequest = OnParcelDwellRequest;
8818 if (handlerParcelDwellRequest != null)
8819 {
8820 handlerParcelDwellRequest(dwellrq.Data.LocalID, this);
8821 }
8822 return true;
8823 }
8824
8825 #endregion Parcel related packets
8826
8827 #region Estate Packets
8828
8829 private bool HandleEstateOwnerMessage(IClientAPI sender, Packet Pack)
8830 {
8831 EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack;
8832 //m_log.Debug(messagePacket.ToString());
8833 GodLandStatRequest handlerLandStatRequest;
8834
8835 #region Packet Session and User Check
8836 if (m_checkPackets)
8837 {
8838 if (messagePacket.AgentData.SessionID != SessionId ||
8839 messagePacket.AgentData.AgentID != AgentId)
8840 return true;
8841 }
8842 #endregion
8843
8844 switch (Utils.BytesToString(messagePacket.MethodData.Method))
8845 {
8846 case "getinfo":
8847 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8848 {
8849 OnDetailedEstateDataRequest(this, messagePacket.MethodData.Invoice);
8850 }
8851 return true;
8852 case "setregioninfo":
8853 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8854 {
8855 OnSetEstateFlagsRequest(convertParamStringToBool(messagePacket.ParamList[0].Parameter), convertParamStringToBool(messagePacket.ParamList[1].Parameter),
8856 convertParamStringToBool(messagePacket.ParamList[2].Parameter), !convertParamStringToBool(messagePacket.ParamList[3].Parameter),
8857 Convert.ToInt16(Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[4].Parameter), Culture.NumberFormatInfo)),
8858 (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter), Culture.NumberFormatInfo),
8859 Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[6].Parameter)),
8860 convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter));
8861 }
8862 return true;
8863 // case "texturebase":
8864 // if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8865 // {
8866 // foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
8867 // {
8868 // string s = Utils.BytesToString(block.Parameter);
8869 // string[] splitField = s.Split(' ');
8870 // if (splitField.Length == 2)
8871 // {
8872 // UUID tempUUID = new UUID(splitField[1]);
8873 // OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID);
8874 // }
8875 // }
8876 // }
8877 // break;
8878 case "texturedetail":
8879 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8880 {
8881 foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
8882 {
8883 string s = Utils.BytesToString(block.Parameter);
8884 string[] splitField = s.Split(' ');
8885 if (splitField.Length == 2)
8886 {
8887 Int16 corner = Convert.ToInt16(splitField[0]);
8888 UUID textureUUID = new UUID(splitField[1]);
8889
8890 OnSetEstateTerrainDetailTexture(this, corner, textureUUID);
8891 }
8892 }
8893 }
8894
8895 return true;
8896 case "textureheights":
8897 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8898 {
8899 foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
8900 {
8901 string s = Utils.BytesToString(block.Parameter);
8902 string[] splitField = s.Split(' ');
8903 if (splitField.Length == 3)
8904 {
8905 Int16 corner = Convert.ToInt16(splitField[0]);
8906 float lowValue = (float)Convert.ToDecimal(splitField[1], Culture.NumberFormatInfo);
8907 float highValue = (float)Convert.ToDecimal(splitField[2], Culture.NumberFormatInfo);
8908
8909 OnSetEstateTerrainTextureHeights(this, corner, lowValue, highValue);
8910 }
8911 }
8912 }
8913 return true;
8914 case "texturecommit":
8915 OnCommitEstateTerrainTextureRequest(this);
8916 return true;
8917 case "setregionterrain":
8918 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8919 {
8920 if (messagePacket.ParamList.Length != 9)
8921 {
8922 m_log.Error("EstateOwnerMessage: SetRegionTerrain method has a ParamList of invalid length");
8923 }
8924 else
8925 {
8926 try
8927 {
8928 string tmp = Utils.BytesToString(messagePacket.ParamList[0].Parameter);
8929 if (!tmp.Contains(".")) tmp += ".00";
8930 float WaterHeight = (float)Convert.ToDecimal(tmp, Culture.NumberFormatInfo);
8931 tmp = Utils.BytesToString(messagePacket.ParamList[1].Parameter);
8932 if (!tmp.Contains(".")) tmp += ".00";
8933 float TerrainRaiseLimit = (float)Convert.ToDecimal(tmp, Culture.NumberFormatInfo);
8934 tmp = Utils.BytesToString(messagePacket.ParamList[2].Parameter);
8935 if (!tmp.Contains(".")) tmp += ".00";
8936 float TerrainLowerLimit = (float)Convert.ToDecimal(tmp, Culture.NumberFormatInfo);
8937 bool UseEstateSun = convertParamStringToBool(messagePacket.ParamList[3].Parameter);
8938 bool UseFixedSun = convertParamStringToBool(messagePacket.ParamList[4].Parameter);
8939 float SunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter), Culture.NumberFormatInfo);
8940 bool UseGlobal = convertParamStringToBool(messagePacket.ParamList[6].Parameter);
8941 bool EstateFixedSun = convertParamStringToBool(messagePacket.ParamList[7].Parameter);
8942 float EstateSunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[8].Parameter), Culture.NumberFormatInfo);
8943
8944 OnSetRegionTerrainSettings(WaterHeight, TerrainRaiseLimit, TerrainLowerLimit, UseEstateSun, UseFixedSun, SunHour, UseGlobal, EstateFixedSun, EstateSunHour);
8945
8946 }
8947 catch (Exception ex)
8948 {
8949 m_log.Error("EstateOwnerMessage: Exception while setting terrain settings: \n" + messagePacket + "\n" + ex);
8950 }
8951 }
8952 }
8953
8954 return true;
8955 case "restart":
8956 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8957 {
8958 // There's only 1 block in the estateResetSim.. and that's the number of seconds till restart.
8959 foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
8960 {
8961 float timeSeconds;
8962 Utils.TryParseSingle(Utils.BytesToString(block.Parameter), out timeSeconds);
8963 timeSeconds = (int)timeSeconds;
8964 OnEstateRestartSimRequest(this, (int)timeSeconds);
8965
8966 }
8967 }
8968 return true;
8969 case "estatechangecovenantid":
8970 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8971 {
8972 foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
8973 {
8974 UUID newCovenantID = new UUID(Utils.BytesToString(block.Parameter));
8975 OnEstateChangeCovenantRequest(this, newCovenantID);
8976 }
8977 }
8978 return true;
8979 case "estateaccessdelta": // Estate access delta manages the banlist and allow list too.
8980 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8981 {
8982 int estateAccessType = Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[1].Parameter));
8983 OnUpdateEstateAccessDeltaRequest(this, messagePacket.MethodData.Invoice, estateAccessType, new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)));
8984
8985 }
8986 return true;
8987 case "simulatormessage":
8988 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8989 {
8990 UUID invoice = messagePacket.MethodData.Invoice;
8991 UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
8992 string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter);
8993 string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter);
8994 UUID sessionID = messagePacket.AgentData.SessionID;
8995 OnSimulatorBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message);
8996 }
8997 return true;
8998 case "instantmessage":
8999 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9000 {
9001 if (messagePacket.ParamList.Length < 2)
9002 return true;
9003
9004 UUID invoice = messagePacket.MethodData.Invoice;
9005 UUID sessionID = messagePacket.AgentData.SessionID;
9006
9007 UUID SenderID;
9008 string SenderName;
9009 string Message;
9010
9011 if (messagePacket.ParamList.Length < 5)
9012 {
9013 SenderID = AgentId;
9014 SenderName = Utils.BytesToString(messagePacket.ParamList[0].Parameter);
9015 Message = Utils.BytesToString(messagePacket.ParamList[1].Parameter);
9016 }
9017 else
9018 {
9019 SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
9020 SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter);
9021 Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter);
9022 }
9023
9024 OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message);
9025 }
9026 return true;
9027 case "setregiondebug":
9028 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9029 {
9030 UUID invoice = messagePacket.MethodData.Invoice;
9031 UUID SenderID = messagePacket.AgentData.AgentID;
9032 bool scripted = convertParamStringToBool(messagePacket.ParamList[0].Parameter);
9033 bool collisionEvents = convertParamStringToBool(messagePacket.ParamList[1].Parameter);
9034 bool physics = convertParamStringToBool(messagePacket.ParamList[2].Parameter);
9035
9036 OnEstateDebugRegionRequest(this, invoice, SenderID, scripted, collisionEvents, physics);
9037 }
9038 return true;
9039 case "teleporthomeuser":
9040 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9041 {
9042 UUID invoice = messagePacket.MethodData.Invoice;
9043 UUID SenderID = messagePacket.AgentData.AgentID;
9044 UUID Prey;
9045
9046 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey);
9047
9048 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey);
9049 }
9050 return true;
9051 case "teleporthomeallusers":
9052 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9053 {
9054 UUID invoice = messagePacket.MethodData.Invoice;
9055 UUID SenderID = messagePacket.AgentData.AgentID;
9056 OnEstateTeleportAllUsersHomeRequest(this, invoice, SenderID);
9057 }
9058 return true;
9059 case "colliders":
9060 handlerLandStatRequest = OnLandStatRequest;
9061 if (handlerLandStatRequest != null)
9062 {
9063 handlerLandStatRequest(0, 1, 0, "", this);
9064 }
9065 return true;
9066 case "scripts":
9067 handlerLandStatRequest = OnLandStatRequest;
9068 if (handlerLandStatRequest != null)
9069 {
9070 handlerLandStatRequest(0, 0, 0, "", this);
9071 }
9072 return true;
9073 case "terrain":
9074 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9075 {
9076 if (messagePacket.ParamList.Length > 0)
9077 {
9078 if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "bake")
9079 {
9080 BakeTerrain handlerBakeTerrain = OnBakeTerrain;
9081 if (handlerBakeTerrain != null)
9082 {
9083 handlerBakeTerrain(this);
9084 }
9085 }
9086 if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "download filename")
9087 {
9088 if (messagePacket.ParamList.Length > 1)
9089 {
9090 RequestTerrain handlerRequestTerrain = OnRequestTerrain;
9091 if (handlerRequestTerrain != null)
9092 {
9093 handlerRequestTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter));
9094 }
9095 }
9096 }
9097 if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "upload filename")
9098 {
9099 if (messagePacket.ParamList.Length > 1)
9100 {
9101 RequestTerrain handlerUploadTerrain = OnUploadTerrain;
9102 if (handlerUploadTerrain != null)
9103 {
9104 handlerUploadTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter));
9105 }
9106 }
9107 }
9108
9109 }
9110
9111
9112 }
9113 return true;
9114
9115 case "estatechangeinfo":
9116 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9117 {
9118 UUID invoice = messagePacket.MethodData.Invoice;
9119 UUID SenderID = messagePacket.AgentData.AgentID;
9120 UInt32 param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter));
9121 UInt32 param2 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
9122
9123 EstateChangeInfo handlerEstateChangeInfo = OnEstateChangeInfo;
9124 if (handlerEstateChangeInfo != null)
9125 {
9126 handlerEstateChangeInfo(this, invoice, SenderID, param1, param2);
9127 }
9128 }
9129 return true;
9130
9131 default:
9132 m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket);
9133 return true;
9134 }
9135
9136 //int parcelID, uint reportType, uint requestflags, string filter
9137
9138 //lsrp.RequestData.ParcelLocalID;
9139 //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts
9140 //lsrp.RequestData.RequestFlags;
9141 //lsrp.RequestData.Filter;
9142
9143// return true;
9144 }
9145
9146 private bool HandleRequestRegionInfo(IClientAPI sender, Packet Pack)
9147 {
9148 RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData;
9149
9150 #region Packet Session and User Check
9151 if (m_checkPackets)
9152 {
9153 if (mPacket.SessionID != SessionId ||
9154 mPacket.AgentID != AgentId)
9155 return true;
9156 }
9157 #endregion
9158
9159 RegionInfoRequest handlerRegionInfoRequest = OnRegionInfoRequest;
9160 if (handlerRegionInfoRequest != null)
9161 {
9162 handlerRegionInfoRequest(this);
9163 }
9164 return true;
9165 }
9166
9167 private bool HandleEstateCovenantRequest(IClientAPI sender, Packet Pack)
9168 {
9169
9170 //EstateCovenantRequestPacket.AgentDataBlock epack =
9171 // ((EstateCovenantRequestPacket)Pack).AgentData;
9172
9173 EstateCovenantRequest handlerEstateCovenantRequest = OnEstateCovenantRequest;
9174 if (handlerEstateCovenantRequest != null)
9175 {
9176 handlerEstateCovenantRequest(this);
9177 }
9178 return true;
9179
9180 }
9181
9182 #endregion Estate Packets
9183
9184 #region GodPackets
9185
9186 private bool HandleRequestGodlikePowers(IClientAPI sender, Packet Pack)
9187 {
9188 RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack;
9189 RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock;
9190 UUID token = rblock.Token;
9191
9192 RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData;
9193
9194 RequestGodlikePowers handlerReqGodlikePowers = OnRequestGodlikePowers;
9195
9196 if (handlerReqGodlikePowers != null)
9197 {
9198 handlerReqGodlikePowers(ablock.AgentID, ablock.SessionID, token, rblock.Godlike, this);
9199 }
9200
9201 return true;
9202 }
9203
9204 private bool HandleGodUpdateRegionInfoUpdate(IClientAPI client, Packet Packet)
9205 {
9206 GodUpdateRegionInfoPacket GodUpdateRegionInfo =
9207 (GodUpdateRegionInfoPacket)Packet;
9208
9209 GodUpdateRegionInfoUpdate handlerGodUpdateRegionInfo = OnGodUpdateRegionInfoUpdate;
9210 if (handlerGodUpdateRegionInfo != null)
9211 {
9212 handlerGodUpdateRegionInfo(this,
9213 GodUpdateRegionInfo.RegionInfo.BillableFactor,
9214 GodUpdateRegionInfo.RegionInfo.EstateID,
9215 GodUpdateRegionInfo.RegionInfo.RegionFlags,
9216 GodUpdateRegionInfo.RegionInfo.SimName,
9217 GodUpdateRegionInfo.RegionInfo.RedirectGridX,
9218 GodUpdateRegionInfo.RegionInfo.RedirectGridY);
9219 return true;
9220 }
9221 return false;
9222 }
9223
9224 private bool HandleSimWideDeletes(IClientAPI client, Packet Packet)
9225 {
9226 SimWideDeletesPacket SimWideDeletesRequest =
9227 (SimWideDeletesPacket)Packet;
9228 SimWideDeletesDelegate handlerSimWideDeletesRequest = OnSimWideDeletes;
9229 if (handlerSimWideDeletesRequest != null)
9230 {
9231 handlerSimWideDeletesRequest(this, SimWideDeletesRequest.AgentData.AgentID,(int)SimWideDeletesRequest.DataBlock.Flags,SimWideDeletesRequest.DataBlock.TargetID);
9232 return true;
9233 }
9234 return false;
9235 }
9236
9237 private bool HandleGodlikeMessage(IClientAPI client, Packet Packet)
9238 {
9239 GodlikeMessagePacket GodlikeMessage =
9240 (GodlikeMessagePacket)Packet;
9241
9242 GodlikeMessage handlerGodlikeMessage = onGodlikeMessage;
9243 if (handlerGodlikeMessage != null)
9244 {
9245 handlerGodlikeMessage(this,
9246 GodlikeMessage.MethodData.Invoice,
9247 GodlikeMessage.MethodData.Method,
9248 GodlikeMessage.ParamList[0].Parameter);
9249 return true;
9250 }
9251 return false;
9252 }
9253
9254 private bool HandleSaveStatePacket(IClientAPI client, Packet Packet)
9255 {
9256 StateSavePacket SaveStateMessage =
9257 (StateSavePacket)Packet;
9258 SaveStateHandler handlerSaveStatePacket = OnSaveState;
9259 if (handlerSaveStatePacket != null)
9260 {
9261 handlerSaveStatePacket(this,SaveStateMessage.AgentData.AgentID);
9262 return true;
9263 }
9264 return false;
9265 }
9266
9267 private bool HandleGodKickUser(IClientAPI sender, Packet Pack)
9268 {
9269 GodKickUserPacket gkupack = (GodKickUserPacket)Pack;
9270
9271 if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID)
9272 {
9273 GodKickUser handlerGodKickUser = OnGodKickUser;
9274 if (handlerGodKickUser != null)
9275 {
9276 handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID,
9277 gkupack.UserInfo.AgentID, gkupack.UserInfo.KickFlags, gkupack.UserInfo.Reason);
9278 }
9279 }
9280 else
9281 {
9282 SendAgentAlertMessage("Kick request denied", false);
9283 }
9284 //KickUserPacket kupack = new KickUserPacket();
9285 //KickUserPacket.UserInfoBlock kupackib = kupack.UserInfo;
9286
9287 //kupack.UserInfo.AgentID = gkupack.UserInfo.AgentID;
9288 //kupack.UserInfo.SessionID = gkupack.UserInfo.GodSessionID;
9289
9290 //kupack.TargetBlock.TargetIP = (uint)0;
9291 //kupack.TargetBlock.TargetPort = (ushort)0;
9292 //kupack.UserInfo.Reason = gkupack.UserInfo.Reason;
9293
9294 //OutPacket(kupack, ThrottleOutPacketType.Task);
9295 return true;
9296 }
9297 #endregion GodPackets
9298
9299 #region Economy/Transaction Packets
9300
9301 private bool HandleMoneyBalanceRequest(IClientAPI sender, Packet Pack)
9302 {
9303 MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack;
9304
9305 #region Packet Session and User Check
9306 if (m_checkPackets)
9307 {
9308 if (moneybalancerequestpacket.AgentData.SessionID != SessionId ||
9309 moneybalancerequestpacket.AgentData.AgentID != AgentId)
9310 return true;
9311 }
9312 #endregion
9313
9314 MoneyBalanceRequest handlerMoneyBalanceRequest = OnMoneyBalanceRequest;
9315
9316 if (handlerMoneyBalanceRequest != null)
9317 {
9318 handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID);
9319 }
9320
9321 return true;
9322 }
9323 private bool HandleEconomyDataRequest(IClientAPI sender, Packet Pack)
9324 {
9325 EconomyDataRequest handlerEconomoyDataRequest = OnEconomyDataRequest;
9326 if (handlerEconomoyDataRequest != null)
9327 {
9328 handlerEconomoyDataRequest(AgentId);
9329 }
9330 return true;
9331 }
9332 private bool HandleRequestPayPrice(IClientAPI sender, Packet Pack)
9333 {
9334 RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack;
9335
9336 RequestPayPrice handlerRequestPayPrice = OnRequestPayPrice;
9337 if (handlerRequestPayPrice != null)
9338 {
9339 handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID);
9340 }
9341 return true;
9342 }
9343 private bool HandleObjectSaleInfo(IClientAPI sender, Packet Pack)
9344 {
9345 ObjectSaleInfoPacket objectSaleInfoPacket = (ObjectSaleInfoPacket)Pack;
9346
9347 #region Packet Session and User Check
9348 if (m_checkPackets)
9349 {
9350 if (objectSaleInfoPacket.AgentData.SessionID != SessionId ||
9351 objectSaleInfoPacket.AgentData.AgentID != AgentId)
9352 return true;
9353 }
9354 #endregion
9355
9356 ObjectSaleInfo handlerObjectSaleInfo = OnObjectSaleInfo;
9357 if (handlerObjectSaleInfo != null)
9358 {
9359 foreach (ObjectSaleInfoPacket.ObjectDataBlock d
9360 in objectSaleInfoPacket.ObjectData)
9361 {
9362 handlerObjectSaleInfo(this,
9363 objectSaleInfoPacket.AgentData.AgentID,
9364 objectSaleInfoPacket.AgentData.SessionID,
9365 d.LocalID,
9366 d.SaleType,
9367 d.SalePrice);
9368 }
9369 }
9370 return true;
9371 }
9372 private bool HandleObjectBuy(IClientAPI sender, Packet Pack)
9373 {
9374 ObjectBuyPacket objectBuyPacket = (ObjectBuyPacket)Pack;
9375
9376 #region Packet Session and User Check
9377 if (m_checkPackets)
9378 {
9379 if (objectBuyPacket.AgentData.SessionID != SessionId ||
9380 objectBuyPacket.AgentData.AgentID != AgentId)
9381 return true;
9382 }
9383 #endregion
9384
9385 ObjectBuy handlerObjectBuy = OnObjectBuy;
9386
9387 if (handlerObjectBuy != null)
9388 {
9389 foreach (ObjectBuyPacket.ObjectDataBlock d
9390 in objectBuyPacket.ObjectData)
9391 {
9392 handlerObjectBuy(this,
9393 objectBuyPacket.AgentData.AgentID,
9394 objectBuyPacket.AgentData.SessionID,
9395 objectBuyPacket.AgentData.GroupID,
9396 objectBuyPacket.AgentData.CategoryID,
9397 d.ObjectLocalID,
9398 d.SaleType,
9399 d.SalePrice);
9400 }
9401 }
9402 return true;
9403 }
9404
9405 #endregion Economy/Transaction Packets
9406
9407 #region Script Packets
9408 private bool HandleGetScriptRunning(IClientAPI sender, Packet Pack)
9409 {
9410 GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack;
9411
9412 GetScriptRunning handlerGetScriptRunning = OnGetScriptRunning;
9413 if (handlerGetScriptRunning != null)
9414 {
9415 handlerGetScriptRunning(this, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID);
9416 }
9417 return true;
9418 }
9419 private bool HandleSetScriptRunning(IClientAPI sender, Packet Pack)
9420 {
9421 SetScriptRunningPacket setScriptRunning = (SetScriptRunningPacket)Pack;
9422
9423 #region Packet Session and User Check
9424 if (m_checkPackets)
9425 {
9426 if (setScriptRunning.AgentData.SessionID != SessionId ||
9427 setScriptRunning.AgentData.AgentID != AgentId)
9428 return true;
9429 }
9430 #endregion
9431
9432 SetScriptRunning handlerSetScriptRunning = OnSetScriptRunning;
9433 if (handlerSetScriptRunning != null)
9434 {
9435 handlerSetScriptRunning(this, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running);
9436 }
9437 return true;
9438 }
9439
9440 private bool HandleScriptReset(IClientAPI sender, Packet Pack)
9441 {
9442 ScriptResetPacket scriptResetPacket = (ScriptResetPacket)Pack;
9443
9444 #region Packet Session and User Check
9445 if (m_checkPackets)
9446 {
9447 if (scriptResetPacket.AgentData.SessionID != SessionId ||
9448 scriptResetPacket.AgentData.AgentID != AgentId)
9449 return true;
9450 }
9451 #endregion
9452
9453 ScriptReset handlerScriptReset = OnScriptReset;
9454 if (handlerScriptReset != null)
9455 {
9456 handlerScriptReset(this, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID);
9457 }
9458 return true;
9459 }
9460
9461 #endregion Script Packets
9462
9463 #region Gesture Managment
9464
9465 private bool HandleActivateGestures(IClientAPI sender, Packet Pack)
9466 {
9467 ActivateGesturesPacket activateGesturePacket = (ActivateGesturesPacket)Pack;
9468
9469 #region Packet Session and User Check
9470 if (m_checkPackets)
9471 {
9472 if (activateGesturePacket.AgentData.SessionID != SessionId ||
9473 activateGesturePacket.AgentData.AgentID != AgentId)
9474 return true;
9475 }
9476 #endregion
9477
9478 ActivateGesture handlerActivateGesture = OnActivateGesture;
9479 if (handlerActivateGesture != null)
9480 {
9481 handlerActivateGesture(this,
9482 activateGesturePacket.Data[0].AssetID,
9483 activateGesturePacket.Data[0].ItemID);
9484 }
9485 else m_log.Error("Null pointer for activateGesture");
9486
9487 return true;
9488 }
9489 private bool HandleDeactivateGestures(IClientAPI sender, Packet Pack)
9490 {
9491 DeactivateGesturesPacket deactivateGesturePacket = (DeactivateGesturesPacket)Pack;
9492
9493 #region Packet Session and User Check
9494 if (m_checkPackets)
9495 {
9496 if (deactivateGesturePacket.AgentData.SessionID != SessionId ||
9497 deactivateGesturePacket.AgentData.AgentID != AgentId)
9498 return true;
9499 }
9500 #endregion
9501
9502 DeactivateGesture handlerDeactivateGesture = OnDeactivateGesture;
9503 if (handlerDeactivateGesture != null)
9504 {
9505 handlerDeactivateGesture(this, deactivateGesturePacket.Data[0].ItemID);
9506 }
9507 return true;
9508 }
9509 private bool HandleObjectOwner(IClientAPI sender, Packet Pack)
9510 {
9511 ObjectOwnerPacket objectOwnerPacket = (ObjectOwnerPacket)Pack;
9512
9513 #region Packet Session and User Check
9514 if (m_checkPackets)
9515 {
9516 if (objectOwnerPacket.AgentData.SessionID != SessionId ||
9517 objectOwnerPacket.AgentData.AgentID != AgentId)
9518 return true;
9519 }
9520 #endregion
9521
9522 List<uint> localIDs = new List<uint>();
9523
9524 foreach (ObjectOwnerPacket.ObjectDataBlock d in objectOwnerPacket.ObjectData)
9525 localIDs.Add(d.ObjectLocalID);
9526
9527 ObjectOwner handlerObjectOwner = OnObjectOwner;
9528 if (handlerObjectOwner != null)
9529 {
9530 handlerObjectOwner(this, objectOwnerPacket.HeaderData.OwnerID, objectOwnerPacket.HeaderData.GroupID, localIDs);
9531 }
9532 return true;
9533 }
9534
9535 #endregion Gesture Managment
9536
9537 private bool HandleAgentFOV(IClientAPI sender, Packet Pack)
9538 {
9539 AgentFOVPacket fovPacket = (AgentFOVPacket)Pack;
9540
9541 if (fovPacket.FOVBlock.GenCounter > m_agentFOVCounter)
9542 {
9543 m_agentFOVCounter = fovPacket.FOVBlock.GenCounter;
9544 AgentFOV handlerAgentFOV = OnAgentFOV;
9545 if (handlerAgentFOV != null)
9546 {
9547 handlerAgentFOV(this, fovPacket.FOVBlock.VerticalAngle);
9548 }
9549 }
9550 return true;
9551 }
9552
9553 #region unimplemented handlers
9554
9555 private bool HandleViewerStats(IClientAPI sender, Packet Pack)
9556 {
9557 // TODO: handle this packet
9558 //m_log.Warn("[CLIENT]: unhandled ViewerStats packet");
9559 return true;
9560 }
9561
9562 private bool HandleMapItemRequest(IClientAPI sender, Packet Pack)
9563 {
9564 MapItemRequestPacket mirpk = (MapItemRequestPacket)Pack;
9565
9566 #region Packet Session and User Check
9567 if (m_checkPackets)
9568 {
9569 if (mirpk.AgentData.SessionID != SessionId ||
9570 mirpk.AgentData.AgentID != AgentId)
9571 return true;
9572 }
9573 #endregion
9574
9575 //m_log.Debug(mirpk.ToString());
9576 MapItemRequest handlerMapItemRequest = OnMapItemRequest;
9577 if (handlerMapItemRequest != null)
9578 {
9579 handlerMapItemRequest(this, mirpk.AgentData.Flags, mirpk.AgentData.EstateID,
9580 mirpk.AgentData.Godlike, mirpk.RequestData.ItemType,
9581 mirpk.RequestData.RegionHandle);
9582
9583 }
9584 return true;
9585 }
9586
9587 private bool HandleTransferAbort(IClientAPI sender, Packet Pack)
9588 {
9589 return true;
9590 }
9591
9592 private bool HandleMuteListRequest(IClientAPI sender, Packet Pack)
9593 {
9594 MuteListRequestPacket muteListRequest =
9595 (MuteListRequestPacket)Pack;
9596
9597 #region Packet Session and User Check
9598 if (m_checkPackets)
9599 {
9600 if (muteListRequest.AgentData.SessionID != SessionId ||
9601 muteListRequest.AgentData.AgentID != AgentId)
9602 return true;
9603 }
9604 #endregion
9605
9606 MuteListRequest handlerMuteListRequest = OnMuteListRequest;
9607 if (handlerMuteListRequest != null)
9608 {
9609 handlerMuteListRequest(this, muteListRequest.MuteData.MuteCRC);
9610 }
9611 else
9612 {
9613 SendUseCachedMuteList();
9614 }
9615 return true;
9616 }
9617
9618 private bool HandleUpdateMuteListEntry(IClientAPI client, Packet Packet)
9619 {
9620 UpdateMuteListEntryPacket UpdateMuteListEntry =
9621 (UpdateMuteListEntryPacket)Packet;
9622 MuteListEntryUpdate handlerUpdateMuteListEntry = OnUpdateMuteListEntry;
9623 if (handlerUpdateMuteListEntry != null)
9624 {
9625 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9626 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9627 UpdateMuteListEntry.MuteData.MuteType,
9628 UpdateMuteListEntry.AgentData.AgentID);
9629 return true;
9630 }
9631 return false;
9632 }
9633
9634 private bool HandleRemoveMuteListEntry(IClientAPI client, Packet Packet)
9635 {
9636 RemoveMuteListEntryPacket RemoveMuteListEntry =
9637 (RemoveMuteListEntryPacket)Packet;
9638 MuteListEntryRemove handlerRemoveMuteListEntry = OnRemoveMuteListEntry;
9639 if (handlerRemoveMuteListEntry != null)
9640 {
9641 handlerRemoveMuteListEntry(this,
9642 RemoveMuteListEntry.MuteData.MuteID,
9643 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName),
9644 RemoveMuteListEntry.AgentData.AgentID);
9645 return true;
9646 }
9647 return false;
9648 }
9649
9650 private bool HandleUserReport(IClientAPI client, Packet Packet)
9651 {
9652 UserReportPacket UserReport =
9653 (UserReportPacket)Packet;
9654
9655 NewUserReport handlerUserReport = OnUserReport;
9656 if (handlerUserReport != null)
9657 {
9658 handlerUserReport(this,
9659 Utils.BytesToString(UserReport.ReportData.AbuseRegionName),
9660 UserReport.ReportData.AbuserID,
9661 UserReport.ReportData.Category,
9662 UserReport.ReportData.CheckFlags,
9663 Utils.BytesToString(UserReport.ReportData.Details),
9664 UserReport.ReportData.ObjectID,
9665 UserReport.ReportData.Position,
9666 UserReport.ReportData.ReportType,
9667 UserReport.ReportData.ScreenshotID,
9668 Utils.BytesToString(UserReport.ReportData.Summary),
9669 UserReport.AgentData.AgentID);
9670 return true;
9671 }
9672 return false;
9673 }
9674
9675 private bool HandleSendPostcard(IClientAPI client, Packet packet)
9676 {
9677// SendPostcardPacket SendPostcard =
9678// (SendPostcardPacket)packet;
9679 SendPostcard handlerSendPostcard = OnSendPostcard;
9680 if (handlerSendPostcard != null)
9681 {
9682 handlerSendPostcard(this);
9683 return true;
9684 }
9685 return false;
9686 }
9687
9688 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack)
9689 {
9690 return true;
9691 }
9692
9693 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9694 {
9695 return true;
9696 }
9697
9698 private bool HandleInventoryDescendents(IClientAPI sender, Packet Pack)
9699 {
9700 return true;
9701 }
9702
9703 #endregion unimplemented handlers
9704
9705 #region Dir handlers
9706
9707 private bool HandleDirPlacesQuery(IClientAPI sender, Packet Pack)
9708 {
9709 DirPlacesQueryPacket dirPlacesQueryPacket = (DirPlacesQueryPacket)Pack;
9710 //m_log.Debug(dirPlacesQueryPacket.ToString());
9711
9712 #region Packet Session and User Check
9713 if (m_checkPackets)
9714 {
9715 if (dirPlacesQueryPacket.AgentData.SessionID != SessionId ||
9716 dirPlacesQueryPacket.AgentData.AgentID != AgentId)
9717 return true;
9718 }
9719 #endregion
9720
9721 DirPlacesQuery handlerDirPlacesQuery = OnDirPlacesQuery;
9722 if (handlerDirPlacesQuery != null)
9723 {
9724 handlerDirPlacesQuery(this,
9725 dirPlacesQueryPacket.QueryData.QueryID,
9726 Utils.BytesToString(
9727 dirPlacesQueryPacket.QueryData.QueryText),
9728 (int)dirPlacesQueryPacket.QueryData.QueryFlags,
9729 (int)dirPlacesQueryPacket.QueryData.Category,
9730 Utils.BytesToString(
9731 dirPlacesQueryPacket.QueryData.SimName),
9732 dirPlacesQueryPacket.QueryData.QueryStart);
9733 }
9734 return true;
9735 }
9736
9737 private bool HandleDirFindQuery(IClientAPI sender, Packet Pack)
9738 {
9739 DirFindQueryPacket dirFindQueryPacket = (DirFindQueryPacket)Pack;
9740
9741 #region Packet Session and User Check
9742 if (m_checkPackets)
9743 {
9744 if (dirFindQueryPacket.AgentData.SessionID != SessionId ||
9745 dirFindQueryPacket.AgentData.AgentID != AgentId)
9746 return true;
9747 }
9748 #endregion
9749
9750 DirFindQuery handlerDirFindQuery = OnDirFindQuery;
9751 if (handlerDirFindQuery != null)
9752 {
9753 handlerDirFindQuery(this,
9754 dirFindQueryPacket.QueryData.QueryID,
9755 Utils.BytesToString(
9756 dirFindQueryPacket.QueryData.QueryText),
9757 dirFindQueryPacket.QueryData.QueryFlags,
9758 dirFindQueryPacket.QueryData.QueryStart);
9759 }
9760 return true;
9761 }
9762
9763 private bool HandleDirLandQuery(IClientAPI sender, Packet Pack)
9764 {
9765 DirLandQueryPacket dirLandQueryPacket = (DirLandQueryPacket)Pack;
9766
9767 #region Packet Session and User Check
9768 if (m_checkPackets)
9769 {
9770 if (dirLandQueryPacket.AgentData.SessionID != SessionId ||
9771 dirLandQueryPacket.AgentData.AgentID != AgentId)
9772 return true;
9773 }
9774 #endregion
9775
9776 DirLandQuery handlerDirLandQuery = OnDirLandQuery;
9777 if (handlerDirLandQuery != null)
9778 {
9779 handlerDirLandQuery(this,
9780 dirLandQueryPacket.QueryData.QueryID,
9781 dirLandQueryPacket.QueryData.QueryFlags,
9782 dirLandQueryPacket.QueryData.SearchType,
9783 dirLandQueryPacket.QueryData.Price,
9784 dirLandQueryPacket.QueryData.Area,
9785 dirLandQueryPacket.QueryData.QueryStart);
9786 }
9787 return true;
9788 }
9789
9790 private bool HandleDirPopularQuery(IClientAPI sender, Packet Pack)
9791 {
9792 DirPopularQueryPacket dirPopularQueryPacket = (DirPopularQueryPacket)Pack;
9793
9794 #region Packet Session and User Check
9795 if (m_checkPackets)
9796 {
9797 if (dirPopularQueryPacket.AgentData.SessionID != SessionId ||
9798 dirPopularQueryPacket.AgentData.AgentID != AgentId)
9799 return true;
9800 }
9801 #endregion
9802
9803 DirPopularQuery handlerDirPopularQuery = OnDirPopularQuery;
9804 if (handlerDirPopularQuery != null)
9805 {
9806 handlerDirPopularQuery(this,
9807 dirPopularQueryPacket.QueryData.QueryID,
9808 dirPopularQueryPacket.QueryData.QueryFlags);
9809 }
9810 return true;
9811 }
9812
9813 private bool HandleDirClassifiedQuery(IClientAPI sender, Packet Pack)
9814 {
9815 DirClassifiedQueryPacket dirClassifiedQueryPacket = (DirClassifiedQueryPacket)Pack;
9816
9817 #region Packet Session and User Check
9818 if (m_checkPackets)
9819 {
9820 if (dirClassifiedQueryPacket.AgentData.SessionID != SessionId ||
9821 dirClassifiedQueryPacket.AgentData.AgentID != AgentId)
9822 return true;
9823 }
9824 #endregion
9825
9826 DirClassifiedQuery handlerDirClassifiedQuery = OnDirClassifiedQuery;
9827 if (handlerDirClassifiedQuery != null)
9828 {
9829 handlerDirClassifiedQuery(this,
9830 dirClassifiedQueryPacket.QueryData.QueryID,
9831 Utils.BytesToString(
9832 dirClassifiedQueryPacket.QueryData.QueryText),
9833 dirClassifiedQueryPacket.QueryData.QueryFlags,
9834 dirClassifiedQueryPacket.QueryData.Category,
9835 dirClassifiedQueryPacket.QueryData.QueryStart);
9836 }
9837 return true;
9838 }
9839
9840 private bool HandleEventInfoRequest(IClientAPI sender, Packet Pack)
9841 {
9842 EventInfoRequestPacket eventInfoRequestPacket = (EventInfoRequestPacket)Pack;
9843
9844 #region Packet Session and User Check
9845 if (m_checkPackets)
9846 {
9847 if (eventInfoRequestPacket.AgentData.SessionID != SessionId ||
9848 eventInfoRequestPacket.AgentData.AgentID != AgentId)
9849 return true;
9850 }
9851 #endregion
9852
9853 if (OnEventInfoRequest != null)
9854 {
9855 OnEventInfoRequest(this, eventInfoRequestPacket.EventData.EventID);
9856 }
9857 return true;
9858 }
9859
9860 #endregion
9861
9862 #region Calling Card
9863
9864 private bool HandleOfferCallingCard(IClientAPI sender, Packet Pack)
9865 {
9866 OfferCallingCardPacket offerCallingCardPacket = (OfferCallingCardPacket)Pack;
9867
9868 #region Packet Session and User Check
9869 if (m_checkPackets)
9870 {
9871 if (offerCallingCardPacket.AgentData.SessionID != SessionId ||
9872 offerCallingCardPacket.AgentData.AgentID != AgentId)
9873 return true;
9874 }
9875 #endregion
9876
9877 if (OnOfferCallingCard != null)
9878 {
9879 OnOfferCallingCard(this,
9880 offerCallingCardPacket.AgentBlock.DestID,
9881 offerCallingCardPacket.AgentBlock.TransactionID);
9882 }
9883 return true;
9884 }
9885
9886 private bool HandleAcceptCallingCard(IClientAPI sender, Packet Pack)
9887 {
9888 AcceptCallingCardPacket acceptCallingCardPacket = (AcceptCallingCardPacket)Pack;
9889
9890 #region Packet Session and User Check
9891 if (m_checkPackets)
9892 {
9893 if (acceptCallingCardPacket.AgentData.SessionID != SessionId ||
9894 acceptCallingCardPacket.AgentData.AgentID != AgentId)
9895 return true;
9896 }
9897 #endregion
9898
9899 // according to http://wiki.secondlife.com/wiki/AcceptCallingCard FolderData should
9900 // contain exactly one entry
9901 if (OnAcceptCallingCard != null && acceptCallingCardPacket.FolderData.Length > 0)
9902 {
9903 OnAcceptCallingCard(this,
9904 acceptCallingCardPacket.TransactionBlock.TransactionID,
9905 acceptCallingCardPacket.FolderData[0].FolderID);
9906 }
9907 return true;
9908 }
9909
9910 private bool HandleDeclineCallingCard(IClientAPI sender, Packet Pack)
9911 {
9912 DeclineCallingCardPacket declineCallingCardPacket = (DeclineCallingCardPacket)Pack;
9913
9914 #region Packet Session and User Check
9915 if (m_checkPackets)
9916 {
9917 if (declineCallingCardPacket.AgentData.SessionID != SessionId ||
9918 declineCallingCardPacket.AgentData.AgentID != AgentId)
9919 return true;
9920 }
9921 #endregion
9922
9923 if (OnDeclineCallingCard != null)
9924 {
9925 OnDeclineCallingCard(this,
9926 declineCallingCardPacket.TransactionBlock.TransactionID);
9927 }
9928 return true;
9929 }
9930
9931 #endregion Calling Card
9932
9933 #region Groups
9934
9935 private bool HandleActivateGroup(IClientAPI sender, Packet Pack)
9936 {
9937 ActivateGroupPacket activateGroupPacket = (ActivateGroupPacket)Pack;
9938
9939 #region Packet Session and User Check
9940 if (m_checkPackets)
9941 {
9942 if (activateGroupPacket.AgentData.SessionID != SessionId ||
9943 activateGroupPacket.AgentData.AgentID != AgentId)
9944 return true;
9945 }
9946 #endregion
9947
9948 if (m_GroupsModule != null)
9949 {
9950 m_GroupsModule.ActivateGroup(this, activateGroupPacket.AgentData.GroupID);
9951 m_GroupsModule.SendAgentGroupDataUpdate(this);
9952 }
9953 return true;
9954
9955 }
9956
9957 private bool HandleGroupVoteHistoryRequest(IClientAPI client, Packet Packet)
9958 {
9959 GroupVoteHistoryRequestPacket GroupVoteHistoryRequest =
9960 (GroupVoteHistoryRequestPacket)Packet;
9961 GroupVoteHistoryRequest handlerGroupVoteHistoryRequest = OnGroupVoteHistoryRequest;
9962 if (handlerGroupVoteHistoryRequest != null)
9963 {
9964 handlerGroupVoteHistoryRequest(this, GroupVoteHistoryRequest.AgentData.AgentID,GroupVoteHistoryRequest.AgentData.SessionID,GroupVoteHistoryRequest.GroupData.GroupID,GroupVoteHistoryRequest.TransactionData.TransactionID);
9965 return true;
9966 }
9967 return false;
9968 }
9969
9970 private bool HandleGroupActiveProposalsRequest(IClientAPI client, Packet Packet)
9971 {
9972 GroupActiveProposalsRequestPacket GroupActiveProposalsRequest =
9973 (GroupActiveProposalsRequestPacket)Packet;
9974 GroupActiveProposalsRequest handlerGroupActiveProposalsRequest = OnGroupActiveProposalsRequest;
9975 if (handlerGroupActiveProposalsRequest != null)
9976 {
9977 handlerGroupActiveProposalsRequest(this, GroupActiveProposalsRequest.AgentData.AgentID,GroupActiveProposalsRequest.AgentData.SessionID,GroupActiveProposalsRequest.GroupData.GroupID,GroupActiveProposalsRequest.TransactionData.TransactionID);
9978 return true;
9979 }
9980 return false;
9981 }
9982
9983 private bool HandleGroupAccountDetailsRequest(IClientAPI client, Packet Packet)
9984 {
9985 GroupAccountDetailsRequestPacket GroupAccountDetailsRequest =
9986 (GroupAccountDetailsRequestPacket)Packet;
9987 GroupAccountDetailsRequest handlerGroupAccountDetailsRequest = OnGroupAccountDetailsRequest;
9988 if (handlerGroupAccountDetailsRequest != null)
9989 {
9990 handlerGroupAccountDetailsRequest(this, GroupAccountDetailsRequest.AgentData.AgentID,GroupAccountDetailsRequest.AgentData.GroupID,GroupAccountDetailsRequest.MoneyData.RequestID,GroupAccountDetailsRequest.AgentData.SessionID);
9991 return true;
9992 }
9993 return false;
9994 }
9995
9996 private bool HandleGroupAccountSummaryRequest(IClientAPI client, Packet Packet)
9997 {
9998 GroupAccountSummaryRequestPacket GroupAccountSummaryRequest =
9999 (GroupAccountSummaryRequestPacket)Packet;
10000 GroupAccountSummaryRequest handlerGroupAccountSummaryRequest = OnGroupAccountSummaryRequest;
10001 if (handlerGroupAccountSummaryRequest != null)
10002 {
10003 handlerGroupAccountSummaryRequest(this, GroupAccountSummaryRequest.AgentData.AgentID,GroupAccountSummaryRequest.AgentData.GroupID);
10004 return true;
10005 }
10006 return false;
10007 }
10008
10009 private bool HandleGroupTransactionsDetailsRequest(IClientAPI client, Packet Packet)
10010 {
10011 GroupAccountTransactionsRequestPacket GroupAccountTransactionsRequest =
10012 (GroupAccountTransactionsRequestPacket)Packet;
10013 GroupAccountTransactionsRequest handlerGroupAccountTransactionsRequest = OnGroupAccountTransactionsRequest;
10014 if (handlerGroupAccountTransactionsRequest != null)
10015 {
10016 handlerGroupAccountTransactionsRequest(this, GroupAccountTransactionsRequest.AgentData.AgentID,GroupAccountTransactionsRequest.AgentData.GroupID,GroupAccountTransactionsRequest.MoneyData.RequestID,GroupAccountTransactionsRequest.AgentData.SessionID);
10017 return true;
10018 }
10019 return false;
10020 }
10021
10022 private bool HandleGroupTitlesRequest(IClientAPI sender, Packet Pack)
10023 {
10024 GroupTitlesRequestPacket groupTitlesRequest =
10025 (GroupTitlesRequestPacket)Pack;
10026
10027 #region Packet Session and User Check
10028 if (m_checkPackets)
10029 {
10030 if (groupTitlesRequest.AgentData.SessionID != SessionId ||
10031 groupTitlesRequest.AgentData.AgentID != AgentId)
10032 return true;
10033 }
10034 #endregion
10035
10036 if (m_GroupsModule != null)
10037 {
10038 GroupTitlesReplyPacket groupTitlesReply = (GroupTitlesReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupTitlesReply);
10039
10040 groupTitlesReply.AgentData =
10041 new GroupTitlesReplyPacket.AgentDataBlock();
10042
10043 groupTitlesReply.AgentData.AgentID = AgentId;
10044 groupTitlesReply.AgentData.GroupID =
10045 groupTitlesRequest.AgentData.GroupID;
10046
10047 groupTitlesReply.AgentData.RequestID =
10048 groupTitlesRequest.AgentData.RequestID;
10049
10050 List<GroupTitlesData> titles =
10051 m_GroupsModule.GroupTitlesRequest(this,
10052 groupTitlesRequest.AgentData.GroupID);
10053
10054 groupTitlesReply.GroupData =
10055 new GroupTitlesReplyPacket.GroupDataBlock[titles.Count];
10056
10057 int i = 0;
10058 foreach (GroupTitlesData d in titles)
10059 {
10060 groupTitlesReply.GroupData[i] =
10061 new GroupTitlesReplyPacket.GroupDataBlock();
10062
10063 groupTitlesReply.GroupData[i].Title =
10064 Util.StringToBytes256(d.Name);
10065 groupTitlesReply.GroupData[i].RoleID =
10066 d.UUID;
10067 groupTitlesReply.GroupData[i].Selected =
10068 d.Selected;
10069 i++;
10070 }
10071
10072 OutPacket(groupTitlesReply, ThrottleOutPacketType.Task);
10073 }
10074 return true;
10075 }
10076 private bool HandleGroupProfileRequest(IClientAPI sender, Packet Pack)
10077 {
10078 GroupProfileRequestPacket groupProfileRequest =
10079 (GroupProfileRequestPacket)Pack;
10080
10081 #region Packet Session and User Check
10082 if (m_checkPackets)
10083 {
10084 if (groupProfileRequest.AgentData.SessionID != SessionId ||
10085 groupProfileRequest.AgentData.AgentID != AgentId)
10086 return true;
10087 }
10088 #endregion
10089
10090 if (m_GroupsModule != null)
10091 {
10092 GroupProfileReplyPacket groupProfileReply = (GroupProfileReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupProfileReply);
10093
10094 groupProfileReply.AgentData = new GroupProfileReplyPacket.AgentDataBlock();
10095 groupProfileReply.GroupData = new GroupProfileReplyPacket.GroupDataBlock();
10096 groupProfileReply.AgentData.AgentID = AgentId;
10097
10098 GroupProfileData d = m_GroupsModule.GroupProfileRequest(this,
10099 groupProfileRequest.GroupData.GroupID);
10100
10101 groupProfileReply.GroupData.GroupID = d.GroupID;
10102 groupProfileReply.GroupData.Name = Util.StringToBytes256(d.Name);
10103 groupProfileReply.GroupData.Charter = Util.StringToBytes1024(d.Charter);
10104 groupProfileReply.GroupData.ShowInList = d.ShowInList;
10105 groupProfileReply.GroupData.MemberTitle = Util.StringToBytes256(d.MemberTitle);
10106 groupProfileReply.GroupData.PowersMask = d.PowersMask;
10107 groupProfileReply.GroupData.InsigniaID = d.InsigniaID;
10108 groupProfileReply.GroupData.FounderID = d.FounderID;
10109 groupProfileReply.GroupData.MembershipFee = d.MembershipFee;
10110 groupProfileReply.GroupData.OpenEnrollment = d.OpenEnrollment;
10111 groupProfileReply.GroupData.Money = d.Money;
10112 groupProfileReply.GroupData.GroupMembershipCount = d.GroupMembershipCount;
10113 groupProfileReply.GroupData.GroupRolesCount = d.GroupRolesCount;
10114 groupProfileReply.GroupData.AllowPublish = d.AllowPublish;
10115 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10116 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10117
10118 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10119 }
10120 return true;
10121 }
10122 private bool HandleGroupMembersRequest(IClientAPI sender, Packet Pack)
10123 {
10124 GroupMembersRequestPacket groupMembersRequestPacket =
10125 (GroupMembersRequestPacket)Pack;
10126
10127 #region Packet Session and User Check
10128 if (m_checkPackets)
10129 {
10130 if (groupMembersRequestPacket.AgentData.SessionID != SessionId ||
10131 groupMembersRequestPacket.AgentData.AgentID != AgentId)
10132 return true;
10133 }
10134 #endregion
10135
10136 if (m_GroupsModule != null)
10137 {
10138 List<GroupMembersData> members =
10139 m_GroupsModule.GroupMembersRequest(this, groupMembersRequestPacket.GroupData.GroupID);
10140
10141 int memberCount = members.Count;
10142
10143 while (true)
10144 {
10145 int blockCount = members.Count;
10146 if (blockCount > 40)
10147 blockCount = 40;
10148
10149 GroupMembersReplyPacket groupMembersReply = (GroupMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupMembersReply);
10150
10151 groupMembersReply.AgentData =
10152 new GroupMembersReplyPacket.AgentDataBlock();
10153 groupMembersReply.GroupData =
10154 new GroupMembersReplyPacket.GroupDataBlock();
10155 groupMembersReply.MemberData =
10156 new GroupMembersReplyPacket.MemberDataBlock[
10157 blockCount];
10158
10159 groupMembersReply.AgentData.AgentID = AgentId;
10160 groupMembersReply.GroupData.GroupID =
10161 groupMembersRequestPacket.GroupData.GroupID;
10162 groupMembersReply.GroupData.RequestID =
10163 groupMembersRequestPacket.GroupData.RequestID;
10164 groupMembersReply.GroupData.MemberCount = memberCount;
10165
10166 for (int i = 0; i < blockCount; i++)
10167 {
10168 GroupMembersData m = members[0];
10169 members.RemoveAt(0);
10170
10171 groupMembersReply.MemberData[i] =
10172 new GroupMembersReplyPacket.MemberDataBlock();
10173 groupMembersReply.MemberData[i].AgentID =
10174 m.AgentID;
10175 groupMembersReply.MemberData[i].Contribution =
10176 m.Contribution;
10177 groupMembersReply.MemberData[i].OnlineStatus =
10178 Util.StringToBytes256(m.OnlineStatus);
10179 groupMembersReply.MemberData[i].AgentPowers =
10180 m.AgentPowers;
10181 groupMembersReply.MemberData[i].Title =
10182 Util.StringToBytes256(m.Title);
10183 groupMembersReply.MemberData[i].IsOwner =
10184 m.IsOwner;
10185 }
10186 OutPacket(groupMembersReply, ThrottleOutPacketType.Task);
10187 if (members.Count == 0)
10188 return true;
10189 }
10190 }
10191 return true;
10192 }
10193 private bool HandleGroupRoleDataRequest(IClientAPI sender, Packet Pack)
10194 {
10195 GroupRoleDataRequestPacket groupRolesRequest =
10196 (GroupRoleDataRequestPacket)Pack;
10197
10198 #region Packet Session and User Check
10199 if (m_checkPackets)
10200 {
10201 if (groupRolesRequest.AgentData.SessionID != SessionId ||
10202 groupRolesRequest.AgentData.AgentID != AgentId)
10203 return true;
10204 }
10205 #endregion
10206
10207 if (m_GroupsModule != null)
10208 {
10209 GroupRoleDataReplyPacket groupRolesReply = (GroupRoleDataReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleDataReply);
10210
10211 groupRolesReply.AgentData =
10212 new GroupRoleDataReplyPacket.AgentDataBlock();
10213
10214 groupRolesReply.AgentData.AgentID = AgentId;
10215
10216 groupRolesReply.GroupData =
10217 new GroupRoleDataReplyPacket.GroupDataBlock();
10218
10219 groupRolesReply.GroupData.GroupID =
10220 groupRolesRequest.GroupData.GroupID;
10221
10222 groupRolesReply.GroupData.RequestID =
10223 groupRolesRequest.GroupData.RequestID;
10224
10225 List<GroupRolesData> titles =
10226 m_GroupsModule.GroupRoleDataRequest(this,
10227 groupRolesRequest.GroupData.GroupID);
10228
10229 groupRolesReply.GroupData.RoleCount =
10230 titles.Count;
10231
10232 groupRolesReply.RoleData =
10233 new GroupRoleDataReplyPacket.RoleDataBlock[titles.Count];
10234
10235 int i = 0;
10236 foreach (GroupRolesData d in titles)
10237 {
10238 groupRolesReply.RoleData[i] =
10239 new GroupRoleDataReplyPacket.RoleDataBlock();
10240
10241 groupRolesReply.RoleData[i].RoleID =
10242 d.RoleID;
10243 groupRolesReply.RoleData[i].Name =
10244 Util.StringToBytes256(d.Name);
10245 groupRolesReply.RoleData[i].Title =
10246 Util.StringToBytes256(d.Title);
10247 groupRolesReply.RoleData[i].Description =
10248 Util.StringToBytes1024(d.Description);
10249 groupRolesReply.RoleData[i].Powers =
10250 d.Powers;
10251 groupRolesReply.RoleData[i].Members =
10252 (uint)d.Members;
10253
10254 i++;
10255 }
10256
10257 OutPacket(groupRolesReply, ThrottleOutPacketType.Task);
10258 }
10259 return true;
10260 }
10261 private bool HandleGroupRoleMembersRequest(IClientAPI sender, Packet Pack)
10262 {
10263 GroupRoleMembersRequestPacket groupRoleMembersRequest =
10264 (GroupRoleMembersRequestPacket)Pack;
10265
10266 #region Packet Session and User Check
10267 if (m_checkPackets)
10268 {
10269 if (groupRoleMembersRequest.AgentData.SessionID != SessionId ||
10270 groupRoleMembersRequest.AgentData.AgentID != AgentId)
10271 return true;
10272 }
10273 #endregion
10274
10275 if (m_GroupsModule != null)
10276 {
10277 List<GroupRoleMembersData> mappings =
10278 m_GroupsModule.GroupRoleMembersRequest(this,
10279 groupRoleMembersRequest.GroupData.GroupID);
10280
10281 int mappingsCount = mappings.Count;
10282
10283 while (mappings.Count > 0)
10284 {
10285 int pairs = mappings.Count;
10286 if (pairs > 32)
10287 pairs = 32;
10288
10289 GroupRoleMembersReplyPacket groupRoleMembersReply = (GroupRoleMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleMembersReply);
10290 groupRoleMembersReply.AgentData =
10291 new GroupRoleMembersReplyPacket.AgentDataBlock();
10292 groupRoleMembersReply.AgentData.AgentID =
10293 AgentId;
10294 groupRoleMembersReply.AgentData.GroupID =
10295 groupRoleMembersRequest.GroupData.GroupID;
10296 groupRoleMembersReply.AgentData.RequestID =
10297 groupRoleMembersRequest.GroupData.RequestID;
10298
10299 groupRoleMembersReply.AgentData.TotalPairs =
10300 (uint)mappingsCount;
10301
10302 groupRoleMembersReply.MemberData =
10303 new GroupRoleMembersReplyPacket.MemberDataBlock[pairs];
10304
10305 for (int i = 0; i < pairs; i++)
10306 {
10307 GroupRoleMembersData d = mappings[0];
10308 mappings.RemoveAt(0);
10309
10310 groupRoleMembersReply.MemberData[i] =
10311 new GroupRoleMembersReplyPacket.MemberDataBlock();
10312
10313 groupRoleMembersReply.MemberData[i].RoleID =
10314 d.RoleID;
10315 groupRoleMembersReply.MemberData[i].MemberID =
10316 d.MemberID;
10317 }
10318
10319 OutPacket(groupRoleMembersReply, ThrottleOutPacketType.Task);
10320 }
10321 }
10322 return true;
10323 }
10324 private bool HandleCreateGroupRequest(IClientAPI sender, Packet Pack)
10325 {
10326 CreateGroupRequestPacket createGroupRequest =
10327 (CreateGroupRequestPacket)Pack;
10328
10329 #region Packet Session and User Check
10330 if (m_checkPackets)
10331 {
10332 if (createGroupRequest.AgentData.SessionID != SessionId ||
10333 createGroupRequest.AgentData.AgentID != AgentId)
10334 return true;
10335 }
10336 #endregion
10337
10338 if (m_GroupsModule != null)
10339 {
10340 m_GroupsModule.CreateGroup(this,
10341 Utils.BytesToString(createGroupRequest.GroupData.Name),
10342 Utils.BytesToString(createGroupRequest.GroupData.Charter),
10343 createGroupRequest.GroupData.ShowInList,
10344 createGroupRequest.GroupData.InsigniaID,
10345 createGroupRequest.GroupData.MembershipFee,
10346 createGroupRequest.GroupData.OpenEnrollment,
10347 createGroupRequest.GroupData.AllowPublish,
10348 createGroupRequest.GroupData.MaturePublish);
10349 }
10350 return true;
10351 }
10352 private bool HandleUpdateGroupInfo(IClientAPI sender, Packet Pack)
10353 {
10354 UpdateGroupInfoPacket updateGroupInfo =
10355 (UpdateGroupInfoPacket)Pack;
10356
10357 #region Packet Session and User Check
10358 if (m_checkPackets)
10359 {
10360 if (updateGroupInfo.AgentData.SessionID != SessionId ||
10361 updateGroupInfo.AgentData.AgentID != AgentId)
10362 return true;
10363 }
10364 #endregion
10365
10366 if (m_GroupsModule != null)
10367 {
10368 m_GroupsModule.UpdateGroupInfo(this,
10369 updateGroupInfo.GroupData.GroupID,
10370 Utils.BytesToString(updateGroupInfo.GroupData.Charter),
10371 updateGroupInfo.GroupData.ShowInList,
10372 updateGroupInfo.GroupData.InsigniaID,
10373 updateGroupInfo.GroupData.MembershipFee,
10374 updateGroupInfo.GroupData.OpenEnrollment,
10375 updateGroupInfo.GroupData.AllowPublish,
10376 updateGroupInfo.GroupData.MaturePublish);
10377 }
10378
10379 return true;
10380 }
10381 private bool HandleSetGroupAcceptNotices(IClientAPI sender, Packet Pack)
10382 {
10383 SetGroupAcceptNoticesPacket setGroupAcceptNotices =
10384 (SetGroupAcceptNoticesPacket)Pack;
10385
10386 #region Packet Session and User Check
10387 if (m_checkPackets)
10388 {
10389 if (setGroupAcceptNotices.AgentData.SessionID != SessionId ||
10390 setGroupAcceptNotices.AgentData.AgentID != AgentId)
10391 return true;
10392 }
10393 #endregion
10394
10395 if (m_GroupsModule != null)
10396 {
10397 m_GroupsModule.SetGroupAcceptNotices(this,
10398 setGroupAcceptNotices.Data.GroupID,
10399 setGroupAcceptNotices.Data.AcceptNotices,
10400 setGroupAcceptNotices.NewData.ListInProfile);
10401 }
10402
10403 return true;
10404 }
10405 private bool HandleGroupTitleUpdate(IClientAPI sender, Packet Pack)
10406 {
10407 GroupTitleUpdatePacket groupTitleUpdate =
10408 (GroupTitleUpdatePacket)Pack;
10409
10410 #region Packet Session and User Check
10411 if (m_checkPackets)
10412 {
10413 if (groupTitleUpdate.AgentData.SessionID != SessionId ||
10414 groupTitleUpdate.AgentData.AgentID != AgentId)
10415 return true;
10416 }
10417 #endregion
10418
10419 if (m_GroupsModule != null)
10420 {
10421 m_GroupsModule.GroupTitleUpdate(this,
10422 groupTitleUpdate.AgentData.GroupID,
10423 groupTitleUpdate.AgentData.TitleRoleID);
10424 }
10425
10426 return true;
10427 }
10428 private bool HandleParcelDeedToGroup(IClientAPI sender, Packet Pack)
10429 {
10430 ParcelDeedToGroupPacket parcelDeedToGroup = (ParcelDeedToGroupPacket)Pack;
10431 if (m_GroupsModule != null)
10432 {
10433 ParcelDeedToGroup handlerParcelDeedToGroup = OnParcelDeedToGroup;
10434 if (handlerParcelDeedToGroup != null)
10435 {
10436 handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID, this);
10437
10438 }
10439 }
10440
10441 return true;
10442 }
10443 private bool HandleGroupNoticesListRequest(IClientAPI sender, Packet Pack)
10444 {
10445 GroupNoticesListRequestPacket groupNoticesListRequest =
10446 (GroupNoticesListRequestPacket)Pack;
10447
10448 #region Packet Session and User Check
10449 if (m_checkPackets)
10450 {
10451 if (groupNoticesListRequest.AgentData.SessionID != SessionId ||
10452 groupNoticesListRequest.AgentData.AgentID != AgentId)
10453 return true;
10454 }
10455 #endregion
10456
10457 if (m_GroupsModule != null)
10458 {
10459 GroupNoticeData[] gn =
10460 m_GroupsModule.GroupNoticesListRequest(this,
10461 groupNoticesListRequest.Data.GroupID);
10462
10463 GroupNoticesListReplyPacket groupNoticesListReply = (GroupNoticesListReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupNoticesListReply);
10464 groupNoticesListReply.AgentData =
10465 new GroupNoticesListReplyPacket.AgentDataBlock();
10466 groupNoticesListReply.AgentData.AgentID = AgentId;
10467 groupNoticesListReply.AgentData.GroupID = groupNoticesListRequest.Data.GroupID;
10468
10469 groupNoticesListReply.Data = new GroupNoticesListReplyPacket.DataBlock[gn.Length];
10470
10471 int i = 0;
10472 foreach (GroupNoticeData g in gn)
10473 {
10474 groupNoticesListReply.Data[i] = new GroupNoticesListReplyPacket.DataBlock();
10475 groupNoticesListReply.Data[i].NoticeID =
10476 g.NoticeID;
10477 groupNoticesListReply.Data[i].Timestamp =
10478 g.Timestamp;
10479 groupNoticesListReply.Data[i].FromName =
10480 Util.StringToBytes256(g.FromName);
10481 groupNoticesListReply.Data[i].Subject =
10482 Util.StringToBytes256(g.Subject);
10483 groupNoticesListReply.Data[i].HasAttachment =
10484 g.HasAttachment;
10485 groupNoticesListReply.Data[i].AssetType =
10486 g.AssetType;
10487 i++;
10488 }
10489
10490 OutPacket(groupNoticesListReply, ThrottleOutPacketType.Task);
10491 }
10492
10493 return true;
10494 }
10495 private bool HandleGroupNoticeRequest(IClientAPI sender, Packet Pack)
10496 {
10497 GroupNoticeRequestPacket groupNoticeRequest =
10498 (GroupNoticeRequestPacket)Pack;
10499
10500 #region Packet Session and User Check
10501 if (m_checkPackets)
10502 {
10503 if (groupNoticeRequest.AgentData.SessionID != SessionId ||
10504 groupNoticeRequest.AgentData.AgentID != AgentId)
10505 return true;
10506 }
10507 #endregion
10508
10509 if (m_GroupsModule != null)
10510 {
10511 m_GroupsModule.GroupNoticeRequest(this,
10512 groupNoticeRequest.Data.GroupNoticeID);
10513 }
10514 return true;
10515 }
10516 private bool HandleGroupRoleUpdate(IClientAPI sender, Packet Pack)
10517 {
10518 GroupRoleUpdatePacket groupRoleUpdate =
10519 (GroupRoleUpdatePacket)Pack;
10520
10521 #region Packet Session and User Check
10522 if (m_checkPackets)
10523 {
10524 if (groupRoleUpdate.AgentData.SessionID != SessionId ||
10525 groupRoleUpdate.AgentData.AgentID != AgentId)
10526 return true;
10527 }
10528 #endregion
10529
10530 if (m_GroupsModule != null)
10531 {
10532 foreach (GroupRoleUpdatePacket.RoleDataBlock d in
10533 groupRoleUpdate.RoleData)
10534 {
10535 m_GroupsModule.GroupRoleUpdate(this,
10536 groupRoleUpdate.AgentData.GroupID,
10537 d.RoleID,
10538 Utils.BytesToString(d.Name),
10539 Utils.BytesToString(d.Description),
10540 Utils.BytesToString(d.Title),
10541 d.Powers,
10542 d.UpdateType);
10543 }
10544 m_GroupsModule.NotifyChange(groupRoleUpdate.AgentData.GroupID);
10545 }
10546 return true;
10547 }
10548 private bool HandleGroupRoleChanges(IClientAPI sender, Packet Pack)
10549 {
10550 GroupRoleChangesPacket groupRoleChanges =
10551 (GroupRoleChangesPacket)Pack;
10552
10553 #region Packet Session and User Check
10554 if (m_checkPackets)
10555 {
10556 if (groupRoleChanges.AgentData.SessionID != SessionId ||
10557 groupRoleChanges.AgentData.AgentID != AgentId)
10558 return true;
10559 }
10560 #endregion
10561
10562 if (m_GroupsModule != null)
10563 {
10564 foreach (GroupRoleChangesPacket.RoleChangeBlock d in
10565 groupRoleChanges.RoleChange)
10566 {
10567 m_GroupsModule.GroupRoleChanges(this,
10568 groupRoleChanges.AgentData.GroupID,
10569 d.RoleID,
10570 d.MemberID,
10571 d.Change);
10572 }
10573 m_GroupsModule.NotifyChange(groupRoleChanges.AgentData.GroupID);
10574 }
10575 return true;
10576 }
10577 private bool HandleJoinGroupRequest(IClientAPI sender, Packet Pack)
10578 {
10579 JoinGroupRequestPacket joinGroupRequest =
10580 (JoinGroupRequestPacket)Pack;
10581
10582 #region Packet Session and User Check
10583 if (m_checkPackets)
10584 {
10585 if (joinGroupRequest.AgentData.SessionID != SessionId ||
10586 joinGroupRequest.AgentData.AgentID != AgentId)
10587 return true;
10588 }
10589 #endregion
10590
10591 if (m_GroupsModule != null)
10592 {
10593 m_GroupsModule.JoinGroupRequest(this,
10594 joinGroupRequest.GroupData.GroupID);
10595 }
10596 return true;
10597 }
10598 private bool HandleLeaveGroupRequest(IClientAPI sender, Packet Pack)
10599 {
10600 LeaveGroupRequestPacket leaveGroupRequest =
10601 (LeaveGroupRequestPacket)Pack;
10602
10603 #region Packet Session and User Check
10604 if (m_checkPackets)
10605 {
10606 if (leaveGroupRequest.AgentData.SessionID != SessionId ||
10607 leaveGroupRequest.AgentData.AgentID != AgentId)
10608 return true;
10609 }
10610 #endregion
10611
10612 if (m_GroupsModule != null)
10613 {
10614 m_GroupsModule.LeaveGroupRequest(this,
10615 leaveGroupRequest.GroupData.GroupID);
10616 }
10617 return true;
10618 }
10619 private bool HandleEjectGroupMemberRequest(IClientAPI sender, Packet Pack)
10620 {
10621 EjectGroupMemberRequestPacket ejectGroupMemberRequest =
10622 (EjectGroupMemberRequestPacket)Pack;
10623
10624 #region Packet Session and User Check
10625 if (m_checkPackets)
10626 {
10627 if (ejectGroupMemberRequest.AgentData.SessionID != SessionId ||
10628 ejectGroupMemberRequest.AgentData.AgentID != AgentId)
10629 return true;
10630 }
10631 #endregion
10632
10633 if (m_GroupsModule != null)
10634 {
10635 foreach (EjectGroupMemberRequestPacket.EjectDataBlock e
10636 in ejectGroupMemberRequest.EjectData)
10637 {
10638 m_GroupsModule.EjectGroupMemberRequest(this,
10639 ejectGroupMemberRequest.GroupData.GroupID,
10640 e.EjecteeID);
10641 }
10642 }
10643 return true;
10644 }
10645 private bool HandleInviteGroupRequest(IClientAPI sender, Packet Pack)
10646 {
10647 InviteGroupRequestPacket inviteGroupRequest =
10648 (InviteGroupRequestPacket)Pack;
10649
10650 #region Packet Session and User Check
10651 if (m_checkPackets)
10652 {
10653 if (inviteGroupRequest.AgentData.SessionID != SessionId ||
10654 inviteGroupRequest.AgentData.AgentID != AgentId)
10655 return true;
10656 }
10657 #endregion
10658
10659 if (m_GroupsModule != null)
10660 {
10661 foreach (InviteGroupRequestPacket.InviteDataBlock b in
10662 inviteGroupRequest.InviteData)
10663 {
10664 m_GroupsModule.InviteGroupRequest(this,
10665 inviteGroupRequest.GroupData.GroupID,
10666 b.InviteeID,
10667 b.RoleID);
10668 }
10669 }
10670 return true;
10671 }
10672
10673 #endregion Groups
10674
10675 private bool HandleStartLure(IClientAPI sender, Packet Pack)
10676 {
10677 StartLurePacket startLureRequest = (StartLurePacket)Pack;
10678
10679 #region Packet Session and User Check
10680 if (m_checkPackets)
10681 {
10682 if (startLureRequest.AgentData.SessionID != SessionId ||
10683 startLureRequest.AgentData.AgentID != AgentId)
10684 return true;
10685 }
10686 #endregion
10687
10688 StartLure handlerStartLure = OnStartLure;
10689 if (handlerStartLure != null)
10690 handlerStartLure(startLureRequest.Info.LureType,
10691 Utils.BytesToString(
10692 startLureRequest.Info.Message),
10693 startLureRequest.TargetData[0].TargetID,
10694 this);
10695 return true;
10696 }
10697 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
10698 {
10699 TeleportLureRequestPacket teleportLureRequest =
10700 (TeleportLureRequestPacket)Pack;
10701
10702 #region Packet Session and User Check
10703 if (m_checkPackets)
10704 {
10705 if (teleportLureRequest.Info.SessionID != SessionId ||
10706 teleportLureRequest.Info.AgentID != AgentId)
10707 return true;
10708 }
10709 #endregion
10710
10711 TeleportLureRequest handlerTeleportLureRequest = OnTeleportLureRequest;
10712 if (handlerTeleportLureRequest != null)
10713 handlerTeleportLureRequest(
10714 teleportLureRequest.Info.LureID,
10715 teleportLureRequest.Info.TeleportFlags,
10716 this);
10717 return true;
10718 }
10719 private bool HandleClassifiedInfoRequest(IClientAPI sender, Packet Pack)
10720 {
10721 ClassifiedInfoRequestPacket classifiedInfoRequest =
10722 (ClassifiedInfoRequestPacket)Pack;
10723
10724 #region Packet Session and User Check
10725 if (m_checkPackets)
10726 {
10727 if (classifiedInfoRequest.AgentData.SessionID != SessionId ||
10728 classifiedInfoRequest.AgentData.AgentID != AgentId)
10729 return true;
10730 }
10731 #endregion
10732
10733 ClassifiedInfoRequest handlerClassifiedInfoRequest = OnClassifiedInfoRequest;
10734 if (handlerClassifiedInfoRequest != null)
10735 handlerClassifiedInfoRequest(
10736 classifiedInfoRequest.Data.ClassifiedID,
10737 this);
10738 return true;
10739 }
10740 private bool HandleClassifiedInfoUpdate(IClientAPI sender, Packet Pack)
10741 {
10742 ClassifiedInfoUpdatePacket classifiedInfoUpdate =
10743 (ClassifiedInfoUpdatePacket)Pack;
10744
10745 #region Packet Session and User Check
10746 if (m_checkPackets)
10747 {
10748 if (classifiedInfoUpdate.AgentData.SessionID != SessionId ||
10749 classifiedInfoUpdate.AgentData.AgentID != AgentId)
10750 return true;
10751 }
10752 #endregion
10753
10754 ClassifiedInfoUpdate handlerClassifiedInfoUpdate = OnClassifiedInfoUpdate;
10755 if (handlerClassifiedInfoUpdate != null)
10756 handlerClassifiedInfoUpdate(
10757 classifiedInfoUpdate.Data.ClassifiedID,
10758 classifiedInfoUpdate.Data.Category,
10759 Utils.BytesToString(
10760 classifiedInfoUpdate.Data.Name),
10761 Utils.BytesToString(
10762 classifiedInfoUpdate.Data.Desc),
10763 classifiedInfoUpdate.Data.ParcelID,
10764 classifiedInfoUpdate.Data.ParentEstate,
10765 classifiedInfoUpdate.Data.SnapshotID,
10766 new Vector3(
10767 classifiedInfoUpdate.Data.PosGlobal),
10768 classifiedInfoUpdate.Data.ClassifiedFlags,
10769 classifiedInfoUpdate.Data.PriceForListing,
10770 this);
10771 return true;
10772 }
10773 private bool HandleClassifiedDelete(IClientAPI sender, Packet Pack)
10774 {
10775 ClassifiedDeletePacket classifiedDelete =
10776 (ClassifiedDeletePacket)Pack;
10777
10778 #region Packet Session and User Check
10779 if (m_checkPackets)
10780 {
10781 if (classifiedDelete.AgentData.SessionID != SessionId ||
10782 classifiedDelete.AgentData.AgentID != AgentId)
10783 return true;
10784 }
10785 #endregion
10786
10787 ClassifiedDelete handlerClassifiedDelete = OnClassifiedDelete;
10788 if (handlerClassifiedDelete != null)
10789 handlerClassifiedDelete(
10790 classifiedDelete.Data.ClassifiedID,
10791 this);
10792 return true;
10793 }
10794 private bool HandleClassifiedGodDelete(IClientAPI sender, Packet Pack)
10795 {
10796 ClassifiedGodDeletePacket classifiedGodDelete =
10797 (ClassifiedGodDeletePacket)Pack;
10798
10799 #region Packet Session and User Check
10800 if (m_checkPackets)
10801 {
10802 if (classifiedGodDelete.AgentData.SessionID != SessionId ||
10803 classifiedGodDelete.AgentData.AgentID != AgentId)
10804 return true;
10805 }
10806 #endregion
10807
10808 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
10809 if (handlerClassifiedGodDelete != null)
10810 handlerClassifiedGodDelete(
10811 classifiedGodDelete.Data.ClassifiedID,
10812 this);
10813 return true;
10814 }
10815 private bool HandleEventGodDelete(IClientAPI sender, Packet Pack)
10816 {
10817 EventGodDeletePacket eventGodDelete =
10818 (EventGodDeletePacket)Pack;
10819
10820 #region Packet Session and User Check
10821 if (m_checkPackets)
10822 {
10823 if (eventGodDelete.AgentData.SessionID != SessionId ||
10824 eventGodDelete.AgentData.AgentID != AgentId)
10825 return true;
10826 }
10827 #endregion
10828
10829 EventGodDelete handlerEventGodDelete = OnEventGodDelete;
10830 if (handlerEventGodDelete != null)
10831 handlerEventGodDelete(
10832 eventGodDelete.EventData.EventID,
10833 eventGodDelete.QueryData.QueryID,
10834 Utils.BytesToString(
10835 eventGodDelete.QueryData.QueryText),
10836 eventGodDelete.QueryData.QueryFlags,
10837 eventGodDelete.QueryData.QueryStart,
10838 this);
10839 return true;
10840 }
10841 private bool HandleEventNotificationAddRequest(IClientAPI sender, Packet Pack)
10842 {
10843 EventNotificationAddRequestPacket eventNotificationAdd =
10844 (EventNotificationAddRequestPacket)Pack;
10845
10846 #region Packet Session and User Check
10847 if (m_checkPackets)
10848 {
10849 if (eventNotificationAdd.AgentData.SessionID != SessionId ||
10850 eventNotificationAdd.AgentData.AgentID != AgentId)
10851 return true;
10852 }
10853 #endregion
10854
10855 EventNotificationAddRequest handlerEventNotificationAddRequest = OnEventNotificationAddRequest;
10856 if (handlerEventNotificationAddRequest != null)
10857 handlerEventNotificationAddRequest(
10858 eventNotificationAdd.EventData.EventID, this);
10859 return true;
10860 }
10861 private bool HandleEventNotificationRemoveRequest(IClientAPI sender, Packet Pack)
10862 {
10863 EventNotificationRemoveRequestPacket eventNotificationRemove =
10864 (EventNotificationRemoveRequestPacket)Pack;
10865
10866 #region Packet Session and User Check
10867 if (m_checkPackets)
10868 {
10869 if (eventNotificationRemove.AgentData.SessionID != SessionId ||
10870 eventNotificationRemove.AgentData.AgentID != AgentId)
10871 return true;
10872 }
10873 #endregion
10874
10875 EventNotificationRemoveRequest handlerEventNotificationRemoveRequest = OnEventNotificationRemoveRequest;
10876 if (handlerEventNotificationRemoveRequest != null)
10877 handlerEventNotificationRemoveRequest(
10878 eventNotificationRemove.EventData.EventID, this);
10879 return true;
10880 }
10881 private bool HandleRetrieveInstantMessages(IClientAPI sender, Packet Pack)
10882 {
10883 RetrieveInstantMessagesPacket rimpInstantMessagePack = (RetrieveInstantMessagesPacket)Pack;
10884
10885 #region Packet Session and User Check
10886 if (m_checkPackets)
10887 {
10888 if (rimpInstantMessagePack.AgentData.SessionID != SessionId ||
10889 rimpInstantMessagePack.AgentData.AgentID != AgentId)
10890 return true;
10891 }
10892 #endregion
10893
10894 RetrieveInstantMessages handlerRetrieveInstantMessages = OnRetrieveInstantMessages;
10895 if (handlerRetrieveInstantMessages != null)
10896 handlerRetrieveInstantMessages(this);
10897 return true;
10898 }
10899 private bool HandlePickDelete(IClientAPI sender, Packet Pack)
10900 {
10901 PickDeletePacket pickDelete =
10902 (PickDeletePacket)Pack;
10903
10904 #region Packet Session and User Check
10905 if (m_checkPackets)
10906 {
10907 if (pickDelete.AgentData.SessionID != SessionId ||
10908 pickDelete.AgentData.AgentID != AgentId)
10909 return true;
10910 }
10911 #endregion
10912
10913 PickDelete handlerPickDelete = OnPickDelete;
10914 if (handlerPickDelete != null)
10915 handlerPickDelete(this, pickDelete.Data.PickID);
10916 return true;
10917 }
10918 private bool HandlePickGodDelete(IClientAPI sender, Packet Pack)
10919 {
10920 PickGodDeletePacket pickGodDelete =
10921 (PickGodDeletePacket)Pack;
10922
10923 #region Packet Session and User Check
10924 if (m_checkPackets)
10925 {
10926 if (pickGodDelete.AgentData.SessionID != SessionId ||
10927 pickGodDelete.AgentData.AgentID != AgentId)
10928 return true;
10929 }
10930 #endregion
10931
10932 PickGodDelete handlerPickGodDelete = OnPickGodDelete;
10933 if (handlerPickGodDelete != null)
10934 handlerPickGodDelete(this,
10935 pickGodDelete.AgentData.AgentID,
10936 pickGodDelete.Data.PickID,
10937 pickGodDelete.Data.QueryID);
10938 return true;
10939 }
10940 private bool HandlePickInfoUpdate(IClientAPI sender, Packet Pack)
10941 {
10942 PickInfoUpdatePacket pickInfoUpdate =
10943 (PickInfoUpdatePacket)Pack;
10944
10945 #region Packet Session and User Check
10946 if (m_checkPackets)
10947 {
10948 if (pickInfoUpdate.AgentData.SessionID != SessionId ||
10949 pickInfoUpdate.AgentData.AgentID != AgentId)
10950 return true;
10951 }
10952 #endregion
10953
10954 PickInfoUpdate handlerPickInfoUpdate = OnPickInfoUpdate;
10955 if (handlerPickInfoUpdate != null)
10956 handlerPickInfoUpdate(this,
10957 pickInfoUpdate.Data.PickID,
10958 pickInfoUpdate.Data.CreatorID,
10959 pickInfoUpdate.Data.TopPick,
10960 Utils.BytesToString(pickInfoUpdate.Data.Name),
10961 Utils.BytesToString(pickInfoUpdate.Data.Desc),
10962 pickInfoUpdate.Data.SnapshotID,
10963 pickInfoUpdate.Data.SortOrder,
10964 pickInfoUpdate.Data.Enabled);
10965 return true;
10966 }
10967 private bool HandleAvatarNotesUpdate(IClientAPI sender, Packet Pack)
10968 {
10969 AvatarNotesUpdatePacket avatarNotesUpdate =
10970 (AvatarNotesUpdatePacket)Pack;
10971
10972 #region Packet Session and User Check
10973 if (m_checkPackets)
10974 {
10975 if (avatarNotesUpdate.AgentData.SessionID != SessionId ||
10976 avatarNotesUpdate.AgentData.AgentID != AgentId)
10977 return true;
10978 }
10979 #endregion
10980
10981 AvatarNotesUpdate handlerAvatarNotesUpdate = OnAvatarNotesUpdate;
10982 if (handlerAvatarNotesUpdate != null)
10983 handlerAvatarNotesUpdate(this,
10984 avatarNotesUpdate.Data.TargetID,
10985 Utils.BytesToString(avatarNotesUpdate.Data.Notes));
10986 return true;
10987 }
10988 private bool HandleAvatarInterestsUpdate(IClientAPI sender, Packet Pack)
10989 {
10990 AvatarInterestsUpdatePacket avatarInterestUpdate =
10991 (AvatarInterestsUpdatePacket)Pack;
10992
10993 #region Packet Session and User Check
10994 if (m_checkPackets)
10995 {
10996 if (avatarInterestUpdate.AgentData.SessionID != SessionId ||
10997 avatarInterestUpdate.AgentData.AgentID != AgentId)
10998 return true;
10999 }
11000 #endregion
11001
11002 AvatarInterestUpdate handlerAvatarInterestUpdate = OnAvatarInterestUpdate;
11003 if (handlerAvatarInterestUpdate != null)
11004 handlerAvatarInterestUpdate(this,
11005 avatarInterestUpdate.PropertiesData.WantToMask,
11006 Utils.BytesToString(avatarInterestUpdate.PropertiesData.WantToText),
11007 avatarInterestUpdate.PropertiesData.SkillsMask,
11008 Utils.BytesToString(avatarInterestUpdate.PropertiesData.SkillsText),
11009 Utils.BytesToString(avatarInterestUpdate.PropertiesData.LanguagesText));
11010 return true;
11011 }
11012 private bool HandleGrantUserRights(IClientAPI sender, Packet Pack)
11013 {
11014 GrantUserRightsPacket GrantUserRights =
11015 (GrantUserRightsPacket)Pack;
11016 #region Packet Session and User Check
11017 if (m_checkPackets)
11018 {
11019 if (GrantUserRights.AgentData.SessionID != SessionId ||
11020 GrantUserRights.AgentData.AgentID != AgentId)
11021 return true;
11022 }
11023 #endregion
11024 GrantUserFriendRights GrantUserRightsHandler = OnGrantUserRights;
11025 if (GrantUserRightsHandler != null)
11026 GrantUserRightsHandler(this,
11027 GrantUserRights.AgentData.AgentID,
11028 GrantUserRights.Rights[0].AgentRelated,
11029 GrantUserRights.Rights[0].RelatedRights);
11030 return true;
11031 }
11032 private bool HandlePlacesQuery(IClientAPI sender, Packet Pack)
11033 {
11034 PlacesQueryPacket placesQueryPacket =
11035 (PlacesQueryPacket)Pack;
11036
11037 PlacesQuery handlerPlacesQuery = OnPlacesQuery;
11038
11039 if (handlerPlacesQuery != null)
11040 handlerPlacesQuery(placesQueryPacket.AgentData.QueryID,
11041 placesQueryPacket.TransactionData.TransactionID,
11042 Utils.BytesToString(
11043 placesQueryPacket.QueryData.QueryText),
11044 placesQueryPacket.QueryData.QueryFlags,
11045 (byte)placesQueryPacket.QueryData.Category,
11046 Utils.BytesToString(
11047 placesQueryPacket.QueryData.SimName),
11048 this);
11049 return true;
11050 }
11051
11052 #endregion Packet Handlers
11053
11054 public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question)
11055 {
11056 ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion);
11057 scriptQuestion.Data = new ScriptQuestionPacket.DataBlock();
11058 // TODO: don't create new blocks if recycling an old packet
11059 scriptQuestion.Data.TaskID = taskID;
11060 scriptQuestion.Data.ItemID = itemID;
11061 scriptQuestion.Data.Questions = question;
11062 scriptQuestion.Data.ObjectName = Util.StringToBytes256(taskName);
11063 scriptQuestion.Data.ObjectOwner = Util.StringToBytes256(ownerName);
11064
11065 OutPacket(scriptQuestion, ThrottleOutPacketType.Task);
11066 }
11067
11068 private void InitDefaultAnimations()
11069 {
11070 using (XmlTextReader reader = new XmlTextReader("data/avataranimations.xml"))
11071 {
11072 XmlDocument doc = new XmlDocument();
11073 doc.Load(reader);
11074 if (doc.DocumentElement != null)
11075 foreach (XmlNode nod in doc.DocumentElement.ChildNodes)
11076 {
11077 if (nod.Attributes["name"] != null)
11078 {
11079 string name = nod.Attributes["name"].Value.ToLower();
11080 string id = nod.InnerText;
11081 m_defaultAnimations.Add(name, (UUID)id);
11082 }
11083 }
11084 }
11085 }
11086
11087 public UUID GetDefaultAnimation(string name)
11088 {
11089 if (m_defaultAnimations.ContainsKey(name))
11090 return m_defaultAnimations[name];
11091 return UUID.Zero;
11092 }
11093
11094 /// <summary>
11095 /// Handler called when we receive a logout packet.
11096 /// </summary>
11097 /// <param name="client"></param>
11098 /// <param name="packet"></param>
11099 /// <returns></returns>
11100 protected virtual bool HandleLogout(IClientAPI client, Packet packet)
11101 {
11102 if (packet.Type == PacketType.LogoutRequest)
11103 {
11104 if (((LogoutRequestPacket)packet).AgentData.SessionID != SessionId) return false;
11105 }
11106
11107 return Logout(client);
11108 }
11109
11110 /// <summary>
11111 ///
11112 /// </summary>
11113 /// <param name="client"></param>
11114 /// <returns></returns>
11115 protected virtual bool Logout(IClientAPI client)
11116 {
11117 m_log.InfoFormat("[CLIENT]: Got a logout request for {0} in {1}", Name, Scene.RegionInfo.RegionName);
11118
11119 Action<IClientAPI> handlerLogout = OnLogout;
11120
11121 if (handlerLogout != null)
11122 {
11123 handlerLogout(client);
11124 }
11125
11126 return true;
11127 }
11128
11129 /// <summary>
11130 /// Send a response back to a client when it asks the asset server (via the region server) if it has
11131 /// its appearance texture cached.
11132 ///
11133 /// At the moment, we always reply that there is no cached texture.
11134 /// </summary>
11135 /// <param name="simclient"></param>
11136 /// <param name="packet"></param>
11137 /// <returns></returns>
11138 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11139 {
11140 //m_log.Debug("texture cached: " + packet.ToString());
11141 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
11142 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
11143
11144 if (cachedtex.AgentData.SessionID != SessionId) return false;
11145
11146 // TODO: don't create new blocks if recycling an old packet
11147 cachedresp.AgentData.AgentID = AgentId;
11148 cachedresp.AgentData.SessionID = m_sessionId;
11149 cachedresp.AgentData.SerialNum = m_cachedTextureSerial;
11150 m_cachedTextureSerial++;
11151 cachedresp.WearableData =
11152 new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length];
11153
11154 for (int i = 0; i < cachedtex.WearableData.Length; i++)
11155 {
11156 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11157 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11158 cachedresp.WearableData[i].TextureID = UUID.Zero;
11159 cachedresp.WearableData[i].HostName = new byte[0];
11160 }
11161
11162 cachedresp.Header.Zerocoded = true;
11163 OutPacket(cachedresp, ThrottleOutPacketType.Task);
11164
11165 return true;
11166 }
11167
11168 protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet)
11169 {
11170 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet;
11171 if (multipleupdate.AgentData.SessionID != SessionId) return false;
11172 // m_log.Debug("new multi update packet " + multipleupdate.ToString());
11173 Scene tScene = (Scene)m_scene;
11174
11175 for (int i = 0; i < multipleupdate.ObjectData.Length; i++)
11176 {
11177 MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i];
11178
11179 // Can't act on Null Data
11180 if (block.Data != null)
11181 {
11182 uint localId = block.ObjectLocalID;
11183 SceneObjectPart part = tScene.GetSceneObjectPart(localId);
11184
11185 if (part == null)
11186 {
11187 // It's a ghost! tell the client to delete it from view.
11188 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
11189 localId);
11190 }
11191 else
11192 {
11193 // UUID partId = part.UUID;
11194 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation;
11195
11196 switch (block.Type)
11197 {
11198 case 1:
11199 Vector3 pos1 = new Vector3(block.Data, 0);
11200
11201 UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
11202 if (handlerUpdatePrimSinglePosition != null)
11203 {
11204 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11205 handlerUpdatePrimSinglePosition(localId, pos1, this);
11206 }
11207 break;
11208 case 2:
11209 Quaternion rot1 = new Quaternion(block.Data, 0, true);
11210
11211 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation;
11212 if (handlerUpdatePrimSingleRotation != null)
11213 {
11214 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W);
11215 handlerUpdatePrimSingleRotation(localId, rot1, this);
11216 }
11217 break;
11218 case 3:
11219 Vector3 rotPos = new Vector3(block.Data, 0);
11220 Quaternion rot2 = new Quaternion(block.Data, 12, true);
11221
11222 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition;
11223 if (handlerUpdatePrimSingleRotationPosition != null)
11224 {
11225 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z);
11226 // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W);
11227 handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this);
11228 }
11229 break;
11230 case 4:
11231 case 20:
11232 Vector3 scale4 = new Vector3(block.Data, 0);
11233
11234 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale;
11235 if (handlerUpdatePrimScale != null)
11236 {
11237 // m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z);
11238 handlerUpdatePrimScale(localId, scale4, this);
11239 }
11240 break;
11241 case 5:
11242
11243 Vector3 scale1 = new Vector3(block.Data, 12);
11244 Vector3 pos11 = new Vector3(block.Data, 0);
11245
11246 handlerUpdatePrimScale = OnUpdatePrimScale;
11247 if (handlerUpdatePrimScale != null)
11248 {
11249 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11250 handlerUpdatePrimScale(localId, scale1, this);
11251
11252 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
11253 if (handlerUpdatePrimSinglePosition != null)
11254 {
11255 handlerUpdatePrimSinglePosition(localId, pos11, this);
11256 }
11257 }
11258 break;
11259 case 9:
11260 Vector3 pos2 = new Vector3(block.Data, 0);
11261
11262 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition;
11263
11264 if (handlerUpdateVector != null)
11265 {
11266
11267 handlerUpdateVector(localId, pos2, this);
11268 }
11269 break;
11270 case 10:
11271 Quaternion rot3 = new Quaternion(block.Data, 0, true);
11272
11273 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation;
11274 if (handlerUpdatePrimRotation != null)
11275 {
11276 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W);
11277 handlerUpdatePrimRotation(localId, rot3, this);
11278 }
11279 break;
11280 case 11:
11281 Vector3 pos3 = new Vector3(block.Data, 0);
11282 Quaternion rot4 = new Quaternion(block.Data, 12, true);
11283
11284 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation;
11285 if (handlerUpdatePrimGroupRotation != null)
11286 {
11287 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11288 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W);
11289 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this);
11290 }
11291 break;
11292 case 12:
11293 case 28:
11294 Vector3 scale7 = new Vector3(block.Data, 0);
11295
11296 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
11297 if (handlerUpdatePrimGroupScale != null)
11298 {
11299 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
11300 handlerUpdatePrimGroupScale(localId, scale7, this);
11301 }
11302 break;
11303 case 13:
11304 Vector3 scale2 = new Vector3(block.Data, 12);
11305 Vector3 pos4 = new Vector3(block.Data, 0);
11306
11307 handlerUpdatePrimScale = OnUpdatePrimScale;
11308 if (handlerUpdatePrimScale != null)
11309 {
11310 //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11311 handlerUpdatePrimScale(localId, scale2, this);
11312
11313 // Change the position based on scale (for bug number 246)
11314 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
11315 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11316 if (handlerUpdatePrimSinglePosition != null)
11317 {
11318 handlerUpdatePrimSinglePosition(localId, pos4, this);
11319 }
11320 }
11321 break;
11322 case 29:
11323 Vector3 scale5 = new Vector3(block.Data, 12);
11324 Vector3 pos5 = new Vector3(block.Data, 0);
11325
11326 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
11327 if (handlerUpdatePrimGroupScale != null)
11328 {
11329 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11330 handlerUpdatePrimGroupScale(localId, scale5, this);
11331 handlerUpdateVector = OnUpdatePrimGroupPosition;
11332
11333 if (handlerUpdateVector != null)
11334 {
11335 handlerUpdateVector(localId, pos5, this);
11336 }
11337 }
11338 break;
11339 case 21:
11340 Vector3 scale6 = new Vector3(block.Data, 12);
11341 Vector3 pos6 = new Vector3(block.Data, 0);
11342
11343 handlerUpdatePrimScale = OnUpdatePrimScale;
11344 if (handlerUpdatePrimScale != null)
11345 {
11346 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11347 handlerUpdatePrimScale(localId, scale6, this);
11348 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
11349 if (handlerUpdatePrimSinglePosition != null)
11350 {
11351 handlerUpdatePrimSinglePosition(localId, pos6, this);
11352 }
11353 }
11354 break;
11355 default:
11356 m_log.Debug("[CLIENT] MultipleObjUpdate recieved an unknown packet type: " + (block.Type));
11357 break;
11358 }
11359 }
11360 }
11361 }
11362 return true;
11363 }
11364
11365 public void RequestMapLayer()
11366 {
11367 //should be getting the map layer from the grid server
11368 //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area)
11369 MapLayerReplyPacket mapReply = (MapLayerReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapLayerReply);
11370 // TODO: don't create new blocks if recycling an old packet
11371 mapReply.AgentData.AgentID = AgentId;
11372 mapReply.AgentData.Flags = 0;
11373 mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1];
11374 mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock();
11375 mapReply.LayerData[0].Bottom = 0;
11376 mapReply.LayerData[0].Left = 0;
11377 mapReply.LayerData[0].Top = 30000;
11378 mapReply.LayerData[0].Right = 30000;
11379 mapReply.LayerData[0].ImageID = new UUID("00000000-0000-1111-9999-000000000006");
11380 mapReply.Header.Zerocoded = true;
11381 OutPacket(mapReply, ThrottleOutPacketType.Land);
11382 }
11383
11384 public void RequestMapBlocksX(int minX, int minY, int maxX, int maxY)
11385 {
11386 /*
11387 IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY);
11388 MapBlockReplyPacket mbReply = new MapBlockReplyPacket();
11389 mbReply.AgentData.AgentId = AgentId;
11390 int len;
11391 if (simMapProfiles == null)
11392 len = 0;
11393 else
11394 len = simMapProfiles.Count;
11395
11396 mbReply.Data = new MapBlockReplyPacket.DataBlock[len];
11397 int iii;
11398 for (iii = 0; iii < len; iii++)
11399 {
11400 Hashtable mp = (Hashtable)simMapProfiles[iii];
11401 mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock();
11402 mbReply.Data[iii].Name = Util.UTF8.GetBytes((string)mp["name"]);
11403 mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]);
11404 mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]);
11405 mbReply.Data[iii].MapImageID = new UUID((string)mp["map-image-id"]);
11406 mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]);
11407 mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]);
11408 mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]);
11409 mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]);
11410 }
11411 this.OutPacket(mbReply, ThrottleOutPacketType.Land);
11412 */
11413 }
11414
11415 /// <summary>
11416 /// Sets the throttles from values supplied by the client
11417 /// </summary>
11418 /// <param name="throttles"></param>
11419 public void SetChildAgentThrottle(byte[] throttles)
11420 {
11421 m_udpClient.SetThrottles(throttles);
11422 }
11423
11424 /// <summary>
11425 /// Get the current throttles for this client as a packed byte array
11426 /// </summary>
11427 /// <param name="multiplier">Unused</param>
11428 /// <returns></returns>
11429 public byte[] GetThrottlesPacked(float multiplier)
11430 {
11431 return m_udpClient.GetThrottlesPacked(multiplier);
11432 }
11433
11434 /// <summary>
11435 /// Cruft?
11436 /// </summary>
11437 public virtual void InPacket(object NewPack)
11438 {
11439 throw new NotImplementedException();
11440 }
11441
11442 /// <summary>
11443 /// This is the starting point for sending a simulator packet out to the client
11444 /// </summary>
11445 /// <param name="packet">Packet to send</param>
11446 /// <param name="throttlePacketType">Throttling category for the packet</param>
11447 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType)
11448 {
11449 #region BinaryStats
11450 LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length);
11451 #endregion BinaryStats
11452
11453 OutPacket(packet, throttlePacketType, true);
11454 }
11455
11456 /// <summary>
11457 /// This is the starting point for sending a simulator packet out to the client
11458 /// </summary>
11459 /// <param name="packet">Packet to send</param>
11460 /// <param name="throttlePacketType">Throttling category for the packet</param>
11461 /// <param name="doAutomaticSplitting">True to automatically split oversized
11462 /// packets (the default), or false to disable splitting if the calling code
11463 /// handles splitting manually</param>
11464 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting)
11465 {
11466 OutPacket(packet, throttlePacketType, doAutomaticSplitting, null);
11467 }
11468
11469 /// <summary>
11470 /// This is the starting point for sending a simulator packet out to the client
11471 /// </summary>
11472 /// <param name="packet">Packet to send</param>
11473 /// <param name="throttlePacketType">Throttling category for the packet</param>
11474 /// <param name="doAutomaticSplitting">True to automatically split oversized
11475 /// packets (the default), or false to disable splitting if the calling code
11476 /// handles splitting manually</param>
11477 /// <param name="method">The method to be called in the event this packet is reliable
11478 /// and unacknowledged. The server will provide normal resend capability if you do not
11479 /// provide your own method.</param>
11480 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
11481 {
11482 if (m_debugPacketLevel > 0)
11483 {
11484 bool logPacket = true;
11485
11486 if (m_debugPacketLevel <= 255
11487 && (packet.Type == PacketType.SimStats || packet.Type == PacketType.SimulatorViewerTimeMessage))
11488 logPacket = false;
11489
11490 if (m_debugPacketLevel <= 200
11491 && (packet.Type == PacketType.ImagePacket
11492 || packet.Type == PacketType.ImageData
11493 || packet.Type == PacketType.LayerData
11494 || packet.Type == PacketType.CoarseLocationUpdate))
11495 logPacket = false;
11496
11497 if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect))
11498 logPacket = false;
11499
11500 if (m_debugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate)
11501 logPacket = false;
11502
11503 if (logPacket)
11504 m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type);
11505 }
11506
11507 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method);
11508 }
11509
11510 public bool AddMoney(int debit)
11511 {
11512 if (m_moneyBalance + debit >= 0)
11513 {
11514 m_moneyBalance += debit;
11515 SendMoneyBalance(UUID.Zero, true, Util.StringToBytes256("Poof Poof!"), m_moneyBalance);
11516 return true;
11517 }
11518 return false;
11519 }
11520
11521 /// <summary>
11522 /// Breaks down the genericMessagePacket into specific events
11523 /// </summary>
11524 /// <param name="gmMethod"></param>
11525 /// <param name="gmInvoice"></param>
11526 /// <param name="gmParams"></param>
11527 public void DecipherGenericMessage(string gmMethod, UUID gmInvoice, GenericMessagePacket.ParamListBlock[] gmParams)
11528 {
11529 switch (gmMethod)
11530 {
11531 case "autopilot":
11532 float locx;
11533 float locy;
11534 float locz;
11535
11536 try
11537 {
11538 uint regionX;
11539 uint regionY;
11540 Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY);
11541 locx = Convert.ToSingle(Utils.BytesToString(gmParams[0].Parameter)) - regionX;
11542 locy = Convert.ToSingle(Utils.BytesToString(gmParams[1].Parameter)) - regionY;
11543 locz = Convert.ToSingle(Utils.BytesToString(gmParams[2].Parameter));
11544 }
11545 catch (InvalidCastException)
11546 {
11547 m_log.Error("[CLIENT]: Invalid autopilot request");
11548 return;
11549 }
11550
11551 UpdateVector handlerAutoPilotGo = OnAutoPilotGo;
11552 if (handlerAutoPilotGo != null)
11553 {
11554 handlerAutoPilotGo(0, new Vector3(locx, locy, locz), this);
11555 }
11556 m_log.InfoFormat("[CLIENT]: Client Requests autopilot to position <{0},{1},{2}>", locx, locy, locz);
11557
11558
11559 break;
11560 default:
11561 m_log.Debug("[CLIENT]: Unknown Generic Message, Method: " + gmMethod + ". Invoice: " + gmInvoice + ". Dumping Params:");
11562 for (int hi = 0; hi < gmParams.Length; hi++)
11563 {
11564 Console.WriteLine(gmParams[hi].ToString());
11565 }
11566 //gmpack.MethodData.
11567 break;
11568
11569 }
11570 }
11571
11572 /// <summary>
11573 /// Entryway from the client to the simulator. All UDP packets from the client will end up here
11574 /// </summary>
11575 /// <param name="Pack">OpenMetaverse.packet</param>
11576 public void ProcessInPacket(Packet packet)
11577 {
11578 if (m_debugPacketLevel > 0)
11579 {
11580 bool outputPacket = true;
11581
11582 if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
11583 outputPacket = false;
11584
11585 if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
11586 outputPacket = false;
11587
11588 if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
11589 outputPacket = false;
11590
11591 if (outputPacket)
11592 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11593 }
11594
11595 if (!ProcessPacketMethod(packet))
11596 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
11597
11598 PacketPool.Instance.ReturnPacket(packet);
11599 }
11600
11601 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
11602 {
11603 PrimitiveBaseShape shape = new PrimitiveBaseShape();
11604
11605 shape.PCode = addPacket.ObjectData.PCode;
11606 shape.State = addPacket.ObjectData.State;
11607 shape.PathBegin = addPacket.ObjectData.PathBegin;
11608 shape.PathEnd = addPacket.ObjectData.PathEnd;
11609 shape.PathScaleX = addPacket.ObjectData.PathScaleX;
11610 shape.PathScaleY = addPacket.ObjectData.PathScaleY;
11611 shape.PathShearX = addPacket.ObjectData.PathShearX;
11612 shape.PathShearY = addPacket.ObjectData.PathShearY;
11613 shape.PathSkew = addPacket.ObjectData.PathSkew;
11614 shape.ProfileBegin = addPacket.ObjectData.ProfileBegin;
11615 shape.ProfileEnd = addPacket.ObjectData.ProfileEnd;
11616 shape.Scale = addPacket.ObjectData.Scale;
11617 shape.PathCurve = addPacket.ObjectData.PathCurve;
11618 shape.ProfileCurve = addPacket.ObjectData.ProfileCurve;
11619 shape.ProfileHollow = addPacket.ObjectData.ProfileHollow;
11620 shape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset;
11621 shape.PathRevolutions = addPacket.ObjectData.PathRevolutions;
11622 shape.PathTaperX = addPacket.ObjectData.PathTaperX;
11623 shape.PathTaperY = addPacket.ObjectData.PathTaperY;
11624 shape.PathTwist = addPacket.ObjectData.PathTwist;
11625 shape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin;
11626 Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("89556747-24cb-43ed-920b-47caed15465f"));
11627 shape.TextureEntry = ntex.GetBytes();
11628 //shape.Textures = ntex;
11629 return shape;
11630 }
11631
11632 public ClientInfo GetClientInfo()
11633 {
11634 ClientInfo info = m_udpClient.GetClientInfo();
11635
11636 info.userEP = m_userEndPoint;
11637 info.proxyEP = null;
11638 info.agentcircuit = RequestClientInfo();
11639
11640 return info;
11641 }
11642
11643 public void SetClientInfo(ClientInfo info)
11644 {
11645 m_udpClient.SetClientInfo(info);
11646 }
11647
11648 public EndPoint GetClientEP()
11649 {
11650 return m_userEndPoint;
11651 }
11652
11653 #region Media Parcel Members
11654
11655 public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time)
11656 {
11657 ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket();
11658 commandMessagePacket.CommandBlock.Flags = flags;
11659 commandMessagePacket.CommandBlock.Command = (uint)command;
11660 commandMessagePacket.CommandBlock.Time = time;
11661
11662 OutPacket(commandMessagePacket, ThrottleOutPacketType.Task);
11663 }
11664
11665 public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID,
11666 byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight,
11667 byte mediaLoop)
11668 {
11669 ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket();
11670 updatePacket.DataBlock.MediaURL = Util.StringToBytes256(mediaUrl);
11671 updatePacket.DataBlock.MediaID = mediaTextureID;
11672 updatePacket.DataBlock.MediaAutoScale = autoScale;
11673
11674 updatePacket.DataBlockExtended.MediaType = Util.StringToBytes256(mediaType);
11675 updatePacket.DataBlockExtended.MediaDesc = Util.StringToBytes256(mediaDesc);
11676 updatePacket.DataBlockExtended.MediaWidth = mediaWidth;
11677 updatePacket.DataBlockExtended.MediaHeight = mediaHeight;
11678 updatePacket.DataBlockExtended.MediaLoop = mediaLoop;
11679
11680 OutPacket(updatePacket, ThrottleOutPacketType.Task);
11681 }
11682
11683 #endregion
11684
11685 #region Camera
11686
11687 public void SendSetFollowCamProperties(UUID objectID, SortedDictionary<int, float> parameters)
11688 {
11689 SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties);
11690 packet.ObjectData.ObjectID = objectID;
11691 SetFollowCamPropertiesPacket.CameraPropertyBlock[] camPropBlock = new SetFollowCamPropertiesPacket.CameraPropertyBlock[parameters.Count];
11692 uint idx = 0;
11693 foreach (KeyValuePair<int, float> pair in parameters)
11694 {
11695 SetFollowCamPropertiesPacket.CameraPropertyBlock block = new SetFollowCamPropertiesPacket.CameraPropertyBlock();
11696 block.Type = pair.Key;
11697 block.Value = pair.Value;
11698
11699 camPropBlock[idx++] = block;
11700 }
11701 packet.CameraProperty = camPropBlock;
11702 OutPacket(packet, ThrottleOutPacketType.Task);
11703 }
11704
11705 public void SendClearFollowCamProperties(UUID objectID)
11706 {
11707 ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties);
11708 packet.ObjectData.ObjectID = objectID;
11709 OutPacket(packet, ThrottleOutPacketType.Task);
11710 }
11711
11712 #endregion
11713
11714 public void SetClientOption(string option, string value)
11715 {
11716 switch (option)
11717 {
11718 default:
11719 break;
11720 }
11721 }
11722
11723 public string GetClientOption(string option)
11724 {
11725 switch (option)
11726 {
11727 default:
11728 break;
11729 }
11730 return string.Empty;
11731 }
11732
11733 public void KillEndDone()
11734 {
11735 }
11736
11737 #region IClientCore
11738
11739 private readonly Dictionary<Type, object> m_clientInterfaces = new Dictionary<Type, object>();
11740
11741 /// <summary>
11742 /// Register an interface on this client, should only be called in the constructor.
11743 /// </summary>
11744 /// <typeparam name="T"></typeparam>
11745 /// <param name="iface"></param>
11746 protected void RegisterInterface<T>(T iface)
11747 {
11748 lock (m_clientInterfaces)
11749 {
11750 if (!m_clientInterfaces.ContainsKey(typeof(T)))
11751 {
11752 m_clientInterfaces.Add(typeof(T), iface);
11753 }
11754 }
11755 }
11756
11757 public bool TryGet<T>(out T iface)
11758 {
11759 if (m_clientInterfaces.ContainsKey(typeof(T)))
11760 {
11761 iface = (T)m_clientInterfaces[typeof(T)];
11762 return true;
11763 }
11764 iface = default(T);
11765 return false;
11766 }
11767
11768 public T Get<T>()
11769 {
11770 return (T)m_clientInterfaces[typeof(T)];
11771 }
11772
11773 public void Disconnect(string reason)
11774 {
11775 Kick(reason);
11776 Thread.Sleep(1000);
11777 Close();
11778 }
11779
11780 public void Disconnect()
11781 {
11782 Close();
11783 }
11784
11785 #endregion
11786
11787 public void RefreshGroupMembership()
11788 {
11789 if (m_GroupsModule != null)
11790 {
11791 GroupMembershipData[] GroupMembership =
11792 m_GroupsModule.GetMembershipData(AgentId);
11793
11794 m_groupPowers.Clear();
11795
11796 if (GroupMembership != null)
11797 {
11798 for (int i = 0; i < GroupMembership.Length; i++)
11799 {
11800 m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers;
11801 }
11802 }
11803 }
11804 }
11805
11806 public string Report()
11807 {
11808 return m_udpClient.GetStats();
11809 }
11810
11811 public string XReport(string uptime, string version)
11812 {
11813 return String.Empty;
11814 }
11815
11816 /// <summary>
11817 /// Make an asset request to the asset service in response to a client request.
11818 /// </summary>
11819 /// <param name="transferRequest"></param>
11820 /// <param name="taskID"></param>
11821 protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID)
11822 {
11823 UUID requestID = UUID.Zero;
11824 if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
11825 {
11826 requestID = new UUID(transferRequest.TransferInfo.Params, 0);
11827 }
11828 else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
11829 {
11830 requestID = new UUID(transferRequest.TransferInfo.Params, 80);
11831 }
11832
11833// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11834
11835 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
11836 }
11837
11838 /// <summary>
11839 /// When we get a reply back from the asset service in response to a client request, send back the data.
11840 /// </summary>
11841 /// <param name="id"></param>
11842 /// <param name="sender"></param>
11843 /// <param name="asset"></param>
11844 protected void AssetReceived(string id, Object sender, AssetBase asset)
11845 {
11846 if (asset == null)
11847 return;
11848
11849 TransferRequestPacket transferRequest = (TransferRequestPacket)sender;
11850
11851 UUID requestID = UUID.Zero;
11852 byte source = (byte)SourceType.Asset;
11853
11854 if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
11855 {
11856 requestID = new UUID(transferRequest.TransferInfo.Params, 0);
11857 }
11858 else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
11859 {
11860 requestID = new UUID(transferRequest.TransferInfo.Params, 80);
11861 source = (byte)SourceType.SimInventoryItem;
11862 //m_log.Debug("asset request " + requestID);
11863 }
11864
11865 // Scripts cannot be retrieved by direct request
11866 if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset && asset.Type == 10)
11867 return;
11868
11869 // The asset is known to exist and is in our cache, so add it to the AssetRequests list
11870 AssetRequestToClient req = new AssetRequestToClient();
11871 req.AssetInf = asset;
11872 req.AssetRequestSource = source;
11873 req.IsTextureRequest = false;
11874 req.NumPackets = CalculateNumPackets(asset.Data);
11875 req.Params = transferRequest.TransferInfo.Params;
11876 req.RequestAssetID = requestID;
11877 req.TransferRequestID = transferRequest.TransferInfo.TransferID;
11878
11879 SendAsset(req);
11880 }
11881
11882 /// <summary>
11883 /// Calculate the number of packets required to send the asset to the client.
11884 /// </summary>
11885 /// <param name="data"></param>
11886 /// <returns></returns>
11887 private static int CalculateNumPackets(byte[] data)
11888 {
11889 const uint m_maxPacketSize = 600;
11890 int numPackets = 1;
11891
11892 if (data == null)
11893 return 0;
11894
11895 if (data.LongLength > m_maxPacketSize)
11896 {
11897 // over max number of bytes so split up file
11898 long restData = data.LongLength - m_maxPacketSize;
11899 int restPackets = (int)((restData + m_maxPacketSize - 1) / m_maxPacketSize);
11900 numPackets += restPackets;
11901 }
11902
11903 return numPackets;
11904 }
11905
11906 #region IClientIPEndpoint Members
11907
11908 public IPAddress EndPoint
11909 {
11910 get
11911 {
11912 if (m_userEndPoint is IPEndPoint)
11913 {
11914 IPEndPoint ep = (IPEndPoint)m_userEndPoint;
11915
11916 return ep.Address;
11917 }
11918 return null;
11919 }
11920 }
11921
11922 #endregion
11923
11924 public void SendRebakeAvatarTextures(UUID textureID)
11925 {
11926 RebakeAvatarTexturesPacket pack =
11927 (RebakeAvatarTexturesPacket)PacketPool.Instance.GetPacket(PacketType.RebakeAvatarTextures);
11928
11929 pack.TextureData = new RebakeAvatarTexturesPacket.TextureDataBlock();
11930 pack.TextureData.TextureID = textureID;
11931 OutPacket(pack, ThrottleOutPacketType.Task);
11932 }
11933
11934 public struct PacketProcessor
11935 {
11936 public PacketMethod method;
11937 public bool Async;
11938 }
11939
11940 public class AsyncPacketProcess
11941 {
11942 public bool result = false;
11943 public readonly LLClientView ClientView = null;
11944 public readonly Packet Pack = null;
11945 public readonly PacketMethod Method = null;
11946 public AsyncPacketProcess(LLClientView pClientview, PacketMethod pMethod, Packet pPack)
11947 {
11948 ClientView = pClientview;
11949 Method = pMethod;
11950 Pack = pPack;
11951 }
11952 }
11953
11954 public static OSD BuildEvent(string eventName, OSD eventBody)
11955 {
11956 OSDMap osdEvent = new OSDMap(2);
11957 osdEvent.Add("message", new OSDString(eventName));
11958 osdEvent.Add("body", eventBody);
11959
11960 return osdEvent;
11961 }
11962
11963 public void SendAvatarInterestsReply(UUID avatarID, uint wantMask, string wantText, uint skillsMask, string skillsText, string languages)
11964 {
11965 AvatarInterestsReplyPacket packet = (AvatarInterestsReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarInterestsReply);
11966
11967 packet.AgentData = new AvatarInterestsReplyPacket.AgentDataBlock();
11968 packet.AgentData.AgentID = AgentId;
11969 packet.AgentData.AvatarID = avatarID;
11970
11971 packet.PropertiesData = new AvatarInterestsReplyPacket.PropertiesDataBlock();
11972 packet.PropertiesData.WantToMask = wantMask;
11973 packet.PropertiesData.WantToText = Utils.StringToBytes(wantText);
11974 packet.PropertiesData.SkillsMask = skillsMask;
11975 packet.PropertiesData.SkillsText = Utils.StringToBytes(skillsText);
11976 packet.PropertiesData.LanguagesText = Utils.StringToBytes(languages);
11977 OutPacket(packet, ThrottleOutPacketType.Task);
11978 }
11979
11980 public void SendChangeUserRights(UUID agentID, UUID friendID, int rights)
11981 {
11982 ChangeUserRightsPacket packet = (ChangeUserRightsPacket)PacketPool.Instance.GetPacket(PacketType.ChangeUserRights);
11983
11984 packet.AgentData = new ChangeUserRightsPacket.AgentDataBlock();
11985 packet.AgentData.AgentID = agentID;
11986
11987 packet.Rights = new ChangeUserRightsPacket.RightsBlock[1];
11988 packet.Rights[0] = new ChangeUserRightsPacket.RightsBlock();
11989 packet.Rights[0].AgentRelated = friendID;
11990 packet.Rights[0].RelatedRights = rights;
11991
11992 OutPacket(packet, ThrottleOutPacketType.Task);
11993 }
11994
11995 public void SendTextBoxRequest(string message, int chatChannel, string objectname, string ownerFirstName, string ownerLastName, UUID objectId)
11996 {
11997 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog);
11998 dialog.Data.ObjectID = objectId;
11999 dialog.Data.ChatChannel = chatChannel;
12000 dialog.Data.ImageID = UUID.Zero;
12001 dialog.Data.ObjectName = Util.StringToBytes256(objectname);
12002 // this is the username of the *owner*
12003 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
12004 dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
12005 dialog.Data.Message = Util.StringToBytes256(message);
12006
12007 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[1];
12008 buttons[0] = new ScriptDialogPacket.ButtonsBlock();
12009 buttons[0].ButtonLabel = Util.StringToBytes256("!!llTextBox!!");
12010 dialog.Buttons = buttons;
12011 OutPacket(dialog, ThrottleOutPacketType.Task);
12012 }
12013
12014 public void StopFlying(ISceneEntity p)
12015 {
12016 if (p is ScenePresence)
12017 {
12018 ScenePresence presence = p as ScenePresence;
12019 // It turns out to get the agent to stop flying, you have to feed it stop flying velocities
12020 // There's no explicit message to send the client to tell it to stop flying.. it relies on the
12021 // velocity, collision plane and avatar height
12022
12023 // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air
12024 // when the avatar stands up
12025
12026 Vector3 pos = presence.AbsolutePosition;
12027
12028 if (presence.Appearance.AvatarHeight != 127.0f)
12029 pos += new Vector3(0f, 0f, (presence.Appearance.AvatarHeight/6f));
12030 else
12031 pos += new Vector3(0f, 0f, (1.56f/6f));
12032
12033 presence.AbsolutePosition = pos;
12034
12035 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
12036 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
12037 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
12038 // certain amount.. because the LLClient wouldn't land in that situation anyway.
12039
12040 // why are we still testing for this really old height value default???
12041 if (presence.Appearance.AvatarHeight != 127.0f)
12042 presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - presence.Appearance.AvatarHeight/6f);
12043 else
12044 presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f/6f));
12045
12046
12047 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block =
12048 CreateImprovedTerseBlock(p, false);
12049
12050 const float TIME_DILATION = 1.0f;
12051 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
12052
12053
12054 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
12055 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
12056 packet.RegionData.TimeDilation = timeDilation;
12057 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
12058
12059 packet.ObjectData[0] = block;
12060
12061 OutPacket(packet, ThrottleOutPacketType.Task, true);
12062 }
12063
12064 //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
12065 // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
12066 }
12067
12068 public void SendPlacesReply(UUID queryID, UUID transactionID,
12069 PlacesReplyData[] data)
12070 {
12071 PlacesReplyPacket reply = null;
12072 PlacesReplyPacket.QueryDataBlock[] dataBlocks =
12073 new PlacesReplyPacket.QueryDataBlock[0];
12074
12075 for (int i = 0 ; i < data.Length ; i++)
12076 {
12077 PlacesReplyPacket.QueryDataBlock block =
12078 new PlacesReplyPacket.QueryDataBlock();
12079
12080 block.OwnerID = data[i].OwnerID;
12081 block.Name = Util.StringToBytes256(data[i].Name);
12082 block.Desc = Util.StringToBytes1024(data[i].Desc);
12083 block.ActualArea = data[i].ActualArea;
12084 block.BillableArea = data[i].BillableArea;
12085 block.Flags = data[i].Flags;
12086 block.GlobalX = data[i].GlobalX;
12087 block.GlobalY = data[i].GlobalY;
12088 block.GlobalZ = data[i].GlobalZ;
12089 block.SimName = Util.StringToBytes256(data[i].SimName);
12090 block.SnapshotID = data[i].SnapshotID;
12091 block.Dwell = data[i].Dwell;
12092 block.Price = data[i].Price;
12093
12094 if (reply != null && reply.Length + block.Length > 1400)
12095 {
12096 OutPacket(reply, ThrottleOutPacketType.Task);
12097
12098 reply = null;
12099 dataBlocks = new PlacesReplyPacket.QueryDataBlock[0];
12100 }
12101
12102 if (reply == null)
12103 {
12104 reply = (PlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.PlacesReply);
12105 reply.AgentData = new PlacesReplyPacket.AgentDataBlock();
12106 reply.AgentData.AgentID = AgentId;
12107 reply.AgentData.QueryID = queryID;
12108
12109 reply.TransactionData = new PlacesReplyPacket.TransactionDataBlock();
12110 reply.TransactionData.TransactionID = transactionID;
12111
12112 reply.QueryData = dataBlocks;
12113 }
12114
12115 Array.Resize(ref dataBlocks, dataBlocks.Length + 1);
12116 dataBlocks[dataBlocks.Length - 1] = block;
12117 reply.QueryData = dataBlocks;
12118 }
12119 if (reply != null)
12120 OutPacket(reply, ThrottleOutPacketType.Task);
12121 }
12122 }
12123}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs
new file mode 100644
index 0000000..9e0db12
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs
@@ -0,0 +1,257 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Threading;
30using System.Collections;
31using System.Collections.Generic;
32using System.Reflection;
33using OpenMetaverse;
34using OpenMetaverse.Imaging;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Services.Interfaces;
38using log4net;
39
40namespace OpenSim.Region.ClientStack.LindenUDP
41{
42 public class LLImageManager
43 {
44 private sealed class J2KImageComparer : IComparer<J2KImage>
45 {
46 public int Compare(J2KImage x, J2KImage y)
47 {
48 return x.Priority.CompareTo(y.Priority);
49 }
50 }
51
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 private bool m_shuttingdown;
54 private AssetBase m_missingImage;
55 private LLClientView m_client; //Client we're assigned to
56 private IAssetService m_assetCache; //Asset Cache
57 private IJ2KDecoder m_j2kDecodeModule; //Our J2K module
58 private C5.IntervalHeap<J2KImage> m_priorityQueue = new C5.IntervalHeap<J2KImage>(10, new J2KImageComparer());
59 private object m_syncRoot = new object();
60
61 public LLClientView Client { get { return m_client; } }
62 public AssetBase MissingImage { get { return m_missingImage; } }
63
64 public LLImageManager(LLClientView client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule)
65 {
66 m_client = client;
67 m_assetCache = pAssetCache;
68
69 if (pAssetCache != null)
70 m_missingImage = pAssetCache.Get("5748decc-f629-461c-9a36-a35a221fe21f");
71
72 if (m_missingImage == null)
73 m_log.Error("[ClientView] - Couldn't set missing image asset, falling back to missing image packet. This is known to crash the client");
74
75 m_j2kDecodeModule = pJ2kDecodeModule;
76 }
77
78 /// <summary>
79 /// Handles an incoming texture request or update to an existing texture request
80 /// </summary>
81 /// <param name="newRequest"></param>
82 public void EnqueueReq(TextureRequestArgs newRequest)
83 {
84 //Make sure we're not shutting down..
85 if (!m_shuttingdown)
86 {
87 J2KImage imgrequest;
88
89 // Do a linear search for this texture download
90 lock (m_syncRoot)
91 m_priorityQueue.Find(delegate(J2KImage img) { return img.TextureID == newRequest.RequestedAssetID; }, out imgrequest);
92
93 if (imgrequest != null)
94 {
95 if (newRequest.DiscardLevel == -1 && newRequest.Priority == 0f)
96 {
97 //m_log.Debug("[TEX]: (CAN) ID=" + newRequest.RequestedAssetID);
98
99 try
100 {
101 lock (m_syncRoot)
102 m_priorityQueue.Delete(imgrequest.PriorityQueueHandle);
103 }
104 catch (Exception) { }
105 }
106 else
107 {
108 //m_log.DebugFormat("[TEX]: (UPD) ID={0}: D={1}, S={2}, P={3}",
109 // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority);
110
111 //Check the packet sequence to make sure this isn't older than
112 //one we've already received
113 if (newRequest.requestSequence > imgrequest.LastSequence)
114 {
115 //Update the sequence number of the last RequestImage packet
116 imgrequest.LastSequence = newRequest.requestSequence;
117
118 //Update the requested discard level
119 imgrequest.DiscardLevel = newRequest.DiscardLevel;
120
121 //Update the requested packet number
122 imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber);
123
124 //Update the requested priority
125 imgrequest.Priority = newRequest.Priority;
126 UpdateImageInQueue(imgrequest);
127
128 //Run an update
129 imgrequest.RunUpdate();
130 }
131 }
132 }
133 else
134 {
135 if (newRequest.DiscardLevel == -1 && newRequest.Priority == 0f)
136 {
137 //m_log.DebugFormat("[TEX]: (IGN) ID={0}: D={1}, S={2}, P={3}",
138 // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority);
139 }
140 else
141 {
142 //m_log.DebugFormat("[TEX]: (NEW) ID={0}: D={1}, S={2}, P={3}",
143 // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority);
144
145 imgrequest = new J2KImage(this);
146 imgrequest.J2KDecoder = m_j2kDecodeModule;
147 imgrequest.AssetService = m_assetCache;
148 imgrequest.AgentID = m_client.AgentId;
149 imgrequest.InventoryAccessModule = m_client.Scene.RequestModuleInterface<IInventoryAccessModule>();
150 imgrequest.DiscardLevel = newRequest.DiscardLevel;
151 imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber);
152 imgrequest.Priority = newRequest.Priority;
153 imgrequest.TextureID = newRequest.RequestedAssetID;
154 imgrequest.Priority = newRequest.Priority;
155
156 //Add this download to the priority queue
157 AddImageToQueue(imgrequest);
158
159 //Run an update
160 imgrequest.RunUpdate();
161 }
162 }
163 }
164 }
165
166 public bool ProcessImageQueue(int packetsToSend)
167 {
168 int packetsSent = 0;
169
170 while (packetsSent < packetsToSend)
171 {
172 J2KImage image = GetHighestPriorityImage();
173
174 // If null was returned, the texture priority queue is currently empty
175 if (image == null)
176 return false;
177
178 if (image.IsDecoded)
179 {
180 int sent;
181 bool imageDone = image.SendPackets(m_client, packetsToSend - packetsSent, out sent);
182 packetsSent += sent;
183
184 // If the send is complete, destroy any knowledge of this transfer
185 if (imageDone)
186 RemoveImageFromQueue(image);
187 }
188 else
189 {
190 // TODO: This is a limitation of how LLImageManager is currently
191 // written. Undecoded textures should not be going into the priority
192 // queue, because a high priority undecoded texture will clog up the
193 // pipeline for a client
194 return true;
195 }
196 }
197
198 return m_priorityQueue.Count > 0;
199 }
200
201 /// <summary>
202 /// Faux destructor
203 /// </summary>
204 public void Close()
205 {
206 m_shuttingdown = true;
207 }
208
209 #region Priority Queue Helpers
210
211 J2KImage GetHighestPriorityImage()
212 {
213 J2KImage image = null;
214
215 lock (m_syncRoot)
216 {
217 if (m_priorityQueue.Count > 0)
218 {
219 try { image = m_priorityQueue.FindMax(); }
220 catch (Exception) { }
221 }
222 }
223 return image;
224 }
225
226 void AddImageToQueue(J2KImage image)
227 {
228 image.PriorityQueueHandle = null;
229
230 lock (m_syncRoot)
231 try { m_priorityQueue.Add(ref image.PriorityQueueHandle, image); }
232 catch (Exception) { }
233 }
234
235 void RemoveImageFromQueue(J2KImage image)
236 {
237 lock (m_syncRoot)
238 try { m_priorityQueue.Delete(image.PriorityQueueHandle); }
239 catch (Exception) { }
240 }
241
242 void UpdateImageInQueue(J2KImage image)
243 {
244 lock (m_syncRoot)
245 {
246 try { m_priorityQueue.Replace(image.PriorityQueueHandle, image); }
247 catch (Exception)
248 {
249 image.PriorityQueueHandle = null;
250 m_priorityQueue.Add(ref image.PriorityQueueHandle, image);
251 }
252 }
253 }
254
255 #endregion Priority Queue Helpers
256 }
257}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
new file mode 100644
index 0000000..ca5501d
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -0,0 +1,697 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Threading;
32using log4net;
33using OpenSim.Framework;
34using OpenMetaverse;
35using OpenMetaverse.Packets;
36
37using TokenBucket = OpenSim.Region.ClientStack.LindenUDP.TokenBucket;
38
39namespace OpenSim.Region.ClientStack.LindenUDP
40{
41 #region Delegates
42
43 /// <summary>
44 /// Fired when updated networking stats are produced for this client
45 /// </summary>
46 /// <param name="inPackets">Number of incoming packets received since this
47 /// event was last fired</param>
48 /// <param name="outPackets">Number of outgoing packets sent since this
49 /// event was last fired</param>
50 /// <param name="unAckedBytes">Current total number of bytes in packets we
51 /// are waiting on ACKs for</param>
52 public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes);
53 /// <summary>
54 /// Fired when the queue for one or more packet categories is empty. This
55 /// event can be hooked to put more data on the empty queues
56 /// </summary>
57 /// <param name="category">Categories of the packet queues that are empty</param>
58 public delegate void QueueEmpty(ThrottleOutPacketTypeFlags categories);
59
60 #endregion Delegates
61
62 /// <summary>
63 /// Tracks state for a client UDP connection and provides client-specific methods
64 /// </summary>
65 public sealed class LLUDPClient
66 {
67 // TODO: Make this a config setting
68 /// <summary>Percentage of the task throttle category that is allocated to avatar and prim
69 /// state updates</summary>
70 const float STATE_TASK_PERCENTAGE = 0.8f;
71
72 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
73
74 /// <summary>The number of packet categories to throttle on. If a throttle category is added
75 /// or removed, this number must also change</summary>
76 const int THROTTLE_CATEGORY_COUNT = 8;
77
78 /// <summary>Fired when updated networking stats are produced for this client</summary>
79 public event PacketStats OnPacketStats;
80 /// <summary>Fired when the queue for a packet category is empty. This event can be
81 /// hooked to put more data on the empty queue</summary>
82 public event QueueEmpty OnQueueEmpty;
83
84 /// <summary>AgentID for this client</summary>
85 public readonly UUID AgentID;
86 /// <summary>The remote address of the connected client</summary>
87 public readonly IPEndPoint RemoteEndPoint;
88 /// <summary>Circuit code that this client is connected on</summary>
89 public readonly uint CircuitCode;
90 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
91 public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200);
92 /// <summary>Packets we have sent that need to be ACKed by the client</summary>
93 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
94 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
95 public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>();
96
97 /// <summary>Current packet sequence number</summary>
98 public int CurrentSequence;
99 /// <summary>Current ping sequence number</summary>
100 public byte CurrentPingSequence;
101 /// <summary>True when this connection is alive, otherwise false</summary>
102 public bool IsConnected = true;
103 /// <summary>True when this connection is paused, otherwise false</summary>
104 public bool IsPaused;
105 /// <summary>Environment.TickCount when the last packet was received for this client</summary>
106 public int TickLastPacketReceived;
107
108 /// <summary>Smoothed round-trip time. A smoothed average of the round-trip time for sending a
109 /// reliable packet to the client and receiving an ACK</summary>
110 public float SRTT;
111 /// <summary>Round-trip time variance. Measures the consistency of round-trip times</summary>
112 public float RTTVAR;
113 /// <summary>Retransmission timeout. Packets that have not been acknowledged in this number of
114 /// milliseconds or longer will be resent</summary>
115 /// <remarks>Calculated from <seealso cref="SRTT"/> and <seealso cref="RTTVAR"/> using the
116 /// guidelines in RFC 2988</remarks>
117 public int RTO;
118 /// <summary>Number of bytes received since the last acknowledgement was sent out. This is used
119 /// to loosely follow the TCP delayed ACK algorithm in RFC 1122 (4.2.3.2)</summary>
120 public int BytesSinceLastACK;
121 /// <summary>Number of packets received from this client</summary>
122 public int PacketsReceived;
123 /// <summary>Number of packets sent to this client</summary>
124 public int PacketsSent;
125 /// <summary>Number of packets resent to this client</summary>
126 public int PacketsResent;
127 /// <summary>Total byte count of unacked packets sent to this client</summary>
128 public int UnackedBytes;
129
130 /// <summary>Total number of received packets that we have reported to the OnPacketStats event(s)</summary>
131 private int m_packetsReceivedReported;
132 /// <summary>Total number of sent packets that we have reported to the OnPacketStats event(s)</summary>
133 private int m_packetsSentReported;
134 /// <summary>Holds the Environment.TickCount value of when the next OnQueueEmpty can be fired</summary>
135 private int m_nextOnQueueEmpty = 1;
136
137 /// <summary>Throttle bucket for this agent's connection</summary>
138 private readonly AdaptiveTokenBucket m_throttleClient;
139 public AdaptiveTokenBucket FlowThrottle
140 {
141 get { return m_throttleClient; }
142 }
143
144 /// <summary>Throttle bucket for this agent's connection</summary>
145 private readonly TokenBucket m_throttleCategory;
146 /// <summary>Throttle buckets for each packet category</summary>
147 private readonly TokenBucket[] m_throttleCategories;
148 /// <summary>Outgoing queues for throttled packets</summary>
149 private readonly OpenSim.Framework.LocklessQueue<OutgoingPacket>[] m_packetOutboxes = new OpenSim.Framework.LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT];
150 /// <summary>A container that can hold one packet for each outbox, used to store
151 /// dequeued packets that are being held for throttling</summary>
152 private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT];
153 /// <summary>A reference to the LLUDPServer that is managing this client</summary>
154 private readonly LLUDPServer m_udpServer;
155
156 /// <summary>Caches packed throttle information</summary>
157 private byte[] m_packedThrottles;
158
159 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
160 private int m_maxRTO = 60000;
161
162 /// <summary>
163 /// Default constructor
164 /// </summary>
165 /// <param name="server">Reference to the UDP server this client is connected to</param>
166 /// <param name="rates">Default throttling rates and maximum throttle limits</param>
167 /// <param name="parentThrottle">Parent HTB (hierarchical token bucket)
168 /// that the child throttles will be governed by</param>
169 /// <param name="circuitCode">Circuit code for this connection</param>
170 /// <param name="agentID">AgentID for the connected agent</param>
171 /// <param name="remoteEndPoint">Remote endpoint for this connection</param>
172 public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO)
173 {
174 AgentID = agentID;
175 RemoteEndPoint = remoteEndPoint;
176 CircuitCode = circuitCode;
177 m_udpServer = server;
178 if (defaultRTO != 0)
179 m_defaultRTO = defaultRTO;
180 if (maxRTO != 0)
181 m_maxRTO = maxRTO;
182
183 // Create a token bucket throttle for this client that has the scene token bucket as a parent
184 m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled);
185 // Create a token bucket throttle for the total categary with the client bucket as a throttle
186 m_throttleCategory = new TokenBucket(m_throttleClient, 0);
187 // Create an array of token buckets for this clients different throttle categories
188 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
189
190 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
191 {
192 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
193
194 // Initialize the packet outboxes, where packets sit while they are waiting for tokens
195 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
196 // Initialize the token buckets that control the throttling for each category
197 m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type));
198 }
199
200 // Default the retransmission timeout to three seconds
201 RTO = m_defaultRTO;
202
203 // Initialize this to a sane value to prevent early disconnects
204 TickLastPacketReceived = Environment.TickCount & Int32.MaxValue;
205 }
206
207 /// <summary>
208 /// Shuts down this client connection
209 /// </summary>
210 public void Shutdown()
211 {
212 IsConnected = false;
213 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
214 {
215 m_packetOutboxes[i].Clear();
216 m_nextPackets[i] = null;
217 }
218
219 // pull the throttle out of the scene throttle
220 m_throttleClient.Parent.UnregisterRequest(m_throttleClient);
221 OnPacketStats = null;
222 OnQueueEmpty = null;
223 }
224
225 /// <summary>
226 /// Gets information about this client connection
227 /// </summary>
228 /// <returns>Information about the client connection</returns>
229 public ClientInfo GetClientInfo()
230 {
231 // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
232 // of pending and needed ACKs for every client every time some method wants information about
233 // this connection is a recipe for poor performance
234 ClientInfo info = new ClientInfo();
235 info.pendingAcks = new Dictionary<uint, uint>();
236 info.needAck = new Dictionary<uint, byte[]>();
237
238 info.resendThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate;
239 info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
240 info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
241 info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
242 info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
243 info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
244 info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
245 info.totalThrottle = (int)m_throttleCategory.DripRate;
246
247 return info;
248 }
249
250 /// <summary>
251 /// Modifies the UDP throttles
252 /// </summary>
253 /// <param name="info">New throttling values</param>
254 public void SetClientInfo(ClientInfo info)
255 {
256 // TODO: Allowing throttles to be manually set from this function seems like a reasonable
257 // idea. On the other hand, letting external code manipulate our ACK accounting is not
258 // going to happen
259 throw new NotImplementedException();
260 }
261
262 /// <summary>
263 /// Return statistics information about client packet queues.
264 /// </summary>
265 ///
266 /// FIXME: This should really be done in a more sensible manner rather than sending back a formatted string.
267 ///
268 /// <returns></returns>
269 public string GetStats()
270 {
271 return string.Format(
272 "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}",
273 PacketsReceived,
274 PacketsSent,
275 PacketsResent,
276 UnackedBytes,
277 m_packetOutboxes[(int)ThrottleOutPacketType.Resend].Count,
278 m_packetOutboxes[(int)ThrottleOutPacketType.Land].Count,
279 m_packetOutboxes[(int)ThrottleOutPacketType.Wind].Count,
280 m_packetOutboxes[(int)ThrottleOutPacketType.Cloud].Count,
281 m_packetOutboxes[(int)ThrottleOutPacketType.Task].Count,
282 m_packetOutboxes[(int)ThrottleOutPacketType.Texture].Count,
283 m_packetOutboxes[(int)ThrottleOutPacketType.Asset].Count,
284 m_packetOutboxes[(int)ThrottleOutPacketType.State].Count);
285 }
286
287 public void SendPacketStats()
288 {
289 PacketStats callback = OnPacketStats;
290 if (callback != null)
291 {
292 int newPacketsReceived = PacketsReceived - m_packetsReceivedReported;
293 int newPacketsSent = PacketsSent - m_packetsSentReported;
294
295 callback(newPacketsReceived, newPacketsSent, UnackedBytes);
296
297 m_packetsReceivedReported += newPacketsReceived;
298 m_packetsSentReported += newPacketsSent;
299 }
300 }
301
302 public void SetThrottles(byte[] throttleData)
303 {
304 byte[] adjData;
305 int pos = 0;
306
307 if (!BitConverter.IsLittleEndian)
308 {
309 byte[] newData = new byte[7 * 4];
310 Buffer.BlockCopy(throttleData, 0, newData, 0, 7 * 4);
311
312 for (int i = 0; i < 7; i++)
313 Array.Reverse(newData, i * 4, 4);
314
315 adjData = newData;
316 }
317 else
318 {
319 adjData = throttleData;
320 }
321
322 // 0.125f converts from bits to bytes
323 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
324 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
325 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
326 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
327 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
328 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
329 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
330 // State is a subcategory of task that we allocate a percentage to
331 int state = 0;
332
333 // Make sure none of the throttles are set below our packet MTU,
334 // otherwise a throttle could become permanently clogged
335 resend = Math.Max(resend, LLUDPServer.MTU);
336 land = Math.Max(land, LLUDPServer.MTU);
337 wind = Math.Max(wind, LLUDPServer.MTU);
338 cloud = Math.Max(cloud, LLUDPServer.MTU);
339 task = Math.Max(task, LLUDPServer.MTU);
340 texture = Math.Max(texture, LLUDPServer.MTU);
341 asset = Math.Max(asset, LLUDPServer.MTU);
342
343 //int total = resend + land + wind + cloud + task + texture + asset;
344 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
345 // AgentID, resend, land, wind, cloud, task, texture, asset, total);
346
347 // Update the token buckets with new throttle values
348 TokenBucket bucket;
349
350 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
351 bucket.RequestedDripRate = resend;
352
353 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land];
354 bucket.RequestedDripRate = land;
355
356 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind];
357 bucket.RequestedDripRate = wind;
358
359 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud];
360 bucket.RequestedDripRate = cloud;
361
362 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset];
363 bucket.RequestedDripRate = asset;
364
365 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task];
366 bucket.RequestedDripRate = task;
367
368 bucket = m_throttleCategories[(int)ThrottleOutPacketType.State];
369 bucket.RequestedDripRate = state;
370
371 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture];
372 bucket.RequestedDripRate = texture;
373
374 // Reset the packed throttles cached data
375 m_packedThrottles = null;
376 }
377
378 public byte[] GetThrottlesPacked(float multiplier)
379 {
380 byte[] data = m_packedThrottles;
381
382 if (data == null)
383 {
384 float rate;
385
386 data = new byte[7 * 4];
387 int i = 0;
388
389 // multiply by 8 to convert bytes back to bits
390 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier;
391 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
392
393 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier;
394 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
395
396 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * 8 * multiplier;
397 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
398
399 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * 8 * multiplier;
400 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
401
402 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * 8 * multiplier;
403 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
404
405 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * 8 * multiplier;
406 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
407
408 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * 8 * multiplier;
409 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
410
411 m_packedThrottles = data;
412 }
413
414 return data;
415 }
416
417 /// <summary>
418 /// Queue an outgoing packet if appropriate.
419 /// </summary>
420 /// <param name="packet"></param>
421 /// <param name="forceQueue">Always queue the packet if at all possible.</param>
422 /// <returns>
423 /// true if the packet has been queued,
424 /// false if the packet has not been queued and should be sent immediately.
425 /// </returns>
426 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue)
427 {
428 int category = (int)packet.Category;
429
430 if (category >= 0 && category < m_packetOutboxes.Length)
431 {
432 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
433 TokenBucket bucket = m_throttleCategories[category];
434
435 // Don't send this packet if there is already a packet waiting in the queue
436 // even if we have the tokens to send it, tokens should go to the already
437 // queued packets
438 if (queue.Count > 0)
439 {
440 queue.Enqueue(packet);
441 return true;
442 }
443
444
445 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
446 {
447 // Enough tokens were removed from the bucket, the packet will not be queued
448 return false;
449 }
450 else
451 {
452 // Force queue specified or not enough tokens in the bucket, queue this packet
453 queue.Enqueue(packet);
454 return true;
455 }
456 }
457 else
458 {
459 // We don't have a token bucket for this category, so it will not be queued
460 return false;
461 }
462 }
463
464 /// <summary>
465 /// Loops through all of the packet queues for this client and tries to send
466 /// an outgoing packet from each, obeying the throttling bucket limits
467 /// </summary>
468 ///
469 /// <remarks>
470 /// Packet queues are inspected in ascending numerical order starting from 0. Therefore, queues with a lower
471 /// ThrottleOutPacketType number will see their packet get sent first (e.g. if both Land and Wind queues have
472 /// packets, then the packet at the front of the Land queue will be sent before the packet at the front of the
473 /// wind queue).
474 ///
475 /// This function is only called from a synchronous loop in the
476 /// UDPServer so we don't need to bother making this thread safe
477 /// </remarks>
478 ///
479 /// <returns>True if any packets were sent, otherwise false</returns>
480 public bool DequeueOutgoing()
481 {
482 OutgoingPacket packet;
483 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
484 TokenBucket bucket;
485 bool packetSent = false;
486 ThrottleOutPacketTypeFlags emptyCategories = 0;
487
488 //string queueDebugOutput = String.Empty; // Serious debug business
489
490 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
491 {
492 bucket = m_throttleCategories[i];
493 //queueDebugOutput += m_packetOutboxes[i].Count + " "; // Serious debug business
494
495 if (m_nextPackets[i] != null)
496 {
497 // This bucket was empty the last time we tried to send a packet,
498 // leaving a dequeued packet still waiting to be sent out. Try to
499 // send it again
500 OutgoingPacket nextPacket = m_nextPackets[i];
501 if (bucket.RemoveTokens(nextPacket.Buffer.DataLength))
502 {
503 // Send the packet
504 m_udpServer.SendPacketFinal(nextPacket);
505 m_nextPackets[i] = null;
506 packetSent = true;
507 }
508 }
509 else
510 {
511 // No dequeued packet waiting to be sent, try to pull one off
512 // this queue
513 queue = m_packetOutboxes[i];
514 if (queue.Dequeue(out packet))
515 {
516 // A packet was pulled off the queue. See if we have
517 // enough tokens in the bucket to send it out
518 if (bucket.RemoveTokens(packet.Buffer.DataLength))
519 {
520 // Send the packet
521 m_udpServer.SendPacketFinal(packet);
522 packetSent = true;
523 }
524 else
525 {
526 // Save the dequeued packet for the next iteration
527 m_nextPackets[i] = packet;
528 }
529
530 // If the queue is empty after this dequeue, fire the queue
531 // empty callback now so it has a chance to fill before we
532 // get back here
533 if (queue.Count == 0)
534 emptyCategories |= CategoryToFlag(i);
535 }
536 else
537 {
538 // No packets in this queue. Fire the queue empty callback
539 // if it has not been called recently
540 emptyCategories |= CategoryToFlag(i);
541 }
542 }
543 }
544
545 if (emptyCategories != 0)
546 BeginFireQueueEmpty(emptyCategories);
547
548 //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business
549 return packetSent;
550 }
551
552 /// <summary>
553 /// Called when an ACK packet is received and a round-trip time for a
554 /// packet is calculated. This is used to calculate the smoothed
555 /// round-trip time, round trip time variance, and finally the
556 /// retransmission timeout
557 /// </summary>
558 /// <param name="r">Round-trip time of a single packet and its
559 /// acknowledgement</param>
560 public void UpdateRoundTrip(float r)
561 {
562 const float ALPHA = 0.125f;
563 const float BETA = 0.25f;
564 const float K = 4.0f;
565
566 if (RTTVAR == 0.0f)
567 {
568 // First RTT measurement
569 SRTT = r;
570 RTTVAR = r * 0.5f;
571 }
572 else
573 {
574 // Subsequence RTT measurement
575 RTTVAR = (1.0f - BETA) * RTTVAR + BETA * Math.Abs(SRTT - r);
576 SRTT = (1.0f - ALPHA) * SRTT + ALPHA * r;
577 }
578
579 int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR));
580
581 // Clamp the retransmission timeout to manageable values
582 rto = Utils.Clamp(rto, m_defaultRTO, m_maxRTO);
583
584 RTO = rto;
585
586 //m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " +
587 // RTTVAR + " based on new RTT of " + r + "ms");
588 }
589
590 /// <summary>
591 /// Exponential backoff of the retransmission timeout, per section 5.5
592 /// of RFC 2988
593 /// </summary>
594 public void BackoffRTO()
595 {
596 // Reset SRTT and RTTVAR, we assume they are bogus since things
597 // didn't work out and we're backing off the timeout
598 SRTT = 0.0f;
599 RTTVAR = 0.0f;
600
601 // Double the retransmission timeout
602 RTO = Math.Min(RTO * 2, m_maxRTO);
603 }
604
605 /// <summary>
606 /// Does an early check to see if this queue empty callback is already
607 /// running, then asynchronously firing the event
608 /// </summary>
609 /// <param name="throttleIndex">Throttle category to fire the callback
610 /// for</param>
611 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
612 {
613 if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
614 {
615 // Use a value of 0 to signal that FireQueueEmpty is running
616 m_nextOnQueueEmpty = 0;
617 // Asynchronously run the callback
618 Util.FireAndForget(FireQueueEmpty, categories);
619 }
620 }
621
622 /// <summary>
623 /// Fires the OnQueueEmpty callback and sets the minimum time that it
624 /// can be called again
625 /// </summary>
626 /// <param name="o">Throttle categories to fire the callback for,
627 /// stored as an object to match the WaitCallback delegate
628 /// signature</param>
629 private void FireQueueEmpty(object o)
630 {
631 const int MIN_CALLBACK_MS = 30;
632
633 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
634 QueueEmpty callback = OnQueueEmpty;
635
636 int start = Environment.TickCount & Int32.MaxValue;
637
638 if (callback != null)
639 {
640 try { callback(categories); }
641 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
642 }
643
644 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
645 if (m_nextOnQueueEmpty == 0)
646 m_nextOnQueueEmpty = 1;
647 }
648
649 /// <summary>
650 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a
651 /// flag value
652 /// </summary>
653 /// <param name="i">Throttle category to convert</param>
654 /// <returns>Flag representation of the throttle category</returns>
655 private static ThrottleOutPacketTypeFlags CategoryToFlag(int i)
656 {
657 ThrottleOutPacketType category = (ThrottleOutPacketType)i;
658
659 /*
660 * Land = 1,
661 /// <summary>Wind data</summary>
662 Wind = 2,
663 /// <summary>Cloud data</summary>
664 Cloud = 3,
665 /// <summary>Any packets that do not fit into the other throttles</summary>
666 Task = 4,
667 /// <summary>Texture assets</summary>
668 Texture = 5,
669 /// <summary>Non-texture assets</summary>
670 Asset = 6,
671 /// <summary>Avatar and primitive data</summary>
672 /// <remarks>This is a sub-category of Task</remarks>
673 State = 7,
674 */
675
676 switch (category)
677 {
678 case ThrottleOutPacketType.Land:
679 return ThrottleOutPacketTypeFlags.Land;
680 case ThrottleOutPacketType.Wind:
681 return ThrottleOutPacketTypeFlags.Wind;
682 case ThrottleOutPacketType.Cloud:
683 return ThrottleOutPacketTypeFlags.Cloud;
684 case ThrottleOutPacketType.Task:
685 return ThrottleOutPacketTypeFlags.Task;
686 case ThrottleOutPacketType.Texture:
687 return ThrottleOutPacketTypeFlags.Texture;
688 case ThrottleOutPacketType.Asset:
689 return ThrottleOutPacketTypeFlags.Asset;
690 case ThrottleOutPacketType.State:
691 return ThrottleOutPacketTypeFlags.State;
692 default:
693 return 0;
694 }
695 }
696 }
697}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
new file mode 100644
index 0000000..aff90c5
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -0,0 +1,1274 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Diagnostics;
31using System.IO;
32using System.Net;
33using System.Net.Sockets;
34using System.Reflection;
35using System.Threading;
36using log4net;
37using Nini.Config;
38using OpenMetaverse.Packets;
39using OpenSim.Framework;
40using OpenSim.Framework.Statistics;
41using OpenSim.Region.Framework.Scenes;
42using OpenMetaverse;
43
44using TokenBucket = OpenSim.Region.ClientStack.LindenUDP.TokenBucket;
45
46namespace OpenSim.Region.ClientStack.LindenUDP
47{
48 /// <summary>
49 /// A shim around LLUDPServer that implements the IClientNetworkServer interface
50 /// </summary>
51 public sealed class LLUDPServerShim : IClientNetworkServer
52 {
53 LLUDPServer m_udpServer;
54
55 public LLUDPServerShim()
56 {
57 }
58
59 public void Initialise(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
60 {
61 m_udpServer = new LLUDPServer(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager);
62 }
63
64 public void NetworkStop()
65 {
66 m_udpServer.Stop();
67 }
68
69 public void AddScene(IScene scene)
70 {
71 m_udpServer.AddScene(scene);
72 }
73
74 public bool HandlesRegion(Location x)
75 {
76 return m_udpServer.HandlesRegion(x);
77 }
78
79 public void Start()
80 {
81 m_udpServer.Start();
82 }
83
84 public void Stop()
85 {
86 m_udpServer.Stop();
87 }
88 }
89
90 /// <summary>
91 /// The LLUDP server for a region. This handles incoming and outgoing
92 /// packets for all UDP connections to the region
93 /// </summary>
94 public class LLUDPServer : OpenSimUDPBase
95 {
96 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
97 public const int MTU = 1400;
98
99 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
100
101 /// <summary>The measured resolution of Environment.TickCount</summary>
102 public readonly float TickCountResolution;
103 /// <summary>Number of prim updates to put on the queue each time the
104 /// OnQueueEmpty event is triggered for updates</summary>
105 public readonly int PrimUpdatesPerCallback;
106 /// <summary>Number of texture packets to put on the queue each time the
107 /// OnQueueEmpty event is triggered for textures</summary>
108 public readonly int TextureSendLimit;
109
110 /// <summary>Handlers for incoming packets</summary>
111 //PacketEventDictionary packetEvents = new PacketEventDictionary();
112 /// <summary>Incoming packets that are awaiting handling</summary>
113 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
114 /// <summary></summary>
115 //private UDPClientCollection m_clients = new UDPClientCollection();
116 /// <summary>Bandwidth throttle for this UDP server</summary>
117 protected TokenBucket m_throttle;
118
119 /// <summary>Bandwidth throttle rates for this UDP server</summary>
120 public ThrottleRates ThrottleRates { get; private set; }
121
122 /// <summary>Manages authentication for agent circuits</summary>
123 private AgentCircuitManager m_circuitManager;
124 /// <summary>Reference to the scene this UDP server is attached to</summary>
125 protected Scene m_scene;
126 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
127 private Location m_location;
128 /// <summary>The size of the receive buffer for the UDP socket. This value
129 /// is passed up to the operating system and used in the system networking
130 /// stack. Use zero to leave this value as the default</summary>
131 private int m_recvBufferSize;
132 /// <summary>Flag to process packets asynchronously or synchronously</summary>
133 private bool m_asyncPacketHandling;
134 /// <summary>Tracks whether or not a packet was sent each round so we know
135 /// whether or not to sleep</summary>
136 private bool m_packetSent;
137
138 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary>
139 private int m_elapsedMSSinceLastStatReport = 0;
140 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary>
141 private int m_tickLastOutgoingPacketHandler;
142 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary>
143 private int m_elapsedMSOutgoingPacketHandler;
144 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary>
145 private int m_elapsed100MSOutgoingPacketHandler;
146 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary>
147 private int m_elapsed500MSOutgoingPacketHandler;
148
149 /// <summary>Flag to signal when clients should check for resends</summary>
150 private bool m_resendUnacked;
151 /// <summary>Flag to signal when clients should send ACKs</summary>
152 private bool m_sendAcks;
153 /// <summary>Flag to signal when clients should send pings</summary>
154 private bool m_sendPing;
155
156 private int m_defaultRTO = 0;
157 private int m_maxRTO = 0;
158
159 private bool m_disableFacelights = false;
160
161 public Socket Server { get { return null; } }
162
163 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
164 : base(listenIP, (int)port)
165 {
166 #region Environment.TickCount Measurement
167
168 // Measure the resolution of Environment.TickCount
169 TickCountResolution = 0f;
170 for (int i = 0; i < 5; i++)
171 {
172 int start = Environment.TickCount;
173 int now = start;
174 while (now == start)
175 now = Environment.TickCount;
176 TickCountResolution += (float)(now - start) * 0.2f;
177 }
178 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms");
179 TickCountResolution = (float)Math.Ceiling(TickCountResolution);
180
181 #endregion Environment.TickCount Measurement
182
183 m_circuitManager = circuitManager;
184 int sceneThrottleBps = 0;
185
186 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
187 if (config != null)
188 {
189 m_asyncPacketHandling = config.GetBoolean("async_packet_handling", true);
190 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
191 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
192
193 PrimUpdatesPerCallback = config.GetInt("PrimUpdatesPerCallback", 100);
194 TextureSendLimit = config.GetInt("TextureSendLimit", 20);
195
196 m_defaultRTO = config.GetInt("DefaultRTO", 0);
197 m_maxRTO = config.GetInt("MaxRTO", 0);
198 m_disableFacelights = config.GetBoolean("DisableFacelights", false);
199 }
200 else
201 {
202 PrimUpdatesPerCallback = 100;
203 TextureSendLimit = 20;
204 }
205
206 #region BinaryStats
207 config = configSource.Configs["Statistics.Binary"];
208 m_shouldCollectStats = false;
209 if (config != null)
210 {
211 if (config.Contains("enabled") && config.GetBoolean("enabled"))
212 {
213 if (config.Contains("collect_packet_headers"))
214 m_shouldCollectStats = config.GetBoolean("collect_packet_headers");
215 if (config.Contains("packet_headers_period_seconds"))
216 {
217 binStatsMaxFilesize = TimeSpan.FromSeconds(config.GetInt("region_stats_period_seconds"));
218 }
219 if (config.Contains("stats_dir"))
220 {
221 binStatsDir = config.GetString("stats_dir");
222 }
223 }
224 else
225 {
226 m_shouldCollectStats = false;
227 }
228 }
229 #endregion BinaryStats
230
231 m_throttle = new TokenBucket(null, sceneThrottleBps);
232 ThrottleRates = new ThrottleRates(configSource);
233 }
234
235 public void Start()
236 {
237 if (m_scene == null)
238 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
239
240 m_log.Info("[LLUDPSERVER]: Starting the LLUDP server in " + (m_asyncPacketHandling ? "asynchronous" : "synchronous") + " mode");
241
242 base.Start(m_recvBufferSize, m_asyncPacketHandling);
243
244 // Start the packet processing threads
245 Watchdog.StartThread(IncomingPacketHandler, "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false);
246 Watchdog.StartThread(OutgoingPacketHandler, "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false);
247 m_elapsedMSSinceLastStatReport = Environment.TickCount;
248 }
249
250 public new void Stop()
251 {
252 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
253 base.Stop();
254 }
255
256 public void AddScene(IScene scene)
257 {
258 if (m_scene != null)
259 {
260 m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene");
261 return;
262 }
263
264 if (!(scene is Scene))
265 {
266 m_log.Error("[LLUDPSERVER]: AddScene() called with an unrecognized scene type " + scene.GetType());
267 return;
268 }
269
270 m_scene = (Scene)scene;
271 m_location = new Location(m_scene.RegionInfo.RegionHandle);
272 }
273
274 public bool HandlesRegion(Location x)
275 {
276 return x == m_location;
277 }
278
279 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
280 {
281 // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way
282 if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting)
283 allowSplitting = false;
284
285 if (allowSplitting && packet.HasVariableBlocks)
286 {
287 byte[][] datas = packet.ToBytesMultiple();
288 int packetCount = datas.Length;
289
290 if (packetCount < 1)
291 m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);
292
293 for (int i = 0; i < packetCount; i++)
294 {
295 byte[] data = datas[i];
296 m_scene.ForEachClient(
297 delegate(IClientAPI client)
298 {
299 if (client is LLClientView)
300 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
301 }
302 );
303 }
304 }
305 else
306 {
307 byte[] data = packet.ToBytes();
308 m_scene.ForEachClient(
309 delegate(IClientAPI client)
310 {
311 if (client is LLClientView)
312 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
313 }
314 );
315 }
316 }
317
318 /// <summary>
319 /// Start the process of sending a packet to the client.
320 /// </summary>
321 /// <param name="udpClient"></param>
322 /// <param name="packet"></param>
323 /// <param name="category"></param>
324 /// <param name="allowSplitting"></param>
325 public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method)
326 {
327 // CoarseLocationUpdate packets cannot be split in an automated way
328 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
329 allowSplitting = false;
330
331 if (allowSplitting && packet.HasVariableBlocks)
332 {
333 byte[][] datas = packet.ToBytesMultiple();
334 int packetCount = datas.Length;
335
336 if (packetCount < 1)
337 m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);
338
339 for (int i = 0; i < packetCount; i++)
340 {
341 byte[] data = datas[i];
342 SendPacketData(udpClient, data, packet.Type, category, method);
343 }
344 }
345 else
346 {
347 byte[] data = packet.ToBytes();
348 SendPacketData(udpClient, data, packet.Type, category, method);
349 }
350 }
351
352 /// <summary>
353 /// Start the process of sending a packet to the client.
354 /// </summary>
355 /// <param name="udpClient"></param>
356 /// <param name="data"></param>
357 /// <param name="type"></param>
358 /// <param name="category"></param>
359 public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method)
360 {
361 int dataLength = data.Length;
362 bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
363 bool doCopy = true;
364
365 // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum.
366 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
367 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
368 // to accomodate for both common scenarios and provide ample room for ACK appending in both
369 int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;
370
371 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
372
373 // Zerocode if needed
374 if (doZerocode)
375 {
376 try
377 {
378 dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data);
379 doCopy = false;
380 }
381 catch (IndexOutOfRangeException)
382 {
383 // The packet grew larger than the bufferSize while zerocoding.
384 // Remove the MSG_ZEROCODED flag and send the unencoded data
385 // instead
386 m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". DataLength=" + dataLength +
387 " and BufferLength=" + buffer.Data.Length + ". Removing MSG_ZEROCODED flag");
388 data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
389 }
390 }
391
392 // If the packet data wasn't already copied during zerocoding, copy it now
393 if (doCopy)
394 {
395 if (dataLength <= buffer.Data.Length)
396 {
397 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
398 }
399 else
400 {
401 bufferSize = dataLength;
402 buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
403
404 // m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
405 // type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet");
406 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
407 }
408 }
409
410 buffer.DataLength = dataLength;
411
412 #region Queue or Send
413
414 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
415 // If we were not provided a method for handling unacked, use the UDPServer default method
416 outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);
417
418 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
419 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object
420 // packet so that it isn't sent before a queued update packet.
421 bool requestQueue = type == PacketType.KillObject;
422 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue))
423 SendPacketFinal(outgoingPacket);
424
425 #endregion Queue or Send
426 }
427
428 public void SendAcks(LLUDPClient udpClient)
429 {
430 uint ack;
431
432 if (udpClient.PendingAcks.Dequeue(out ack))
433 {
434 List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>();
435 PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock();
436 block.ID = ack;
437 blocks.Add(block);
438
439 while (udpClient.PendingAcks.Dequeue(out ack))
440 {
441 block = new PacketAckPacket.PacketsBlock();
442 block.ID = ack;
443 blocks.Add(block);
444 }
445
446 PacketAckPacket packet = new PacketAckPacket();
447 packet.Header.Reliable = false;
448 packet.Packets = blocks.ToArray();
449
450 SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true, null);
451 }
452 }
453
454 public void SendPing(LLUDPClient udpClient)
455 {
456 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck);
457 pc.Header.Reliable = false;
458
459 pc.PingID.PingID = (byte)udpClient.CurrentPingSequence++;
460 // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit
461 pc.PingID.OldestUnacked = 0;
462
463 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null);
464 }
465
466 public void CompletePing(LLUDPClient udpClient, byte pingID)
467 {
468 CompletePingCheckPacket completePing = new CompletePingCheckPacket();
469 completePing.PingID.PingID = pingID;
470 SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null);
471 }
472
473 public void HandleUnacked(LLUDPClient udpClient)
474 {
475 if (!udpClient.IsConnected)
476 return;
477
478 // Disconnect an agent if no packets are received for some time
479 //FIXME: Make 60 an .ini setting
480 if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60)
481 {
482 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
483
484 RemoveClient(udpClient);
485 return;
486 }
487
488 // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO
489 List<OutgoingPacket> expiredPackets = udpClient.NeedAcks.GetExpiredPackets(udpClient.RTO);
490
491 if (expiredPackets != null)
492 {
493 //m_log.Debug("[LLUDPSERVER]: Handling " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO);
494 // Exponential backoff of the retransmission timeout
495 udpClient.BackoffRTO();
496 for (int i = 0; i < expiredPackets.Count; ++i)
497 expiredPackets[i].UnackedMethod(expiredPackets[i]);
498 }
499 }
500
501 public void ResendUnacked(OutgoingPacket outgoingPacket)
502 {
503 //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
504 // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount);
505
506 // Set the resent flag
507 outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
508 outgoingPacket.Category = ThrottleOutPacketType.Resend;
509
510 // Bump up the resend count on this packet
511 Interlocked.Increment(ref outgoingPacket.ResendCount);
512
513 // Requeue or resend the packet
514 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false))
515 SendPacketFinal(outgoingPacket);
516 }
517
518 public void Flush(LLUDPClient udpClient)
519 {
520 // FIXME: Implement?
521 }
522
523 /// <summary>
524 /// Actually send a packet to a client.
525 /// </summary>
526 /// <param name="outgoingPacket"></param>
527 internal void SendPacketFinal(OutgoingPacket outgoingPacket)
528 {
529 UDPPacketBuffer buffer = outgoingPacket.Buffer;
530 byte flags = buffer.Data[0];
531 bool isResend = (flags & Helpers.MSG_RESENT) != 0;
532 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0;
533 bool isZerocoded = (flags & Helpers.MSG_ZEROCODED) != 0;
534 LLUDPClient udpClient = outgoingPacket.Client;
535
536 if (!udpClient.IsConnected)
537 return;
538
539 #region ACK Appending
540
541 int dataLength = buffer.DataLength;
542
543 // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here
544 if (!isZerocoded)
545 {
546 // Keep appending ACKs until there is no room left in the buffer or there are
547 // no more ACKs to append
548 uint ackCount = 0;
549 uint ack;
550 while (dataLength + 5 < buffer.Data.Length && udpClient.PendingAcks.Dequeue(out ack))
551 {
552 Utils.UIntToBytesBig(ack, buffer.Data, dataLength);
553 dataLength += 4;
554 ++ackCount;
555 }
556
557 if (ackCount > 0)
558 {
559 // Set the last byte of the packet equal to the number of appended ACKs
560 buffer.Data[dataLength++] = (byte)ackCount;
561 // Set the appended ACKs flag on this packet
562 buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS);
563 }
564 }
565
566 buffer.DataLength = dataLength;
567
568 #endregion ACK Appending
569
570 #region Sequence Number Assignment
571
572 if (!isResend)
573 {
574 // Not a resend, assign a new sequence number
575 uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence);
576 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
577 outgoingPacket.SequenceNumber = sequenceNumber;
578
579 if (isReliable)
580 {
581 // Add this packet to the list of ACK responses we are waiting on from the server
582 udpClient.NeedAcks.Add(outgoingPacket);
583 }
584 }
585 else
586 {
587 Interlocked.Increment(ref udpClient.PacketsResent);
588 }
589
590 #endregion Sequence Number Assignment
591
592 // Stats tracking
593 Interlocked.Increment(ref udpClient.PacketsSent);
594
595 // Put the UDP payload on the wire
596 AsyncBeginSend(buffer);
597
598 // Keep track of when this packet was sent out (right now)
599 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
600 }
601
602 protected override void PacketReceived(UDPPacketBuffer buffer)
603 {
604 // Debugging/Profiling
605 //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; }
606 //catch (Exception) { }
607
608 LLUDPClient udpClient = null;
609 Packet packet = null;
610 int packetEnd = buffer.DataLength - 1;
611 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint;
612
613 #region Decoding
614
615 try
616 {
617 packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
618 // Only allocate a buffer for zerodecoding if the packet is zerocoded
619 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
620 }
621 catch (MalformedDataException)
622 {
623 }
624
625 // Fail-safe check
626 if (packet == null)
627 {
628 m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}:",
629 buffer.DataLength, buffer.RemoteEndPoint);
630 m_log.Error(Utils.BytesToHexString(buffer.Data, buffer.DataLength, null));
631 return;
632 }
633
634 #endregion Decoding
635
636 #region Packet to Client Mapping
637
638 // UseCircuitCode handling
639 if (packet.Type == PacketType.UseCircuitCode)
640 {
641 object[] array = new object[] { buffer, packet };
642
643 Util.FireAndForget(HandleUseCircuitCode, array);
644
645 return;
646 }
647
648 // Determine which agent this packet came from
649 IClientAPI client;
650 if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView))
651 {
652 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
653 return;
654 }
655
656 udpClient = ((LLClientView)client).UDPClient;
657
658 if (!udpClient.IsConnected)
659 return;
660
661 #endregion Packet to Client Mapping
662
663 // Stats tracking
664 Interlocked.Increment(ref udpClient.PacketsReceived);
665
666 int now = Environment.TickCount & Int32.MaxValue;
667 udpClient.TickLastPacketReceived = now;
668
669 #region ACK Receiving
670
671 // Handle appended ACKs
672 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
673 {
674 for (int i = 0; i < packet.Header.AckList.Length; i++)
675 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
676 }
677
678 // Handle PacketAck packets
679 if (packet.Type == PacketType.PacketAck)
680 {
681 PacketAckPacket ackPacket = (PacketAckPacket)packet;
682
683 for (int i = 0; i < ackPacket.Packets.Length; i++)
684 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
685
686 // We don't need to do anything else with PacketAck packets
687 return;
688 }
689
690 #endregion ACK Receiving
691
692 #region ACK Sending
693
694 if (packet.Header.Reliable)
695 {
696 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
697
698 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
699 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove
700 // 2*MTU bytes from the value and send ACKs, and finally add the local value back to
701 // client.BytesSinceLastACK. Lockless thread safety
702 int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0);
703 bytesSinceLastACK += buffer.DataLength;
704 if (bytesSinceLastACK > LLUDPServer.MTU * 2)
705 {
706 bytesSinceLastACK -= LLUDPServer.MTU * 2;
707 SendAcks(udpClient);
708 }
709 Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
710 }
711
712 #endregion ACK Sending
713
714 #region Incoming Packet Accounting
715
716 // Check the archive of received reliable packet IDs to see whether we already received this packet
717 if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence))
718 {
719 if (packet.Header.Resent)
720 m_log.DebugFormat(
721 "[LLUDPSERVER]: Received a resend of already processed packet #{0}, type {1} from {2}",
722 packet.Header.Sequence, packet.Type, client.Name);
723 else
724 m_log.WarnFormat(
725 "[LLUDPSERVER]: Received a duplicate (not marked as resend) of packet #{0}, type {1} from {2}",
726 packet.Header.Sequence, packet.Type, client.Name);
727
728 // Avoid firing a callback twice for the same packet
729 return;
730 }
731
732 #endregion Incoming Packet Accounting
733
734 #region BinaryStats
735 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
736 #endregion BinaryStats
737
738 #region Ping Check Handling
739
740 if (packet.Type == PacketType.StartPingCheck)
741 {
742 // We don't need to do anything else with ping checks
743 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
744 CompletePing(udpClient, startPing.PingID.PingID);
745
746 if ((Environment.TickCount - m_elapsedMSSinceLastStatReport) >= 3000)
747 {
748 udpClient.SendPacketStats();
749 m_elapsedMSSinceLastStatReport = Environment.TickCount;
750 }
751 return;
752 }
753 else if (packet.Type == PacketType.CompletePingCheck)
754 {
755 // We don't currently track client ping times
756 return;
757 }
758
759 #endregion Ping Check Handling
760
761 // Inbox insertion
762 packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
763 }
764
765 #region BinaryStats
766
767 public class PacketLogger
768 {
769 public DateTime StartTime;
770 public string Path = null;
771 public System.IO.BinaryWriter Log = null;
772 }
773
774 public static PacketLogger PacketLog;
775
776 protected static bool m_shouldCollectStats = false;
777 // Number of seconds to log for
778 static TimeSpan binStatsMaxFilesize = TimeSpan.FromSeconds(300);
779 static object binStatsLogLock = new object();
780 static string binStatsDir = "";
781
782 public static void LogPacketHeader(bool incoming, uint circuit, byte flags, PacketType packetType, ushort size)
783 {
784 if (!m_shouldCollectStats) return;
785
786 // Binary logging format is TTTTTTTTCCCCFPPPSS, T=Time, C=Circuit, F=Flags, P=PacketType, S=size
787
788 // Put the incoming bit into the least significant bit of the flags byte
789 if (incoming)
790 flags |= 0x01;
791 else
792 flags &= 0xFE;
793
794 // Put the flags byte into the most significant bits of the type integer
795 uint type = (uint)packetType;
796 type |= (uint)flags << 24;
797
798 // m_log.Debug("1 LogPacketHeader(): Outside lock");
799 lock (binStatsLogLock)
800 {
801 DateTime now = DateTime.Now;
802
803 // m_log.Debug("2 LogPacketHeader(): Inside lock. now is " + now.Ticks);
804 try
805 {
806 if (PacketLog == null || (now > PacketLog.StartTime + binStatsMaxFilesize))
807 {
808 if (PacketLog != null && PacketLog.Log != null)
809 {
810 PacketLog.Log.Close();
811 }
812
813 // First log file or time has expired, start writing to a new log file
814 PacketLog = new PacketLogger();
815 PacketLog.StartTime = now;
816 PacketLog.Path = (binStatsDir.Length > 0 ? binStatsDir + System.IO.Path.DirectorySeparatorChar.ToString() : "")
817 + String.Format("packets-{0}.log", now.ToString("yyyyMMddHHmmss"));
818 PacketLog.Log = new BinaryWriter(File.Open(PacketLog.Path, FileMode.Append, FileAccess.Write));
819 }
820
821 // Serialize the data
822 byte[] output = new byte[18];
823 Buffer.BlockCopy(BitConverter.GetBytes(now.Ticks), 0, output, 0, 8);
824 Buffer.BlockCopy(BitConverter.GetBytes(circuit), 0, output, 8, 4);
825 Buffer.BlockCopy(BitConverter.GetBytes(type), 0, output, 12, 4);
826 Buffer.BlockCopy(BitConverter.GetBytes(size), 0, output, 16, 2);
827
828 // Write the serialized data to disk
829 if (PacketLog != null && PacketLog.Log != null)
830 PacketLog.Log.Write(output);
831 }
832 catch (Exception ex)
833 {
834 m_log.Error("Packet statistics gathering failed: " + ex.Message, ex);
835 if (PacketLog.Log != null)
836 {
837 PacketLog.Log.Close();
838 }
839 PacketLog = null;
840 }
841 }
842 }
843
844 #endregion BinaryStats
845
846 private void HandleUseCircuitCode(object o)
847 {
848// DateTime startTime = DateTime.Now;
849 object[] array = (object[])o;
850 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0];
851 UseCircuitCodePacket packet = (UseCircuitCodePacket)array[1];
852
853 m_log.DebugFormat("[LLUDPSERVER]: Handling UseCircuitCode request from {0}", buffer.RemoteEndPoint);
854
855 IPEndPoint remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
856
857 // Begin the process of adding the client to the simulator
858 AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint);
859
860 // Send ack
861 SendAckImmediate(remoteEndPoint, packet.Header.Sequence);
862
863 // m_log.DebugFormat(
864// "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms",
865// buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds);
866 }
867
868 private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber)
869 {
870 PacketAckPacket ack = new PacketAckPacket();
871 ack.Header.Reliable = false;
872 ack.Packets = new PacketAckPacket.PacketsBlock[1];
873 ack.Packets[0] = new PacketAckPacket.PacketsBlock();
874 ack.Packets[0].ID = sequenceNumber;
875
876 byte[] packetData = ack.ToBytes();
877 int length = packetData.Length;
878
879 UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length);
880 buffer.DataLength = length;
881
882 Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length);
883
884 AsyncBeginSend(buffer);
885 }
886
887 private bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo)
888 {
889 UUID agentID = useCircuitCode.CircuitCode.ID;
890 UUID sessionID = useCircuitCode.CircuitCode.SessionID;
891 uint circuitCode = useCircuitCode.CircuitCode.Code;
892
893 sessionInfo = m_circuitManager.AuthenticateSession(sessionID, agentID, circuitCode);
894 return sessionInfo.Authorised;
895 }
896
897 private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint)
898 {
899 UUID agentID = useCircuitCode.CircuitCode.ID;
900 UUID sessionID = useCircuitCode.CircuitCode.SessionID;
901 uint circuitCode = useCircuitCode.CircuitCode.Code;
902
903 if (m_scene.RegionStatus != RegionStatus.SlaveScene)
904 {
905 AuthenticateResponse sessionInfo;
906 if (IsClientAuthorized(useCircuitCode, out sessionInfo))
907 {
908 AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo);
909 }
910 else
911 {
912 // Don't create circuits for unauthorized clients
913 m_log.WarnFormat(
914 "[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}",
915 useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint);
916 }
917 }
918 else
919 {
920 // Slave regions don't accept new clients
921 m_log.Debug("[LLUDPSERVER]: Slave region " + m_scene.RegionInfo.RegionName + " ignoring UseCircuitCode packet");
922 }
923 }
924
925 protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
926 {
927 // In priciple there shouldn't be more than one thread here, ever.
928 // But in case that happens, we need to synchronize this piece of code
929 // because it's too important
930 lock (this)
931 {
932 IClientAPI existingClient;
933
934 if (!m_scene.TryGetClient(agentID, out existingClient))
935 {
936 // Create the LLUDPClient
937 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
938 // Create the LLClientView
939 LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
940 client.OnLogout += LogoutHandler;
941
942 client.DisableFacelights = m_disableFacelights;
943
944 // Start the IClientAPI
945 client.Start();
946
947 }
948 else
949 {
950 m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}",
951 existingClient.AgentId, remoteEndPoint, circuitCode);
952 }
953 }
954 }
955
956 private void RemoveClient(LLUDPClient udpClient)
957 {
958 // Remove this client from the scene
959 IClientAPI client;
960 if (m_scene.TryGetClient(udpClient.AgentID, out client))
961 {
962 client.IsLoggingOut = true;
963 client.Close();
964 }
965 }
966
967 private void IncomingPacketHandler()
968 {
969 // Set this culture for the thread that incoming packets are received
970 // on to en-US to avoid number parsing issues
971 Culture.SetCurrentCulture();
972
973 while (base.IsRunning)
974 {
975 try
976 {
977 IncomingPacket incomingPacket = null;
978
979 // HACK: This is a test to try and rate limit packet handling on Mono.
980 // If it works, a more elegant solution can be devised
981 if (Util.FireAndForgetCount() < 2)
982 {
983 //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping");
984 Thread.Sleep(30);
985 }
986
987 if (packetInbox.Dequeue(100, ref incomingPacket))
988 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket);
989 }
990 catch (Exception ex)
991 {
992 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
993 }
994
995 Watchdog.UpdateThread();
996 }
997
998 if (packetInbox.Count > 0)
999 m_log.Warn("[LLUDPSERVER]: IncomingPacketHandler is shutting down, dropping " + packetInbox.Count + " packets");
1000 packetInbox.Clear();
1001
1002 Watchdog.RemoveThread();
1003 }
1004
1005 private void OutgoingPacketHandler()
1006 {
1007 // Set this culture for the thread that outgoing packets are sent
1008 // on to en-US to avoid number parsing issues
1009 Culture.SetCurrentCulture();
1010
1011 // Typecast the function to an Action<IClientAPI> once here to avoid allocating a new
1012 // Action generic every round
1013 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
1014
1015 while (base.IsRunning)
1016 {
1017 try
1018 {
1019 m_packetSent = false;
1020
1021 #region Update Timers
1022
1023 m_resendUnacked = false;
1024 m_sendAcks = false;
1025 m_sendPing = false;
1026
1027 // Update elapsed time
1028 int thisTick = Environment.TickCount & Int32.MaxValue;
1029 if (m_tickLastOutgoingPacketHandler > thisTick)
1030 m_elapsedMSOutgoingPacketHandler += ((Int32.MaxValue - m_tickLastOutgoingPacketHandler) + thisTick);
1031 else
1032 m_elapsedMSOutgoingPacketHandler += (thisTick - m_tickLastOutgoingPacketHandler);
1033
1034 m_tickLastOutgoingPacketHandler = thisTick;
1035
1036 // Check for pending outgoing resends every 100ms
1037 if (m_elapsedMSOutgoingPacketHandler >= 100)
1038 {
1039 m_resendUnacked = true;
1040 m_elapsedMSOutgoingPacketHandler = 0;
1041 m_elapsed100MSOutgoingPacketHandler += 1;
1042 }
1043
1044 // Check for pending outgoing ACKs every 500ms
1045 if (m_elapsed100MSOutgoingPacketHandler >= 5)
1046 {
1047 m_sendAcks = true;
1048 m_elapsed100MSOutgoingPacketHandler = 0;
1049 m_elapsed500MSOutgoingPacketHandler += 1;
1050 }
1051
1052 // Send pings to clients every 5000ms
1053 if (m_elapsed500MSOutgoingPacketHandler >= 10)
1054 {
1055 m_sendPing = true;
1056 m_elapsed500MSOutgoingPacketHandler = 0;
1057 }
1058
1059 #endregion Update Timers
1060
1061 // Use this for emergency monitoring -- bug hunting
1062 //if (m_scene.EmergencyMonitoring)
1063 // clientPacketHandler = MonitoredClientOutgoingPacketHandler;
1064 //else
1065 // clientPacketHandler = ClientOutgoingPacketHandler;
1066
1067 // Handle outgoing packets, resends, acknowledgements, and pings for each
1068 // client. m_packetSent will be set to true if a packet is sent
1069 m_scene.ForEachClient(clientPacketHandler);
1070
1071 // If nothing was sent, sleep for the minimum amount of time before a
1072 // token bucket could get more tokens
1073 if (!m_packetSent)
1074 Thread.Sleep((int)TickCountResolution);
1075
1076 Watchdog.UpdateThread();
1077 }
1078 catch (Exception ex)
1079 {
1080 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex);
1081 }
1082
1083 }
1084
1085 Watchdog.RemoveThread();
1086 }
1087
1088 private void ClientOutgoingPacketHandler(IClientAPI client)
1089 {
1090 try
1091 {
1092 if (client is LLClientView)
1093 {
1094 LLUDPClient udpClient = ((LLClientView)client).UDPClient;
1095
1096 if (udpClient.IsConnected)
1097 {
1098 if (m_resendUnacked)
1099 HandleUnacked(udpClient);
1100
1101 if (m_sendAcks)
1102 SendAcks(udpClient);
1103
1104 if (m_sendPing)
1105 SendPing(udpClient);
1106
1107 // Dequeue any outgoing packets that are within the throttle limits
1108 if (udpClient.DequeueOutgoing())
1109 m_packetSent = true;
1110 }
1111 }
1112 }
1113 catch (Exception ex)
1114 {
1115 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name +
1116 " threw an exception: " + ex.Message, ex);
1117 }
1118 }
1119
1120 #region Emergency Monitoring
1121 // Alternative packet handler fuull of instrumentation
1122 // Handy for hunting bugs
1123 private Stopwatch watch1 = new Stopwatch();
1124 private Stopwatch watch2 = new Stopwatch();
1125
1126 private float avgProcessingTicks = 0;
1127 private float avgResendUnackedTicks = 0;
1128 private float avgSendAcksTicks = 0;
1129 private float avgSendPingTicks = 0;
1130 private float avgDequeueTicks = 0;
1131 private long nticks = 0;
1132 private long nticksUnack = 0;
1133 private long nticksAck = 0;
1134 private long nticksPing = 0;
1135 private int npacksSent = 0;
1136 private int npackNotSent = 0;
1137
1138 private void MonitoredClientOutgoingPacketHandler(IClientAPI client)
1139 {
1140 nticks++;
1141 watch1.Start();
1142 try
1143 {
1144 if (client is LLClientView)
1145 {
1146 LLUDPClient udpClient = ((LLClientView)client).UDPClient;
1147
1148 if (udpClient.IsConnected)
1149 {
1150 if (m_resendUnacked)
1151 {
1152 nticksUnack++;
1153 watch2.Start();
1154
1155 HandleUnacked(udpClient);
1156
1157 watch2.Stop();
1158 avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
1159 watch2.Reset();
1160 }
1161
1162 if (m_sendAcks)
1163 {
1164 nticksAck++;
1165 watch2.Start();
1166
1167 SendAcks(udpClient);
1168
1169 watch2.Stop();
1170 avgSendAcksTicks = (nticksAck - 1) / (float)nticksAck * avgSendAcksTicks + (watch2.ElapsedTicks / (float)nticksAck);
1171 watch2.Reset();
1172 }
1173
1174 if (m_sendPing)
1175 {
1176 nticksPing++;
1177 watch2.Start();
1178
1179 SendPing(udpClient);
1180
1181 watch2.Stop();
1182 avgSendPingTicks = (nticksPing - 1) / (float)nticksPing * avgSendPingTicks + (watch2.ElapsedTicks / (float)nticksPing);
1183 watch2.Reset();
1184 }
1185
1186 watch2.Start();
1187 // Dequeue any outgoing packets that are within the throttle limits
1188 if (udpClient.DequeueOutgoing())
1189 {
1190 m_packetSent = true;
1191 npacksSent++;
1192 }
1193 else
1194 npackNotSent++;
1195
1196 watch2.Stop();
1197 avgDequeueTicks = (nticks - 1) / (float)nticks * avgDequeueTicks + (watch2.ElapsedTicks / (float)nticks);
1198 watch2.Reset();
1199
1200 }
1201 else
1202 m_log.WarnFormat("[LLUDPSERVER]: Client is not connected");
1203 }
1204 }
1205 catch (Exception ex)
1206 {
1207 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name +
1208 " threw an exception: " + ex.Message, ex);
1209 }
1210 watch1.Stop();
1211 avgProcessingTicks = (nticks - 1) / (float)nticks * avgProcessingTicks + (watch1.ElapsedTicks / (float)nticks);
1212 watch1.Reset();
1213
1214 // reuse this -- it's every ~100ms
1215 if (m_scene.EmergencyMonitoring && nticks % 100 == 0)
1216 {
1217 m_log.InfoFormat("[LLUDPSERVER]: avg processing ticks: {0} avg unacked: {1} avg acks: {2} avg ping: {3} avg dequeue: {4} (TickCountRes: {5} sent: {6} notsent: {7})",
1218 avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent);
1219 npackNotSent = npacksSent = 0;
1220 }
1221
1222 }
1223
1224 #endregion
1225
1226 private void ProcessInPacket(object state)
1227 {
1228 IncomingPacket incomingPacket = (IncomingPacket)state;
1229 Packet packet = incomingPacket.Packet;
1230 LLUDPClient udpClient = incomingPacket.Client;
1231 IClientAPI client;
1232
1233 // Sanity check
1234 if (packet == null || udpClient == null)
1235 {
1236 m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", UDPClient=\"{1}\"",
1237 packet, udpClient);
1238 }
1239
1240 // Make sure this client is still alive
1241 if (m_scene.TryGetClient(udpClient.AgentID, out client))
1242 {
1243 try
1244 {
1245 // Process this packet
1246 client.ProcessInPacket(packet);
1247 }
1248 catch (ThreadAbortException)
1249 {
1250 // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down
1251 m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server");
1252 Stop();
1253 }
1254 catch (Exception e)
1255 {
1256 // Don't let a failure in an individual client thread crash the whole sim.
1257 m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type);
1258 m_log.Error(e.Message, e);
1259 }
1260 }
1261 else
1262 {
1263 m_log.DebugFormat("[LLUDPSERVER]: Dropping incoming {0} packet for dead client {1}", packet.Type, udpClient.AgentID);
1264 }
1265 }
1266
1267 protected void LogoutHandler(IClientAPI client)
1268 {
1269 client.SendLogoutPacket();
1270 if (client.IsActive)
1271 RemoveClient(((LLClientView)client).UDPClient);
1272 }
1273 }
1274}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
new file mode 100644
index 0000000..6eebd9d
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -0,0 +1,284 @@
1/*
2 * Copyright (c) 2006, Clutch, Inc.
3 * Original Author: Jeff Cesnik
4 * All rights reserved.
5 *
6 * - Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * - Redistributions of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer.
11 * - 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 * this software without specific prior written permission.
14 *
15 * 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 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * 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 * 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 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Net;
30using System.Net.Sockets;
31using System.Threading;
32using log4net;
33
34namespace OpenMetaverse
35{
36 /// <summary>
37 /// Base UDP server
38 /// </summary>
39 public abstract class OpenSimUDPBase
40 {
41 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
42
43 /// <summary>
44 /// This method is called when an incoming packet is received
45 /// </summary>
46 /// <param name="buffer">Incoming packet buffer</param>
47 protected abstract void PacketReceived(UDPPacketBuffer buffer);
48
49 /// <summary>UDP port to bind to in server mode</summary>
50 protected int m_udpPort;
51
52 /// <summary>Local IP address to bind to in server mode</summary>
53 protected IPAddress m_localBindAddress;
54
55 /// <summary>UDP socket, used in either client or server mode</summary>
56 private Socket m_udpSocket;
57
58 /// <summary>Flag to process packets asynchronously or synchronously</summary>
59 private bool m_asyncPacketHandling;
60
61 /// <summary>The all important shutdown flag</summary>
62 private volatile bool m_shutdownFlag = true;
63
64 /// <summary>Returns true if the server is currently listening, otherwise false</summary>
65 public bool IsRunning { get { return !m_shutdownFlag; } }
66
67 /// <summary>
68 /// Default constructor
69 /// </summary>
70 /// <param name="bindAddress">Local IP address to bind the server to</param>
71 /// <param name="port">Port to listening for incoming UDP packets on</param>
72 public OpenSimUDPBase(IPAddress bindAddress, int port)
73 {
74 m_localBindAddress = bindAddress;
75 m_udpPort = port;
76 }
77
78 /// <summary>
79 /// Start the UDP server
80 /// </summary>
81 /// <param name="recvBufferSize">The size of the receive buffer for
82 /// the UDP socket. This value is passed up to the operating system
83 /// and used in the system networking stack. Use zero to leave this
84 /// value as the default</param>
85 /// <param name="asyncPacketHandling">Set this to true to start
86 /// receiving more packets while current packet handler callbacks are
87 /// still running. Setting this to false will complete each packet
88 /// callback before the next packet is processed</param>
89 /// <remarks>This method will attempt to set the SIO_UDP_CONNRESET flag
90 /// on the socket to get newer versions of Windows to behave in a sane
91 /// manner (not throwing an exception when the remote side resets the
92 /// connection). This call is ignored on Mono where the flag is not
93 /// necessary</remarks>
94 public void Start(int recvBufferSize, bool asyncPacketHandling)
95 {
96 m_asyncPacketHandling = asyncPacketHandling;
97
98 if (m_shutdownFlag)
99 {
100 const int SIO_UDP_CONNRESET = -1744830452;
101
102 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
103
104 m_log.DebugFormat(
105 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
106 ipep.Address, ipep.Port);
107
108 m_udpSocket = new Socket(
109 AddressFamily.InterNetwork,
110 SocketType.Dgram,
111 ProtocolType.Udp);
112
113 try
114 {
115 // This udp socket flag is not supported under mono,
116 // so we'll catch the exception and continue
117 m_udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null);
118 m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag set");
119 }
120 catch (SocketException)
121 {
122 m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag not supported on this platform, ignoring");
123 }
124
125 if (recvBufferSize != 0)
126 m_udpSocket.ReceiveBufferSize = recvBufferSize;
127
128 m_udpSocket.Bind(ipep);
129
130 // we're not shutting down, we're starting up
131 m_shutdownFlag = false;
132
133 // kick off an async receive. The Start() method will return, the
134 // actual receives will occur asynchronously and will be caught in
135 // AsyncEndRecieve().
136 AsyncBeginReceive();
137 }
138 }
139
140 /// <summary>
141 /// Stops the UDP server
142 /// </summary>
143 public void Stop()
144 {
145 if (!m_shutdownFlag)
146 {
147 // wait indefinitely for a writer lock. Once this is called, the .NET runtime
148 // will deny any more reader locks, in effect blocking all other send/receive
149 // threads. Once we have the lock, we set shutdownFlag to inform the other
150 // threads that the socket is closed.
151 m_shutdownFlag = true;
152 m_udpSocket.Close();
153 }
154 }
155
156 private void AsyncBeginReceive()
157 {
158 // allocate a packet buffer
159 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
160 UDPPacketBuffer buf = new UDPPacketBuffer();
161
162 if (!m_shutdownFlag)
163 {
164 try
165 {
166 // kick off an async read
167 m_udpSocket.BeginReceiveFrom(
168 //wrappedBuffer.Instance.Data,
169 buf.Data,
170 0,
171 UDPPacketBuffer.BUFFER_SIZE,
172 SocketFlags.None,
173 ref buf.RemoteEndPoint,
174 AsyncEndReceive,
175 //wrappedBuffer);
176 buf);
177 }
178 catch (SocketException e)
179 {
180 if (e.SocketErrorCode == SocketError.ConnectionReset)
181 {
182 m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort);
183 bool salvaged = false;
184 while (!salvaged)
185 {
186 try
187 {
188 m_udpSocket.BeginReceiveFrom(
189 //wrappedBuffer.Instance.Data,
190 buf.Data,
191 0,
192 UDPPacketBuffer.BUFFER_SIZE,
193 SocketFlags.None,
194 ref buf.RemoteEndPoint,
195 AsyncEndReceive,
196 //wrappedBuffer);
197 buf);
198 salvaged = true;
199 }
200 catch (SocketException) { }
201 catch (ObjectDisposedException) { return; }
202 }
203
204 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
205 }
206 }
207 catch (ObjectDisposedException) { }
208 }
209 }
210
211 private void AsyncEndReceive(IAsyncResult iar)
212 {
213 // Asynchronous receive operations will complete here through the call
214 // to AsyncBeginReceive
215 if (!m_shutdownFlag)
216 {
217 // Asynchronous mode will start another receive before the
218 // callback for this packet is even fired. Very parallel :-)
219 if (m_asyncPacketHandling)
220 AsyncBeginReceive();
221
222 // get the buffer that was created in AsyncBeginReceive
223 // this is the received data
224 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
225 //UDPPacketBuffer buffer = wrappedBuffer.Instance;
226 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
227
228 try
229 {
230 // get the length of data actually read from the socket, store it with the
231 // buffer
232 buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);
233
234 // call the abstract method PacketReceived(), passing the buffer that
235 // has just been filled from the socket read.
236 PacketReceived(buffer);
237 }
238 catch (SocketException) { }
239 catch (ObjectDisposedException) { }
240 finally
241 {
242 //wrappedBuffer.Dispose();
243
244 // Synchronous mode waits until the packet callback completes
245 // before starting the receive to fetch another packet
246 if (!m_asyncPacketHandling)
247 AsyncBeginReceive();
248 }
249
250 }
251 }
252
253 public void AsyncBeginSend(UDPPacketBuffer buf)
254 {
255 if (!m_shutdownFlag)
256 {
257 try
258 {
259 m_udpSocket.BeginSendTo(
260 buf.Data,
261 0,
262 buf.DataLength,
263 SocketFlags.None,
264 buf.RemoteEndPoint,
265 AsyncEndSend,
266 buf);
267 }
268 catch (SocketException) { }
269 catch (ObjectDisposedException) { }
270 }
271 }
272
273 void AsyncEndSend(IAsyncResult result)
274 {
275 try
276 {
277// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState;
278 m_udpSocket.EndSendTo(result);
279 }
280 catch (SocketException) { }
281 catch (ObjectDisposedException) { }
282 }
283 }
284}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OutgoingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/OutgoingPacket.cs
new file mode 100644
index 0000000..76c6c14
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OutgoingPacket.cs
@@ -0,0 +1,75 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenSim.Framework;
30using OpenMetaverse;
31
32namespace OpenSim.Region.ClientStack.LindenUDP
33{
34
35 public delegate void UnackedPacketMethod(OutgoingPacket oPacket);
36 /// <summary>
37 /// Holds a reference to the <seealso cref="LLUDPClient"/> this packet is
38 /// destined for, along with the serialized packet data, sequence number
39 /// (if this is a resend), number of times this packet has been resent,
40 /// the time of the last resend, and the throttling category for this
41 /// packet
42 /// </summary>
43 public sealed class OutgoingPacket
44 {
45 /// <summary>Client this packet is destined for</summary>
46 public LLUDPClient Client;
47 /// <summary>Packet data to send</summary>
48 public UDPPacketBuffer Buffer;
49 /// <summary>Sequence number of the wrapped packet</summary>
50 public uint SequenceNumber;
51 /// <summary>Number of times this packet has been resent</summary>
52 public int ResendCount;
53 /// <summary>Environment.TickCount when this packet was last sent over the wire</summary>
54 public int TickCount;
55 /// <summary>Category this packet belongs to</summary>
56 public ThrottleOutPacketType Category;
57 /// <summary>The delegate to be called if this packet is determined to be unacknowledged</summary>
58 public UnackedPacketMethod UnackedMethod;
59
60 /// <summary>
61 /// Default constructor
62 /// </summary>
63 /// <param name="client">Reference to the client this packet is destined for</param>
64 /// <param name="buffer">Serialized packet data. If the flags or sequence number
65 /// need to be updated, they will be injected directly into this binary buffer</param>
66 /// <param name="category">Throttling category for this packet</param>
67 public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method)
68 {
69 Client = client;
70 Buffer = buffer;
71 Category = category;
72 UnackedMethod = method;
73 }
74 }
75}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
new file mode 100644
index 0000000..daab84f
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
@@ -0,0 +1,299 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Net;
29using log4net.Config;
30using Nini.Config;
31using NUnit.Framework;
32using NUnit.Framework.SyntaxHelpers;
33using OpenMetaverse;
34using OpenMetaverse.Packets;
35using OpenSim.Framework;
36using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock;
38
39namespace OpenSim.Region.ClientStack.LindenUDP.Tests
40{
41 /// <summary>
42 /// This will contain basic tests for the LindenUDP client stack
43 /// </summary>
44 [TestFixture]
45 public class BasicCircuitTests
46 {
47 [SetUp]
48 public void Init()
49 {
50 try
51 {
52 XmlConfigurator.Configure();
53 }
54 catch
55 {
56 // I don't care, just leave log4net off
57 }
58 }
59
60 /// <summary>
61 /// Add a client for testing
62 /// </summary>
63 /// <param name="scene"></param>
64 /// <param name="testLLUDPServer"></param>
65 /// <param name="testPacketServer"></param>
66 /// <param name="acm">Agent circuit manager used in setting up the stack</param>
67 protected void SetupStack(
68 IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
69 out AgentCircuitManager acm)
70 {
71 IConfigSource configSource = new IniConfigSource();
72 ClientStackUserSettings userSettings = new ClientStackUserSettings();
73 testLLUDPServer = new TestLLUDPServer();
74 acm = new AgentCircuitManager();
75
76 uint port = 666;
77 testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
78 testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
79 testLLUDPServer.LocalScene = scene;
80 }
81
82 /// <summary>
83 /// Set up a client for tests which aren't concerned with this process itself and where only one client is being
84 /// tested
85 /// </summary>
86 /// <param name="circuitCode"></param>
87 /// <param name="epSender"></param>
88 /// <param name="testLLUDPServer"></param>
89 /// <param name="acm"></param>
90 protected void AddClient(
91 uint circuitCode, EndPoint epSender, TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
92 {
93 UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
94 UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
95
96 AddClient(circuitCode, epSender, myAgentUuid, mySessionUuid, testLLUDPServer, acm);
97 }
98
99 /// <summary>
100 /// Set up a client for tests which aren't concerned with this process itself
101 /// </summary>
102 /// <param name="circuitCode"></param>
103 /// <param name="epSender"></param>
104 /// <param name="agentId"></param>
105 /// <param name="sessionId"></param>
106 /// <param name="testLLUDPServer"></param>
107 /// <param name="acm"></param>
108 protected void AddClient(
109 uint circuitCode, EndPoint epSender, UUID agentId, UUID sessionId,
110 TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
111 {
112 AgentCircuitData acd = new AgentCircuitData();
113 acd.AgentID = agentId;
114 acd.SessionID = sessionId;
115
116 UseCircuitCodePacket uccp = new UseCircuitCodePacket();
117
118 UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
119 = new UseCircuitCodePacket.CircuitCodeBlock();
120 uccpCcBlock.Code = circuitCode;
121 uccpCcBlock.ID = agentId;
122 uccpCcBlock.SessionID = sessionId;
123 uccp.CircuitCode = uccpCcBlock;
124
125 acm.AddNewCircuit(circuitCode, acd);
126
127 testLLUDPServer.LoadReceive(uccp, epSender);
128 testLLUDPServer.ReceiveData(null);
129 }
130
131 /// <summary>
132 /// Build an object name packet for test purposes
133 /// </summary>
134 /// <param name="objectLocalId"></param>
135 /// <param name="objectName"></param>
136 protected ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName)
137 {
138 ObjectNamePacket onp = new ObjectNamePacket();
139 ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock();
140 odb.LocalID = objectLocalId;
141 odb.Name = Utils.StringToBytes(objectName);
142 onp.ObjectData = new ObjectNamePacket.ObjectDataBlock[] { odb };
143 onp.Header.Zerocoded = false;
144
145 return onp;
146 }
147
148 /// <summary>
149 /// Test adding a client to the stack
150 /// </summary>
151 [Test, LongRunning]
152 public void TestAddClient()
153 {
154 TestHelper.InMethod();
155
156 uint myCircuitCode = 123456;
157 UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
158 UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
159
160 TestLLUDPServer testLLUDPServer;
161 TestLLPacketServer testLLPacketServer;
162 AgentCircuitManager acm;
163 SetupStack(new MockScene(), out testLLUDPServer, out testLLPacketServer, out acm);
164
165 AgentCircuitData acd = new AgentCircuitData();
166 acd.AgentID = myAgentUuid;
167 acd.SessionID = mySessionUuid;
168
169 UseCircuitCodePacket uccp = new UseCircuitCodePacket();
170
171 UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
172 = new UseCircuitCodePacket.CircuitCodeBlock();
173 uccpCcBlock.Code = myCircuitCode;
174 uccpCcBlock.ID = myAgentUuid;
175 uccpCcBlock.SessionID = mySessionUuid;
176 uccp.CircuitCode = uccpCcBlock;
177
178 EndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
179
180 testLLUDPServer.LoadReceive(uccp, testEp);
181 testLLUDPServer.ReceiveData(null);
182
183 // Circuit shouildn't exist since the circuit manager doesn't know about this circuit for authentication yet
184 Assert.IsFalse(testLLUDPServer.HasCircuit(myCircuitCode));
185
186 acm.AddNewCircuit(myCircuitCode, acd);
187
188 testLLUDPServer.LoadReceive(uccp, testEp);
189 testLLUDPServer.ReceiveData(null);
190
191 // Should succeed now
192 Assert.IsTrue(testLLUDPServer.HasCircuit(myCircuitCode));
193 Assert.IsFalse(testLLUDPServer.HasCircuit(101));
194 }
195
196 /// <summary>
197 /// Test removing a client from the stack
198 /// </summary>
199 [Test]
200 public void TestRemoveClient()
201 {
202 TestHelper.InMethod();
203
204 uint myCircuitCode = 123457;
205
206 TestLLUDPServer testLLUDPServer;
207 TestLLPacketServer testLLPacketServer;
208 AgentCircuitManager acm;
209 SetupStack(new MockScene(), out testLLUDPServer, out testLLPacketServer, out acm);
210 AddClient(myCircuitCode, new IPEndPoint(IPAddress.Loopback, 1000), testLLUDPServer, acm);
211
212 testLLUDPServer.RemoveClientCircuit(myCircuitCode);
213 Assert.IsFalse(testLLUDPServer.HasCircuit(myCircuitCode));
214
215 // Check that removing a non-existant circuit doesn't have any bad effects
216 testLLUDPServer.RemoveClientCircuit(101);
217 Assert.IsFalse(testLLUDPServer.HasCircuit(101));
218 }
219
220 /// <summary>
221 /// Make sure that the client stack reacts okay to malformed packets
222 /// </summary>
223 [Test]
224 public void TestMalformedPacketSend()
225 {
226 TestHelper.InMethod();
227
228 uint myCircuitCode = 123458;
229 EndPoint testEp = new IPEndPoint(IPAddress.Loopback, 1001);
230 MockScene scene = new MockScene();
231
232 TestLLUDPServer testLLUDPServer;
233 TestLLPacketServer testLLPacketServer;
234 AgentCircuitManager acm;
235 SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm);
236 AddClient(myCircuitCode, testEp, testLLUDPServer, acm);
237
238 byte[] data = new byte[] { 0x01, 0x02, 0x03, 0x04 };
239
240 // Send two garbled 'packets' in succession
241 testLLUDPServer.LoadReceive(data, testEp);
242 testLLUDPServer.LoadReceive(data, testEp);
243 testLLUDPServer.ReceiveData(null);
244
245 // Check that we are still here
246 Assert.IsTrue(testLLUDPServer.HasCircuit(myCircuitCode));
247 Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(0));
248
249 // Check that sending a valid packet to same circuit still succeeds
250 Assert.That(scene.ObjectNameCallsReceived, Is.EqualTo(0));
251
252 testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "helloooo"), testEp);
253 testLLUDPServer.ReceiveData(null);
254
255 Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(1));
256 Assert.That(testLLPacketServer.GetPacketsReceivedFor(PacketType.ObjectName), Is.EqualTo(1));
257 }
258
259 /// <summary>
260 /// Test that the stack continues to work even if some client has caused a
261 /// SocketException on Socket.BeginReceive()
262 /// </summary>
263 [Test]
264 public void TestExceptionOnBeginReceive()
265 {
266 TestHelper.InMethod();
267
268 MockScene scene = new MockScene();
269
270 uint circuitCodeA = 130000;
271 EndPoint epA = new IPEndPoint(IPAddress.Loopback, 1300);
272 UUID agentIdA = UUID.Parse("00000000-0000-0000-0000-000000001300");
273 UUID sessionIdA = UUID.Parse("00000000-0000-0000-0000-000000002300");
274
275 uint circuitCodeB = 130001;
276 EndPoint epB = new IPEndPoint(IPAddress.Loopback, 1301);
277 UUID agentIdB = UUID.Parse("00000000-0000-0000-0000-000000001301");
278 UUID sessionIdB = UUID.Parse("00000000-0000-0000-0000-000000002301");
279
280 TestLLUDPServer testLLUDPServer;
281 TestLLPacketServer testLLPacketServer;
282 AgentCircuitManager acm;
283 SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm);
284 AddClient(circuitCodeA, epA, agentIdA, sessionIdA, testLLUDPServer, acm);
285 AddClient(circuitCodeB, epB, agentIdB, sessionIdB, testLLUDPServer, acm);
286
287 testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "packet1"), epA);
288 testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "packet2"), epB);
289 testLLUDPServer.LoadReceiveWithBeginException(epA);
290 testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(2, "packet3"), epB);
291 testLLUDPServer.ReceiveData(null);
292
293 Assert.IsFalse(testLLUDPServer.HasCircuit(circuitCodeA));
294
295 Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(3));
296 Assert.That(testLLPacketServer.GetPacketsReceivedFor(PacketType.ObjectName), Is.EqualTo(3));
297 }
298 }
299}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
new file mode 100644
index 0000000..34c21aa
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
@@ -0,0 +1,72 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenMetaverse;
29using OpenSim.Framework;
30using OpenSim.Region.Framework.Scenes;
31using GridRegion = OpenSim.Services.Interfaces.GridRegion;
32
33namespace OpenSim.Region.ClientStack.LindenUDP.Tests
34{
35 /// <summary>
36 /// Mock scene for unit tests
37 /// </summary>
38 public class MockScene : SceneBase
39 {
40 public int ObjectNameCallsReceived
41 {
42 get { return m_objectNameCallsReceived; }
43 }
44 protected int m_objectNameCallsReceived;
45
46 public MockScene()
47 {
48 m_regInfo = new RegionInfo(1000, 1000, null, null);
49 m_regStatus = RegionStatus.Up;
50 }
51
52 public override void Update() {}
53 public override void LoadWorldMap() {}
54
55 public override void AddNewClient(IClientAPI client)
56 {
57 client.OnObjectName += RecordObjectNameCall;
58 }
59
60 public override void RemoveClient(UUID agentID) {}
61 public override void CloseAllAgents(uint circuitcode) {}
62 public override void OtherRegionUp(GridRegion otherRegion) { }
63
64 /// <summary>
65 /// Doesn't really matter what the call is - we're using this to test that a packet has actually been received
66 /// </summary>
67 protected void RecordObjectNameCall(IClientAPI remoteClient, uint localID, string message)
68 {
69 m_objectNameCallsReceived++;
70 }
71 }
72}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs
new file mode 100644
index 0000000..7d0757f
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs
@@ -0,0 +1,106 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using Nini.Config;
29using NUnit.Framework;
30using NUnit.Framework.SyntaxHelpers;
31using OpenMetaverse;
32using OpenMetaverse.Packets;
33using OpenSim.Framework;
34using OpenSim.Tests.Common.Mock;
35using OpenSim.Tests.Common;
36
37namespace OpenSim.Region.ClientStack.LindenUDP.Tests
38{
39 /// <summary>
40 /// Tests for the LL packet handler
41 /// </summary>
42 [TestFixture]
43 public class PacketHandlerTests
44 {
45 [Test]
46 /// <summary>
47 /// More a placeholder, really
48 /// </summary>
49 public void InPacketTest()
50 {
51 TestHelper.InMethod();
52
53 AgentCircuitData agent = new AgentCircuitData();
54 agent.AgentID = UUID.Random();
55 agent.firstname = "testfirstname";
56 agent.lastname = "testlastname";
57 agent.SessionID = UUID.Zero;
58 agent.SecureSessionID = UUID.Zero;
59 agent.circuitcode = 123;
60 agent.BaseFolder = UUID.Zero;
61 agent.InventoryFolder = UUID.Zero;
62 agent.startpos = Vector3.Zero;
63 agent.CapsPath = "http://wibble.com";
64
65 TestLLUDPServer testLLUDPServer;
66 TestLLPacketServer testLLPacketServer;
67 AgentCircuitManager acm;
68 IScene scene = new MockScene();
69 SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm);
70
71 TestClient testClient = new TestClient(agent, scene);
72
73 LLPacketHandler packetHandler
74 = new LLPacketHandler(testClient, testLLPacketServer, new ClientStackUserSettings());
75
76 packetHandler.InPacket(new AgentAnimationPacket());
77 LLQueItem receivedPacket = packetHandler.PacketQueue.Dequeue();
78
79 Assert.That(receivedPacket, Is.Not.Null);
80 Assert.That(receivedPacket.Incoming, Is.True);
81 Assert.That(receivedPacket.Packet, Is.TypeOf(typeof(AgentAnimationPacket)));
82 }
83
84 /// <summary>
85 /// Add a client for testing
86 /// </summary>
87 /// <param name="scene"></param>
88 /// <param name="testLLUDPServer"></param>
89 /// <param name="testPacketServer"></param>
90 /// <param name="acm">Agent circuit manager used in setting up the stack</param>
91 protected void SetupStack(
92 IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
93 out AgentCircuitManager acm)
94 {
95 IConfigSource configSource = new IniConfigSource();
96 ClientStackUserSettings userSettings = new ClientStackUserSettings();
97 testLLUDPServer = new TestLLUDPServer();
98 acm = new AgentCircuitManager();
99
100 uint port = 666;
101 testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
102 testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
103 testLLUDPServer.LocalScene = scene;
104 }
105 }
106}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLPacketServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLPacketServer.cs
new file mode 100644
index 0000000..e995d65
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLPacketServer.cs
@@ -0,0 +1,72 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Collections.Generic;
29using OpenMetaverse.Packets;
30
31namespace OpenSim.Region.ClientStack.LindenUDP.Tests
32{
33 public class TestLLPacketServer : LLPacketServer
34 {
35 /// <summary>
36 /// Record counts of packets received
37 /// </summary>
38 protected Dictionary<PacketType, int> m_packetsReceived = new Dictionary<PacketType, int>();
39
40 public TestLLPacketServer(LLUDPServer networkHandler, ClientStackUserSettings userSettings)
41 : base(networkHandler, userSettings)
42 {}
43
44 public override void InPacket(uint circuitCode, Packet packet)
45 {
46 base.InPacket(circuitCode, packet);
47
48 if (m_packetsReceived.ContainsKey(packet.Type))
49 m_packetsReceived[packet.Type]++;
50 else
51 m_packetsReceived[packet.Type] = 1;
52 }
53
54 public int GetTotalPacketsReceived()
55 {
56 int totalCount = 0;
57
58 foreach (int count in m_packetsReceived.Values)
59 totalCount += count;
60
61 return totalCount;
62 }
63
64 public int GetPacketsReceivedFor(PacketType packetType)
65 {
66 if (m_packetsReceived.ContainsKey(packetType))
67 return m_packetsReceived[packetType];
68 else
69 return 0;
70 }
71 }
72}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs
new file mode 100644
index 0000000..f98586d
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs
@@ -0,0 +1,153 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Net.Sockets;
32using OpenMetaverse.Packets;
33
34namespace OpenSim.Region.ClientStack.LindenUDP.Tests
35{
36 /// <summary>
37 /// This class enables synchronous testing of the LLUDPServer by allowing us to load our own data into the end
38 /// receive event
39 /// </summary>
40 public class TestLLUDPServer : LLUDPServer
41 {
42 /// <summary>
43 /// The chunks of data to pass to the LLUDPServer when it calls EndReceive
44 /// </summary>
45 protected Queue<ChunkSenderTuple> m_chunksToLoad = new Queue<ChunkSenderTuple>();
46
47 protected override void BeginReceive()
48 {
49 if (m_chunksToLoad.Count > 0 && m_chunksToLoad.Peek().BeginReceiveException)
50 {
51 ChunkSenderTuple tuple = m_chunksToLoad.Dequeue();
52 reusedEpSender = tuple.Sender;
53 throw new SocketException();
54 }
55 }
56
57 protected override bool EndReceive(out int numBytes, IAsyncResult result, ref EndPoint epSender)
58 {
59 numBytes = 0;
60
61 //m_log.Debug("Queue size " + m_chunksToLoad.Count);
62
63 if (m_chunksToLoad.Count <= 0)
64 return false;
65
66 ChunkSenderTuple tuple = m_chunksToLoad.Dequeue();
67 RecvBuffer = tuple.Data;
68 numBytes = tuple.Data.Length;
69 epSender = tuple.Sender;
70
71 return true;
72 }
73
74 public override void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
75 {
76 // Don't do anything just yet
77 }
78
79 /// <summary>
80 /// Signal that this chunk should throw an exception on Socket.BeginReceive()
81 /// </summary>
82 /// <param name="epSender"></param>
83 public void LoadReceiveWithBeginException(EndPoint epSender)
84 {
85 ChunkSenderTuple tuple = new ChunkSenderTuple(epSender);
86 tuple.BeginReceiveException = true;
87 m_chunksToLoad.Enqueue(tuple);
88 }
89
90 /// <summary>
91 /// Load some data to be received by the LLUDPServer on the next receive call
92 /// </summary>
93 /// <param name="data"></param>
94 /// <param name="epSender"></param>
95 public void LoadReceive(byte[] data, EndPoint epSender)
96 {
97 m_chunksToLoad.Enqueue(new ChunkSenderTuple(data, epSender));
98 }
99
100 /// <summary>
101 /// Load a packet to be received by the LLUDPServer on the next receive call
102 /// </summary>
103 /// <param name="packet"></param>
104 public void LoadReceive(Packet packet, EndPoint epSender)
105 {
106 LoadReceive(packet.ToBytes(), epSender);
107 }
108
109 /// <summary>
110 /// Calls the protected asynchronous result method. This fires out all data chunks currently queued for send
111 /// </summary>
112 /// <param name="result"></param>
113 public void ReceiveData(IAsyncResult result)
114 {
115 while (m_chunksToLoad.Count > 0)
116 OnReceivedData(result);
117 }
118
119 /// <summary>
120 /// Has a circuit with the given code been established?
121 /// </summary>
122 /// <param name="circuitCode"></param>
123 /// <returns></returns>
124 public bool HasCircuit(uint circuitCode)
125 {
126 lock (clientCircuits_reverse)
127 {
128 return clientCircuits_reverse.ContainsKey(circuitCode);
129 }
130 }
131 }
132
133 /// <summary>
134 /// Record the data and sender tuple
135 /// </summary>
136 public class ChunkSenderTuple
137 {
138 public byte[] Data;
139 public EndPoint Sender;
140 public bool BeginReceiveException;
141
142 public ChunkSenderTuple(byte[] data, EndPoint sender)
143 {
144 Data = data;
145 Sender = sender;
146 }
147
148 public ChunkSenderTuple(EndPoint sender)
149 {
150 Sender = sender;
151 }
152 }
153}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
new file mode 100644
index 0000000..c9aac0b
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
@@ -0,0 +1,111 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenSim.Framework;
30using Nini.Config;
31
32namespace OpenSim.Region.ClientStack.LindenUDP
33{
34 /// <summary>
35 /// Holds drip rates and maximum burst rates for throttling with hierarchical
36 /// token buckets. The maximum burst rates set here are hard limits and can
37 /// not be overridden by client requests
38 /// </summary>
39 public sealed class ThrottleRates
40 {
41 /// <summary>Drip rate for resent packets</summary>
42 public int Resend;
43 /// <summary>Drip rate for terrain packets</summary>
44 public int Land;
45 /// <summary>Drip rate for wind packets</summary>
46 public int Wind;
47 /// <summary>Drip rate for cloud packets</summary>
48 public int Cloud;
49 /// <summary>Drip rate for task packets</summary>
50 public int Task;
51 /// <summary>Drip rate for texture packets</summary>
52 public int Texture;
53 /// <summary>Drip rate for asset packets</summary>
54 public int Asset;
55
56 /// <summary>Drip rate for the parent token bucket</summary>
57 public int Total;
58
59 /// <summary>Flag used to enable adaptive throttles</summary>
60 public bool AdaptiveThrottlesEnabled;
61
62 /// <summary>
63 /// Default constructor
64 /// </summary>
65 /// <param name="config">Config source to load defaults from</param>
66 public ThrottleRates(IConfigSource config)
67 {
68 try
69 {
70 IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"];
71
72 Resend = throttleConfig.GetInt("resend_default", 6625);
73 Land = throttleConfig.GetInt("land_default", 9125);
74 Wind = throttleConfig.GetInt("wind_default", 1750);
75 Cloud = throttleConfig.GetInt("cloud_default", 1750);
76 Task = throttleConfig.GetInt("task_default", 18500);
77 Texture = throttleConfig.GetInt("texture_default", 18500);
78 Asset = throttleConfig.GetInt("asset_default", 10500);
79
80 Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
81
82 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
83 }
84 catch (Exception) { }
85 }
86
87 public int GetRate(ThrottleOutPacketType type)
88 {
89 switch (type)
90 {
91 case ThrottleOutPacketType.Resend:
92 return Resend;
93 case ThrottleOutPacketType.Land:
94 return Land;
95 case ThrottleOutPacketType.Wind:
96 return Wind;
97 case ThrottleOutPacketType.Cloud:
98 return Cloud;
99 case ThrottleOutPacketType.Task:
100 return Task;
101 case ThrottleOutPacketType.Texture:
102 return Texture;
103 case ThrottleOutPacketType.Asset:
104 return Asset;
105 case ThrottleOutPacketType.Unknown:
106 default:
107 return 0;
108 }
109 }
110 }
111}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
new file mode 100644
index 0000000..29fd1a4
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
@@ -0,0 +1,393 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using OpenSim.Framework;
33
34using log4net;
35
36namespace OpenSim.Region.ClientStack.LindenUDP
37{
38 /// <summary>
39 /// A hierarchical token bucket for bandwidth throttling. See
40 /// http://en.wikipedia.org/wiki/Token_bucket for more information
41 /// </summary>
42 public class TokenBucket
43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 private static Int32 m_counter = 0;
46
47 private Int32 m_identifier;
48
49 /// <summary>
50 /// Number of ticks (ms) per quantum, drip rate and max burst
51 /// are defined over this interval.
52 /// </summary>
53 protected const Int32 m_ticksPerQuantum = 1000;
54
55 /// <summary>
56 /// This is the number of quantums worth of packets that can
57 /// be accommodated during a burst
58 /// </summary>
59 protected const Double m_quantumsPerBurst = 1.5;
60
61 /// <summary>
62 /// </summary>
63 protected const Int32 m_minimumDripRate = 1400;
64
65 /// <summary>Time of the last drip, in system ticks</summary>
66 protected Int32 m_lastDrip;
67
68 /// <summary>
69 /// The number of bytes that can be sent at this moment. This is the
70 /// current number of tokens in the bucket
71 /// </summary>
72 protected Int64 m_tokenCount;
73
74 /// <summary>
75 /// Map of children buckets and their requested maximum burst rate
76 /// </summary>
77 protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>();
78
79#region Properties
80
81 /// <summary>
82 /// The parent bucket of this bucket, or null if this bucket has no
83 /// parent. The parent bucket will limit the aggregate bandwidth of all
84 /// of its children buckets
85 /// </summary>
86 protected TokenBucket m_parent;
87 public TokenBucket Parent
88 {
89 get { return m_parent; }
90 set { m_parent = value; }
91 }
92
93 /// <summary>
94 /// Maximum burst rate in bytes per second. This is the maximum number
95 /// of tokens that can accumulate in the bucket at any one time. This
96 /// also sets the total request for leaf nodes
97 /// </summary>
98 protected Int64 m_burstRate;
99 public Int64 RequestedBurstRate
100 {
101 get { return m_burstRate; }
102 set { m_burstRate = (value < 0 ? 0 : value); }
103 }
104
105 public Int64 BurstRate
106 {
107 get {
108 double rate = RequestedBurstRate * BurstRateModifier();
109 if (rate < m_minimumDripRate * m_quantumsPerBurst)
110 rate = m_minimumDripRate * m_quantumsPerBurst;
111
112 return (Int64) rate;
113 }
114 }
115
116 /// <summary>
117 /// The speed limit of this bucket in bytes per second. This is the
118 /// number of tokens that are added to the bucket per quantum
119 /// </summary>
120 /// <remarks>Tokens are added to the bucket any time
121 /// <seealso cref="RemoveTokens"/> is called, at the granularity of
122 /// the system tick interval (typically around 15-22ms)</remarks>
123 protected Int64 m_dripRate;
124 public virtual Int64 RequestedDripRate
125 {
126 get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
127 set {
128 m_dripRate = (value < 0 ? 0 : value);
129 m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst);
130 m_totalDripRequest = m_dripRate;
131 if (m_parent != null)
132 m_parent.RegisterRequest(this,m_dripRate);
133 }
134 }
135
136 public virtual Int64 DripRate
137 {
138 get {
139 if (m_parent == null)
140 return Math.Min(RequestedDripRate,TotalDripRequest);
141
142 double rate = (double)RequestedDripRate * m_parent.DripRateModifier();
143 if (rate < m_minimumDripRate)
144 rate = m_minimumDripRate;
145
146 return (Int64)rate;
147 }
148 }
149
150 /// <summary>
151 /// The current total of the requested maximum burst rates of
152 /// this bucket's children buckets.
153 /// </summary>
154 protected Int64 m_totalDripRequest;
155 public Int64 TotalDripRequest
156 {
157 get { return m_totalDripRequest; }
158 set { m_totalDripRequest = value; }
159 }
160
161#endregion Properties
162
163#region Constructor
164
165 /// <summary>
166 /// Default constructor
167 /// </summary>
168 /// <param name="parent">Parent bucket if this is a child bucket, or
169 /// null if this is a root bucket</param>
170 /// <param name="maxBurst">Maximum size of the bucket in bytes, or
171 /// zero if this bucket has no maximum capacity</param>
172 /// <param name="dripRate">Rate that the bucket fills, in bytes per
173 /// second. If zero, the bucket always remains full</param>
174 public TokenBucket(TokenBucket parent, Int64 dripRate)
175 {
176 m_identifier = m_counter++;
177
178 Parent = parent;
179 RequestedDripRate = dripRate;
180 // TotalDripRequest = dripRate; // this will be overwritten when a child node registers
181 // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst);
182 m_lastDrip = Util.EnvironmentTickCount();
183 }
184
185#endregion Constructor
186
187 /// <summary>
188 /// Compute a modifier for the MaxBurst rate. This is 1.0, meaning
189 /// no modification if the requested bandwidth is less than the
190 /// max burst bandwidth all the way to the root of the throttle
191 /// hierarchy. However, if any of the parents is over-booked, then
192 /// the modifier will be less than 1.
193 /// </summary>
194 protected double DripRateModifier()
195 {
196 Int64 driprate = DripRate;
197 return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest;
198 }
199
200 /// <summary>
201 /// </summary>
202 protected double BurstRateModifier()
203 {
204 // for now... burst rate is always m_quantumsPerBurst (constant)
205 // larger than drip rate so the ratio of burst requests is the
206 // same as the drip ratio
207 return DripRateModifier();
208 }
209
210 /// <summary>
211 /// Register drip rate requested by a child of this throttle. Pass the
212 /// changes up the hierarchy.
213 /// </summary>
214 public void RegisterRequest(TokenBucket child, Int64 request)
215 {
216 lock (m_children)
217 {
218 m_children[child] = request;
219 // m_totalDripRequest = m_children.Values.Sum();
220
221 m_totalDripRequest = 0;
222 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
223 m_totalDripRequest += cref.Value;
224 }
225
226 // Pass the new values up to the parent
227 if (m_parent != null)
228 m_parent.RegisterRequest(this,Math.Min(RequestedDripRate, TotalDripRequest));
229 }
230
231 /// <summary>
232 /// Remove the rate requested by a child of this throttle. Pass the
233 /// changes up the hierarchy.
234 /// </summary>
235 public void UnregisterRequest(TokenBucket child)
236 {
237 lock (m_children)
238 {
239 m_children.Remove(child);
240 // m_totalDripRequest = m_children.Values.Sum();
241
242 m_totalDripRequest = 0;
243 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
244 m_totalDripRequest += cref.Value;
245 }
246
247
248 // Pass the new values up to the parent
249 if (m_parent != null)
250 m_parent.RegisterRequest(this,Math.Min(RequestedDripRate, TotalDripRequest));
251 }
252
253 /// <summary>
254 /// Remove a given number of tokens from the bucket
255 /// </summary>
256 /// <param name="amount">Number of tokens to remove from the bucket</param>
257 /// <returns>True if the requested number of tokens were removed from
258 /// the bucket, otherwise false</returns>
259 public bool RemoveTokens(Int64 amount)
260 {
261 // Deposit tokens for this interval
262 Drip();
263
264 // If we have enough tokens then remove them and return
265 if (m_tokenCount - amount >= 0)
266 {
267 // we don't have to remove from the parent, the drip rate is already
268 // reflective of the drip rate limits in the parent
269 m_tokenCount -= amount;
270 return true;
271 }
272
273 return false;
274 }
275
276 /// <summary>
277 /// Deposit tokens into the bucket from a child bucket that did
278 /// not use all of its available tokens
279 /// </summary>
280 protected void Deposit(Int64 count)
281 {
282 m_tokenCount += count;
283
284 // Deposit the overflow in the parent bucket, this is how we share
285 // unused bandwidth
286 Int64 burstrate = BurstRate;
287 if (m_tokenCount > burstrate)
288 m_tokenCount = burstrate;
289 }
290
291 /// <summary>
292 /// Add tokens to the bucket over time. The number of tokens added each
293 /// call depends on the length of time that has passed since the last
294 /// call to Drip
295 /// </summary>
296 /// <returns>True if tokens were added to the bucket, otherwise false</returns>
297 protected void Drip()
298 {
299 // This should never happen... means we are a leaf node and were created
300 // with no drip rate...
301 if (DripRate == 0)
302 {
303 m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0");
304 return;
305 }
306
307 // Determine the interval over which we are adding tokens, never add
308 // more than a single quantum of tokens
309 Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum);
310 m_lastDrip = Util.EnvironmentTickCount();
311
312 // This can be 0 in the very unusual case that the timer wrapped
313 // It can be 0 if we try add tokens at a sub-tick rate
314 if (deltaMS <= 0)
315 return;
316
317 Deposit(deltaMS * DripRate / m_ticksPerQuantum);
318 }
319 }
320
321 public class AdaptiveTokenBucket : TokenBucket
322 {
323 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
324
325 /// <summary>
326 /// The minimum rate for flow control. Minimum drip rate is one
327 /// packet per second. Open the throttle to 15 packets per second
328 /// or about 160kbps.
329 /// </summary>
330 protected const Int64 m_minimumFlow = m_minimumDripRate * 15;
331
332 // <summary>
333 // The maximum rate for flow control. Drip rate can never be
334 // greater than this.
335 // </summary>
336 protected Int64 m_maxDripRate = 0;
337 protected Int64 MaxDripRate
338 {
339 get { return (m_maxDripRate == 0 ? m_totalDripRequest : m_maxDripRate); }
340 set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); }
341 }
342
343 private bool m_enabled = false;
344
345 // <summary>
346 //
347 // </summary>
348 public virtual Int64 AdjustedDripRate
349 {
350 get { return m_dripRate; }
351 set {
352 m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value,m_minimumFlow,MaxDripRate);
353 m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst);
354 if (m_parent != null)
355 m_parent.RegisterRequest(this,m_dripRate);
356 }
357 }
358
359 // <summary>
360 //
361 // </summary>
362 public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate, bool enabled) : base(parent,maxDripRate)
363 {
364 m_enabled = enabled;
365
366 if (m_enabled)
367 {
368 // m_log.DebugFormat("[TOKENBUCKET] Adaptive throttle enabled");
369 MaxDripRate = maxDripRate;
370 AdjustedDripRate = m_minimumFlow;
371 }
372 }
373
374 // <summary>
375 //
376 // </summary>
377 public void ExpirePackets(Int32 count)
378 {
379 // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count);
380 if (m_enabled)
381 AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count));
382 }
383
384 // <summary>
385 //
386 // </summary>
387 public void AcknowledgePackets(Int32 count)
388 {
389 if (m_enabled)
390 AdjustedDripRate = AdjustedDripRate + count;
391 }
392 }
393}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs
new file mode 100644
index 0000000..793aefe
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs
@@ -0,0 +1,219 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Threading;
32using OpenMetaverse;
33
34namespace OpenSim.Region.ClientStack.LindenUDP
35{
36 /// <summary>
37 /// Special collection that is optimized for tracking unacknowledged packets
38 /// </summary>
39 public sealed class UnackedPacketCollection
40 {
41 /// <summary>
42 /// Holds information about a pending acknowledgement
43 /// </summary>
44 private struct PendingAck
45 {
46 /// <summary>Sequence number of the packet to remove</summary>
47 public uint SequenceNumber;
48 /// <summary>Environment.TickCount value when the remove was queued.
49 /// This is used to update round-trip times for packets</summary>
50 public int RemoveTime;
51 /// <summary>Whether or not this acknowledgement was attached to a
52 /// resent packet. If so, round-trip time will not be calculated</summary>
53 public bool FromResend;
54
55 public PendingAck(uint sequenceNumber, int currentTime, bool fromResend)
56 {
57 SequenceNumber = sequenceNumber;
58 RemoveTime = currentTime;
59 FromResend = fromResend;
60 }
61 }
62
63 /// <summary>Holds the actual unacked packet data, sorted by sequence number</summary>
64 private Dictionary<uint, OutgoingPacket> m_packets = new Dictionary<uint, OutgoingPacket>();
65 /// <summary>Holds packets that need to be added to the unacknowledged list</summary>
66 private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>();
67 /// <summary>Holds information about pending acknowledgements</summary>
68 private LocklessQueue<PendingAck> m_pendingAcknowledgements = new LocklessQueue<PendingAck>();
69 /// <summary>Holds information about pending removals</summary>
70 private LocklessQueue<uint> m_pendingRemoves = new LocklessQueue<uint>();
71
72 /// <summary>
73 /// Add an unacked packet to the collection
74 /// </summary>
75 /// <param name="packet">Packet that is awaiting acknowledgement</param>
76 /// <returns>True if the packet was successfully added, false if the
77 /// packet already existed in the collection</returns>
78 /// <remarks>This does not immediately add the ACK to the collection,
79 /// it only queues it so it can be added in a thread-safe way later</remarks>
80 public void Add(OutgoingPacket packet)
81 {
82 m_pendingAdds.Enqueue(packet);
83 Interlocked.Add(ref packet.Client.UnackedBytes, packet.Buffer.DataLength);
84 }
85
86 /// <summary>
87 /// Marks a packet as acknowledged
88 /// This method is used when an acknowledgement is received from the network for a previously
89 /// sent packet. Effects of removal this way are to update unacked byte count, adjust RTT
90 /// and increase throttle to the coresponding client.
91 /// </summary>
92 /// <param name="sequenceNumber">Sequence number of the packet to
93 /// acknowledge</param>
94 /// <param name="currentTime">Current value of Environment.TickCount</param>
95 /// <remarks>This does not immediately acknowledge the packet, it only
96 /// queues the ack so it can be handled in a thread-safe way later</remarks>
97 public void Acknowledge(uint sequenceNumber, int currentTime, bool fromResend)
98 {
99 m_pendingAcknowledgements.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend));
100 }
101
102 /// <summary>
103 /// Marks a packet as no longer needing acknowledgement without a received acknowledgement.
104 /// This method is called when a packet expires and we no longer need an acknowledgement.
105 /// When some reliable packet types expire, they are handled in a way other than simply
106 /// resending them. The only effect of removal this way is to update unacked byte count.
107 /// </summary>
108 /// <param name="sequenceNumber">Sequence number of the packet to
109 /// acknowledge</param>
110 /// <remarks>The does not immediately remove the packet, it only queues the removal
111 /// so it can be handled in a thread safe way later</remarks>
112 public void Remove(uint sequenceNumber)
113 {
114 m_pendingRemoves.Enqueue(sequenceNumber);
115 }
116
117 /// <summary>
118 /// Returns a list of all of the packets with a TickCount older than
119 /// the specified timeout
120 /// </summary>
121 /// <param name="timeoutMS">Number of ticks (milliseconds) before a
122 /// packet is considered expired</param>
123 /// <returns>A list of all expired packets according to the given
124 /// expiration timeout</returns>
125 /// <remarks>This function is not thread safe, and cannot be called
126 /// multiple times concurrently</remarks>
127 public List<OutgoingPacket> GetExpiredPackets(int timeoutMS)
128 {
129 ProcessQueues();
130
131 List<OutgoingPacket> expiredPackets = null;
132
133 if (m_packets.Count > 0)
134 {
135 int now = Environment.TickCount & Int32.MaxValue;
136
137 foreach (OutgoingPacket packet in m_packets.Values)
138 {
139 // TickCount of zero means a packet is in the resend queue
140 // but hasn't actually been sent over the wire yet
141 if (packet.TickCount == 0)
142 continue;
143
144 if (now - packet.TickCount >= timeoutMS)
145 {
146 if (expiredPackets == null)
147 expiredPackets = new List<OutgoingPacket>();
148
149 // The TickCount will be set to the current time when the packet
150 // is actually sent out again
151 packet.TickCount = 0;
152
153 // As with other network applications, assume that an expired packet is
154 // an indication of some network problem, slow transmission
155 packet.Client.FlowThrottle.ExpirePackets(1);
156
157 expiredPackets.Add(packet);
158 }
159 }
160 }
161
162 return expiredPackets;
163 }
164
165 private void ProcessQueues()
166 {
167 // Process all the pending adds
168 OutgoingPacket pendingAdd;
169 while (m_pendingAdds.TryDequeue(out pendingAdd))
170 if (pendingAdd != null)
171 m_packets[pendingAdd.SequenceNumber] = pendingAdd;
172
173 // Process all the pending removes, including updating statistics and round-trip times
174 PendingAck pendingAcknowledgement;
175 while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement))
176 {
177 OutgoingPacket ackedPacket;
178 if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket))
179 {
180 if (ackedPacket != null)
181 {
182 m_packets.Remove(pendingAcknowledgement.SequenceNumber);
183
184 // As with other network applications, assume that an acknowledged packet is an
185 // indication that the network can handle a little more load, speed up the transmission
186 ackedPacket.Client.FlowThrottle.AcknowledgePackets(ackedPacket.Buffer.DataLength);
187
188 // Update stats
189 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
190
191 if (!pendingAcknowledgement.FromResend)
192 {
193 // Calculate the round-trip time for this packet and its ACK
194 int rtt = pendingAcknowledgement.RemoveTime - ackedPacket.TickCount;
195 if (rtt > 0)
196 ackedPacket.Client.UpdateRoundTrip(rtt);
197 }
198 }
199 }
200 }
201
202 uint pendingRemove;
203 while(m_pendingRemoves.TryDequeue(out pendingRemove))
204 {
205 OutgoingPacket removedPacket;
206 if (m_packets.TryGetValue(pendingRemove, out removedPacket))
207 {
208 if (removedPacket != null)
209 {
210 m_packets.Remove(pendingRemove);
211
212 // Update stats
213 Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
214 }
215 }
216 }
217 }
218 }
219}