aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden
diff options
context:
space:
mode:
authorMelanie2011-05-05 09:49:10 +0100
committerMelanie2011-05-05 09:49:10 +0100
commit4beb0c9b9b402c1e8f70a02c0efa557c1f292f1c (patch)
tree24e24cb7b424df74b13788d28be9d7588fbd99d0 /OpenSim/Region/ClientStack/Linden
parentMerge branch 'master' into careminster-presence-refactor (diff)
parentTest m_Enabled on RemoveRegion. (diff)
downloadopensim-SC-4beb0c9b9b402c1e8f70a02c0efa557c1f292f1c.zip
opensim-SC-4beb0c9b9b402c1e8f70a02c0efa557c1f292f1c.tar.gz
opensim-SC-4beb0c9b9b402c1e8f70a02c0efa557c1f292f1c.tar.bz2
opensim-SC-4beb0c9b9b402c1e8f70a02c0efa557c1f292f1c.tar.xz
Merge branch 'master' into careminster-presence-refactor
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs938
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs91
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs731
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs399
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs139
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs142
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs275
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs370
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs374
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs134
-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.cs401
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs12218
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs257
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs707
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs1276
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs280
-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
27 files changed, 20362 insertions, 0 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
new file mode 100644
index 0000000..95713e9
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -0,0 +1,938 @@
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.IO;
5using System.Reflection;
6
7using OpenMetaverse;
8using Nini.Config;
9using log4net;
10
11using OpenSim.Framework;
12using OpenSim.Framework.Capabilities;
13using OpenSim.Region.Framework;
14using OpenSim.Region.Framework.Scenes;
15using OpenSim.Framework.Servers;
16using OpenSim.Framework.Servers.HttpServer;
17using OpenSim.Services.Interfaces;
18
19using Caps = OpenSim.Framework.Capabilities.Caps;
20
21namespace OpenSim.Region.ClientStack.Linden
22{
23 public delegate void UpLoadedAsset(
24 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
25 byte[] data, string inventoryType, string assetType);
26
27 public delegate void UploadedBakedTexture(UUID assetID, byte[] data);
28
29 public delegate UUID UpdateItem(UUID itemID, byte[] data);
30
31 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors);
32
33 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item);
34
35 public delegate void NewAsset(AssetBase asset);
36
37 public delegate UUID ItemUpdatedCallback(UUID userID, UUID itemID, byte[] data);
38
39 public delegate ArrayList TaskScriptUpdatedCallback(UUID userID, UUID itemID, UUID primID,
40 bool isScriptRunning, byte[] data);
41
42 public delegate InventoryCollection FetchInventoryDescendentsCAPS(UUID agentID, UUID folderID, UUID ownerID,
43 bool fetchFolders, bool fetchItems, int sortOrder, out int version);
44
45 /// <summary>
46 /// XXX Probably not a particularly nice way of allow us to get the scene presence from the scene (chiefly so that
47 /// we can popup a message on the user's client if the inventory service has permanently failed). But I didn't want
48 /// to just pass the whole Scene into CAPS.
49 /// </summary>
50 public delegate IClientAPI GetClientDelegate(UUID agentID);
51
52 public class BunchOfCaps
53 {
54 private static readonly ILog m_log =
55 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 private Scene m_Scene;
58 private Caps m_HostCapsObj;
59
60 private static readonly string m_requestPath = "0000/";
61 // private static readonly string m_mapLayerPath = "0001/";
62 private static readonly string m_newInventory = "0002/";
63 //private static readonly string m_requestTexture = "0003/";
64 private static readonly string m_notecardUpdatePath = "0004/";
65 private static readonly string m_notecardTaskUpdatePath = "0005/";
66 // private static readonly string m_fetchInventoryPath = "0006/";
67 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule.
68 private static readonly string m_uploadBakedTexturePath = "0010/";// This is in the LandManagementModule.
69
70
71 // These are callbacks which will be setup by the scene so that we can update scene data when we
72 // receive capability calls
73 public NewInventoryItem AddNewInventoryItem = null;
74 public NewAsset AddNewAsset = null;
75 public ItemUpdatedCallback ItemUpdatedCall = null;
76 public TaskScriptUpdatedCallback TaskScriptUpdatedCall = null;
77 public FetchInventoryDescendentsCAPS CAPSFetchInventoryDescendents = null;
78 public GetClientDelegate GetClient = null;
79
80 private bool m_persistBakedTextures = false;
81 private IAssetService m_assetService;
82 private bool m_dumpAssetsToFile;
83 private string m_regionName;
84
85 public BunchOfCaps(Scene scene, Caps caps)
86 {
87 m_Scene = scene;
88 m_HostCapsObj = caps;
89 IConfigSource config = m_Scene.Config;
90 if (config != null)
91 {
92 IConfig sconfig = config.Configs["Startup"];
93 if (sconfig != null)
94 m_persistBakedTextures = sconfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
95 }
96
97 m_assetService = m_Scene.AssetService;
98 m_regionName = m_Scene.RegionInfo.RegionName;
99
100 RegisterHandlers();
101
102 AddNewInventoryItem = m_Scene.AddUploadedInventoryItem;
103 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset;
104 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset;
105 CAPSFetchInventoryDescendents = m_Scene.HandleFetchInventoryDescendentsCAPS;
106 GetClient = m_Scene.SceneContents.GetControllingClient;
107
108 }
109
110 /// <summary>
111 /// Register a bunch of CAPS http service handlers
112 /// </summary>
113 public void RegisterHandlers()
114 {
115 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
116
117 RegisterRegionServiceHandlers(capsBase);
118 RegisterInventoryServiceHandlers(capsBase);
119 }
120
121 public void RegisterRegionServiceHandlers(string capsBase)
122 {
123 try
124 {
125 // the root of all evil
126 m_HostCapsObj.RegisterHandler("SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest));
127 m_log.DebugFormat(
128 "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID);
129
130 //m_capsHandlers["MapLayer"] =
131 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
132 // capsBase + m_mapLayerPath,
133 // GetMapLayer);
134 IRequestHandler req = new RestStreamHandler("POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory);
135 m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req);
136 m_HostCapsObj.RegisterHandler("UpdateScriptTask", req);
137 m_HostCapsObj.RegisterHandler("UploadBakedTexture", new RestStreamHandler("POST", capsBase + m_uploadBakedTexturePath, UploadBakedTexture));
138
139 }
140 catch (Exception e)
141 {
142 m_log.Error("[CAPS]: " + e.ToString());
143 }
144 }
145
146 public void RegisterInventoryServiceHandlers(string capsBase)
147 {
148 try
149 {
150 // I don't think this one works...
151 m_HostCapsObj.RegisterHandler("NewFileAgentInventory", new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>("POST",
152 capsBase + m_newInventory,
153 NewAgentInventoryRequest));
154 IRequestHandler req = new RestStreamHandler("POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory);
155 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
156 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
157 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
158
159 // As of RC 1.22.9 of the Linden client this is
160 // supported
161
162 //m_capsHandlers["WebFetchInventoryDescendents"] =new RestStreamHandler("POST", capsBase + m_fetchInventoryPath, FetchInventoryDescendentsRequest);
163
164 // justincc: I've disabled the CAPS service for now to fix problems with selecting textures, and
165 // subsequent inventory breakage, in the edit object pane (such as mantis 1085). This requires
166 // enhancements (probably filling out the folder part of the LLSD reply) to our CAPS service,
167 // but when I went on the Linden grid, the
168 // simulators I visited (version 1.21) were, surprisingly, no longer supplying this capability. Instead,
169 // the 1.19.1.4 client appeared to be happily flowing inventory data over UDP
170 //
171 // This is very probably just a temporary measure - once the CAPS service appears again on the Linden grid
172 // we will be
173 // able to get the data we need to implement the necessary part of the protocol to fix the issue above.
174 // m_capsHandlers["FetchInventoryDescendents"] =
175 // new RestStreamHandler("POST", capsBase + m_fetchInventoryPath, FetchInventoryRequest);
176
177 // m_capsHandlers["FetchInventoryDescendents"] =
178 // new LLSDStreamhandler<LLSDFetchInventoryDescendents, LLSDInventoryDescendents>("POST",
179 // capsBase + m_fetchInventory,
180 // FetchInventory));
181 // m_capsHandlers["RequestTextureDownload"] = new RestStreamHandler("POST",
182 // capsBase + m_requestTexture,
183 // RequestTexture);
184 }
185 catch (Exception e)
186 {
187 m_log.Error("[CAPS]: " + e.ToString());
188 }
189 }
190
191 /// <summary>
192 /// Construct a client response detailing all the capabilities this server can provide.
193 /// </summary>
194 /// <param name="request"></param>
195 /// <param name="path"></param>
196 /// <param name="param"></param>
197 /// <param name="httpRequest">HTTP request header object</param>
198 /// <param name="httpResponse">HTTP response header object</param>
199 /// <returns></returns>
200 public string SeedCapRequest(string request, string path, string param,
201 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
202 {
203 m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName);
204
205 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
206 {
207 m_log.DebugFormat("[CAPS]: Unauthorized CAPS client");
208 return string.Empty;
209 }
210
211 Hashtable caps = m_HostCapsObj.CapsHandlers.CapsDetails;
212 // Add the external too
213 foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers)
214 caps[kvp.Key] = kvp.Value;
215
216 string result = LLSDHelpers.SerialiseLLSDReply(caps);
217
218 //m_log.DebugFormat("[CAPS] CapsRequest {0}", result);
219
220 return result;
221 }
222
223 /// <summary>
224 /// Called by the script task update handler. Provides a URL to which the client can upload a new asset.
225 /// </summary>
226 /// <param name="request"></param>
227 /// <param name="path"></param>
228 /// <param name="param"></param>
229 /// <param name="httpRequest">HTTP request header object</param>
230 /// <param name="httpResponse">HTTP response header object</param>
231 /// <returns></returns>
232 public string ScriptTaskInventory(string request, string path, string param,
233 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
234 {
235 try
236 {
237 m_log.Debug("[CAPS]: ScriptTaskInventory Request in region: " + m_regionName);
238 //m_log.DebugFormat("[CAPS]: request: {0}, path: {1}, param: {2}", request, path, param);
239
240 Hashtable hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
241 LLSDTaskScriptUpdate llsdUpdateRequest = new LLSDTaskScriptUpdate();
242 LLSDHelpers.DeserialiseOSDMap(hash, llsdUpdateRequest);
243
244 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
245 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
246
247 TaskInventoryScriptUpdater uploader =
248 new TaskInventoryScriptUpdater(
249 llsdUpdateRequest.item_id,
250 llsdUpdateRequest.task_id,
251 llsdUpdateRequest.is_script_running,
252 capsBase + uploaderPath,
253 m_HostCapsObj.HttpListener,
254 m_dumpAssetsToFile);
255 uploader.OnUpLoad += TaskScriptUpdated;
256
257 m_HostCapsObj.HttpListener.AddStreamHandler(new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
258
259 string protocol = "http://";
260
261 if (m_HostCapsObj.SSLCaps)
262 protocol = "https://";
263
264 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
265 uploaderPath;
266
267 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
268 uploadResponse.uploader = uploaderURL;
269 uploadResponse.state = "upload";
270
271 // m_log.InfoFormat("[CAPS]: " +
272 // "ScriptTaskInventory response: {0}",
273 // LLSDHelpers.SerialiseLLSDReply(uploadResponse)));
274
275 return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
276 }
277 catch (Exception e)
278 {
279 m_log.Error("[CAPS]: " + e.ToString());
280 }
281
282 return null;
283 }
284
285 /// <summary>
286 /// Called when new asset data for an agent inventory item update has been uploaded.
287 /// </summary>
288 /// <param name="itemID">Item to update</param>
289 /// <param name="primID">Prim containing item to update</param>
290 /// <param name="isScriptRunning">Signals whether the script to update is currently running</param>
291 /// <param name="data">New asset data</param>
292 public void TaskScriptUpdated(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors)
293 {
294 if (TaskScriptUpdatedCall != null)
295 {
296 ArrayList e = TaskScriptUpdatedCall(m_HostCapsObj.AgentID, itemID, primID, isScriptRunning, data);
297 foreach (Object item in e)
298 errors.Add(item);
299 }
300 }
301
302 public string UploadBakedTexture(string request, string path,
303 string param, OSHttpRequest httpRequest,
304 OSHttpResponse httpResponse)
305 {
306 try
307 {
308 // m_log.Debug("[CAPS]: UploadBakedTexture Request in region: " +
309 // m_regionName);
310
311 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
312 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
313
314 BakedTextureUploader uploader =
315 new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener);
316 uploader.OnUpLoad += BakedTextureUploaded;
317
318 m_HostCapsObj.HttpListener.AddStreamHandler(
319 new BinaryStreamHandler("POST", capsBase + uploaderPath,
320 uploader.uploaderCaps));
321
322 string protocol = "http://";
323
324 if (m_HostCapsObj.SSLCaps)
325 protocol = "https://";
326
327 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" +
328 m_HostCapsObj.Port.ToString() + capsBase + uploaderPath;
329
330 LLSDAssetUploadResponse uploadResponse =
331 new LLSDAssetUploadResponse();
332 uploadResponse.uploader = uploaderURL;
333 uploadResponse.state = "upload";
334
335 return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
336 }
337 catch (Exception e)
338 {
339 m_log.Error("[CAPS]: " + e.ToString());
340 }
341
342 return null;
343 }
344
345 public void BakedTextureUploaded(UUID assetID, byte[] data)
346 {
347 // m_log.WarnFormat("[CAPS]: Received baked texture {0}", assetID.ToString());
348
349 AssetBase asset;
350 asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString());
351 asset.Data = data;
352 asset.Temporary = true;
353 asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are
354 m_assetService.Store(asset);
355 }
356
357 /// <summary>
358 /// Called when new asset data for an agent inventory item update has been uploaded.
359 /// </summary>
360 /// <param name="itemID">Item to update</param>
361 /// <param name="data">New asset data</param>
362 /// <returns></returns>
363 public UUID ItemUpdated(UUID itemID, byte[] data)
364 {
365 if (ItemUpdatedCall != null)
366 {
367 return ItemUpdatedCall(m_HostCapsObj.AgentID, itemID, data);
368 }
369
370 return UUID.Zero;
371 }
372
373 /// <summary>
374 ///
375 /// </summary>
376 /// <param name="llsdRequest"></param>
377 /// <returns></returns>
378 public LLSDAssetUploadResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest)
379 {
380 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
381 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
382
383 if (llsdRequest.asset_type == "texture" ||
384 llsdRequest.asset_type == "animation" ||
385 llsdRequest.asset_type == "sound")
386 {
387 IClientAPI client = null;
388 IScene scene = null;
389 if (GetClient != null)
390 {
391 client = GetClient(m_HostCapsObj.AgentID);
392 scene = client.Scene;
393
394 IMoneyModule mm = scene.RequestModuleInterface<IMoneyModule>();
395
396 if (mm != null)
397 {
398 if (!mm.UploadCovered(client, mm.UploadCharge))
399 {
400 if (client != null)
401 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
402
403 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
404 errorResponse.uploader = "";
405 errorResponse.state = "error";
406 return errorResponse;
407 }
408 }
409 }
410 }
411
412 string assetName = llsdRequest.name;
413 string assetDes = llsdRequest.description;
414 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
415 UUID newAsset = UUID.Random();
416 UUID newInvItem = UUID.Random();
417 UUID parentFolder = llsdRequest.folder_id;
418 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
419
420 AssetUploader uploader =
421 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
422 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile);
423 m_HostCapsObj.HttpListener.AddStreamHandler(
424 new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
425
426 string protocol = "http://";
427
428 if (m_HostCapsObj.SSLCaps)
429 protocol = "https://";
430
431 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
432 uploaderPath;
433
434 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
435 uploadResponse.uploader = uploaderURL;
436 uploadResponse.state = "upload";
437 uploader.OnUpLoad += UploadCompleteHandler;
438 return uploadResponse;
439 }
440
441 /// <summary>
442 ///
443 /// </summary>
444 /// <param name="assetID"></param>
445 /// <param name="inventoryItem"></param>
446 /// <param name="data"></param>
447 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
448 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
449 string assetType)
450 {
451 sbyte assType = 0;
452 sbyte inType = 0;
453
454 if (inventoryType == "sound")
455 {
456 inType = 1;
457 assType = 1;
458 }
459 else if (inventoryType == "animation")
460 {
461 inType = 19;
462 assType = 20;
463 }
464 else if (inventoryType == "wearable")
465 {
466 inType = 18;
467 switch (assetType)
468 {
469 case "bodypart":
470 assType = 13;
471 break;
472 case "clothing":
473 assType = 5;
474 break;
475 }
476 }
477
478 AssetBase asset;
479 asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString());
480 asset.Data = data;
481 if (AddNewAsset != null)
482 AddNewAsset(asset);
483 else if (m_assetService != null)
484 m_assetService.Store(asset);
485
486 InventoryItemBase item = new InventoryItemBase();
487 item.Owner = m_HostCapsObj.AgentID;
488 item.CreatorId = m_HostCapsObj.AgentID.ToString();
489 item.CreatorData = String.Empty;
490 item.ID = inventoryItem;
491 item.AssetID = asset.FullID;
492 item.Description = assetDescription;
493 item.Name = assetName;
494 item.AssetType = assType;
495 item.InvType = inType;
496 item.Folder = parentFolder;
497 item.CurrentPermissions = (uint)PermissionMask.All;
498 item.BasePermissions = (uint)PermissionMask.All;
499 item.EveryOnePermissions = 0;
500 item.NextPermissions = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
501 item.CreationDate = Util.UnixTimeSinceEpoch();
502
503 if (AddNewInventoryItem != null)
504 {
505 AddNewInventoryItem(m_HostCapsObj.AgentID, item);
506 }
507 }
508
509
510
511 /// <summary>
512 ///
513 /// </summary>
514 /// <param name="mapReq"></param>
515 /// <returns></returns>
516 public LLSDMapLayerResponse GetMapLayer(LLSDMapRequest mapReq)
517 {
518 m_log.Debug("[CAPS]: MapLayer Request in region: " + m_regionName);
519 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
520 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
521 return mapResponse;
522 }
523
524 /// <summary>
525 ///
526 /// </summary>
527 /// <returns></returns>
528 protected static OSDMapLayer GetOSDMapLayerResponse()
529 {
530 OSDMapLayer mapLayer = new OSDMapLayer();
531 mapLayer.Right = 5000;
532 mapLayer.Top = 5000;
533 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
534
535 return mapLayer;
536 }
537
538 /// <summary>
539 ///
540 /// </summary>
541 /// <param name="request"></param>
542 /// <param name="path"></param>
543 /// <param name="param"></param>
544 /// <returns></returns>
545 public string RequestTexture(string request, string path, string param)
546 {
547 m_log.Debug("texture request " + request);
548 // Needs implementing (added to remove compiler warning)
549 return String.Empty;
550 }
551
552
553 /// <summary>
554 /// Called by the notecard update handler. Provides a URL to which the client can upload a new asset.
555 /// </summary>
556 /// <param name="request"></param>
557 /// <param name="path"></param>
558 /// <param name="param"></param>
559 /// <returns></returns>
560 public string NoteCardAgentInventory(string request, string path, string param,
561 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
562 {
563 //m_log.Debug("[CAPS]: NoteCardAgentInventory Request in region: " + m_regionName + "\n" + request);
564 //m_log.Debug("[CAPS]: NoteCardAgentInventory Request is: " + request);
565
566 //OpenMetaverse.StructuredData.OSDMap hash = (OpenMetaverse.StructuredData.OSDMap)OpenMetaverse.StructuredData.LLSDParser.DeserializeBinary(Utils.StringToBytes(request));
567 Hashtable hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
568 LLSDItemUpdate llsdRequest = new LLSDItemUpdate();
569 LLSDHelpers.DeserialiseOSDMap(hash, llsdRequest);
570
571 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
572 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
573
574 ItemUpdater uploader =
575 new ItemUpdater(llsdRequest.item_id, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile);
576 uploader.OnUpLoad += ItemUpdated;
577
578 m_HostCapsObj.HttpListener.AddStreamHandler(
579 new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
580
581 string protocol = "http://";
582
583 if (m_HostCapsObj.SSLCaps)
584 protocol = "https://";
585
586 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
587 uploaderPath;
588
589 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
590 uploadResponse.uploader = uploaderURL;
591 uploadResponse.state = "upload";
592
593 // m_log.InfoFormat("[CAPS]: " +
594 // "NoteCardAgentInventory response: {0}",
595 // LLSDHelpers.SerialiseLLSDReply(uploadResponse)));
596
597 return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
598 }
599 }
600
601 public class AssetUploader
602 {
603 public event UpLoadedAsset OnUpLoad;
604 private UpLoadedAsset handlerUpLoad = null;
605
606 private string uploaderPath = String.Empty;
607 private UUID newAssetID;
608 private UUID inventoryItemID;
609 private UUID parentFolder;
610 private IHttpServer httpListener;
611 private bool m_dumpAssetsToFile;
612 private string m_assetName = String.Empty;
613 private string m_assetDes = String.Empty;
614
615 private string m_invType = String.Empty;
616 private string m_assetType = String.Empty;
617
618 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
619 UUID parentFolderID, string invType, string assetType, string path,
620 IHttpServer httpServer, bool dumpAssetsToFile)
621 {
622 m_assetName = assetName;
623 m_assetDes = description;
624 newAssetID = assetID;
625 inventoryItemID = inventoryItem;
626 uploaderPath = path;
627 httpListener = httpServer;
628 parentFolder = parentFolderID;
629 m_assetType = assetType;
630 m_invType = invType;
631 m_dumpAssetsToFile = dumpAssetsToFile;
632 }
633
634 /// <summary>
635 ///
636 /// </summary>
637 /// <param name="data"></param>
638 /// <param name="path"></param>
639 /// <param name="param"></param>
640 /// <returns></returns>
641 public string uploaderCaps(byte[] data, string path, string param)
642 {
643 UUID inv = inventoryItemID;
644 string res = String.Empty;
645 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
646 uploadComplete.new_asset = newAssetID.ToString();
647 uploadComplete.new_inventory_item = inv;
648 uploadComplete.state = "complete";
649
650 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
651
652 httpListener.RemoveStreamHandler("POST", uploaderPath);
653
654 // TODO: probably make this a better set of extensions here
655 string extension = ".jp2";
656 if (m_invType != "image")
657 {
658 extension = ".dat";
659 }
660
661 if (m_dumpAssetsToFile)
662 {
663 SaveAssetToFile(m_assetName + extension, data);
664 }
665 handlerUpLoad = OnUpLoad;
666 if (handlerUpLoad != null)
667 {
668 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType);
669 }
670
671 return res;
672 }
673 ///Left this in and commented in case there are unforseen issues
674 //private void SaveAssetToFile(string filename, byte[] data)
675 //{
676 // FileStream fs = File.Create(filename);
677 // BinaryWriter bw = new BinaryWriter(fs);
678 // bw.Write(data);
679 // bw.Close();
680 // fs.Close();
681 //}
682 private static void SaveAssetToFile(string filename, byte[] data)
683 {
684 string assetPath = "UserAssets";
685 if (!Directory.Exists(assetPath))
686 {
687 Directory.CreateDirectory(assetPath);
688 }
689 FileStream fs = File.Create(Path.Combine(assetPath, Util.safeFileName(filename)));
690 BinaryWriter bw = new BinaryWriter(fs);
691 bw.Write(data);
692 bw.Close();
693 fs.Close();
694 }
695 }
696
697 /// <summary>
698 /// This class is a callback invoked when a client sends asset data to
699 /// an agent inventory notecard update url
700 /// </summary>
701 public class ItemUpdater
702 {
703 public event UpdateItem OnUpLoad;
704
705 private UpdateItem handlerUpdateItem = null;
706
707 private string uploaderPath = String.Empty;
708 private UUID inventoryItemID;
709 private IHttpServer httpListener;
710 private bool m_dumpAssetToFile;
711
712 public ItemUpdater(UUID inventoryItem, string path, IHttpServer httpServer, bool dumpAssetToFile)
713 {
714 m_dumpAssetToFile = dumpAssetToFile;
715
716 inventoryItemID = inventoryItem;
717 uploaderPath = path;
718 httpListener = httpServer;
719 }
720
721 /// <summary>
722 ///
723 /// </summary>
724 /// <param name="data"></param>
725 /// <param name="path"></param>
726 /// <param name="param"></param>
727 /// <returns></returns>
728 public string uploaderCaps(byte[] data, string path, string param)
729 {
730 UUID inv = inventoryItemID;
731 string res = String.Empty;
732 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
733 UUID assetID = UUID.Zero;
734 handlerUpdateItem = OnUpLoad;
735 if (handlerUpdateItem != null)
736 {
737 assetID = handlerUpdateItem(inv, data);
738 }
739
740 uploadComplete.new_asset = assetID.ToString();
741 uploadComplete.new_inventory_item = inv;
742 uploadComplete.state = "complete";
743
744 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
745
746 httpListener.RemoveStreamHandler("POST", uploaderPath);
747
748 if (m_dumpAssetToFile)
749 {
750 SaveAssetToFile("updateditem" + Util.RandomClass.Next(1, 1000) + ".dat", data);
751 }
752
753 return res;
754 }
755 ///Left this in and commented in case there are unforseen issues
756 //private void SaveAssetToFile(string filename, byte[] data)
757 //{
758 // FileStream fs = File.Create(filename);
759 // BinaryWriter bw = new BinaryWriter(fs);
760 // bw.Write(data);
761 // bw.Close();
762 // fs.Close();
763 //}
764 private static void SaveAssetToFile(string filename, byte[] data)
765 {
766 string assetPath = "UserAssets";
767 if (!Directory.Exists(assetPath))
768 {
769 Directory.CreateDirectory(assetPath);
770 }
771 FileStream fs = File.Create(Path.Combine(assetPath, filename));
772 BinaryWriter bw = new BinaryWriter(fs);
773 bw.Write(data);
774 bw.Close();
775 fs.Close();
776 }
777 }
778
779 /// <summary>
780 /// This class is a callback invoked when a client sends asset data to
781 /// a task inventory script update url
782 /// </summary>
783 public class TaskInventoryScriptUpdater
784 {
785 private static readonly ILog m_log =
786 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
787
788 public event UpdateTaskScript OnUpLoad;
789
790 private UpdateTaskScript handlerUpdateTaskScript = null;
791
792 private string uploaderPath = String.Empty;
793 private UUID inventoryItemID;
794 private UUID primID;
795 private bool isScriptRunning;
796 private IHttpServer httpListener;
797 private bool m_dumpAssetToFile;
798
799 public TaskInventoryScriptUpdater(UUID inventoryItemID, UUID primID, int isScriptRunning,
800 string path, IHttpServer httpServer, bool dumpAssetToFile)
801 {
802 m_dumpAssetToFile = dumpAssetToFile;
803
804 this.inventoryItemID = inventoryItemID;
805 this.primID = primID;
806
807 // This comes in over the packet as an integer, but actually appears to be treated as a bool
808 this.isScriptRunning = (0 == isScriptRunning ? false : true);
809
810 uploaderPath = path;
811 httpListener = httpServer;
812 }
813
814 /// <summary>
815 ///
816 /// </summary>
817 /// <param name="data"></param>
818 /// <param name="path"></param>
819 /// <param name="param"></param>
820 /// <returns></returns>
821 public string uploaderCaps(byte[] data, string path, string param)
822 {
823 try
824 {
825 // m_log.InfoFormat("[CAPS]: " +
826 // "TaskInventoryScriptUpdater received data: {0}, path: {1}, param: {2}",
827 // data, path, param));
828
829 string res = String.Empty;
830 LLSDTaskScriptUploadComplete uploadComplete = new LLSDTaskScriptUploadComplete();
831
832 ArrayList errors = new ArrayList();
833 handlerUpdateTaskScript = OnUpLoad;
834 if (handlerUpdateTaskScript != null)
835 {
836 handlerUpdateTaskScript(inventoryItemID, primID, isScriptRunning, data, ref errors);
837 }
838
839 uploadComplete.new_asset = inventoryItemID;
840 uploadComplete.compiled = errors.Count > 0 ? false : true;
841 uploadComplete.state = "complete";
842 uploadComplete.errors = new OSDArray();
843 uploadComplete.errors.Array = errors;
844
845 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
846
847 httpListener.RemoveStreamHandler("POST", uploaderPath);
848
849 if (m_dumpAssetToFile)
850 {
851 SaveAssetToFile("updatedtaskscript" + Util.RandomClass.Next(1, 1000) + ".dat", data);
852 }
853
854 // m_log.InfoFormat("[CAPS]: TaskInventoryScriptUpdater.uploaderCaps res: {0}", res);
855
856 return res;
857 }
858 catch (Exception e)
859 {
860 m_log.Error("[CAPS]: " + e.ToString());
861 }
862
863 // XXX Maybe this should be some meaningful error packet
864 return null;
865 }
866 ///Left this in and commented in case there are unforseen issues
867 //private void SaveAssetToFile(string filename, byte[] data)
868 //{
869 // FileStream fs = File.Create(filename);
870 // BinaryWriter bw = new BinaryWriter(fs);
871 // bw.Write(data);
872 // bw.Close();
873 // fs.Close();
874 //}
875 private static void SaveAssetToFile(string filename, byte[] data)
876 {
877 string assetPath = "UserAssets";
878 if (!Directory.Exists(assetPath))
879 {
880 Directory.CreateDirectory(assetPath);
881 }
882 FileStream fs = File.Create(Path.Combine(assetPath, filename));
883 BinaryWriter bw = new BinaryWriter(fs);
884 bw.Write(data);
885 bw.Close();
886 fs.Close();
887 }
888 }
889
890 public class BakedTextureUploader
891 {
892 public event UploadedBakedTexture OnUpLoad;
893 private UploadedBakedTexture handlerUpLoad = null;
894
895 private string uploaderPath = String.Empty;
896 private UUID newAssetID;
897 private IHttpServer httpListener;
898
899 public BakedTextureUploader(string path, IHttpServer httpServer)
900 {
901 newAssetID = UUID.Random();
902 uploaderPath = path;
903 httpListener = httpServer;
904 // m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID);
905 }
906
907 /// <summary>
908 ///
909 /// </summary>
910 /// <param name="data"></param>
911 /// <param name="path"></param>
912 /// <param name="param"></param>
913 /// <returns></returns>
914 public string uploaderCaps(byte[] data, string path, string param)
915 {
916 handlerUpLoad = OnUpLoad;
917 if (handlerUpLoad != null)
918 {
919 Util.FireAndForget(delegate(object o) { handlerUpLoad(newAssetID, data); });
920 }
921
922 string res = String.Empty;
923 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
924 uploadComplete.new_asset = newAssetID.ToString();
925 uploadComplete.new_inventory_item = UUID.Zero;
926 uploadComplete.state = "complete";
927
928 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
929
930 httpListener.RemoveStreamHandler("POST", uploaderPath);
931
932 // m_log.InfoFormat("[CAPS] baked texture upload completed for {0}",newAssetID);
933
934 return res;
935 }
936 }
937
938}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs
new file mode 100644
index 0000000..14160ae
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs
@@ -0,0 +1,91 @@
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.Reflection;
31
32using log4net;
33using Nini.Config;
34using OpenMetaverse;
35using Mono.Addins;
36
37using OpenSim.Framework;
38using OpenSim.Region.Framework;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41using Caps = OpenSim.Framework.Capabilities.Caps;
42
43[assembly: Addin("LindenCaps", "0.1")]
44[assembly: AddinDependency("OpenSim", "0.5")]
45namespace OpenSim.Region.ClientStack.Linden
46{
47
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
49 public class BunchOfCapsModule : INonSharedRegionModule
50 {
51 private static readonly ILog m_log =
52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private Scene m_Scene;
55
56 #region INonSharedRegionModule
57
58 public string Name { get { return "BunchOfCapsModule"; } }
59
60 public Type ReplaceableInterface { get { return null; } }
61
62 public void Initialise(IConfigSource source)
63 {
64 }
65
66 public void Close() { }
67
68 public void AddRegion(Scene scene)
69 {
70 m_Scene = scene;
71 m_Scene.EventManager.OnRegisterCaps += OnRegisterCaps;
72 }
73
74 public void RemoveRegion(Scene scene)
75 {
76 }
77
78 public void RegionLoaded(Scene scene)
79 {
80 }
81
82 public void PostInitialise() { }
83 #endregion
84
85 private void OnRegisterCaps(UUID agentID, Caps caps)
86 {
87 new BunchOfCaps(m_Scene, caps);
88 }
89
90 }
91}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
new file mode 100644
index 0000000..139d8b8
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -0,0 +1,731 @@
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.Threading;
34using log4net;
35using Nini.Config;
36using Mono.Addins;
37using OpenMetaverse;
38using OpenMetaverse.Messages.Linden;
39using OpenMetaverse.Packets;
40using OpenMetaverse.StructuredData;
41using OpenSim.Framework;
42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Servers.HttpServer;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes;
46using BlockingLLSDQueue = OpenSim.Framework.BlockingQueue<OpenMetaverse.StructuredData.OSD>;
47using Caps=OpenSim.Framework.Capabilities.Caps;
48
49namespace OpenSim.Region.ClientStack.Linden
50{
51 public struct QueueItem
52 {
53 public int id;
54 public OSDMap body;
55 }
56
57 //[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
58 public class EventQueueGetModule : IEventQueue, IRegionModule
59 {
60 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61 protected Scene m_scene = null;
62 private IConfigSource m_gConfig;
63 bool enabledYN = false;
64
65 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
66
67 private Dictionary<UUID, Queue<OSD>> queues = new Dictionary<UUID, Queue<OSD>>();
68 private Dictionary<UUID, UUID> m_QueueUUIDAvatarMapping = new Dictionary<UUID, UUID>();
69 private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>();
70
71 #region IRegionModule methods
72 public virtual void Initialise(Scene scene, IConfigSource config)
73 {
74 m_gConfig = config;
75
76 IConfig startupConfig = m_gConfig.Configs["Startup"];
77
78 ReadConfigAndPopulate(scene, startupConfig, "Startup");
79
80 if (enabledYN)
81 {
82 m_scene = scene;
83 scene.RegisterModuleInterface<IEventQueue>(this);
84
85 // Register fallback handler
86 // Why does EQG Fail on region crossings!
87
88 //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack);
89
90 scene.EventManager.OnNewClient += OnNewClient;
91
92 // TODO: Leaving these open, or closing them when we
93 // become a child is incorrect. It messes up TP in a big
94 // way. CAPS/EQ need to be active as long as the UDP
95 // circuit is there.
96
97 scene.EventManager.OnClientClosed += ClientClosed;
98 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
99 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
100 }
101 else
102 {
103 m_gConfig = null;
104 }
105
106 }
107
108 private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string p)
109 {
110 enabledYN = startupConfig.GetBoolean("EventQueue", true);
111 }
112
113 public void PostInitialise()
114 {
115 }
116
117 public virtual void Close()
118 {
119 }
120
121 public virtual string Name
122 {
123 get { return "EventQueueGetModule"; }
124 }
125
126 public bool IsSharedModule
127 {
128 get { return false; }
129 }
130 #endregion
131
132 /// <summary>
133 /// Always returns a valid queue
134 /// </summary>
135 /// <param name="agentId"></param>
136 /// <returns></returns>
137 private Queue<OSD> TryGetQueue(UUID agentId)
138 {
139 lock (queues)
140 {
141 if (!queues.ContainsKey(agentId))
142 {
143 /*
144 m_log.DebugFormat(
145 "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}",
146 agentId, m_scene.RegionInfo.RegionName);
147 */
148 queues[agentId] = new Queue<OSD>();
149 }
150
151 return queues[agentId];
152 }
153 }
154
155 /// <summary>
156 /// May return a null queue
157 /// </summary>
158 /// <param name="agentId"></param>
159 /// <returns></returns>
160 private Queue<OSD> GetQueue(UUID agentId)
161 {
162 lock (queues)
163 {
164 if (queues.ContainsKey(agentId))
165 {
166 return queues[agentId];
167 }
168 else
169 return null;
170 }
171 }
172
173 #region IEventQueue Members
174
175 public bool Enqueue(OSD ev, UUID avatarID)
176 {
177 //m_log.DebugFormat("[EVENTQUEUE]: Enqueuing event for {0} in region {1}", avatarID, m_scene.RegionInfo.RegionName);
178 try
179 {
180 Queue<OSD> queue = GetQueue(avatarID);
181 if (queue != null)
182 queue.Enqueue(ev);
183 }
184 catch(NullReferenceException e)
185 {
186 m_log.Error("[EVENTQUEUE] Caught exception: " + e);
187 return false;
188 }
189
190 return true;
191 }
192
193 #endregion
194
195 private void OnNewClient(IClientAPI client)
196 {
197 //client.OnLogout += ClientClosed;
198 }
199
200// private void ClientClosed(IClientAPI client)
201// {
202// ClientClosed(client.AgentId);
203// }
204
205 private void ClientClosed(UUID AgentID, Scene scene)
206 {
207 //m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", AgentID, m_scene.RegionInfo.RegionName);
208
209 int count = 0;
210 while (queues.ContainsKey(AgentID) && queues[AgentID].Count > 0 && count++ < 5)
211 {
212 Thread.Sleep(1000);
213 }
214
215 lock (queues)
216 {
217 queues.Remove(AgentID);
218 }
219 List<UUID> removeitems = new List<UUID>();
220 lock (m_AvatarQueueUUIDMapping)
221 {
222 foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
223 {
224 if (ky == AgentID)
225 {
226 removeitems.Add(ky);
227 }
228 }
229
230 foreach (UUID ky in removeitems)
231 {
232 m_AvatarQueueUUIDMapping.Remove(ky);
233 MainServer.Instance.RemovePollServiceHTTPHandler("","/CAPS/EQG/" + ky.ToString() + "/");
234 }
235
236 }
237 UUID searchval = UUID.Zero;
238
239 removeitems.Clear();
240
241 lock (m_QueueUUIDAvatarMapping)
242 {
243 foreach (UUID ky in m_QueueUUIDAvatarMapping.Keys)
244 {
245 searchval = m_QueueUUIDAvatarMapping[ky];
246
247 if (searchval == AgentID)
248 {
249 removeitems.Add(ky);
250 }
251 }
252
253 foreach (UUID ky in removeitems)
254 m_QueueUUIDAvatarMapping.Remove(ky);
255
256 }
257 }
258
259 private void MakeChildAgent(ScenePresence avatar)
260 {
261 //m_log.DebugFormat("[EVENTQUEUE]: Make Child agent {0} in region {1}.", avatar.UUID, m_scene.RegionInfo.RegionName);
262 //lock (m_ids)
263 // {
264 //if (m_ids.ContainsKey(avatar.UUID))
265 //{
266 // close the event queue.
267 //m_ids[avatar.UUID] = -1;
268 //}
269 //}
270 }
271
272 public void OnRegisterCaps(UUID agentID, Caps caps)
273 {
274 // Register an event queue for the client
275
276 //m_log.DebugFormat(
277 // "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
278 // agentID, caps, m_scene.RegionInfo.RegionName);
279
280 // Let's instantiate a Queue for this agent right now
281 TryGetQueue(agentID);
282
283 string capsBase = "/CAPS/EQG/";
284 UUID EventQueueGetUUID = UUID.Zero;
285
286 lock (m_AvatarQueueUUIDMapping)
287 {
288 // Reuse open queues. The client does!
289 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
290 {
291 //m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
292 EventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
293 }
294 else
295 {
296 EventQueueGetUUID = UUID.Random();
297 //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
298 }
299 }
300
301 lock (m_QueueUUIDAvatarMapping)
302 {
303 if (!m_QueueUUIDAvatarMapping.ContainsKey(EventQueueGetUUID))
304 m_QueueUUIDAvatarMapping.Add(EventQueueGetUUID, agentID);
305 }
306
307 lock (m_AvatarQueueUUIDMapping)
308 {
309 if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID))
310 m_AvatarQueueUUIDMapping.Add(agentID, EventQueueGetUUID);
311 }
312
313 // Register this as a caps handler
314 caps.RegisterHandler("EventQueueGet",
315 new RestHTTPHandler("POST", capsBase + EventQueueGetUUID.ToString() + "/",
316 delegate(Hashtable m_dhttpMethod)
317 {
318 return ProcessQueue(m_dhttpMethod, agentID, caps);
319 }));
320
321 // This will persist this beyond the expiry of the caps handlers
322 MainServer.Instance.AddPollServiceHTTPHandler(
323 capsBase + EventQueueGetUUID.ToString() + "/", EventQueuePoll, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID));
324
325 Random rnd = new Random(Environment.TickCount);
326 lock (m_ids)
327 {
328 if (!m_ids.ContainsKey(agentID))
329 m_ids.Add(agentID, rnd.Next(30000000));
330 }
331 }
332
333 public bool HasEvents(UUID requestID, UUID agentID)
334 {
335 // Don't use this, because of race conditions at agent closing time
336 //Queue<OSD> queue = TryGetQueue(agentID);
337
338 Queue<OSD> queue = GetQueue(agentID);
339 if (queue != null)
340 lock (queue)
341 {
342 if (queue.Count > 0)
343 return true;
344 else
345 return false;
346 }
347 return false;
348 }
349
350 public Hashtable GetEvents(UUID requestID, UUID pAgentId, string request)
351 {
352 Queue<OSD> queue = TryGetQueue(pAgentId);
353 OSD element;
354 lock (queue)
355 {
356 if (queue.Count == 0)
357 return NoEvents(requestID, pAgentId);
358 element = queue.Dequeue(); // 15s timeout
359 }
360
361
362
363 int thisID = 0;
364 lock (m_ids)
365 thisID = m_ids[pAgentId];
366
367 OSDArray array = new OSDArray();
368 if (element == null) // didn't have an event in 15s
369 {
370 // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
371 array.Add(EventQueueHelper.KeepAliveEvent());
372 //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", pAgentId, m_scene.RegionInfo.RegionName);
373 }
374 else
375 {
376 array.Add(element);
377 lock (queue)
378 {
379 while (queue.Count > 0)
380 {
381 array.Add(queue.Dequeue());
382 thisID++;
383 }
384 }
385 }
386
387 OSDMap events = new OSDMap();
388 events.Add("events", array);
389
390 events.Add("id", new OSDInteger(thisID));
391 lock (m_ids)
392 {
393 m_ids[pAgentId] = thisID + 1;
394 }
395 Hashtable responsedata = new Hashtable();
396 responsedata["int_response_code"] = 200;
397 responsedata["content_type"] = "application/xml";
398 responsedata["keepalive"] = false;
399 responsedata["reusecontext"] = false;
400 responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
401 //m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", pAgentId, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
402 return responsedata;
403 }
404
405 public Hashtable NoEvents(UUID requestID, UUID agentID)
406 {
407 Hashtable responsedata = new Hashtable();
408 responsedata["int_response_code"] = 502;
409 responsedata["content_type"] = "text/plain";
410 responsedata["keepalive"] = false;
411 responsedata["reusecontext"] = false;
412 responsedata["str_response_string"] = "Upstream error: ";
413 responsedata["error_status_text"] = "Upstream error:";
414 responsedata["http_protocol_version"] = "HTTP/1.0";
415 return responsedata;
416 }
417
418 public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps)
419 {
420 // TODO: this has to be redone to not busy-wait (and block the thread),
421 // TODO: as soon as we have a non-blocking way to handle HTTP-requests.
422
423// if (m_log.IsDebugEnabled)
424// {
425// String debug = "[EVENTQUEUE]: Got request for agent {0} in region {1} from thread {2}: [ ";
426// foreach (object key in request.Keys)
427// {
428// debug += key.ToString() + "=" + request[key].ToString() + " ";
429// }
430// m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name);
431// }
432
433 Queue<OSD> queue = TryGetQueue(agentID);
434 OSD element = queue.Dequeue(); // 15s timeout
435
436 Hashtable responsedata = new Hashtable();
437
438 int thisID = 0;
439 lock (m_ids)
440 thisID = m_ids[agentID];
441
442 if (element == null)
443 {
444 //m_log.ErrorFormat("[EVENTQUEUE]: Nothing to process in " + m_scene.RegionInfo.RegionName);
445 if (thisID == -1) // close-request
446 {
447 m_log.ErrorFormat("[EVENTQUEUE]: 404 in " + m_scene.RegionInfo.RegionName);
448 responsedata["int_response_code"] = 404; //501; //410; //404;
449 responsedata["content_type"] = "text/plain";
450 responsedata["keepalive"] = false;
451 responsedata["str_response_string"] = "Closed EQG";
452 return responsedata;
453 }
454 responsedata["int_response_code"] = 502;
455 responsedata["content_type"] = "text/plain";
456 responsedata["keepalive"] = false;
457 responsedata["str_response_string"] = "Upstream error: ";
458 responsedata["error_status_text"] = "Upstream error:";
459 responsedata["http_protocol_version"] = "HTTP/1.0";
460 return responsedata;
461 }
462
463 OSDArray array = new OSDArray();
464 if (element == null) // didn't have an event in 15s
465 {
466 // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
467 array.Add(EventQueueHelper.KeepAliveEvent());
468 //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
469 }
470 else
471 {
472 array.Add(element);
473 while (queue.Count > 0)
474 {
475 array.Add(queue.Dequeue());
476 thisID++;
477 }
478 }
479
480 OSDMap events = new OSDMap();
481 events.Add("events", array);
482
483 events.Add("id", new OSDInteger(thisID));
484 lock (m_ids)
485 {
486 m_ids[agentID] = thisID + 1;
487 }
488
489 responsedata["int_response_code"] = 200;
490 responsedata["content_type"] = "application/xml";
491 responsedata["keepalive"] = false;
492 responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
493 //m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
494
495 return responsedata;
496 }
497
498 public Hashtable EventQueuePoll(Hashtable request)
499 {
500 return new Hashtable();
501 }
502
503 public Hashtable EventQueuePath2(Hashtable request)
504 {
505 string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/","");
506 // pull off the last "/" in the path.
507 Hashtable responsedata = new Hashtable();
508 capuuid = capuuid.Substring(0, capuuid.Length - 1);
509 capuuid = capuuid.Replace("/CAPS/EQG/", "");
510 UUID AvatarID = UUID.Zero;
511 UUID capUUID = UUID.Zero;
512
513 // parse the path and search for the avatar with it registered
514 if (UUID.TryParse(capuuid, out capUUID))
515 {
516 lock (m_QueueUUIDAvatarMapping)
517 {
518 if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
519 {
520 AvatarID = m_QueueUUIDAvatarMapping[capUUID];
521 }
522 }
523 if (AvatarID != UUID.Zero)
524 {
525 return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsForUser(AvatarID));
526 }
527 else
528 {
529 responsedata["int_response_code"] = 404;
530 responsedata["content_type"] = "text/plain";
531 responsedata["keepalive"] = false;
532 responsedata["str_response_string"] = "Not Found";
533 responsedata["error_status_text"] = "Not Found";
534 responsedata["http_protocol_version"] = "HTTP/1.0";
535 return responsedata;
536 // return 404
537 }
538 }
539 else
540 {
541 responsedata["int_response_code"] = 404;
542 responsedata["content_type"] = "text/plain";
543 responsedata["keepalive"] = false;
544 responsedata["str_response_string"] = "Not Found";
545 responsedata["error_status_text"] = "Not Found";
546 responsedata["http_protocol_version"] = "HTTP/1.0";
547 return responsedata;
548 // return 404
549 }
550
551 }
552
553 public OSD EventQueueFallBack(string path, OSD request, string endpoint)
554 {
555 // This is a fallback element to keep the client from loosing EventQueueGet
556 // Why does CAPS fail sometimes!?
557 m_log.Warn("[EVENTQUEUE]: In the Fallback handler! We lost the Queue in the rest handler!");
558 string capuuid = path.Replace("/CAPS/EQG/","");
559 capuuid = capuuid.Substring(0, capuuid.Length - 1);
560
561// UUID AvatarID = UUID.Zero;
562 UUID capUUID = UUID.Zero;
563 if (UUID.TryParse(capuuid, out capUUID))
564 {
565/* Don't remove this yet code cleaners!
566 * Still testing this!
567 *
568 lock (m_QueueUUIDAvatarMapping)
569 {
570 if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
571 {
572 AvatarID = m_QueueUUIDAvatarMapping[capUUID];
573 }
574 }
575
576
577 if (AvatarID != UUID.Zero)
578 {
579 // Repair the CAP!
580 //OpenSim.Framework.Capabilities.Caps caps = m_scene.GetCapsHandlerForUser(AvatarID);
581 //string capsBase = "/CAPS/EQG/";
582 //caps.RegisterHandler("EventQueueGet",
583 //new RestHTTPHandler("POST", capsBase + capUUID.ToString() + "/",
584 //delegate(Hashtable m_dhttpMethod)
585 //{
586 // return ProcessQueue(m_dhttpMethod, AvatarID, caps);
587 //}));
588 // start new ID sequence.
589 Random rnd = new Random(System.Environment.TickCount);
590 lock (m_ids)
591 {
592 if (!m_ids.ContainsKey(AvatarID))
593 m_ids.Add(AvatarID, rnd.Next(30000000));
594 }
595
596
597 int thisID = 0;
598 lock (m_ids)
599 thisID = m_ids[AvatarID];
600
601 BlockingLLSDQueue queue = GetQueue(AvatarID);
602 OSDArray array = new OSDArray();
603 LLSD element = queue.Dequeue(15000); // 15s timeout
604 if (element == null)
605 {
606
607 array.Add(EventQueueHelper.KeepAliveEvent());
608 }
609 else
610 {
611 array.Add(element);
612 while (queue.Count() > 0)
613 {
614 array.Add(queue.Dequeue(1));
615 thisID++;
616 }
617 }
618 OSDMap events = new OSDMap();
619 events.Add("events", array);
620
621 events.Add("id", new LLSDInteger(thisID));
622
623 lock (m_ids)
624 {
625 m_ids[AvatarID] = thisID + 1;
626 }
627
628 return events;
629 }
630 else
631 {
632 return new LLSD();
633 }
634*
635*/
636 }
637 else
638 {
639 //return new LLSD();
640 }
641
642 return new OSDString("shutdown404!");
643 }
644
645 public void DisableSimulator(ulong handle, UUID avatarID)
646 {
647 OSD item = EventQueueHelper.DisableSimulator(handle);
648 Enqueue(item, avatarID);
649 }
650
651 public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID)
652 {
653 OSD item = EventQueueHelper.EnableSimulator(handle, endPoint);
654 Enqueue(item, avatarID);
655 }
656
657 public virtual void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath)
658 {
659 OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath);
660 Enqueue(item, avatarID);
661 }
662
663 public virtual void TeleportFinishEvent(ulong regionHandle, byte simAccess,
664 IPEndPoint regionExternalEndPoint,
665 uint locationID, uint flags, string capsURL,
666 UUID avatarID)
667 {
668 OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint,
669 locationID, flags, capsURL, avatarID);
670 Enqueue(item, avatarID);
671 }
672
673 public virtual void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
674 IPEndPoint newRegionExternalEndPoint,
675 string capsURL, UUID avatarID, UUID sessionID)
676 {
677 OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint,
678 capsURL, avatarID, sessionID);
679 Enqueue(item, avatarID);
680 }
681
682 public void ChatterboxInvitation(UUID sessionID, string sessionName,
683 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
684 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
685 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
686 {
687 OSD item = EventQueueHelper.ChatterboxInvitation(sessionID, sessionName, fromAgent, message, toAgent, fromName, dialog,
688 timeStamp, offline, parentEstateID, position, ttl, transactionID,
689 fromGroup, binaryBucket);
690 Enqueue(item, toAgent);
691 //m_log.InfoFormat("########### eq ChatterboxInvitation #############\n{0}", item);
692
693 }
694
695 public void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat,
696 bool isModerator, bool textMute)
697 {
698 OSD item = EventQueueHelper.ChatterBoxSessionAgentListUpdates(sessionID, fromAgent, canVoiceChat,
699 isModerator, textMute);
700 Enqueue(item, toAgent);
701 //m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item);
702 }
703
704 public void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID)
705 {
706 OSD item = EventQueueHelper.ParcelProperties(parcelPropertiesMessage);
707 Enqueue(item, avatarID);
708 }
709
710 public void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID)
711 {
712 OSD item = EventQueueHelper.GroupMembership(groupUpdate);
713 Enqueue(item, avatarID);
714 }
715 public void QueryReply(PlacesReplyPacket groupUpdate, UUID avatarID)
716 {
717 OSD item = EventQueueHelper.PlacesQuery(groupUpdate);
718 Enqueue(item, avatarID);
719 }
720
721 public OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono)
722 {
723 return EventQueueHelper.ScriptRunningReplyEvent(objectID, itemID, running, mono);
724 }
725
726 public OSD BuildEvent(string eventName, OSD eventBody)
727 {
728 return EventQueueHelper.BuildEvent(eventName, eventBody);
729 }
730 }
731}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
new file mode 100644
index 0000000..3f49aba
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
@@ -0,0 +1,399 @@
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.Net;
30using OpenMetaverse;
31using OpenMetaverse.Packets;
32using OpenMetaverse.StructuredData;
33using OpenMetaverse.Messages.Linden;
34
35namespace OpenSim.Region.ClientStack.Linden
36{
37 public class EventQueueHelper
38 {
39 private EventQueueHelper() {} // no construction possible, it's an utility class
40
41 private static byte[] ulongToByteArray(ulong uLongValue)
42 {
43 // Reverse endianness of RegionHandle
44 return new byte[]
45 {
46 (byte)((uLongValue >> 56) % 256),
47 (byte)((uLongValue >> 48) % 256),
48 (byte)((uLongValue >> 40) % 256),
49 (byte)((uLongValue >> 32) % 256),
50 (byte)((uLongValue >> 24) % 256),
51 (byte)((uLongValue >> 16) % 256),
52 (byte)((uLongValue >> 8) % 256),
53 (byte)(uLongValue % 256)
54 };
55 }
56
57// private static byte[] uintToByteArray(uint uIntValue)
58// {
59// byte[] result = new byte[4];
60// Utils.UIntToBytesBig(uIntValue, result, 0);
61// return result;
62// }
63
64 public static OSD BuildEvent(string eventName, OSD eventBody)
65 {
66 OSDMap llsdEvent = new OSDMap(2);
67 llsdEvent.Add("message", new OSDString(eventName));
68 llsdEvent.Add("body", eventBody);
69
70 return llsdEvent;
71 }
72
73 public static OSD EnableSimulator(ulong handle, IPEndPoint endPoint)
74 {
75 OSDMap llsdSimInfo = new OSDMap(3);
76
77 llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle)));
78 llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes()));
79 llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port));
80
81 OSDArray arr = new OSDArray(1);
82 arr.Add(llsdSimInfo);
83
84 OSDMap llsdBody = new OSDMap(1);
85 llsdBody.Add("SimulatorInfo", arr);
86
87 return BuildEvent("EnableSimulator", llsdBody);
88 }
89
90 public static OSD DisableSimulator(ulong handle)
91 {
92 //OSDMap llsdSimInfo = new OSDMap(1);
93
94 //llsdSimInfo.Add("Handle", new OSDBinary(regionHandleToByteArray(handle)));
95
96 //OSDArray arr = new OSDArray(1);
97 //arr.Add(llsdSimInfo);
98
99 OSDMap llsdBody = new OSDMap(0);
100 //llsdBody.Add("SimulatorInfo", arr);
101
102 return BuildEvent("DisableSimulator", llsdBody);
103 }
104
105 public static OSD CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
106 IPEndPoint newRegionExternalEndPoint,
107 string capsURL, UUID agentID, UUID sessionID)
108 {
109 OSDArray lookAtArr = new OSDArray(3);
110 lookAtArr.Add(OSD.FromReal(lookAt.X));
111 lookAtArr.Add(OSD.FromReal(lookAt.Y));
112 lookAtArr.Add(OSD.FromReal(lookAt.Z));
113
114 OSDArray positionArr = new OSDArray(3);
115 positionArr.Add(OSD.FromReal(pos.X));
116 positionArr.Add(OSD.FromReal(pos.Y));
117 positionArr.Add(OSD.FromReal(pos.Z));
118
119 OSDMap infoMap = new OSDMap(2);
120 infoMap.Add("LookAt", lookAtArr);
121 infoMap.Add("Position", positionArr);
122
123 OSDArray infoArr = new OSDArray(1);
124 infoArr.Add(infoMap);
125
126 OSDMap agentDataMap = new OSDMap(2);
127 agentDataMap.Add("AgentID", OSD.FromUUID(agentID));
128 agentDataMap.Add("SessionID", OSD.FromUUID(sessionID));
129
130 OSDArray agentDataArr = new OSDArray(1);
131 agentDataArr.Add(agentDataMap);
132
133 OSDMap regionDataMap = new OSDMap(4);
134 regionDataMap.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(handle)));
135 regionDataMap.Add("SeedCapability", OSD.FromString(capsURL));
136 regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes()));
137 regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port));
138
139 OSDArray regionDataArr = new OSDArray(1);
140 regionDataArr.Add(regionDataMap);
141
142 OSDMap llsdBody = new OSDMap(3);
143 llsdBody.Add("Info", infoArr);
144 llsdBody.Add("AgentData", agentDataArr);
145 llsdBody.Add("RegionData", regionDataArr);
146
147 return BuildEvent("CrossedRegion", llsdBody);
148 }
149
150 public static OSD TeleportFinishEvent(
151 ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
152 uint locationID, uint flags, string capsURL, UUID agentID)
153 {
154 OSDMap info = new OSDMap();
155 info.Add("AgentID", OSD.FromUUID(agentID));
156 info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this?
157 info.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(regionHandle)));
158 info.Add("SeedCapability", OSD.FromString(capsURL));
159 info.Add("SimAccess", OSD.FromInteger(simAccess));
160 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes()));
161 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port));
162 info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation
163
164 OSDArray infoArr = new OSDArray();
165 infoArr.Add(info);
166
167 OSDMap body = new OSDMap();
168 body.Add("Info", infoArr);
169
170 return BuildEvent("TeleportFinish", body);
171 }
172
173 public static OSD ScriptRunningReplyEvent(UUID objectID, UUID itemID, bool running, bool mono)
174 {
175 OSDMap script = new OSDMap();
176 script.Add("ObjectID", OSD.FromUUID(objectID));
177 script.Add("ItemID", OSD.FromUUID(itemID));
178 script.Add("Running", OSD.FromBoolean(running));
179 script.Add("Mono", OSD.FromBoolean(mono));
180
181 OSDArray scriptArr = new OSDArray();
182 scriptArr.Add(script);
183
184 OSDMap body = new OSDMap();
185 body.Add("Script", scriptArr);
186
187 return BuildEvent("ScriptRunningReply", body);
188 }
189
190 public static OSD EstablishAgentCommunication(UUID agentID, string simIpAndPort, string seedcap)
191 {
192 OSDMap body = new OSDMap(3);
193 body.Add("agent-id", new OSDUUID(agentID));
194 body.Add("sim-ip-and-port", new OSDString(simIpAndPort));
195 body.Add("seed-capability", new OSDString(seedcap));
196
197 return BuildEvent("EstablishAgentCommunication", body);
198 }
199
200 public static OSD KeepAliveEvent()
201 {
202 return BuildEvent("FAKEEVENT", new OSDMap());
203 }
204
205 public static OSD AgentParams(UUID agentID, bool checkEstate, int godLevel, bool limitedToEstate)
206 {
207 OSDMap body = new OSDMap(4);
208
209 body.Add("agent_id", new OSDUUID(agentID));
210 body.Add("check_estate", new OSDInteger(checkEstate ? 1 : 0));
211 body.Add("god_level", new OSDInteger(godLevel));
212 body.Add("limited_to_estate", new OSDInteger(limitedToEstate ? 1 : 0));
213
214 return body;
215 }
216
217 public static OSD InstantMessageParams(UUID fromAgent, string message, UUID toAgent,
218 string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID,
219 Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
220 {
221 OSDMap messageParams = new OSDMap(15);
222 messageParams.Add("type", new OSDInteger((int)dialog));
223
224 OSDArray positionArray = new OSDArray(3);
225 positionArray.Add(OSD.FromReal(position.X));
226 positionArray.Add(OSD.FromReal(position.Y));
227 positionArray.Add(OSD.FromReal(position.Z));
228 messageParams.Add("position", positionArray);
229
230 messageParams.Add("region_id", new OSDUUID(UUID.Zero));
231 messageParams.Add("to_id", new OSDUUID(toAgent));
232 messageParams.Add("source", new OSDInteger(0));
233
234 OSDMap data = new OSDMap(1);
235 data.Add("binary_bucket", OSD.FromBinary(binaryBucket));
236 messageParams.Add("data", data);
237 messageParams.Add("message", new OSDString(message));
238 messageParams.Add("id", new OSDUUID(transactionID));
239 messageParams.Add("from_name", new OSDString(fromName));
240 messageParams.Add("timestamp", new OSDInteger((int)timeStamp));
241 messageParams.Add("offline", new OSDInteger(offline ? 1 : 0));
242 messageParams.Add("parent_estate_id", new OSDInteger(parentEstateID));
243 messageParams.Add("ttl", new OSDInteger((int)ttl));
244 messageParams.Add("from_id", new OSDUUID(fromAgent));
245 messageParams.Add("from_group", new OSDInteger(fromGroup ? 1 : 0));
246
247 return messageParams;
248 }
249
250 public static OSD InstantMessage(UUID fromAgent, string message, UUID toAgent,
251 string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID,
252 Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket,
253 bool checkEstate, int godLevel, bool limitedToEstate)
254 {
255 OSDMap im = new OSDMap(2);
256 im.Add("message_params", InstantMessageParams(fromAgent, message, toAgent,
257 fromName, dialog, timeStamp, offline, parentEstateID,
258 position, ttl, transactionID, fromGroup, binaryBucket));
259
260 im.Add("agent_params", AgentParams(fromAgent, checkEstate, godLevel, limitedToEstate));
261
262 return im;
263 }
264
265
266 public static OSD ChatterboxInvitation(UUID sessionID, string sessionName,
267 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
268 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
269 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
270 {
271 OSDMap body = new OSDMap(5);
272 body.Add("session_id", new OSDUUID(sessionID));
273 body.Add("from_name", new OSDString(fromName));
274 body.Add("session_name", new OSDString(sessionName));
275 body.Add("from_id", new OSDUUID(fromAgent));
276
277 body.Add("instantmessage", InstantMessage(fromAgent, message, toAgent,
278 fromName, dialog, timeStamp, offline, parentEstateID, position,
279 ttl, transactionID, fromGroup, binaryBucket, true, 0, true));
280
281 OSDMap chatterboxInvitation = new OSDMap(2);
282 chatterboxInvitation.Add("message", new OSDString("ChatterBoxInvitation"));
283 chatterboxInvitation.Add("body", body);
284 return chatterboxInvitation;
285 }
286
287 public static OSD ChatterBoxSessionAgentListUpdates(UUID sessionID,
288 UUID agentID, bool canVoiceChat, bool isModerator, bool textMute)
289 {
290 OSDMap body = new OSDMap();
291 OSDMap agentUpdates = new OSDMap();
292 OSDMap infoDetail = new OSDMap();
293 OSDMap mutes = new OSDMap();
294
295 mutes.Add("text", OSD.FromBoolean(textMute));
296 infoDetail.Add("can_voice_chat", OSD.FromBoolean(canVoiceChat));
297 infoDetail.Add("is_moderator", OSD.FromBoolean(isModerator));
298 infoDetail.Add("mutes", mutes);
299 OSDMap info = new OSDMap();
300 info.Add("info", infoDetail);
301 agentUpdates.Add(agentID.ToString(), info);
302 body.Add("agent_updates", agentUpdates);
303 body.Add("session_id", OSD.FromUUID(sessionID));
304 body.Add("updates", new OSD());
305
306 OSDMap chatterBoxSessionAgentListUpdates = new OSDMap();
307 chatterBoxSessionAgentListUpdates.Add("message", OSD.FromString("ChatterBoxSessionAgentListUpdates"));
308 chatterBoxSessionAgentListUpdates.Add("body", body);
309
310 return chatterBoxSessionAgentListUpdates;
311 }
312
313 public static OSD GroupMembership(AgentGroupDataUpdatePacket groupUpdatePacket)
314 {
315 OSDMap groupUpdate = new OSDMap();
316 groupUpdate.Add("message", OSD.FromString("AgentGroupDataUpdate"));
317
318 OSDMap body = new OSDMap();
319 OSDArray agentData = new OSDArray();
320 OSDMap agentDataMap = new OSDMap();
321 agentDataMap.Add("AgentID", OSD.FromUUID(groupUpdatePacket.AgentData.AgentID));
322 agentData.Add(agentDataMap);
323 body.Add("AgentData", agentData);
324
325 OSDArray groupData = new OSDArray();
326
327 foreach (AgentGroupDataUpdatePacket.GroupDataBlock groupDataBlock in groupUpdatePacket.GroupData)
328 {
329 OSDMap groupDataMap = new OSDMap();
330 groupDataMap.Add("ListInProfile", OSD.FromBoolean(false));
331 groupDataMap.Add("GroupID", OSD.FromUUID(groupDataBlock.GroupID));
332 groupDataMap.Add("GroupInsigniaID", OSD.FromUUID(groupDataBlock.GroupInsigniaID));
333 groupDataMap.Add("Contribution", OSD.FromInteger(groupDataBlock.Contribution));
334 groupDataMap.Add("GroupPowers", OSD.FromBinary(ulongToByteArray(groupDataBlock.GroupPowers)));
335 groupDataMap.Add("GroupName", OSD.FromString(Utils.BytesToString(groupDataBlock.GroupName)));
336 groupDataMap.Add("AcceptNotices", OSD.FromBoolean(groupDataBlock.AcceptNotices));
337
338 groupData.Add(groupDataMap);
339
340 }
341 body.Add("GroupData", groupData);
342 groupUpdate.Add("body", body);
343
344 return groupUpdate;
345 }
346
347 public static OSD PlacesQuery(PlacesReplyPacket PlacesReply)
348 {
349 OSDMap placesReply = new OSDMap();
350 placesReply.Add("message", OSD.FromString("PlacesReplyMessage"));
351
352 OSDMap body = new OSDMap();
353 OSDArray agentData = new OSDArray();
354 OSDMap agentDataMap = new OSDMap();
355 agentDataMap.Add("AgentID", OSD.FromUUID(PlacesReply.AgentData.AgentID));
356 agentDataMap.Add("QueryID", OSD.FromUUID(PlacesReply.AgentData.QueryID));
357 agentDataMap.Add("TransactionID", OSD.FromUUID(PlacesReply.TransactionData.TransactionID));
358 agentData.Add(agentDataMap);
359 body.Add("AgentData", agentData);
360
361 OSDArray QueryData = new OSDArray();
362
363 foreach (PlacesReplyPacket.QueryDataBlock groupDataBlock in PlacesReply.QueryData)
364 {
365 OSDMap QueryDataMap = new OSDMap();
366 QueryDataMap.Add("ActualArea", OSD.FromInteger(groupDataBlock.ActualArea));
367 QueryDataMap.Add("BillableArea", OSD.FromInteger(groupDataBlock.BillableArea));
368 QueryDataMap.Add("Description", OSD.FromBinary(groupDataBlock.Desc));
369 QueryDataMap.Add("Dwell", OSD.FromInteger((int)groupDataBlock.Dwell));
370 QueryDataMap.Add("Flags", OSD.FromString(Convert.ToString(groupDataBlock.Flags)));
371 QueryDataMap.Add("GlobalX", OSD.FromInteger((int)groupDataBlock.GlobalX));
372 QueryDataMap.Add("GlobalY", OSD.FromInteger((int)groupDataBlock.GlobalY));
373 QueryDataMap.Add("GlobalZ", OSD.FromInteger((int)groupDataBlock.GlobalZ));
374 QueryDataMap.Add("Name", OSD.FromBinary(groupDataBlock.Name));
375 QueryDataMap.Add("OwnerID", OSD.FromUUID(groupDataBlock.OwnerID));
376 QueryDataMap.Add("SimName", OSD.FromBinary(groupDataBlock.SimName));
377 QueryDataMap.Add("SnapShotID", OSD.FromUUID(groupDataBlock.SnapshotID));
378 QueryDataMap.Add("ProductSku", OSD.FromInteger(0));
379 QueryDataMap.Add("Price", OSD.FromInteger(groupDataBlock.Price));
380
381 QueryData.Add(QueryDataMap);
382 }
383 body.Add("QueryData", QueryData);
384 placesReply.Add("QueryData[]", body);
385
386 return placesReply;
387 }
388
389 public static OSD ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage)
390 {
391 OSDMap message = new OSDMap();
392 message.Add("message", OSD.FromString("ParcelProperties"));
393 OSD message_body = parcelPropertiesMessage.Serialize();
394 message.Add("body", message_body);
395 return message;
396 }
397
398 }
399}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
new file mode 100644
index 0000000..e0807ee
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
@@ -0,0 +1,139 @@
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.Specialized;
31using System.Reflection;
32using System.IO;
33using System.Web;
34using Mono.Addins;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Capabilities.Handlers;
40using OpenSim.Framework;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45using OpenSim.Services.Interfaces;
46using Caps = OpenSim.Framework.Capabilities.Caps;
47
48namespace OpenSim.Region.ClientStack.Linden
49{
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
51 public class GetMeshModule : INonSharedRegionModule
52 {
53 private static readonly ILog m_log =
54 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 private Scene m_scene;
57 private IAssetService m_AssetService;
58 private bool m_Enabled = true;
59 private string m_URL;
60
61 #region IRegionModuleBase Members
62
63 public Type ReplaceableInterface
64 {
65 get { return null; }
66 }
67
68 public void Initialise(IConfigSource source)
69 {
70 IConfig config = source.Configs["ClientStack.LindenCaps"];
71 if (config == null)
72 return;
73
74 m_URL = config.GetString("Cap_GetMesh", string.Empty);
75 // Cap doesn't exist
76 if (m_URL != string.Empty)
77 m_Enabled = true;
78 }
79
80 public void AddRegion(Scene pScene)
81 {
82 if (!m_Enabled)
83 return;
84
85 m_scene = pScene;
86 }
87
88 public void RemoveRegion(Scene scene)
89 {
90 if (!m_Enabled)
91 return;
92
93 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
94 m_scene = null;
95 }
96
97 public void RegionLoaded(Scene scene)
98 {
99 if (!m_Enabled)
100 return;
101
102 m_AssetService = m_scene.RequestModuleInterface<IAssetService>();
103 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
104 }
105
106
107 public void Close() { }
108
109 public string Name { get { return "GetMeshModule"; } }
110
111 #endregion
112
113
114 public void RegisterCaps(UUID agentID, Caps caps)
115 {
116 UUID capID = UUID.Random();
117
118 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture));
119 if (m_URL == "localhost")
120 {
121 m_log.InfoFormat("[GETMESH]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
122 GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService);
123 IRequestHandler reqHandler = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(),
124 delegate(Hashtable m_dhttpMethod)
125 {
126 return gmeshHandler.ProcessGetMesh(m_dhttpMethod, UUID.Zero, null);
127 });
128
129 caps.RegisterHandler("GetMesh", reqHandler);
130 }
131 else
132 {
133 m_log.InfoFormat("[GETMESH]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName);
134 caps.RegisterHandler("GetMesh", m_URL);
135 }
136 }
137
138 }
139}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
new file mode 100644
index 0000000..35eedb4
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -0,0 +1,142 @@
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.Specialized;
31using System.Drawing;
32using System.Drawing.Imaging;
33using System.Reflection;
34using System.IO;
35using System.Web;
36using log4net;
37using Nini.Config;
38using Mono.Addins;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41using OpenMetaverse.Imaging;
42using OpenSim.Framework;
43using OpenSim.Framework.Servers;
44using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes;
47using OpenSim.Services.Interfaces;
48using Caps = OpenSim.Framework.Capabilities.Caps;
49using OpenSim.Capabilities.Handlers;
50
51namespace OpenSim.Region.ClientStack.Linden
52{
53
54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
55 public class GetTextureModule : INonSharedRegionModule
56 {
57 private static readonly ILog m_log =
58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 private Scene m_scene;
60 private IAssetService m_assetService;
61
62 private bool m_Enabled = false;
63
64 // TODO: Change this to a config option
65 const string REDIRECT_URL = null;
66
67 private string m_URL;
68
69 #region ISharedRegionModule Members
70
71 public void Initialise(IConfigSource source)
72 {
73 IConfig config = source.Configs["ClientStack.LindenCaps"];
74 if (config == null)
75 return;
76
77 m_URL = config.GetString("Cap_GetTexture", string.Empty);
78 // Cap doesn't exist
79 if (m_URL != string.Empty)
80 m_Enabled = true;
81 }
82
83 public void AddRegion(Scene s)
84 {
85 if (!m_Enabled)
86 return;
87
88 m_scene = s;
89 }
90
91 public void RemoveRegion(Scene s)
92 {
93 if (!m_Enabled)
94 return;
95
96 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
97 m_scene = null;
98 }
99
100 public void RegionLoaded(Scene s)
101 {
102 if (!m_Enabled)
103 return;
104
105 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
106 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
107 }
108
109 public void PostInitialise()
110 {
111 }
112
113 public void Close() { }
114
115 public string Name { get { return "GetTextureModule"; } }
116
117 public Type ReplaceableInterface
118 {
119 get { return null; }
120 }
121
122 #endregion
123
124 public void RegisterCaps(UUID agentID, Caps caps)
125 {
126 UUID capID = UUID.Random();
127
128 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture));
129 if (m_URL == "localhost")
130 {
131 m_log.InfoFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
132 caps.RegisterHandler("GetTexture", new GetTextureHandler("/CAPS/" + capID + "/", m_assetService));
133 }
134 else
135 {
136 m_log.InfoFormat("[GETTEXTURE]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName);
137 caps.RegisterHandler("GetTexture", m_URL);
138 }
139 }
140
141 }
142}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs
new file mode 100644
index 0000000..b7e79cc
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs
@@ -0,0 +1,275 @@
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.Specialized;
31using System.Reflection;
32using System.IO;
33using System.Web;
34using Mono.Addins;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes;
44using OpenSim.Services.Interfaces;
45using Caps = OpenSim.Framework.Capabilities.Caps;
46using OpenSim.Framework.Capabilities;
47
48namespace OpenSim.Region.ClientStack.Linden
49{
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
51 public class NewFileAgentInventoryVariablePriceModule : INonSharedRegionModule
52 {
53// private static readonly ILog m_log =
54// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 private Scene m_scene;
57// private IAssetService m_assetService;
58 private bool m_dumpAssetsToFile = false;
59 private bool m_enabled = true;
60
61 #region IRegionModuleBase Members
62
63
64 public Type ReplaceableInterface
65 {
66 get { return null; }
67 }
68
69 public void Initialise(IConfigSource source)
70 {
71 IConfig meshConfig = source.Configs["Mesh"];
72 if (meshConfig == null)
73 return;
74
75 m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true);
76 }
77
78 public void AddRegion(Scene pScene)
79 {
80 m_scene = pScene;
81 }
82
83 public void RemoveRegion(Scene scene)
84 {
85
86 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
87 m_scene = null;
88 }
89
90 public void RegionLoaded(Scene scene)
91 {
92
93// m_assetService = m_scene.RequestModuleInterface<IAssetService>();
94 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
95 }
96
97 #endregion
98
99
100 #region IRegionModule Members
101
102
103
104 public void Close() { }
105
106 public string Name { get { return "NewFileAgentInventoryVariablePriceModule"; } }
107
108
109 public void RegisterCaps(UUID agentID, Caps caps)
110 {
111 if(!m_enabled)
112 return;
113
114 UUID capID = UUID.Random();
115
116// m_log.Debug("[NEW FILE AGENT INVENTORY VARIABLE PRICE]: /CAPS/" + capID);
117 caps.RegisterHandler("NewFileAgentInventoryVariablePrice",
118
119 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDNewFileAngentInventoryVariablePriceReplyResponse>("POST",
120 "/CAPS/" + capID.ToString(),
121 delegate(LLSDAssetUploadRequest req)
122 {
123 return NewAgentInventoryRequest(req,agentID);
124 }));
125
126 }
127
128 #endregion
129
130 public LLSDNewFileAngentInventoryVariablePriceReplyResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest, UUID agentID)
131 {
132
133 //TODO: The Mesh uploader uploads many types of content. If you're going to implement a Money based limit
134 // You need to be aware of this and
135
136
137 //if (llsdRequest.asset_type == "texture" ||
138 // llsdRequest.asset_type == "animation" ||
139 // llsdRequest.asset_type == "sound")
140 // {
141 IClientAPI client = null;
142
143
144 IMoneyModule mm = m_scene.RequestModuleInterface<IMoneyModule>();
145
146 if (mm != null)
147 {
148 if (m_scene.TryGetClient(agentID, out client))
149 {
150 if (!mm.UploadCovered(client, mm.UploadCharge))
151 {
152 if (client != null)
153 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
154
155 LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
156 errorResponse.rsvp = "";
157 errorResponse.state = "error";
158 return errorResponse;
159 }
160 }
161 }
162 // }
163
164
165
166 string assetName = llsdRequest.name;
167 string assetDes = llsdRequest.description;
168 string capsBase = "/CAPS/NewFileAgentInventoryVariablePrice/";
169 UUID newAsset = UUID.Random();
170 UUID newInvItem = UUID.Random();
171 UUID parentFolder = llsdRequest.folder_id;
172 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000") + "/";
173
174 AssetUploader uploader =
175 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
176 llsdRequest.asset_type, capsBase + uploaderPath, MainServer.Instance, m_dumpAssetsToFile);
177 MainServer.Instance.AddStreamHandler(
178 new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
179
180 string protocol = "http://";
181
182 if (MainServer.Instance.UseSSL)
183 protocol = "https://";
184
185 string uploaderURL = protocol + m_scene.RegionInfo.ExternalHostName + ":" + MainServer.Instance.Port.ToString() + capsBase +
186 uploaderPath;
187
188
189 LLSDNewFileAngentInventoryVariablePriceReplyResponse uploadResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
190
191
192 uploadResponse.rsvp = uploaderURL;
193 uploadResponse.state = "upload";
194 uploadResponse.resource_cost = 0;
195 uploadResponse.upload_price = 0;
196
197 uploader.OnUpLoad += //UploadCompleteHandler;
198
199 delegate(
200 string passetName, string passetDescription, UUID passetID,
201 UUID pinventoryItem, UUID pparentFolder, byte[] pdata, string pinventoryType,
202 string passetType)
203 {
204 UploadCompleteHandler(passetName, passetDescription, passetID,
205 pinventoryItem, pparentFolder, pdata, pinventoryType,
206 passetType,agentID);
207 };
208 return uploadResponse;
209 }
210
211
212 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
213 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
214 string assetType,UUID AgentID)
215 {
216
217 sbyte assType = 0;
218 sbyte inType = 0;
219
220 if (inventoryType == "sound")
221 {
222 inType = 1;
223 assType = 1;
224 }
225 else if (inventoryType == "animation")
226 {
227 inType = 19;
228 assType = 20;
229 }
230 else if (inventoryType == "wearable")
231 {
232 inType = 18;
233 switch (assetType)
234 {
235 case "bodypart":
236 assType = 13;
237 break;
238 case "clothing":
239 assType = 5;
240 break;
241 }
242 }
243 else if (inventoryType == "mesh")
244 {
245 inType = (sbyte)InventoryType.Mesh;
246 assType = (sbyte)AssetType.Mesh;
247 }
248
249 AssetBase asset;
250 asset = new AssetBase(assetID, assetName, assType, AgentID.ToString());
251 asset.Data = data;
252
253 if (m_scene.AssetService != null)
254 m_scene.AssetService.Store(asset);
255
256 InventoryItemBase item = new InventoryItemBase();
257 item.Owner = AgentID;
258 item.CreatorId = AgentID.ToString();
259 item.ID = inventoryItem;
260 item.AssetID = asset.FullID;
261 item.Description = assetDescription;
262 item.Name = assetName;
263 item.AssetType = assType;
264 item.InvType = inType;
265 item.Folder = parentFolder;
266 item.CurrentPermissions = (uint)PermissionMask.All;
267 item.BasePermissions = (uint)PermissionMask.All;
268 item.EveryOnePermissions = 0;
269 item.NextPermissions = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
270 item.CreationDate = Util.UnixTimeSinceEpoch();
271 m_scene.AddInventoryItem(item);
272
273 }
274 }
275}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
new file mode 100644
index 0000000..15139a3
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
@@ -0,0 +1,370 @@
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.Reflection;
31using log4net;
32using Nini.Config;
33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
35using OpenSim.Framework;
36using OpenSim.Framework.Servers;
37using OpenSim.Framework.Servers.HttpServer;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using Caps=OpenSim.Framework.Capabilities.Caps;
41
42namespace OpenSim.Region.ClientStack.Linden
43{
44 public class ObjectAdd : IRegionModule
45 {
46// private static readonly ILog m_log =
47// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private Scene m_scene;
50 #region IRegionModule Members
51
52 public void Initialise(Scene pScene, IConfigSource pSource)
53 {
54 m_scene = pScene;
55 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
56 }
57
58 public void PostInitialise()
59 {
60
61 }
62
63 public void RegisterCaps(UUID agentID, Caps caps)
64 {
65 UUID capuuid = UUID.Random();
66
67// m_log.InfoFormat("[OBJECTADD]: {0}", "/CAPS/OA/" + capuuid + "/");
68
69 caps.RegisterHandler("ObjectAdd",
70 new RestHTTPHandler("POST", "/CAPS/OA/" + capuuid + "/",
71 delegate(Hashtable m_dhttpMethod)
72 {
73 return ProcessAdd(m_dhttpMethod, agentID, caps);
74 }));
75 }
76
77 public Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap)
78 {
79 Hashtable responsedata = new Hashtable();
80 responsedata["int_response_code"] = 400; //501; //410; //404;
81 responsedata["content_type"] = "text/plain";
82 responsedata["keepalive"] = false;
83 responsedata["str_response_string"] = "Request wasn't what was expected";
84 ScenePresence avatar;
85
86 if (!m_scene.TryGetScenePresence(AgentId, out avatar))
87 return responsedata;
88
89
90 OSD r = OSDParser.DeserializeLLSDXml((string)request["requestbody"]);
91 //UUID session_id = UUID.Zero;
92 bool bypass_raycast = false;
93 uint everyone_mask = 0;
94 uint group_mask = 0;
95 uint next_owner_mask = 0;
96 uint flags = 0;
97 UUID group_id = UUID.Zero;
98 int hollow = 0;
99 int material = 0;
100 int p_code = 0;
101 int path_begin = 0;
102 int path_curve = 0;
103 int path_end = 0;
104 int path_radius_offset = 0;
105 int path_revolutions = 0;
106 int path_scale_x = 0;
107 int path_scale_y = 0;
108 int path_shear_x = 0;
109 int path_shear_y = 0;
110 int path_skew = 0;
111 int path_taper_x = 0;
112 int path_taper_y = 0;
113 int path_twist = 0;
114 int path_twist_begin = 0;
115 int profile_begin = 0;
116 int profile_curve = 0;
117 int profile_end = 0;
118 Vector3 ray_end = Vector3.Zero;
119 bool ray_end_is_intersection = false;
120 Vector3 ray_start = Vector3.Zero;
121 UUID ray_target_id = UUID.Zero;
122 Quaternion rotation = Quaternion.Identity;
123 Vector3 scale = Vector3.Zero;
124 int state = 0;
125
126 if (r.Type != OSDType.Map) // not a proper req
127 return responsedata;
128
129 OSDMap rm = (OSDMap)r;
130
131 if (rm.ContainsKey("ObjectData")) //v2
132 {
133 if (rm["ObjectData"].Type != OSDType.Map)
134 {
135 responsedata["str_response_string"] = "Has ObjectData key, but data not in expected format";
136 return responsedata;
137 }
138
139 OSDMap ObjMap = (OSDMap) rm["ObjectData"];
140
141 bypass_raycast = ObjMap["BypassRaycast"].AsBoolean();
142 everyone_mask = readuintval(ObjMap["EveryoneMask"]);
143 flags = readuintval(ObjMap["Flags"]);
144 group_mask = readuintval(ObjMap["GroupMask"]);
145 material = ObjMap["Material"].AsInteger();
146 next_owner_mask = readuintval(ObjMap["NextOwnerMask"]);
147 p_code = ObjMap["PCode"].AsInteger();
148
149 if (ObjMap.ContainsKey("Path"))
150 {
151 if (ObjMap["Path"].Type != OSDType.Map)
152 {
153 responsedata["str_response_string"] = "Has Path key, but data not in expected format";
154 return responsedata;
155 }
156
157 OSDMap PathMap = (OSDMap)ObjMap["Path"];
158 path_begin = PathMap["Begin"].AsInteger();
159 path_curve = PathMap["Curve"].AsInteger();
160 path_end = PathMap["End"].AsInteger();
161 path_radius_offset = PathMap["RadiusOffset"].AsInteger();
162 path_revolutions = PathMap["Revolutions"].AsInteger();
163 path_scale_x = PathMap["ScaleX"].AsInteger();
164 path_scale_y = PathMap["ScaleY"].AsInteger();
165 path_shear_x = PathMap["ShearX"].AsInteger();
166 path_shear_y = PathMap["ShearY"].AsInteger();
167 path_skew = PathMap["Skew"].AsInteger();
168 path_taper_x = PathMap["TaperX"].AsInteger();
169 path_taper_y = PathMap["TaperY"].AsInteger();
170 path_twist = PathMap["Twist"].AsInteger();
171 path_twist_begin = PathMap["TwistBegin"].AsInteger();
172
173 }
174
175 if (ObjMap.ContainsKey("Profile"))
176 {
177 if (ObjMap["Profile"].Type != OSDType.Map)
178 {
179 responsedata["str_response_string"] = "Has Profile key, but data not in expected format";
180 return responsedata;
181 }
182
183 OSDMap ProfileMap = (OSDMap)ObjMap["Profile"];
184
185 profile_begin = ProfileMap["Begin"].AsInteger();
186 profile_curve = ProfileMap["Curve"].AsInteger();
187 profile_end = ProfileMap["End"].AsInteger();
188 hollow = ProfileMap["Hollow"].AsInteger();
189 }
190 ray_end_is_intersection = ObjMap["RayEndIsIntersection"].AsBoolean();
191
192 ray_target_id = ObjMap["RayTargetId"].AsUUID();
193 state = ObjMap["State"].AsInteger();
194 try
195 {
196 ray_end = ((OSDArray) ObjMap["RayEnd"]).AsVector3();
197 ray_start = ((OSDArray) ObjMap["RayStart"]).AsVector3();
198 scale = ((OSDArray) ObjMap["Scale"]).AsVector3();
199 rotation = ((OSDArray)ObjMap["Rotation"]).AsQuaternion();
200 }
201 catch (Exception)
202 {
203 responsedata["str_response_string"] = "RayEnd, RayStart, Scale or Rotation wasn't in the expected format";
204 return responsedata;
205 }
206
207 if (rm.ContainsKey("AgentData"))
208 {
209 if (rm["AgentData"].Type != OSDType.Map)
210 {
211 responsedata["str_response_string"] = "Has AgentData key, but data not in expected format";
212 return responsedata;
213 }
214
215 OSDMap AgentDataMap = (OSDMap) rm["AgentData"];
216
217 //session_id = AgentDataMap["SessionId"].AsUUID();
218 group_id = AgentDataMap["GroupId"].AsUUID();
219 }
220
221 }
222 else
223 { //v1
224 bypass_raycast = rm["bypass_raycast"].AsBoolean();
225
226 everyone_mask = readuintval(rm["everyone_mask"]);
227 flags = readuintval(rm["flags"]);
228 group_id = rm["group_id"].AsUUID();
229 group_mask = readuintval(rm["group_mask"]);
230 hollow = rm["hollow"].AsInteger();
231 material = rm["material"].AsInteger();
232 next_owner_mask = readuintval(rm["next_owner_mask"]);
233 hollow = rm["hollow"].AsInteger();
234 p_code = rm["p_code"].AsInteger();
235 path_begin = rm["path_begin"].AsInteger();
236 path_curve = rm["path_curve"].AsInteger();
237 path_end = rm["path_end"].AsInteger();
238 path_radius_offset = rm["path_radius_offset"].AsInteger();
239 path_revolutions = rm["path_revolutions"].AsInteger();
240 path_scale_x = rm["path_scale_x"].AsInteger();
241 path_scale_y = rm["path_scale_y"].AsInteger();
242 path_shear_x = rm["path_shear_x"].AsInteger();
243 path_shear_y = rm["path_shear_y"].AsInteger();
244 path_skew = rm["path_skew"].AsInteger();
245 path_taper_x = rm["path_taper_x"].AsInteger();
246 path_taper_y = rm["path_taper_y"].AsInteger();
247 path_twist = rm["path_twist"].AsInteger();
248 path_twist_begin = rm["path_twist_begin"].AsInteger();
249 profile_begin = rm["profile_begin"].AsInteger();
250 profile_curve = rm["profile_curve"].AsInteger();
251 profile_end = rm["profile_end"].AsInteger();
252
253 ray_end_is_intersection = rm["ray_end_is_intersection"].AsBoolean();
254
255 ray_target_id = rm["ray_target_id"].AsUUID();
256
257
258 //session_id = rm["session_id"].AsUUID();
259 state = rm["state"].AsInteger();
260 try
261 {
262 ray_end = ((OSDArray)rm["ray_end"]).AsVector3();
263 ray_start = ((OSDArray)rm["ray_start"]).AsVector3();
264 rotation = ((OSDArray)rm["rotation"]).AsQuaternion();
265 scale = ((OSDArray)rm["scale"]).AsVector3();
266 }
267 catch (Exception)
268 {
269 responsedata["str_response_string"] = "RayEnd, RayStart, Scale or Rotation wasn't in the expected format";
270 return responsedata;
271 }
272 }
273
274
275
276 Vector3 pos = m_scene.GetNewRezLocation(ray_start, ray_end, ray_target_id, rotation, (bypass_raycast) ? (byte)1 : (byte)0, (ray_end_is_intersection) ? (byte)1 : (byte)0, true, scale, false);
277
278 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
279
280 pbs.PathBegin = (ushort)path_begin;
281 pbs.PathCurve = (byte)path_curve;
282 pbs.PathEnd = (ushort)path_end;
283 pbs.PathRadiusOffset = (sbyte)path_radius_offset;
284 pbs.PathRevolutions = (byte)path_revolutions;
285 pbs.PathScaleX = (byte)path_scale_x;
286 pbs.PathScaleY = (byte)path_scale_y;
287 pbs.PathShearX = (byte) path_shear_x;
288 pbs.PathShearY = (byte)path_shear_y;
289 pbs.PathSkew = (sbyte)path_skew;
290 pbs.PathTaperX = (sbyte)path_taper_x;
291 pbs.PathTaperY = (sbyte)path_taper_y;
292 pbs.PathTwist = (sbyte)path_twist;
293 pbs.PathTwistBegin = (sbyte)path_twist_begin;
294 pbs.HollowShape = (HollowShape) hollow;
295 pbs.PCode = (byte)p_code;
296 pbs.ProfileBegin = (ushort) profile_begin;
297 pbs.ProfileCurve = (byte) profile_curve;
298 pbs.ProfileEnd = (ushort)profile_end;
299 pbs.Scale = scale;
300 pbs.State = (byte)state;
301
302 SceneObjectGroup obj = null; ;
303
304 if (m_scene.Permissions.CanRezObject(1, avatar.UUID, pos))
305 {
306 // rez ON the ground, not IN the ground
307 // pos.Z += 0.25F;
308
309 obj = m_scene.AddNewPrim(avatar.UUID, group_id, pos, rotation, pbs);
310 }
311
312
313 if (obj == null)
314 return responsedata;
315
316 SceneObjectPart rootpart = obj.RootPart;
317 rootpart.Shape = pbs;
318 rootpart.Flags |= (PrimFlags)flags;
319 rootpart.EveryoneMask = everyone_mask;
320 rootpart.GroupID = group_id;
321 rootpart.GroupMask = group_mask;
322 rootpart.NextOwnerMask = next_owner_mask;
323 rootpart.Material = (byte)material;
324
325
326
327 m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor);
328
329 responsedata["int_response_code"] = 200; //501; //410; //404;
330 responsedata["content_type"] = "text/plain";
331 responsedata["keepalive"] = false;
332 responsedata["str_response_string"] = String.Format("<llsd><map><key>local_id</key>{0}</map></llsd>",ConvertUintToBytes(obj.LocalId));
333
334 return responsedata;
335 }
336
337 private uint readuintval(OSD obj)
338 {
339 byte[] tmp = obj.AsBinary();
340 if (BitConverter.IsLittleEndian)
341 Array.Reverse(tmp);
342 return Utils.BytesToUInt(tmp);
343
344 }
345 private string ConvertUintToBytes(uint val)
346 {
347 byte[] resultbytes = Utils.UIntToBytes(val);
348 if (BitConverter.IsLittleEndian)
349 Array.Reverse(resultbytes);
350 return String.Format("<binary encoding=\"base64\">{0}</binary>",Convert.ToBase64String(resultbytes));
351 }
352
353 public void Close()
354 {
355
356 }
357
358 public string Name
359 {
360 get { return "ObjectAddModule"; }
361 }
362
363 public bool IsSharedModule
364 {
365 get { return false; }
366 }
367
368 #endregion
369 }
370}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
new file mode 100644
index 0000000..3809f84
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
@@ -0,0 +1,374 @@
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.Specialized;
31using System.Reflection;
32using System.IO;
33using System.Web;
34using Mono.Addins;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenMetaverse.Messages.Linden;
40using OpenSim.Framework;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45using OpenSim.Services.Interfaces;
46using Caps = OpenSim.Framework.Capabilities.Caps;
47using OSD = OpenMetaverse.StructuredData.OSD;
48using OSDMap = OpenMetaverse.StructuredData.OSDMap;
49using OpenSim.Framework.Capabilities;
50using ExtraParamType = OpenMetaverse.ExtraParamType;
51
52namespace OpenSim.Region.ClientStack.Linden
53{
54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
55 public class UploadObjectAssetModule : INonSharedRegionModule
56 {
57 private static readonly ILog m_log =
58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 private Scene m_scene;
60
61 #region IRegionModuleBase Members
62
63
64 public Type ReplaceableInterface
65 {
66 get { return null; }
67 }
68
69 public void Initialise(IConfigSource source)
70 {
71
72 }
73
74 public void AddRegion(Scene pScene)
75 {
76 m_scene = pScene;
77 }
78
79 public void RemoveRegion(Scene scene)
80 {
81
82 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
83 m_scene = null;
84 }
85
86 public void RegionLoaded(Scene scene)
87 {
88
89 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
90 }
91
92 #endregion
93
94
95 #region IRegionModule Members
96
97
98
99 public void Close() { }
100
101 public string Name { get { return "UploadObjectAssetModuleModule"; } }
102
103
104 public void RegisterCaps(UUID agentID, Caps caps)
105 {
106 UUID capID = UUID.Random();
107
108// m_log.Debug("[UPLOAD OBJECT ASSET MODULE]: /CAPS/" + capID);
109 caps.RegisterHandler("UploadObjectAsset",
110 new RestHTTPHandler("POST", "/CAPS/OA/" + capID + "/",
111 delegate(Hashtable m_dhttpMethod)
112 {
113 return ProcessAdd(m_dhttpMethod, agentID, caps);
114 }));
115 /*
116 caps.RegisterHandler("NewFileAgentInventoryVariablePrice",
117
118 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDNewFileAngentInventoryVariablePriceReplyResponse>("POST",
119 "/CAPS/" + capID.ToString(),
120 delegate(LLSDAssetUploadRequest req)
121 {
122 return NewAgentInventoryRequest(req,agentID);
123 }));
124 */
125
126 }
127
128 #endregion
129
130
131 /// <summary>
132 /// Parses ad request
133 /// </summary>
134 /// <param name="request"></param>
135 /// <param name="AgentId"></param>
136 /// <param name="cap"></param>
137 /// <returns></returns>
138 public Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap)
139 {
140 Hashtable responsedata = new Hashtable();
141 responsedata["int_response_code"] = 400; //501; //410; //404;
142 responsedata["content_type"] = "text/plain";
143 responsedata["keepalive"] = false;
144 responsedata["str_response_string"] = "Request wasn't what was expected";
145 ScenePresence avatar;
146
147 if (!m_scene.TryGetScenePresence(AgentId, out avatar))
148 return responsedata;
149
150 OSDMap r = (OSDMap)OSDParser.Deserialize((string)request["requestbody"]);
151 UploadObjectAssetMessage message = new UploadObjectAssetMessage();
152 try
153 {
154 message.Deserialize(r);
155
156 }
157 catch (Exception ex)
158 {
159 m_log.Error("[UPLOAD OBJECT ASSET MODULE]: Error deserializing message " + ex.ToString());
160 message = null;
161 }
162
163 if (message == null)
164 {
165 responsedata["int_response_code"] = 400; //501; //410; //404;
166 responsedata["content_type"] = "text/plain";
167 responsedata["keepalive"] = false;
168 responsedata["str_response_string"] =
169 "<llsd><map><key>error</key><string>Error parsing Object</string></map></llsd>";
170
171 return responsedata;
172 }
173
174 Vector3 pos = avatar.AbsolutePosition + (Vector3.UnitX * avatar.Rotation);
175 Quaternion rot = Quaternion.Identity;
176 Vector3 rootpos = Vector3.Zero;
177// Quaternion rootrot = Quaternion.Identity;
178
179 SceneObjectGroup rootGroup = null;
180 SceneObjectGroup[] allparts = new SceneObjectGroup[message.Objects.Length];
181 for (int i = 0; i < message.Objects.Length; i++)
182 {
183 UploadObjectAssetMessage.Object obj = message.Objects[i];
184 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
185
186 if (i == 0)
187 {
188 rootpos = obj.Position;
189// rootrot = obj.Rotation;
190 }
191
192 // Combine the extraparams data into it's ugly blob again....
193 //int bytelength = 0;
194 //for (int extparams = 0; extparams < obj.ExtraParams.Length; extparams++)
195 //{
196 // bytelength += obj.ExtraParams[extparams].ExtraParamData.Length;
197 //}
198 //byte[] extraparams = new byte[bytelength];
199 //int position = 0;
200
201
202
203 //for (int extparams = 0; extparams < obj.ExtraParams.Length; extparams++)
204 //{
205 // Buffer.BlockCopy(obj.ExtraParams[extparams].ExtraParamData, 0, extraparams, position,
206 // obj.ExtraParams[extparams].ExtraParamData.Length);
207 //
208 // position += obj.ExtraParams[extparams].ExtraParamData.Length;
209 // }
210
211 //pbs.ExtraParams = extraparams;
212 for (int extparams = 0; extparams < obj.ExtraParams.Length; extparams++)
213 {
214 UploadObjectAssetMessage.Object.ExtraParam extraParam = obj.ExtraParams[extparams];
215 switch ((ushort)extraParam.Type)
216 {
217 case (ushort)ExtraParamType.Sculpt:
218 Primitive.SculptData sculpt = new Primitive.SculptData(extraParam.ExtraParamData, 0);
219
220 pbs.SculptEntry = true;
221
222 pbs.SculptTexture = obj.SculptID;
223 pbs.SculptType = (byte)sculpt.Type;
224
225 break;
226 case (ushort)ExtraParamType.Flexible:
227 Primitive.FlexibleData flex = new Primitive.FlexibleData(extraParam.ExtraParamData, 0);
228 pbs.FlexiEntry = true;
229 pbs.FlexiDrag = flex.Drag;
230 pbs.FlexiForceX = flex.Force.X;
231 pbs.FlexiForceY = flex.Force.Y;
232 pbs.FlexiForceZ = flex.Force.Z;
233 pbs.FlexiGravity = flex.Gravity;
234 pbs.FlexiSoftness = flex.Softness;
235 pbs.FlexiTension = flex.Tension;
236 pbs.FlexiWind = flex.Wind;
237 break;
238 case (ushort)ExtraParamType.Light:
239 Primitive.LightData light = new Primitive.LightData(extraParam.ExtraParamData, 0);
240 pbs.LightColorA = light.Color.A;
241 pbs.LightColorB = light.Color.B;
242 pbs.LightColorG = light.Color.G;
243 pbs.LightColorR = light.Color.R;
244 pbs.LightCutoff = light.Cutoff;
245 pbs.LightEntry = true;
246 pbs.LightFalloff = light.Falloff;
247 pbs.LightIntensity = light.Intensity;
248 pbs.LightRadius = light.Radius;
249 break;
250 case 0x40:
251 pbs.ReadProjectionData(extraParam.ExtraParamData, 0);
252 break;
253
254 }
255
256
257 }
258 pbs.PathBegin = (ushort) obj.PathBegin;
259 pbs.PathCurve = (byte) obj.PathCurve;
260 pbs.PathEnd = (ushort) obj.PathEnd;
261 pbs.PathRadiusOffset = (sbyte) obj.RadiusOffset;
262 pbs.PathRevolutions = (byte) obj.Revolutions;
263 pbs.PathScaleX = (byte) obj.ScaleX;
264 pbs.PathScaleY = (byte) obj.ScaleY;
265 pbs.PathShearX = (byte) obj.ShearX;
266 pbs.PathShearY = (byte) obj.ShearY;
267 pbs.PathSkew = (sbyte) obj.Skew;
268 pbs.PathTaperX = (sbyte) obj.TaperX;
269 pbs.PathTaperY = (sbyte) obj.TaperY;
270 pbs.PathTwist = (sbyte) obj.Twist;
271 pbs.PathTwistBegin = (sbyte) obj.TwistBegin;
272 pbs.HollowShape = (HollowShape) obj.ProfileHollow;
273 pbs.PCode = (byte) PCode.Prim;
274 pbs.ProfileBegin = (ushort) obj.ProfileBegin;
275 pbs.ProfileCurve = (byte) obj.ProfileCurve;
276 pbs.ProfileEnd = (ushort) obj.ProfileEnd;
277 pbs.Scale = obj.Scale;
278 pbs.State = (byte) 0;
279 SceneObjectPart prim = new SceneObjectPart();
280 prim.UUID = UUID.Random();
281 prim.CreatorID = AgentId;
282 prim.OwnerID = AgentId;
283 prim.GroupID = obj.GroupID;
284 prim.LastOwnerID = prim.OwnerID;
285 prim.CreationDate = Util.UnixTimeSinceEpoch();
286 prim.Name = obj.Name;
287 prim.Description = "";
288
289 prim.PayPrice[0] = -2;
290 prim.PayPrice[1] = -2;
291 prim.PayPrice[2] = -2;
292 prim.PayPrice[3] = -2;
293 prim.PayPrice[4] = -2;
294 Primitive.TextureEntry tmp =
295 new Primitive.TextureEntry(UUID.Parse("89556747-24cb-43ed-920b-47caed15465f"));
296
297 for (int j = 0; j < obj.Faces.Length; j++)
298 {
299 UploadObjectAssetMessage.Object.Face face = obj.Faces[j];
300
301 Primitive.TextureEntryFace primFace = tmp.CreateFace((uint) j);
302
303 primFace.Bump = face.Bump;
304 primFace.RGBA = face.Color;
305 primFace.Fullbright = face.Fullbright;
306 primFace.Glow = face.Glow;
307 primFace.TextureID = face.ImageID;
308 primFace.Rotation = face.ImageRot;
309 primFace.MediaFlags = ((face.MediaFlags & 1) != 0);
310
311 primFace.OffsetU = face.OffsetS;
312 primFace.OffsetV = face.OffsetT;
313 primFace.RepeatU = face.ScaleS;
314 primFace.RepeatV = face.ScaleT;
315 primFace.TexMapType = (MappingType) (face.MediaFlags & 6);
316 }
317 pbs.TextureEntry = tmp.GetBytes();
318 prim.Shape = pbs;
319 prim.Scale = obj.Scale;
320
321
322 SceneObjectGroup grp = new SceneObjectGroup();
323
324 grp.SetRootPart(prim);
325 prim.ParentID = 0;
326 if (i == 0)
327 {
328 rootGroup = grp;
329
330 }
331 grp.AttachToScene(m_scene);
332 grp.AbsolutePosition = obj.Position;
333 prim.RotationOffset = obj.Rotation;
334
335 grp.RootPart.IsAttachment = false;
336 // Required for linking
337 grp.RootPart.UpdateFlag = 0;
338
339 if (m_scene.Permissions.CanRezObject(1, avatar.UUID, pos))
340 {
341 m_scene.AddSceneObject(grp);
342 grp.AbsolutePosition = obj.Position;
343 }
344 allparts[i] = grp;
345
346 }
347
348 for (int j = 1; j < allparts.Length; j++)
349 {
350 rootGroup.RootPart.UpdateFlag = 0;
351 allparts[j].RootPart.UpdateFlag = 0;
352 rootGroup.LinkToGroup(allparts[j]);
353 }
354
355 rootGroup.ScheduleGroupForFullUpdate();
356 pos = m_scene.GetNewRezLocation(Vector3.Zero, rootpos, UUID.Zero, rot, (byte)1, 1, true, allparts[0].GroupScale(), false);
357
358 responsedata["int_response_code"] = 200; //501; //410; //404;
359 responsedata["content_type"] = "text/plain";
360 responsedata["keepalive"] = false;
361 responsedata["str_response_string"] = String.Format("<llsd><map><key>local_id</key>{0}</map></llsd>", ConvertUintToBytes(allparts[0].LocalId));
362
363 return responsedata;
364 }
365
366 private string ConvertUintToBytes(uint val)
367 {
368 byte[] resultbytes = Utils.UIntToBytes(val);
369 if (BitConverter.IsLittleEndian)
370 Array.Reverse(resultbytes);
371 return String.Format("<binary encoding=\"base64\">{0}</binary>", Convert.ToBase64String(resultbytes));
372 }
373 }
374} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
new file mode 100644
index 0000000..94629a2
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -0,0 +1,134 @@
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.Reflection;
31using log4net;
32using Nini.Config;
33using Mono.Addins;
34using OpenMetaverse;
35using OpenSim.Framework;
36using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces;
40using Caps = OpenSim.Framework.Capabilities.Caps;
41using OpenSim.Capabilities.Handlers;
42
43namespace OpenSim.Region.ClientStack.Linden
44{
45
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
47 public class WebFetchInvDescModule : INonSharedRegionModule
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 private Scene m_scene;
52
53 private IInventoryService m_InventoryService;
54 private ILibraryService m_LibraryService;
55 private bool m_Enabled = false;
56 private string m_URL;
57
58 #region ISharedRegionModule Members
59
60 public void Initialise(IConfigSource source)
61 {
62 IConfig config = source.Configs["ClientStack.LindenCaps"];
63 if (config == null)
64 return;
65
66 m_URL = config.GetString("Cap_WebFetchInventoryDescendents", string.Empty);
67 // Cap doesn't exist
68 if (m_URL != string.Empty)
69 m_Enabled = true;
70 }
71
72 public void AddRegion(Scene s)
73 {
74 if (!m_Enabled)
75 return;
76
77 m_scene = s;
78 }
79
80 public void RemoveRegion(Scene s)
81 {
82 if (!m_Enabled)
83 return;
84
85 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
86 m_scene = null;
87 }
88
89 public void RegionLoaded(Scene s)
90 {
91 if (!m_Enabled)
92 return;
93
94 m_InventoryService = m_scene.InventoryService; ;
95 m_LibraryService = m_scene.LibraryService;
96 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
97 }
98
99 public void PostInitialise()
100 {
101 }
102
103 public void Close() { }
104
105 public string Name { get { return "WebFetchInvDescModule"; } }
106
107 public Type ReplaceableInterface
108 {
109 get { return null; }
110 }
111
112 #endregion
113
114 public void RegisterCaps(UUID agentID, Caps caps)
115 {
116 UUID capID = UUID.Random();
117
118 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture));
119 if (m_URL == "localhost")
120 {
121 m_log.InfoFormat("[WEBFETCHINVENTORYDESCENDANTS]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
122 WebFetchInvDescHandler webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
123 IRequestHandler reqHandler = new RestStreamHandler("POST", "/CAPS/" + UUID.Random(), webFetchHandler.FetchInventoryDescendentsRequest);
124 caps.RegisterHandler("WebFetchInventoryDescendents", reqHandler);
125 }
126 else
127 {
128 m_log.InfoFormat("[WEBFETCHINVENTORYDESCENDANTS]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName);
129 caps.RegisterHandler("WebFetchInventoryDescendents", m_URL);
130 }
131 }
132
133 }
134}
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..9dd6663
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
@@ -0,0 +1,401 @@
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 //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way)
206 if (m_stopPacket == 1 && Layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++;
207
208 m_currentPacket = StartPacket;
209 }
210 }
211 }
212 }
213
214 private bool SendFirstPacket(LLClientView client)
215 {
216 if (client == null)
217 return false;
218
219 if (m_asset == null)
220 {
221 m_log.Warn("[J2KIMAGE]: Sending ImageNotInDatabase for texture " + TextureID);
222 client.SendImageNotFound(TextureID);
223 return true;
224 }
225 else if (m_asset.Length <= FIRST_PACKET_SIZE)
226 {
227 // We have less then one packet's worth of data
228 client.SendImageFirstPart(1, TextureID, (uint)m_asset.Length, m_asset, 2);
229 m_stopPacket = 0;
230 return true;
231 }
232 else
233 {
234 // This is going to be a multi-packet texture download
235 byte[] firstImageData = new byte[FIRST_PACKET_SIZE];
236
237 try { Buffer.BlockCopy(m_asset, 0, firstImageData, 0, FIRST_PACKET_SIZE); }
238 catch (Exception)
239 {
240 m_log.ErrorFormat("[J2KIMAGE]: Texture block copy for the first packet failed. textureid={0}, assetlength={1}", TextureID, m_asset.Length);
241 return true;
242 }
243
244 client.SendImageFirstPart(TexturePacketCount(), TextureID, (uint)m_asset.Length, firstImageData, (byte)ImageCodec.J2C);
245 }
246 return false;
247 }
248
249 private bool SendPacket(LLClientView client)
250 {
251 if (client == null)
252 return false;
253
254 bool complete = false;
255 int imagePacketSize = ((int)m_currentPacket == (TexturePacketCount())) ? LastPacketSize() : IMAGE_PACKET_SIZE;
256
257 try
258 {
259 if ((CurrentBytePosition() + IMAGE_PACKET_SIZE) > m_asset.Length)
260 {
261 imagePacketSize = LastPacketSize();
262 complete = true;
263 if ((CurrentBytePosition() + imagePacketSize) > m_asset.Length)
264 {
265 imagePacketSize = m_asset.Length - CurrentBytePosition();
266 complete = true;
267 }
268 }
269
270 // It's concievable that the client might request packet one
271 // from a one packet image, which is really packet 0,
272 // which would leave us with a negative imagePacketSize..
273 if (imagePacketSize > 0)
274 {
275 byte[] imageData = new byte[imagePacketSize];
276 int currentPosition = CurrentBytePosition();
277
278 try { Buffer.BlockCopy(m_asset, currentPosition, imageData, 0, imagePacketSize); }
279 catch (Exception e)
280 {
281 m_log.ErrorFormat("[J2KIMAGE]: Texture block copy for the first packet failed. textureid={0}, assetlength={1}, currentposition={2}, imagepacketsize={3}, exception={4}",
282 TextureID, m_asset.Length, currentPosition, imagePacketSize, e.Message);
283 return false;
284 }
285
286 //Send the packet
287 client.SendImageNextPart((ushort)(m_currentPacket - 1), TextureID, imageData);
288 }
289
290 return !complete;
291 }
292 catch (Exception)
293 {
294 return false;
295 }
296 }
297
298 private ushort TexturePacketCount()
299 {
300 if (!IsDecoded)
301 return 0;
302
303 if (m_asset == null)
304 return 0;
305
306 if (m_asset.Length <= FIRST_PACKET_SIZE)
307 return 1;
308
309 return (ushort)(((m_asset.Length - FIRST_PACKET_SIZE + IMAGE_PACKET_SIZE - 1) / IMAGE_PACKET_SIZE) + 1);
310 }
311
312 private int GetPacketForBytePosition(int bytePosition)
313 {
314 return ((bytePosition - FIRST_PACKET_SIZE + IMAGE_PACKET_SIZE - 1) / IMAGE_PACKET_SIZE) + 1;
315 }
316
317 private int LastPacketSize()
318 {
319 if (m_currentPacket == 1)
320 return m_asset.Length;
321 int lastsize = (m_asset.Length - FIRST_PACKET_SIZE) % IMAGE_PACKET_SIZE;
322 //If the last packet size is zero, it's really cImagePacketSize, it sits on the boundary
323 if (lastsize == 0)
324 {
325 lastsize = IMAGE_PACKET_SIZE;
326 }
327 return lastsize;
328 }
329
330 private int CurrentBytePosition()
331 {
332 if (m_currentPacket == 0)
333 return 0;
334 if (m_currentPacket == 1)
335 return FIRST_PACKET_SIZE;
336
337 int result = FIRST_PACKET_SIZE + ((int)m_currentPacket - 2) * IMAGE_PACKET_SIZE;
338 if (result < 0)
339 {
340 result = FIRST_PACKET_SIZE;
341 }
342 return result;
343 }
344
345 private void J2KDecodedCallback(UUID AssetId, OpenJPEG.J2KLayerInfo[] layers)
346 {
347 Layers = layers;
348 IsDecoded = true;
349 RunUpdate();
350 }
351
352 private void AssetDataCallback(UUID AssetID, AssetBase asset)
353 {
354 HasAsset = true;
355
356 if (asset == null || asset.Data == null)
357 {
358 if (m_imageManager.MissingImage != null)
359 {
360 m_asset = m_imageManager.MissingImage.Data;
361 }
362 else
363 {
364 m_asset = null;
365 IsDecoded = true;
366 }
367 }
368 else
369 {
370 m_asset = asset.Data;
371 }
372
373 RunUpdate();
374 }
375
376 private void AssetReceived(string id, Object sender, AssetBase asset)
377 {
378 UUID assetID = UUID.Zero;
379 if (asset != null)
380 assetID = asset.FullID;
381 else if ((InventoryAccessModule != null) && (sender != InventoryAccessModule))
382 {
383 // Unfortunately we need this here, there's no other way.
384 // This is due to the fact that textures opened directly from the agent's inventory
385 // don't have any distinguishing feature. As such, in order to serve those when the
386 // foreign user is visiting, we need to try again after the first fail to the local
387 // asset service.
388 string assetServerURL = string.Empty;
389 if (InventoryAccessModule.IsForeignUser(AgentID, out assetServerURL))
390 {
391 m_log.DebugFormat("[J2KIMAGE]: texture {0} not found in local asset storage. Trying user's storage.", id);
392 AssetService.Get(assetServerURL + "/" + id, InventoryAccessModule, AssetReceived);
393 return;
394 }
395 }
396
397 AssetDataCallback(assetID, asset);
398
399 }
400 }
401}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
new file mode 100644
index 0000000..910fb76
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -0,0 +1,12218 @@
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 MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
161 public event MoveInventoryItem OnMoveInventoryItem;
162 public event RemoveInventoryItem OnRemoveInventoryItem;
163 public event RemoveInventoryFolder OnRemoveInventoryFolder;
164 public event UDPAssetUploadRequest OnAssetUploadRequest;
165 public event XferReceive OnXferReceive;
166 public event RequestXfer OnRequestXfer;
167 public event ConfirmXfer OnConfirmXfer;
168 public event AbortXfer OnAbortXfer;
169 public event RequestTerrain OnRequestTerrain;
170 public event RezScript OnRezScript;
171 public event UpdateTaskInventory OnUpdateTaskInventory;
172 public event MoveTaskInventory OnMoveTaskItem;
173 public event RemoveTaskInventory OnRemoveTaskItem;
174 public event RequestAsset OnRequestAsset;
175 public event UUIDNameRequest OnNameFromUUIDRequest;
176 public event ParcelAccessListRequest OnParcelAccessListRequest;
177 public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest;
178 public event ParcelPropertiesRequest OnParcelPropertiesRequest;
179 public event ParcelDivideRequest OnParcelDivideRequest;
180 public event ParcelJoinRequest OnParcelJoinRequest;
181 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
182 public event ParcelSelectObjects OnParcelSelectObjects;
183 public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest;
184 public event ParcelAbandonRequest OnParcelAbandonRequest;
185 public event ParcelGodForceOwner OnParcelGodForceOwner;
186 public event ParcelReclaim OnParcelReclaim;
187 public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest;
188 public event ParcelDeedToGroup OnParcelDeedToGroup;
189 public event RegionInfoRequest OnRegionInfoRequest;
190 public event EstateCovenantRequest OnEstateCovenantRequest;
191 public event FriendActionDelegate OnApproveFriendRequest;
192 public event FriendActionDelegate OnDenyFriendRequest;
193 public event FriendshipTermination OnTerminateFriendship;
194 public event GrantUserFriendRights OnGrantUserRights;
195 public event MoneyTransferRequest OnMoneyTransferRequest;
196 public event EconomyDataRequest OnEconomyDataRequest;
197 public event MoneyBalanceRequest OnMoneyBalanceRequest;
198 public event ParcelBuy OnParcelBuy;
199 public event UUIDNameRequest OnTeleportHomeRequest;
200 public event UUIDNameRequest OnUUIDGroupNameRequest;
201 public event ScriptAnswer OnScriptAnswer;
202 public event RequestPayPrice OnRequestPayPrice;
203 public event ObjectSaleInfo OnObjectSaleInfo;
204 public event ObjectBuy OnObjectBuy;
205 public event BuyObjectInventory OnBuyObjectInventory;
206 public event AgentSit OnUndo;
207 public event AgentSit OnRedo;
208 public event LandUndo OnLandUndo;
209 public event ForceReleaseControls OnForceReleaseControls;
210 public event GodLandStatRequest OnLandStatRequest;
211 public event RequestObjectPropertiesFamily OnObjectGroupRequest;
212 public event DetailedEstateDataRequest OnDetailedEstateDataRequest;
213 public event SetEstateFlagsRequest OnSetEstateFlagsRequest;
214 public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture;
215 public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture;
216 public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights;
217 public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest;
218 public event SetRegionTerrainSettings OnSetRegionTerrainSettings;
219 public event BakeTerrain OnBakeTerrain;
220 public event RequestTerrain OnUploadTerrain;
221 public event EstateChangeInfo OnEstateChangeInfo;
222 public event EstateRestartSimRequest OnEstateRestartSimRequest;
223 public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest;
224 public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest;
225 public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest;
226 public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest;
227 public event EstateDebugRegionRequest OnEstateDebugRegionRequest;
228 public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest;
229 public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest;
230 public event RegionHandleRequest OnRegionHandleRequest;
231 public event ParcelInfoRequest OnParcelInfoRequest;
232 public event ScriptReset OnScriptReset;
233 public event GetScriptRunning OnGetScriptRunning;
234 public event SetScriptRunning OnSetScriptRunning;
235 public event UpdateVector OnAutoPilotGo;
236 public event TerrainUnacked OnUnackedTerrain;
237 public event ActivateGesture OnActivateGesture;
238 public event DeactivateGesture OnDeactivateGesture;
239 public event ObjectOwner OnObjectOwner;
240 public event DirPlacesQuery OnDirPlacesQuery;
241 public event DirFindQuery OnDirFindQuery;
242 public event DirLandQuery OnDirLandQuery;
243 public event DirPopularQuery OnDirPopularQuery;
244 public event DirClassifiedQuery OnDirClassifiedQuery;
245 public event EventInfoRequest OnEventInfoRequest;
246 public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime;
247 public event MapItemRequest OnMapItemRequest;
248 public event OfferCallingCard OnOfferCallingCard;
249 public event AcceptCallingCard OnAcceptCallingCard;
250 public event DeclineCallingCard OnDeclineCallingCard;
251 public event SoundTrigger OnSoundTrigger;
252 public event StartLure OnStartLure;
253 public event TeleportLureRequest OnTeleportLureRequest;
254 public event NetworkStats OnNetworkStatsUpdate;
255 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
256 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
257 public event ClassifiedDelete OnClassifiedDelete;
258 public event ClassifiedGodDelete OnClassifiedGodDelete;
259 public event EventNotificationAddRequest OnEventNotificationAddRequest;
260 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
261 public event EventGodDelete OnEventGodDelete;
262 public event ParcelDwellRequest OnParcelDwellRequest;
263 public event UserInfoRequest OnUserInfoRequest;
264 public event UpdateUserInfo OnUpdateUserInfo;
265 public event RetrieveInstantMessages OnRetrieveInstantMessages;
266 public event PickDelete OnPickDelete;
267 public event PickGodDelete OnPickGodDelete;
268 public event PickInfoUpdate OnPickInfoUpdate;
269 public event AvatarNotesUpdate OnAvatarNotesUpdate;
270 public event MuteListRequest OnMuteListRequest;
271 public event AvatarInterestUpdate OnAvatarInterestUpdate;
272 public event PlacesQuery OnPlacesQuery;
273 public event AgentFOV OnAgentFOV;
274 public event FindAgentUpdate OnFindAgent;
275 public event TrackAgentUpdate OnTrackAgent;
276 public event NewUserReport OnUserReport;
277 public event SaveStateHandler OnSaveState;
278 public event GroupAccountSummaryRequest OnGroupAccountSummaryRequest;
279 public event GroupAccountDetailsRequest OnGroupAccountDetailsRequest;
280 public event GroupAccountTransactionsRequest OnGroupAccountTransactionsRequest;
281 public event FreezeUserUpdate OnParcelFreezeUser;
282 public event EjectUserUpdate OnParcelEjectUser;
283 public event ParcelBuyPass OnParcelBuyPass;
284 public event ParcelGodMark OnParcelGodMark;
285 public event GroupActiveProposalsRequest OnGroupActiveProposalsRequest;
286 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
287 public event SimWideDeletesDelegate OnSimWideDeletes;
288 public event SendPostcard OnSendPostcard;
289 public event MuteListEntryUpdate OnUpdateMuteListEntry;
290 public event MuteListEntryRemove OnRemoveMuteListEntry;
291 public event GodlikeMessage onGodlikeMessage;
292 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
293
294 #endregion Events
295
296 #region Class Members
297
298 // LLClientView Only
299 public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args);
300
301 /// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary>
302 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
303
304 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
305 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
306
307 private readonly LLUDPServer m_udpServer;
308 private readonly LLUDPClient m_udpClient;
309 private readonly UUID m_sessionId;
310 private readonly UUID m_secureSessionId;
311 protected readonly UUID m_agentId;
312 private readonly uint m_circuitCode;
313 private readonly byte[] m_channelVersion = Utils.EmptyBytes;
314 private readonly Dictionary<string, UUID> m_defaultAnimations = new Dictionary<string, UUID>();
315 private readonly IGroupsModule m_GroupsModule;
316
317 private int m_cachedTextureSerial;
318 private PriorityQueue m_entityUpdates;
319 private PriorityQueue m_entityProps;
320 private Prioritizer m_prioritizer;
321 private bool m_disableFacelights = false;
322
323 /// <value>
324 /// List used in construction of data blocks for an object update packet. This is to stop us having to
325 /// continually recreate it.
326 /// </value>
327 protected List<ObjectUpdatePacket.ObjectDataBlock> m_fullUpdateDataBlocksBuilder;
328
329 /// <value>
330 /// Maintain a record of all the objects killed. This allows us to stop an update being sent from the
331 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
332 /// ownerless phantom.
333 ///
334 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
335 ///
336 /// </value>
337 protected HashSet<uint> m_killRecord;
338
339// protected HashSet<uint> m_attachmentsSent;
340
341 private int m_moneyBalance;
342 private bool m_deliverPackets = true;
343 private int m_animationSequenceNumber = 1;
344 private bool m_SendLogoutPacketWhenClosing = true;
345 private AgentUpdateArgs lastarg;
346 private bool m_IsActive = true;
347 private bool m_IsLoggingOut = false;
348
349 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
350 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
351 protected Scene m_scene;
352 protected LLImageManager m_imageManager;
353 protected string m_firstName;
354 protected string m_lastName;
355 protected Thread m_clientThread;
356 protected Vector3 m_startpos;
357 protected EndPoint m_userEndPoint;
358 protected UUID m_activeGroupID;
359 protected string m_activeGroupName = String.Empty;
360 protected ulong m_activeGroupPowers;
361 protected Dictionary<UUID, ulong> m_groupPowers = new Dictionary<UUID, ulong>();
362 protected int m_terrainCheckerCount;
363 protected uint m_agentFOVCounter;
364
365 protected IAssetService m_assetService;
366 private const bool m_checkPackets = true;
367
368 #endregion Class Members
369
370 #region Properties
371
372 public LLUDPClient UDPClient { get { return m_udpClient; } }
373 public LLUDPServer UDPServer { get { return m_udpServer; } }
374 public IPEndPoint RemoteEndPoint { get { return m_udpClient.RemoteEndPoint; } }
375 public UUID SecureSessionId { get { return m_secureSessionId; } }
376 public IScene Scene { get { return m_scene; } }
377 public UUID SessionId { get { return m_sessionId; } }
378 public Vector3 StartPos
379 {
380 get { return m_startpos; }
381 set { m_startpos = value; }
382 }
383 public bool DeliverPackets
384 {
385 get { return m_deliverPackets; }
386 set {
387 m_deliverPackets = value;
388 m_udpClient.m_deliverPackets = value;
389 }
390 }
391 public UUID AgentId { get { return m_agentId; } }
392 public UUID ActiveGroupId { get { return m_activeGroupID; } }
393 public string ActiveGroupName { get { return m_activeGroupName; } }
394 public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } }
395 public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
396
397 /// <summary>
398 /// Entity update queues
399 /// </summary>
400 public PriorityQueue EntityUpdateQueue { get { return m_entityUpdates; } }
401
402 /// <summary>
403 /// First name of the agent/avatar represented by the client
404 /// </summary>
405 public string FirstName { get { return m_firstName; } }
406
407 /// <summary>
408 /// Last name of the agent/avatar represented by the client
409 /// </summary>
410 public string LastName { get { return m_lastName; } }
411
412 /// <summary>
413 /// Full name of the client (first name and last name)
414 /// </summary>
415 public string Name { get { return FirstName + " " + LastName; } }
416
417 public uint CircuitCode { get { return m_circuitCode; } }
418 public int MoneyBalance { get { return m_moneyBalance; } }
419 public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } }
420 public bool IsActive
421 {
422 get { return m_IsActive; }
423 set { m_IsActive = value; }
424 }
425 public bool IsLoggingOut
426 {
427 get { return m_IsLoggingOut; }
428 set { m_IsLoggingOut = value; }
429 }
430
431 public bool DisableFacelights
432 {
433 get { return m_disableFacelights; }
434 set { m_disableFacelights = value; }
435 }
436
437 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
438
439 #endregion Properties
440
441 /// <summary>
442 /// Constructor
443 /// </summary>
444 public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
445 UUID agentId, UUID sessionId, uint circuitCode)
446 {
447 RegisterInterface<IClientIM>(this);
448 RegisterInterface<IClientChat>(this);
449 RegisterInterface<IClientIPEndpoint>(this);
450
451 InitDefaultAnimations();
452
453 m_scene = scene;
454
455 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
456 m_entityProps = new PriorityQueue(m_scene.Entities.Count);
457 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
458 m_killRecord = new HashSet<uint>();
459// m_attachmentsSent = new HashSet<uint>();
460
461 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
462 m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>();
463 m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>());
464 m_channelVersion = Util.StringToBytes256(scene.GetSimulatorVersion());
465 m_agentId = agentId;
466 m_sessionId = sessionId;
467 m_secureSessionId = sessionInfo.LoginInfo.SecureSession;
468 m_circuitCode = circuitCode;
469 m_userEndPoint = remoteEP;
470 m_firstName = sessionInfo.LoginInfo.First;
471 m_lastName = sessionInfo.LoginInfo.Last;
472 m_startpos = sessionInfo.LoginInfo.StartPos;
473 m_moneyBalance = 1000;
474
475 m_udpServer = udpServer;
476 m_udpClient = udpClient;
477 m_udpClient.OnQueueEmpty += HandleQueueEmpty;
478 m_udpClient.OnPacketStats += PopulateStats;
479
480 m_prioritizer = new Prioritizer(m_scene);
481
482 RegisterLocalPacketHandlers();
483 }
484
485 public void SetDebugPacketLevel(int newDebug)
486 {
487 m_debugPacketLevel = newDebug;
488 }
489
490 #region Client Methods
491
492
493 /// <summary>
494 /// Shut down the client view
495 /// </summary>
496 public void Close()
497 {
498 Close(true);
499 }
500
501 /// <summary>
502 /// Shut down the client view
503 /// </summary>
504 public void Close(bool sendStop)
505 {
506 m_log.DebugFormat(
507 "[CLIENT]: Close has been called for {0} attached to scene {1}",
508 Name, m_scene.RegionInfo.RegionName);
509
510 if (sendStop)
511 {
512 // Send the STOP packet
513 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
514 OutPacket(disable, ThrottleOutPacketType.Unknown);
515 }
516
517 IsActive = false;
518
519 // Shutdown the image manager
520 if (m_imageManager != null)
521 m_imageManager.Close();
522
523 // Fire the callback for this connection closing
524 if (OnConnectionClosed != null)
525 OnConnectionClosed(this);
526
527 // Flush all of the packets out of the UDP server for this client
528 if (m_udpServer != null)
529 m_udpServer.Flush(m_udpClient);
530
531 // Remove ourselves from the scene
532 m_scene.RemoveClient(AgentId);
533
534 // We can't reach into other scenes and close the connection
535 // We need to do this over grid communications
536 //m_scene.CloseAllAgents(CircuitCode);
537
538 // Disable UDP handling for this client
539 m_udpClient.Shutdown();
540
541 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
542 //GC.Collect();
543 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
544 }
545
546 public void Kick(string message)
547 {
548 if (!ChildAgentStatus())
549 {
550 KickUserPacket kupack = (KickUserPacket)PacketPool.Instance.GetPacket(PacketType.KickUser);
551 kupack.UserInfo.AgentID = AgentId;
552 kupack.UserInfo.SessionID = SessionId;
553 kupack.TargetBlock.TargetIP = 0;
554 kupack.TargetBlock.TargetPort = 0;
555 kupack.UserInfo.Reason = Util.StringToBytes256(message);
556 OutPacket(kupack, ThrottleOutPacketType.Task);
557 // You must sleep here or users get no message!
558 Thread.Sleep(500);
559 }
560 }
561
562 public void Stop()
563 {
564
565 }
566
567 #endregion Client Methods
568
569 #region Packet Handling
570
571 public void PopulateStats(int inPackets, int outPackets, int unAckedBytes)
572 {
573 NetworkStats handlerNetworkStatsUpdate = OnNetworkStatsUpdate;
574 if (handlerNetworkStatsUpdate != null)
575 {
576 handlerNetworkStatsUpdate(inPackets, outPackets, unAckedBytes);
577 }
578 }
579
580 public static bool AddPacketHandler(PacketType packetType, PacketMethod handler)
581 {
582 bool result = false;
583 lock (PacketHandlers)
584 {
585 if (!PacketHandlers.ContainsKey(packetType))
586 {
587 PacketHandlers.Add(packetType, handler);
588 result = true;
589 }
590 }
591 return result;
592 }
593
594 public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler)
595 {
596 return AddLocalPacketHandler(packetType, handler, true);
597 }
598
599 public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool async)
600 {
601 bool result = false;
602 lock (m_packetHandlers)
603 {
604 if (!m_packetHandlers.ContainsKey(packetType))
605 {
606 m_packetHandlers.Add(packetType, new PacketProcessor() { method = handler, Async = async });
607 result = true;
608 }
609 }
610 return result;
611 }
612
613 public bool AddGenericPacketHandler(string MethodName, GenericMessage handler)
614 {
615 MethodName = MethodName.ToLower().Trim();
616
617 bool result = false;
618 lock (m_genericPacketHandlers)
619 {
620 if (!m_genericPacketHandlers.ContainsKey(MethodName))
621 {
622 m_genericPacketHandlers.Add(MethodName, handler);
623 result = true;
624 }
625 }
626 return result;
627 }
628
629 /// <summary>
630 /// Try to process a packet using registered packet handlers
631 /// </summary>
632 /// <param name="packet"></param>
633 /// <returns>True if a handler was found which successfully processed the packet.</returns>
634 protected virtual bool ProcessPacketMethod(Packet packet)
635 {
636 bool result = false;
637 PacketProcessor pprocessor;
638 if (m_packetHandlers.TryGetValue(packet.Type, out pprocessor))
639 {
640 //there is a local handler for this packet type
641 if (pprocessor.Async)
642 {
643 object obj = new AsyncPacketProcess(this, pprocessor.method, packet);
644 Util.FireAndForget(ProcessSpecificPacketAsync, obj);
645 result = true;
646 }
647 else
648 {
649 result = pprocessor.method(this, packet);
650 }
651 }
652 else
653 {
654 //there is not a local handler so see if there is a Global handler
655 PacketMethod method = null;
656 bool found;
657 lock (PacketHandlers)
658 {
659 found = PacketHandlers.TryGetValue(packet.Type, out method);
660 }
661 if (found)
662 {
663 result = method(this, packet);
664 }
665 }
666 return result;
667 }
668
669 public void ProcessSpecificPacketAsync(object state)
670 {
671 AsyncPacketProcess packetObject = (AsyncPacketProcess)state;
672
673 try
674 {
675 packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack);
676 }
677 catch (Exception e)
678 {
679 // Make sure that we see any exception caused by the asynchronous operation.
680 m_log.ErrorFormat(
681 "[LLCLIENTVIEW]: Caught exception while processing {0} for {1}, {2} {3}",
682 packetObject.Pack, Name, e.Message, e.StackTrace);
683 }
684 }
685
686 #endregion Packet Handling
687
688 # region Setup
689
690 public virtual void Start()
691 {
692 m_scene.AddNewClient(this);
693
694 RefreshGroupMembership();
695 }
696
697 # endregion
698
699 public void ActivateGesture(UUID assetId, UUID gestureId)
700 {
701 }
702
703 public void DeactivateGesture(UUID assetId, UUID gestureId)
704 {
705 }
706
707 // Sound
708 public void SoundTrigger(UUID soundId, UUID owerid, UUID Objectid, UUID ParentId, float Gain, Vector3 Position, UInt64 Handle)
709 {
710 }
711
712 #region Scene/Avatar to Client
713
714 public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args)
715 {
716 RegionHandshakePacket handshake = (RegionHandshakePacket)PacketPool.Instance.GetPacket(PacketType.RegionHandshake);
717 handshake.RegionInfo = new RegionHandshakePacket.RegionInfoBlock();
718 handshake.RegionInfo.BillableFactor = args.billableFactor;
719 handshake.RegionInfo.IsEstateManager = args.isEstateManager;
720 handshake.RegionInfo.TerrainHeightRange00 = args.terrainHeightRange0;
721 handshake.RegionInfo.TerrainHeightRange01 = args.terrainHeightRange1;
722 handshake.RegionInfo.TerrainHeightRange10 = args.terrainHeightRange2;
723 handshake.RegionInfo.TerrainHeightRange11 = args.terrainHeightRange3;
724 handshake.RegionInfo.TerrainStartHeight00 = args.terrainStartHeight0;
725 handshake.RegionInfo.TerrainStartHeight01 = args.terrainStartHeight1;
726 handshake.RegionInfo.TerrainStartHeight10 = args.terrainStartHeight2;
727 handshake.RegionInfo.TerrainStartHeight11 = args.terrainStartHeight3;
728 handshake.RegionInfo.SimAccess = args.simAccess;
729 handshake.RegionInfo.WaterHeight = args.waterHeight;
730
731 handshake.RegionInfo.RegionFlags = args.regionFlags;
732 handshake.RegionInfo.SimName = Util.StringToBytes256(args.regionName);
733 handshake.RegionInfo.SimOwner = args.SimOwner;
734 handshake.RegionInfo.TerrainBase0 = args.terrainBase0;
735 handshake.RegionInfo.TerrainBase1 = args.terrainBase1;
736 handshake.RegionInfo.TerrainBase2 = args.terrainBase2;
737 handshake.RegionInfo.TerrainBase3 = args.terrainBase3;
738 handshake.RegionInfo.TerrainDetail0 = args.terrainDetail0;
739 handshake.RegionInfo.TerrainDetail1 = args.terrainDetail1;
740 handshake.RegionInfo.TerrainDetail2 = args.terrainDetail2;
741 handshake.RegionInfo.TerrainDetail3 = args.terrainDetail3;
742 handshake.RegionInfo.CacheID = UUID.Random(); //I guess this is for the client to remember an old setting?
743 handshake.RegionInfo2 = new RegionHandshakePacket.RegionInfo2Block();
744 handshake.RegionInfo2.RegionID = regionInfo.RegionID;
745
746 handshake.RegionInfo3 = new RegionHandshakePacket.RegionInfo3Block();
747 handshake.RegionInfo3.CPUClassID = 9;
748 handshake.RegionInfo3.CPURatio = 1;
749
750 handshake.RegionInfo3.ColoName = Utils.EmptyBytes;
751 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType);
752 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes;
753
754 OutPacket(handshake, ThrottleOutPacketType.Task);
755 }
756
757 /// <summary>
758 ///
759 /// </summary>
760 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
761 {
762 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete);
763 mov.SimData.ChannelVersion = m_channelVersion;
764 mov.AgentData.SessionID = m_sessionId;
765 mov.AgentData.AgentID = AgentId;
766 mov.Data.RegionHandle = regInfo.RegionHandle;
767 mov.Data.Timestamp = (uint)Util.UnixTimeSinceEpoch();
768
769 if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0))
770 {
771 mov.Data.Position = m_startpos;
772 }
773 else
774 {
775 mov.Data.Position = pos;
776 }
777 mov.Data.LookAt = look;
778
779 // Hack to get this out immediately and skip the throttles
780 OutPacket(mov, ThrottleOutPacketType.Unknown);
781 }
782
783 public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName,
784 UUID fromAgentID, byte source, byte audible)
785 {
786 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
787 reply.ChatData.Audible = audible;
788 reply.ChatData.Message = Util.StringToBytes1024(message);
789 reply.ChatData.ChatType = type;
790 reply.ChatData.SourceType = source;
791 reply.ChatData.Position = fromPos;
792 reply.ChatData.FromName = Util.StringToBytes256(fromName);
793 reply.ChatData.OwnerID = fromAgentID;
794 reply.ChatData.SourceID = fromAgentID;
795
796 OutPacket(reply, ThrottleOutPacketType.Unknown);
797 }
798
799 /// <summary>
800 /// Send an instant message to this client
801 /// </summary>
802 //
803 // Don't remove transaction ID! Groups and item gives need to set it!
804 public void SendInstantMessage(GridInstantMessage im)
805 {
806 if (((Scene)(m_scene)).Permissions.CanInstantMessage(new UUID(im.fromAgentID), new UUID(im.toAgentID)))
807 {
808 ImprovedInstantMessagePacket msg
809 = (ImprovedInstantMessagePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedInstantMessage);
810
811 msg.AgentData.AgentID = new UUID(im.fromAgentID);
812 msg.AgentData.SessionID = UUID.Zero;
813 msg.MessageBlock.FromAgentName = Util.StringToBytes256(im.fromAgentName);
814 msg.MessageBlock.Dialog = im.dialog;
815 msg.MessageBlock.FromGroup = im.fromGroup;
816 if (im.imSessionID == UUID.Zero.Guid)
817 msg.MessageBlock.ID = new UUID(im.fromAgentID) ^ new UUID(im.toAgentID);
818 else
819 msg.MessageBlock.ID = new UUID(im.imSessionID);
820 msg.MessageBlock.Offline = im.offline;
821 msg.MessageBlock.ParentEstateID = im.ParentEstateID;
822 msg.MessageBlock.Position = im.Position;
823 msg.MessageBlock.RegionID = new UUID(im.RegionID);
824 msg.MessageBlock.Timestamp = im.timestamp;
825 msg.MessageBlock.ToAgentID = new UUID(im.toAgentID);
826 msg.MessageBlock.Message = Util.StringToBytes1024(im.message);
827 msg.MessageBlock.BinaryBucket = im.binaryBucket;
828
829 if (im.message.StartsWith("[grouptest]"))
830 { // this block is test code for implementing group IM - delete when group IM is finished
831 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
832 if (eq != null)
833 {
834 im.dialog = 17;
835
836 //eq.ChatterboxInvitation(
837 // new UUID("00000000-68f9-1111-024e-222222111123"),
838 // "OpenSimulator Testing", im.fromAgentID, im.message, im.toAgentID, im.fromAgentName, im.dialog, 0,
839 // false, 0, new Vector3(), 1, im.imSessionID, im.fromGroup, im.binaryBucket);
840
841 eq.ChatterboxInvitation(
842 new UUID("00000000-68f9-1111-024e-222222111123"),
843 "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0,
844 false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Util.StringToBytes256("OpenSimulator Testing"));
845
846 eq.ChatterBoxSessionAgentListUpdates(
847 new UUID("00000000-68f9-1111-024e-222222111123"),
848 new UUID(im.fromAgentID), new UUID(im.toAgentID), false, false, false);
849 }
850
851 Console.WriteLine("SendInstantMessage: " + msg);
852 }
853 else
854 OutPacket(msg, ThrottleOutPacketType.Task);
855 }
856 }
857
858 public void SendGenericMessage(string method, List<string> message)
859 {
860 GenericMessagePacket gmp = new GenericMessagePacket();
861 gmp.MethodData.Method = Util.StringToBytes256(method);
862 gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count];
863 int i = 0;
864 foreach (string val in message)
865 {
866 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock();
867 gmp.ParamList[i++].Parameter = Util.StringToBytes256(val);
868 }
869
870 OutPacket(gmp, ThrottleOutPacketType.Task);
871 }
872
873 public void SendGenericMessage(string method, List<byte[]> message)
874 {
875 GenericMessagePacket gmp = new GenericMessagePacket();
876 gmp.MethodData.Method = Util.StringToBytes256(method);
877 gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count];
878 int i = 0;
879 foreach (byte[] val in message)
880 {
881 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock();
882 gmp.ParamList[i++].Parameter = val;
883 }
884
885 OutPacket(gmp, ThrottleOutPacketType.Task);
886 }
887
888 public void SendGroupActiveProposals(UUID groupID, UUID transactionID, GroupActiveProposals[] Proposals)
889 {
890 int i = 0;
891 foreach (GroupActiveProposals Proposal in Proposals)
892 {
893 GroupActiveProposalItemReplyPacket GAPIRP = new GroupActiveProposalItemReplyPacket();
894
895 GAPIRP.AgentData.AgentID = AgentId;
896 GAPIRP.AgentData.GroupID = groupID;
897 GAPIRP.TransactionData.TransactionID = transactionID;
898 GAPIRP.TransactionData.TotalNumItems = ((uint)i+1);
899 GroupActiveProposalItemReplyPacket.ProposalDataBlock ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock();
900 GAPIRP.ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock[1];
901 ProposalData.VoteCast = Utils.StringToBytes("false");
902 ProposalData.VoteID = new UUID(Proposal.VoteID);
903 ProposalData.VoteInitiator = new UUID(Proposal.VoteInitiator);
904 ProposalData.Majority = (float)Convert.ToInt32(Proposal.Majority);
905 ProposalData.Quorum = Convert.ToInt32(Proposal.Quorum);
906 ProposalData.TerseDateID = Utils.StringToBytes(Proposal.TerseDateID);
907 ProposalData.StartDateTime = Utils.StringToBytes(Proposal.StartDateTime);
908 ProposalData.EndDateTime = Utils.StringToBytes(Proposal.EndDateTime);
909 ProposalData.ProposalText = Utils.StringToBytes(Proposal.ProposalText);
910 ProposalData.AlreadyVoted = false;
911 GAPIRP.ProposalData[i] = ProposalData;
912 OutPacket(GAPIRP, ThrottleOutPacketType.Task);
913 i++;
914 }
915 if (Proposals.Length == 0)
916 {
917 GroupActiveProposalItemReplyPacket GAPIRP = new GroupActiveProposalItemReplyPacket();
918
919 GAPIRP.AgentData.AgentID = AgentId;
920 GAPIRP.AgentData.GroupID = groupID;
921 GAPIRP.TransactionData.TransactionID = transactionID;
922 GAPIRP.TransactionData.TotalNumItems = 1;
923 GroupActiveProposalItemReplyPacket.ProposalDataBlock ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock();
924 GAPIRP.ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock[1];
925 ProposalData.VoteCast = Utils.StringToBytes("false");
926 ProposalData.VoteID = UUID.Zero;
927 ProposalData.VoteInitiator = UUID.Zero;
928 ProposalData.Majority = 0;
929 ProposalData.Quorum = 0;
930 ProposalData.TerseDateID = Utils.StringToBytes("");
931 ProposalData.StartDateTime = Utils.StringToBytes("");
932 ProposalData.EndDateTime = Utils.StringToBytes("");
933 ProposalData.ProposalText = Utils.StringToBytes("");
934 ProposalData.AlreadyVoted = false;
935 GAPIRP.ProposalData[0] = ProposalData;
936 OutPacket(GAPIRP, ThrottleOutPacketType.Task);
937 }
938 }
939
940 public void SendGroupVoteHistory(UUID groupID, UUID transactionID, GroupVoteHistory[] Votes)
941 {
942 int i = 0;
943 foreach (GroupVoteHistory Vote in Votes)
944 {
945 GroupVoteHistoryItemReplyPacket GVHIRP = new GroupVoteHistoryItemReplyPacket();
946
947 GVHIRP.AgentData.AgentID = AgentId;
948 GVHIRP.AgentData.GroupID = groupID;
949 GVHIRP.TransactionData.TransactionID = transactionID;
950 GVHIRP.TransactionData.TotalNumItems = ((uint)i+1);
951 GVHIRP.HistoryItemData.VoteID = new UUID(Vote.VoteID);
952 GVHIRP.HistoryItemData.VoteInitiator = new UUID(Vote.VoteInitiator);
953 GVHIRP.HistoryItemData.Majority = (float)Convert.ToInt32(Vote.Majority);
954 GVHIRP.HistoryItemData.Quorum = Convert.ToInt32(Vote.Quorum);
955 GVHIRP.HistoryItemData.TerseDateID = Utils.StringToBytes(Vote.TerseDateID);
956 GVHIRP.HistoryItemData.StartDateTime = Utils.StringToBytes(Vote.StartDateTime);
957 GVHIRP.HistoryItemData.EndDateTime = Utils.StringToBytes(Vote.EndDateTime);
958 GVHIRP.HistoryItemData.VoteType = Utils.StringToBytes(Vote.VoteType);
959 GVHIRP.HistoryItemData.VoteResult = Utils.StringToBytes(Vote.VoteResult);
960 GVHIRP.HistoryItemData.ProposalText = Utils.StringToBytes(Vote.ProposalText);
961 GroupVoteHistoryItemReplyPacket.VoteItemBlock VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock();
962 GVHIRP.VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock[1];
963 VoteItem.CandidateID = UUID.Zero;
964 VoteItem.NumVotes = 0; //TODO: FIX THIS!!!
965 VoteItem.VoteCast = Utils.StringToBytes("Yes");
966 GVHIRP.VoteItem[i] = VoteItem;
967 OutPacket(GVHIRP, ThrottleOutPacketType.Task);
968 i++;
969 }
970 if (Votes.Length == 0)
971 {
972 GroupVoteHistoryItemReplyPacket GVHIRP = new GroupVoteHistoryItemReplyPacket();
973
974 GVHIRP.AgentData.AgentID = AgentId;
975 GVHIRP.AgentData.GroupID = groupID;
976 GVHIRP.TransactionData.TransactionID = transactionID;
977 GVHIRP.TransactionData.TotalNumItems = 0;
978 GVHIRP.HistoryItemData.VoteID = UUID.Zero;
979 GVHIRP.HistoryItemData.VoteInitiator = UUID.Zero;
980 GVHIRP.HistoryItemData.Majority = 0;
981 GVHIRP.HistoryItemData.Quorum = 0;
982 GVHIRP.HistoryItemData.TerseDateID = Utils.StringToBytes("");
983 GVHIRP.HistoryItemData.StartDateTime = Utils.StringToBytes("");
984 GVHIRP.HistoryItemData.EndDateTime = Utils.StringToBytes("");
985 GVHIRP.HistoryItemData.VoteType = Utils.StringToBytes("");
986 GVHIRP.HistoryItemData.VoteResult = Utils.StringToBytes("");
987 GVHIRP.HistoryItemData.ProposalText = Utils.StringToBytes("");
988 GroupVoteHistoryItemReplyPacket.VoteItemBlock VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock();
989 GVHIRP.VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock[1];
990 VoteItem.CandidateID = UUID.Zero;
991 VoteItem.NumVotes = 0; //TODO: FIX THIS!!!
992 VoteItem.VoteCast = Utils.StringToBytes("No");
993 GVHIRP.VoteItem[0] = VoteItem;
994 OutPacket(GVHIRP, ThrottleOutPacketType.Task);
995 }
996 }
997
998 public void SendGroupAccountingDetails(IClientAPI sender,UUID groupID, UUID transactionID, UUID sessionID, int amt)
999 {
1000 GroupAccountDetailsReplyPacket GADRP = new GroupAccountDetailsReplyPacket();
1001 GADRP.AgentData = new GroupAccountDetailsReplyPacket.AgentDataBlock();
1002 GADRP.AgentData.AgentID = sender.AgentId;
1003 GADRP.AgentData.GroupID = groupID;
1004 GADRP.HistoryData = new GroupAccountDetailsReplyPacket.HistoryDataBlock[1];
1005 GroupAccountDetailsReplyPacket.HistoryDataBlock History = new GroupAccountDetailsReplyPacket.HistoryDataBlock();
1006 GADRP.MoneyData = new GroupAccountDetailsReplyPacket.MoneyDataBlock();
1007 GADRP.MoneyData.CurrentInterval = 0;
1008 GADRP.MoneyData.IntervalDays = 7;
1009 GADRP.MoneyData.RequestID = transactionID;
1010 GADRP.MoneyData.StartDate = Utils.StringToBytes(DateTime.Today.ToString());
1011 History.Amount = amt;
1012 History.Description = Utils.StringToBytes("");
1013 GADRP.HistoryData[0] = History;
1014 OutPacket(GADRP, ThrottleOutPacketType.Task);
1015 }
1016
1017 public void SendGroupAccountingSummary(IClientAPI sender,UUID groupID, uint moneyAmt, int totalTier, int usedTier)
1018 {
1019 GroupAccountSummaryReplyPacket GASRP =
1020 (GroupAccountSummaryReplyPacket)PacketPool.Instance.GetPacket(
1021 PacketType.GroupAccountSummaryReply);
1022
1023 GASRP.AgentData = new GroupAccountSummaryReplyPacket.AgentDataBlock();
1024 GASRP.AgentData.AgentID = sender.AgentId;
1025 GASRP.AgentData.GroupID = groupID;
1026 GASRP.MoneyData = new GroupAccountSummaryReplyPacket.MoneyDataBlock();
1027 GASRP.MoneyData.Balance = (int)moneyAmt;
1028 GASRP.MoneyData.TotalCredits = totalTier;
1029 GASRP.MoneyData.TotalDebits = usedTier;
1030 GASRP.MoneyData.StartDate = new byte[1];
1031 GASRP.MoneyData.CurrentInterval = 1;
1032 GASRP.MoneyData.GroupTaxCurrent = 0;
1033 GASRP.MoneyData.GroupTaxEstimate = 0;
1034 GASRP.MoneyData.IntervalDays = 0;
1035 GASRP.MoneyData.LandTaxCurrent = 0;
1036 GASRP.MoneyData.LandTaxEstimate = 0;
1037 GASRP.MoneyData.LastTaxDate = new byte[1];
1038 GASRP.MoneyData.LightTaxCurrent = 0;
1039 GASRP.MoneyData.TaxDate = new byte[1];
1040 GASRP.MoneyData.RequestID = sender.AgentId;
1041 GASRP.MoneyData.ParcelDirFeeEstimate = 0;
1042 GASRP.MoneyData.ParcelDirFeeCurrent = 0;
1043 GASRP.MoneyData.ObjectTaxEstimate = 0;
1044 GASRP.MoneyData.NonExemptMembers = 0;
1045 GASRP.MoneyData.ObjectTaxCurrent = 0;
1046 GASRP.MoneyData.LightTaxEstimate = 0;
1047 OutPacket(GASRP, ThrottleOutPacketType.Task);
1048 }
1049
1050 public void SendGroupTransactionsSummaryDetails(IClientAPI sender,UUID groupID, UUID transactionID, UUID sessionID, int amt)
1051 {
1052 GroupAccountTransactionsReplyPacket GATRP =
1053 (GroupAccountTransactionsReplyPacket)PacketPool.Instance.GetPacket(
1054 PacketType.GroupAccountTransactionsReply);
1055
1056 GATRP.AgentData = new GroupAccountTransactionsReplyPacket.AgentDataBlock();
1057 GATRP.AgentData.AgentID = sender.AgentId;
1058 GATRP.AgentData.GroupID = groupID;
1059 GATRP.MoneyData = new GroupAccountTransactionsReplyPacket.MoneyDataBlock();
1060 GATRP.MoneyData.CurrentInterval = 0;
1061 GATRP.MoneyData.IntervalDays = 7;
1062 GATRP.MoneyData.RequestID = transactionID;
1063 GATRP.MoneyData.StartDate = Utils.StringToBytes(DateTime.Today.ToString());
1064 GATRP.HistoryData = new GroupAccountTransactionsReplyPacket.HistoryDataBlock[1];
1065 GroupAccountTransactionsReplyPacket.HistoryDataBlock History = new GroupAccountTransactionsReplyPacket.HistoryDataBlock();
1066 History.Amount = 0;
1067 History.Item = Utils.StringToBytes("");
1068 History.Time = Utils.StringToBytes("");
1069 History.Type = 0;
1070 History.User = Utils.StringToBytes("");
1071 GATRP.HistoryData[0] = History;
1072 OutPacket(GATRP, ThrottleOutPacketType.Task);
1073 }
1074
1075 /// <summary>
1076 /// Send the region heightmap to the client
1077 /// </summary>
1078 /// <param name="map">heightmap</param>
1079 public virtual void SendLayerData(float[] map)
1080 {
1081 Util.FireAndForget(DoSendLayerData, map);
1082
1083 // Send it sync, and async. It's not that much data
1084 // and it improves user experience just so much!
1085 DoSendLayerData(map);
1086 }
1087
1088 /// <summary>
1089 /// Send terrain layer information to the client.
1090 /// </summary>
1091 /// <param name="o"></param>
1092 private void DoSendLayerData(object o)
1093 {
1094 float[] map = LLHeightFieldMoronize((float[])o);
1095
1096 try
1097 {
1098 for (int y = 0; y < 16; y++)
1099 {
1100 for (int x = 0; x < 16; x+=4)
1101 {
1102 SendLayerPacket(x, y, map);
1103 }
1104 }
1105 }
1106 catch (Exception e)
1107 {
1108 m_log.Error("[CLIENT]: SendLayerData() Failed with exception: " + e.Message, e);
1109 }
1110 }
1111
1112 /// <summary>
1113 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1114 /// </summary>
1115 /// <param name="map">heightmap</param>
1116 /// <param name="px">X coordinate for patches 0..12</param>
1117 /// <param name="py">Y coordinate for patches 0..15</param>
1118 private void SendLayerPacket(int x, int y, float[] map)
1119 {
1120 int[] patches = new int[4];
1121 patches[0] = x + 0 + y * 16;
1122 patches[1] = x + 1 + y * 16;
1123 patches[2] = x + 2 + y * 16;
1124 patches[3] = x + 3 + y * 16;
1125
1126 float[] heightmap = (map.Length == 65536) ?
1127 map :
1128 LLHeightFieldMoronize(map);
1129
1130 try
1131 {
1132 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1133 OutPacket(layerpack, ThrottleOutPacketType.Land);
1134 }
1135 catch
1136 {
1137 for (int px = x ; px < x + 4 ; px++)
1138 SendLayerData(px, y, map);
1139 }
1140 }
1141
1142 /// <summary>
1143 /// Sends a specified patch to a client
1144 /// </summary>
1145 /// <param name="px">Patch coordinate (x) 0..15</param>
1146 /// <param name="py">Patch coordinate (y) 0..15</param>
1147 /// <param name="map">heightmap</param>
1148 public void SendLayerData(int px, int py, float[] map)
1149 {
1150 try
1151 {
1152 int[] patches = new int[] { py * 16 + px };
1153 float[] heightmap = (map.Length == 65536) ?
1154 map :
1155 LLHeightFieldMoronize(map);
1156
1157 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1158 layerpack.Header.Reliable = true;
1159
1160 OutPacket(layerpack, ThrottleOutPacketType.Task);
1161 }
1162 catch (Exception e)
1163 {
1164 m_log.Error("[CLIENT]: SendLayerData() Failed with exception: " + e.Message, e);
1165 }
1166 }
1167
1168 /// <summary>
1169 /// Munges heightfield into the LLUDP backed in restricted heightfield.
1170 /// </summary>
1171 /// <param name="map">float array in the base; Constants.RegionSize</param>
1172 /// <returns>float array in the base 256</returns>
1173 internal float[] LLHeightFieldMoronize(float[] map)
1174 {
1175 if (map.Length == 65536)
1176 return map;
1177 else
1178 {
1179 float[] returnmap = new float[65536];
1180
1181 if (map.Length < 65535)
1182 {
1183 // rebase the vector stride to 256
1184 for (int i = 0; i < Constants.RegionSize; i++)
1185 Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, (int)Constants.RegionSize);
1186 }
1187 else
1188 {
1189 for (int i = 0; i < 256; i++)
1190 Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256);
1191 }
1192
1193 //Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536);
1194
1195 return returnmap;
1196 }
1197
1198 }
1199
1200 /// <summary>
1201 /// Send the wind matrix to the client
1202 /// </summary>
1203 /// <param name="windSpeeds">16x16 array of wind speeds</param>
1204 public virtual void SendWindData(Vector2[] windSpeeds)
1205 {
1206 Util.FireAndForget(DoSendWindData, windSpeeds);
1207 }
1208
1209 /// <summary>
1210 /// Send the cloud matrix to the client
1211 /// </summary>
1212 /// <param name="windSpeeds">16x16 array of cloud densities</param>
1213 public virtual void SendCloudData(float[] cloudDensity)
1214 {
1215 Util.FireAndForget(DoSendCloudData, cloudDensity);
1216 }
1217
1218 /// <summary>
1219 /// Send wind layer information to the client.
1220 /// </summary>
1221 /// <param name="o"></param>
1222 private void DoSendWindData(object o)
1223 {
1224 Vector2[] windSpeeds = (Vector2[])o;
1225 TerrainPatch[] patches = new TerrainPatch[2];
1226 patches[0] = new TerrainPatch();
1227 patches[0].Data = new float[16 * 16];
1228 patches[1] = new TerrainPatch();
1229 patches[1].Data = new float[16 * 16];
1230
1231 for (int y = 0; y < 16; y++)
1232 {
1233 for (int x = 0; x < 16; x++)
1234 {
1235 patches[0].Data[y * 16 + x] = windSpeeds[y * 16 + x].X;
1236 patches[1].Data[y * 16 + x] = windSpeeds[y * 16 + x].Y;
1237 }
1238 }
1239
1240 LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Wind);
1241 layerpack.Header.Zerocoded = true;
1242 OutPacket(layerpack, ThrottleOutPacketType.Wind);
1243 }
1244
1245 /// <summary>
1246 /// Send cloud layer information to the client.
1247 /// </summary>
1248 /// <param name="o"></param>
1249 private void DoSendCloudData(object o)
1250 {
1251 float[] cloudCover = (float[])o;
1252 TerrainPatch[] patches = new TerrainPatch[1];
1253 patches[0] = new TerrainPatch();
1254 patches[0].Data = new float[16 * 16];
1255
1256 for (int y = 0; y < 16; y++)
1257 {
1258 for (int x = 0; x < 16; x++)
1259 {
1260 patches[0].Data[y * 16 + x] = cloudCover[y * 16 + x];
1261 }
1262 }
1263
1264 LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Cloud);
1265 layerpack.Header.Zerocoded = true;
1266 OutPacket(layerpack, ThrottleOutPacketType.Cloud);
1267 }
1268
1269 /// <summary>
1270 /// Tell the client that the given neighbour region is ready to receive a child agent.
1271 /// </summary>
1272 public virtual void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourEndPoint)
1273 {
1274 IPAddress neighbourIP = neighbourEndPoint.Address;
1275 ushort neighbourPort = (ushort)neighbourEndPoint.Port;
1276
1277 EnableSimulatorPacket enablesimpacket = (EnableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.EnableSimulator);
1278 // TODO: don't create new blocks if recycling an old packet
1279 enablesimpacket.SimulatorInfo = new EnableSimulatorPacket.SimulatorInfoBlock();
1280 enablesimpacket.SimulatorInfo.Handle = neighbourHandle;
1281
1282 byte[] byteIP = neighbourIP.GetAddressBytes();
1283 enablesimpacket.SimulatorInfo.IP = (uint)byteIP[3] << 24;
1284 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[2] << 16;
1285 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[1] << 8;
1286 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[0];
1287 enablesimpacket.SimulatorInfo.Port = neighbourPort;
1288
1289 enablesimpacket.Header.Reliable = true; // ESP's should be reliable.
1290
1291 OutPacket(enablesimpacket, ThrottleOutPacketType.Task);
1292 }
1293
1294 public AgentCircuitData RequestClientInfo()
1295 {
1296 AgentCircuitData agentData = new AgentCircuitData();
1297 agentData.AgentID = AgentId;
1298 agentData.SessionID = m_sessionId;
1299 agentData.SecureSessionID = SecureSessionId;
1300 agentData.circuitcode = m_circuitCode;
1301 agentData.child = false;
1302 agentData.firstname = m_firstName;
1303 agentData.lastname = m_lastName;
1304
1305 ICapabilitiesModule capsModule = m_scene.RequestModuleInterface<ICapabilitiesModule>();
1306
1307 if (capsModule == null) // can happen when shutting down.
1308 return agentData;
1309
1310 agentData.CapsPath = capsModule.GetCapsPath(m_agentId);
1311 agentData.ChildrenCapSeeds = new Dictionary<ulong, string>(capsModule.GetChildrenSeeds(m_agentId));
1312
1313 return agentData;
1314 }
1315
1316 public virtual void CrossRegion(ulong newRegionHandle, Vector3 pos, Vector3 lookAt, IPEndPoint externalIPEndPoint,
1317 string capsURL)
1318 {
1319 Vector3 look = new Vector3(lookAt.X * 10, lookAt.Y * 10, lookAt.Z * 10);
1320
1321 //CrossedRegionPacket newSimPack = (CrossedRegionPacket)PacketPool.Instance.GetPacket(PacketType.CrossedRegion);
1322 CrossedRegionPacket newSimPack = new CrossedRegionPacket();
1323 // TODO: don't create new blocks if recycling an old packet
1324 newSimPack.AgentData = new CrossedRegionPacket.AgentDataBlock();
1325 newSimPack.AgentData.AgentID = AgentId;
1326 newSimPack.AgentData.SessionID = m_sessionId;
1327 newSimPack.Info = new CrossedRegionPacket.InfoBlock();
1328 newSimPack.Info.Position = pos;
1329 newSimPack.Info.LookAt = look;
1330 newSimPack.RegionData = new CrossedRegionPacket.RegionDataBlock();
1331 newSimPack.RegionData.RegionHandle = newRegionHandle;
1332 byte[] byteIP = externalIPEndPoint.Address.GetAddressBytes();
1333 newSimPack.RegionData.SimIP = (uint)byteIP[3] << 24;
1334 newSimPack.RegionData.SimIP += (uint)byteIP[2] << 16;
1335 newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8;
1336 newSimPack.RegionData.SimIP += (uint)byteIP[0];
1337 newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port;
1338 newSimPack.RegionData.SeedCapability = Util.StringToBytes256(capsURL);
1339
1340 // Hack to get this out immediately and skip throttles
1341 OutPacket(newSimPack, ThrottleOutPacketType.Unknown);
1342 }
1343
1344 internal void SendMapBlockSplit(List<MapBlockData> mapBlocks, uint flag)
1345 {
1346 MapBlockReplyPacket mapReply = (MapBlockReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapBlockReply);
1347 // TODO: don't create new blocks if recycling an old packet
1348
1349 MapBlockData[] mapBlocks2 = mapBlocks.ToArray();
1350
1351 mapReply.AgentData.AgentID = AgentId;
1352 mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length];
1353 mapReply.AgentData.Flags = flag;
1354
1355 for (int i = 0; i < mapBlocks2.Length; i++)
1356 {
1357 mapReply.Data[i] = new MapBlockReplyPacket.DataBlock();
1358 mapReply.Data[i].MapImageID = mapBlocks2[i].MapImageId;
1359 //m_log.Warn(mapBlocks2[i].MapImageId.ToString());
1360 mapReply.Data[i].X = mapBlocks2[i].X;
1361 mapReply.Data[i].Y = mapBlocks2[i].Y;
1362 mapReply.Data[i].WaterHeight = mapBlocks2[i].WaterHeight;
1363 mapReply.Data[i].Name = Utils.StringToBytes(mapBlocks2[i].Name);
1364 mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags;
1365 mapReply.Data[i].Access = mapBlocks2[i].Access;
1366 mapReply.Data[i].Agents = mapBlocks2[i].Agents;
1367 }
1368 OutPacket(mapReply, ThrottleOutPacketType.Land);
1369 }
1370
1371 public void SendMapBlock(List<MapBlockData> mapBlocks, uint flag)
1372 {
1373
1374 MapBlockData[] mapBlocks2 = mapBlocks.ToArray();
1375
1376 int maxsend = 10;
1377
1378 //int packets = Math.Ceiling(mapBlocks2.Length / maxsend);
1379
1380 List<MapBlockData> sendingBlocks = new List<MapBlockData>();
1381
1382 for (int i = 0; i < mapBlocks2.Length; i++)
1383 {
1384 sendingBlocks.Add(mapBlocks2[i]);
1385 if (((i + 1) == mapBlocks2.Length) || (((i + 1) % maxsend) == 0))
1386 {
1387 SendMapBlockSplit(sendingBlocks, flag);
1388 sendingBlocks = new List<MapBlockData>();
1389 }
1390 }
1391 }
1392
1393 public void SendLocalTeleport(Vector3 position, Vector3 lookAt, uint flags)
1394 {
1395 TeleportLocalPacket tpLocal = (TeleportLocalPacket)PacketPool.Instance.GetPacket(PacketType.TeleportLocal);
1396 tpLocal.Info.AgentID = AgentId;
1397 tpLocal.Info.TeleportFlags = flags;
1398 tpLocal.Info.LocationID = 2;
1399 tpLocal.Info.LookAt = lookAt;
1400 tpLocal.Info.Position = position;
1401
1402 // Hack to get this out immediately and skip throttles
1403 OutPacket(tpLocal, ThrottleOutPacketType.Unknown);
1404 }
1405
1406 public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint newRegionEndPoint, uint locationID,
1407 uint flags, string capsURL)
1408 {
1409 //TeleportFinishPacket teleport = (TeleportFinishPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFinish);
1410
1411 TeleportFinishPacket teleport = new TeleportFinishPacket();
1412 teleport.Info.AgentID = AgentId;
1413 teleport.Info.RegionHandle = regionHandle;
1414 teleport.Info.SimAccess = simAccess;
1415
1416 teleport.Info.SeedCapability = Util.StringToBytes256(capsURL);
1417
1418 IPAddress oIP = newRegionEndPoint.Address;
1419 byte[] byteIP = oIP.GetAddressBytes();
1420 uint ip = (uint)byteIP[3] << 24;
1421 ip += (uint)byteIP[2] << 16;
1422 ip += (uint)byteIP[1] << 8;
1423 ip += (uint)byteIP[0];
1424
1425 teleport.Info.SimIP = ip;
1426 teleport.Info.SimPort = (ushort)newRegionEndPoint.Port;
1427 teleport.Info.LocationID = 4;
1428 teleport.Info.TeleportFlags = 1 << 4;
1429
1430 // Hack to get this out immediately and skip throttles.
1431 OutPacket(teleport, ThrottleOutPacketType.Unknown);
1432 }
1433
1434 /// <summary>
1435 /// Inform the client that a teleport attempt has failed
1436 /// </summary>
1437 public void SendTeleportFailed(string reason)
1438 {
1439 TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed);
1440 tpFailed.Info.AgentID = AgentId;
1441 tpFailed.Info.Reason = Util.StringToBytes256(reason);
1442 tpFailed.AlertInfo = new TeleportFailedPacket.AlertInfoBlock[0];
1443
1444 // Hack to get this out immediately and skip throttles
1445 OutPacket(tpFailed, ThrottleOutPacketType.Unknown);
1446 }
1447
1448 /// <summary>
1449 ///
1450 /// </summary>
1451 public void SendTeleportStart(uint flags)
1452 {
1453 TeleportStartPacket tpStart = (TeleportStartPacket)PacketPool.Instance.GetPacket(PacketType.TeleportStart);
1454 //TeleportStartPacket tpStart = new TeleportStartPacket();
1455 tpStart.Info.TeleportFlags = flags; //16; // Teleport via location
1456
1457 // Hack to get this out immediately and skip throttles
1458 OutPacket(tpStart, ThrottleOutPacketType.Unknown);
1459 }
1460
1461 public void SendTeleportProgress(uint flags, string message)
1462 {
1463 TeleportProgressPacket tpProgress = (TeleportProgressPacket)PacketPool.Instance.GetPacket(PacketType.TeleportProgress);
1464 tpProgress.AgentData.AgentID = this.AgentId;
1465 tpProgress.Info.TeleportFlags = flags;
1466 tpProgress.Info.Message = Util.StringToBytes256(message);
1467
1468 // Hack to get this out immediately and skip throttles
1469 OutPacket(tpProgress, ThrottleOutPacketType.Unknown);
1470 }
1471
1472 public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance)
1473 {
1474 MoneyBalanceReplyPacket money = (MoneyBalanceReplyPacket)PacketPool.Instance.GetPacket(PacketType.MoneyBalanceReply);
1475 money.MoneyData.AgentID = AgentId;
1476 money.MoneyData.TransactionID = transaction;
1477 money.MoneyData.TransactionSuccess = success;
1478 money.MoneyData.Description = description;
1479 money.MoneyData.MoneyBalance = balance;
1480 OutPacket(money, ThrottleOutPacketType.Task);
1481 }
1482
1483 public void SendPayPrice(UUID objectID, int[] payPrice)
1484 {
1485 if (payPrice[0] == 0 &&
1486 payPrice[1] == 0 &&
1487 payPrice[2] == 0 &&
1488 payPrice[3] == 0 &&
1489 payPrice[4] == 0)
1490 return;
1491
1492 PayPriceReplyPacket payPriceReply = (PayPriceReplyPacket)PacketPool.Instance.GetPacket(PacketType.PayPriceReply);
1493 payPriceReply.ObjectData.ObjectID = objectID;
1494 payPriceReply.ObjectData.DefaultPayPrice = payPrice[0];
1495
1496 payPriceReply.ButtonData = new PayPriceReplyPacket.ButtonDataBlock[4];
1497 payPriceReply.ButtonData[0] = new PayPriceReplyPacket.ButtonDataBlock();
1498 payPriceReply.ButtonData[0].PayButton = payPrice[1];
1499 payPriceReply.ButtonData[1] = new PayPriceReplyPacket.ButtonDataBlock();
1500 payPriceReply.ButtonData[1].PayButton = payPrice[2];
1501 payPriceReply.ButtonData[2] = new PayPriceReplyPacket.ButtonDataBlock();
1502 payPriceReply.ButtonData[2].PayButton = payPrice[3];
1503 payPriceReply.ButtonData[3] = new PayPriceReplyPacket.ButtonDataBlock();
1504 payPriceReply.ButtonData[3].PayButton = payPrice[4];
1505
1506 OutPacket(payPriceReply, ThrottleOutPacketType.Task);
1507 }
1508
1509 public void SendStartPingCheck(byte seq)
1510 {
1511 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck);
1512 pc.Header.Reliable = false;
1513
1514 pc.PingID.PingID = seq;
1515 // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit
1516 pc.PingID.OldestUnacked = 0;
1517
1518 OutPacket(pc, ThrottleOutPacketType.Unknown);
1519 }
1520
1521 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1522 {
1523// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle);
1524
1525 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1526 // TODO: don't create new blocks if recycling an old packet
1527 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count];
1528 for (int i = 0 ; i < localIDs.Count ; i++ )
1529 {
1530 kill.ObjectData[i] = new KillObjectPacket.ObjectDataBlock();
1531 kill.ObjectData[i].ID = localIDs[i];
1532 }
1533 kill.Header.Reliable = true;
1534 kill.Header.Zerocoded = true;
1535
1536 lock (m_killRecord)
1537 {
1538 if (localIDs.Count == 1)
1539 {
1540 if (m_scene.GetScenePresence(localIDs[0]) != null)
1541 {
1542 OutPacket(kill, ThrottleOutPacketType.State);
1543 return;
1544 }
1545 m_killRecord.Add(localIDs[0]);
1546 }
1547 else
1548 {
1549 lock (m_entityUpdates.SyncRoot)
1550 {
1551 foreach (uint localID in localIDs)
1552 m_killRecord.Add(localID);
1553 }
1554 }
1555 }
1556
1557 // The throttle queue used here must match that being used for
1558 // updates. Otherwise, there is a chance that a kill packet put
1559 // on a separate queue will be sent to the client before an
1560 // existing update packet on another queue. Receiving updates
1561 // after kills results in unowned and undeletable
1562 // scene objects in a viewer until that viewer is relogged in.
1563 OutPacket(kill, ThrottleOutPacketType.Task);
1564 }
1565
1566 /// <summary>
1567 /// Send information about the items contained in a folder to the client.
1568 ///
1569 /// XXX This method needs some refactoring loving
1570 /// </summary>
1571 /// <param name="ownerID">The owner of the folder</param>
1572 /// <param name="folderID">The id of the folder</param>
1573 /// <param name="items">The items contained in the folder identified by folderID</param>
1574 /// <param name="folders"></param>
1575 /// <param name="fetchFolders">Do we need to send folder information?</param>
1576 /// <param name="fetchItems">Do we need to send item information?</param>
1577 public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items,
1578 List<InventoryFolderBase> folders, int version,
1579 bool fetchFolders, bool fetchItems)
1580 {
1581 // An inventory descendents packet consists of a single agent section and an inventory details
1582 // section for each inventory item. The size of each inventory item is approximately 550 bytes.
1583 // In theory, UDP has a maximum packet size of 64k, so it should be possible to send descendent
1584 // packets containing metadata for in excess of 100 items. But in practice, there may be other
1585 // factors (e.g. firewalls) restraining the maximum UDP packet size. See,
1586 //
1587 // http://opensimulator.org/mantis/view.php?id=226
1588 //
1589 // for one example of this kind of thing. In fact, the Linden servers appear to only send about
1590 // 6 to 7 items at a time, so let's stick with 6
1591 int MAX_ITEMS_PER_PACKET = 5;
1592 int MAX_FOLDERS_PER_PACKET = 6;
1593
1594 int totalItems = fetchItems ? items.Count : 0;
1595 int totalFolders = fetchFolders ? folders.Count : 0;
1596 int itemsSent = 0;
1597 int foldersSent = 0;
1598 int foldersToSend = 0;
1599 int itemsToSend = 0;
1600
1601 InventoryDescendentsPacket currentPacket = null;
1602
1603 // Handle empty folders
1604 //
1605 if (totalItems == 0 && totalFolders == 0)
1606 currentPacket = CreateInventoryDescendentsPacket(ownerID, folderID, version, items.Count + folders.Count, 0, 0);
1607
1608 // To preserve SL compatibility, we will NOT combine folders and items in one packet
1609 //
1610 while (itemsSent < totalItems || foldersSent < totalFolders)
1611 {
1612 if (currentPacket == null) // Start a new packet
1613 {
1614 foldersToSend = totalFolders - foldersSent;
1615 if (foldersToSend > MAX_FOLDERS_PER_PACKET)
1616 foldersToSend = MAX_FOLDERS_PER_PACKET;
1617
1618 if (foldersToSend == 0)
1619 {
1620 itemsToSend = totalItems - itemsSent;
1621 if (itemsToSend > MAX_ITEMS_PER_PACKET)
1622 itemsToSend = MAX_ITEMS_PER_PACKET;
1623 }
1624
1625 currentPacket = CreateInventoryDescendentsPacket(ownerID, folderID, version, items.Count + folders.Count, foldersToSend, itemsToSend);
1626 }
1627
1628 if (foldersToSend-- > 0)
1629 currentPacket.FolderData[foldersSent % MAX_FOLDERS_PER_PACKET] = CreateFolderDataBlock(folders[foldersSent++]);
1630 else if (itemsToSend-- > 0)
1631 currentPacket.ItemData[itemsSent % MAX_ITEMS_PER_PACKET] = CreateItemDataBlock(items[itemsSent++]);
1632 else
1633 {
1634 OutPacket(currentPacket, ThrottleOutPacketType.Asset, false);
1635 currentPacket = null;
1636 }
1637
1638 }
1639
1640 if (currentPacket != null)
1641 OutPacket(currentPacket, ThrottleOutPacketType.Asset, false);
1642 }
1643
1644 private InventoryDescendentsPacket.FolderDataBlock CreateFolderDataBlock(InventoryFolderBase folder)
1645 {
1646 InventoryDescendentsPacket.FolderDataBlock newBlock = new InventoryDescendentsPacket.FolderDataBlock();
1647 newBlock.FolderID = folder.ID;
1648 newBlock.Name = Util.StringToBytes256(folder.Name);
1649 newBlock.ParentID = folder.ParentID;
1650 newBlock.Type = (sbyte)folder.Type;
1651
1652 return newBlock;
1653 }
1654
1655 private InventoryDescendentsPacket.ItemDataBlock CreateItemDataBlock(InventoryItemBase item)
1656 {
1657 InventoryDescendentsPacket.ItemDataBlock newBlock = new InventoryDescendentsPacket.ItemDataBlock();
1658 newBlock.ItemID = item.ID;
1659 newBlock.AssetID = item.AssetID;
1660 newBlock.CreatorID = item.CreatorIdAsUuid;
1661 newBlock.BaseMask = item.BasePermissions;
1662 newBlock.Description = Util.StringToBytes256(item.Description);
1663 newBlock.EveryoneMask = item.EveryOnePermissions;
1664 newBlock.OwnerMask = item.CurrentPermissions;
1665 newBlock.FolderID = item.Folder;
1666 newBlock.InvType = (sbyte)item.InvType;
1667 newBlock.Name = Util.StringToBytes256(item.Name);
1668 newBlock.NextOwnerMask = item.NextPermissions;
1669 newBlock.OwnerID = item.Owner;
1670 newBlock.Type = (sbyte)item.AssetType;
1671
1672 newBlock.GroupID = item.GroupID;
1673 newBlock.GroupOwned = item.GroupOwned;
1674 newBlock.GroupMask = item.GroupPermissions;
1675 newBlock.CreationDate = item.CreationDate;
1676 newBlock.SalePrice = item.SalePrice;
1677 newBlock.SaleType = item.SaleType;
1678 newBlock.Flags = item.Flags;
1679
1680 newBlock.CRC =
1681 Helpers.InventoryCRC(newBlock.CreationDate, newBlock.SaleType,
1682 newBlock.InvType, newBlock.Type,
1683 newBlock.AssetID, newBlock.GroupID,
1684 newBlock.SalePrice,
1685 newBlock.OwnerID, newBlock.CreatorID,
1686 newBlock.ItemID, newBlock.FolderID,
1687 newBlock.EveryoneMask,
1688 newBlock.Flags, newBlock.OwnerMask,
1689 newBlock.GroupMask, newBlock.NextOwnerMask);
1690
1691 return newBlock;
1692 }
1693
1694 private void AddNullFolderBlockToDecendentsPacket(ref InventoryDescendentsPacket packet)
1695 {
1696 packet.FolderData = new InventoryDescendentsPacket.FolderDataBlock[1];
1697 packet.FolderData[0] = new InventoryDescendentsPacket.FolderDataBlock();
1698 packet.FolderData[0].FolderID = UUID.Zero;
1699 packet.FolderData[0].ParentID = UUID.Zero;
1700 packet.FolderData[0].Type = -1;
1701 packet.FolderData[0].Name = new byte[0];
1702 }
1703
1704 private void AddNullItemBlockToDescendentsPacket(ref InventoryDescendentsPacket packet)
1705 {
1706 packet.ItemData = new InventoryDescendentsPacket.ItemDataBlock[1];
1707 packet.ItemData[0] = new InventoryDescendentsPacket.ItemDataBlock();
1708 packet.ItemData[0].ItemID = UUID.Zero;
1709 packet.ItemData[0].AssetID = UUID.Zero;
1710 packet.ItemData[0].CreatorID = UUID.Zero;
1711 packet.ItemData[0].BaseMask = 0;
1712 packet.ItemData[0].Description = new byte[0];
1713 packet.ItemData[0].EveryoneMask = 0;
1714 packet.ItemData[0].OwnerMask = 0;
1715 packet.ItemData[0].FolderID = UUID.Zero;
1716 packet.ItemData[0].InvType = (sbyte)0;
1717 packet.ItemData[0].Name = new byte[0];
1718 packet.ItemData[0].NextOwnerMask = 0;
1719 packet.ItemData[0].OwnerID = UUID.Zero;
1720 packet.ItemData[0].Type = -1;
1721
1722 packet.ItemData[0].GroupID = UUID.Zero;
1723 packet.ItemData[0].GroupOwned = false;
1724 packet.ItemData[0].GroupMask = 0;
1725 packet.ItemData[0].CreationDate = 0;
1726 packet.ItemData[0].SalePrice = 0;
1727 packet.ItemData[0].SaleType = 0;
1728 packet.ItemData[0].Flags = 0;
1729
1730 // No need to add CRC
1731 }
1732
1733 private InventoryDescendentsPacket CreateInventoryDescendentsPacket(UUID ownerID, UUID folderID, int version, int descendents, int folders, int items)
1734 {
1735 InventoryDescendentsPacket descend = (InventoryDescendentsPacket)PacketPool.Instance.GetPacket(PacketType.InventoryDescendents);
1736 descend.Header.Zerocoded = true;
1737 descend.AgentData.AgentID = AgentId;
1738 descend.AgentData.OwnerID = ownerID;
1739 descend.AgentData.FolderID = folderID;
1740 descend.AgentData.Version = version;
1741 descend.AgentData.Descendents = descendents;
1742
1743 if (folders > 0)
1744 descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[folders];
1745 else
1746 AddNullFolderBlockToDecendentsPacket(ref descend);
1747
1748 if (items > 0)
1749 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items];
1750 else
1751 AddNullItemBlockToDescendentsPacket(ref descend);
1752
1753 return descend;
1754 }
1755
1756 public void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item)
1757 {
1758 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
1759
1760 FetchInventoryReplyPacket inventoryReply = (FetchInventoryReplyPacket)PacketPool.Instance.GetPacket(PacketType.FetchInventoryReply);
1761 // TODO: don't create new blocks if recycling an old packet
1762 inventoryReply.AgentData.AgentID = AgentId;
1763 inventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[1];
1764 inventoryReply.InventoryData[0] = new FetchInventoryReplyPacket.InventoryDataBlock();
1765 inventoryReply.InventoryData[0].ItemID = item.ID;
1766 inventoryReply.InventoryData[0].AssetID = item.AssetID;
1767 inventoryReply.InventoryData[0].CreatorID = item.CreatorIdAsUuid;
1768 inventoryReply.InventoryData[0].BaseMask = item.BasePermissions;
1769 inventoryReply.InventoryData[0].CreationDate = item.CreationDate;
1770
1771 inventoryReply.InventoryData[0].Description = Util.StringToBytes256(item.Description);
1772 inventoryReply.InventoryData[0].EveryoneMask = item.EveryOnePermissions;
1773 inventoryReply.InventoryData[0].FolderID = item.Folder;
1774 inventoryReply.InventoryData[0].InvType = (sbyte)item.InvType;
1775 inventoryReply.InventoryData[0].Name = Util.StringToBytes256(item.Name);
1776 inventoryReply.InventoryData[0].NextOwnerMask = item.NextPermissions;
1777 inventoryReply.InventoryData[0].OwnerID = item.Owner;
1778 inventoryReply.InventoryData[0].OwnerMask = item.CurrentPermissions;
1779 inventoryReply.InventoryData[0].Type = (sbyte)item.AssetType;
1780
1781 inventoryReply.InventoryData[0].GroupID = item.GroupID;
1782 inventoryReply.InventoryData[0].GroupOwned = item.GroupOwned;
1783 inventoryReply.InventoryData[0].GroupMask = item.GroupPermissions;
1784 inventoryReply.InventoryData[0].Flags = item.Flags;
1785 inventoryReply.InventoryData[0].SalePrice = item.SalePrice;
1786 inventoryReply.InventoryData[0].SaleType = item.SaleType;
1787
1788 inventoryReply.InventoryData[0].CRC =
1789 Helpers.InventoryCRC(
1790 1000, 0, inventoryReply.InventoryData[0].InvType,
1791 inventoryReply.InventoryData[0].Type, inventoryReply.InventoryData[0].AssetID,
1792 inventoryReply.InventoryData[0].GroupID, 100,
1793 inventoryReply.InventoryData[0].OwnerID, inventoryReply.InventoryData[0].CreatorID,
1794 inventoryReply.InventoryData[0].ItemID, inventoryReply.InventoryData[0].FolderID,
1795 FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
1796 FULL_MASK_PERMISSIONS);
1797 inventoryReply.Header.Zerocoded = true;
1798 OutPacket(inventoryReply, ThrottleOutPacketType.Asset);
1799 }
1800
1801 protected void SendBulkUpdateInventoryFolder(InventoryFolderBase folderBase)
1802 {
1803 // We will use the same transaction id for all the separate packets to be sent out in this update.
1804 UUID transactionId = UUID.Random();
1805
1806 List<BulkUpdateInventoryPacket.FolderDataBlock> folderDataBlocks
1807 = new List<BulkUpdateInventoryPacket.FolderDataBlock>();
1808
1809 SendBulkUpdateInventoryFolderRecursive(folderBase, ref folderDataBlocks, transactionId);
1810
1811 if (folderDataBlocks.Count > 0)
1812 {
1813 // We'll end up with some unsent folder blocks if there were some empty folders at the end of the list
1814 // Send these now
1815 BulkUpdateInventoryPacket bulkUpdate
1816 = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory);
1817 bulkUpdate.Header.Zerocoded = true;
1818
1819 bulkUpdate.AgentData.AgentID = AgentId;
1820 bulkUpdate.AgentData.TransactionID = transactionId;
1821 bulkUpdate.FolderData = folderDataBlocks.ToArray();
1822 List<BulkUpdateInventoryPacket.ItemDataBlock> foo = new List<BulkUpdateInventoryPacket.ItemDataBlock>();
1823 bulkUpdate.ItemData = foo.ToArray();
1824
1825 //m_log.Debug("SendBulkUpdateInventory :" + bulkUpdate);
1826 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
1827 }
1828 }
1829
1830 /// <summary>
1831 /// Recursively construct bulk update packets to send folders and items
1832 /// </summary>
1833 /// <param name="folder"></param>
1834 /// <param name="folderDataBlocks"></param>
1835 /// <param name="transactionId"></param>
1836 private void SendBulkUpdateInventoryFolderRecursive(
1837 InventoryFolderBase folder, ref List<BulkUpdateInventoryPacket.FolderDataBlock> folderDataBlocks,
1838 UUID transactionId)
1839 {
1840 folderDataBlocks.Add(GenerateBulkUpdateFolderDataBlock(folder));
1841
1842 const int MAX_ITEMS_PER_PACKET = 5;
1843
1844 IInventoryService invService = m_scene.RequestModuleInterface<IInventoryService>();
1845 // If there are any items then we have to start sending them off in this packet - the next folder will have
1846 // to be in its own bulk update packet. Also, we can only fit 5 items in a packet (at least this was the limit
1847 // being used on the Linden grid at 20081203).
1848 InventoryCollection contents = invService.GetFolderContent(AgentId, folder.ID); // folder.RequestListOfItems();
1849 List<InventoryItemBase> items = contents.Items;
1850 while (items.Count > 0)
1851 {
1852 BulkUpdateInventoryPacket bulkUpdate
1853 = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory);
1854 bulkUpdate.Header.Zerocoded = true;
1855
1856 bulkUpdate.AgentData.AgentID = AgentId;
1857 bulkUpdate.AgentData.TransactionID = transactionId;
1858 bulkUpdate.FolderData = folderDataBlocks.ToArray();
1859
1860 int itemsToSend = (items.Count > MAX_ITEMS_PER_PACKET ? MAX_ITEMS_PER_PACKET : items.Count);
1861 bulkUpdate.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[itemsToSend];
1862
1863 for (int i = 0; i < itemsToSend; i++)
1864 {
1865 // Remove from the end of the list so that we don't incur a performance penalty
1866 bulkUpdate.ItemData[i] = GenerateBulkUpdateItemDataBlock(items[items.Count - 1]);
1867 items.RemoveAt(items.Count - 1);
1868 }
1869
1870 //m_log.Debug("SendBulkUpdateInventoryRecursive :" + bulkUpdate);
1871 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
1872
1873 folderDataBlocks = new List<BulkUpdateInventoryPacket.FolderDataBlock>();
1874
1875 // If we're going to be sending another items packet then it needs to contain just the folder to which those
1876 // items belong.
1877 if (items.Count > 0)
1878 folderDataBlocks.Add(GenerateBulkUpdateFolderDataBlock(folder));
1879 }
1880
1881 List<InventoryFolderBase> subFolders = contents.Folders;
1882 foreach (InventoryFolderBase subFolder in subFolders)
1883 {
1884 SendBulkUpdateInventoryFolderRecursive(subFolder, ref folderDataBlocks, transactionId);
1885 }
1886 }
1887
1888 /// <summary>
1889 /// Generate a bulk update inventory data block for the given folder
1890 /// </summary>
1891 /// <param name="folder"></param>
1892 /// <returns></returns>
1893 private BulkUpdateInventoryPacket.FolderDataBlock GenerateBulkUpdateFolderDataBlock(InventoryFolderBase folder)
1894 {
1895 BulkUpdateInventoryPacket.FolderDataBlock folderBlock = new BulkUpdateInventoryPacket.FolderDataBlock();
1896
1897 folderBlock.FolderID = folder.ID;
1898 folderBlock.ParentID = folder.ParentID;
1899 folderBlock.Type = -1;
1900 folderBlock.Name = Util.StringToBytes256(folder.Name);
1901
1902 return folderBlock;
1903 }
1904
1905 /// <summary>
1906 /// Generate a bulk update inventory data block for the given item
1907 /// </summary>
1908 /// <param name="item"></param>
1909 /// <returns></returns>
1910 private BulkUpdateInventoryPacket.ItemDataBlock GenerateBulkUpdateItemDataBlock(InventoryItemBase item)
1911 {
1912 BulkUpdateInventoryPacket.ItemDataBlock itemBlock = new BulkUpdateInventoryPacket.ItemDataBlock();
1913
1914 itemBlock.ItemID = item.ID;
1915 itemBlock.AssetID = item.AssetID;
1916 itemBlock.CreatorID = item.CreatorIdAsUuid;
1917 itemBlock.BaseMask = item.BasePermissions;
1918 itemBlock.Description = Util.StringToBytes256(item.Description);
1919 itemBlock.EveryoneMask = item.EveryOnePermissions;
1920 itemBlock.FolderID = item.Folder;
1921 itemBlock.InvType = (sbyte)item.InvType;
1922 itemBlock.Name = Util.StringToBytes256(item.Name);
1923 itemBlock.NextOwnerMask = item.NextPermissions;
1924 itemBlock.OwnerID = item.Owner;
1925 itemBlock.OwnerMask = item.CurrentPermissions;
1926 itemBlock.Type = (sbyte)item.AssetType;
1927 itemBlock.GroupID = item.GroupID;
1928 itemBlock.GroupOwned = item.GroupOwned;
1929 itemBlock.GroupMask = item.GroupPermissions;
1930 itemBlock.Flags = item.Flags;
1931 itemBlock.SalePrice = item.SalePrice;
1932 itemBlock.SaleType = item.SaleType;
1933 itemBlock.CreationDate = item.CreationDate;
1934
1935 itemBlock.CRC =
1936 Helpers.InventoryCRC(
1937 1000, 0, itemBlock.InvType,
1938 itemBlock.Type, itemBlock.AssetID,
1939 itemBlock.GroupID, 100,
1940 itemBlock.OwnerID, itemBlock.CreatorID,
1941 itemBlock.ItemID, itemBlock.FolderID,
1942 (uint)PermissionMask.All, 1, (uint)PermissionMask.All, (uint)PermissionMask.All,
1943 (uint)PermissionMask.All);
1944
1945 return itemBlock;
1946 }
1947
1948 public void SendBulkUpdateInventory(InventoryNodeBase node)
1949 {
1950 if (node is InventoryItemBase)
1951 SendBulkUpdateInventoryItem((InventoryItemBase)node);
1952 else if (node is InventoryFolderBase)
1953 SendBulkUpdateInventoryFolder((InventoryFolderBase)node);
1954 else
1955 m_log.ErrorFormat("[CLIENT]: Client for {0} sent unknown inventory node named {1}", Name, node.Name);
1956 }
1957
1958 protected void SendBulkUpdateInventoryItem(InventoryItemBase item)
1959 {
1960 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
1961
1962 BulkUpdateInventoryPacket bulkUpdate
1963 = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory);
1964
1965 bulkUpdate.AgentData.AgentID = AgentId;
1966 bulkUpdate.AgentData.TransactionID = UUID.Random();
1967
1968 bulkUpdate.FolderData = new BulkUpdateInventoryPacket.FolderDataBlock[1];
1969 bulkUpdate.FolderData[0] = new BulkUpdateInventoryPacket.FolderDataBlock();
1970 bulkUpdate.FolderData[0].FolderID = UUID.Zero;
1971 bulkUpdate.FolderData[0].ParentID = UUID.Zero;
1972 bulkUpdate.FolderData[0].Type = -1;
1973 bulkUpdate.FolderData[0].Name = new byte[0];
1974
1975 bulkUpdate.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[1];
1976 bulkUpdate.ItemData[0] = new BulkUpdateInventoryPacket.ItemDataBlock();
1977 bulkUpdate.ItemData[0].ItemID = item.ID;
1978 bulkUpdate.ItemData[0].AssetID = item.AssetID;
1979 bulkUpdate.ItemData[0].CreatorID = item.CreatorIdAsUuid;
1980 bulkUpdate.ItemData[0].BaseMask = item.BasePermissions;
1981 bulkUpdate.ItemData[0].CreationDate = item.CreationDate;
1982 bulkUpdate.ItemData[0].Description = Util.StringToBytes256(item.Description);
1983 bulkUpdate.ItemData[0].EveryoneMask = item.EveryOnePermissions;
1984 bulkUpdate.ItemData[0].FolderID = item.Folder;
1985 bulkUpdate.ItemData[0].InvType = (sbyte)item.InvType;
1986 bulkUpdate.ItemData[0].Name = Util.StringToBytes256(item.Name);
1987 bulkUpdate.ItemData[0].NextOwnerMask = item.NextPermissions;
1988 bulkUpdate.ItemData[0].OwnerID = item.Owner;
1989 bulkUpdate.ItemData[0].OwnerMask = item.CurrentPermissions;
1990 bulkUpdate.ItemData[0].Type = (sbyte)item.AssetType;
1991
1992 bulkUpdate.ItemData[0].GroupID = item.GroupID;
1993 bulkUpdate.ItemData[0].GroupOwned = item.GroupOwned;
1994 bulkUpdate.ItemData[0].GroupMask = item.GroupPermissions;
1995 bulkUpdate.ItemData[0].Flags = item.Flags;
1996 bulkUpdate.ItemData[0].SalePrice = item.SalePrice;
1997 bulkUpdate.ItemData[0].SaleType = item.SaleType;
1998
1999 bulkUpdate.ItemData[0].CRC =
2000 Helpers.InventoryCRC(1000, 0, bulkUpdate.ItemData[0].InvType,
2001 bulkUpdate.ItemData[0].Type, bulkUpdate.ItemData[0].AssetID,
2002 bulkUpdate.ItemData[0].GroupID, 100,
2003 bulkUpdate.ItemData[0].OwnerID, bulkUpdate.ItemData[0].CreatorID,
2004 bulkUpdate.ItemData[0].ItemID, bulkUpdate.ItemData[0].FolderID,
2005 FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
2006 FULL_MASK_PERMISSIONS);
2007 bulkUpdate.Header.Zerocoded = true;
2008 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
2009 }
2010
2011 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2012 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
2013 {
2014 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
2015
2016 UpdateCreateInventoryItemPacket InventoryReply
2017 = (UpdateCreateInventoryItemPacket)PacketPool.Instance.GetPacket(
2018 PacketType.UpdateCreateInventoryItem);
2019
2020 // TODO: don't create new blocks if recycling an old packet
2021 InventoryReply.AgentData.AgentID = AgentId;
2022 InventoryReply.AgentData.SimApproved = true;
2023 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
2024 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
2025 InventoryReply.InventoryData[0].ItemID = Item.ID;
2026 InventoryReply.InventoryData[0].AssetID = Item.AssetID;
2027 InventoryReply.InventoryData[0].CreatorID = Item.CreatorIdAsUuid;
2028 InventoryReply.InventoryData[0].BaseMask = Item.BasePermissions;
2029 InventoryReply.InventoryData[0].Description = Util.StringToBytes256(Item.Description);
2030 InventoryReply.InventoryData[0].EveryoneMask = Item.EveryOnePermissions;
2031 InventoryReply.InventoryData[0].FolderID = Item.Folder;
2032 InventoryReply.InventoryData[0].InvType = (sbyte)Item.InvType;
2033 InventoryReply.InventoryData[0].Name = Util.StringToBytes256(Item.Name);
2034 InventoryReply.InventoryData[0].NextOwnerMask = Item.NextPermissions;
2035 InventoryReply.InventoryData[0].OwnerID = Item.Owner;
2036 InventoryReply.InventoryData[0].OwnerMask = Item.CurrentPermissions;
2037 InventoryReply.InventoryData[0].Type = (sbyte)Item.AssetType;
2038 InventoryReply.InventoryData[0].CallbackID = callbackId;
2039
2040 InventoryReply.InventoryData[0].GroupID = Item.GroupID;
2041 InventoryReply.InventoryData[0].GroupOwned = Item.GroupOwned;
2042 InventoryReply.InventoryData[0].GroupMask = Item.GroupPermissions;
2043 InventoryReply.InventoryData[0].Flags = Item.Flags;
2044 InventoryReply.InventoryData[0].SalePrice = Item.SalePrice;
2045 InventoryReply.InventoryData[0].SaleType = Item.SaleType;
2046 InventoryReply.InventoryData[0].CreationDate = Item.CreationDate;
2047
2048 InventoryReply.InventoryData[0].CRC =
2049 Helpers.InventoryCRC(1000, 0, InventoryReply.InventoryData[0].InvType,
2050 InventoryReply.InventoryData[0].Type, InventoryReply.InventoryData[0].AssetID,
2051 InventoryReply.InventoryData[0].GroupID, 100,
2052 InventoryReply.InventoryData[0].OwnerID, InventoryReply.InventoryData[0].CreatorID,
2053 InventoryReply.InventoryData[0].ItemID, InventoryReply.InventoryData[0].FolderID,
2054 FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
2055 FULL_MASK_PERMISSIONS);
2056 InventoryReply.Header.Zerocoded = true;
2057 OutPacket(InventoryReply, ThrottleOutPacketType.Asset);
2058 }
2059
2060 public void SendRemoveInventoryItem(UUID itemID)
2061 {
2062 RemoveInventoryItemPacket remove = (RemoveInventoryItemPacket)PacketPool.Instance.GetPacket(PacketType.RemoveInventoryItem);
2063 // TODO: don't create new blocks if recycling an old packet
2064 remove.AgentData.AgentID = AgentId;
2065 remove.AgentData.SessionID = m_sessionId;
2066 remove.InventoryData = new RemoveInventoryItemPacket.InventoryDataBlock[1];
2067 remove.InventoryData[0] = new RemoveInventoryItemPacket.InventoryDataBlock();
2068 remove.InventoryData[0].ItemID = itemID;
2069 remove.Header.Zerocoded = true;
2070 OutPacket(remove, ThrottleOutPacketType.Asset);
2071 }
2072
2073 public void SendTakeControls(int controls, bool passToAgent, bool TakeControls)
2074 {
2075 ScriptControlChangePacket scriptcontrol = (ScriptControlChangePacket)PacketPool.Instance.GetPacket(PacketType.ScriptControlChange);
2076 ScriptControlChangePacket.DataBlock[] data = new ScriptControlChangePacket.DataBlock[1];
2077 ScriptControlChangePacket.DataBlock ddata = new ScriptControlChangePacket.DataBlock();
2078 ddata.Controls = (uint)controls;
2079 ddata.PassToAgent = passToAgent;
2080 ddata.TakeControls = TakeControls;
2081 data[0] = ddata;
2082 scriptcontrol.Data = data;
2083 OutPacket(scriptcontrol, ThrottleOutPacketType.Task);
2084 }
2085
2086 public void SendTaskInventory(UUID taskID, short serial, byte[] fileName)
2087 {
2088 ReplyTaskInventoryPacket replytask = (ReplyTaskInventoryPacket)PacketPool.Instance.GetPacket(PacketType.ReplyTaskInventory);
2089 replytask.InventoryData.TaskID = taskID;
2090 replytask.InventoryData.Serial = serial;
2091 replytask.InventoryData.Filename = fileName;
2092 OutPacket(replytask, ThrottleOutPacketType.Asset);
2093 }
2094
2095 public void SendXferPacket(ulong xferID, uint packet, byte[] data)
2096 {
2097 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket);
2098 sendXfer.XferID.ID = xferID;
2099 sendXfer.XferID.Packet = packet;
2100 sendXfer.DataPacket.Data = data;
2101 OutPacket(sendXfer, ThrottleOutPacketType.Asset);
2102 }
2103
2104 public void SendAbortXferPacket(ulong xferID)
2105 {
2106 AbortXferPacket xferItem = (AbortXferPacket)PacketPool.Instance.GetPacket(PacketType.AbortXfer);
2107 xferItem.XferID.ID = xferID;
2108 OutPacket(xferItem, ThrottleOutPacketType.Asset);
2109 }
2110
2111 public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit,
2112 int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor,
2113 int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay,
2114 int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent)
2115 {
2116 EconomyDataPacket economyData = (EconomyDataPacket)PacketPool.Instance.GetPacket(PacketType.EconomyData);
2117 economyData.Info.EnergyEfficiency = EnergyEfficiency;
2118 economyData.Info.ObjectCapacity = ObjectCapacity;
2119 economyData.Info.ObjectCount = ObjectCount;
2120 economyData.Info.PriceEnergyUnit = PriceEnergyUnit;
2121 economyData.Info.PriceGroupCreate = PriceGroupCreate;
2122 economyData.Info.PriceObjectClaim = PriceObjectClaim;
2123 economyData.Info.PriceObjectRent = PriceObjectRent;
2124 economyData.Info.PriceObjectScaleFactor = PriceObjectScaleFactor;
2125 economyData.Info.PriceParcelClaim = PriceParcelClaim;
2126 economyData.Info.PriceParcelClaimFactor = PriceParcelClaimFactor;
2127 economyData.Info.PriceParcelRent = PriceParcelRent;
2128 economyData.Info.PricePublicObjectDecay = PricePublicObjectDecay;
2129 economyData.Info.PricePublicObjectDelete = PricePublicObjectDelete;
2130 economyData.Info.PriceRentLight = PriceRentLight;
2131 economyData.Info.PriceUpload = PriceUpload;
2132 economyData.Info.TeleportMinPrice = TeleportMinPrice;
2133 economyData.Info.TeleportPriceExponent = TeleportPriceExponent;
2134 economyData.Header.Reliable = true;
2135 OutPacket(economyData, ThrottleOutPacketType.Task);
2136 }
2137
2138 public void SendAvatarPickerReply(AvatarPickerReplyAgentDataArgs AgentData, List<AvatarPickerReplyDataArgs> Data)
2139 {
2140 //construct the AvatarPickerReply packet.
2141 AvatarPickerReplyPacket replyPacket = new AvatarPickerReplyPacket();
2142 replyPacket.AgentData.AgentID = AgentData.AgentID;
2143 replyPacket.AgentData.QueryID = AgentData.QueryID;
2144 //int i = 0;
2145 List<AvatarPickerReplyPacket.DataBlock> data_block = new List<AvatarPickerReplyPacket.DataBlock>();
2146 foreach (AvatarPickerReplyDataArgs arg in Data)
2147 {
2148 AvatarPickerReplyPacket.DataBlock db = new AvatarPickerReplyPacket.DataBlock();
2149 db.AvatarID = arg.AvatarID;
2150 db.FirstName = arg.FirstName;
2151 db.LastName = arg.LastName;
2152 data_block.Add(db);
2153 }
2154 replyPacket.Data = data_block.ToArray();
2155 OutPacket(replyPacket, ThrottleOutPacketType.Task);
2156 }
2157
2158 public void SendAgentDataUpdate(UUID agentid, UUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle)
2159 {
2160 m_activeGroupID = activegroupid;
2161 m_activeGroupName = groupname;
2162 m_activeGroupPowers = grouppowers;
2163
2164 AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate);
2165 sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid;
2166 sendAgentDataUpdate.AgentData.AgentID = agentid;
2167 sendAgentDataUpdate.AgentData.FirstName = Util.StringToBytes256(firstname);
2168 sendAgentDataUpdate.AgentData.GroupName = Util.StringToBytes256(groupname);
2169 sendAgentDataUpdate.AgentData.GroupPowers = grouppowers;
2170 sendAgentDataUpdate.AgentData.GroupTitle = Util.StringToBytes256(grouptitle);
2171 sendAgentDataUpdate.AgentData.LastName = Util.StringToBytes256(lastname);
2172 OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task);
2173 }
2174
2175 /// <summary>
2176 /// Send an alert message to the client. On the Linden client (tested 1.19.1.4), this pops up a brief duration
2177 /// blue information box in the bottom right hand corner.
2178 /// </summary>
2179 /// <param name="message"></param>
2180 public void SendAlertMessage(string message)
2181 {
2182 AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage);
2183 alertPack.AlertData = new AlertMessagePacket.AlertDataBlock();
2184 alertPack.AlertData.Message = Util.StringToBytes256(message);
2185 alertPack.AlertInfo = new AlertMessagePacket.AlertInfoBlock[0];
2186 OutPacket(alertPack, ThrottleOutPacketType.Task);
2187 }
2188
2189 /// <summary>
2190 /// Send an agent alert message to the client.
2191 /// </summary>
2192 /// <param name="message"></param>
2193 /// <param name="modal">On the linden client, if this true then it displays a one button text box placed in the
2194 /// middle of the window. If false, the message is displayed in a brief duration blue information box (as for
2195 /// the AlertMessage packet).</param>
2196 public void SendAgentAlertMessage(string message, bool modal)
2197 {
2198 OutPacket(BuildAgentAlertPacket(message, modal), ThrottleOutPacketType.Task);
2199 }
2200
2201 /// <summary>
2202 /// Construct an agent alert packet
2203 /// </summary>
2204 /// <param name="message"></param>
2205 /// <param name="modal"></param>
2206 /// <returns></returns>
2207 public AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal)
2208 {
2209 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage);
2210 alertPack.AgentData.AgentID = AgentId;
2211 alertPack.AlertData.Message = Util.StringToBytes256(message);
2212 alertPack.AlertData.Modal = modal;
2213
2214 return alertPack;
2215 }
2216
2217 public void SendLoadURL(string objectname, UUID objectID, UUID ownerID, bool groupOwned, string message,
2218 string url)
2219 {
2220 LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL);
2221 loadURL.Data.ObjectName = Util.StringToBytes256(objectname);
2222 loadURL.Data.ObjectID = objectID;
2223 loadURL.Data.OwnerID = ownerID;
2224 loadURL.Data.OwnerIsGroup = groupOwned;
2225 loadURL.Data.Message = Util.StringToBytes256(message);
2226 loadURL.Data.URL = Util.StringToBytes256(url);
2227 OutPacket(loadURL, ThrottleOutPacketType.Task);
2228 }
2229
2230 public void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels)
2231 {
2232 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog);
2233 dialog.Data.ObjectID = objectID;
2234 dialog.Data.ObjectName = Util.StringToBytes256(objectname);
2235 // this is the username of the *owner*
2236 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
2237 dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
2238 dialog.Data.Message = Util.StringToBytes1024(msg);
2239 dialog.Data.ImageID = textureID;
2240 dialog.Data.ChatChannel = ch;
2241 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length];
2242 for (int i = 0; i < buttonlabels.Length; i++)
2243 {
2244 buttons[i] = new ScriptDialogPacket.ButtonsBlock();
2245 buttons[i].ButtonLabel = Util.StringToBytes256(buttonlabels[i]);
2246 }
2247 dialog.Buttons = buttons;
2248 OutPacket(dialog, ThrottleOutPacketType.Task);
2249 }
2250
2251 public void SendPreLoadSound(UUID objectID, UUID ownerID, UUID soundID)
2252 {
2253 PreloadSoundPacket preSound = (PreloadSoundPacket)PacketPool.Instance.GetPacket(PacketType.PreloadSound);
2254 // TODO: don't create new blocks if recycling an old packet
2255 preSound.DataBlock = new PreloadSoundPacket.DataBlockBlock[1];
2256 preSound.DataBlock[0] = new PreloadSoundPacket.DataBlockBlock();
2257 preSound.DataBlock[0].ObjectID = objectID;
2258 preSound.DataBlock[0].OwnerID = ownerID;
2259 preSound.DataBlock[0].SoundID = soundID;
2260 preSound.Header.Zerocoded = true;
2261 OutPacket(preSound, ThrottleOutPacketType.Task);
2262 }
2263
2264 public void SendPlayAttachedSound(UUID soundID, UUID objectID, UUID ownerID, float gain, byte flags)
2265 {
2266 AttachedSoundPacket sound = (AttachedSoundPacket)PacketPool.Instance.GetPacket(PacketType.AttachedSound);
2267 sound.DataBlock.SoundID = soundID;
2268 sound.DataBlock.ObjectID = objectID;
2269 sound.DataBlock.OwnerID = ownerID;
2270 sound.DataBlock.Gain = gain;
2271 sound.DataBlock.Flags = flags;
2272
2273 OutPacket(sound, ThrottleOutPacketType.Task);
2274 }
2275
2276 public void SendTransferAbort(TransferRequestPacket transferRequest)
2277 {
2278 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2279 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2280 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2281 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2282 OutPacket(abort, ThrottleOutPacketType.Task);
2283 }
2284
2285 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2286 {
2287 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
2288 sound.SoundData.SoundID = soundID;
2289 sound.SoundData.OwnerID = ownerID;
2290 sound.SoundData.ObjectID = objectID;
2291 sound.SoundData.ParentID = parentID;
2292 sound.SoundData.Handle = handle;
2293 sound.SoundData.Position = position;
2294 sound.SoundData.Gain = gain;
2295
2296 OutPacket(sound, ThrottleOutPacketType.Task);
2297 }
2298
2299 public void SendAttachedSoundGainChange(UUID objectID, float gain)
2300 {
2301 AttachedSoundGainChangePacket sound = (AttachedSoundGainChangePacket)PacketPool.Instance.GetPacket(PacketType.AttachedSoundGainChange);
2302 sound.DataBlock.ObjectID = objectID;
2303 sound.DataBlock.Gain = gain;
2304
2305 OutPacket(sound, ThrottleOutPacketType.Task);
2306 }
2307
2308 public void SendSunPos(Vector3 Position, Vector3 Velocity, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, float OrbitalPosition)
2309 {
2310 // Viewers based on the Linden viwer code, do wacky things for oribital positions from Midnight to Sunrise
2311 // So adjust for that
2312 // Contributed by: Godfrey
2313
2314 if (OrbitalPosition > m_sunPainDaHalfOrbitalCutoff) // things get weird from midnight to sunrise
2315 {
2316 OrbitalPosition = (OrbitalPosition - m_sunPainDaHalfOrbitalCutoff) * 0.6666666667f + m_sunPainDaHalfOrbitalCutoff;
2317 }
2318
2319
2320
2321 SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage);
2322 viewertime.TimeInfo.SunDirection = Position;
2323 viewertime.TimeInfo.SunAngVelocity = Velocity;
2324
2325 // Sun module used to add 6 hours to adjust for linden sun hour, adding here
2326 // to prevent existing code from breaking if it assumed that 6 hours were included.
2327 // 21600 == 6 hours * 60 minutes * 60 Seconds
2328 viewertime.TimeInfo.UsecSinceStart = CurrentTime + 21600;
2329
2330 viewertime.TimeInfo.SecPerDay = SecondsPerSunCycle;
2331 viewertime.TimeInfo.SecPerYear = SecondsPerYear;
2332 viewertime.TimeInfo.SunPhase = OrbitalPosition;
2333 viewertime.Header.Reliable = false;
2334 viewertime.Header.Zerocoded = true;
2335 OutPacket(viewertime, ThrottleOutPacketType.Task);
2336 }
2337
2338 // Currently Deprecated
2339 public void SendViewerTime(int phase)
2340 {
2341 /*
2342 Console.WriteLine("SunPhase: {0}", phase);
2343 SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage);
2344 //viewertime.TimeInfo.SecPerDay = 86400;
2345 //viewertime.TimeInfo.SecPerYear = 31536000;
2346 viewertime.TimeInfo.SecPerDay = 1000;
2347 viewertime.TimeInfo.SecPerYear = 365000;
2348 viewertime.TimeInfo.SunPhase = 1;
2349 int sunPhase = (phase + 2) / 2;
2350 if ((sunPhase < 6) || (sunPhase > 36))
2351 {
2352 viewertime.TimeInfo.SunDirection = new Vector3(0f, 0.8f, -0.8f);
2353 Console.WriteLine("sending night");
2354 }
2355 else
2356 {
2357 if (sunPhase < 12)
2358 {
2359 sunPhase = 12;
2360 }
2361 sunPhase = sunPhase - 12;
2362
2363 float yValue = 0.1f * (sunPhase);
2364 Console.WriteLine("Computed SunPhase: {0}, yValue: {1}", sunPhase, yValue);
2365 if (yValue > 1.2f)
2366 {
2367 yValue = yValue - 1.2f;
2368 }
2369
2370 yValue = Util.Clip(yValue, 0, 1);
2371
2372 if (sunPhase < 14)
2373 {
2374 yValue = 1 - yValue;
2375 }
2376 if (sunPhase < 12)
2377 {
2378 yValue *= -1;
2379 }
2380 viewertime.TimeInfo.SunDirection = new Vector3(0f, yValue, 0.3f);
2381 Console.WriteLine("sending sun update " + yValue);
2382 }
2383 viewertime.TimeInfo.SunAngVelocity = new Vector3(0, 0.0f, 10.0f);
2384 viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch();
2385 viewertime.Header.Reliable = false;
2386 OutPacket(viewertime, ThrottleOutPacketType.Task);
2387 */
2388 }
2389
2390 public void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks)
2391 {
2392 ViewerEffectPacket packet = (ViewerEffectPacket)PacketPool.Instance.GetPacket(PacketType.ViewerEffect);
2393 packet.Header.Reliable = false;
2394 packet.Header.Zerocoded = true;
2395
2396 packet.AgentData.AgentID = AgentId;
2397 packet.AgentData.SessionID = SessionId;
2398
2399 packet.Effect = effectBlocks;
2400
2401 // OutPacket(packet, ThrottleOutPacketType.State);
2402 OutPacket(packet, ThrottleOutPacketType.Task);
2403 }
2404
2405 public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember,
2406 string flAbout, uint flags, UUID flImageID, UUID imageID, string profileURL,
2407 UUID partnerID)
2408 {
2409 AvatarPropertiesReplyPacket avatarReply = (AvatarPropertiesReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPropertiesReply);
2410 avatarReply.AgentData.AgentID = AgentId;
2411 avatarReply.AgentData.AvatarID = avatarID;
2412 if (aboutText != null)
2413 avatarReply.PropertiesData.AboutText = Util.StringToBytes1024(aboutText);
2414 else
2415 avatarReply.PropertiesData.AboutText = Utils.EmptyBytes;
2416 avatarReply.PropertiesData.BornOn = Util.StringToBytes256(bornOn);
2417 avatarReply.PropertiesData.CharterMember = charterMember;
2418 if (flAbout != null)
2419 avatarReply.PropertiesData.FLAboutText = Util.StringToBytes256(flAbout);
2420 else
2421 avatarReply.PropertiesData.FLAboutText = Utils.EmptyBytes;
2422 avatarReply.PropertiesData.Flags = flags;
2423 avatarReply.PropertiesData.FLImageID = flImageID;
2424 avatarReply.PropertiesData.ImageID = imageID;
2425 avatarReply.PropertiesData.ProfileURL = Util.StringToBytes256(profileURL);
2426 avatarReply.PropertiesData.PartnerID = partnerID;
2427 OutPacket(avatarReply, ThrottleOutPacketType.Task);
2428 }
2429
2430 /// <summary>
2431 /// Send the client an Estate message blue box pop-down with a single OK button
2432 /// </summary>
2433 /// <param name="FromAvatarID"></param>
2434 /// <param name="fromSessionID"></param>
2435 /// <param name="FromAvatarName"></param>
2436 /// <param name="Message"></param>
2437 public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message)
2438 {
2439 if (!ChildAgentStatus())
2440 SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3()));
2441
2442 //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch());
2443 }
2444
2445 public void SendLogoutPacket()
2446 {
2447 // I know this is a bit of a hack, however there are times when you don't
2448 // want to send this, but still need to do the rest of the shutdown process
2449 // this method gets called from the packet server.. which makes it practically
2450 // impossible to do any other way.
2451
2452 if (m_SendLogoutPacketWhenClosing)
2453 {
2454 LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply);
2455 // TODO: don't create new blocks if recycling an old packet
2456 logReply.AgentData.AgentID = AgentId;
2457 logReply.AgentData.SessionID = SessionId;
2458 logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
2459 logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
2460 logReply.InventoryData[0].ItemID = UUID.Zero;
2461
2462 OutPacket(logReply, ThrottleOutPacketType.Task);
2463 }
2464 }
2465
2466 public void SendHealth(float health)
2467 {
2468 HealthMessagePacket healthpacket = (HealthMessagePacket)PacketPool.Instance.GetPacket(PacketType.HealthMessage);
2469 healthpacket.HealthData.Health = health;
2470 OutPacket(healthpacket, ThrottleOutPacketType.Task);
2471 }
2472
2473 public void SendAgentOnline(UUID[] agentIDs)
2474 {
2475 OnlineNotificationPacket onp = new OnlineNotificationPacket();
2476 OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[agentIDs.Length];
2477 for (int i = 0; i < agentIDs.Length; i++)
2478 {
2479 OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock();
2480 onpbl.AgentID = agentIDs[i];
2481 onpb[i] = onpbl;
2482 }
2483 onp.AgentBlock = onpb;
2484 onp.Header.Reliable = true;
2485 OutPacket(onp, ThrottleOutPacketType.Task);
2486 }
2487
2488 public void SendAgentOffline(UUID[] agentIDs)
2489 {
2490 OfflineNotificationPacket offp = new OfflineNotificationPacket();
2491 OfflineNotificationPacket.AgentBlockBlock[] offpb = new OfflineNotificationPacket.AgentBlockBlock[agentIDs.Length];
2492 for (int i = 0; i < agentIDs.Length; i++)
2493 {
2494 OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock();
2495 onpbl.AgentID = agentIDs[i];
2496 offpb[i] = onpbl;
2497 }
2498 offp.AgentBlock = offpb;
2499 offp.Header.Reliable = true;
2500 OutPacket(offp, ThrottleOutPacketType.Task);
2501 }
2502
2503 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot,
2504 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
2505 {
2506 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket();
2507 avatarSitResponse.SitObject.ID = TargetID;
2508 if (CameraAtOffset != Vector3.Zero)
2509 {
2510 avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
2511 avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
2512 }
2513 avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook;
2514 avatarSitResponse.SitTransform.AutoPilot = autopilot;
2515 avatarSitResponse.SitTransform.SitPosition = OffsetPos;
2516 avatarSitResponse.SitTransform.SitRotation = SitOrientation;
2517
2518 OutPacket(avatarSitResponse, ThrottleOutPacketType.Task);
2519 }
2520
2521 public void SendAdminResponse(UUID Token, uint AdminLevel)
2522 {
2523 GrantGodlikePowersPacket respondPacket = new GrantGodlikePowersPacket();
2524 GrantGodlikePowersPacket.GrantDataBlock gdb = new GrantGodlikePowersPacket.GrantDataBlock();
2525 GrantGodlikePowersPacket.AgentDataBlock adb = new GrantGodlikePowersPacket.AgentDataBlock();
2526
2527 adb.AgentID = AgentId;
2528 adb.SessionID = SessionId; // More security
2529 gdb.GodLevel = (byte)AdminLevel;
2530 gdb.Token = Token;
2531 //respondPacket.AgentData = (GrantGodlikePowersPacket.AgentDataBlock)ablock;
2532 respondPacket.GrantData = gdb;
2533 respondPacket.AgentData = adb;
2534 OutPacket(respondPacket, ThrottleOutPacketType.Task);
2535 }
2536
2537 public void SendGroupMembership(GroupMembershipData[] GroupMembership)
2538 {
2539 m_groupPowers.Clear();
2540
2541 AgentGroupDataUpdatePacket Groupupdate = new AgentGroupDataUpdatePacket();
2542 AgentGroupDataUpdatePacket.GroupDataBlock[] Groups = new AgentGroupDataUpdatePacket.GroupDataBlock[GroupMembership.Length];
2543 for (int i = 0; i < GroupMembership.Length; i++)
2544 {
2545 m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers;
2546
2547 AgentGroupDataUpdatePacket.GroupDataBlock Group = new AgentGroupDataUpdatePacket.GroupDataBlock();
2548 Group.AcceptNotices = GroupMembership[i].AcceptNotices;
2549 Group.Contribution = GroupMembership[i].Contribution;
2550 Group.GroupID = GroupMembership[i].GroupID;
2551 Group.GroupInsigniaID = GroupMembership[i].GroupPicture;
2552 Group.GroupName = Util.StringToBytes256(GroupMembership[i].GroupName);
2553 Group.GroupPowers = GroupMembership[i].GroupPowers;
2554 Groups[i] = Group;
2555
2556
2557 }
2558 Groupupdate.GroupData = Groups;
2559 Groupupdate.AgentData = new AgentGroupDataUpdatePacket.AgentDataBlock();
2560 Groupupdate.AgentData.AgentID = AgentId;
2561 OutPacket(Groupupdate, ThrottleOutPacketType.Task);
2562
2563 try
2564 {
2565 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
2566 if (eq != null)
2567 {
2568 eq.GroupMembership(Groupupdate, this.AgentId);
2569 }
2570 }
2571 catch (Exception ex)
2572 {
2573 m_log.Error("Unable to send group membership data via eventqueue - exception: " + ex.ToString());
2574 m_log.Warn("sending group membership data via UDP");
2575 OutPacket(Groupupdate, ThrottleOutPacketType.Task);
2576 }
2577 }
2578
2579
2580 public void SendGroupNameReply(UUID groupLLUID, string GroupName)
2581 {
2582 UUIDGroupNameReplyPacket pack = new UUIDGroupNameReplyPacket();
2583 UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1];
2584 UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock();
2585 uidnamebloc.ID = groupLLUID;
2586 uidnamebloc.GroupName = Util.StringToBytes256(GroupName);
2587 uidnameblock[0] = uidnamebloc;
2588 pack.UUIDNameBlock = uidnameblock;
2589 OutPacket(pack, ThrottleOutPacketType.Task);
2590 }
2591
2592 public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia)
2593 {
2594 LandStatReplyPacket lsrp = new LandStatReplyPacket();
2595 // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock();
2596 LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length];
2597 //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock();
2598 // lsrepdb.
2599 lsrp.RequestData.ReportType = reportType;
2600 lsrp.RequestData.RequestFlags = requestFlags;
2601 lsrp.RequestData.TotalObjectCount = resultCount;
2602 for (int i = 0; i < lsrpia.Length; i++)
2603 {
2604 LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock();
2605 lsrepdb.LocationX = lsrpia[i].LocationX;
2606 lsrepdb.LocationY = lsrpia[i].LocationY;
2607 lsrepdb.LocationZ = lsrpia[i].LocationZ;
2608 lsrepdb.Score = lsrpia[i].Score;
2609 lsrepdb.TaskID = lsrpia[i].TaskID;
2610 lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID;
2611 lsrepdb.TaskName = Util.StringToBytes256(lsrpia[i].TaskName);
2612 lsrepdb.OwnerName = Util.StringToBytes256(lsrpia[i].OwnerName);
2613 lsrepdba[i] = lsrepdb;
2614 }
2615 lsrp.ReportData = lsrepdba;
2616 OutPacket(lsrp, ThrottleOutPacketType.Task);
2617 }
2618
2619 public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running)
2620 {
2621 ScriptRunningReplyPacket scriptRunningReply = new ScriptRunningReplyPacket();
2622 scriptRunningReply.Script.ObjectID = objectID;
2623 scriptRunningReply.Script.ItemID = itemID;
2624 scriptRunningReply.Script.Running = running;
2625
2626 OutPacket(scriptRunningReply, ThrottleOutPacketType.Task);
2627 }
2628
2629 public void SendAsset(AssetRequestToClient req)
2630 {
2631 if (req.AssetInf.Data == null)
2632 {
2633 m_log.ErrorFormat("Cannot send asset {0} ({1}), asset data is null",
2634 req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
2635 return;
2636 }
2637
2638 //m_log.Debug("sending asset " + req.RequestAssetID);
2639 TransferInfoPacket Transfer = new TransferInfoPacket();
2640 Transfer.TransferInfo.ChannelType = 2;
2641 Transfer.TransferInfo.Status = 0;
2642 Transfer.TransferInfo.TargetType = 0;
2643 if (req.AssetRequestSource == 2)
2644 {
2645 Transfer.TransferInfo.Params = new byte[20];
2646 Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
2647 int assType = req.AssetInf.Type;
2648 Array.Copy(Utils.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4);
2649 }
2650 else if (req.AssetRequestSource == 3)
2651 {
2652 Transfer.TransferInfo.Params = req.Params;
2653 // Transfer.TransferInfo.Params = new byte[100];
2654 //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
2655 //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16);
2656 }
2657 Transfer.TransferInfo.Size = req.AssetInf.Data.Length;
2658 Transfer.TransferInfo.TransferID = req.TransferRequestID;
2659 Transfer.Header.Zerocoded = true;
2660 OutPacket(Transfer, ThrottleOutPacketType.Asset);
2661
2662 if (req.NumPackets == 1)
2663 {
2664 TransferPacketPacket TransferPacket = new TransferPacketPacket();
2665 TransferPacket.TransferData.Packet = 0;
2666 TransferPacket.TransferData.ChannelType = 2;
2667 TransferPacket.TransferData.TransferID = req.TransferRequestID;
2668 TransferPacket.TransferData.Data = req.AssetInf.Data;
2669 TransferPacket.TransferData.Status = 1;
2670 TransferPacket.Header.Zerocoded = true;
2671 OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
2672 }
2673 else
2674 {
2675 int processedLength = 0;
2676 int maxChunkSize = Settings.MAX_PACKET_SIZE - 100;
2677 int packetNumber = 0;
2678
2679 while (processedLength < req.AssetInf.Data.Length)
2680 {
2681 TransferPacketPacket TransferPacket = new TransferPacketPacket();
2682 TransferPacket.TransferData.Packet = packetNumber;
2683 TransferPacket.TransferData.ChannelType = 2;
2684 TransferPacket.TransferData.TransferID = req.TransferRequestID;
2685
2686 int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize);
2687 byte[] chunk = new byte[chunkSize];
2688 Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length);
2689
2690 TransferPacket.TransferData.Data = chunk;
2691
2692 // 0 indicates more packets to come, 1 indicates last packet
2693 if (req.AssetInf.Data.Length - processedLength > maxChunkSize)
2694 {
2695 TransferPacket.TransferData.Status = 0;
2696 }
2697 else
2698 {
2699 TransferPacket.TransferData.Status = 1;
2700 }
2701 TransferPacket.Header.Zerocoded = true;
2702 OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
2703
2704 processedLength += chunkSize;
2705 packetNumber++;
2706 }
2707 }
2708 }
2709
2710 public void SendTexture(AssetBase TextureAsset)
2711 {
2712
2713 }
2714
2715 public void SendRegionHandle(UUID regionID, ulong handle)
2716 {
2717 RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)PacketPool.Instance.GetPacket(PacketType.RegionIDAndHandleReply);
2718 reply.ReplyBlock.RegionID = regionID;
2719 reply.ReplyBlock.RegionHandle = handle;
2720 OutPacket(reply, ThrottleOutPacketType.Land);
2721 }
2722
2723 public void SendParcelInfo(RegionInfo info, LandData land, UUID parcelID, uint x, uint y)
2724 {
2725 float dwell = 0.0f;
2726 IDwellModule dwellModule = m_scene.RequestModuleInterface<IDwellModule>();
2727 if (dwellModule != null)
2728 dwell = dwellModule.GetDwell(land.GlobalID);
2729 ParcelInfoReplyPacket reply = (ParcelInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelInfoReply);
2730 reply.AgentData.AgentID = m_agentId;
2731 reply.Data.ParcelID = parcelID;
2732 reply.Data.OwnerID = land.OwnerID;
2733 reply.Data.Name = Utils.StringToBytes(land.Name);
2734 reply.Data.Desc = Utils.StringToBytes(land.Description);
2735 reply.Data.ActualArea = land.Area;
2736 reply.Data.BillableArea = land.Area; // TODO: what is this?
2737
2738 // Bit 0: Mature, bit 7: on sale, other bits: no idea
2739 reply.Data.Flags = (byte)(
2740 (info.AccessLevel > 13 ? (1 << 0) : 0) +
2741 ((land.Flags & (uint)ParcelFlags.ForSale) != 0 ? (1 << 7) : 0));
2742
2743 Vector3 pos = land.UserLocation;
2744 if (pos.Equals(Vector3.Zero))
2745 {
2746 pos = (land.AABBMax + land.AABBMin) * 0.5f;
2747 }
2748 reply.Data.GlobalX = info.RegionLocX + x;
2749 reply.Data.GlobalY = info.RegionLocY + y;
2750 reply.Data.GlobalZ = pos.Z;
2751 reply.Data.SimName = Utils.StringToBytes(info.RegionName);
2752 reply.Data.SnapshotID = land.SnapshotID;
2753 reply.Data.Dwell = dwell;
2754 reply.Data.SalePrice = land.SalePrice;
2755 reply.Data.AuctionID = (int)land.AuctionID;
2756
2757 OutPacket(reply, ThrottleOutPacketType.Land);
2758 }
2759
2760 public void SendScriptTeleportRequest(string objName, string simName, Vector3 pos, Vector3 lookAt)
2761 {
2762 ScriptTeleportRequestPacket packet = (ScriptTeleportRequestPacket)PacketPool.Instance.GetPacket(PacketType.ScriptTeleportRequest);
2763
2764 packet.Data.ObjectName = Utils.StringToBytes(objName);
2765 packet.Data.SimName = Utils.StringToBytes(simName);
2766 packet.Data.SimPosition = pos;
2767 packet.Data.LookAt = lookAt;
2768
2769 OutPacket(packet, ThrottleOutPacketType.Task);
2770 }
2771
2772 public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data)
2773 {
2774 DirPlacesReplyPacket packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply);
2775
2776 packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock();
2777
2778 packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1];
2779 packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock();
2780
2781 packet.AgentData.AgentID = AgentId;
2782
2783 packet.QueryData[0].QueryID = queryID;
2784
2785 DirPlacesReplyPacket.QueryRepliesBlock[] replies =
2786 new DirPlacesReplyPacket.QueryRepliesBlock[0];
2787 DirPlacesReplyPacket.StatusDataBlock[] status =
2788 new DirPlacesReplyPacket.StatusDataBlock[0];
2789
2790 packet.QueryReplies = replies;
2791 packet.StatusData = status;
2792
2793 foreach (DirPlacesReplyData d in data)
2794 {
2795 int idx = replies.Length;
2796 Array.Resize(ref replies, idx + 1);
2797 Array.Resize(ref status, idx + 1);
2798
2799 replies[idx] = new DirPlacesReplyPacket.QueryRepliesBlock();
2800 status[idx] = new DirPlacesReplyPacket.StatusDataBlock();
2801 replies[idx].ParcelID = d.parcelID;
2802 replies[idx].Name = Utils.StringToBytes(d.name);
2803 replies[idx].ForSale = d.forSale;
2804 replies[idx].Auction = d.auction;
2805 replies[idx].Dwell = d.dwell;
2806 status[idx].Status = d.Status;
2807
2808 packet.QueryReplies = replies;
2809 packet.StatusData = status;
2810
2811 if (packet.Length >= 1000)
2812 {
2813 OutPacket(packet, ThrottleOutPacketType.Task);
2814
2815 packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply);
2816
2817 packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock();
2818
2819 packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1];
2820 packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock();
2821
2822 packet.AgentData.AgentID = AgentId;
2823
2824 packet.QueryData[0].QueryID = queryID;
2825
2826 replies = new DirPlacesReplyPacket.QueryRepliesBlock[0];
2827 status = new DirPlacesReplyPacket.StatusDataBlock[0];
2828 }
2829 }
2830
2831 if (replies.Length > 0 || data.Length == 0)
2832 OutPacket(packet, ThrottleOutPacketType.Task);
2833 }
2834
2835 public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data)
2836 {
2837 DirPeopleReplyPacket packet = (DirPeopleReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPeopleReply);
2838
2839 packet.AgentData = new DirPeopleReplyPacket.AgentDataBlock();
2840 packet.AgentData.AgentID = AgentId;
2841
2842 packet.QueryData = new DirPeopleReplyPacket.QueryDataBlock();
2843 packet.QueryData.QueryID = queryID;
2844
2845 packet.QueryReplies = new DirPeopleReplyPacket.QueryRepliesBlock[
2846 data.Length];
2847
2848 int i = 0;
2849 foreach (DirPeopleReplyData d in data)
2850 {
2851 packet.QueryReplies[i] = new DirPeopleReplyPacket.QueryRepliesBlock();
2852 packet.QueryReplies[i].AgentID = d.agentID;
2853 packet.QueryReplies[i].FirstName =
2854 Utils.StringToBytes(d.firstName);
2855 packet.QueryReplies[i].LastName =
2856 Utils.StringToBytes(d.lastName);
2857 packet.QueryReplies[i].Group =
2858 Utils.StringToBytes(d.group);
2859 packet.QueryReplies[i].Online = d.online;
2860 packet.QueryReplies[i].Reputation = d.reputation;
2861 i++;
2862 }
2863
2864 OutPacket(packet, ThrottleOutPacketType.Task);
2865 }
2866
2867 public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data)
2868 {
2869 DirEventsReplyPacket packet = (DirEventsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirEventsReply);
2870
2871 packet.AgentData = new DirEventsReplyPacket.AgentDataBlock();
2872 packet.AgentData.AgentID = AgentId;
2873
2874 packet.QueryData = new DirEventsReplyPacket.QueryDataBlock();
2875 packet.QueryData.QueryID = queryID;
2876
2877 packet.QueryReplies = new DirEventsReplyPacket.QueryRepliesBlock[
2878 data.Length];
2879
2880 packet.StatusData = new DirEventsReplyPacket.StatusDataBlock[
2881 data.Length];
2882
2883 int i = 0;
2884 foreach (DirEventsReplyData d in data)
2885 {
2886 packet.QueryReplies[i] = new DirEventsReplyPacket.QueryRepliesBlock();
2887 packet.StatusData[i] = new DirEventsReplyPacket.StatusDataBlock();
2888 packet.QueryReplies[i].OwnerID = d.ownerID;
2889 packet.QueryReplies[i].Name =
2890 Utils.StringToBytes(d.name);
2891 packet.QueryReplies[i].EventID = d.eventID;
2892 packet.QueryReplies[i].Date =
2893 Utils.StringToBytes(d.date);
2894 packet.QueryReplies[i].UnixTime = d.unixTime;
2895 packet.QueryReplies[i].EventFlags = d.eventFlags;
2896 packet.StatusData[i].Status = d.Status;
2897 i++;
2898 }
2899
2900 OutPacket(packet, ThrottleOutPacketType.Task);
2901 }
2902
2903 public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data)
2904 {
2905 DirGroupsReplyPacket packet = (DirGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirGroupsReply);
2906
2907 packet.AgentData = new DirGroupsReplyPacket.AgentDataBlock();
2908 packet.AgentData.AgentID = AgentId;
2909
2910 packet.QueryData = new DirGroupsReplyPacket.QueryDataBlock();
2911 packet.QueryData.QueryID = queryID;
2912
2913 packet.QueryReplies = new DirGroupsReplyPacket.QueryRepliesBlock[
2914 data.Length];
2915
2916 int i = 0;
2917 foreach (DirGroupsReplyData d in data)
2918 {
2919 packet.QueryReplies[i] = new DirGroupsReplyPacket.QueryRepliesBlock();
2920 packet.QueryReplies[i].GroupID = d.groupID;
2921 packet.QueryReplies[i].GroupName =
2922 Utils.StringToBytes(d.groupName);
2923 packet.QueryReplies[i].Members = d.members;
2924 packet.QueryReplies[i].SearchOrder = d.searchOrder;
2925 i++;
2926 }
2927
2928 OutPacket(packet, ThrottleOutPacketType.Task);
2929 }
2930
2931 public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data)
2932 {
2933 DirClassifiedReplyPacket packet = (DirClassifiedReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirClassifiedReply);
2934
2935 packet.AgentData = new DirClassifiedReplyPacket.AgentDataBlock();
2936 packet.AgentData.AgentID = AgentId;
2937
2938 packet.QueryData = new DirClassifiedReplyPacket.QueryDataBlock();
2939 packet.QueryData.QueryID = queryID;
2940
2941 packet.QueryReplies = new DirClassifiedReplyPacket.QueryRepliesBlock[
2942 data.Length];
2943 packet.StatusData = new DirClassifiedReplyPacket.StatusDataBlock[
2944 data.Length];
2945
2946 int i = 0;
2947 foreach (DirClassifiedReplyData d in data)
2948 {
2949 packet.QueryReplies[i] = new DirClassifiedReplyPacket.QueryRepliesBlock();
2950 packet.StatusData[i] = new DirClassifiedReplyPacket.StatusDataBlock();
2951 packet.QueryReplies[i].ClassifiedID = d.classifiedID;
2952 packet.QueryReplies[i].Name =
2953 Utils.StringToBytes(d.name);
2954 packet.QueryReplies[i].ClassifiedFlags = d.classifiedFlags;
2955 packet.QueryReplies[i].CreationDate = d.creationDate;
2956 packet.QueryReplies[i].ExpirationDate = d.expirationDate;
2957 packet.QueryReplies[i].PriceForListing = d.price;
2958 packet.StatusData[i].Status = d.Status;
2959 i++;
2960 }
2961
2962 OutPacket(packet, ThrottleOutPacketType.Task);
2963 }
2964
2965 public void SendDirLandReply(UUID queryID, DirLandReplyData[] data)
2966 {
2967 DirLandReplyPacket packet = (DirLandReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirLandReply);
2968
2969 packet.AgentData = new DirLandReplyPacket.AgentDataBlock();
2970 packet.AgentData.AgentID = AgentId;
2971
2972 packet.QueryData = new DirLandReplyPacket.QueryDataBlock();
2973 packet.QueryData.QueryID = queryID;
2974
2975 packet.QueryReplies = new DirLandReplyPacket.QueryRepliesBlock[
2976 data.Length];
2977
2978 int i = 0;
2979 foreach (DirLandReplyData d in data)
2980 {
2981 packet.QueryReplies[i] = new DirLandReplyPacket.QueryRepliesBlock();
2982 packet.QueryReplies[i].ParcelID = d.parcelID;
2983 packet.QueryReplies[i].Name =
2984 Utils.StringToBytes(d.name);
2985 packet.QueryReplies[i].Auction = d.auction;
2986 packet.QueryReplies[i].ForSale = d.forSale;
2987 packet.QueryReplies[i].SalePrice = d.salePrice;
2988 packet.QueryReplies[i].ActualArea = d.actualArea;
2989 i++;
2990 }
2991
2992 OutPacket(packet, ThrottleOutPacketType.Task);
2993 }
2994
2995 public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data)
2996 {
2997 DirPopularReplyPacket packet = (DirPopularReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPopularReply);
2998
2999 packet.AgentData = new DirPopularReplyPacket.AgentDataBlock();
3000 packet.AgentData.AgentID = AgentId;
3001
3002 packet.QueryData = new DirPopularReplyPacket.QueryDataBlock();
3003 packet.QueryData.QueryID = queryID;
3004
3005 packet.QueryReplies = new DirPopularReplyPacket.QueryRepliesBlock[
3006 data.Length];
3007
3008 int i = 0;
3009 foreach (DirPopularReplyData d in data)
3010 {
3011 packet.QueryReplies[i] = new DirPopularReplyPacket.QueryRepliesBlock();
3012 packet.QueryReplies[i].ParcelID = d.parcelID;
3013 packet.QueryReplies[i].Name =
3014 Utils.StringToBytes(d.name);
3015 packet.QueryReplies[i].Dwell = d.dwell;
3016 i++;
3017 }
3018
3019 OutPacket(packet, ThrottleOutPacketType.Task);
3020 }
3021
3022 public void SendEventInfoReply(EventData data)
3023 {
3024 EventInfoReplyPacket packet = (EventInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.EventInfoReply);
3025
3026 packet.AgentData = new EventInfoReplyPacket.AgentDataBlock();
3027 packet.AgentData.AgentID = AgentId;
3028
3029 packet.EventData = new EventInfoReplyPacket.EventDataBlock();
3030 packet.EventData.EventID = data.eventID;
3031 packet.EventData.Creator = Utils.StringToBytes(data.creator);
3032 packet.EventData.Name = Utils.StringToBytes(data.name);
3033 packet.EventData.Category = Utils.StringToBytes(data.category);
3034 packet.EventData.Desc = Utils.StringToBytes(data.description);
3035 packet.EventData.Date = Utils.StringToBytes(data.date);
3036 packet.EventData.DateUTC = data.dateUTC;
3037 packet.EventData.Duration = data.duration;
3038 packet.EventData.Cover = data.cover;
3039 packet.EventData.Amount = data.amount;
3040 packet.EventData.SimName = Utils.StringToBytes(data.simName);
3041 packet.EventData.GlobalPos = new Vector3d(data.globalPos);
3042 packet.EventData.EventFlags = data.eventFlags;
3043
3044 OutPacket(packet, ThrottleOutPacketType.Task);
3045 }
3046
3047 public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags)
3048 {
3049 MapItemReplyPacket mirplk = new MapItemReplyPacket();
3050 mirplk.AgentData.AgentID = AgentId;
3051 mirplk.RequestData.ItemType = mapitemtype;
3052 mirplk.Data = new MapItemReplyPacket.DataBlock[replies.Length];
3053 for (int i = 0; i < replies.Length; i++)
3054 {
3055 MapItemReplyPacket.DataBlock mrdata = new MapItemReplyPacket.DataBlock();
3056 mrdata.X = replies[i].x;
3057 mrdata.Y = replies[i].y;
3058 mrdata.ID = replies[i].id;
3059 mrdata.Extra = replies[i].Extra;
3060 mrdata.Extra2 = replies[i].Extra2;
3061 mrdata.Name = Utils.StringToBytes(replies[i].name);
3062 mirplk.Data[i] = mrdata;
3063 }
3064 //m_log.Debug(mirplk.ToString());
3065 OutPacket(mirplk, ThrottleOutPacketType.Task);
3066
3067 }
3068
3069 public void SendOfferCallingCard(UUID srcID, UUID transactionID)
3070 {
3071 // a bit special, as this uses AgentID to store the source instead
3072 // of the destination. The destination (the receiver) goes into destID
3073 OfferCallingCardPacket p = (OfferCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.OfferCallingCard);
3074 p.AgentData.AgentID = srcID;
3075 p.AgentData.SessionID = UUID.Zero;
3076 p.AgentBlock.DestID = AgentId;
3077 p.AgentBlock.TransactionID = transactionID;
3078 OutPacket(p, ThrottleOutPacketType.Task);
3079 }
3080
3081 public void SendAcceptCallingCard(UUID transactionID)
3082 {
3083 AcceptCallingCardPacket p = (AcceptCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.AcceptCallingCard);
3084 p.AgentData.AgentID = AgentId;
3085 p.AgentData.SessionID = UUID.Zero;
3086 p.FolderData = new AcceptCallingCardPacket.FolderDataBlock[1];
3087 p.FolderData[0] = new AcceptCallingCardPacket.FolderDataBlock();
3088 p.FolderData[0].FolderID = UUID.Zero;
3089 OutPacket(p, ThrottleOutPacketType.Task);
3090 }
3091
3092 public void SendDeclineCallingCard(UUID transactionID)
3093 {
3094 DeclineCallingCardPacket p = (DeclineCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.DeclineCallingCard);
3095 p.AgentData.AgentID = AgentId;
3096 p.AgentData.SessionID = UUID.Zero;
3097 p.TransactionBlock.TransactionID = transactionID;
3098 OutPacket(p, ThrottleOutPacketType.Task);
3099 }
3100
3101 public void SendTerminateFriend(UUID exFriendID)
3102 {
3103 TerminateFriendshipPacket p = (TerminateFriendshipPacket)PacketPool.Instance.GetPacket(PacketType.TerminateFriendship);
3104 p.AgentData.AgentID = AgentId;
3105 p.AgentData.SessionID = SessionId;
3106 p.ExBlock.OtherID = exFriendID;
3107 OutPacket(p, ThrottleOutPacketType.Task);
3108 }
3109
3110 public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data)
3111 {
3112 OSDMap llsd = new OSDMap(3);
3113 OSDArray AgentData = new OSDArray(1);
3114 OSDMap AgentDataMap = new OSDMap(1);
3115 AgentDataMap.Add("AgentID", OSD.FromUUID(this.AgentId));
3116 AgentDataMap.Add("AvatarID", OSD.FromUUID(avatarID));
3117 AgentData.Add(AgentDataMap);
3118 llsd.Add("AgentData", AgentData);
3119 OSDArray GroupData = new OSDArray(data.Length);
3120 OSDArray NewGroupData = new OSDArray(data.Length);
3121 foreach (GroupMembershipData m in data)
3122 {
3123 OSDMap GroupDataMap = new OSDMap(6);
3124 OSDMap NewGroupDataMap = new OSDMap(1);
3125 GroupDataMap.Add("GroupPowers", OSD.FromULong(m.GroupPowers));
3126 GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(m.AcceptNotices));
3127 GroupDataMap.Add("GroupTitle", OSD.FromString(m.GroupTitle));
3128 GroupDataMap.Add("GroupID", OSD.FromUUID(m.GroupID));
3129 GroupDataMap.Add("GroupName", OSD.FromString(m.GroupName));
3130 GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(m.GroupPicture));
3131 NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(m.ListInProfile));
3132 GroupData.Add(GroupDataMap);
3133 NewGroupData.Add(NewGroupDataMap);
3134 }
3135 llsd.Add("GroupData", GroupData);
3136 llsd.Add("NewGroupData", NewGroupData);
3137
3138 IEventQueue eq = this.Scene.RequestModuleInterface<IEventQueue>();
3139 if (eq != null)
3140 {
3141 eq.Enqueue(BuildEvent("AvatarGroupsReply", llsd), this.AgentId);
3142 }
3143 }
3144
3145 public void SendJoinGroupReply(UUID groupID, bool success)
3146 {
3147 JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply);
3148
3149 p.AgentData = new JoinGroupReplyPacket.AgentDataBlock();
3150 p.AgentData.AgentID = AgentId;
3151
3152 p.GroupData = new JoinGroupReplyPacket.GroupDataBlock();
3153 p.GroupData.GroupID = groupID;
3154 p.GroupData.Success = success;
3155
3156 OutPacket(p, ThrottleOutPacketType.Task);
3157 }
3158
3159 public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success)
3160 {
3161 EjectGroupMemberReplyPacket p = (EjectGroupMemberReplyPacket)PacketPool.Instance.GetPacket(PacketType.EjectGroupMemberReply);
3162
3163 p.AgentData = new EjectGroupMemberReplyPacket.AgentDataBlock();
3164 p.AgentData.AgentID = agentID;
3165
3166 p.GroupData = new EjectGroupMemberReplyPacket.GroupDataBlock();
3167 p.GroupData.GroupID = groupID;
3168
3169 p.EjectData = new EjectGroupMemberReplyPacket.EjectDataBlock();
3170 p.EjectData.Success = success;
3171
3172 OutPacket(p, ThrottleOutPacketType.Task);
3173 }
3174
3175 public void SendLeaveGroupReply(UUID groupID, bool success)
3176 {
3177 LeaveGroupReplyPacket p = (LeaveGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.LeaveGroupReply);
3178
3179 p.AgentData = new LeaveGroupReplyPacket.AgentDataBlock();
3180 p.AgentData.AgentID = AgentId;
3181
3182 p.GroupData = new LeaveGroupReplyPacket.GroupDataBlock();
3183 p.GroupData.GroupID = groupID;
3184 p.GroupData.Success = success;
3185
3186 OutPacket(p, ThrottleOutPacketType.Task);
3187 }
3188
3189 public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name)
3190 {
3191 if (classifiedID.Length != name.Length)
3192 return;
3193
3194 AvatarClassifiedReplyPacket ac =
3195 (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket(
3196 PacketType.AvatarClassifiedReply);
3197
3198 ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock();
3199 ac.AgentData.AgentID = AgentId;
3200 ac.AgentData.TargetID = targetID;
3201
3202 ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifiedID.Length];
3203 int i;
3204 for (i = 0; i < classifiedID.Length; i++)
3205 {
3206 ac.Data[i].ClassifiedID = classifiedID[i];
3207 ac.Data[i].Name = Utils.StringToBytes(name[i]);
3208 }
3209
3210 OutPacket(ac, ThrottleOutPacketType.Task);
3211 }
3212
3213 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)
3214 {
3215 ClassifiedInfoReplyPacket cr =
3216 (ClassifiedInfoReplyPacket)PacketPool.Instance.GetPacket(
3217 PacketType.ClassifiedInfoReply);
3218
3219 cr.AgentData = new ClassifiedInfoReplyPacket.AgentDataBlock();
3220 cr.AgentData.AgentID = AgentId;
3221
3222 cr.Data = new ClassifiedInfoReplyPacket.DataBlock();
3223 cr.Data.ClassifiedID = classifiedID;
3224 cr.Data.CreatorID = creatorID;
3225 cr.Data.CreationDate = creationDate;
3226 cr.Data.ExpirationDate = expirationDate;
3227 cr.Data.Category = category;
3228 cr.Data.Name = Utils.StringToBytes(name);
3229 cr.Data.Desc = Utils.StringToBytes(description);
3230 cr.Data.ParcelID = parcelID;
3231 cr.Data.ParentEstate = parentEstate;
3232 cr.Data.SnapshotID = snapshotID;
3233 cr.Data.SimName = Utils.StringToBytes(simName);
3234 cr.Data.PosGlobal = new Vector3d(globalPos);
3235 cr.Data.ParcelName = Utils.StringToBytes(parcelName);
3236 cr.Data.ClassifiedFlags = classifiedFlags;
3237 cr.Data.PriceForListing = price;
3238
3239 OutPacket(cr, ThrottleOutPacketType.Task);
3240 }
3241
3242 public void SendAgentDropGroup(UUID groupID)
3243 {
3244 AgentDropGroupPacket dg =
3245 (AgentDropGroupPacket)PacketPool.Instance.GetPacket(
3246 PacketType.AgentDropGroup);
3247
3248 dg.AgentData = new AgentDropGroupPacket.AgentDataBlock();
3249 dg.AgentData.AgentID = AgentId;
3250 dg.AgentData.GroupID = groupID;
3251
3252 OutPacket(dg, ThrottleOutPacketType.Task);
3253 }
3254
3255 public void SendAvatarNotesReply(UUID targetID, string text)
3256 {
3257 AvatarNotesReplyPacket an =
3258 (AvatarNotesReplyPacket)PacketPool.Instance.GetPacket(
3259 PacketType.AvatarNotesReply);
3260
3261 an.AgentData = new AvatarNotesReplyPacket.AgentDataBlock();
3262 an.AgentData.AgentID = AgentId;
3263
3264 an.Data = new AvatarNotesReplyPacket.DataBlock();
3265 an.Data.TargetID = targetID;
3266 an.Data.Notes = Utils.StringToBytes(text);
3267
3268 OutPacket(an, ThrottleOutPacketType.Task);
3269 }
3270
3271 public void SendAvatarPicksReply(UUID targetID, Dictionary<UUID, string> picks)
3272 {
3273 AvatarPicksReplyPacket ap =
3274 (AvatarPicksReplyPacket)PacketPool.Instance.GetPacket(
3275 PacketType.AvatarPicksReply);
3276
3277 ap.AgentData = new AvatarPicksReplyPacket.AgentDataBlock();
3278 ap.AgentData.AgentID = AgentId;
3279 ap.AgentData.TargetID = targetID;
3280
3281 ap.Data = new AvatarPicksReplyPacket.DataBlock[picks.Count];
3282
3283 int i = 0;
3284 foreach (KeyValuePair<UUID, string> pick in picks)
3285 {
3286 ap.Data[i] = new AvatarPicksReplyPacket.DataBlock();
3287 ap.Data[i].PickID = pick.Key;
3288 ap.Data[i].PickName = Utils.StringToBytes(pick.Value);
3289 i++;
3290 }
3291
3292 OutPacket(ap, ThrottleOutPacketType.Task);
3293 }
3294
3295 public void SendAvatarClassifiedReply(UUID targetID, Dictionary<UUID, string> classifieds)
3296 {
3297 AvatarClassifiedReplyPacket ac =
3298 (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket(
3299 PacketType.AvatarClassifiedReply);
3300
3301 ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock();
3302 ac.AgentData.AgentID = AgentId;
3303 ac.AgentData.TargetID = targetID;
3304
3305 ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifieds.Count];
3306
3307 int i = 0;
3308 foreach (KeyValuePair<UUID, string> classified in classifieds)
3309 {
3310 ac.Data[i] = new AvatarClassifiedReplyPacket.DataBlock();
3311 ac.Data[i].ClassifiedID = classified.Key;
3312 ac.Data[i].Name = Utils.StringToBytes(classified.Value);
3313 i++;
3314 }
3315
3316 OutPacket(ac, ThrottleOutPacketType.Task);
3317 }
3318
3319 public void SendParcelDwellReply(int localID, UUID parcelID, float dwell)
3320 {
3321 ParcelDwellReplyPacket pd =
3322 (ParcelDwellReplyPacket)PacketPool.Instance.GetPacket(
3323 PacketType.ParcelDwellReply);
3324
3325 pd.AgentData = new ParcelDwellReplyPacket.AgentDataBlock();
3326 pd.AgentData.AgentID = AgentId;
3327
3328 pd.Data = new ParcelDwellReplyPacket.DataBlock();
3329 pd.Data.LocalID = localID;
3330 pd.Data.ParcelID = parcelID;
3331 pd.Data.Dwell = dwell;
3332
3333 OutPacket(pd, ThrottleOutPacketType.Land);
3334 }
3335
3336 public void SendUserInfoReply(bool imViaEmail, bool visible, string email)
3337 {
3338 UserInfoReplyPacket ur =
3339 (UserInfoReplyPacket)PacketPool.Instance.GetPacket(
3340 PacketType.UserInfoReply);
3341
3342 string Visible = "hidden";
3343 if (visible)
3344 Visible = "default";
3345
3346 ur.AgentData = new UserInfoReplyPacket.AgentDataBlock();
3347 ur.AgentData.AgentID = AgentId;
3348
3349 ur.UserData = new UserInfoReplyPacket.UserDataBlock();
3350 ur.UserData.IMViaEMail = imViaEmail;
3351 ur.UserData.DirectoryVisibility = Utils.StringToBytes(Visible);
3352 ur.UserData.EMail = Utils.StringToBytes(email);
3353
3354 OutPacket(ur, ThrottleOutPacketType.Task);
3355 }
3356
3357 public void SendCreateGroupReply(UUID groupID, bool success, string message)
3358 {
3359 CreateGroupReplyPacket createGroupReply = (CreateGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.CreateGroupReply);
3360
3361 createGroupReply.AgentData =
3362 new CreateGroupReplyPacket.AgentDataBlock();
3363 createGroupReply.ReplyData =
3364 new CreateGroupReplyPacket.ReplyDataBlock();
3365
3366 createGroupReply.AgentData.AgentID = AgentId;
3367 createGroupReply.ReplyData.GroupID = groupID;
3368
3369 createGroupReply.ReplyData.Success = success;
3370 createGroupReply.ReplyData.Message = Utils.StringToBytes(message);
3371 OutPacket(createGroupReply, ThrottleOutPacketType.Task);
3372 }
3373
3374 public void SendUseCachedMuteList()
3375 {
3376 UseCachedMuteListPacket useCachedMuteList = (UseCachedMuteListPacket)PacketPool.Instance.GetPacket(PacketType.UseCachedMuteList);
3377
3378 useCachedMuteList.AgentData = new UseCachedMuteListPacket.AgentDataBlock();
3379 useCachedMuteList.AgentData.AgentID = AgentId;
3380
3381 OutPacket(useCachedMuteList, ThrottleOutPacketType.Task);
3382 }
3383
3384 public void SendMuteListUpdate(string filename)
3385 {
3386 MuteListUpdatePacket muteListUpdate = (MuteListUpdatePacket)PacketPool.Instance.GetPacket(PacketType.MuteListUpdate);
3387
3388 muteListUpdate.MuteData = new MuteListUpdatePacket.MuteDataBlock();
3389 muteListUpdate.MuteData.AgentID = AgentId;
3390 muteListUpdate.MuteData.Filename = Utils.StringToBytes(filename);
3391
3392 OutPacket(muteListUpdate, ThrottleOutPacketType.Task);
3393 }
3394
3395 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)
3396 {
3397 PickInfoReplyPacket pickInfoReply = (PickInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.PickInfoReply);
3398
3399 pickInfoReply.AgentData = new PickInfoReplyPacket.AgentDataBlock();
3400 pickInfoReply.AgentData.AgentID = AgentId;
3401
3402 pickInfoReply.Data = new PickInfoReplyPacket.DataBlock();
3403 pickInfoReply.Data.PickID = pickID;
3404 pickInfoReply.Data.CreatorID = creatorID;
3405 pickInfoReply.Data.TopPick = topPick;
3406 pickInfoReply.Data.ParcelID = parcelID;
3407 pickInfoReply.Data.Name = Utils.StringToBytes(name);
3408 pickInfoReply.Data.Desc = Utils.StringToBytes(desc);
3409 pickInfoReply.Data.SnapshotID = snapshotID;
3410 pickInfoReply.Data.User = Utils.StringToBytes(user);
3411 pickInfoReply.Data.OriginalName = Utils.StringToBytes(originalName);
3412 pickInfoReply.Data.SimName = Utils.StringToBytes(simName);
3413 pickInfoReply.Data.PosGlobal = new Vector3d(posGlobal);
3414 pickInfoReply.Data.SortOrder = sortOrder;
3415 pickInfoReply.Data.Enabled = enabled;
3416
3417 OutPacket(pickInfoReply, ThrottleOutPacketType.Task);
3418 }
3419
3420 #endregion Scene/Avatar to Client
3421
3422 // Gesture
3423
3424 #region Appearance/ Wearables Methods
3425
3426 public void SendWearables(AvatarWearable[] wearables, int serial)
3427 {
3428 AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate);
3429 aw.AgentData.AgentID = AgentId;
3430 aw.AgentData.SerialNum = (uint)serial;
3431 aw.AgentData.SessionID = m_sessionId;
3432
3433 int count = 0;
3434 for (int i = 0; i < wearables.Length; i++)
3435 count += wearables[i].Count;
3436
3437 // TODO: don't create new blocks if recycling an old packet
3438 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count];
3439 AgentWearablesUpdatePacket.WearableDataBlock awb;
3440 int idx = 0;
3441 for (int i = 0; i < wearables.Length; i++)
3442 {
3443 for (int j = 0; j < wearables[i].Count; j++)
3444 {
3445 awb = new AgentWearablesUpdatePacket.WearableDataBlock();
3446 awb.WearableType = (byte)i;
3447 awb.AssetID = wearables[i][j].AssetID;
3448 awb.ItemID = wearables[i][j].ItemID;
3449 aw.WearableData[idx] = awb;
3450 idx++;
3451
3452// m_log.DebugFormat(
3453// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}",
3454// awb.ItemID, awb.AssetID, i, Name);
3455 }
3456 }
3457
3458 OutPacket(aw, ThrottleOutPacketType.Task);
3459 }
3460
3461 public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry)
3462 {
3463 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance);
3464 // TODO: don't create new blocks if recycling an old packet
3465 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218];
3466 avp.ObjectData.TextureEntry = textureEntry;
3467
3468 AvatarAppearancePacket.VisualParamBlock avblock = null;
3469 for (int i = 0; i < visualParams.Length; i++)
3470 {
3471 avblock = new AvatarAppearancePacket.VisualParamBlock();
3472 avblock.ParamValue = visualParams[i];
3473 avp.VisualParam[i] = avblock;
3474 }
3475
3476 avp.Sender.IsTrial = false;
3477 avp.Sender.ID = agentID;
3478 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString());
3479 OutPacket(avp, ThrottleOutPacketType.Task);
3480 }
3481
3482 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
3483 {
3484 //m_log.DebugFormat("[CLIENT]: Sending animations to {0}", Name);
3485
3486 AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation);
3487 // TODO: don't create new blocks if recycling an old packet
3488 ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[animations.Length];
3489 ani.Sender = new AvatarAnimationPacket.SenderBlock();
3490 ani.Sender.ID = sourceAgentId;
3491 ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length];
3492 ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0];
3493
3494 for (int i = 0; i < animations.Length; ++i)
3495 {
3496 ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock();
3497 ani.AnimationList[i].AnimID = animations[i];
3498 ani.AnimationList[i].AnimSequenceID = seqs[i];
3499
3500 ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock();
3501 if (objectIDs[i].Equals(sourceAgentId))
3502 ani.AnimationSourceList[i].ObjectID = UUID.Zero;
3503 else
3504 ani.AnimationSourceList[i].ObjectID = objectIDs[i];
3505 }
3506 ani.Header.Reliable = false;
3507 OutPacket(ani, ThrottleOutPacketType.Task);
3508 }
3509
3510 #endregion
3511
3512 #region Avatar Packet/Data Sending Methods
3513
3514 /// <summary>
3515 /// Send an ObjectUpdate packet with information about an avatar
3516 /// </summary>
3517 public void SendAvatarDataImmediate(ISceneEntity avatar)
3518 {
3519 ScenePresence presence = avatar as ScenePresence;
3520 if (presence == null)
3521 return;
3522
3523 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3524 objupdate.Header.Zerocoded = true;
3525
3526 objupdate.RegionData.RegionHandle = presence.RegionHandle;
3527 objupdate.RegionData.TimeDilation = ushort.MaxValue;
3528
3529 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3530 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence);
3531
3532 OutPacket(objupdate, ThrottleOutPacketType.Task);
3533
3534 // We need to record the avatar local id since the root prim of an attachment points to this.
3535// m_attachmentsSent.Add(avatar.LocalId);
3536 }
3537
3538 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
3539 {
3540 if (!IsActive) return; // We don't need to update inactive clients.
3541
3542 CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate);
3543 loc.Header.Reliable = false;
3544
3545 // Each packet can only hold around 60 avatar positions and the client clears the mini-map each time
3546 // a CoarseLocationUpdate packet is received. Oh well.
3547 int total = Math.Min(CoarseLocations.Count, 60);
3548
3549 CoarseLocationUpdatePacket.IndexBlock ib = new CoarseLocationUpdatePacket.IndexBlock();
3550
3551 loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total];
3552 loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total];
3553
3554 int selfindex = -1;
3555 for (int i = 0; i < total; i++)
3556 {
3557 CoarseLocationUpdatePacket.LocationBlock lb =
3558 new CoarseLocationUpdatePacket.LocationBlock();
3559
3560 lb.X = (byte)CoarseLocations[i].X;
3561 lb.Y = (byte)CoarseLocations[i].Y;
3562
3563 lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25f);
3564 loc.Location[i] = lb;
3565 loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock();
3566 loc.AgentData[i].AgentID = users[i];
3567 if (users[i] == AgentId)
3568 selfindex = i;
3569 }
3570
3571 ib.You = (short)selfindex;
3572 ib.Prey = -1;
3573 loc.Index = ib;
3574
3575 OutPacket(loc, ThrottleOutPacketType.Task);
3576 }
3577
3578 #endregion Avatar Packet/Data Sending Methods
3579
3580 #region Primitive Packet/Data Sending Methods
3581
3582
3583 /// <summary>
3584 /// Generate one of the object update packets based on PrimUpdateFlags
3585 /// and broadcast the packet to clients
3586 /// </summary>
3587 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3588 {
3589 if (entity is SceneObjectPart)
3590 {
3591 SceneObjectPart e = (SceneObjectPart)entity;
3592 SceneObjectGroup g = e.ParentGroup;
3593 if (g.RootPart.Shape.State > 30) // HUD
3594 if (g.OwnerID != AgentId)
3595 return; // Don't send updates for other people's HUDs
3596 }
3597
3598 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3599
3600 lock (m_entityUpdates.SyncRoot)
3601 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
3602 }
3603
3604 /// <summary>
3605 /// Requeue an EntityUpdate when it was not acknowledged by the client.
3606 /// We will update the priority and put it in the correct queue, merging update flags
3607 /// with any other updates that may be queued for the same entity.
3608 /// The original update time is used for the merged update.
3609 /// </summary>
3610 private void ResendPrimUpdate(EntityUpdate update)
3611 {
3612 // If the update exists in priority queue, it will be updated.
3613 // If it does not exist then it will be added with the current (rather than its original) priority
3614 uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity);
3615
3616 lock (m_entityUpdates.SyncRoot)
3617 m_entityUpdates.Enqueue(priority, update);
3618 }
3619
3620 /// <summary>
3621 /// Requeue a list of EntityUpdates when they were not acknowledged by the client.
3622 /// We will update the priority and put it in the correct queue, merging update flags
3623 /// with any other updates that may be queued for the same entity.
3624 /// The original update time is used for the merged update.
3625 /// </summary>
3626 private void ResendPrimUpdates(List<EntityUpdate> updates, OutgoingPacket oPacket)
3627 {
3628 // m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime);
3629
3630 // Remove the update packet from the list of packets waiting for acknowledgement
3631 // because we are requeuing the list of updates. They will be resent in new packets
3632 // with the most recent state and priority.
3633 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
3634
3635 // Count this as a resent packet since we are going to requeue all of the updates contained in it
3636 Interlocked.Increment(ref m_udpClient.PacketsResent);
3637
3638 foreach (EntityUpdate update in updates)
3639 ResendPrimUpdate(update);
3640 }
3641
3642 private void ProcessEntityUpdates(int maxUpdates)
3643 {
3644 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
3645 OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
3646 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3647 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3648
3649 OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3650 OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3651 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3652 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3653
3654 // Check to see if this is a flush
3655 if (maxUpdates <= 0)
3656 {
3657 maxUpdates = Int32.MaxValue;
3658 }
3659
3660 int updatesThisCall = 0;
3661
3662 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3663 // condition where a kill can be processed before an out-of-date update for the same object.
3664 float avgTimeDilation = 1.0f;
3665 IEntityUpdate iupdate;
3666 Int32 timeinqueue; // this is just debugging code & can be dropped later
3667
3668 while (updatesThisCall < maxUpdates)
3669 {
3670 lock (m_entityUpdates.SyncRoot)
3671 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3672 break;
3673
3674 EntityUpdate update = (EntityUpdate)iupdate;
3675
3676 avgTimeDilation += update.TimeDilation;
3677 avgTimeDilation *= 0.5f;
3678
3679 if (update.Entity is SceneObjectPart)
3680 {
3681 SceneObjectPart part = (SceneObjectPart)update.Entity;
3682
3683 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3684 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3685 // safety measure.
3686 //
3687 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3688 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3689 // updates and kills on different threads with different scheduling strategies, hence this protection.
3690 //
3691 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3692 // after the root prim has been deleted.
3693 lock (m_killRecord)
3694 {
3695 if (m_killRecord.Contains(part.LocalId))
3696 continue;
3697 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3698 continue;
3699 }
3700
3701 if (part.ParentGroup.IsDeleted)
3702 continue;
3703
3704 if (part.ParentGroup.IsAttachment)
3705 { // Someone else's HUD, why are we getting these?
3706 if (part.ParentGroup.OwnerID != AgentId &&
3707 part.ParentGroup.RootPart.Shape.State >= 30)
3708 continue;
3709 ScenePresence sp;
3710 // Owner is not in the sim, don't update it to
3711 // anyone
3712 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3713 continue;
3714
3715 List<SceneObjectGroup> atts = sp.Attachments;
3716 bool found = false;
3717 foreach (SceneObjectGroup att in atts)
3718 {
3719 if (att == part.ParentGroup)
3720 {
3721 found = true;
3722 break;
3723 }
3724 }
3725
3726 // It's an attachment of a valid avatar, but
3727 // doesn't seem to be attached, skip
3728 if (!found)
3729 continue;
3730 }
3731 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3732 {
3733 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3734 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3735 {
3736 part.Shape.LightEntry = false;
3737 }
3738 }
3739 }
3740
3741 ++updatesThisCall;
3742
3743 #region UpdateFlags to packet type conversion
3744
3745 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3746
3747 bool canUseCompressed = true;
3748 bool canUseImproved = true;
3749
3750 // Compressed object updates only make sense for LL primitives
3751 if (!(update.Entity is SceneObjectPart))
3752 {
3753 canUseCompressed = false;
3754 }
3755
3756 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3757 {
3758 canUseCompressed = false;
3759 canUseImproved = false;
3760 }
3761 else
3762 {
3763 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3764 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3765 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3766 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3767 {
3768 canUseCompressed = false;
3769 }
3770
3771 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3772 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3773 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3774 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3775 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3776 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3777 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3778 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3779 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3780 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3781 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3782 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3783 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3784 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3785 {
3786 canUseImproved = false;
3787 }
3788 }
3789
3790 #endregion UpdateFlags to packet type conversion
3791
3792 #region Block Construction
3793
3794 // TODO: Remove this once we can build compressed updates
3795 canUseCompressed = false;
3796
3797 if (!canUseImproved && !canUseCompressed)
3798 {
3799 if (update.Entity is ScenePresence)
3800 {
3801 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3802 }
3803 else
3804 {
3805 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3806 }
3807 }
3808 else if (!canUseImproved)
3809 {
3810 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3811 }
3812 else
3813 {
3814 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3815 // Self updates go into a special list
3816 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3817 else
3818 // Everything else goes here
3819 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3820 }
3821
3822 #endregion Block Construction
3823 }
3824
3825 #region Packet Sending
3826
3827 const float TIME_DILATION = 1.0f;
3828 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3829
3830 if (terseAgentUpdateBlocks.IsValueCreated)
3831 {
3832 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3833
3834 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3835 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3836 packet.RegionData.TimeDilation = timeDilation;
3837 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3838
3839 for (int i = 0; i < blocks.Count; i++)
3840 packet.ObjectData[i] = blocks[i];
3841
3842 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3843 }
3844
3845 if (objectUpdateBlocks.IsValueCreated)
3846 {
3847 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3848
3849 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3850 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3851 packet.RegionData.TimeDilation = timeDilation;
3852 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3853
3854 for (int i = 0; i < blocks.Count; i++)
3855 packet.ObjectData[i] = blocks[i];
3856
3857 OutPacket(packet, ThrottleOutPacketType.Task, true);
3858 }
3859
3860 if (compressedUpdateBlocks.IsValueCreated)
3861 {
3862 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3863
3864 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3865 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3866 packet.RegionData.TimeDilation = timeDilation;
3867 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3868
3869 for (int i = 0; i < blocks.Count; i++)
3870 packet.ObjectData[i] = blocks[i];
3871
3872 OutPacket(packet, ThrottleOutPacketType.Task, true);
3873 }
3874
3875 if (terseUpdateBlocks.IsValueCreated)
3876 {
3877 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3878
3879 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3880 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3881 packet.RegionData.TimeDilation = timeDilation;
3882 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3883
3884 for (int i = 0; i < blocks.Count; i++)
3885 packet.ObjectData[i] = blocks[i];
3886
3887 OutPacket(packet, ThrottleOutPacketType.Task, true);
3888 }
3889
3890 #endregion Packet Sending
3891 }
3892
3893 public void ReprioritizeUpdates()
3894 {
3895 lock (m_entityUpdates.SyncRoot)
3896 m_entityUpdates.Reprioritize(UpdatePriorityHandler);
3897 }
3898
3899 private bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity)
3900 {
3901 if (entity != null)
3902 {
3903 priority = m_prioritizer.GetUpdatePriority(this, entity);
3904 return true;
3905 }
3906
3907 return false;
3908 }
3909
3910 public void FlushPrimUpdates()
3911 {
3912 m_log.WarnFormat("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName);
3913
3914 while (m_entityUpdates.Count > 0)
3915 ProcessEntityUpdates(-1);
3916 }
3917
3918 #endregion Primitive Packet/Data Sending Methods
3919
3920 // These are used to implement an adaptive backoff in the number
3921 // of updates converted to packets. Since we don't want packets
3922 // to sit in the queue with old data, only convert enough updates
3923 // to packets that can be sent in 200ms.
3924 private Int32 m_LastQueueFill = 0;
3925 private Int32 m_maxUpdates = 0;
3926
3927 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
3928 {
3929 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
3930 {
3931 if (m_maxUpdates == 0 || m_LastQueueFill == 0)
3932 {
3933 m_maxUpdates = m_udpServer.PrimUpdatesPerCallback;
3934 }
3935 else
3936 {
3937 if (Util.EnvironmentTickCountSubtract(m_LastQueueFill) < 200)
3938 m_maxUpdates += 5;
3939 else
3940 m_maxUpdates = m_maxUpdates >> 1;
3941 }
3942 m_maxUpdates = Util.Clamp<Int32>(m_maxUpdates,10,500);
3943 m_LastQueueFill = Util.EnvironmentTickCount();
3944
3945 if (m_entityUpdates.Count > 0)
3946 ProcessEntityUpdates(m_maxUpdates);
3947
3948 if (m_entityProps.Count > 0)
3949 ProcessEntityPropertyRequests(m_maxUpdates);
3950 }
3951
3952 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
3953 {
3954 ProcessTextureRequests();
3955 }
3956 }
3957
3958 void ProcessTextureRequests()
3959 {
3960 if (m_imageManager != null)
3961 m_imageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
3962 }
3963
3964 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
3965 {
3966 AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
3967 newPack.AssetBlock.Type = AssetType;
3968 newPack.AssetBlock.Success = Success;
3969 newPack.AssetBlock.UUID = AssetFullID;
3970 newPack.Header.Zerocoded = true;
3971 OutPacket(newPack, ThrottleOutPacketType.Asset);
3972 }
3973
3974 public void SendXferRequest(ulong XferID, short AssetType, UUID vFileID, byte FilePath, byte[] FileName)
3975 {
3976 RequestXferPacket newPack = new RequestXferPacket();
3977 newPack.XferID.ID = XferID;
3978 newPack.XferID.VFileType = AssetType;
3979 newPack.XferID.VFileID = vFileID;
3980 newPack.XferID.FilePath = FilePath;
3981 newPack.XferID.Filename = FileName;
3982 newPack.Header.Zerocoded = true;
3983 OutPacket(newPack, ThrottleOutPacketType.Asset);
3984 }
3985
3986 public void SendConfirmXfer(ulong xferID, uint PacketID)
3987 {
3988 ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket();
3989 newPack.XferID.ID = xferID;
3990 newPack.XferID.Packet = PacketID;
3991 newPack.Header.Zerocoded = true;
3992 OutPacket(newPack, ThrottleOutPacketType.Asset);
3993 }
3994
3995 public void SendInitiateDownload(string simFileName, string clientFileName)
3996 {
3997 InitiateDownloadPacket newPack = new InitiateDownloadPacket();
3998 newPack.AgentData.AgentID = AgentId;
3999 newPack.FileData.SimFilename = Utils.StringToBytes(simFileName);
4000 newPack.FileData.ViewerFilename = Utils.StringToBytes(clientFileName);
4001 OutPacket(newPack, ThrottleOutPacketType.Asset);
4002 }
4003
4004 public void SendImageFirstPart(
4005 ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec)
4006 {
4007 ImageDataPacket im = new ImageDataPacket();
4008 im.Header.Reliable = false;
4009 im.ImageID.Packets = numParts;
4010 im.ImageID.ID = ImageUUID;
4011
4012 if (ImageSize > 0)
4013 im.ImageID.Size = ImageSize;
4014
4015 im.ImageData.Data = ImageData;
4016 im.ImageID.Codec = imageCodec;
4017 im.Header.Zerocoded = true;
4018 OutPacket(im, ThrottleOutPacketType.Texture);
4019 }
4020
4021 public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData)
4022 {
4023 ImagePacketPacket im = new ImagePacketPacket();
4024 im.Header.Reliable = false;
4025 im.ImageID.Packet = partNumber;
4026 im.ImageID.ID = imageUuid;
4027 im.ImageData.Data = imageData;
4028
4029 OutPacket(im, ThrottleOutPacketType.Texture);
4030 }
4031
4032 public void SendImageNotFound(UUID imageid)
4033 {
4034 ImageNotInDatabasePacket notFoundPacket
4035 = (ImageNotInDatabasePacket)PacketPool.Instance.GetPacket(PacketType.ImageNotInDatabase);
4036
4037 notFoundPacket.ImageID.ID = imageid;
4038
4039 OutPacket(notFoundPacket, ThrottleOutPacketType.Texture);
4040 }
4041
4042 public void SendShutdownConnectionNotice()
4043 {
4044 OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown);
4045 }
4046
4047 public void SendSimStats(SimStats stats)
4048 {
4049 SimStatsPacket pack = new SimStatsPacket();
4050 pack.Region = new SimStatsPacket.RegionBlock();
4051 pack.Region.RegionX = stats.RegionX;
4052 pack.Region.RegionY = stats.RegionY;
4053 pack.Region.RegionFlags = stats.RegionFlags;
4054 pack.Region.ObjectCapacity = stats.ObjectCapacity;
4055 //pack.Region = //stats.RegionBlock;
4056 pack.Stat = stats.StatsBlock;
4057
4058 pack.Header.Reliable = false;
4059
4060 OutPacket(pack, ThrottleOutPacketType.Task);
4061 }
4062
4063 private class ObjectPropertyUpdate : IEntityUpdate
4064 {
4065 internal bool SendFamilyProps;
4066 internal bool SendObjectProps;
4067
4068 public ObjectPropertyUpdate(ISceneEntity entity, uint flags, bool sendfam, bool sendobj)
4069 : base(entity,flags)
4070 {
4071 SendFamilyProps = sendfam;
4072 SendObjectProps = sendobj;
4073 }
4074 public void Update(ObjectPropertyUpdate update)
4075 {
4076 SendFamilyProps = SendFamilyProps || update.SendFamilyProps;
4077 SendObjectProps = SendObjectProps || update.SendObjectProps;
4078 // other properties may need to be updated by base class
4079 base.Update(update);
4080 }
4081 }
4082
4083 public void SendObjectPropertiesFamilyData(ISceneEntity entity, uint requestFlags)
4084 {
4085 uint priority = 0; // time based ordering only
4086 lock (m_entityProps.SyncRoot)
4087 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false));
4088 }
4089
4090 private void ResendPropertyUpdate(ObjectPropertyUpdate update)
4091 {
4092 uint priority = 0;
4093 lock (m_entityProps.SyncRoot)
4094 m_entityProps.Enqueue(priority, update);
4095 }
4096
4097 private void ResendPropertyUpdates(List<ObjectPropertyUpdate> updates, OutgoingPacket oPacket)
4098 {
4099 // m_log.WarnFormat("[CLIENT] resending object property {0}",updates[0].UpdateTime);
4100
4101 // Remove the update packet from the list of packets waiting for acknowledgement
4102 // because we are requeuing the list of updates. They will be resent in new packets
4103 // with the most recent state.
4104 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
4105
4106 // Count this as a resent packet since we are going to requeue all of the updates contained in it
4107 Interlocked.Increment(ref m_udpClient.PacketsResent);
4108
4109 foreach (ObjectPropertyUpdate update in updates)
4110 ResendPropertyUpdate(update);
4111 }
4112
4113 public void SendObjectPropertiesReply(ISceneEntity entity)
4114 {
4115 uint priority = 0; // time based ordering only
4116 lock (m_entityProps.SyncRoot)
4117 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,0,false,true));
4118 }
4119
4120 private void ProcessEntityPropertyRequests(int maxUpdates)
4121 {
4122 OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>> objectFamilyBlocks =
4123 new OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>>();
4124
4125 OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks =
4126 new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>();
4127
4128 OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> familyUpdates =
4129 new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
4130
4131 OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates =
4132 new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
4133
4134 IEntityUpdate iupdate;
4135 Int32 timeinqueue; // this is just debugging code & can be dropped later
4136
4137 int updatesThisCall = 0;
4138 while (updatesThisCall < m_maxUpdates)
4139 {
4140 lock (m_entityProps.SyncRoot)
4141 if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue))
4142 break;
4143
4144 ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate;
4145 if (update.SendFamilyProps)
4146 {
4147 if (update.Entity is SceneObjectPart)
4148 {
4149 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4150 ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
4151 objectFamilyBlocks.Value.Add(objPropDB);
4152 familyUpdates.Value.Add(update);
4153 }
4154 }
4155
4156 if (update.SendObjectProps)
4157 {
4158 if (update.Entity is SceneObjectPart)
4159 {
4160 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4161 ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
4162 objectPropertiesBlocks.Value.Add(objPropDB);
4163 propertyUpdates.Value.Add(update);
4164 }
4165 }
4166
4167 updatesThisCall++;
4168 }
4169
4170
4171 // Int32 ppcnt = 0;
4172 // Int32 pbcnt = 0;
4173
4174 if (objectPropertiesBlocks.IsValueCreated)
4175 {
4176 List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value;
4177 List<ObjectPropertyUpdate> updates = propertyUpdates.Value;
4178
4179 ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
4180 packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count];
4181 for (int i = 0; i < blocks.Count; i++)
4182 packet.ObjectData[i] = blocks[i];
4183
4184 packet.Header.Zerocoded = true;
4185
4186 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4187 // of the object rather than the properties when the packet was created
4188 OutPacket(packet, ThrottleOutPacketType.Task, true,
4189 delegate(OutgoingPacket oPacket)
4190 {
4191 ResendPropertyUpdates(updates, oPacket);
4192 });
4193
4194 // pbcnt += blocks.Count;
4195 // ppcnt++;
4196 }
4197
4198 // Int32 fpcnt = 0;
4199 // Int32 fbcnt = 0;
4200
4201 if (objectFamilyBlocks.IsValueCreated)
4202 {
4203 List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value;
4204
4205 // one packet per object block... uggh...
4206 for (int i = 0; i < blocks.Count; i++)
4207 {
4208 ObjectPropertiesFamilyPacket packet =
4209 (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
4210
4211 packet.ObjectData = blocks[i];
4212 packet.Header.Zerocoded = true;
4213
4214 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4215 // of the object rather than the properties when the packet was created
4216 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
4217 updates.Add(familyUpdates.Value[i]);
4218 OutPacket(packet, ThrottleOutPacketType.Task, true,
4219 delegate(OutgoingPacket oPacket)
4220 {
4221 ResendPropertyUpdates(updates, oPacket);
4222 });
4223
4224 // fpcnt++;
4225 // fbcnt++;
4226 }
4227
4228 }
4229
4230 // m_log.WarnFormat("[PACKETCOUNTS] queued {0} property packets with {1} blocks",ppcnt,pbcnt);
4231 // m_log.WarnFormat("[PACKETCOUNTS] queued {0} family property packets with {1} blocks",fpcnt,fbcnt);
4232 }
4233
4234 private ObjectPropertiesFamilyPacket.ObjectDataBlock CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, uint requestFlags)
4235 {
4236 ObjectPropertiesFamilyPacket.ObjectDataBlock block = new ObjectPropertiesFamilyPacket.ObjectDataBlock();
4237
4238 block.RequestFlags = requestFlags;
4239 block.ObjectID = sop.UUID;
4240 if (sop.OwnerID == sop.GroupID)
4241 block.OwnerID = UUID.Zero;
4242 else
4243 block.OwnerID = sop.OwnerID;
4244 block.GroupID = sop.GroupID;
4245 block.BaseMask = sop.BaseMask;
4246 block.OwnerMask = sop.OwnerMask;
4247 block.GroupMask = sop.GroupMask;
4248 block.EveryoneMask = sop.EveryoneMask;
4249 block.NextOwnerMask = sop.NextOwnerMask;
4250
4251 // TODO: More properties are needed in SceneObjectPart!
4252 block.OwnershipCost = sop.OwnershipCost;
4253 block.SaleType = sop.ObjectSaleType;
4254 block.SalePrice = sop.SalePrice;
4255 block.Category = sop.Category;
4256 block.LastOwnerID = sop.CreatorID; // copied from old SOG call... is this right?
4257 block.Name = Util.StringToBytes256(sop.Name);
4258 block.Description = Util.StringToBytes256(sop.Description);
4259
4260 return block;
4261 }
4262
4263 private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop)
4264 {
4265 //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
4266 // TODO: don't create new blocks if recycling an old packet
4267
4268 ObjectPropertiesPacket.ObjectDataBlock block =
4269 new ObjectPropertiesPacket.ObjectDataBlock();
4270
4271 block.ObjectID = sop.UUID;
4272 block.Name = Util.StringToBytes256(sop.Name);
4273 block.Description = Util.StringToBytes256(sop.Description);
4274
4275 block.CreationDate = (ulong)sop.CreationDate * 1000000; // viewer wants date in microseconds
4276 block.CreatorID = sop.CreatorID;
4277 block.GroupID = sop.GroupID;
4278 block.LastOwnerID = sop.LastOwnerID;
4279 if (sop.OwnerID == sop.GroupID)
4280 block.OwnerID = UUID.Zero;
4281 else
4282 block.OwnerID = sop.OwnerID;
4283
4284 block.ItemID = sop.FromUserInventoryItemID;
4285 block.FolderID = UUID.Zero; // sop.FromFolderID ??
4286 block.FromTaskID = UUID.Zero; // ???
4287 block.InventorySerial = (short)sop.InventorySerial;
4288
4289 SceneObjectPart root = sop.ParentGroup.RootPart;
4290
4291 block.TouchName = Util.StringToBytes256(root.TouchName);
4292 block.TextureID = new byte[0]; // TextureID ???
4293 block.SitName = Util.StringToBytes256(root.SitName);
4294 block.OwnerMask = root.OwnerMask;
4295 block.NextOwnerMask = root.NextOwnerMask;
4296 block.GroupMask = root.GroupMask;
4297 block.EveryoneMask = root.EveryoneMask;
4298 block.BaseMask = root.BaseMask;
4299 block.SaleType = root.ObjectSaleType;
4300 block.SalePrice = root.SalePrice;
4301
4302 return block;
4303 }
4304
4305 #region Estate Data Sending Methods
4306
4307 private static bool convertParamStringToBool(byte[] field)
4308 {
4309 string s = Utils.BytesToString(field);
4310 if (s == "1" || s.ToLower() == "y" || s.ToLower() == "yes" || s.ToLower() == "t" || s.ToLower() == "true")
4311 {
4312 return true;
4313 }
4314 return false;
4315 }
4316
4317 public void SendEstateList(UUID invoice, int code, UUID[] Data, uint estateID)
4318
4319 {
4320 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
4321 packet.AgentData.TransactionID = UUID.Random();
4322 packet.AgentData.AgentID = AgentId;
4323 packet.AgentData.SessionID = SessionId;
4324 packet.MethodData.Invoice = invoice;
4325 packet.MethodData.Method = Utils.StringToBytes("setaccess");
4326
4327 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + Data.Length];
4328
4329 for (int i = 0; i < (6 + Data.Length); i++)
4330 {
4331 returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock();
4332 }
4333 int j = 0;
4334
4335 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4336 returnblock[j].Parameter = Utils.StringToBytes(code.ToString()); j++;
4337 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4338 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4339 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4340 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4341
4342 j = 2; // Agents
4343 if ((code & 2) != 0)
4344 j = 3; // Groups
4345 if ((code & 8) != 0)
4346 j = 5; // Managers
4347
4348 returnblock[j].Parameter = Utils.StringToBytes(Data.Length.ToString());
4349 j = 6;
4350
4351 for (int i = 0; i < Data.Length; i++)
4352 {
4353 returnblock[j].Parameter = Data[i].GetBytes(); j++;
4354 }
4355 packet.ParamList = returnblock;
4356 packet.Header.Reliable = true;
4357 OutPacket(packet, ThrottleOutPacketType.Task);
4358 }
4359
4360 public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID)
4361 {
4362 List<UUID> BannedUsers = new List<UUID>();
4363
4364 for (int i = 0; i < bl.Length; i++)
4365 {
4366 if (bl[i] == null)
4367 continue;
4368 if (bl[i].BannedUserID == UUID.Zero)
4369 continue;
4370 BannedUsers.Add(bl[i].BannedUserID);
4371 }
4372
4373 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
4374 packet.AgentData.TransactionID = UUID.Random();
4375 packet.AgentData.AgentID = AgentId;
4376 packet.AgentData.SessionID = SessionId;
4377 packet.MethodData.Invoice = invoice;
4378 packet.MethodData.Method = Utils.StringToBytes("setaccess");
4379
4380 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count];
4381
4382 for (int i = 0; i < (6 + BannedUsers.Count); i++)
4383 {
4384 returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock();
4385 }
4386 int j = 0;
4387
4388 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4389 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
4390 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4391 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4392 returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++;
4393 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4394
4395 foreach (UUID banned in BannedUsers)
4396 {
4397 returnblock[j].Parameter = banned.GetBytes(); j++;
4398 }
4399 packet.ParamList = returnblock;
4400 packet.Header.Reliable = false;
4401 OutPacket(packet, ThrottleOutPacketType.Task);
4402 }
4403
4404 public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args)
4405 {
4406 RegionInfoPacket rinfopack = new RegionInfoPacket();
4407 RegionInfoPacket.RegionInfoBlock rinfoblk = new RegionInfoPacket.RegionInfoBlock();
4408 rinfopack.AgentData.AgentID = AgentId;
4409 rinfopack.AgentData.SessionID = SessionId;
4410 rinfoblk.BillableFactor = args.billableFactor;
4411 rinfoblk.EstateID = args.estateID;
4412 rinfoblk.MaxAgents = args.maxAgents;
4413 rinfoblk.ObjectBonusFactor = args.objectBonusFactor;
4414 rinfoblk.ParentEstateID = args.parentEstateID;
4415 rinfoblk.PricePerMeter = args.pricePerMeter;
4416 rinfoblk.RedirectGridX = args.redirectGridX;
4417 rinfoblk.RedirectGridY = args.redirectGridY;
4418 rinfoblk.RegionFlags = args.regionFlags;
4419 rinfoblk.SimAccess = args.simAccess;
4420 rinfoblk.SunHour = args.sunHour;
4421 rinfoblk.TerrainLowerLimit = args.terrainLowerLimit;
4422 rinfoblk.TerrainRaiseLimit = args.terrainRaiseLimit;
4423 rinfoblk.UseEstateSun = args.useEstateSun;
4424 rinfoblk.WaterHeight = args.waterHeight;
4425 rinfoblk.SimName = Utils.StringToBytes(args.simName);
4426
4427 rinfopack.RegionInfo2 = new RegionInfoPacket.RegionInfo2Block();
4428 rinfopack.RegionInfo2.HardMaxAgents = uint.MaxValue;
4429 rinfopack.RegionInfo2.HardMaxObjects = uint.MaxValue;
4430 rinfopack.RegionInfo2.MaxAgents32 = uint.MaxValue;
4431 rinfopack.RegionInfo2.ProductName = Util.StringToBytes256(args.regionType);
4432 rinfopack.RegionInfo2.ProductSKU = Utils.EmptyBytes;
4433
4434 rinfopack.HasVariableBlocks = true;
4435 rinfopack.RegionInfo = rinfoblk;
4436 rinfopack.AgentData = new RegionInfoPacket.AgentDataBlock();
4437 rinfopack.AgentData.AgentID = AgentId;
4438 rinfopack.AgentData.SessionID = SessionId;
4439
4440
4441 OutPacket(rinfopack, ThrottleOutPacketType.Task);
4442 }
4443
4444 public void SendEstateCovenantInformation(UUID covenant)
4445 {
4446// m_log.DebugFormat("[LLCLIENTVIEW]: Sending estate covenant asset id of {0} to {1}", covenant, Name);
4447
4448 EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket();
4449 EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock();
4450 edata.CovenantID = covenant;
4451 edata.CovenantTimestamp = 0;
4452 edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
4453 edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName);
4454 einfopack.Data = edata;
4455 OutPacket(einfopack, ThrottleOutPacketType.Task);
4456 }
4457
4458 public void SendDetailedEstateData(
4459 UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition,
4460 UUID covenant, string abuseEmail, UUID estateOwner)
4461 {
4462// m_log.DebugFormat(
4463// "[LLCLIENTVIEW]: Sending detailed estate data to {0} with covenant asset id {1}", Name, covenant);
4464
4465 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
4466 packet.MethodData.Invoice = invoice;
4467 packet.AgentData.TransactionID = UUID.Random();
4468 packet.MethodData.Method = Utils.StringToBytes("estateupdateinfo");
4469 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[10];
4470
4471 for (int i = 0; i < 10; i++)
4472 {
4473 returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock();
4474 }
4475
4476 //Sending Estate Settings
4477 returnblock[0].Parameter = Utils.StringToBytes(estateName);
4478 returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString());
4479 returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString());
4480
4481 returnblock[3].Parameter = Utils.StringToBytes(estateFlags.ToString());
4482 returnblock[4].Parameter = Utils.StringToBytes(sunPosition.ToString());
4483 returnblock[5].Parameter = Utils.StringToBytes(parentEstate.ToString());
4484 returnblock[6].Parameter = Utils.StringToBytes(covenant.ToString());
4485 returnblock[7].Parameter = Utils.StringToBytes("1160895077"); // what is this?
4486 returnblock[8].Parameter = Utils.StringToBytes("1"); // what is this?
4487 returnblock[9].Parameter = Utils.StringToBytes(abuseEmail);
4488
4489 packet.ParamList = returnblock;
4490 packet.Header.Reliable = false;
4491 //m_log.Debug("[ESTATE]: SIM--->" + packet.ToString());
4492 OutPacket(packet, ThrottleOutPacketType.Task);
4493 }
4494
4495 #endregion
4496
4497 #region Land Data Sending Methods
4498
4499 public void SendLandParcelOverlay(byte[] data, int sequence_id)
4500 {
4501 ParcelOverlayPacket packet = (ParcelOverlayPacket)PacketPool.Instance.GetPacket(PacketType.ParcelOverlay);
4502 packet.ParcelData.Data = data;
4503 packet.ParcelData.SequenceID = sequence_id;
4504 packet.Header.Zerocoded = true;
4505 OutPacket(packet, ThrottleOutPacketType.Task);
4506 }
4507
4508 public void SendLandProperties(
4509 int sequence_id, bool snap_selection, int request_result, ILandObject lo,
4510 float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags)
4511 {
4512// m_log.DebugFormat("[LLCLIENTVIEW]: Sending land properties for {0} to {1}", lo.LandData.GlobalID, Name);
4513
4514 LandData landData = lo.LandData;
4515
4516 ParcelPropertiesMessage updateMessage = new ParcelPropertiesMessage();
4517
4518 updateMessage.AABBMax = landData.AABBMax;
4519 updateMessage.AABBMin = landData.AABBMin;
4520 updateMessage.Area = landData.Area;
4521 updateMessage.AuctionID = landData.AuctionID;
4522 updateMessage.AuthBuyerID = landData.AuthBuyerID;
4523 updateMessage.Bitmap = landData.Bitmap;
4524 updateMessage.Desc = landData.Description;
4525 updateMessage.Category = landData.Category;
4526 updateMessage.ClaimDate = Util.ToDateTime(landData.ClaimDate);
4527 updateMessage.ClaimPrice = landData.ClaimPrice;
4528 updateMessage.GroupID = landData.GroupID;
4529 updateMessage.IsGroupOwned = landData.IsGroupOwned;
4530 updateMessage.LandingType = (LandingType) landData.LandingType;
4531 updateMessage.LocalID = landData.LocalID;
4532
4533 if (landData.Area > 0)
4534 {
4535 updateMessage.MaxPrims = parcelObjectCapacity;
4536 }
4537 else
4538 {
4539 updateMessage.MaxPrims = 0;
4540 }
4541
4542 updateMessage.MediaAutoScale = Convert.ToBoolean(landData.MediaAutoScale);
4543 updateMessage.MediaID = landData.MediaID;
4544 updateMessage.MediaURL = landData.MediaURL;
4545 updateMessage.MusicURL = landData.MusicURL;
4546 updateMessage.Name = landData.Name;
4547 updateMessage.OtherCleanTime = landData.OtherCleanTime;
4548 updateMessage.OtherCount = 0; //TODO: Unimplemented
4549 updateMessage.OwnerID = landData.OwnerID;
4550 updateMessage.ParcelFlags = (ParcelFlags) landData.Flags;
4551 updateMessage.ParcelPrimBonus = simObjectBonusFactor;
4552 updateMessage.PassHours = landData.PassHours;
4553 updateMessage.PassPrice = landData.PassPrice;
4554 updateMessage.PublicCount = 0; //TODO: Unimplemented
4555
4556 updateMessage.RegionPushOverride = (regionFlags & (uint)RegionFlags.RestrictPushObject) > 0;
4557 updateMessage.RegionDenyAnonymous = (regionFlags & (uint)RegionFlags.DenyAnonymous) > 0;
4558
4559 //updateMessage.RegionDenyIdentified = (regionFlags & (uint)RegionFlags.DenyIdentified) > 0;
4560 //updateMessage.RegionDenyTransacted = (regionFlags & (uint)RegionFlags.DenyTransacted) > 0;
4561
4562 updateMessage.RentPrice = 0;
4563 updateMessage.RequestResult = (ParcelResult) request_result;
4564 updateMessage.SalePrice = landData.SalePrice;
4565 updateMessage.SelfCount = 0; //TODO: Unimplemented
4566 updateMessage.SequenceID = sequence_id;
4567
4568 if (landData.SimwideArea > 0)
4569 {
4570 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus);
4571 updateMessage.SimWideMaxPrims = simulatorCapacity;
4572 }
4573 else
4574 {
4575 updateMessage.SimWideMaxPrims = 0;
4576 }
4577
4578 updateMessage.SnapSelection = snap_selection;
4579 updateMessage.SnapshotID = landData.SnapshotID;
4580 updateMessage.Status = (ParcelStatus) landData.Status;
4581 updateMessage.UserLocation = landData.UserLocation;
4582 updateMessage.UserLookAt = landData.UserLookAt;
4583
4584 updateMessage.MediaType = landData.MediaType;
4585 updateMessage.MediaDesc = landData.MediaDescription;
4586 updateMessage.MediaWidth = landData.MediaWidth;
4587 updateMessage.MediaHeight = landData.MediaHeight;
4588 updateMessage.MediaLoop = landData.MediaLoop;
4589 updateMessage.ObscureMusic = landData.ObscureMusic;
4590 updateMessage.ObscureMedia = landData.ObscureMedia;
4591
4592 IPrimCounts pc = lo.PrimCounts;
4593 updateMessage.OwnerPrims = pc.Owner;
4594 updateMessage.GroupPrims = pc.Group;
4595 updateMessage.OtherPrims = pc.Others;
4596 updateMessage.SelectedPrims = pc.Selected;
4597 updateMessage.TotalPrims = pc.Total;
4598 updateMessage.SimWideTotalPrims = pc.Simulator;
4599
4600 try
4601 {
4602 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
4603 if (eq != null)
4604 {
4605 eq.ParcelProperties(updateMessage, this.AgentId);
4606 }
4607 else
4608 {
4609 m_log.Warn("[LLCLIENTVIEW]: No EQ Interface when sending parcel data.");
4610 }
4611 }
4612 catch (Exception ex)
4613 {
4614 m_log.Error("[LLCLIENTVIEW]: Unable to send parcel data via eventqueue - exception: " + ex.ToString());
4615 }
4616 }
4617
4618 public void SendLandAccessListData(List<UUID> avatars, uint accessFlag, int localLandID)
4619 {
4620 ParcelAccessListReplyPacket replyPacket = (ParcelAccessListReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply);
4621 replyPacket.Data.AgentID = AgentId;
4622 replyPacket.Data.Flags = accessFlag;
4623 replyPacket.Data.LocalID = localLandID;
4624 replyPacket.Data.SequenceID = 0;
4625
4626 List<ParcelAccessListReplyPacket.ListBlock> list = new List<ParcelAccessListReplyPacket.ListBlock>();
4627 foreach (UUID avatar in avatars)
4628 {
4629 ParcelAccessListReplyPacket.ListBlock block = new ParcelAccessListReplyPacket.ListBlock();
4630 block.Flags = accessFlag;
4631 block.ID = avatar;
4632 block.Time = 0;
4633 list.Add(block);
4634 }
4635
4636 replyPacket.List = list.ToArray();
4637 replyPacket.Header.Zerocoded = true;
4638 OutPacket(replyPacket, ThrottleOutPacketType.Task);
4639 }
4640
4641 public void SendForceClientSelectObjects(List<uint> ObjectIDs)
4642 {
4643 m_log.WarnFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count);
4644
4645 bool firstCall = true;
4646 const int MAX_OBJECTS_PER_PACKET = 251;
4647 ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect);
4648 ForceObjectSelectPacket.DataBlock[] data;
4649 while (ObjectIDs.Count > 0)
4650 {
4651 if (firstCall)
4652 {
4653 pack._Header.ResetList = true;
4654 firstCall = false;
4655 }
4656 else
4657 {
4658 pack._Header.ResetList = false;
4659 }
4660
4661 if (ObjectIDs.Count > MAX_OBJECTS_PER_PACKET)
4662 {
4663 data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET];
4664 }
4665 else
4666 {
4667 data = new ForceObjectSelectPacket.DataBlock[ObjectIDs.Count];
4668 }
4669
4670 int i;
4671 for (i = 0; i < MAX_OBJECTS_PER_PACKET && ObjectIDs.Count > 0; i++)
4672 {
4673 data[i] = new ForceObjectSelectPacket.DataBlock();
4674 data[i].LocalID = Convert.ToUInt32(ObjectIDs[0]);
4675 ObjectIDs.RemoveAt(0);
4676 }
4677 pack.Data = data;
4678 pack.Header.Zerocoded = true;
4679 OutPacket(pack, ThrottleOutPacketType.Task);
4680 }
4681 }
4682
4683 public void SendCameraConstraint(Vector4 ConstraintPlane)
4684 {
4685 CameraConstraintPacket cpack = (CameraConstraintPacket)PacketPool.Instance.GetPacket(PacketType.CameraConstraint);
4686 cpack.CameraCollidePlane = new CameraConstraintPacket.CameraCollidePlaneBlock();
4687 cpack.CameraCollidePlane.Plane = ConstraintPlane;
4688 //m_log.DebugFormat("[CLIENTVIEW]: Constraint {0}", ConstraintPlane);
4689 OutPacket(cpack, ThrottleOutPacketType.Task);
4690 }
4691
4692 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount)
4693 {
4694 int notifyCount = ownersAndCount.Count;
4695 ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply);
4696
4697 if (notifyCount > 0)
4698 {
4699// if (notifyCount > 32)
4700// {
4701// m_log.InfoFormat(
4702// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4703// + " - a developer might want to investigate whether this is a hard limit", 32);
4704//
4705// notifyCount = 32;
4706// }
4707
4708 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4709 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
4710
4711 int num = 0;
4712 foreach (UUID owner in ownersAndCount.Keys)
4713 {
4714 dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock();
4715 dataBlock[num].Count = ownersAndCount[owner];
4716
4717 if (land.GroupID == owner || groups.Contains(owner))
4718 dataBlock[num].IsGroupOwned = true;
4719
4720 dataBlock[num].OnlineStatus = true; //TODO: fix me later
4721 dataBlock[num].OwnerID = owner;
4722
4723 num++;
4724
4725 if (num >= notifyCount)
4726 {
4727 break;
4728 }
4729 }
4730
4731 pack.Data = dataBlock;
4732 }
4733 else
4734 {
4735 pack.Data = new ParcelObjectOwnersReplyPacket.DataBlock[0];
4736 }
4737 pack.Header.Zerocoded = true;
4738 this.OutPacket(pack, ThrottleOutPacketType.Task);
4739 }
4740
4741 #endregion
4742
4743 #region Helper Methods
4744
4745 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(ISceneEntity entity, bool sendTexture)
4746 {
4747 #region ScenePresence/SOP Handling
4748
4749 bool avatar = (entity is ScenePresence);
4750 uint localID = entity.LocalId;
4751 uint attachPoint;
4752 Vector4 collisionPlane;
4753 Vector3 position, velocity, acceleration, angularVelocity;
4754 Quaternion rotation;
4755 byte[] textureEntry;
4756
4757 if (entity is ScenePresence)
4758 {
4759 ScenePresence presence = (ScenePresence)entity;
4760
4761 attachPoint = 0;
4762 collisionPlane = presence.CollisionPlane;
4763 position = presence.OffsetPosition;
4764 velocity = presence.Velocity;
4765 acceleration = Vector3.Zero;
4766 angularVelocity = Vector3.Zero;
4767 rotation = presence.Rotation;
4768
4769 if (sendTexture)
4770 textureEntry = presence.Appearance.Texture.GetBytes();
4771 else
4772 textureEntry = null;
4773 }
4774 else
4775 {
4776 SceneObjectPart part = (SceneObjectPart)entity;
4777
4778 attachPoint = part.AttachmentPoint;
4779 collisionPlane = Vector4.Zero;
4780 position = part.RelativePosition;
4781 velocity = part.Velocity;
4782 acceleration = part.Acceleration;
4783 angularVelocity = part.AngularVelocity;
4784 rotation = part.RotationOffset;
4785
4786 if (sendTexture)
4787 textureEntry = part.Shape.TextureEntry;
4788 else
4789 textureEntry = null;
4790 }
4791
4792 #endregion ScenePresence/SOP Handling
4793
4794 int pos = 0;
4795 byte[] data = new byte[(avatar ? 60 : 44)];
4796
4797 // LocalID
4798 Utils.UIntToBytes(localID, data, pos);
4799 pos += 4;
4800
4801 // Avatar/CollisionPlane
4802 data[pos++] = (byte)((attachPoint % 16) * 16 + (attachPoint / 16)); ;
4803 if (avatar)
4804 {
4805 data[pos++] = 1;
4806
4807 if (collisionPlane == Vector4.Zero)
4808 collisionPlane = Vector4.UnitW;
4809 //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane);
4810 collisionPlane.ToBytes(data, pos);
4811 pos += 16;
4812 }
4813 else
4814 {
4815 ++pos;
4816 }
4817
4818 // Position
4819 position.ToBytes(data, pos);
4820 pos += 12;
4821
4822 // Velocity
4823 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.X, -128.0f, 128.0f), data, pos); pos += 2;
4824 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Y, -128.0f, 128.0f), data, pos); pos += 2;
4825 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Z, -128.0f, 128.0f), data, pos); pos += 2;
4826
4827 // Acceleration
4828 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.X, -64.0f, 64.0f), data, pos); pos += 2;
4829 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Y, -64.0f, 64.0f), data, pos); pos += 2;
4830 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Z, -64.0f, 64.0f), data, pos); pos += 2;
4831
4832 // Rotation
4833 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.X, -1.0f, 1.0f), data, pos); pos += 2;
4834 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.Y, -1.0f, 1.0f), data, pos); pos += 2;
4835 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.Z, -1.0f, 1.0f), data, pos); pos += 2;
4836 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.W, -1.0f, 1.0f), data, pos); pos += 2;
4837
4838 // Angular Velocity
4839 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.X, -64.0f, 64.0f), data, pos); pos += 2;
4840 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
4841 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
4842
4843 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
4844 block.Data = data;
4845
4846 if (textureEntry != null && textureEntry.Length > 0)
4847 {
4848 byte[] teBytesFinal = new byte[textureEntry.Length + 4];
4849
4850 // Texture Length
4851 Utils.IntToBytes(textureEntry.Length, textureEntry, 0);
4852 // Texture
4853 Buffer.BlockCopy(textureEntry, 0, teBytesFinal, 4, textureEntry.Length);
4854
4855 block.TextureEntry = teBytesFinal;
4856 }
4857 else
4858 {
4859 block.TextureEntry = Utils.EmptyBytes;
4860 }
4861
4862 return block;
4863 }
4864
4865 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
4866 {
4867 byte[] objectData = new byte[76];
4868
4869 data.CollisionPlane.ToBytes(objectData, 0);
4870 data.OffsetPosition.ToBytes(objectData, 16);
4871 //data.Velocity.ToBytes(objectData, 28);
4872 //data.Acceleration.ToBytes(objectData, 40);
4873 data.Rotation.ToBytes(objectData, 52);
4874 //data.AngularVelocity.ToBytes(objectData, 64);
4875
4876 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
4877
4878 update.Data = Utils.EmptyBytes;
4879 update.ExtraParams = new byte[1];
4880 update.FullID = data.UUID;
4881 update.ID = data.LocalId;
4882 update.Material = (byte)Material.Flesh;
4883 update.MediaURL = Utils.EmptyBytes;
4884 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
4885 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
4886 update.ObjectData = objectData;
4887 update.ParentID = data.ParentID;
4888 update.PathCurve = 16;
4889 update.PathScaleX = 100;
4890 update.PathScaleY = 100;
4891 update.PCode = (byte)PCode.Avatar;
4892 update.ProfileCurve = 1;
4893 update.PSBlock = Utils.EmptyBytes;
4894 update.Scale = new Vector3(0.45f, 0.6f, 1.9f);
4895 update.Text = Utils.EmptyBytes;
4896 update.TextColor = new byte[4];
4897 update.TextureAnim = Utils.EmptyBytes;
4898 update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
4899 update.UpdateFlags = (uint)(
4900 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
4901 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
4902 PrimFlags.ObjectOwnerModify);
4903
4904 return update;
4905 }
4906
4907 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID)
4908 {
4909 byte[] objectData = new byte[60];
4910 data.RelativePosition.ToBytes(objectData, 0);
4911 data.Velocity.ToBytes(objectData, 12);
4912 data.Acceleration.ToBytes(objectData, 24);
4913 try
4914 {
4915 data.RotationOffset.ToBytes(objectData, 36);
4916 }
4917 catch (Exception e)
4918 {
4919 m_log.Warn("[LLClientView]: exception converting quaternion to bytes, using Quaternion.Identity. Exception: " + e.ToString());
4920 OpenMetaverse.Quaternion.Identity.ToBytes(objectData, 36);
4921 }
4922 data.AngularVelocity.ToBytes(objectData, 48);
4923
4924 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
4925 update.ClickAction = (byte)data.ClickAction;
4926 update.CRC = 0;
4927 update.ExtraParams = data.Shape.ExtraParams ?? Utils.EmptyBytes;
4928 update.FullID = data.UUID;
4929 update.ID = data.LocalId;
4930 //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated
4931 //update.JointPivot = Vector3.Zero;
4932 //update.JointType = 0;
4933 update.Material = data.Material;
4934 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
4935 if (data.IsAttachment)
4936 {
4937 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID);
4938 update.State = (byte)((data.AttachmentPoint % 16) * 16 + (data.AttachmentPoint / 16));
4939 }
4940 else
4941 {
4942 update.NameValue = Utils.EmptyBytes;
4943 update.State = data.Shape.State;
4944 }
4945
4946 update.ObjectData = objectData;
4947 update.ParentID = data.ParentID;
4948 update.PathBegin = data.Shape.PathBegin;
4949 update.PathCurve = data.Shape.PathCurve;
4950 update.PathEnd = data.Shape.PathEnd;
4951 update.PathRadiusOffset = data.Shape.PathRadiusOffset;
4952 update.PathRevolutions = data.Shape.PathRevolutions;
4953 update.PathScaleX = data.Shape.PathScaleX;
4954 update.PathScaleY = data.Shape.PathScaleY;
4955 update.PathShearX = data.Shape.PathShearX;
4956 update.PathShearY = data.Shape.PathShearY;
4957 update.PathSkew = data.Shape.PathSkew;
4958 update.PathTaperX = data.Shape.PathTaperX;
4959 update.PathTaperY = data.Shape.PathTaperY;
4960 update.PathTwist = data.Shape.PathTwist;
4961 update.PathTwistBegin = data.Shape.PathTwistBegin;
4962 update.PCode = data.Shape.PCode;
4963 update.ProfileBegin = data.Shape.ProfileBegin;
4964 update.ProfileCurve = data.Shape.ProfileCurve;
4965 update.ProfileEnd = data.Shape.ProfileEnd;
4966 update.ProfileHollow = data.Shape.ProfileHollow;
4967 update.PSBlock = data.ParticleSystem ?? Utils.EmptyBytes;
4968 update.TextColor = data.GetTextColor().GetBytes(false);
4969 update.TextureAnim = data.TextureAnimation ?? Utils.EmptyBytes;
4970 update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes;
4971 update.Scale = data.Shape.Scale;
4972 update.Text = Util.StringToBytes256(data.Text);
4973 update.MediaURL = Util.StringToBytes256(data.MediaUrl);
4974
4975 #region PrimFlags
4976
4977 PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(recipientID, data.UUID);
4978
4979 // Don't send the CreateSelected flag to everyone
4980 flags &= ~PrimFlags.CreateSelected;
4981
4982 if (recipientID == data.OwnerID)
4983 {
4984 if (data.CreateSelected)
4985 {
4986 // Only send this flag once, then unset it
4987 flags |= PrimFlags.CreateSelected;
4988 data.CreateSelected = false;
4989 }
4990 }
4991
4992// m_log.DebugFormat(
4993// "[LLCLIENTVIEW]: Constructing client update for part {0} {1} with flags {2}, localId {3}",
4994// data.Name, update.FullID, flags, update.ID);
4995
4996 update.UpdateFlags = (uint)flags;
4997
4998 #endregion PrimFlags
4999
5000 if (data.Sound != UUID.Zero)
5001 {
5002 update.Sound = data.Sound;
5003 update.OwnerID = data.OwnerID;
5004 update.Gain = (float)data.SoundGain;
5005 update.Radius = (float)data.SoundRadius;
5006 update.Flags = data.SoundFlags;
5007 }
5008
5009 switch ((PCode)data.Shape.PCode)
5010 {
5011 case PCode.Grass:
5012 case PCode.Tree:
5013 case PCode.NewTree:
5014 update.Data = new byte[] { data.Shape.State };
5015 break;
5016 default:
5017 update.Data = Utils.EmptyBytes;
5018 break;
5019 }
5020
5021 return update;
5022 }
5023
5024 protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags)
5025 {
5026 // TODO: Implement this
5027 return null;
5028 }
5029
5030 public void SendNameReply(UUID profileId, string firstname, string lastname)
5031 {
5032 UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply);
5033 // TODO: don't create new blocks if recycling an old packet
5034 packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1];
5035 packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock();
5036 packet.UUIDNameBlock[0].ID = profileId;
5037 packet.UUIDNameBlock[0].FirstName = Util.StringToBytes256(firstname);
5038 packet.UUIDNameBlock[0].LastName = Util.StringToBytes256(lastname);
5039
5040 OutPacket(packet, ThrottleOutPacketType.Task);
5041 }
5042
5043 public ulong GetGroupPowers(UUID groupID)
5044 {
5045 if (groupID == m_activeGroupID)
5046 return m_activeGroupPowers;
5047
5048 if (m_groupPowers.ContainsKey(groupID))
5049 return m_groupPowers[groupID];
5050
5051 return 0;
5052 }
5053
5054 /// <summary>
5055 /// This is a utility method used by single states to not duplicate kicks and blue card of death messages.
5056 /// </summary>
5057 public bool ChildAgentStatus()
5058 {
5059 return m_scene.PresenceChildStatus(AgentId);
5060 }
5061
5062 #endregion
5063
5064 /// <summary>
5065 /// This is a different way of processing packets then ProcessInPacket
5066 /// </summary>
5067 protected virtual void RegisterLocalPacketHandlers()
5068 {
5069 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout);
5070 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
5071 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
5072 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
5073 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
5074 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false);
5075 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false);
5076 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false);
5077 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false);
5078 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage);
5079 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest);
5080 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
5081 AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate);
5082 AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply);
5083 AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage, false);
5084 AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship);
5085 AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship);
5086 AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFrendship);
5087 AddLocalPacketHandler(PacketType.RezObject, HandlerRezObject);
5088 AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject);
5089 AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand);
5090 AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply);
5091 AddLocalPacketHandler(PacketType.AgentWearablesRequest, HandlerAgentWearablesRequest);
5092 AddLocalPacketHandler(PacketType.AgentSetAppearance, HandlerAgentSetAppearance);
5093 AddLocalPacketHandler(PacketType.AgentIsNowWearing, HandlerAgentIsNowWearing);
5094 AddLocalPacketHandler(PacketType.RezSingleAttachmentFromInv, HandlerRezSingleAttachmentFromInv);
5095 AddLocalPacketHandler(PacketType.RezMultipleAttachmentsFromInv, HandleRezMultipleAttachmentsFromInv);
5096 AddLocalPacketHandler(PacketType.DetachAttachmentIntoInv, HandleDetachAttachmentIntoInv);
5097 AddLocalPacketHandler(PacketType.ObjectAttach, HandleObjectAttach);
5098 AddLocalPacketHandler(PacketType.ObjectDetach, HandleObjectDetach);
5099 AddLocalPacketHandler(PacketType.ObjectDrop, HandleObjectDrop);
5100 AddLocalPacketHandler(PacketType.SetAlwaysRun, HandleSetAlwaysRun, false);
5101 AddLocalPacketHandler(PacketType.CompleteAgentMovement, HandleCompleteAgentMovement);
5102 AddLocalPacketHandler(PacketType.AgentAnimation, HandleAgentAnimation, false);
5103 AddLocalPacketHandler(PacketType.AgentRequestSit, HandleAgentRequestSit);
5104 AddLocalPacketHandler(PacketType.AgentSit, HandleAgentSit);
5105 AddLocalPacketHandler(PacketType.SoundTrigger, HandleSoundTrigger);
5106 AddLocalPacketHandler(PacketType.AvatarPickerRequest, HandleAvatarPickerRequest);
5107 AddLocalPacketHandler(PacketType.AgentDataUpdateRequest, HandleAgentDataUpdateRequest);
5108 AddLocalPacketHandler(PacketType.UserInfoRequest, HandleUserInfoRequest);
5109 AddLocalPacketHandler(PacketType.UpdateUserInfo, HandleUpdateUserInfo);
5110 AddLocalPacketHandler(PacketType.SetStartLocationRequest, HandleSetStartLocationRequest);
5111 AddLocalPacketHandler(PacketType.AgentThrottle, HandleAgentThrottle, false);
5112 AddLocalPacketHandler(PacketType.AgentPause, HandleAgentPause, false);
5113 AddLocalPacketHandler(PacketType.AgentResume, HandleAgentResume, false);
5114 AddLocalPacketHandler(PacketType.ForceScriptControlRelease, HandleForceScriptControlRelease);
5115 AddLocalPacketHandler(PacketType.ObjectLink, HandleObjectLink);
5116 AddLocalPacketHandler(PacketType.ObjectDelink, HandleObjectDelink);
5117 AddLocalPacketHandler(PacketType.ObjectAdd, HandleObjectAdd);
5118 AddLocalPacketHandler(PacketType.ObjectShape, HandleObjectShape);
5119 AddLocalPacketHandler(PacketType.ObjectExtraParams, HandleObjectExtraParams);
5120 AddLocalPacketHandler(PacketType.ObjectDuplicate, HandleObjectDuplicate);
5121 AddLocalPacketHandler(PacketType.RequestMultipleObjects, HandleRequestMultipleObjects);
5122 AddLocalPacketHandler(PacketType.ObjectSelect, HandleObjectSelect);
5123 AddLocalPacketHandler(PacketType.ObjectDeselect, HandleObjectDeselect);
5124 AddLocalPacketHandler(PacketType.ObjectPosition, HandleObjectPosition);
5125 AddLocalPacketHandler(PacketType.ObjectScale, HandleObjectScale);
5126 AddLocalPacketHandler(PacketType.ObjectRotation, HandleObjectRotation);
5127 AddLocalPacketHandler(PacketType.ObjectFlagUpdate, HandleObjectFlagUpdate);
5128
5129 // Handle ObjectImage (TextureEntry) updates synchronously, since when updating multiple prim faces at once,
5130 // some clients will send out a separate ObjectImage packet for each face
5131 AddLocalPacketHandler(PacketType.ObjectImage, HandleObjectImage, false);
5132
5133 AddLocalPacketHandler(PacketType.ObjectGrab, HandleObjectGrab, false);
5134 AddLocalPacketHandler(PacketType.ObjectGrabUpdate, HandleObjectGrabUpdate, false);
5135 AddLocalPacketHandler(PacketType.ObjectDeGrab, HandleObjectDeGrab);
5136 AddLocalPacketHandler(PacketType.ObjectSpinStart, HandleObjectSpinStart, false);
5137 AddLocalPacketHandler(PacketType.ObjectSpinUpdate, HandleObjectSpinUpdate, false);
5138 AddLocalPacketHandler(PacketType.ObjectSpinStop, HandleObjectSpinStop, false);
5139 AddLocalPacketHandler(PacketType.ObjectDescription, HandleObjectDescription, false);
5140 AddLocalPacketHandler(PacketType.ObjectName, HandleObjectName, false);
5141 AddLocalPacketHandler(PacketType.ObjectPermissions, HandleObjectPermissions, false);
5142 AddLocalPacketHandler(PacketType.Undo, HandleUndo, false);
5143 AddLocalPacketHandler(PacketType.UndoLand, HandleLandUndo, false);
5144 AddLocalPacketHandler(PacketType.Redo, HandleRedo, false);
5145 AddLocalPacketHandler(PacketType.ObjectDuplicateOnRay, HandleObjectDuplicateOnRay);
5146 AddLocalPacketHandler(PacketType.RequestObjectPropertiesFamily, HandleRequestObjectPropertiesFamily, false);
5147 AddLocalPacketHandler(PacketType.ObjectIncludeInSearch, HandleObjectIncludeInSearch);
5148 AddLocalPacketHandler(PacketType.ScriptAnswerYes, HandleScriptAnswerYes, false);
5149 AddLocalPacketHandler(PacketType.ObjectClickAction, HandleObjectClickAction, false);
5150 AddLocalPacketHandler(PacketType.ObjectMaterial, HandleObjectMaterial, false);
5151 AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage);
5152 AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest);
5153 AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest);
5154 AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer);
5155 AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket);
5156 AddLocalPacketHandler(PacketType.ConfirmXferPacket, HandleConfirmXferPacket);
5157 AddLocalPacketHandler(PacketType.AbortXfer, HandleAbortXfer);
5158 AddLocalPacketHandler(PacketType.CreateInventoryFolder, HandleCreateInventoryFolder);
5159 AddLocalPacketHandler(PacketType.UpdateInventoryFolder, HandleUpdateInventoryFolder);
5160 AddLocalPacketHandler(PacketType.MoveInventoryFolder, HandleMoveInventoryFolder);
5161 AddLocalPacketHandler(PacketType.CreateInventoryItem, HandleCreateInventoryItem);
5162 AddLocalPacketHandler(PacketType.LinkInventoryItem, HandleLinkInventoryItem);
5163 AddLocalPacketHandler(PacketType.FetchInventory, HandleFetchInventory);
5164 AddLocalPacketHandler(PacketType.FetchInventoryDescendents, HandleFetchInventoryDescendents);
5165 AddLocalPacketHandler(PacketType.PurgeInventoryDescendents, HandlePurgeInventoryDescendents);
5166 AddLocalPacketHandler(PacketType.UpdateInventoryItem, HandleUpdateInventoryItem);
5167 AddLocalPacketHandler(PacketType.CopyInventoryItem, HandleCopyInventoryItem);
5168 AddLocalPacketHandler(PacketType.MoveInventoryItem, HandleMoveInventoryItem);
5169 AddLocalPacketHandler(PacketType.RemoveInventoryItem, HandleRemoveInventoryItem);
5170 AddLocalPacketHandler(PacketType.RemoveInventoryFolder, HandleRemoveInventoryFolder);
5171 AddLocalPacketHandler(PacketType.RemoveInventoryObjects, HandleRemoveInventoryObjects);
5172 AddLocalPacketHandler(PacketType.RequestTaskInventory, HandleRequestTaskInventory);
5173 AddLocalPacketHandler(PacketType.UpdateTaskInventory, HandleUpdateTaskInventory);
5174 AddLocalPacketHandler(PacketType.RemoveTaskInventory, HandleRemoveTaskInventory);
5175 AddLocalPacketHandler(PacketType.MoveTaskInventory, HandleMoveTaskInventory);
5176 AddLocalPacketHandler(PacketType.RezScript, HandleRezScript);
5177 AddLocalPacketHandler(PacketType.MapLayerRequest, HandleMapLayerRequest, false);
5178 AddLocalPacketHandler(PacketType.MapBlockRequest, HandleMapBlockRequest, false);
5179 AddLocalPacketHandler(PacketType.MapNameRequest, HandleMapNameRequest, false);
5180 AddLocalPacketHandler(PacketType.TeleportLandmarkRequest, HandleTeleportLandmarkRequest);
5181 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest);
5182 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false);
5183 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest);
5184 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest);
5185 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false);
5186 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false);
5187 AddLocalPacketHandler(PacketType.ParcelPropertiesRequest, HandleParcelPropertiesRequest, false);
5188 AddLocalPacketHandler(PacketType.ParcelDivide, HandleParcelDivide);
5189 AddLocalPacketHandler(PacketType.ParcelJoin, HandleParcelJoin);
5190 AddLocalPacketHandler(PacketType.ParcelPropertiesUpdate, HandleParcelPropertiesUpdate);
5191 AddLocalPacketHandler(PacketType.ParcelSelectObjects, HandleParcelSelectObjects);
5192 AddLocalPacketHandler(PacketType.ParcelObjectOwnersRequest, HandleParcelObjectOwnersRequest);
5193 AddLocalPacketHandler(PacketType.ParcelGodForceOwner, HandleParcelGodForceOwner);
5194 AddLocalPacketHandler(PacketType.ParcelRelease, HandleParcelRelease);
5195 AddLocalPacketHandler(PacketType.ParcelReclaim, HandleParcelReclaim);
5196 AddLocalPacketHandler(PacketType.ParcelReturnObjects, HandleParcelReturnObjects);
5197 AddLocalPacketHandler(PacketType.ParcelSetOtherCleanTime, HandleParcelSetOtherCleanTime);
5198 AddLocalPacketHandler(PacketType.LandStatRequest, HandleLandStatRequest);
5199 AddLocalPacketHandler(PacketType.ParcelDwellRequest, HandleParcelDwellRequest);
5200 AddLocalPacketHandler(PacketType.EstateOwnerMessage, HandleEstateOwnerMessage);
5201 AddLocalPacketHandler(PacketType.RequestRegionInfo, HandleRequestRegionInfo, false);
5202 AddLocalPacketHandler(PacketType.EstateCovenantRequest, HandleEstateCovenantRequest);
5203 AddLocalPacketHandler(PacketType.RequestGodlikePowers, HandleRequestGodlikePowers);
5204 AddLocalPacketHandler(PacketType.GodKickUser, HandleGodKickUser);
5205 AddLocalPacketHandler(PacketType.MoneyBalanceRequest, HandleMoneyBalanceRequest);
5206 AddLocalPacketHandler(PacketType.EconomyDataRequest, HandleEconomyDataRequest);
5207 AddLocalPacketHandler(PacketType.RequestPayPrice, HandleRequestPayPrice);
5208 AddLocalPacketHandler(PacketType.ObjectSaleInfo, HandleObjectSaleInfo);
5209 AddLocalPacketHandler(PacketType.ObjectBuy, HandleObjectBuy);
5210 AddLocalPacketHandler(PacketType.GetScriptRunning, HandleGetScriptRunning);
5211 AddLocalPacketHandler(PacketType.SetScriptRunning, HandleSetScriptRunning);
5212 AddLocalPacketHandler(PacketType.ScriptReset, HandleScriptReset);
5213 AddLocalPacketHandler(PacketType.ActivateGestures, HandleActivateGestures);
5214 AddLocalPacketHandler(PacketType.DeactivateGestures, HandleDeactivateGestures);
5215 AddLocalPacketHandler(PacketType.ObjectOwner, HandleObjectOwner);
5216 AddLocalPacketHandler(PacketType.AgentFOV, HandleAgentFOV, false);
5217 AddLocalPacketHandler(PacketType.ViewerStats, HandleViewerStats);
5218 AddLocalPacketHandler(PacketType.MapItemRequest, HandleMapItemRequest, false);
5219 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5220 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5221 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5222 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5223 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5224 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5225 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
5226 AddLocalPacketHandler(PacketType.DirFindQuery, HandleDirFindQuery);
5227 AddLocalPacketHandler(PacketType.DirLandQuery, HandleDirLandQuery);
5228 AddLocalPacketHandler(PacketType.DirPopularQuery, HandleDirPopularQuery);
5229 AddLocalPacketHandler(PacketType.DirClassifiedQuery, HandleDirClassifiedQuery);
5230 AddLocalPacketHandler(PacketType.EventInfoRequest, HandleEventInfoRequest);
5231 AddLocalPacketHandler(PacketType.OfferCallingCard, HandleOfferCallingCard);
5232 AddLocalPacketHandler(PacketType.AcceptCallingCard, HandleAcceptCallingCard);
5233 AddLocalPacketHandler(PacketType.DeclineCallingCard, HandleDeclineCallingCard);
5234 AddLocalPacketHandler(PacketType.ActivateGroup, HandleActivateGroup);
5235 AddLocalPacketHandler(PacketType.GroupTitlesRequest, HandleGroupTitlesRequest);
5236 AddLocalPacketHandler(PacketType.GroupProfileRequest, HandleGroupProfileRequest);
5237 AddLocalPacketHandler(PacketType.GroupMembersRequest, HandleGroupMembersRequest);
5238 AddLocalPacketHandler(PacketType.GroupRoleDataRequest, HandleGroupRoleDataRequest);
5239 AddLocalPacketHandler(PacketType.GroupRoleMembersRequest, HandleGroupRoleMembersRequest);
5240 AddLocalPacketHandler(PacketType.CreateGroupRequest, HandleCreateGroupRequest);
5241 AddLocalPacketHandler(PacketType.UpdateGroupInfo, HandleUpdateGroupInfo);
5242 AddLocalPacketHandler(PacketType.SetGroupAcceptNotices, HandleSetGroupAcceptNotices);
5243 AddLocalPacketHandler(PacketType.GroupTitleUpdate, HandleGroupTitleUpdate);
5244 AddLocalPacketHandler(PacketType.ParcelDeedToGroup, HandleParcelDeedToGroup);
5245 AddLocalPacketHandler(PacketType.GroupNoticesListRequest, HandleGroupNoticesListRequest);
5246 AddLocalPacketHandler(PacketType.GroupNoticeRequest, HandleGroupNoticeRequest);
5247 AddLocalPacketHandler(PacketType.GroupRoleUpdate, HandleGroupRoleUpdate);
5248 AddLocalPacketHandler(PacketType.GroupRoleChanges, HandleGroupRoleChanges);
5249 AddLocalPacketHandler(PacketType.JoinGroupRequest, HandleJoinGroupRequest);
5250 AddLocalPacketHandler(PacketType.LeaveGroupRequest, HandleLeaveGroupRequest);
5251 AddLocalPacketHandler(PacketType.EjectGroupMemberRequest, HandleEjectGroupMemberRequest);
5252 AddLocalPacketHandler(PacketType.InviteGroupRequest, HandleInviteGroupRequest);
5253 AddLocalPacketHandler(PacketType.StartLure, HandleStartLure);
5254 AddLocalPacketHandler(PacketType.TeleportLureRequest, HandleTeleportLureRequest);
5255 AddLocalPacketHandler(PacketType.ClassifiedInfoRequest, HandleClassifiedInfoRequest);
5256 AddLocalPacketHandler(PacketType.ClassifiedInfoUpdate, HandleClassifiedInfoUpdate);
5257 AddLocalPacketHandler(PacketType.ClassifiedDelete, HandleClassifiedDelete);
5258 AddLocalPacketHandler(PacketType.ClassifiedGodDelete, HandleClassifiedGodDelete);
5259 AddLocalPacketHandler(PacketType.EventGodDelete, HandleEventGodDelete);
5260 AddLocalPacketHandler(PacketType.EventNotificationAddRequest, HandleEventNotificationAddRequest);
5261 AddLocalPacketHandler(PacketType.EventNotificationRemoveRequest, HandleEventNotificationRemoveRequest);
5262 AddLocalPacketHandler(PacketType.RetrieveInstantMessages, HandleRetrieveInstantMessages);
5263 AddLocalPacketHandler(PacketType.PickDelete, HandlePickDelete);
5264 AddLocalPacketHandler(PacketType.PickGodDelete, HandlePickGodDelete);
5265 AddLocalPacketHandler(PacketType.PickInfoUpdate, HandlePickInfoUpdate);
5266 AddLocalPacketHandler(PacketType.AvatarNotesUpdate, HandleAvatarNotesUpdate);
5267 AddLocalPacketHandler(PacketType.AvatarInterestsUpdate, HandleAvatarInterestsUpdate);
5268 AddLocalPacketHandler(PacketType.GrantUserRights, HandleGrantUserRights);
5269 AddLocalPacketHandler(PacketType.PlacesQuery, HandlePlacesQuery);
5270 AddLocalPacketHandler(PacketType.UpdateMuteListEntry, HandleUpdateMuteListEntry);
5271 AddLocalPacketHandler(PacketType.RemoveMuteListEntry, HandleRemoveMuteListEntry);
5272 AddLocalPacketHandler(PacketType.UserReport, HandleUserReport);
5273 AddLocalPacketHandler(PacketType.FindAgent, HandleFindAgent);
5274 AddLocalPacketHandler(PacketType.TrackAgent, HandleTrackAgent);
5275 AddLocalPacketHandler(PacketType.GodUpdateRegionInfo, HandleGodUpdateRegionInfoUpdate);
5276 AddLocalPacketHandler(PacketType.GodlikeMessage, HandleGodlikeMessage);
5277 AddLocalPacketHandler(PacketType.StateSave, HandleSaveStatePacket);
5278 AddLocalPacketHandler(PacketType.GroupAccountDetailsRequest, HandleGroupAccountDetailsRequest);
5279 AddLocalPacketHandler(PacketType.GroupAccountSummaryRequest, HandleGroupAccountSummaryRequest);
5280 AddLocalPacketHandler(PacketType.GroupAccountTransactionsRequest, HandleGroupTransactionsDetailsRequest);
5281 AddLocalPacketHandler(PacketType.FreezeUser, HandleFreezeUser);
5282 AddLocalPacketHandler(PacketType.EjectUser, HandleEjectUser);
5283 AddLocalPacketHandler(PacketType.ParcelBuyPass, HandleParcelBuyPass);
5284 AddLocalPacketHandler(PacketType.ParcelGodMarkAsContent, HandleParcelGodMarkAsContent);
5285 AddLocalPacketHandler(PacketType.GroupActiveProposalsRequest, HandleGroupActiveProposalsRequest);
5286 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest);
5287 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes);
5288 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard);
5289 }
5290
5291 #region Packet Handlers
5292
5293 #region Scene/Avatar
5294
5295 private bool HandleAgentUpdate(IClientAPI sener, Packet Pack)
5296 {
5297 if (OnAgentUpdate != null)
5298 {
5299 bool update = false;
5300 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
5301
5302 #region Packet Session and User Check
5303 if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId)
5304 return false;
5305 #endregion
5306
5307 AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData;
5308
5309 // We can only check when we have something to check
5310 // against.
5311
5312 if (lastarg != null)
5313 {
5314 update =
5315 (
5316 (x.BodyRotation != lastarg.BodyRotation) ||
5317 (x.CameraAtAxis != lastarg.CameraAtAxis) ||
5318 (x.CameraCenter != lastarg.CameraCenter) ||
5319 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5320 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5321 (x.ControlFlags != lastarg.ControlFlags) ||
5322 (x.ControlFlags != 0) ||
5323 (x.Far != lastarg.Far) ||
5324 (x.Flags != lastarg.Flags) ||
5325 (x.State != lastarg.State) ||
5326 (x.HeadRotation != lastarg.HeadRotation) ||
5327 (x.SessionID != lastarg.SessionID) ||
5328 (x.AgentID != lastarg.AgentID)
5329 );
5330 }
5331 else
5332 update = true;
5333
5334 // These should be ordered from most-likely to
5335 // least likely to change. I've made an initial
5336 // guess at that.
5337
5338 if (update)
5339 {
5340 AgentUpdateArgs arg = new AgentUpdateArgs();
5341 arg.AgentID = x.AgentID;
5342 arg.BodyRotation = x.BodyRotation;
5343 arg.CameraAtAxis = x.CameraAtAxis;
5344 arg.CameraCenter = x.CameraCenter;
5345 arg.CameraLeftAxis = x.CameraLeftAxis;
5346 arg.CameraUpAxis = x.CameraUpAxis;
5347 arg.ControlFlags = x.ControlFlags;
5348 arg.Far = x.Far;
5349 arg.Flags = x.Flags;
5350 arg.HeadRotation = x.HeadRotation;
5351 arg.SessionID = x.SessionID;
5352 arg.State = x.State;
5353 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5354 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5355 lastarg = arg; // save this set of arguments for nexttime
5356 if (handlerPreAgentUpdate != null)
5357 OnPreAgentUpdate(this, arg);
5358 if (handlerAgentUpdate != null)
5359 OnAgentUpdate(this, arg);
5360
5361 handlerAgentUpdate = null;
5362 handlerPreAgentUpdate = null;
5363 }
5364 }
5365
5366 return true;
5367 }
5368
5369 private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack)
5370 {
5371 MoneyTransferRequestPacket money = (MoneyTransferRequestPacket)Pack;
5372 // validate the agent owns the agentID and sessionID
5373 if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId &&
5374 money.AgentData.SessionID == sender.SessionId)
5375 {
5376 MoneyTransferRequest handlerMoneyTransferRequest = OnMoneyTransferRequest;
5377 if (handlerMoneyTransferRequest != null)
5378 {
5379 handlerMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID,
5380 money.MoneyData.Amount, money.MoneyData.TransactionType,
5381 Util.FieldToString(money.MoneyData.Description));
5382 }
5383
5384 return true;
5385 }
5386
5387 return false;
5388 }
5389
5390 private bool HandleParcelGodMarkAsContent(IClientAPI client, Packet Packet)
5391 {
5392 ParcelGodMarkAsContentPacket ParcelGodMarkAsContent =
5393 (ParcelGodMarkAsContentPacket)Packet;
5394
5395 ParcelGodMark ParcelGodMarkAsContentHandler = OnParcelGodMark;
5396 if (ParcelGodMarkAsContentHandler != null)
5397 {
5398 ParcelGodMarkAsContentHandler(this,
5399 ParcelGodMarkAsContent.AgentData.AgentID,
5400 ParcelGodMarkAsContent.ParcelData.LocalID);
5401 return true;
5402 }
5403 return false;
5404 }
5405
5406 private bool HandleFreezeUser(IClientAPI client, Packet Packet)
5407 {
5408 FreezeUserPacket FreezeUser = (FreezeUserPacket)Packet;
5409
5410 FreezeUserUpdate FreezeUserHandler = OnParcelFreezeUser;
5411 if (FreezeUserHandler != null)
5412 {
5413 FreezeUserHandler(this,
5414 FreezeUser.AgentData.AgentID,
5415 FreezeUser.Data.Flags,
5416 FreezeUser.Data.TargetID);
5417 return true;
5418 }
5419 return false;
5420 }
5421
5422 private bool HandleEjectUser(IClientAPI client, Packet Packet)
5423 {
5424 EjectUserPacket EjectUser =
5425 (EjectUserPacket)Packet;
5426
5427 EjectUserUpdate EjectUserHandler = OnParcelEjectUser;
5428 if (EjectUserHandler != null)
5429 {
5430 EjectUserHandler(this,
5431 EjectUser.AgentData.AgentID,
5432 EjectUser.Data.Flags,
5433 EjectUser.Data.TargetID);
5434 return true;
5435 }
5436 return false;
5437 }
5438
5439 private bool HandleParcelBuyPass(IClientAPI client, Packet Packet)
5440 {
5441 ParcelBuyPassPacket ParcelBuyPass =
5442 (ParcelBuyPassPacket)Packet;
5443
5444 ParcelBuyPass ParcelBuyPassHandler = OnParcelBuyPass;
5445 if (ParcelBuyPassHandler != null)
5446 {
5447 ParcelBuyPassHandler(this,
5448 ParcelBuyPass.AgentData.AgentID,
5449 ParcelBuyPass.ParcelData.LocalID);
5450 return true;
5451 }
5452 return false;
5453 }
5454
5455 private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack)
5456 {
5457 ParcelBuyPacket parcel = (ParcelBuyPacket)Pack;
5458 if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId)
5459 {
5460 ParcelBuy handlerParcelBuy = OnParcelBuy;
5461 if (handlerParcelBuy != null)
5462 {
5463 handlerParcelBuy(parcel.AgentData.AgentID, parcel.Data.GroupID, parcel.Data.Final,
5464 parcel.Data.IsGroupOwned,
5465 parcel.Data.RemoveContribution, parcel.Data.LocalID, parcel.ParcelData.Area,
5466 parcel.ParcelData.Price,
5467 false);
5468 }
5469 return true;
5470 }
5471 return false;
5472 }
5473
5474 private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack)
5475 {
5476 UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack;
5477
5478
5479 for (int i = 0; i < upack.UUIDNameBlock.Length; i++)
5480 {
5481 UUIDNameRequest handlerUUIDGroupNameRequest = OnUUIDGroupNameRequest;
5482 if (handlerUUIDGroupNameRequest != null)
5483 {
5484 handlerUUIDGroupNameRequest(upack.UUIDNameBlock[i].ID, this);
5485 }
5486 }
5487
5488 return true;
5489 }
5490
5491 public bool HandleGenericMessage(IClientAPI sender, Packet pack)
5492 {
5493 GenericMessagePacket gmpack = (GenericMessagePacket)pack;
5494 if (m_genericPacketHandlers.Count == 0) return false;
5495 if (gmpack.AgentData.SessionID != SessionId) return false;
5496
5497 GenericMessage handlerGenericMessage = null;
5498
5499 string method = Util.FieldToString(gmpack.MethodData.Method).ToLower().Trim();
5500
5501 if (m_genericPacketHandlers.TryGetValue(method, out handlerGenericMessage))
5502 {
5503 List<string> msg = new List<string>();
5504 List<byte[]> msgBytes = new List<byte[]>();
5505
5506 if (handlerGenericMessage != null)
5507 {
5508 foreach (GenericMessagePacket.ParamListBlock block in gmpack.ParamList)
5509 {
5510 msg.Add(Util.FieldToString(block.Parameter));
5511 msgBytes.Add(block.Parameter);
5512 }
5513 try
5514 {
5515 if (OnBinaryGenericMessage != null)
5516 {
5517 OnBinaryGenericMessage(this, method, msgBytes.ToArray());
5518 }
5519 handlerGenericMessage(sender, method, msg);
5520 return true;
5521 }
5522 catch (Exception e)
5523 {
5524 m_log.ErrorFormat(
5525 "[LLCLIENTVIEW]: Exeception when handling generic message {0}{1}", e.Message, e.StackTrace);
5526 }
5527 }
5528 }
5529
5530 //m_log.Debug("[LLCLIENTVIEW]: Not handling GenericMessage with method-type of: " + method);
5531 return false;
5532 }
5533
5534 public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack)
5535 {
5536 ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack;
5537 if (ogpack.AgentData.SessionID != SessionId) return false;
5538
5539 RequestObjectPropertiesFamily handlerObjectGroupRequest = OnObjectGroupRequest;
5540 if (handlerObjectGroupRequest != null)
5541 {
5542 for (int i = 0; i < ogpack.ObjectData.Length; i++)
5543 {
5544 handlerObjectGroupRequest(this, ogpack.AgentData.GroupID, ogpack.ObjectData[i].ObjectLocalID, UUID.Zero);
5545 }
5546 }
5547 return true;
5548 }
5549
5550 private bool HandleViewerEffect(IClientAPI sender, Packet Pack)
5551 {
5552 ViewerEffectPacket viewer = (ViewerEffectPacket)Pack;
5553 if (viewer.AgentData.SessionID != SessionId) return false;
5554 ViewerEffectEventHandler handlerViewerEffect = OnViewerEffect;
5555 if (handlerViewerEffect != null)
5556 {
5557 int length = viewer.Effect.Length;
5558 List<ViewerEffectEventHandlerArg> args = new List<ViewerEffectEventHandlerArg>(length);
5559 for (int i = 0; i < length; i++)
5560 {
5561 //copy the effects block arguments into the event handler arg.
5562 ViewerEffectEventHandlerArg argument = new ViewerEffectEventHandlerArg();
5563 argument.AgentID = viewer.Effect[i].AgentID;
5564 argument.Color = viewer.Effect[i].Color;
5565 argument.Duration = viewer.Effect[i].Duration;
5566 argument.ID = viewer.Effect[i].ID;
5567 argument.Type = viewer.Effect[i].Type;
5568 argument.TypeData = viewer.Effect[i].TypeData;
5569 args.Add(argument);
5570 }
5571
5572 handlerViewerEffect(sender, args);
5573 }
5574
5575 return true;
5576 }
5577
5578 private bool HandleAvatarPropertiesRequest(IClientAPI sender, Packet Pack)
5579 {
5580 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack;
5581
5582 #region Packet Session and User Check
5583 if (m_checkPackets)
5584 {
5585 if (avatarProperties.AgentData.SessionID != SessionId ||
5586 avatarProperties.AgentData.AgentID != AgentId)
5587 return true;
5588 }
5589 #endregion
5590
5591 RequestAvatarProperties handlerRequestAvatarProperties = OnRequestAvatarProperties;
5592 if (handlerRequestAvatarProperties != null)
5593 {
5594 handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID);
5595 }
5596 return true;
5597 }
5598
5599 private bool HandleChatFromViewer(IClientAPI sender, Packet Pack)
5600 {
5601 ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack;
5602
5603 #region Packet Session and User Check
5604 if (m_checkPackets)
5605 {
5606 if (inchatpack.AgentData.SessionID != SessionId ||
5607 inchatpack.AgentData.AgentID != AgentId)
5608 return true;
5609 }
5610 #endregion
5611
5612 string fromName = String.Empty; //ClientAvatar.firstname + " " + ClientAvatar.lastname;
5613 byte[] message = inchatpack.ChatData.Message;
5614 byte type = inchatpack.ChatData.Type;
5615 Vector3 fromPos = new Vector3(); // ClientAvatar.Pos;
5616 // UUID fromAgentID = AgentId;
5617
5618 int channel = inchatpack.ChatData.Channel;
5619
5620 if (OnChatFromClient != null)
5621 {
5622 OSChatMessage args = new OSChatMessage();
5623 args.Channel = channel;
5624 args.From = fromName;
5625 args.Message = Utils.BytesToString(message);
5626 args.Type = (ChatTypeEnum)type;
5627 args.Position = fromPos;
5628
5629 args.Scene = Scene;
5630 args.Sender = this;
5631 args.SenderUUID = this.AgentId;
5632
5633 ChatMessage handlerChatFromClient = OnChatFromClient;
5634 if (handlerChatFromClient != null)
5635 handlerChatFromClient(this, args);
5636 }
5637 return true;
5638 }
5639
5640 private bool HandlerAvatarPropertiesUpdate(IClientAPI sender, Packet Pack)
5641 {
5642 AvatarPropertiesUpdatePacket avatarProps = (AvatarPropertiesUpdatePacket)Pack;
5643
5644 #region Packet Session and User Check
5645 if (m_checkPackets)
5646 {
5647 if (avatarProps.AgentData.SessionID != SessionId ||
5648 avatarProps.AgentData.AgentID != AgentId)
5649 return true;
5650 }
5651 #endregion
5652
5653 UpdateAvatarProperties handlerUpdateAvatarProperties = OnUpdateAvatarProperties;
5654 if (handlerUpdateAvatarProperties != null)
5655 {
5656 AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = avatarProps.PropertiesData;
5657 UserProfileData UserProfile = new UserProfileData();
5658 UserProfile.ID = AgentId;
5659 UserProfile.AboutText = Utils.BytesToString(Properties.AboutText);
5660 UserProfile.FirstLifeAboutText = Utils.BytesToString(Properties.FLAboutText);
5661 UserProfile.FirstLifeImage = Properties.FLImageID;
5662 UserProfile.Image = Properties.ImageID;
5663 UserProfile.ProfileUrl = Utils.BytesToString(Properties.ProfileURL);
5664 UserProfile.UserFlags &= ~3;
5665 UserProfile.UserFlags |= Properties.AllowPublish ? 1 : 0;
5666 UserProfile.UserFlags |= Properties.MaturePublish ? 2 : 0;
5667
5668 handlerUpdateAvatarProperties(this, UserProfile);
5669 }
5670 return true;
5671 }
5672
5673 private bool HandlerScriptDialogReply(IClientAPI sender, Packet Pack)
5674 {
5675 ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack;
5676
5677 //m_log.DebugFormat("[CLIENT]: Received ScriptDialogReply from {0}", rdialog.Data.ObjectID);
5678
5679 #region Packet Session and User Check
5680 if (m_checkPackets)
5681 {
5682 if (rdialog.AgentData.SessionID != SessionId ||
5683 rdialog.AgentData.AgentID != AgentId)
5684 return true;
5685 }
5686 #endregion
5687
5688 int ch = rdialog.Data.ChatChannel;
5689 byte[] msg = rdialog.Data.ButtonLabel;
5690 if (OnChatFromClient != null)
5691 {
5692 OSChatMessage args = new OSChatMessage();
5693 args.Channel = ch;
5694 args.From = String.Empty;
5695 args.Message = Utils.BytesToString(msg);
5696 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5697 args.Position = new Vector3();
5698 args.Scene = Scene;
5699 args.Sender = this;
5700 ChatMessage handlerChatFromClient2 = OnChatFromClient;
5701 if (handlerChatFromClient2 != null)
5702 handlerChatFromClient2(this, args);
5703 }
5704
5705 return true;
5706 }
5707
5708 private bool HandlerImprovedInstantMessage(IClientAPI sender, Packet Pack)
5709 {
5710 ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack;
5711
5712 #region Packet Session and User Check
5713 if (m_checkPackets)
5714 {
5715 if (msgpack.AgentData.SessionID != SessionId ||
5716 msgpack.AgentData.AgentID != AgentId)
5717 return true;
5718 }
5719 #endregion
5720
5721 string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName);
5722 string IMmessage = Utils.BytesToString(msgpack.MessageBlock.Message);
5723 ImprovedInstantMessage handlerInstantMessage = OnInstantMessage;
5724
5725 if (handlerInstantMessage != null)
5726 {
5727 GridInstantMessage im = new GridInstantMessage(Scene,
5728 msgpack.AgentData.AgentID,
5729 IMfromName,
5730 msgpack.MessageBlock.ToAgentID,
5731 msgpack.MessageBlock.Dialog,
5732 msgpack.MessageBlock.FromGroup,
5733 IMmessage,
5734 msgpack.MessageBlock.ID,
5735 msgpack.MessageBlock.Offline != 0 ? true : false,
5736 msgpack.MessageBlock.Position,
5737 msgpack.MessageBlock.BinaryBucket);
5738
5739 handlerInstantMessage(this, im);
5740 }
5741 return true;
5742
5743 }
5744
5745 private bool HandlerAcceptFriendship(IClientAPI sender, Packet Pack)
5746 {
5747 AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack;
5748
5749 #region Packet Session and User Check
5750 if (m_checkPackets)
5751 {
5752 if (afriendpack.AgentData.SessionID != SessionId ||
5753 afriendpack.AgentData.AgentID != AgentId)
5754 return true;
5755 }
5756 #endregion
5757
5758 // My guess is this is the folder to stick the calling card into
5759 List<UUID> callingCardFolders = new List<UUID>();
5760
5761 UUID agentID = afriendpack.AgentData.AgentID;
5762 UUID transactionID = afriendpack.TransactionBlock.TransactionID;
5763
5764 for (int fi = 0; fi < afriendpack.FolderData.Length; fi++)
5765 {
5766 callingCardFolders.Add(afriendpack.FolderData[fi].FolderID);
5767 }
5768
5769 FriendActionDelegate handlerApproveFriendRequest = OnApproveFriendRequest;
5770 if (handlerApproveFriendRequest != null)
5771 {
5772 handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders);
5773 }
5774 return true;
5775
5776 }
5777
5778 private bool HandlerDeclineFriendship(IClientAPI sender, Packet Pack)
5779 {
5780 DeclineFriendshipPacket dfriendpack = (DeclineFriendshipPacket)Pack;
5781
5782 #region Packet Session and User Check
5783 if (m_checkPackets)
5784 {
5785 if (dfriendpack.AgentData.SessionID != SessionId ||
5786 dfriendpack.AgentData.AgentID != AgentId)
5787 return true;
5788 }
5789 #endregion
5790
5791 if (OnDenyFriendRequest != null)
5792 {
5793 OnDenyFriendRequest(this,
5794 dfriendpack.AgentData.AgentID,
5795 dfriendpack.TransactionBlock.TransactionID,
5796 null);
5797 }
5798 return true;
5799 }
5800
5801 private bool HandlerTerminateFrendship(IClientAPI sender, Packet Pack)
5802 {
5803 TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack;
5804
5805 #region Packet Session and User Check
5806 if (m_checkPackets)
5807 {
5808 if (tfriendpack.AgentData.SessionID != SessionId ||
5809 tfriendpack.AgentData.AgentID != AgentId)
5810 return true;
5811 }
5812 #endregion
5813
5814 UUID listOwnerAgentID = tfriendpack.AgentData.AgentID;
5815 UUID exFriendID = tfriendpack.ExBlock.OtherID;
5816
5817 FriendshipTermination handlerTerminateFriendship = OnTerminateFriendship;
5818 if (handlerTerminateFriendship != null)
5819 {
5820 handlerTerminateFriendship(this, listOwnerAgentID, exFriendID);
5821 }
5822 return true;
5823 }
5824
5825 private bool HandleFindAgent(IClientAPI client, Packet Packet)
5826 {
5827 FindAgentPacket FindAgent =
5828 (FindAgentPacket)Packet;
5829
5830 FindAgentUpdate FindAgentHandler = OnFindAgent;
5831 if (FindAgentHandler != null)
5832 {
5833 FindAgentHandler(this,FindAgent.AgentBlock.Hunter,FindAgent.AgentBlock.Prey);
5834 return true;
5835 }
5836 return false;
5837 }
5838
5839 private bool HandleTrackAgent(IClientAPI client, Packet Packet)
5840 {
5841 TrackAgentPacket TrackAgent =
5842 (TrackAgentPacket)Packet;
5843
5844 TrackAgentUpdate TrackAgentHandler = OnTrackAgent;
5845 if (TrackAgentHandler != null)
5846 {
5847 TrackAgentHandler(this,
5848 TrackAgent.AgentData.AgentID,
5849 TrackAgent.TargetData.PreyID);
5850 return true;
5851 }
5852 return false;
5853 }
5854
5855 private bool HandlerRezObject(IClientAPI sender, Packet Pack)
5856 {
5857 RezObjectPacket rezPacket = (RezObjectPacket)Pack;
5858
5859 #region Packet Session and User Check
5860 if (m_checkPackets)
5861 {
5862 if (rezPacket.AgentData.SessionID != SessionId ||
5863 rezPacket.AgentData.AgentID != AgentId)
5864 return true;
5865 }
5866 #endregion
5867
5868 RezObject handlerRezObject = OnRezObject;
5869 if (handlerRezObject != null)
5870 {
5871 handlerRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd,
5872 rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID,
5873 rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection,
5874 rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem,
5875 rezPacket.RezData.FromTaskID);
5876 }
5877 return true;
5878 }
5879
5880 private bool HandlerDeRezObject(IClientAPI sender, Packet Pack)
5881 {
5882 DeRezObjectPacket DeRezPacket = (DeRezObjectPacket)Pack;
5883
5884 #region Packet Session and User Check
5885 if (m_checkPackets)
5886 {
5887 if (DeRezPacket.AgentData.SessionID != SessionId ||
5888 DeRezPacket.AgentData.AgentID != AgentId)
5889 return true;
5890 }
5891 #endregion
5892
5893 DeRezObject handlerDeRezObject = OnDeRezObject;
5894 if (handlerDeRezObject != null)
5895 {
5896 List<uint> deRezIDs = new List<uint>();
5897
5898 foreach (DeRezObjectPacket.ObjectDataBlock data in
5899 DeRezPacket.ObjectData)
5900 {
5901 deRezIDs.Add(data.ObjectLocalID);
5902 }
5903 // It just so happens that the values on the DeRezAction enumerator match the Destination
5904 // values given by a Second Life client
5905 handlerDeRezObject(this, deRezIDs,
5906 DeRezPacket.AgentBlock.GroupID,
5907 (DeRezAction)DeRezPacket.AgentBlock.Destination,
5908 DeRezPacket.AgentBlock.DestinationID);
5909
5910 }
5911 return true;
5912 }
5913
5914 private bool HandlerModifyLand(IClientAPI sender, Packet Pack)
5915 {
5916 ModifyLandPacket modify = (ModifyLandPacket)Pack;
5917
5918 #region Packet Session and User Check
5919 if (m_checkPackets)
5920 {
5921 if (modify.AgentData.SessionID != SessionId ||
5922 modify.AgentData.AgentID != AgentId)
5923 return true;
5924 }
5925
5926 #endregion
5927 //m_log.Info("[LAND]: LAND:" + modify.ToString());
5928 if (modify.ParcelData.Length > 0)
5929 {
5930 if (OnModifyTerrain != null)
5931 {
5932 for (int i = 0; i < modify.ParcelData.Length; i++)
5933 {
5934 ModifyTerrain handlerModifyTerrain = OnModifyTerrain;
5935 if (handlerModifyTerrain != null)
5936 {
5937 handlerModifyTerrain(AgentId, modify.ModifyBlock.Height, modify.ModifyBlock.Seconds,
5938 modify.ModifyBlock.BrushSize,
5939 modify.ModifyBlock.Action, modify.ParcelData[i].North,
5940 modify.ParcelData[i].West, modify.ParcelData[i].South,
5941 modify.ParcelData[i].East, AgentId);
5942 }
5943 }
5944 }
5945 }
5946
5947 return true;
5948 }
5949
5950 private bool HandlerRegionHandshakeReply(IClientAPI sender, Packet Pack)
5951 {
5952 Action<IClientAPI> handlerRegionHandShakeReply = OnRegionHandShakeReply;
5953 if (handlerRegionHandShakeReply != null)
5954 {
5955 handlerRegionHandShakeReply(this);
5956 }
5957
5958 return true;
5959 }
5960
5961 private bool HandlerAgentWearablesRequest(IClientAPI sender, Packet Pack)
5962 {
5963 GenericCall1 handlerRequestWearables = OnRequestWearables;
5964
5965 if (handlerRequestWearables != null)
5966 {
5967 handlerRequestWearables(sender);
5968 }
5969
5970 Action<IClientAPI> handlerRequestAvatarsData = OnRequestAvatarsData;
5971
5972 if (handlerRequestAvatarsData != null)
5973 {
5974 handlerRequestAvatarsData(this);
5975 }
5976
5977 return true;
5978 }
5979
5980 private bool HandlerAgentSetAppearance(IClientAPI sender, Packet Pack)
5981 {
5982 AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack;
5983
5984 #region Packet Session and User Check
5985 if (m_checkPackets)
5986 {
5987 if (appear.AgentData.SessionID != SessionId ||
5988 appear.AgentData.AgentID != AgentId)
5989 return true;
5990 }
5991 #endregion
5992
5993 SetAppearance handlerSetAppearance = OnSetAppearance;
5994 if (handlerSetAppearance != null)
5995 {
5996 // Temporarily protect ourselves from the mantis #951 failure.
5997 // However, we could do this for several other handlers where a failure isn't terminal
5998 // for the client session anyway, in order to protect ourselves against bad code in plugins
5999 try
6000 {
6001
6002 byte[] visualparams = new byte[appear.VisualParam.Length];
6003 for (int i = 0; i < appear.VisualParam.Length; i++)
6004 visualparams[i] = appear.VisualParam[i].ParamValue;
6005
6006 Primitive.TextureEntry te = null;
6007 if (appear.ObjectData.TextureEntry.Length > 1)
6008 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length);
6009
6010 handlerSetAppearance(sender, te, visualparams);
6011 }
6012 catch (Exception e)
6013 {
6014 m_log.ErrorFormat(
6015 "[CLIENT VIEW]: AgentSetApperance packet handler threw an exception, {0}",
6016 e);
6017 }
6018 }
6019
6020 return true;
6021 }
6022
6023 private bool HandlerAgentIsNowWearing(IClientAPI sender, Packet Pack)
6024 {
6025 if (OnAvatarNowWearing != null)
6026 {
6027 AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack;
6028
6029 #region Packet Session and User Check
6030 if (m_checkPackets)
6031 {
6032 if (nowWearing.AgentData.SessionID != SessionId ||
6033 nowWearing.AgentData.AgentID != AgentId)
6034 return true;
6035 }
6036 #endregion
6037
6038 AvatarWearingArgs wearingArgs = new AvatarWearingArgs();
6039 for (int i = 0; i < nowWearing.WearableData.Length; i++)
6040 {
6041 m_log.DebugFormat("[XXX]: Wearable type {0} item {1}", nowWearing.WearableData[i].WearableType, nowWearing.WearableData[i].ItemID);
6042 AvatarWearingArgs.Wearable wearable =
6043 new AvatarWearingArgs.Wearable(nowWearing.WearableData[i].ItemID,
6044 nowWearing.WearableData[i].WearableType);
6045 wearingArgs.NowWearing.Add(wearable);
6046 }
6047
6048 AvatarNowWearing handlerAvatarNowWearing = OnAvatarNowWearing;
6049 if (handlerAvatarNowWearing != null)
6050 {
6051 handlerAvatarNowWearing(this, wearingArgs);
6052 }
6053 }
6054 return true;
6055 }
6056
6057 private bool HandlerRezSingleAttachmentFromInv(IClientAPI sender, Packet Pack)
6058 {
6059 RezSingleAttachmentFromInv handlerRezSingleAttachment = OnRezSingleAttachmentFromInv;
6060 if (handlerRezSingleAttachment != null)
6061 {
6062 RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack;
6063
6064 #region Packet Session and User Check
6065 if (m_checkPackets)
6066 {
6067 if (rez.AgentData.SessionID != SessionId ||
6068 rez.AgentData.AgentID != AgentId)
6069 return true;
6070 }
6071 #endregion
6072
6073 handlerRezSingleAttachment(this, rez.ObjectData.ItemID,
6074 rez.ObjectData.AttachmentPt);
6075 }
6076
6077 return true;
6078 }
6079
6080 private bool HandleRezMultipleAttachmentsFromInv(IClientAPI sender, Packet Pack)
6081 {
6082 RezMultipleAttachmentsFromInv handlerRezMultipleAttachments = OnRezMultipleAttachmentsFromInv;
6083 if (handlerRezMultipleAttachments != null)
6084 {
6085 RezMultipleAttachmentsFromInvPacket rez = (RezMultipleAttachmentsFromInvPacket)Pack;
6086 handlerRezMultipleAttachments(this, rez.HeaderData,
6087 rez.ObjectData);
6088 }
6089
6090 return true;
6091 }
6092
6093 private bool HandleDetachAttachmentIntoInv(IClientAPI sender, Packet Pack)
6094 {
6095 UUIDNameRequest handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv;
6096 if (handlerDetachAttachmentIntoInv != null)
6097 {
6098 DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack;
6099
6100 #region Packet Session and User Check
6101 // UNSUPPORTED ON THIS PACKET
6102 #endregion
6103
6104 UUID itemID = detachtoInv.ObjectData.ItemID;
6105 // UUID ATTACH_agentID = detachtoInv.ObjectData.AgentID;
6106
6107 handlerDetachAttachmentIntoInv(itemID, this);
6108 }
6109 return true;
6110 }
6111
6112 private bool HandleObjectAttach(IClientAPI sender, Packet Pack)
6113 {
6114 if (OnObjectAttach != null)
6115 {
6116 ObjectAttachPacket att = (ObjectAttachPacket)Pack;
6117
6118 #region Packet Session and User Check
6119 if (m_checkPackets)
6120 {
6121 if (att.AgentData.SessionID != SessionId ||
6122 att.AgentData.AgentID != AgentId)
6123 return true;
6124 }
6125 #endregion
6126
6127 ObjectAttach handlerObjectAttach = OnObjectAttach;
6128
6129 if (handlerObjectAttach != null)
6130 {
6131 if (att.ObjectData.Length > 0)
6132 {
6133 handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, false);
6134 }
6135 }
6136 }
6137 return true;
6138 }
6139
6140 private bool HandleObjectDetach(IClientAPI sender, Packet Pack)
6141 {
6142 ObjectDetachPacket dett = (ObjectDetachPacket)Pack;
6143
6144 #region Packet Session and User Check
6145 if (m_checkPackets)
6146 {
6147 if (dett.AgentData.SessionID != SessionId ||
6148 dett.AgentData.AgentID != AgentId)
6149 return true;
6150 }
6151 #endregion
6152
6153 for (int j = 0; j < dett.ObjectData.Length; j++)
6154 {
6155 uint obj = dett.ObjectData[j].ObjectLocalID;
6156 ObjectDeselect handlerObjectDetach = OnObjectDetach;
6157 if (handlerObjectDetach != null)
6158 {
6159 handlerObjectDetach(obj, this);
6160 }
6161
6162 }
6163 return true;
6164 }
6165
6166 private bool HandleObjectDrop(IClientAPI sender, Packet Pack)
6167 {
6168 ObjectDropPacket dropp = (ObjectDropPacket)Pack;
6169
6170 #region Packet Session and User Check
6171 if (m_checkPackets)
6172 {
6173 if (dropp.AgentData.SessionID != SessionId ||
6174 dropp.AgentData.AgentID != AgentId)
6175 return true;
6176 }
6177 #endregion
6178
6179 for (int j = 0; j < dropp.ObjectData.Length; j++)
6180 {
6181 uint obj = dropp.ObjectData[j].ObjectLocalID;
6182 ObjectDrop handlerObjectDrop = OnObjectDrop;
6183 if (handlerObjectDrop != null)
6184 {
6185 handlerObjectDrop(obj, this);
6186 }
6187 }
6188 return true;
6189 }
6190
6191 private bool HandleSetAlwaysRun(IClientAPI sender, Packet Pack)
6192 {
6193 SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack;
6194
6195 #region Packet Session and User Check
6196 if (m_checkPackets)
6197 {
6198 if (run.AgentData.SessionID != SessionId ||
6199 run.AgentData.AgentID != AgentId)
6200 return true;
6201 }
6202 #endregion
6203
6204 SetAlwaysRun handlerSetAlwaysRun = OnSetAlwaysRun;
6205 if (handlerSetAlwaysRun != null)
6206 handlerSetAlwaysRun(this, run.AgentData.AlwaysRun);
6207
6208 return true;
6209 }
6210
6211 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack)
6212 {
6213 GenericCall1 handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
6214 if (handlerCompleteMovementToRegion != null)
6215 {
6216 handlerCompleteMovementToRegion(sender);
6217 }
6218 handlerCompleteMovementToRegion = null;
6219
6220 return true;
6221 }
6222
6223 private bool HandleAgentAnimation(IClientAPI sender, Packet Pack)
6224 {
6225 AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack;
6226
6227 #region Packet Session and User Check
6228 if (m_checkPackets)
6229 {
6230 if (AgentAni.AgentData.SessionID != SessionId ||
6231 AgentAni.AgentData.AgentID != AgentId)
6232 return true;
6233 }
6234 #endregion
6235
6236 StartAnim handlerStartAnim = null;
6237 StopAnim handlerStopAnim = null;
6238
6239 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
6240 {
6241 if (AgentAni.AnimationList[i].StartAnim)
6242 {
6243 handlerStartAnim = OnStartAnim;
6244 if (handlerStartAnim != null)
6245 {
6246 handlerStartAnim(this, AgentAni.AnimationList[i].AnimID);
6247 }
6248 }
6249 else
6250 {
6251 handlerStopAnim = OnStopAnim;
6252 if (handlerStopAnim != null)
6253 {
6254 handlerStopAnim(this, AgentAni.AnimationList[i].AnimID);
6255 }
6256 }
6257 }
6258 return true;
6259 }
6260
6261 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack)
6262 {
6263 if (OnAgentRequestSit != null)
6264 {
6265 AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket)Pack;
6266
6267 #region Packet Session and User Check
6268 if (m_checkPackets)
6269 {
6270 if (agentRequestSit.AgentData.SessionID != SessionId ||
6271 agentRequestSit.AgentData.AgentID != AgentId)
6272 return true;
6273 }
6274 #endregion
6275
6276 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit;
6277 if (handlerAgentRequestSit != null)
6278 handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID,
6279 agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset);
6280 }
6281 return true;
6282 }
6283
6284 private bool HandleAgentSit(IClientAPI sender, Packet Pack)
6285 {
6286 if (OnAgentSit != null)
6287 {
6288 AgentSitPacket agentSit = (AgentSitPacket)Pack;
6289
6290 #region Packet Session and User Check
6291 if (m_checkPackets)
6292 {
6293 if (agentSit.AgentData.SessionID != SessionId ||
6294 agentSit.AgentData.AgentID != AgentId)
6295 return true;
6296 }
6297 #endregion
6298
6299 AgentSit handlerAgentSit = OnAgentSit;
6300 if (handlerAgentSit != null)
6301 {
6302 OnAgentSit(this, agentSit.AgentData.AgentID);
6303 }
6304 }
6305 return true;
6306 }
6307
6308 private bool HandleSoundTrigger(IClientAPI sender, Packet Pack)
6309 {
6310 SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack;
6311
6312 #region Packet Session and User Check
6313 if (m_checkPackets)
6314 {
6315 // UNSUPPORTED ON THIS PACKET
6316 }
6317 #endregion
6318
6319 SoundTrigger handlerSoundTrigger = OnSoundTrigger;
6320 if (handlerSoundTrigger != null)
6321 {
6322 // UUIDS are sent as zeroes by the client, substitute agent's id
6323 handlerSoundTrigger(soundTriggerPacket.SoundData.SoundID, AgentId,
6324 AgentId, AgentId,
6325 soundTriggerPacket.SoundData.Gain, soundTriggerPacket.SoundData.Position,
6326 soundTriggerPacket.SoundData.Handle, 0);
6327
6328 }
6329 return true;
6330 }
6331
6332 private bool HandleAvatarPickerRequest(IClientAPI sender, Packet Pack)
6333 {
6334 AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack;
6335
6336 #region Packet Session and User Check
6337 if (m_checkPackets)
6338 {
6339 if (avRequestQuery.AgentData.SessionID != SessionId ||
6340 avRequestQuery.AgentData.AgentID != AgentId)
6341 return true;
6342 }
6343 #endregion
6344
6345 AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData;
6346 AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data;
6347 //m_log.Debug("Agent Sends:" + Utils.BytesToString(querydata.Name));
6348
6349 AvatarPickerRequest handlerAvatarPickerRequest = OnAvatarPickerRequest;
6350 if (handlerAvatarPickerRequest != null)
6351 {
6352 handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID,
6353 Utils.BytesToString(querydata.Name));
6354 }
6355 return true;
6356 }
6357
6358 private bool HandleAgentDataUpdateRequest(IClientAPI sender, Packet Pack)
6359 {
6360 AgentDataUpdateRequestPacket avRequestDataUpdatePacket = (AgentDataUpdateRequestPacket)Pack;
6361
6362 #region Packet Session and User Check
6363 if (m_checkPackets)
6364 {
6365 if (avRequestDataUpdatePacket.AgentData.SessionID != SessionId ||
6366 avRequestDataUpdatePacket.AgentData.AgentID != AgentId)
6367 return true;
6368 }
6369 #endregion
6370
6371 FetchInventory handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest;
6372
6373 if (handlerAgentDataUpdateRequest != null)
6374 {
6375 handlerAgentDataUpdateRequest(this, avRequestDataUpdatePacket.AgentData.AgentID, avRequestDataUpdatePacket.AgentData.SessionID);
6376 }
6377
6378 return true;
6379 }
6380
6381 private bool HandleUserInfoRequest(IClientAPI sender, Packet Pack)
6382 {
6383 UserInfoRequest handlerUserInfoRequest = OnUserInfoRequest;
6384 if (handlerUserInfoRequest != null)
6385 {
6386 handlerUserInfoRequest(this);
6387 }
6388 else
6389 {
6390 SendUserInfoReply(false, true, "");
6391 }
6392 return true;
6393
6394 }
6395
6396 private bool HandleUpdateUserInfo(IClientAPI sender, Packet Pack)
6397 {
6398 UpdateUserInfoPacket updateUserInfo = (UpdateUserInfoPacket)Pack;
6399
6400 #region Packet Session and User Check
6401 if (m_checkPackets)
6402 {
6403 if (updateUserInfo.AgentData.SessionID != SessionId ||
6404 updateUserInfo.AgentData.AgentID != AgentId)
6405 return true;
6406 }
6407 #endregion
6408
6409 UpdateUserInfo handlerUpdateUserInfo = OnUpdateUserInfo;
6410 if (handlerUpdateUserInfo != null)
6411 {
6412 bool visible = true;
6413 string DirectoryVisibility =
6414 Utils.BytesToString(updateUserInfo.UserData.DirectoryVisibility);
6415 if (DirectoryVisibility == "hidden")
6416 visible = false;
6417
6418 handlerUpdateUserInfo(
6419 updateUserInfo.UserData.IMViaEMail,
6420 visible, this);
6421 }
6422 return true;
6423 }
6424
6425 private bool HandleSetStartLocationRequest(IClientAPI sender, Packet Pack)
6426 {
6427 SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack;
6428
6429 #region Packet Session and User Check
6430 if (m_checkPackets)
6431 {
6432 if (avSetStartLocationRequestPacket.AgentData.SessionID != SessionId ||
6433 avSetStartLocationRequestPacket.AgentData.AgentID != AgentId)
6434 return true;
6435 }
6436 #endregion
6437
6438 if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId)
6439 {
6440 // Linden Client limitation..
6441 if (avSetStartLocationRequestPacket.StartLocationData.LocationPos.X == 255.5f
6442 || avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y == 255.5f)
6443 {
6444 ScenePresence avatar = null;
6445 if (((Scene)m_scene).TryGetScenePresence(AgentId, out avatar))
6446 {
6447 if (avSetStartLocationRequestPacket.StartLocationData.LocationPos.X == 255.5f)
6448 {
6449 avSetStartLocationRequestPacket.StartLocationData.LocationPos.X = avatar.AbsolutePosition.X;
6450 }
6451 if (avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y == 255.5f)
6452 {
6453 avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y = avatar.AbsolutePosition.Y;
6454 }
6455 }
6456
6457 }
6458 TeleportLocationRequest handlerSetStartLocationRequest = OnSetStartLocationRequest;
6459 if (handlerSetStartLocationRequest != null)
6460 {
6461 handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos,
6462 avSetStartLocationRequestPacket.StartLocationData.LocationLookAt,
6463 avSetStartLocationRequestPacket.StartLocationData.LocationID);
6464 }
6465 }
6466 return true;
6467 }
6468
6469 private bool HandleAgentThrottle(IClientAPI sender, Packet Pack)
6470 {
6471 AgentThrottlePacket atpack = (AgentThrottlePacket)Pack;
6472
6473 #region Packet Session and User Check
6474 if (m_checkPackets)
6475 {
6476 if (atpack.AgentData.SessionID != SessionId ||
6477 atpack.AgentData.AgentID != AgentId)
6478 return true;
6479 }
6480 #endregion
6481
6482 m_udpClient.SetThrottles(atpack.Throttle.Throttles);
6483 return true;
6484 }
6485
6486 private bool HandleAgentPause(IClientAPI sender, Packet Pack)
6487 {
6488 m_udpClient.IsPaused = true;
6489 return true;
6490 }
6491
6492 private bool HandleAgentResume(IClientAPI sender, Packet Pack)
6493 {
6494 m_udpClient.IsPaused = false;
6495 SendStartPingCheck(m_udpClient.CurrentPingSequence++);
6496 return true;
6497 }
6498
6499 private bool HandleForceScriptControlRelease(IClientAPI sender, Packet Pack)
6500 {
6501 ForceReleaseControls handlerForceReleaseControls = OnForceReleaseControls;
6502 if (handlerForceReleaseControls != null)
6503 {
6504 handlerForceReleaseControls(this, AgentId);
6505 }
6506 return true;
6507 }
6508
6509 #endregion Scene/Avatar
6510
6511 #region Objects/m_sceneObjects
6512
6513 private bool HandleObjectLink(IClientAPI sender, Packet Pack)
6514 {
6515 ObjectLinkPacket link = (ObjectLinkPacket)Pack;
6516
6517 #region Packet Session and User Check
6518 if (m_checkPackets)
6519 {
6520 if (link.AgentData.SessionID != SessionId ||
6521 link.AgentData.AgentID != AgentId)
6522 return true;
6523 }
6524 #endregion
6525
6526 uint parentprimid = 0;
6527 List<uint> childrenprims = new List<uint>();
6528 if (link.ObjectData.Length > 1)
6529 {
6530 parentprimid = link.ObjectData[0].ObjectLocalID;
6531
6532 for (int i = 1; i < link.ObjectData.Length; i++)
6533 {
6534 childrenprims.Add(link.ObjectData[i].ObjectLocalID);
6535 }
6536 }
6537 LinkObjects handlerLinkObjects = OnLinkObjects;
6538 if (handlerLinkObjects != null)
6539 {
6540 handlerLinkObjects(this, parentprimid, childrenprims);
6541 }
6542 return true;
6543 }
6544
6545 private bool HandleObjectDelink(IClientAPI sender, Packet Pack)
6546 {
6547 ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack;
6548
6549 #region Packet Session and User Check
6550 if (m_checkPackets)
6551 {
6552 if (delink.AgentData.SessionID != SessionId ||
6553 delink.AgentData.AgentID != AgentId)
6554 return true;
6555 }
6556 #endregion
6557
6558 // It appears the prim at index 0 is not always the root prim (for
6559 // instance, when one prim of a link set has been edited independently
6560 // of the others). Therefore, we'll pass all the ids onto the delink
6561 // method for it to decide which is the root.
6562 List<uint> prims = new List<uint>();
6563 for (int i = 0; i < delink.ObjectData.Length; i++)
6564 {
6565 prims.Add(delink.ObjectData[i].ObjectLocalID);
6566 }
6567 DelinkObjects handlerDelinkObjects = OnDelinkObjects;
6568 if (handlerDelinkObjects != null)
6569 {
6570 handlerDelinkObjects(prims, this);
6571 }
6572
6573 return true;
6574 }
6575
6576 private bool HandleObjectAdd(IClientAPI sender, Packet Pack)
6577 {
6578 if (OnAddPrim != null)
6579 {
6580 ObjectAddPacket addPacket = (ObjectAddPacket)Pack;
6581
6582 #region Packet Session and User Check
6583 if (m_checkPackets)
6584 {
6585 if (addPacket.AgentData.SessionID != SessionId ||
6586 addPacket.AgentData.AgentID != AgentId)
6587 return true;
6588 }
6589 #endregion
6590
6591 PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket);
6592 // m_log.Info("[REZData]: " + addPacket.ToString());
6593 //BypassRaycast: 1
6594 //RayStart: <69.79469, 158.2652, 98.40343>
6595 //RayEnd: <61.97724, 141.995, 92.58341>
6596 //RayTargetID: 00000000-0000-0000-0000-000000000000
6597
6598 //Check to see if adding the prim is allowed; useful for any module wanting to restrict the
6599 //object from rezing initially
6600
6601 AddNewPrim handlerAddPrim = OnAddPrim;
6602 if (handlerAddPrim != null)
6603 handlerAddPrim(AgentId, ActiveGroupId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection);
6604 }
6605 return true;
6606 }
6607
6608 private bool HandleObjectShape(IClientAPI sender, Packet Pack)
6609 {
6610 ObjectShapePacket shapePacket = (ObjectShapePacket)Pack;
6611
6612 #region Packet Session and User Check
6613 if (m_checkPackets)
6614 {
6615 if (shapePacket.AgentData.SessionID != SessionId ||
6616 shapePacket.AgentData.AgentID != AgentId)
6617 return true;
6618 }
6619 #endregion
6620
6621 UpdateShape handlerUpdatePrimShape = null;
6622 for (int i = 0; i < shapePacket.ObjectData.Length; i++)
6623 {
6624 handlerUpdatePrimShape = OnUpdatePrimShape;
6625 if (handlerUpdatePrimShape != null)
6626 {
6627 UpdateShapeArgs shapeData = new UpdateShapeArgs();
6628 shapeData.ObjectLocalID = shapePacket.ObjectData[i].ObjectLocalID;
6629 shapeData.PathBegin = shapePacket.ObjectData[i].PathBegin;
6630 shapeData.PathCurve = shapePacket.ObjectData[i].PathCurve;
6631 shapeData.PathEnd = shapePacket.ObjectData[i].PathEnd;
6632 shapeData.PathRadiusOffset = shapePacket.ObjectData[i].PathRadiusOffset;
6633 shapeData.PathRevolutions = shapePacket.ObjectData[i].PathRevolutions;
6634 shapeData.PathScaleX = shapePacket.ObjectData[i].PathScaleX;
6635 shapeData.PathScaleY = shapePacket.ObjectData[i].PathScaleY;
6636 shapeData.PathShearX = shapePacket.ObjectData[i].PathShearX;
6637 shapeData.PathShearY = shapePacket.ObjectData[i].PathShearY;
6638 shapeData.PathSkew = shapePacket.ObjectData[i].PathSkew;
6639 shapeData.PathTaperX = shapePacket.ObjectData[i].PathTaperX;
6640 shapeData.PathTaperY = shapePacket.ObjectData[i].PathTaperY;
6641 shapeData.PathTwist = shapePacket.ObjectData[i].PathTwist;
6642 shapeData.PathTwistBegin = shapePacket.ObjectData[i].PathTwistBegin;
6643 shapeData.ProfileBegin = shapePacket.ObjectData[i].ProfileBegin;
6644 shapeData.ProfileCurve = shapePacket.ObjectData[i].ProfileCurve;
6645 shapeData.ProfileEnd = shapePacket.ObjectData[i].ProfileEnd;
6646 shapeData.ProfileHollow = shapePacket.ObjectData[i].ProfileHollow;
6647
6648 handlerUpdatePrimShape(m_agentId, shapePacket.ObjectData[i].ObjectLocalID,
6649 shapeData);
6650 }
6651 }
6652 return true;
6653 }
6654
6655 private bool HandleObjectExtraParams(IClientAPI sender, Packet Pack)
6656 {
6657 ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack;
6658
6659 #region Packet Session and User Check
6660 if (m_checkPackets)
6661 {
6662 if (extraPar.AgentData.SessionID != SessionId ||
6663 extraPar.AgentData.AgentID != AgentId)
6664 return true;
6665 }
6666 #endregion
6667
6668 ObjectExtraParams handlerUpdateExtraParams = OnUpdateExtraParams;
6669 if (handlerUpdateExtraParams != null)
6670 {
6671 for (int i = 0; i < extraPar.ObjectData.Length; i++)
6672 {
6673 handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[i].ObjectLocalID,
6674 extraPar.ObjectData[i].ParamType,
6675 extraPar.ObjectData[i].ParamInUse, extraPar.ObjectData[i].ParamData);
6676 }
6677 }
6678 return true;
6679 }
6680
6681 private bool HandleObjectDuplicate(IClientAPI sender, Packet Pack)
6682 {
6683 ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack;
6684
6685 #region Packet Session and User Check
6686 if (m_checkPackets)
6687 {
6688 if (dupe.AgentData.SessionID != SessionId ||
6689 dupe.AgentData.AgentID != AgentId)
6690 return true;
6691 }
6692 #endregion
6693
6694// ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData;
6695
6696 ObjectDuplicate handlerObjectDuplicate = null;
6697
6698 for (int i = 0; i < dupe.ObjectData.Length; i++)
6699 {
6700 handlerObjectDuplicate = OnObjectDuplicate;
6701 if (handlerObjectDuplicate != null)
6702 {
6703 handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset,
6704 dupe.SharedData.DuplicateFlags, AgentId,
6705 m_activeGroupID);
6706 }
6707 }
6708
6709 return true;
6710 }
6711
6712 private bool HandleRequestMultipleObjects(IClientAPI sender, Packet Pack)
6713 {
6714 RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack;
6715
6716 #region Packet Session and User Check
6717 if (m_checkPackets)
6718 {
6719 if (incomingRequest.AgentData.SessionID != SessionId ||
6720 incomingRequest.AgentData.AgentID != AgentId)
6721 return true;
6722 }
6723 #endregion
6724
6725 ObjectRequest handlerObjectRequest = null;
6726
6727 for (int i = 0; i < incomingRequest.ObjectData.Length; i++)
6728 {
6729 handlerObjectRequest = OnObjectRequest;
6730 if (handlerObjectRequest != null)
6731 {
6732 handlerObjectRequest(incomingRequest.ObjectData[i].ID, this);
6733 }
6734 }
6735 return true;
6736 }
6737
6738 private bool HandleObjectSelect(IClientAPI sender, Packet Pack)
6739 {
6740 ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack;
6741
6742 #region Packet Session and User Check
6743 if (m_checkPackets)
6744 {
6745 if (incomingselect.AgentData.SessionID != SessionId ||
6746 incomingselect.AgentData.AgentID != AgentId)
6747 return true;
6748 }
6749 #endregion
6750
6751 ObjectSelect handlerObjectSelect = null;
6752
6753 for (int i = 0; i < incomingselect.ObjectData.Length; i++)
6754 {
6755 handlerObjectSelect = OnObjectSelect;
6756 if (handlerObjectSelect != null)
6757 {
6758 handlerObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this);
6759 }
6760 }
6761 return true;
6762 }
6763
6764 private bool HandleObjectDeselect(IClientAPI sender, Packet Pack)
6765 {
6766 ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack;
6767
6768 #region Packet Session and User Check
6769 if (m_checkPackets)
6770 {
6771 if (incomingdeselect.AgentData.SessionID != SessionId ||
6772 incomingdeselect.AgentData.AgentID != AgentId)
6773 return true;
6774 }
6775 #endregion
6776
6777 ObjectDeselect handlerObjectDeselect = null;
6778
6779 for (int i = 0; i < incomingdeselect.ObjectData.Length; i++)
6780 {
6781 handlerObjectDeselect = OnObjectDeselect;
6782 if (handlerObjectDeselect != null)
6783 {
6784 OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this);
6785 }
6786 }
6787 return true;
6788 }
6789
6790 private bool HandleObjectPosition(IClientAPI sender, Packet Pack)
6791 {
6792 // DEPRECATED: but till libsecondlife removes it, people will use it
6793 ObjectPositionPacket position = (ObjectPositionPacket)Pack;
6794
6795 #region Packet Session and User Check
6796 if (m_checkPackets)
6797 {
6798 if (position.AgentData.SessionID != SessionId ||
6799 position.AgentData.AgentID != AgentId)
6800 return true;
6801 }
6802 #endregion
6803
6804
6805 for (int i = 0; i < position.ObjectData.Length; i++)
6806 {
6807 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition;
6808 if (handlerUpdateVector != null)
6809 handlerUpdateVector(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, this);
6810 }
6811
6812 return true;
6813 }
6814
6815 private bool HandleObjectScale(IClientAPI sender, Packet Pack)
6816 {
6817 // DEPRECATED: but till libsecondlife removes it, people will use it
6818 ObjectScalePacket scale = (ObjectScalePacket)Pack;
6819
6820 #region Packet Session and User Check
6821 if (m_checkPackets)
6822 {
6823 if (scale.AgentData.SessionID != SessionId ||
6824 scale.AgentData.AgentID != AgentId)
6825 return true;
6826 }
6827 #endregion
6828
6829 for (int i = 0; i < scale.ObjectData.Length; i++)
6830 {
6831 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
6832 if (handlerUpdatePrimGroupScale != null)
6833 handlerUpdatePrimGroupScale(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, this);
6834 }
6835
6836 return true;
6837 }
6838
6839 private bool HandleObjectRotation(IClientAPI sender, Packet Pack)
6840 {
6841 // DEPRECATED: but till libsecondlife removes it, people will use it
6842 ObjectRotationPacket rotation = (ObjectRotationPacket)Pack;
6843
6844 #region Packet Session and User Check
6845 if (m_checkPackets)
6846 {
6847 if (rotation.AgentData.SessionID != SessionId ||
6848 rotation.AgentData.AgentID != AgentId)
6849 return true;
6850 }
6851 #endregion
6852
6853 for (int i = 0; i < rotation.ObjectData.Length; i++)
6854 {
6855 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation;
6856 if (handlerUpdatePrimRotation != null)
6857 handlerUpdatePrimRotation(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, this);
6858 }
6859
6860 return true;
6861 }
6862
6863 private bool HandleObjectFlagUpdate(IClientAPI sender, Packet Pack)
6864 {
6865 ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack;
6866
6867 #region Packet Session and User Check
6868 if (m_checkPackets)
6869 {
6870 if (flags.AgentData.SessionID != SessionId ||
6871 flags.AgentData.AgentID != AgentId)
6872 return true;
6873 }
6874 #endregion
6875
6876 UpdatePrimFlags handlerUpdatePrimFlags = OnUpdatePrimFlags;
6877
6878 if (handlerUpdatePrimFlags != null)
6879 {
6880 byte[] data = Pack.ToBytes();
6881 // 46,47,48 are special positions within the packet
6882 // This may change so perhaps we need a better way
6883 // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?)
6884 bool UsePhysics = (data[46] != 0) ? true : false;
6885 bool IsTemporary = (data[47] != 0) ? true : false;
6886 bool IsPhantom = (data[48] != 0) ? true : false;
6887 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this);
6888 }
6889 return true;
6890 }
6891
6892 private bool HandleObjectImage(IClientAPI sender, Packet Pack)
6893 {
6894 ObjectImagePacket imagePack = (ObjectImagePacket)Pack;
6895
6896 UpdatePrimTexture handlerUpdatePrimTexture = null;
6897 for (int i = 0; i < imagePack.ObjectData.Length; i++)
6898 {
6899 handlerUpdatePrimTexture = OnUpdatePrimTexture;
6900 if (handlerUpdatePrimTexture != null)
6901 {
6902 handlerUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID,
6903 imagePack.ObjectData[i].TextureEntry, this);
6904 }
6905 }
6906 return true;
6907 }
6908
6909 private bool HandleObjectGrab(IClientAPI sender, Packet Pack)
6910 {
6911 ObjectGrabPacket grab = (ObjectGrabPacket)Pack;
6912
6913 #region Packet Session and User Check
6914 if (m_checkPackets)
6915 {
6916 if (grab.AgentData.SessionID != SessionId ||
6917 grab.AgentData.AgentID != AgentId)
6918 return true;
6919 }
6920 #endregion
6921
6922 GrabObject handlerGrabObject = OnGrabObject;
6923
6924 if (handlerGrabObject != null)
6925 {
6926 List<SurfaceTouchEventArgs> touchArgs = new List<SurfaceTouchEventArgs>();
6927 if ((grab.SurfaceInfo != null) && (grab.SurfaceInfo.Length > 0))
6928 {
6929 foreach (ObjectGrabPacket.SurfaceInfoBlock surfaceInfo in grab.SurfaceInfo)
6930 {
6931 SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs();
6932 arg.Binormal = surfaceInfo.Binormal;
6933 arg.FaceIndex = surfaceInfo.FaceIndex;
6934 arg.Normal = surfaceInfo.Normal;
6935 arg.Position = surfaceInfo.Position;
6936 arg.STCoord = surfaceInfo.STCoord;
6937 arg.UVCoord = surfaceInfo.UVCoord;
6938 touchArgs.Add(arg);
6939 }
6940 }
6941 handlerGrabObject(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, this, touchArgs);
6942 }
6943 return true;
6944 }
6945
6946 private bool HandleObjectGrabUpdate(IClientAPI sender, Packet Pack)
6947 {
6948 ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack;
6949
6950 #region Packet Session and User Check
6951 if (m_checkPackets)
6952 {
6953 if (grabUpdate.AgentData.SessionID != SessionId ||
6954 grabUpdate.AgentData.AgentID != AgentId)
6955 return true;
6956 }
6957 #endregion
6958
6959 MoveObject handlerGrabUpdate = OnGrabUpdate;
6960
6961 if (handlerGrabUpdate != null)
6962 {
6963 List<SurfaceTouchEventArgs> touchArgs = new List<SurfaceTouchEventArgs>();
6964 if ((grabUpdate.SurfaceInfo != null) && (grabUpdate.SurfaceInfo.Length > 0))
6965 {
6966 foreach (ObjectGrabUpdatePacket.SurfaceInfoBlock surfaceInfo in grabUpdate.SurfaceInfo)
6967 {
6968 SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs();
6969 arg.Binormal = surfaceInfo.Binormal;
6970 arg.FaceIndex = surfaceInfo.FaceIndex;
6971 arg.Normal = surfaceInfo.Normal;
6972 arg.Position = surfaceInfo.Position;
6973 arg.STCoord = surfaceInfo.STCoord;
6974 arg.UVCoord = surfaceInfo.UVCoord;
6975 touchArgs.Add(arg);
6976 }
6977 }
6978 handlerGrabUpdate(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial,
6979 grabUpdate.ObjectData.GrabPosition, this, touchArgs);
6980 }
6981 return true;
6982 }
6983
6984 private bool HandleObjectDeGrab(IClientAPI sender, Packet Pack)
6985 {
6986 ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack;
6987
6988 #region Packet Session and User Check
6989 if (m_checkPackets)
6990 {
6991 if (deGrab.AgentData.SessionID != SessionId ||
6992 deGrab.AgentData.AgentID != AgentId)
6993 return true;
6994 }
6995 #endregion
6996
6997 DeGrabObject handlerDeGrabObject = OnDeGrabObject;
6998 if (handlerDeGrabObject != null)
6999 {
7000 List<SurfaceTouchEventArgs> touchArgs = new List<SurfaceTouchEventArgs>();
7001 if ((deGrab.SurfaceInfo != null) && (deGrab.SurfaceInfo.Length > 0))
7002 {
7003 foreach (ObjectDeGrabPacket.SurfaceInfoBlock surfaceInfo in deGrab.SurfaceInfo)
7004 {
7005 SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs();
7006 arg.Binormal = surfaceInfo.Binormal;
7007 arg.FaceIndex = surfaceInfo.FaceIndex;
7008 arg.Normal = surfaceInfo.Normal;
7009 arg.Position = surfaceInfo.Position;
7010 arg.STCoord = surfaceInfo.STCoord;
7011 arg.UVCoord = surfaceInfo.UVCoord;
7012 touchArgs.Add(arg);
7013 }
7014 }
7015 handlerDeGrabObject(deGrab.ObjectData.LocalID, this, touchArgs);
7016 }
7017 return true;
7018 }
7019
7020 private bool HandleObjectSpinStart(IClientAPI sender, Packet Pack)
7021 {
7022 //m_log.Warn("[CLIENT]: unhandled ObjectSpinStart packet");
7023 ObjectSpinStartPacket spinStart = (ObjectSpinStartPacket)Pack;
7024
7025 #region Packet Session and User Check
7026 if (m_checkPackets)
7027 {
7028 if (spinStart.AgentData.SessionID != SessionId ||
7029 spinStart.AgentData.AgentID != AgentId)
7030 return true;
7031 }
7032 #endregion
7033
7034 SpinStart handlerSpinStart = OnSpinStart;
7035 if (handlerSpinStart != null)
7036 {
7037 handlerSpinStart(spinStart.ObjectData.ObjectID, this);
7038 }
7039 return true;
7040 }
7041
7042 private bool HandleObjectSpinUpdate(IClientAPI sender, Packet Pack)
7043 {
7044 //m_log.Warn("[CLIENT]: unhandled ObjectSpinUpdate packet");
7045 ObjectSpinUpdatePacket spinUpdate = (ObjectSpinUpdatePacket)Pack;
7046
7047 #region Packet Session and User Check
7048 if (m_checkPackets)
7049 {
7050 if (spinUpdate.AgentData.SessionID != SessionId ||
7051 spinUpdate.AgentData.AgentID != AgentId)
7052 return true;
7053 }
7054 #endregion
7055
7056 Vector3 axis;
7057 float angle;
7058 spinUpdate.ObjectData.Rotation.GetAxisAngle(out axis, out angle);
7059 //m_log.Warn("[CLIENT]: ObjectSpinUpdate packet rot axis:" + axis + " angle:" + angle);
7060
7061 SpinObject handlerSpinUpdate = OnSpinUpdate;
7062 if (handlerSpinUpdate != null)
7063 {
7064 handlerSpinUpdate(spinUpdate.ObjectData.ObjectID, spinUpdate.ObjectData.Rotation, this);
7065 }
7066 return true;
7067 }
7068
7069 private bool HandleObjectSpinStop(IClientAPI sender, Packet Pack)
7070 {
7071 //m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet");
7072 ObjectSpinStopPacket spinStop = (ObjectSpinStopPacket)Pack;
7073
7074 #region Packet Session and User Check
7075 if (m_checkPackets)
7076 {
7077 if (spinStop.AgentData.SessionID != SessionId ||
7078 spinStop.AgentData.AgentID != AgentId)
7079 return true;
7080 }
7081 #endregion
7082
7083 SpinStop handlerSpinStop = OnSpinStop;
7084 if (handlerSpinStop != null)
7085 {
7086 handlerSpinStop(spinStop.ObjectData.ObjectID, this);
7087 }
7088 return true;
7089 }
7090
7091 private bool HandleObjectDescription(IClientAPI sender, Packet Pack)
7092 {
7093 ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack;
7094
7095 #region Packet Session and User Check
7096 if (m_checkPackets)
7097 {
7098 if (objDes.AgentData.SessionID != SessionId ||
7099 objDes.AgentData.AgentID != AgentId)
7100 return true;
7101 }
7102 #endregion
7103
7104 GenericCall7 handlerObjectDescription = null;
7105
7106 for (int i = 0; i < objDes.ObjectData.Length; i++)
7107 {
7108 handlerObjectDescription = OnObjectDescription;
7109 if (handlerObjectDescription != null)
7110 {
7111 handlerObjectDescription(this, objDes.ObjectData[i].LocalID,
7112 Util.FieldToString(objDes.ObjectData[i].Description));
7113 }
7114 }
7115 return true;
7116 }
7117
7118 private bool HandleObjectName(IClientAPI sender, Packet Pack)
7119 {
7120 ObjectNamePacket objName = (ObjectNamePacket)Pack;
7121
7122 #region Packet Session and User Check
7123 if (m_checkPackets)
7124 {
7125 if (objName.AgentData.SessionID != SessionId ||
7126 objName.AgentData.AgentID != AgentId)
7127 return true;
7128 }
7129 #endregion
7130
7131 GenericCall7 handlerObjectName = null;
7132 for (int i = 0; i < objName.ObjectData.Length; i++)
7133 {
7134 handlerObjectName = OnObjectName;
7135 if (handlerObjectName != null)
7136 {
7137 handlerObjectName(this, objName.ObjectData[i].LocalID,
7138 Util.FieldToString(objName.ObjectData[i].Name));
7139 }
7140 }
7141 return true;
7142 }
7143
7144 private bool HandleObjectPermissions(IClientAPI sender, Packet Pack)
7145 {
7146 if (OnObjectPermissions != null)
7147 {
7148 ObjectPermissionsPacket newobjPerms = (ObjectPermissionsPacket)Pack;
7149
7150 #region Packet Session and User Check
7151 if (m_checkPackets)
7152 {
7153 if (newobjPerms.AgentData.SessionID != SessionId ||
7154 newobjPerms.AgentData.AgentID != AgentId)
7155 return true;
7156 }
7157 #endregion
7158
7159 UUID AgentID = newobjPerms.AgentData.AgentID;
7160 UUID SessionID = newobjPerms.AgentData.SessionID;
7161
7162 ObjectPermissions handlerObjectPermissions = null;
7163
7164 for (int i = 0; i < newobjPerms.ObjectData.Length; i++)
7165 {
7166 ObjectPermissionsPacket.ObjectDataBlock permChanges = newobjPerms.ObjectData[i];
7167
7168 byte field = permChanges.Field;
7169 uint localID = permChanges.ObjectLocalID;
7170 uint mask = permChanges.Mask;
7171 byte set = permChanges.Set;
7172
7173 handlerObjectPermissions = OnObjectPermissions;
7174
7175 if (handlerObjectPermissions != null)
7176 handlerObjectPermissions(this, AgentID, SessionID, field, localID, mask, set);
7177 }
7178 }
7179
7180 // Here's our data,
7181 // PermField contains the field the info goes into
7182 // PermField determines which mask we're changing
7183 //
7184 // chmask is the mask of the change
7185 // setTF is whether we're adding it or taking it away
7186 //
7187 // objLocalID is the localID of the object.
7188
7189 // Unfortunately, we have to pass the event the packet because objData is an array
7190 // That means multiple object perms may be updated in a single packet.
7191
7192 return true;
7193 }
7194
7195 private bool HandleUndo(IClientAPI sender, Packet Pack)
7196 {
7197 UndoPacket undoitem = (UndoPacket)Pack;
7198
7199 #region Packet Session and User Check
7200 if (m_checkPackets)
7201 {
7202 if (undoitem.AgentData.SessionID != SessionId ||
7203 undoitem.AgentData.AgentID != AgentId)
7204 return true;
7205 }
7206 #endregion
7207
7208 if (undoitem.ObjectData.Length > 0)
7209 {
7210 for (int i = 0; i < undoitem.ObjectData.Length; i++)
7211 {
7212 UUID objiD = undoitem.ObjectData[i].ObjectID;
7213 AgentSit handlerOnUndo = OnUndo;
7214 if (handlerOnUndo != null)
7215 {
7216 handlerOnUndo(this, objiD);
7217 }
7218
7219 }
7220 }
7221 return true;
7222 }
7223
7224 private bool HandleLandUndo(IClientAPI sender, Packet Pack)
7225 {
7226 UndoLandPacket undolanditem = (UndoLandPacket)Pack;
7227
7228 #region Packet Session and User Check
7229 if (m_checkPackets)
7230 {
7231 if (undolanditem.AgentData.SessionID != SessionId ||
7232 undolanditem.AgentData.AgentID != AgentId)
7233 return true;
7234 }
7235 #endregion
7236
7237 LandUndo handlerOnUndo = OnLandUndo;
7238 if (handlerOnUndo != null)
7239 {
7240 handlerOnUndo(this);
7241 }
7242 return true;
7243 }
7244
7245 private bool HandleRedo(IClientAPI sender, Packet Pack)
7246 {
7247 RedoPacket redoitem = (RedoPacket)Pack;
7248
7249 #region Packet Session and User Check
7250 if (m_checkPackets)
7251 {
7252 if (redoitem.AgentData.SessionID != SessionId ||
7253 redoitem.AgentData.AgentID != AgentId)
7254 return true;
7255 }
7256 #endregion
7257
7258 if (redoitem.ObjectData.Length > 0)
7259 {
7260 for (int i = 0; i < redoitem.ObjectData.Length; i++)
7261 {
7262 UUID objiD = redoitem.ObjectData[i].ObjectID;
7263 AgentSit handlerOnRedo = OnRedo;
7264 if (handlerOnRedo != null)
7265 {
7266 handlerOnRedo(this, objiD);
7267 }
7268
7269 }
7270 }
7271 return true;
7272 }
7273
7274 private bool HandleObjectDuplicateOnRay(IClientAPI sender, Packet Pack)
7275 {
7276 ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack;
7277
7278 #region Packet Session and User Check
7279 if (m_checkPackets)
7280 {
7281 if (dupeOnRay.AgentData.SessionID != SessionId ||
7282 dupeOnRay.AgentData.AgentID != AgentId)
7283 return true;
7284 }
7285 #endregion
7286
7287 ObjectDuplicateOnRay handlerObjectDuplicateOnRay = null;
7288
7289 for (int i = 0; i < dupeOnRay.ObjectData.Length; i++)
7290 {
7291 handlerObjectDuplicateOnRay = OnObjectDuplicateOnRay;
7292 if (handlerObjectDuplicateOnRay != null)
7293 {
7294 handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags,
7295 AgentId, m_activeGroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd,
7296 dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection,
7297 dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates);
7298 }
7299 }
7300
7301 return true;
7302 }
7303
7304 private bool HandleRequestObjectPropertiesFamily(IClientAPI sender, Packet Pack)
7305 {
7306 //This powers the little tooltip that appears when you move your mouse over an object
7307 RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack;
7308
7309 #region Packet Session and User Check
7310 if (m_checkPackets)
7311 {
7312 if (packToolTip.AgentData.SessionID != SessionId ||
7313 packToolTip.AgentData.AgentID != AgentId)
7314 return true;
7315 }
7316 #endregion
7317
7318 RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData;
7319
7320 RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily;
7321
7322 if (handlerRequestObjectPropertiesFamily != null)
7323 {
7324 handlerRequestObjectPropertiesFamily(this, m_agentId, packObjBlock.RequestFlags,
7325 packObjBlock.ObjectID);
7326 }
7327
7328 return true;
7329 }
7330
7331 private bool HandleObjectIncludeInSearch(IClientAPI sender, Packet Pack)
7332 {
7333 //This lets us set objects to appear in search (stuff like DataSnapshot, etc)
7334 ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack;
7335 ObjectIncludeInSearch handlerObjectIncludeInSearch = null;
7336
7337 #region Packet Session and User Check
7338 if (m_checkPackets)
7339 {
7340 if (packInSearch.AgentData.SessionID != SessionId ||
7341 packInSearch.AgentData.AgentID != AgentId)
7342 return true;
7343 }
7344 #endregion
7345
7346 foreach (ObjectIncludeInSearchPacket.ObjectDataBlock objData in packInSearch.ObjectData)
7347 {
7348 bool inSearch = objData.IncludeInSearch;
7349 uint localID = objData.ObjectLocalID;
7350
7351 handlerObjectIncludeInSearch = OnObjectIncludeInSearch;
7352
7353 if (handlerObjectIncludeInSearch != null)
7354 {
7355 handlerObjectIncludeInSearch(this, inSearch, localID);
7356 }
7357 }
7358 return true;
7359 }
7360
7361 private bool HandleScriptAnswerYes(IClientAPI sender, Packet Pack)
7362 {
7363 ScriptAnswerYesPacket scriptAnswer = (ScriptAnswerYesPacket)Pack;
7364
7365 #region Packet Session and User Check
7366 if (m_checkPackets)
7367 {
7368 if (scriptAnswer.AgentData.SessionID != SessionId ||
7369 scriptAnswer.AgentData.AgentID != AgentId)
7370 return true;
7371 }
7372 #endregion
7373
7374 ScriptAnswer handlerScriptAnswer = OnScriptAnswer;
7375 if (handlerScriptAnswer != null)
7376 {
7377 handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions);
7378 }
7379 return true;
7380 }
7381
7382 private bool HandleObjectClickAction(IClientAPI sender, Packet Pack)
7383 {
7384 ObjectClickActionPacket ocpacket = (ObjectClickActionPacket)Pack;
7385
7386 #region Packet Session and User Check
7387 if (m_checkPackets)
7388 {
7389 if (ocpacket.AgentData.SessionID != SessionId ||
7390 ocpacket.AgentData.AgentID != AgentId)
7391 return true;
7392 }
7393 #endregion
7394
7395 GenericCall7 handlerObjectClickAction = OnObjectClickAction;
7396 if (handlerObjectClickAction != null)
7397 {
7398 foreach (ObjectClickActionPacket.ObjectDataBlock odata in ocpacket.ObjectData)
7399 {
7400 byte action = odata.ClickAction;
7401 uint localID = odata.ObjectLocalID;
7402 handlerObjectClickAction(this, localID, action.ToString());
7403 }
7404 }
7405 return true;
7406 }
7407
7408 private bool HandleObjectMaterial(IClientAPI sender, Packet Pack)
7409 {
7410 ObjectMaterialPacket ompacket = (ObjectMaterialPacket)Pack;
7411
7412 #region Packet Session and User Check
7413 if (m_checkPackets)
7414 {
7415 if (ompacket.AgentData.SessionID != SessionId ||
7416 ompacket.AgentData.AgentID != AgentId)
7417 return true;
7418 }
7419 #endregion
7420
7421 GenericCall7 handlerObjectMaterial = OnObjectMaterial;
7422 if (handlerObjectMaterial != null)
7423 {
7424 foreach (ObjectMaterialPacket.ObjectDataBlock odata in ompacket.ObjectData)
7425 {
7426 byte material = odata.Material;
7427 uint localID = odata.ObjectLocalID;
7428 handlerObjectMaterial(this, localID, material.ToString());
7429 }
7430 }
7431 return true;
7432 }
7433
7434 #endregion Objects/m_sceneObjects
7435
7436 #region Inventory/Asset/Other related packets
7437
7438 private bool HandleRequestImage(IClientAPI sender, Packet Pack)
7439 {
7440 RequestImagePacket imageRequest = (RequestImagePacket)Pack;
7441 //m_log.Debug("image request: " + Pack.ToString());
7442
7443 #region Packet Session and User Check
7444 if (m_checkPackets)
7445 {
7446 if (imageRequest.AgentData.SessionID != SessionId ||
7447 imageRequest.AgentData.AgentID != AgentId)
7448 return true;
7449 }
7450 #endregion
7451
7452 //handlerTextureRequest = null;
7453 for (int i = 0; i < imageRequest.RequestImage.Length; i++)
7454 {
7455 TextureRequestArgs args = new TextureRequestArgs();
7456
7457 RequestImagePacket.RequestImageBlock block = imageRequest.RequestImage[i];
7458
7459 args.RequestedAssetID = block.Image;
7460 args.DiscardLevel = block.DiscardLevel;
7461 args.PacketNumber = block.Packet;
7462 args.Priority = block.DownloadPriority;
7463 args.requestSequence = imageRequest.Header.Sequence;
7464
7465 // NOTE: This is not a built in part of the LLUDP protocol, but we double the
7466 // priority of avatar textures to get avatars rezzing in faster than the
7467 // surrounding scene
7468 if ((ImageType)block.Type == ImageType.Baked)
7469 args.Priority *= 2.0f;
7470
7471 // in the end, we null this, so we have to check if it's null
7472 if (m_imageManager != null)
7473 {
7474 m_imageManager.EnqueueReq(args);
7475 }
7476 }
7477 return true;
7478 }
7479
7480 /// <summary>
7481 /// This is the entry point for the UDP route by which the client can retrieve asset data. If the request
7482 /// is successful then a TransferInfo packet will be sent back, followed by one or more TransferPackets
7483 /// </summary>
7484 /// <param name="sender"></param>
7485 /// <param name="Pack"></param>
7486 /// <returns>This parameter may be ignored since we appear to return true whatever happens</returns>
7487 private bool HandleTransferRequest(IClientAPI sender, Packet Pack)
7488 {
7489 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request");
7490
7491 TransferRequestPacket transfer = (TransferRequestPacket)Pack;
7492 //m_log.Debug("Transfer Request: " + transfer.ToString());
7493 // Validate inventory transfers
7494 // Has to be done here, because AssetCache can't do it
7495 //
7496 UUID taskID = UUID.Zero;
7497 if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
7498 {
7499 taskID = new UUID(transfer.TransferInfo.Params, 48);
7500 UUID itemID = new UUID(transfer.TransferInfo.Params, 64);
7501 UUID requestID = new UUID(transfer.TransferInfo.Params, 80);
7502
7503// m_log.DebugFormat(
7504// "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}",
7505// requestID, itemID, taskID, Name);
7506
7507 if (!(((Scene)m_scene).Permissions.BypassPermissions()))
7508 {
7509 if (taskID != UUID.Zero) // Prim
7510 {
7511 SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID);
7512
7513 if (part == null)
7514 {
7515 m_log.WarnFormat(
7516 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist",
7517 Name, requestID, itemID, taskID);
7518 return true;
7519 }
7520
7521 TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID);
7522 if (tii == null)
7523 {
7524 m_log.WarnFormat(
7525 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist",
7526 Name, requestID, itemID, taskID);
7527 return true;
7528 }
7529
7530 if (tii.Type == (int)AssetType.LSLText)
7531 {
7532 if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId))
7533 return true;
7534 }
7535 else if (tii.Type == (int)AssetType.Notecard)
7536 {
7537 if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId))
7538 return true;
7539 }
7540 else
7541 {
7542 // TODO: Change this code to allow items other than notecards and scripts to be successfully
7543 // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule
7544 if (part.OwnerID != AgentId)
7545 {
7546 m_log.WarnFormat(
7547 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}",
7548 Name, requestID, itemID, taskID, part.OwnerID);
7549 return true;
7550 }
7551
7552 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
7553 {
7554 m_log.WarnFormat(
7555 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set",
7556 Name, requestID, itemID, taskID);
7557 return true;
7558 }
7559
7560 if (tii.OwnerID != AgentId)
7561 {
7562 m_log.WarnFormat(
7563 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}",
7564 Name, requestID, itemID, taskID, tii.OwnerID);
7565 return true;
7566 }
7567
7568 if ((
7569 tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
7570 != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
7571 {
7572 m_log.WarnFormat(
7573 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer",
7574 Name, requestID, itemID, taskID);
7575 return true;
7576 }
7577
7578 if (tii.AssetID != requestID)
7579 {
7580 m_log.WarnFormat(
7581 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}",
7582 Name, requestID, itemID, taskID, tii.AssetID);
7583 return true;
7584 }
7585 }
7586 }
7587 else // Agent
7588 {
7589 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
7590 if (invAccess != null)
7591 {
7592 if (!invAccess.GetAgentInventoryItem(this, itemID, requestID))
7593 return false;
7594
7595 }
7596 else
7597 return false;
7598
7599 }
7600 }
7601 }
7602
7603 MakeAssetRequest(transfer, taskID);
7604
7605 return true;
7606 }
7607
7608 private bool HandleAssetUploadRequest(IClientAPI sender, Packet Pack)
7609 {
7610 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
7611
7612
7613 // m_log.Debug("upload request " + request.ToString());
7614 // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString());
7615 UUID temp = UUID.Combine(request.AssetBlock.TransactionID, SecureSessionId);
7616
7617 UDPAssetUploadRequest handlerAssetUploadRequest = OnAssetUploadRequest;
7618
7619 if (handlerAssetUploadRequest != null)
7620 {
7621 handlerAssetUploadRequest(this, temp,
7622 request.AssetBlock.TransactionID, request.AssetBlock.Type,
7623 request.AssetBlock.AssetData, request.AssetBlock.StoreLocal,
7624 request.AssetBlock.Tempfile);
7625 }
7626 return true;
7627 }
7628
7629 private bool HandleRequestXfer(IClientAPI sender, Packet Pack)
7630 {
7631 RequestXferPacket xferReq = (RequestXferPacket)Pack;
7632
7633 RequestXfer handlerRequestXfer = OnRequestXfer;
7634
7635 if (handlerRequestXfer != null)
7636 {
7637 handlerRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename));
7638 }
7639 return true;
7640 }
7641
7642 private bool HandleSendXferPacket(IClientAPI sender, Packet Pack)
7643 {
7644 SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack;
7645
7646 XferReceive handlerXferReceive = OnXferReceive;
7647 if (handlerXferReceive != null)
7648 {
7649 handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data);
7650 }
7651 return true;
7652 }
7653
7654 private bool HandleConfirmXferPacket(IClientAPI sender, Packet Pack)
7655 {
7656 ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack;
7657
7658 ConfirmXfer handlerConfirmXfer = OnConfirmXfer;
7659 if (handlerConfirmXfer != null)
7660 {
7661 handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet);
7662 }
7663 return true;
7664 }
7665
7666 private bool HandleAbortXfer(IClientAPI sender, Packet Pack)
7667 {
7668 AbortXferPacket abortXfer = (AbortXferPacket)Pack;
7669 AbortXfer handlerAbortXfer = OnAbortXfer;
7670 if (handlerAbortXfer != null)
7671 {
7672 handlerAbortXfer(this, abortXfer.XferID.ID);
7673 }
7674
7675 return true;
7676 }
7677
7678 private bool HandleCreateInventoryFolder(IClientAPI sender, Packet Pack)
7679 {
7680 CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack;
7681
7682 #region Packet Session and User Check
7683 if (m_checkPackets)
7684 {
7685 if (invFolder.AgentData.SessionID != SessionId ||
7686 invFolder.AgentData.AgentID != AgentId)
7687 return true;
7688 }
7689 #endregion
7690
7691 CreateInventoryFolder handlerCreateInventoryFolder = OnCreateNewInventoryFolder;
7692 if (handlerCreateInventoryFolder != null)
7693 {
7694 handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID,
7695 (ushort)invFolder.FolderData.Type,
7696 Util.FieldToString(invFolder.FolderData.Name),
7697 invFolder.FolderData.ParentID);
7698 }
7699 return true;
7700 }
7701
7702 private bool HandleUpdateInventoryFolder(IClientAPI sender, Packet Pack)
7703 {
7704 if (OnUpdateInventoryFolder != null)
7705 {
7706 UpdateInventoryFolderPacket invFolderx = (UpdateInventoryFolderPacket)Pack;
7707
7708 #region Packet Session and User Check
7709 if (m_checkPackets)
7710 {
7711 if (invFolderx.AgentData.SessionID != SessionId ||
7712 invFolderx.AgentData.AgentID != AgentId)
7713 return true;
7714 }
7715 #endregion
7716
7717 UpdateInventoryFolder handlerUpdateInventoryFolder = null;
7718
7719 for (int i = 0; i < invFolderx.FolderData.Length; i++)
7720 {
7721 handlerUpdateInventoryFolder = OnUpdateInventoryFolder;
7722 if (handlerUpdateInventoryFolder != null)
7723 {
7724 OnUpdateInventoryFolder(this, invFolderx.FolderData[i].FolderID,
7725 (ushort)invFolderx.FolderData[i].Type,
7726 Util.FieldToString(invFolderx.FolderData[i].Name),
7727 invFolderx.FolderData[i].ParentID);
7728 }
7729 }
7730 }
7731 return true;
7732 }
7733
7734 private bool HandleMoveInventoryFolder(IClientAPI sender, Packet Pack)
7735 {
7736 if (OnMoveInventoryFolder != null)
7737 {
7738 MoveInventoryFolderPacket invFoldery = (MoveInventoryFolderPacket)Pack;
7739
7740 #region Packet Session and User Check
7741 if (m_checkPackets)
7742 {
7743 if (invFoldery.AgentData.SessionID != SessionId ||
7744 invFoldery.AgentData.AgentID != AgentId)
7745 return true;
7746 }
7747 #endregion
7748
7749 MoveInventoryFolder handlerMoveInventoryFolder = null;
7750
7751 for (int i = 0; i < invFoldery.InventoryData.Length; i++)
7752 {
7753 handlerMoveInventoryFolder = OnMoveInventoryFolder;
7754 if (handlerMoveInventoryFolder != null)
7755 {
7756 OnMoveInventoryFolder(this, invFoldery.InventoryData[i].FolderID,
7757 invFoldery.InventoryData[i].ParentID);
7758 }
7759 }
7760 }
7761 return true;
7762 }
7763
7764 private bool HandleCreateInventoryItem(IClientAPI sender, Packet Pack)
7765 {
7766 CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack;
7767
7768 #region Packet Session and User Check
7769 if (m_checkPackets)
7770 {
7771 if (createItem.AgentData.SessionID != SessionId ||
7772 createItem.AgentData.AgentID != AgentId)
7773 return true;
7774 }
7775 #endregion
7776
7777 CreateNewInventoryItem handlerCreateNewInventoryItem = OnCreateNewInventoryItem;
7778 if (handlerCreateNewInventoryItem != null)
7779 {
7780 handlerCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID,
7781 createItem.InventoryBlock.FolderID,
7782 createItem.InventoryBlock.CallbackID,
7783 Util.FieldToString(createItem.InventoryBlock.Description),
7784 Util.FieldToString(createItem.InventoryBlock.Name),
7785 createItem.InventoryBlock.InvType,
7786 createItem.InventoryBlock.Type,
7787 createItem.InventoryBlock.WearableType,
7788 createItem.InventoryBlock.NextOwnerMask,
7789 Util.UnixTimeSinceEpoch());
7790 }
7791 return true;
7792 }
7793
7794 private bool HandleLinkInventoryItem(IClientAPI sender, Packet Pack)
7795 {
7796 LinkInventoryItemPacket createLink = (LinkInventoryItemPacket)Pack;
7797
7798 #region Packet Session and User Check
7799 if (m_checkPackets)
7800 {
7801 if (createLink.AgentData.SessionID != SessionId ||
7802 createLink.AgentData.AgentID != AgentId)
7803 return true;
7804 }
7805 #endregion
7806
7807 LinkInventoryItem linkInventoryItem = OnLinkInventoryItem;
7808
7809 if (linkInventoryItem != null)
7810 {
7811 linkInventoryItem(
7812 this,
7813 createLink.InventoryBlock.TransactionID,
7814 createLink.InventoryBlock.FolderID,
7815 createLink.InventoryBlock.CallbackID,
7816 Util.FieldToString(createLink.InventoryBlock.Description),
7817 Util.FieldToString(createLink.InventoryBlock.Name),
7818 createLink.InventoryBlock.InvType,
7819 createLink.InventoryBlock.Type,
7820 createLink.InventoryBlock.OldItemID);
7821 }
7822
7823 return true;
7824 }
7825
7826 private bool HandleFetchInventory(IClientAPI sender, Packet Pack)
7827 {
7828 if (OnFetchInventory != null)
7829 {
7830 FetchInventoryPacket FetchInventoryx = (FetchInventoryPacket)Pack;
7831
7832 #region Packet Session and User Check
7833 if (m_checkPackets)
7834 {
7835 if (FetchInventoryx.AgentData.SessionID != SessionId ||
7836 FetchInventoryx.AgentData.AgentID != AgentId)
7837 return true;
7838 }
7839 #endregion
7840
7841 FetchInventory handlerFetchInventory = null;
7842
7843 for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++)
7844 {
7845 handlerFetchInventory = OnFetchInventory;
7846
7847 if (handlerFetchInventory != null)
7848 {
7849 OnFetchInventory(this, FetchInventoryx.InventoryData[i].ItemID,
7850 FetchInventoryx.InventoryData[i].OwnerID);
7851 }
7852 }
7853 }
7854 return true;
7855 }
7856
7857 private bool HandleFetchInventoryDescendents(IClientAPI sender, Packet Pack)
7858 {
7859 FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack;
7860
7861 #region Packet Session and User Check
7862 if (m_checkPackets)
7863 {
7864 if (Fetch.AgentData.SessionID != SessionId ||
7865 Fetch.AgentData.AgentID != AgentId)
7866 return true;
7867 }
7868 #endregion
7869
7870 FetchInventoryDescendents handlerFetchInventoryDescendents = OnFetchInventoryDescendents;
7871 if (handlerFetchInventoryDescendents != null)
7872 {
7873 handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID,
7874 Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems,
7875 Fetch.InventoryData.SortOrder);
7876 }
7877 return true;
7878 }
7879
7880 private bool HandlePurgeInventoryDescendents(IClientAPI sender, Packet Pack)
7881 {
7882 PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack;
7883
7884 #region Packet Session and User Check
7885 if (m_checkPackets)
7886 {
7887 if (Purge.AgentData.SessionID != SessionId ||
7888 Purge.AgentData.AgentID != AgentId)
7889 return true;
7890 }
7891 #endregion
7892
7893 PurgeInventoryDescendents handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents;
7894 if (handlerPurgeInventoryDescendents != null)
7895 {
7896 handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID);
7897 }
7898 return true;
7899 }
7900
7901 private bool HandleUpdateInventoryItem(IClientAPI sender, Packet Pack)
7902 {
7903 UpdateInventoryItemPacket inventoryItemUpdate = (UpdateInventoryItemPacket)Pack;
7904
7905 #region Packet Session and User Check
7906 if (m_checkPackets)
7907 {
7908 if (inventoryItemUpdate.AgentData.SessionID != SessionId ||
7909 inventoryItemUpdate.AgentData.AgentID != AgentId)
7910 return true;
7911 }
7912 #endregion
7913
7914 if (OnUpdateInventoryItem != null)
7915 {
7916 UpdateInventoryItem handlerUpdateInventoryItem = null;
7917 for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++)
7918 {
7919 handlerUpdateInventoryItem = OnUpdateInventoryItem;
7920
7921 if (handlerUpdateInventoryItem != null)
7922 {
7923 InventoryItemBase itemUpd = new InventoryItemBase();
7924 itemUpd.ID = inventoryItemUpdate.InventoryData[i].ItemID;
7925 itemUpd.Name = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Name);
7926 itemUpd.Description = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Description);
7927 itemUpd.GroupID = inventoryItemUpdate.InventoryData[i].GroupID;
7928 itemUpd.GroupOwned = inventoryItemUpdate.InventoryData[i].GroupOwned;
7929 itemUpd.GroupPermissions = inventoryItemUpdate.InventoryData[i].GroupMask;
7930 itemUpd.NextPermissions = inventoryItemUpdate.InventoryData[i].NextOwnerMask;
7931 itemUpd.EveryOnePermissions = inventoryItemUpdate.InventoryData[i].EveryoneMask;
7932 itemUpd.CreationDate = inventoryItemUpdate.InventoryData[i].CreationDate;
7933 itemUpd.Folder = inventoryItemUpdate.InventoryData[i].FolderID;
7934 itemUpd.InvType = inventoryItemUpdate.InventoryData[i].InvType;
7935 itemUpd.SalePrice = inventoryItemUpdate.InventoryData[i].SalePrice;
7936 itemUpd.SaleType = inventoryItemUpdate.InventoryData[i].SaleType;
7937 itemUpd.Flags = inventoryItemUpdate.InventoryData[i].Flags;
7938
7939 OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID,
7940 inventoryItemUpdate.InventoryData[i].ItemID,
7941 itemUpd);
7942 }
7943 }
7944 }
7945 return true;
7946 }
7947
7948 private bool HandleCopyInventoryItem(IClientAPI sender, Packet Pack)
7949 {
7950 CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack;
7951
7952 #region Packet Session and User Check
7953 if (m_checkPackets)
7954 {
7955 if (copyitem.AgentData.SessionID != SessionId ||
7956 copyitem.AgentData.AgentID != AgentId)
7957 return true;
7958 }
7959 #endregion
7960
7961 CopyInventoryItem handlerCopyInventoryItem = null;
7962 if (OnCopyInventoryItem != null)
7963 {
7964 foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData)
7965 {
7966 handlerCopyInventoryItem = OnCopyInventoryItem;
7967 if (handlerCopyInventoryItem != null)
7968 {
7969 handlerCopyInventoryItem(this, datablock.CallbackID, datablock.OldAgentID,
7970 datablock.OldItemID, datablock.NewFolderID,
7971 Util.FieldToString(datablock.NewName));
7972 }
7973 }
7974 }
7975 return true;
7976 }
7977
7978 private bool HandleMoveInventoryItem(IClientAPI sender, Packet Pack)
7979 {
7980 MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack;
7981
7982 #region Packet Session and User Check
7983 if (m_checkPackets)
7984 {
7985 if (moveitem.AgentData.SessionID != SessionId ||
7986 moveitem.AgentData.AgentID != AgentId)
7987 return true;
7988 }
7989 #endregion
7990
7991 if (OnMoveInventoryItem != null)
7992 {
7993 MoveInventoryItem handlerMoveInventoryItem = null;
7994 InventoryItemBase itm = null;
7995 List<InventoryItemBase> items = new List<InventoryItemBase>();
7996 foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData)
7997 {
7998 itm = new InventoryItemBase(datablock.ItemID, AgentId);
7999 itm.Folder = datablock.FolderID;
8000 itm.Name = Util.FieldToString(datablock.NewName);
8001 // weird, comes out as empty string
8002 //m_log.DebugFormat("[XXX] new name: {0}", itm.Name);
8003 items.Add(itm);
8004 }
8005 handlerMoveInventoryItem = OnMoveInventoryItem;
8006 if (handlerMoveInventoryItem != null)
8007 {
8008 handlerMoveInventoryItem(this, items);
8009 }
8010 }
8011 return true;
8012 }
8013
8014 private bool HandleRemoveInventoryItem(IClientAPI sender, Packet Pack)
8015 {
8016 RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack;
8017
8018 #region Packet Session and User Check
8019 if (m_checkPackets)
8020 {
8021 if (removeItem.AgentData.SessionID != SessionId ||
8022 removeItem.AgentData.AgentID != AgentId)
8023 return true;
8024 }
8025 #endregion
8026
8027 if (OnRemoveInventoryItem != null)
8028 {
8029 RemoveInventoryItem handlerRemoveInventoryItem = null;
8030 List<UUID> uuids = new List<UUID>();
8031 foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData)
8032 {
8033 uuids.Add(datablock.ItemID);
8034 }
8035 handlerRemoveInventoryItem = OnRemoveInventoryItem;
8036 if (handlerRemoveInventoryItem != null)
8037 {
8038 handlerRemoveInventoryItem(this, uuids);
8039 }
8040
8041 }
8042 return true;
8043 }
8044
8045 private bool HandleRemoveInventoryFolder(IClientAPI sender, Packet Pack)
8046 {
8047 RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack;
8048
8049 #region Packet Session and User Check
8050 if (m_checkPackets)
8051 {
8052 if (removeFolder.AgentData.SessionID != SessionId ||
8053 removeFolder.AgentData.AgentID != AgentId)
8054 return true;
8055 }
8056 #endregion
8057
8058 if (OnRemoveInventoryFolder != null)
8059 {
8060 RemoveInventoryFolder handlerRemoveInventoryFolder = null;
8061 List<UUID> uuids = new List<UUID>();
8062 foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData)
8063 {
8064 uuids.Add(datablock.FolderID);
8065 }
8066 handlerRemoveInventoryFolder = OnRemoveInventoryFolder;
8067 if (handlerRemoveInventoryFolder != null)
8068 {
8069 handlerRemoveInventoryFolder(this, uuids);
8070 }
8071 }
8072 return true;
8073 }
8074
8075 private bool HandleRemoveInventoryObjects(IClientAPI sender, Packet Pack)
8076 {
8077 RemoveInventoryObjectsPacket removeObject = (RemoveInventoryObjectsPacket)Pack;
8078 #region Packet Session and User Check
8079 if (m_checkPackets)
8080 {
8081 if (removeObject.AgentData.SessionID != SessionId ||
8082 removeObject.AgentData.AgentID != AgentId)
8083 return true;
8084 }
8085 #endregion
8086 if (OnRemoveInventoryFolder != null)
8087 {
8088 RemoveInventoryFolder handlerRemoveInventoryFolder = null;
8089 List<UUID> uuids = new List<UUID>();
8090 foreach (RemoveInventoryObjectsPacket.FolderDataBlock datablock in removeObject.FolderData)
8091 {
8092 uuids.Add(datablock.FolderID);
8093 }
8094 handlerRemoveInventoryFolder = OnRemoveInventoryFolder;
8095 if (handlerRemoveInventoryFolder != null)
8096 {
8097 handlerRemoveInventoryFolder(this, uuids);
8098 }
8099 }
8100
8101 if (OnRemoveInventoryItem != null)
8102 {
8103 RemoveInventoryItem handlerRemoveInventoryItem = null;
8104 List<UUID> uuids = new List<UUID>();
8105 foreach (RemoveInventoryObjectsPacket.ItemDataBlock datablock in removeObject.ItemData)
8106 {
8107 uuids.Add(datablock.ItemID);
8108 }
8109 handlerRemoveInventoryItem = OnRemoveInventoryItem;
8110 if (handlerRemoveInventoryItem != null)
8111 {
8112 handlerRemoveInventoryItem(this, uuids);
8113 }
8114 }
8115 return true;
8116 }
8117
8118 private bool HandleRequestTaskInventory(IClientAPI sender, Packet Pack)
8119 {
8120 RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack;
8121
8122 #region Packet Session and User Check
8123 if (m_checkPackets)
8124 {
8125 if (requesttask.AgentData.SessionID != SessionId ||
8126 requesttask.AgentData.AgentID != AgentId)
8127 return true;
8128 }
8129 #endregion
8130
8131 RequestTaskInventory handlerRequestTaskInventory = OnRequestTaskInventory;
8132 if (handlerRequestTaskInventory != null)
8133 {
8134 handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID);
8135 }
8136 return true;
8137 }
8138
8139 private bool HandleUpdateTaskInventory(IClientAPI sender, Packet Pack)
8140 {
8141 UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack;
8142
8143 #region Packet Session and User Check
8144 if (m_checkPackets)
8145 {
8146 if (updatetask.AgentData.SessionID != SessionId ||
8147 updatetask.AgentData.AgentID != AgentId)
8148 return true;
8149 }
8150 #endregion
8151
8152 if (OnUpdateTaskInventory != null)
8153 {
8154 if (updatetask.UpdateData.Key == 0)
8155 {
8156 UpdateTaskInventory handlerUpdateTaskInventory = OnUpdateTaskInventory;
8157 if (handlerUpdateTaskInventory != null)
8158 {
8159 TaskInventoryItem newTaskItem = new TaskInventoryItem();
8160 newTaskItem.ItemID = updatetask.InventoryData.ItemID;
8161 newTaskItem.ParentID = updatetask.InventoryData.FolderID;
8162 newTaskItem.CreatorID = updatetask.InventoryData.CreatorID;
8163 newTaskItem.OwnerID = updatetask.InventoryData.OwnerID;
8164 newTaskItem.GroupID = updatetask.InventoryData.GroupID;
8165 newTaskItem.BasePermissions = updatetask.InventoryData.BaseMask;
8166 newTaskItem.CurrentPermissions = updatetask.InventoryData.OwnerMask;
8167 newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask;
8168 newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask;
8169 newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask;
8170
8171 // Unused? Clicking share with group sets GroupPermissions instead, so perhaps this is something
8172 // different
8173 //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned;
8174 newTaskItem.Type = updatetask.InventoryData.Type;
8175 newTaskItem.InvType = updatetask.InventoryData.InvType;
8176 newTaskItem.Flags = updatetask.InventoryData.Flags;
8177 //newTaskItem.SaleType=updatetask.InventoryData.SaleType;
8178 //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;
8179 newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name);
8180 newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description);
8181 newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate;
8182 handlerUpdateTaskInventory(this, updatetask.InventoryData.TransactionID,
8183 newTaskItem, updatetask.UpdateData.LocalID);
8184 }
8185 }
8186 }
8187
8188 return true;
8189 }
8190
8191 private bool HandleRemoveTaskInventory(IClientAPI sender, Packet Pack)
8192 {
8193 RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack;
8194
8195 #region Packet Session and User Check
8196 if (m_checkPackets)
8197 {
8198 if (removeTask.AgentData.SessionID != SessionId ||
8199 removeTask.AgentData.AgentID != AgentId)
8200 return true;
8201 }
8202 #endregion
8203
8204 RemoveTaskInventory handlerRemoveTaskItem = OnRemoveTaskItem;
8205
8206 if (handlerRemoveTaskItem != null)
8207 {
8208 handlerRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID);
8209 }
8210
8211 return true;
8212 }
8213
8214 private bool HandleMoveTaskInventory(IClientAPI sender, Packet Pack)
8215 {
8216 MoveTaskInventoryPacket moveTaskInventoryPacket = (MoveTaskInventoryPacket)Pack;
8217
8218 #region Packet Session and User Check
8219 if (m_checkPackets)
8220 {
8221 if (moveTaskInventoryPacket.AgentData.SessionID != SessionId ||
8222 moveTaskInventoryPacket.AgentData.AgentID != AgentId)
8223 return true;
8224 }
8225 #endregion
8226
8227 MoveTaskInventory handlerMoveTaskItem = OnMoveTaskItem;
8228
8229 if (handlerMoveTaskItem != null)
8230 {
8231 handlerMoveTaskItem(
8232 this, moveTaskInventoryPacket.AgentData.FolderID,
8233 moveTaskInventoryPacket.InventoryData.LocalID,
8234 moveTaskInventoryPacket.InventoryData.ItemID);
8235 }
8236
8237 return true;
8238 }
8239
8240 private bool HandleRezScript(IClientAPI sender, Packet Pack)
8241 {
8242 //m_log.Debug(Pack.ToString());
8243 RezScriptPacket rezScriptx = (RezScriptPacket)Pack;
8244
8245 #region Packet Session and User Check
8246 if (m_checkPackets)
8247 {
8248 if (rezScriptx.AgentData.SessionID != SessionId ||
8249 rezScriptx.AgentData.AgentID != AgentId)
8250 return true;
8251 }
8252 #endregion
8253
8254 RezScript handlerRezScript = OnRezScript;
8255 InventoryItemBase item = new InventoryItemBase();
8256 item.ID = rezScriptx.InventoryBlock.ItemID;
8257 item.Folder = rezScriptx.InventoryBlock.FolderID;
8258 item.CreatorId = rezScriptx.InventoryBlock.CreatorID.ToString();
8259 item.Owner = rezScriptx.InventoryBlock.OwnerID;
8260 item.BasePermissions = rezScriptx.InventoryBlock.BaseMask;
8261 item.CurrentPermissions = rezScriptx.InventoryBlock.OwnerMask;
8262 item.EveryOnePermissions = rezScriptx.InventoryBlock.EveryoneMask;
8263 item.NextPermissions = rezScriptx.InventoryBlock.NextOwnerMask;
8264 item.GroupPermissions = rezScriptx.InventoryBlock.GroupMask;
8265 item.GroupOwned = rezScriptx.InventoryBlock.GroupOwned;
8266 item.GroupID = rezScriptx.InventoryBlock.GroupID;
8267 item.AssetType = rezScriptx.InventoryBlock.Type;
8268 item.InvType = rezScriptx.InventoryBlock.InvType;
8269 item.Flags = rezScriptx.InventoryBlock.Flags;
8270 item.SaleType = rezScriptx.InventoryBlock.SaleType;
8271 item.SalePrice = rezScriptx.InventoryBlock.SalePrice;
8272 item.Name = Util.FieldToString(rezScriptx.InventoryBlock.Name);
8273 item.Description = Util.FieldToString(rezScriptx.InventoryBlock.Description);
8274 item.CreationDate = rezScriptx.InventoryBlock.CreationDate;
8275
8276 if (handlerRezScript != null)
8277 {
8278 handlerRezScript(this, item, rezScriptx.InventoryBlock.TransactionID, rezScriptx.UpdateBlock.ObjectLocalID);
8279 }
8280 return true;
8281 }
8282
8283 private bool HandleMapLayerRequest(IClientAPI sender, Packet Pack)
8284 {
8285 RequestMapLayer();
8286 return true;
8287 }
8288
8289 private bool HandleMapBlockRequest(IClientAPI sender, Packet Pack)
8290 {
8291 MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack;
8292
8293 #region Packet Session and User Check
8294 if (m_checkPackets)
8295 {
8296 if (MapRequest.AgentData.SessionID != SessionId ||
8297 MapRequest.AgentData.AgentID != AgentId)
8298 return true;
8299 }
8300 #endregion
8301
8302 RequestMapBlocks handlerRequestMapBlocks = OnRequestMapBlocks;
8303 if (handlerRequestMapBlocks != null)
8304 {
8305 handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY,
8306 MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY, MapRequest.AgentData.Flags);
8307 }
8308 return true;
8309 }
8310
8311 private bool HandleMapNameRequest(IClientAPI sender, Packet Pack)
8312 {
8313 MapNameRequestPacket map = (MapNameRequestPacket)Pack;
8314
8315 #region Packet Session and User Check
8316 if (m_checkPackets)
8317 {
8318 if (map.AgentData.SessionID != SessionId ||
8319 map.AgentData.AgentID != AgentId)
8320 return true;
8321 }
8322 #endregion
8323
8324 string mapName = Util.UTF8.GetString(map.NameData.Name, 0,
8325 map.NameData.Name.Length - 1);
8326 RequestMapName handlerMapNameRequest = OnMapNameRequest;
8327 if (handlerMapNameRequest != null)
8328 {
8329 handlerMapNameRequest(this, mapName);
8330 }
8331 return true;
8332 }
8333
8334 private bool HandleTeleportLandmarkRequest(IClientAPI sender, Packet Pack)
8335 {
8336 TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack;
8337
8338 #region Packet Session and User Check
8339 if (m_checkPackets)
8340 {
8341 if (tpReq.Info.SessionID != SessionId ||
8342 tpReq.Info.AgentID != AgentId)
8343 return true;
8344 }
8345 #endregion
8346
8347 UUID lmid = tpReq.Info.LandmarkID;
8348 AssetLandmark lm;
8349 if (lmid != UUID.Zero)
8350 {
8351 //AssetBase lma = m_assetCache.GetAsset(lmid, false);
8352 AssetBase lma = m_assetService.Get(lmid.ToString());
8353
8354 if (lma == null)
8355 {
8356 // Failed to find landmark
8357 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
8358 tpCancel.Info.SessionID = tpReq.Info.SessionID;
8359 tpCancel.Info.AgentID = tpReq.Info.AgentID;
8360 OutPacket(tpCancel, ThrottleOutPacketType.Task);
8361 }
8362
8363 try
8364 {
8365 lm = new AssetLandmark(lma);
8366 }
8367 catch (NullReferenceException)
8368 {
8369 // asset not found generates null ref inside the assetlandmark constructor.
8370 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
8371 tpCancel.Info.SessionID = tpReq.Info.SessionID;
8372 tpCancel.Info.AgentID = tpReq.Info.AgentID;
8373 OutPacket(tpCancel, ThrottleOutPacketType.Task);
8374 return true;
8375 }
8376 }
8377 else
8378 {
8379 // Teleport home request
8380 UUIDNameRequest handlerTeleportHomeRequest = OnTeleportHomeRequest;
8381 if (handlerTeleportHomeRequest != null)
8382 {
8383 handlerTeleportHomeRequest(AgentId, this);
8384 }
8385 return true;
8386 }
8387
8388 TeleportLandmarkRequest handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest;
8389 if (handlerTeleportLandmarkRequest != null)
8390 {
8391 handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position);
8392 }
8393 else
8394 {
8395 //no event handler so cancel request
8396
8397
8398 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
8399 tpCancel.Info.AgentID = tpReq.Info.AgentID;
8400 tpCancel.Info.SessionID = tpReq.Info.SessionID;
8401 OutPacket(tpCancel, ThrottleOutPacketType.Task);
8402
8403 }
8404 return true;
8405 }
8406
8407 private bool HandleTeleportLocationRequest(IClientAPI sender, Packet Pack)
8408 {
8409 TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack;
8410 // m_log.Debug(tpLocReq.ToString());
8411
8412 #region Packet Session and User Check
8413 if (m_checkPackets)
8414 {
8415 if (tpLocReq.AgentData.SessionID != SessionId ||
8416 tpLocReq.AgentData.AgentID != AgentId)
8417 return true;
8418 }
8419 #endregion
8420
8421 TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest;
8422 if (handlerTeleportLocationRequest != null)
8423 {
8424 handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position,
8425 tpLocReq.Info.LookAt, 16);
8426 }
8427 else
8428 {
8429 //no event handler so cancel request
8430 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
8431 tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID;
8432 tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID;
8433 OutPacket(tpCancel, ThrottleOutPacketType.Task);
8434 }
8435 return true;
8436 }
8437
8438 #endregion Inventory/Asset/Other related packets
8439
8440 private bool HandleUUIDNameRequest(IClientAPI sender, Packet Pack)
8441 {
8442 UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack;
8443
8444 foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock)
8445 {
8446 UUIDNameRequest handlerNameRequest = OnNameFromUUIDRequest;
8447 if (handlerNameRequest != null)
8448 {
8449 handlerNameRequest(UUIDBlock.ID, this);
8450 }
8451 }
8452 return true;
8453 }
8454
8455 #region Parcel related packets
8456
8457 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack)
8458 {
8459 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack;
8460
8461 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest;
8462 if (handlerRegionHandleRequest != null)
8463 {
8464 handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID);
8465 }
8466 return true;
8467 }
8468
8469 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack)
8470 {
8471 ParcelInfoRequestPacket pirPack = (ParcelInfoRequestPacket)Pack;
8472
8473 #region Packet Session and User Check
8474 if (m_checkPackets)
8475 {
8476 if (pirPack.AgentData.SessionID != SessionId ||
8477 pirPack.AgentData.AgentID != AgentId)
8478 return true;
8479 }
8480 #endregion
8481
8482 ParcelInfoRequest handlerParcelInfoRequest = OnParcelInfoRequest;
8483 if (handlerParcelInfoRequest != null)
8484 {
8485 handlerParcelInfoRequest(this, pirPack.Data.ParcelID);
8486 }
8487 return true;
8488 }
8489
8490 private bool HandleParcelAccessListRequest(IClientAPI sender, Packet Pack)
8491 {
8492 ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack;
8493
8494 #region Packet Session and User Check
8495 if (m_checkPackets)
8496 {
8497 if (requestPacket.AgentData.SessionID != SessionId ||
8498 requestPacket.AgentData.AgentID != AgentId)
8499 return true;
8500 }
8501 #endregion
8502
8503 ParcelAccessListRequest handlerParcelAccessListRequest = OnParcelAccessListRequest;
8504
8505 if (handlerParcelAccessListRequest != null)
8506 {
8507 handlerParcelAccessListRequest(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID,
8508 requestPacket.Data.Flags, requestPacket.Data.SequenceID,
8509 requestPacket.Data.LocalID, this);
8510 }
8511 return true;
8512 }
8513
8514 private bool HandleParcelAccessListUpdate(IClientAPI sender, Packet Pack)
8515 {
8516 ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack;
8517
8518 #region Packet Session and User Check
8519 if (m_checkPackets)
8520 {
8521 if (updatePacket.AgentData.SessionID != SessionId ||
8522 updatePacket.AgentData.AgentID != AgentId)
8523 return true;
8524 }
8525 #endregion
8526
8527 List<ParcelManager.ParcelAccessEntry> entries = new List<ParcelManager.ParcelAccessEntry>();
8528 foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List)
8529 {
8530 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
8531 entry.AgentID = block.ID;
8532 entry.Flags = (AccessList)block.Flags;
8533 entry.Time = Util.ToDateTime(block.Time);
8534 entries.Add(entry);
8535 }
8536
8537 ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest;
8538 if (handlerParcelAccessListUpdateRequest != null)
8539 {
8540 handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID,
8541 updatePacket.Data.Flags,
8542 updatePacket.Data.LocalID,
8543 updatePacket.Data.TransactionID,
8544 updatePacket.Data.SequenceID,
8545 updatePacket.Data.Sections,
8546 entries, this);
8547 }
8548 return true;
8549 }
8550
8551 private bool HandleParcelPropertiesRequest(IClientAPI sender, Packet Pack)
8552 {
8553 ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack;
8554
8555 #region Packet Session and User Check
8556 if (m_checkPackets)
8557 {
8558 if (propertiesRequest.AgentData.SessionID != SessionId ||
8559 propertiesRequest.AgentData.AgentID != AgentId)
8560 return true;
8561 }
8562 #endregion
8563
8564 ParcelPropertiesRequest handlerParcelPropertiesRequest = OnParcelPropertiesRequest;
8565 if (handlerParcelPropertiesRequest != null)
8566 {
8567 handlerParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West),
8568 (int)Math.Round(propertiesRequest.ParcelData.South),
8569 (int)Math.Round(propertiesRequest.ParcelData.East),
8570 (int)Math.Round(propertiesRequest.ParcelData.North),
8571 propertiesRequest.ParcelData.SequenceID,
8572 propertiesRequest.ParcelData.SnapSelection, this);
8573 }
8574 return true;
8575 }
8576
8577 private bool HandleParcelDivide(IClientAPI sender, Packet Pack)
8578 {
8579 ParcelDividePacket landDivide = (ParcelDividePacket)Pack;
8580
8581 #region Packet Session and User Check
8582 if (m_checkPackets)
8583 {
8584 if (landDivide.AgentData.SessionID != SessionId ||
8585 landDivide.AgentData.AgentID != AgentId)
8586 return true;
8587 }
8588 #endregion
8589
8590 ParcelDivideRequest handlerParcelDivideRequest = OnParcelDivideRequest;
8591 if (handlerParcelDivideRequest != null)
8592 {
8593 handlerParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West),
8594 (int)Math.Round(landDivide.ParcelData.South),
8595 (int)Math.Round(landDivide.ParcelData.East),
8596 (int)Math.Round(landDivide.ParcelData.North), this);
8597 }
8598 return true;
8599 }
8600
8601 private bool HandleParcelJoin(IClientAPI sender, Packet Pack)
8602 {
8603 ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack;
8604
8605 #region Packet Session and User Check
8606 if (m_checkPackets)
8607 {
8608 if (landJoin.AgentData.SessionID != SessionId ||
8609 landJoin.AgentData.AgentID != AgentId)
8610 return true;
8611 }
8612 #endregion
8613
8614 ParcelJoinRequest handlerParcelJoinRequest = OnParcelJoinRequest;
8615
8616 if (handlerParcelJoinRequest != null)
8617 {
8618 handlerParcelJoinRequest((int)Math.Round(landJoin.ParcelData.West),
8619 (int)Math.Round(landJoin.ParcelData.South),
8620 (int)Math.Round(landJoin.ParcelData.East),
8621 (int)Math.Round(landJoin.ParcelData.North), this);
8622 }
8623 return true;
8624 }
8625
8626 private bool HandleParcelPropertiesUpdate(IClientAPI sender, Packet Pack)
8627 {
8628 ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack;
8629
8630 #region Packet Session and User Check
8631 if (m_checkPackets)
8632 {
8633 if (parcelPropertiesPacket.AgentData.SessionID != SessionId ||
8634 parcelPropertiesPacket.AgentData.AgentID != AgentId)
8635 return true;
8636 }
8637 #endregion
8638
8639 ParcelPropertiesUpdateRequest handlerParcelPropertiesUpdateRequest = OnParcelPropertiesUpdateRequest;
8640
8641 if (handlerParcelPropertiesUpdateRequest != null)
8642 {
8643 LandUpdateArgs args = new LandUpdateArgs();
8644
8645 args.AuthBuyerID = parcelPropertiesPacket.ParcelData.AuthBuyerID;
8646 args.Category = (ParcelCategory)parcelPropertiesPacket.ParcelData.Category;
8647 args.Desc = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Desc);
8648 args.GroupID = parcelPropertiesPacket.ParcelData.GroupID;
8649 args.LandingType = parcelPropertiesPacket.ParcelData.LandingType;
8650 args.MediaAutoScale = parcelPropertiesPacket.ParcelData.MediaAutoScale;
8651 args.MediaID = parcelPropertiesPacket.ParcelData.MediaID;
8652 args.MediaURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MediaURL);
8653 args.MusicURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MusicURL);
8654 args.Name = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Name);
8655 args.ParcelFlags = parcelPropertiesPacket.ParcelData.ParcelFlags;
8656 args.PassHours = parcelPropertiesPacket.ParcelData.PassHours;
8657 args.PassPrice = parcelPropertiesPacket.ParcelData.PassPrice;
8658 args.SalePrice = parcelPropertiesPacket.ParcelData.SalePrice;
8659 args.SnapshotID = parcelPropertiesPacket.ParcelData.SnapshotID;
8660 args.UserLocation = parcelPropertiesPacket.ParcelData.UserLocation;
8661 args.UserLookAt = parcelPropertiesPacket.ParcelData.UserLookAt;
8662 handlerParcelPropertiesUpdateRequest(args, parcelPropertiesPacket.ParcelData.LocalID, this);
8663 }
8664 return true;
8665 }
8666
8667 private bool HandleParcelSelectObjects(IClientAPI sender, Packet Pack)
8668 {
8669 ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack;
8670
8671 #region Packet Session and User Check
8672 if (m_checkPackets)
8673 {
8674 if (selectPacket.AgentData.SessionID != SessionId ||
8675 selectPacket.AgentData.AgentID != AgentId)
8676 return true;
8677 }
8678 #endregion
8679
8680 List<UUID> returnIDs = new List<UUID>();
8681
8682 foreach (ParcelSelectObjectsPacket.ReturnIDsBlock rb in
8683 selectPacket.ReturnIDs)
8684 {
8685 returnIDs.Add(rb.ReturnID);
8686 }
8687
8688 ParcelSelectObjects handlerParcelSelectObjects = OnParcelSelectObjects;
8689
8690 if (handlerParcelSelectObjects != null)
8691 {
8692 handlerParcelSelectObjects(selectPacket.ParcelData.LocalID,
8693 Convert.ToInt32(selectPacket.ParcelData.ReturnType), returnIDs, this);
8694 }
8695 return true;
8696 }
8697
8698 private bool HandleParcelObjectOwnersRequest(IClientAPI sender, Packet Pack)
8699 {
8700 ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack;
8701
8702 #region Packet Session and User Check
8703 if (m_checkPackets)
8704 {
8705 if (reqPacket.AgentData.SessionID != SessionId ||
8706 reqPacket.AgentData.AgentID != AgentId)
8707 return true;
8708 }
8709 #endregion
8710
8711 ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest;
8712
8713 if (handlerParcelObjectOwnerRequest != null)
8714 {
8715 handlerParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this);
8716 }
8717 return true;
8718
8719 }
8720
8721 private bool HandleParcelGodForceOwner(IClientAPI sender, Packet Pack)
8722 {
8723 ParcelGodForceOwnerPacket godForceOwnerPacket = (ParcelGodForceOwnerPacket)Pack;
8724
8725 #region Packet Session and User Check
8726 if (m_checkPackets)
8727 {
8728 if (godForceOwnerPacket.AgentData.SessionID != SessionId ||
8729 godForceOwnerPacket.AgentData.AgentID != AgentId)
8730 return true;
8731 }
8732 #endregion
8733
8734 ParcelGodForceOwner handlerParcelGodForceOwner = OnParcelGodForceOwner;
8735 if (handlerParcelGodForceOwner != null)
8736 {
8737 handlerParcelGodForceOwner(godForceOwnerPacket.Data.LocalID, godForceOwnerPacket.Data.OwnerID, this);
8738 }
8739 return true;
8740 }
8741
8742 private bool HandleParcelRelease(IClientAPI sender, Packet Pack)
8743 {
8744 ParcelReleasePacket releasePacket = (ParcelReleasePacket)Pack;
8745
8746 #region Packet Session and User Check
8747 if (m_checkPackets)
8748 {
8749 if (releasePacket.AgentData.SessionID != SessionId ||
8750 releasePacket.AgentData.AgentID != AgentId)
8751 return true;
8752 }
8753 #endregion
8754
8755 ParcelAbandonRequest handlerParcelAbandonRequest = OnParcelAbandonRequest;
8756 if (handlerParcelAbandonRequest != null)
8757 {
8758 handlerParcelAbandonRequest(releasePacket.Data.LocalID, this);
8759 }
8760 return true;
8761 }
8762
8763 private bool HandleParcelReclaim(IClientAPI sender, Packet Pack)
8764 {
8765 ParcelReclaimPacket reclaimPacket = (ParcelReclaimPacket)Pack;
8766
8767 #region Packet Session and User Check
8768 if (m_checkPackets)
8769 {
8770 if (reclaimPacket.AgentData.SessionID != SessionId ||
8771 reclaimPacket.AgentData.AgentID != AgentId)
8772 return true;
8773 }
8774 #endregion
8775
8776 ParcelReclaim handlerParcelReclaim = OnParcelReclaim;
8777 if (handlerParcelReclaim != null)
8778 {
8779 handlerParcelReclaim(reclaimPacket.Data.LocalID, this);
8780 }
8781 return true;
8782 }
8783
8784 private bool HandleParcelReturnObjects(IClientAPI sender, Packet Pack)
8785 {
8786 ParcelReturnObjectsPacket parcelReturnObjects = (ParcelReturnObjectsPacket)Pack;
8787
8788 #region Packet Session and User Check
8789 if (m_checkPackets)
8790 {
8791 if (parcelReturnObjects.AgentData.SessionID != SessionId ||
8792 parcelReturnObjects.AgentData.AgentID != AgentId)
8793 return true;
8794 }
8795 #endregion
8796
8797 UUID[] puserselectedOwnerIDs = new UUID[parcelReturnObjects.OwnerIDs.Length];
8798 for (int parceliterator = 0; parceliterator < parcelReturnObjects.OwnerIDs.Length; parceliterator++)
8799 puserselectedOwnerIDs[parceliterator] = parcelReturnObjects.OwnerIDs[parceliterator].OwnerID;
8800
8801 UUID[] puserselectedTaskIDs = new UUID[parcelReturnObjects.TaskIDs.Length];
8802
8803 for (int parceliterator = 0; parceliterator < parcelReturnObjects.TaskIDs.Length; parceliterator++)
8804 puserselectedTaskIDs[parceliterator] = parcelReturnObjects.TaskIDs[parceliterator].TaskID;
8805
8806 ParcelReturnObjectsRequest handlerParcelReturnObjectsRequest = OnParcelReturnObjectsRequest;
8807 if (handlerParcelReturnObjectsRequest != null)
8808 {
8809 handlerParcelReturnObjectsRequest(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, this);
8810
8811 }
8812 return true;
8813 }
8814
8815 private bool HandleParcelSetOtherCleanTime(IClientAPI sender, Packet Pack)
8816 {
8817 ParcelSetOtherCleanTimePacket parcelSetOtherCleanTimePacket = (ParcelSetOtherCleanTimePacket)Pack;
8818
8819 #region Packet Session and User Check
8820 if (m_checkPackets)
8821 {
8822 if (parcelSetOtherCleanTimePacket.AgentData.SessionID != SessionId ||
8823 parcelSetOtherCleanTimePacket.AgentData.AgentID != AgentId)
8824 return true;
8825 }
8826 #endregion
8827
8828 ParcelSetOtherCleanTime handlerParcelSetOtherCleanTime = OnParcelSetOtherCleanTime;
8829 if (handlerParcelSetOtherCleanTime != null)
8830 {
8831 handlerParcelSetOtherCleanTime(this,
8832 parcelSetOtherCleanTimePacket.ParcelData.LocalID,
8833 parcelSetOtherCleanTimePacket.ParcelData.OtherCleanTime);
8834 }
8835 return true;
8836 }
8837
8838 private bool HandleLandStatRequest(IClientAPI sender, Packet Pack)
8839 {
8840 LandStatRequestPacket lsrp = (LandStatRequestPacket)Pack;
8841
8842 #region Packet Session and User Check
8843 if (m_checkPackets)
8844 {
8845 if (lsrp.AgentData.SessionID != SessionId ||
8846 lsrp.AgentData.AgentID != AgentId)
8847 return true;
8848 }
8849 #endregion
8850
8851 GodLandStatRequest handlerLandStatRequest = OnLandStatRequest;
8852 if (handlerLandStatRequest != null)
8853 {
8854 handlerLandStatRequest(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Utils.BytesToString(lsrp.RequestData.Filter), this);
8855 }
8856 return true;
8857 }
8858
8859 private bool HandleParcelDwellRequest(IClientAPI sender, Packet Pack)
8860 {
8861 ParcelDwellRequestPacket dwellrq =
8862 (ParcelDwellRequestPacket)Pack;
8863
8864 #region Packet Session and User Check
8865 if (m_checkPackets)
8866 {
8867 if (dwellrq.AgentData.SessionID != SessionId ||
8868 dwellrq.AgentData.AgentID != AgentId)
8869 return true;
8870 }
8871 #endregion
8872
8873 ParcelDwellRequest handlerParcelDwellRequest = OnParcelDwellRequest;
8874 if (handlerParcelDwellRequest != null)
8875 {
8876 handlerParcelDwellRequest(dwellrq.Data.LocalID, this);
8877 }
8878 return true;
8879 }
8880
8881 #endregion Parcel related packets
8882
8883 #region Estate Packets
8884
8885 private bool HandleEstateOwnerMessage(IClientAPI sender, Packet Pack)
8886 {
8887 EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack;
8888 //m_log.Debug(messagePacket.ToString());
8889 GodLandStatRequest handlerLandStatRequest;
8890
8891 #region Packet Session and User Check
8892 if (m_checkPackets)
8893 {
8894 if (messagePacket.AgentData.SessionID != SessionId ||
8895 messagePacket.AgentData.AgentID != AgentId)
8896 return true;
8897 }
8898 #endregion
8899
8900 switch (Utils.BytesToString(messagePacket.MethodData.Method))
8901 {
8902 case "getinfo":
8903 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8904 {
8905 OnDetailedEstateDataRequest(this, messagePacket.MethodData.Invoice);
8906 }
8907 return true;
8908 case "setregioninfo":
8909 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8910 {
8911 OnSetEstateFlagsRequest(convertParamStringToBool(messagePacket.ParamList[0].Parameter), convertParamStringToBool(messagePacket.ParamList[1].Parameter),
8912 convertParamStringToBool(messagePacket.ParamList[2].Parameter), !convertParamStringToBool(messagePacket.ParamList[3].Parameter),
8913 Convert.ToInt16(Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[4].Parameter), Culture.NumberFormatInfo)),
8914 (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter), Culture.NumberFormatInfo),
8915 Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[6].Parameter)),
8916 convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter));
8917 }
8918 return true;
8919 // case "texturebase":
8920 // if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8921 // {
8922 // foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
8923 // {
8924 // string s = Utils.BytesToString(block.Parameter);
8925 // string[] splitField = s.Split(' ');
8926 // if (splitField.Length == 2)
8927 // {
8928 // UUID tempUUID = new UUID(splitField[1]);
8929 // OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID);
8930 // }
8931 // }
8932 // }
8933 // break;
8934 case "texturedetail":
8935 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8936 {
8937 foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
8938 {
8939 string s = Utils.BytesToString(block.Parameter);
8940 string[] splitField = s.Split(' ');
8941 if (splitField.Length == 2)
8942 {
8943 Int16 corner = Convert.ToInt16(splitField[0]);
8944 UUID textureUUID = new UUID(splitField[1]);
8945
8946 OnSetEstateTerrainDetailTexture(this, corner, textureUUID);
8947 }
8948 }
8949 }
8950
8951 return true;
8952 case "textureheights":
8953 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8954 {
8955 foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
8956 {
8957 string s = Utils.BytesToString(block.Parameter);
8958 string[] splitField = s.Split(' ');
8959 if (splitField.Length == 3)
8960 {
8961 Int16 corner = Convert.ToInt16(splitField[0]);
8962 float lowValue = (float)Convert.ToDecimal(splitField[1], Culture.NumberFormatInfo);
8963 float highValue = (float)Convert.ToDecimal(splitField[2], Culture.NumberFormatInfo);
8964
8965 OnSetEstateTerrainTextureHeights(this, corner, lowValue, highValue);
8966 }
8967 }
8968 }
8969 return true;
8970 case "texturecommit":
8971 OnCommitEstateTerrainTextureRequest(this);
8972 return true;
8973 case "setregionterrain":
8974 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8975 {
8976 if (messagePacket.ParamList.Length != 9)
8977 {
8978 m_log.Error("EstateOwnerMessage: SetRegionTerrain method has a ParamList of invalid length");
8979 }
8980 else
8981 {
8982 try
8983 {
8984 string tmp = Utils.BytesToString(messagePacket.ParamList[0].Parameter);
8985 if (!tmp.Contains(".")) tmp += ".00";
8986 float WaterHeight = (float)Convert.ToDecimal(tmp, Culture.NumberFormatInfo);
8987 tmp = Utils.BytesToString(messagePacket.ParamList[1].Parameter);
8988 if (!tmp.Contains(".")) tmp += ".00";
8989 float TerrainRaiseLimit = (float)Convert.ToDecimal(tmp, Culture.NumberFormatInfo);
8990 tmp = Utils.BytesToString(messagePacket.ParamList[2].Parameter);
8991 if (!tmp.Contains(".")) tmp += ".00";
8992 float TerrainLowerLimit = (float)Convert.ToDecimal(tmp, Culture.NumberFormatInfo);
8993 bool UseEstateSun = convertParamStringToBool(messagePacket.ParamList[3].Parameter);
8994 bool UseFixedSun = convertParamStringToBool(messagePacket.ParamList[4].Parameter);
8995 float SunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter), Culture.NumberFormatInfo);
8996 bool UseGlobal = convertParamStringToBool(messagePacket.ParamList[6].Parameter);
8997 bool EstateFixedSun = convertParamStringToBool(messagePacket.ParamList[7].Parameter);
8998 float EstateSunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[8].Parameter), Culture.NumberFormatInfo);
8999
9000 OnSetRegionTerrainSettings(WaterHeight, TerrainRaiseLimit, TerrainLowerLimit, UseEstateSun, UseFixedSun, SunHour, UseGlobal, EstateFixedSun, EstateSunHour);
9001
9002 }
9003 catch (Exception ex)
9004 {
9005 m_log.Error("EstateOwnerMessage: Exception while setting terrain settings: \n" + messagePacket + "\n" + ex);
9006 }
9007 }
9008 }
9009
9010 return true;
9011 case "restart":
9012 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9013 {
9014 // There's only 1 block in the estateResetSim.. and that's the number of seconds till restart.
9015 foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
9016 {
9017 float timeSeconds;
9018 Utils.TryParseSingle(Utils.BytesToString(block.Parameter), out timeSeconds);
9019 timeSeconds = (int)timeSeconds;
9020 OnEstateRestartSimRequest(this, (int)timeSeconds);
9021
9022 }
9023 }
9024 return true;
9025 case "estatechangecovenantid":
9026 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9027 {
9028 foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
9029 {
9030 UUID newCovenantID = new UUID(Utils.BytesToString(block.Parameter));
9031 OnEstateChangeCovenantRequest(this, newCovenantID);
9032 }
9033 }
9034 return true;
9035 case "estateaccessdelta": // Estate access delta manages the banlist and allow list too.
9036 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9037 {
9038 int estateAccessType = Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[1].Parameter));
9039 OnUpdateEstateAccessDeltaRequest(this, messagePacket.MethodData.Invoice, estateAccessType, new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)));
9040
9041 }
9042 return true;
9043 case "simulatormessage":
9044 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9045 {
9046 UUID invoice = messagePacket.MethodData.Invoice;
9047 UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
9048 string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter);
9049 string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter);
9050 UUID sessionID = messagePacket.AgentData.SessionID;
9051 OnSimulatorBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message);
9052 }
9053 return true;
9054 case "instantmessage":
9055 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9056 {
9057 if (messagePacket.ParamList.Length < 2)
9058 return true;
9059
9060 UUID invoice = messagePacket.MethodData.Invoice;
9061 UUID sessionID = messagePacket.AgentData.SessionID;
9062
9063 UUID SenderID;
9064 string SenderName;
9065 string Message;
9066
9067 if (messagePacket.ParamList.Length < 5)
9068 {
9069 SenderID = AgentId;
9070 SenderName = Utils.BytesToString(messagePacket.ParamList[0].Parameter);
9071 Message = Utils.BytesToString(messagePacket.ParamList[1].Parameter);
9072 }
9073 else
9074 {
9075 SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
9076 SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter);
9077 Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter);
9078 }
9079
9080 OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message);
9081 }
9082 return true;
9083 case "setregiondebug":
9084 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9085 {
9086 UUID invoice = messagePacket.MethodData.Invoice;
9087 UUID SenderID = messagePacket.AgentData.AgentID;
9088 bool scripted = convertParamStringToBool(messagePacket.ParamList[0].Parameter);
9089 bool collisionEvents = convertParamStringToBool(messagePacket.ParamList[1].Parameter);
9090 bool physics = convertParamStringToBool(messagePacket.ParamList[2].Parameter);
9091
9092 OnEstateDebugRegionRequest(this, invoice, SenderID, scripted, collisionEvents, physics);
9093 }
9094 return true;
9095 case "teleporthomeuser":
9096 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9097 {
9098 UUID invoice = messagePacket.MethodData.Invoice;
9099 UUID SenderID = messagePacket.AgentData.AgentID;
9100 UUID Prey;
9101
9102 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey);
9103
9104 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey);
9105 }
9106 return true;
9107 case "teleporthomeallusers":
9108 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9109 {
9110 UUID invoice = messagePacket.MethodData.Invoice;
9111 UUID SenderID = messagePacket.AgentData.AgentID;
9112 OnEstateTeleportAllUsersHomeRequest(this, invoice, SenderID);
9113 }
9114 return true;
9115 case "colliders":
9116 handlerLandStatRequest = OnLandStatRequest;
9117 if (handlerLandStatRequest != null)
9118 {
9119 handlerLandStatRequest(0, 1, 0, "", this);
9120 }
9121 return true;
9122 case "scripts":
9123 handlerLandStatRequest = OnLandStatRequest;
9124 if (handlerLandStatRequest != null)
9125 {
9126 handlerLandStatRequest(0, 0, 0, "", this);
9127 }
9128 return true;
9129 case "terrain":
9130 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9131 {
9132 if (messagePacket.ParamList.Length > 0)
9133 {
9134 if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "bake")
9135 {
9136 BakeTerrain handlerBakeTerrain = OnBakeTerrain;
9137 if (handlerBakeTerrain != null)
9138 {
9139 handlerBakeTerrain(this);
9140 }
9141 }
9142 if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "download filename")
9143 {
9144 if (messagePacket.ParamList.Length > 1)
9145 {
9146 RequestTerrain handlerRequestTerrain = OnRequestTerrain;
9147 if (handlerRequestTerrain != null)
9148 {
9149 handlerRequestTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter));
9150 }
9151 }
9152 }
9153 if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "upload filename")
9154 {
9155 if (messagePacket.ParamList.Length > 1)
9156 {
9157 RequestTerrain handlerUploadTerrain = OnUploadTerrain;
9158 if (handlerUploadTerrain != null)
9159 {
9160 handlerUploadTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter));
9161 }
9162 }
9163 }
9164
9165 }
9166
9167
9168 }
9169 return true;
9170
9171 case "estatechangeinfo":
9172 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
9173 {
9174 UUID invoice = messagePacket.MethodData.Invoice;
9175 UUID SenderID = messagePacket.AgentData.AgentID;
9176 UInt32 param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter));
9177 UInt32 param2 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
9178
9179 EstateChangeInfo handlerEstateChangeInfo = OnEstateChangeInfo;
9180 if (handlerEstateChangeInfo != null)
9181 {
9182 handlerEstateChangeInfo(this, invoice, SenderID, param1, param2);
9183 }
9184 }
9185 return true;
9186
9187 default:
9188 m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket);
9189 return true;
9190 }
9191
9192 //int parcelID, uint reportType, uint requestflags, string filter
9193
9194 //lsrp.RequestData.ParcelLocalID;
9195 //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts
9196 //lsrp.RequestData.RequestFlags;
9197 //lsrp.RequestData.Filter;
9198
9199// return true;
9200 }
9201
9202 private bool HandleRequestRegionInfo(IClientAPI sender, Packet Pack)
9203 {
9204 RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData;
9205
9206 #region Packet Session and User Check
9207 if (m_checkPackets)
9208 {
9209 if (mPacket.SessionID != SessionId ||
9210 mPacket.AgentID != AgentId)
9211 return true;
9212 }
9213 #endregion
9214
9215 RegionInfoRequest handlerRegionInfoRequest = OnRegionInfoRequest;
9216 if (handlerRegionInfoRequest != null)
9217 {
9218 handlerRegionInfoRequest(this);
9219 }
9220 return true;
9221 }
9222
9223 private bool HandleEstateCovenantRequest(IClientAPI sender, Packet Pack)
9224 {
9225
9226 //EstateCovenantRequestPacket.AgentDataBlock epack =
9227 // ((EstateCovenantRequestPacket)Pack).AgentData;
9228
9229 EstateCovenantRequest handlerEstateCovenantRequest = OnEstateCovenantRequest;
9230 if (handlerEstateCovenantRequest != null)
9231 {
9232 handlerEstateCovenantRequest(this);
9233 }
9234 return true;
9235
9236 }
9237
9238 #endregion Estate Packets
9239
9240 #region GodPackets
9241
9242 private bool HandleRequestGodlikePowers(IClientAPI sender, Packet Pack)
9243 {
9244 RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack;
9245 RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock;
9246 UUID token = rblock.Token;
9247
9248 RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData;
9249
9250 RequestGodlikePowers handlerReqGodlikePowers = OnRequestGodlikePowers;
9251
9252 if (handlerReqGodlikePowers != null)
9253 {
9254 handlerReqGodlikePowers(ablock.AgentID, ablock.SessionID, token, rblock.Godlike, this);
9255 }
9256
9257 return true;
9258 }
9259
9260 private bool HandleGodUpdateRegionInfoUpdate(IClientAPI client, Packet Packet)
9261 {
9262 GodUpdateRegionInfoPacket GodUpdateRegionInfo =
9263 (GodUpdateRegionInfoPacket)Packet;
9264
9265 GodUpdateRegionInfoUpdate handlerGodUpdateRegionInfo = OnGodUpdateRegionInfoUpdate;
9266 if (handlerGodUpdateRegionInfo != null)
9267 {
9268 handlerGodUpdateRegionInfo(this,
9269 GodUpdateRegionInfo.RegionInfo.BillableFactor,
9270 GodUpdateRegionInfo.RegionInfo.EstateID,
9271 GodUpdateRegionInfo.RegionInfo.RegionFlags,
9272 GodUpdateRegionInfo.RegionInfo.SimName,
9273 GodUpdateRegionInfo.RegionInfo.RedirectGridX,
9274 GodUpdateRegionInfo.RegionInfo.RedirectGridY);
9275 return true;
9276 }
9277 return false;
9278 }
9279
9280 private bool HandleSimWideDeletes(IClientAPI client, Packet Packet)
9281 {
9282 SimWideDeletesPacket SimWideDeletesRequest =
9283 (SimWideDeletesPacket)Packet;
9284 SimWideDeletesDelegate handlerSimWideDeletesRequest = OnSimWideDeletes;
9285 if (handlerSimWideDeletesRequest != null)
9286 {
9287 handlerSimWideDeletesRequest(this, SimWideDeletesRequest.AgentData.AgentID,(int)SimWideDeletesRequest.DataBlock.Flags,SimWideDeletesRequest.DataBlock.TargetID);
9288 return true;
9289 }
9290 return false;
9291 }
9292
9293 private bool HandleGodlikeMessage(IClientAPI client, Packet Packet)
9294 {
9295 GodlikeMessagePacket GodlikeMessage =
9296 (GodlikeMessagePacket)Packet;
9297
9298 GodlikeMessage handlerGodlikeMessage = onGodlikeMessage;
9299 if (handlerGodlikeMessage != null)
9300 {
9301 handlerGodlikeMessage(this,
9302 GodlikeMessage.MethodData.Invoice,
9303 GodlikeMessage.MethodData.Method,
9304 GodlikeMessage.ParamList[0].Parameter);
9305 return true;
9306 }
9307 return false;
9308 }
9309
9310 private bool HandleSaveStatePacket(IClientAPI client, Packet Packet)
9311 {
9312 StateSavePacket SaveStateMessage =
9313 (StateSavePacket)Packet;
9314 SaveStateHandler handlerSaveStatePacket = OnSaveState;
9315 if (handlerSaveStatePacket != null)
9316 {
9317 handlerSaveStatePacket(this,SaveStateMessage.AgentData.AgentID);
9318 return true;
9319 }
9320 return false;
9321 }
9322
9323 private bool HandleGodKickUser(IClientAPI sender, Packet Pack)
9324 {
9325 GodKickUserPacket gkupack = (GodKickUserPacket)Pack;
9326
9327 if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID)
9328 {
9329 GodKickUser handlerGodKickUser = OnGodKickUser;
9330 if (handlerGodKickUser != null)
9331 {
9332 handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID,
9333 gkupack.UserInfo.AgentID, gkupack.UserInfo.KickFlags, gkupack.UserInfo.Reason);
9334 }
9335 }
9336 else
9337 {
9338 SendAgentAlertMessage("Kick request denied", false);
9339 }
9340 //KickUserPacket kupack = new KickUserPacket();
9341 //KickUserPacket.UserInfoBlock kupackib = kupack.UserInfo;
9342
9343 //kupack.UserInfo.AgentID = gkupack.UserInfo.AgentID;
9344 //kupack.UserInfo.SessionID = gkupack.UserInfo.GodSessionID;
9345
9346 //kupack.TargetBlock.TargetIP = (uint)0;
9347 //kupack.TargetBlock.TargetPort = (ushort)0;
9348 //kupack.UserInfo.Reason = gkupack.UserInfo.Reason;
9349
9350 //OutPacket(kupack, ThrottleOutPacketType.Task);
9351 return true;
9352 }
9353 #endregion GodPackets
9354
9355 #region Economy/Transaction Packets
9356
9357 private bool HandleMoneyBalanceRequest(IClientAPI sender, Packet Pack)
9358 {
9359 MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack;
9360
9361 #region Packet Session and User Check
9362 if (m_checkPackets)
9363 {
9364 if (moneybalancerequestpacket.AgentData.SessionID != SessionId ||
9365 moneybalancerequestpacket.AgentData.AgentID != AgentId)
9366 return true;
9367 }
9368 #endregion
9369
9370 MoneyBalanceRequest handlerMoneyBalanceRequest = OnMoneyBalanceRequest;
9371
9372 if (handlerMoneyBalanceRequest != null)
9373 {
9374 handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID);
9375 }
9376
9377 return true;
9378 }
9379 private bool HandleEconomyDataRequest(IClientAPI sender, Packet Pack)
9380 {
9381 EconomyDataRequest handlerEconomoyDataRequest = OnEconomyDataRequest;
9382 if (handlerEconomoyDataRequest != null)
9383 {
9384 handlerEconomoyDataRequest(AgentId);
9385 }
9386 return true;
9387 }
9388 private bool HandleRequestPayPrice(IClientAPI sender, Packet Pack)
9389 {
9390 RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack;
9391
9392 RequestPayPrice handlerRequestPayPrice = OnRequestPayPrice;
9393 if (handlerRequestPayPrice != null)
9394 {
9395 handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID);
9396 }
9397 return true;
9398 }
9399 private bool HandleObjectSaleInfo(IClientAPI sender, Packet Pack)
9400 {
9401 ObjectSaleInfoPacket objectSaleInfoPacket = (ObjectSaleInfoPacket)Pack;
9402
9403 #region Packet Session and User Check
9404 if (m_checkPackets)
9405 {
9406 if (objectSaleInfoPacket.AgentData.SessionID != SessionId ||
9407 objectSaleInfoPacket.AgentData.AgentID != AgentId)
9408 return true;
9409 }
9410 #endregion
9411
9412 ObjectSaleInfo handlerObjectSaleInfo = OnObjectSaleInfo;
9413 if (handlerObjectSaleInfo != null)
9414 {
9415 foreach (ObjectSaleInfoPacket.ObjectDataBlock d
9416 in objectSaleInfoPacket.ObjectData)
9417 {
9418 handlerObjectSaleInfo(this,
9419 objectSaleInfoPacket.AgentData.AgentID,
9420 objectSaleInfoPacket.AgentData.SessionID,
9421 d.LocalID,
9422 d.SaleType,
9423 d.SalePrice);
9424 }
9425 }
9426 return true;
9427 }
9428 private bool HandleObjectBuy(IClientAPI sender, Packet Pack)
9429 {
9430 ObjectBuyPacket objectBuyPacket = (ObjectBuyPacket)Pack;
9431
9432 #region Packet Session and User Check
9433 if (m_checkPackets)
9434 {
9435 if (objectBuyPacket.AgentData.SessionID != SessionId ||
9436 objectBuyPacket.AgentData.AgentID != AgentId)
9437 return true;
9438 }
9439 #endregion
9440
9441 ObjectBuy handlerObjectBuy = OnObjectBuy;
9442
9443 if (handlerObjectBuy != null)
9444 {
9445 foreach (ObjectBuyPacket.ObjectDataBlock d
9446 in objectBuyPacket.ObjectData)
9447 {
9448 handlerObjectBuy(this,
9449 objectBuyPacket.AgentData.AgentID,
9450 objectBuyPacket.AgentData.SessionID,
9451 objectBuyPacket.AgentData.GroupID,
9452 objectBuyPacket.AgentData.CategoryID,
9453 d.ObjectLocalID,
9454 d.SaleType,
9455 d.SalePrice);
9456 }
9457 }
9458 return true;
9459 }
9460
9461 #endregion Economy/Transaction Packets
9462
9463 #region Script Packets
9464 private bool HandleGetScriptRunning(IClientAPI sender, Packet Pack)
9465 {
9466 GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack;
9467
9468 GetScriptRunning handlerGetScriptRunning = OnGetScriptRunning;
9469 if (handlerGetScriptRunning != null)
9470 {
9471 handlerGetScriptRunning(this, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID);
9472 }
9473 return true;
9474 }
9475 private bool HandleSetScriptRunning(IClientAPI sender, Packet Pack)
9476 {
9477 SetScriptRunningPacket setScriptRunning = (SetScriptRunningPacket)Pack;
9478
9479 #region Packet Session and User Check
9480 if (m_checkPackets)
9481 {
9482 if (setScriptRunning.AgentData.SessionID != SessionId ||
9483 setScriptRunning.AgentData.AgentID != AgentId)
9484 return true;
9485 }
9486 #endregion
9487
9488 SetScriptRunning handlerSetScriptRunning = OnSetScriptRunning;
9489 if (handlerSetScriptRunning != null)
9490 {
9491 handlerSetScriptRunning(this, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running);
9492 }
9493 return true;
9494 }
9495
9496 private bool HandleScriptReset(IClientAPI sender, Packet Pack)
9497 {
9498 ScriptResetPacket scriptResetPacket = (ScriptResetPacket)Pack;
9499
9500 #region Packet Session and User Check
9501 if (m_checkPackets)
9502 {
9503 if (scriptResetPacket.AgentData.SessionID != SessionId ||
9504 scriptResetPacket.AgentData.AgentID != AgentId)
9505 return true;
9506 }
9507 #endregion
9508
9509 ScriptReset handlerScriptReset = OnScriptReset;
9510 if (handlerScriptReset != null)
9511 {
9512 handlerScriptReset(this, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID);
9513 }
9514 return true;
9515 }
9516
9517 #endregion Script Packets
9518
9519 #region Gesture Managment
9520
9521 private bool HandleActivateGestures(IClientAPI sender, Packet Pack)
9522 {
9523 ActivateGesturesPacket activateGesturePacket = (ActivateGesturesPacket)Pack;
9524
9525 #region Packet Session and User Check
9526 if (m_checkPackets)
9527 {
9528 if (activateGesturePacket.AgentData.SessionID != SessionId ||
9529 activateGesturePacket.AgentData.AgentID != AgentId)
9530 return true;
9531 }
9532 #endregion
9533
9534 ActivateGesture handlerActivateGesture = OnActivateGesture;
9535 if (handlerActivateGesture != null)
9536 {
9537 handlerActivateGesture(this,
9538 activateGesturePacket.Data[0].AssetID,
9539 activateGesturePacket.Data[0].ItemID);
9540 }
9541 else m_log.Error("Null pointer for activateGesture");
9542
9543 return true;
9544 }
9545 private bool HandleDeactivateGestures(IClientAPI sender, Packet Pack)
9546 {
9547 DeactivateGesturesPacket deactivateGesturePacket = (DeactivateGesturesPacket)Pack;
9548
9549 #region Packet Session and User Check
9550 if (m_checkPackets)
9551 {
9552 if (deactivateGesturePacket.AgentData.SessionID != SessionId ||
9553 deactivateGesturePacket.AgentData.AgentID != AgentId)
9554 return true;
9555 }
9556 #endregion
9557
9558 DeactivateGesture handlerDeactivateGesture = OnDeactivateGesture;
9559 if (handlerDeactivateGesture != null)
9560 {
9561 handlerDeactivateGesture(this, deactivateGesturePacket.Data[0].ItemID);
9562 }
9563 return true;
9564 }
9565 private bool HandleObjectOwner(IClientAPI sender, Packet Pack)
9566 {
9567 ObjectOwnerPacket objectOwnerPacket = (ObjectOwnerPacket)Pack;
9568
9569 #region Packet Session and User Check
9570 if (m_checkPackets)
9571 {
9572 if (objectOwnerPacket.AgentData.SessionID != SessionId ||
9573 objectOwnerPacket.AgentData.AgentID != AgentId)
9574 return true;
9575 }
9576 #endregion
9577
9578 List<uint> localIDs = new List<uint>();
9579
9580 foreach (ObjectOwnerPacket.ObjectDataBlock d in objectOwnerPacket.ObjectData)
9581 localIDs.Add(d.ObjectLocalID);
9582
9583 ObjectOwner handlerObjectOwner = OnObjectOwner;
9584 if (handlerObjectOwner != null)
9585 {
9586 handlerObjectOwner(this, objectOwnerPacket.HeaderData.OwnerID, objectOwnerPacket.HeaderData.GroupID, localIDs);
9587 }
9588 return true;
9589 }
9590
9591 #endregion Gesture Managment
9592
9593 private bool HandleAgentFOV(IClientAPI sender, Packet Pack)
9594 {
9595 AgentFOVPacket fovPacket = (AgentFOVPacket)Pack;
9596
9597 if (fovPacket.FOVBlock.GenCounter > m_agentFOVCounter)
9598 {
9599 m_agentFOVCounter = fovPacket.FOVBlock.GenCounter;
9600 AgentFOV handlerAgentFOV = OnAgentFOV;
9601 if (handlerAgentFOV != null)
9602 {
9603 handlerAgentFOV(this, fovPacket.FOVBlock.VerticalAngle);
9604 }
9605 }
9606 return true;
9607 }
9608
9609 #region unimplemented handlers
9610
9611 private bool HandleViewerStats(IClientAPI sender, Packet Pack)
9612 {
9613 // TODO: handle this packet
9614 //m_log.Warn("[CLIENT]: unhandled ViewerStats packet");
9615 return true;
9616 }
9617
9618 private bool HandleMapItemRequest(IClientAPI sender, Packet Pack)
9619 {
9620 MapItemRequestPacket mirpk = (MapItemRequestPacket)Pack;
9621
9622 #region Packet Session and User Check
9623 if (m_checkPackets)
9624 {
9625 if (mirpk.AgentData.SessionID != SessionId ||
9626 mirpk.AgentData.AgentID != AgentId)
9627 return true;
9628 }
9629 #endregion
9630
9631 //m_log.Debug(mirpk.ToString());
9632 MapItemRequest handlerMapItemRequest = OnMapItemRequest;
9633 if (handlerMapItemRequest != null)
9634 {
9635 handlerMapItemRequest(this, mirpk.AgentData.Flags, mirpk.AgentData.EstateID,
9636 mirpk.AgentData.Godlike, mirpk.RequestData.ItemType,
9637 mirpk.RequestData.RegionHandle);
9638
9639 }
9640 return true;
9641 }
9642
9643 private bool HandleTransferAbort(IClientAPI sender, Packet Pack)
9644 {
9645 return true;
9646 }
9647
9648 private bool HandleMuteListRequest(IClientAPI sender, Packet Pack)
9649 {
9650 MuteListRequestPacket muteListRequest =
9651 (MuteListRequestPacket)Pack;
9652
9653 #region Packet Session and User Check
9654 if (m_checkPackets)
9655 {
9656 if (muteListRequest.AgentData.SessionID != SessionId ||
9657 muteListRequest.AgentData.AgentID != AgentId)
9658 return true;
9659 }
9660 #endregion
9661
9662 MuteListRequest handlerMuteListRequest = OnMuteListRequest;
9663 if (handlerMuteListRequest != null)
9664 {
9665 handlerMuteListRequest(this, muteListRequest.MuteData.MuteCRC);
9666 }
9667 else
9668 {
9669 SendUseCachedMuteList();
9670 }
9671 return true;
9672 }
9673
9674 private bool HandleUpdateMuteListEntry(IClientAPI client, Packet Packet)
9675 {
9676 UpdateMuteListEntryPacket UpdateMuteListEntry =
9677 (UpdateMuteListEntryPacket)Packet;
9678 MuteListEntryUpdate handlerUpdateMuteListEntry = OnUpdateMuteListEntry;
9679 if (handlerUpdateMuteListEntry != null)
9680 {
9681 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9682 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9683 UpdateMuteListEntry.MuteData.MuteType,
9684 UpdateMuteListEntry.MuteData.MuteFlags);
9685 return true;
9686 }
9687 return false;
9688 }
9689
9690 private bool HandleRemoveMuteListEntry(IClientAPI client, Packet Packet)
9691 {
9692 RemoveMuteListEntryPacket RemoveMuteListEntry =
9693 (RemoveMuteListEntryPacket)Packet;
9694 MuteListEntryRemove handlerRemoveMuteListEntry = OnRemoveMuteListEntry;
9695 if (handlerRemoveMuteListEntry != null)
9696 {
9697 handlerRemoveMuteListEntry(this,
9698 RemoveMuteListEntry.MuteData.MuteID,
9699 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9700 return true;
9701 }
9702 return false;
9703 }
9704
9705 private bool HandleUserReport(IClientAPI client, Packet Packet)
9706 {
9707 UserReportPacket UserReport =
9708 (UserReportPacket)Packet;
9709
9710 NewUserReport handlerUserReport = OnUserReport;
9711 if (handlerUserReport != null)
9712 {
9713 handlerUserReport(this,
9714 Utils.BytesToString(UserReport.ReportData.AbuseRegionName),
9715 UserReport.ReportData.AbuserID,
9716 UserReport.ReportData.Category,
9717 UserReport.ReportData.CheckFlags,
9718 Utils.BytesToString(UserReport.ReportData.Details),
9719 UserReport.ReportData.ObjectID,
9720 UserReport.ReportData.Position,
9721 UserReport.ReportData.ReportType,
9722 UserReport.ReportData.ScreenshotID,
9723 Utils.BytesToString(UserReport.ReportData.Summary),
9724 UserReport.AgentData.AgentID);
9725 return true;
9726 }
9727 return false;
9728 }
9729
9730 private bool HandleSendPostcard(IClientAPI client, Packet packet)
9731 {
9732// SendPostcardPacket SendPostcard =
9733// (SendPostcardPacket)packet;
9734 SendPostcard handlerSendPostcard = OnSendPostcard;
9735 if (handlerSendPostcard != null)
9736 {
9737 handlerSendPostcard(this);
9738 return true;
9739 }
9740 return false;
9741 }
9742
9743 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack)
9744 {
9745 return true;
9746 }
9747
9748 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
9749 {
9750 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
9751
9752 #region Packet Session and User Check
9753 if (m_checkPackets)
9754 {
9755 if (packet.AgentData.SessionID != SessionId ||
9756 packet.AgentData.AgentID != AgentId)
9757 return true;
9758 }
9759 #endregion
9760 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
9761 List<InventoryItemBase> items = new List<InventoryItemBase>();
9762 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
9763 {
9764 InventoryItemBase b = new InventoryItemBase();
9765 b.ID = n.OldItemID;
9766 b.Folder = n.OldFolderID;
9767 items.Add(b);
9768 }
9769
9770 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
9771 if (handlerMoveItemsAndLeaveCopy != null)
9772 {
9773 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
9774 }
9775
9776 return true;
9777 }
9778
9779 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9780 {
9781 return true;
9782 }
9783
9784 private bool HandleInventoryDescendents(IClientAPI sender, Packet Pack)
9785 {
9786 return true;
9787 }
9788
9789 #endregion unimplemented handlers
9790
9791 #region Dir handlers
9792
9793 private bool HandleDirPlacesQuery(IClientAPI sender, Packet Pack)
9794 {
9795 DirPlacesQueryPacket dirPlacesQueryPacket = (DirPlacesQueryPacket)Pack;
9796 //m_log.Debug(dirPlacesQueryPacket.ToString());
9797
9798 #region Packet Session and User Check
9799 if (m_checkPackets)
9800 {
9801 if (dirPlacesQueryPacket.AgentData.SessionID != SessionId ||
9802 dirPlacesQueryPacket.AgentData.AgentID != AgentId)
9803 return true;
9804 }
9805 #endregion
9806
9807 DirPlacesQuery handlerDirPlacesQuery = OnDirPlacesQuery;
9808 if (handlerDirPlacesQuery != null)
9809 {
9810 handlerDirPlacesQuery(this,
9811 dirPlacesQueryPacket.QueryData.QueryID,
9812 Utils.BytesToString(
9813 dirPlacesQueryPacket.QueryData.QueryText),
9814 (int)dirPlacesQueryPacket.QueryData.QueryFlags,
9815 (int)dirPlacesQueryPacket.QueryData.Category,
9816 Utils.BytesToString(
9817 dirPlacesQueryPacket.QueryData.SimName),
9818 dirPlacesQueryPacket.QueryData.QueryStart);
9819 }
9820 return true;
9821 }
9822
9823 private bool HandleDirFindQuery(IClientAPI sender, Packet Pack)
9824 {
9825 DirFindQueryPacket dirFindQueryPacket = (DirFindQueryPacket)Pack;
9826
9827 #region Packet Session and User Check
9828 if (m_checkPackets)
9829 {
9830 if (dirFindQueryPacket.AgentData.SessionID != SessionId ||
9831 dirFindQueryPacket.AgentData.AgentID != AgentId)
9832 return true;
9833 }
9834 #endregion
9835
9836 DirFindQuery handlerDirFindQuery = OnDirFindQuery;
9837 if (handlerDirFindQuery != null)
9838 {
9839 handlerDirFindQuery(this,
9840 dirFindQueryPacket.QueryData.QueryID,
9841 Utils.BytesToString(
9842 dirFindQueryPacket.QueryData.QueryText),
9843 dirFindQueryPacket.QueryData.QueryFlags,
9844 dirFindQueryPacket.QueryData.QueryStart);
9845 }
9846 return true;
9847 }
9848
9849 private bool HandleDirLandQuery(IClientAPI sender, Packet Pack)
9850 {
9851 DirLandQueryPacket dirLandQueryPacket = (DirLandQueryPacket)Pack;
9852
9853 #region Packet Session and User Check
9854 if (m_checkPackets)
9855 {
9856 if (dirLandQueryPacket.AgentData.SessionID != SessionId ||
9857 dirLandQueryPacket.AgentData.AgentID != AgentId)
9858 return true;
9859 }
9860 #endregion
9861
9862 DirLandQuery handlerDirLandQuery = OnDirLandQuery;
9863 if (handlerDirLandQuery != null)
9864 {
9865 handlerDirLandQuery(this,
9866 dirLandQueryPacket.QueryData.QueryID,
9867 dirLandQueryPacket.QueryData.QueryFlags,
9868 dirLandQueryPacket.QueryData.SearchType,
9869 dirLandQueryPacket.QueryData.Price,
9870 dirLandQueryPacket.QueryData.Area,
9871 dirLandQueryPacket.QueryData.QueryStart);
9872 }
9873 return true;
9874 }
9875
9876 private bool HandleDirPopularQuery(IClientAPI sender, Packet Pack)
9877 {
9878 DirPopularQueryPacket dirPopularQueryPacket = (DirPopularQueryPacket)Pack;
9879
9880 #region Packet Session and User Check
9881 if (m_checkPackets)
9882 {
9883 if (dirPopularQueryPacket.AgentData.SessionID != SessionId ||
9884 dirPopularQueryPacket.AgentData.AgentID != AgentId)
9885 return true;
9886 }
9887 #endregion
9888
9889 DirPopularQuery handlerDirPopularQuery = OnDirPopularQuery;
9890 if (handlerDirPopularQuery != null)
9891 {
9892 handlerDirPopularQuery(this,
9893 dirPopularQueryPacket.QueryData.QueryID,
9894 dirPopularQueryPacket.QueryData.QueryFlags);
9895 }
9896 return true;
9897 }
9898
9899 private bool HandleDirClassifiedQuery(IClientAPI sender, Packet Pack)
9900 {
9901 DirClassifiedQueryPacket dirClassifiedQueryPacket = (DirClassifiedQueryPacket)Pack;
9902
9903 #region Packet Session and User Check
9904 if (m_checkPackets)
9905 {
9906 if (dirClassifiedQueryPacket.AgentData.SessionID != SessionId ||
9907 dirClassifiedQueryPacket.AgentData.AgentID != AgentId)
9908 return true;
9909 }
9910 #endregion
9911
9912 DirClassifiedQuery handlerDirClassifiedQuery = OnDirClassifiedQuery;
9913 if (handlerDirClassifiedQuery != null)
9914 {
9915 handlerDirClassifiedQuery(this,
9916 dirClassifiedQueryPacket.QueryData.QueryID,
9917 Utils.BytesToString(
9918 dirClassifiedQueryPacket.QueryData.QueryText),
9919 dirClassifiedQueryPacket.QueryData.QueryFlags,
9920 dirClassifiedQueryPacket.QueryData.Category,
9921 dirClassifiedQueryPacket.QueryData.QueryStart);
9922 }
9923 return true;
9924 }
9925
9926 private bool HandleEventInfoRequest(IClientAPI sender, Packet Pack)
9927 {
9928 EventInfoRequestPacket eventInfoRequestPacket = (EventInfoRequestPacket)Pack;
9929
9930 #region Packet Session and User Check
9931 if (m_checkPackets)
9932 {
9933 if (eventInfoRequestPacket.AgentData.SessionID != SessionId ||
9934 eventInfoRequestPacket.AgentData.AgentID != AgentId)
9935 return true;
9936 }
9937 #endregion
9938
9939 if (OnEventInfoRequest != null)
9940 {
9941 OnEventInfoRequest(this, eventInfoRequestPacket.EventData.EventID);
9942 }
9943 return true;
9944 }
9945
9946 #endregion
9947
9948 #region Calling Card
9949
9950 private bool HandleOfferCallingCard(IClientAPI sender, Packet Pack)
9951 {
9952 OfferCallingCardPacket offerCallingCardPacket = (OfferCallingCardPacket)Pack;
9953
9954 #region Packet Session and User Check
9955 if (m_checkPackets)
9956 {
9957 if (offerCallingCardPacket.AgentData.SessionID != SessionId ||
9958 offerCallingCardPacket.AgentData.AgentID != AgentId)
9959 return true;
9960 }
9961 #endregion
9962
9963 if (OnOfferCallingCard != null)
9964 {
9965 OnOfferCallingCard(this,
9966 offerCallingCardPacket.AgentBlock.DestID,
9967 offerCallingCardPacket.AgentBlock.TransactionID);
9968 }
9969 return true;
9970 }
9971
9972 private bool HandleAcceptCallingCard(IClientAPI sender, Packet Pack)
9973 {
9974 AcceptCallingCardPacket acceptCallingCardPacket = (AcceptCallingCardPacket)Pack;
9975
9976 #region Packet Session and User Check
9977 if (m_checkPackets)
9978 {
9979 if (acceptCallingCardPacket.AgentData.SessionID != SessionId ||
9980 acceptCallingCardPacket.AgentData.AgentID != AgentId)
9981 return true;
9982 }
9983 #endregion
9984
9985 // according to http://wiki.secondlife.com/wiki/AcceptCallingCard FolderData should
9986 // contain exactly one entry
9987 if (OnAcceptCallingCard != null && acceptCallingCardPacket.FolderData.Length > 0)
9988 {
9989 OnAcceptCallingCard(this,
9990 acceptCallingCardPacket.TransactionBlock.TransactionID,
9991 acceptCallingCardPacket.FolderData[0].FolderID);
9992 }
9993 return true;
9994 }
9995
9996 private bool HandleDeclineCallingCard(IClientAPI sender, Packet Pack)
9997 {
9998 DeclineCallingCardPacket declineCallingCardPacket = (DeclineCallingCardPacket)Pack;
9999
10000 #region Packet Session and User Check
10001 if (m_checkPackets)
10002 {
10003 if (declineCallingCardPacket.AgentData.SessionID != SessionId ||
10004 declineCallingCardPacket.AgentData.AgentID != AgentId)
10005 return true;
10006 }
10007 #endregion
10008
10009 if (OnDeclineCallingCard != null)
10010 {
10011 OnDeclineCallingCard(this,
10012 declineCallingCardPacket.TransactionBlock.TransactionID);
10013 }
10014 return true;
10015 }
10016
10017 #endregion Calling Card
10018
10019 #region Groups
10020
10021 private bool HandleActivateGroup(IClientAPI sender, Packet Pack)
10022 {
10023 ActivateGroupPacket activateGroupPacket = (ActivateGroupPacket)Pack;
10024
10025 #region Packet Session and User Check
10026 if (m_checkPackets)
10027 {
10028 if (activateGroupPacket.AgentData.SessionID != SessionId ||
10029 activateGroupPacket.AgentData.AgentID != AgentId)
10030 return true;
10031 }
10032 #endregion
10033
10034 if (m_GroupsModule != null)
10035 {
10036 m_GroupsModule.ActivateGroup(this, activateGroupPacket.AgentData.GroupID);
10037 m_GroupsModule.SendAgentGroupDataUpdate(this);
10038 }
10039 return true;
10040
10041 }
10042
10043 private bool HandleGroupVoteHistoryRequest(IClientAPI client, Packet Packet)
10044 {
10045 GroupVoteHistoryRequestPacket GroupVoteHistoryRequest =
10046 (GroupVoteHistoryRequestPacket)Packet;
10047 GroupVoteHistoryRequest handlerGroupVoteHistoryRequest = OnGroupVoteHistoryRequest;
10048 if (handlerGroupVoteHistoryRequest != null)
10049 {
10050 handlerGroupVoteHistoryRequest(this, GroupVoteHistoryRequest.AgentData.AgentID,GroupVoteHistoryRequest.AgentData.SessionID,GroupVoteHistoryRequest.GroupData.GroupID,GroupVoteHistoryRequest.TransactionData.TransactionID);
10051 return true;
10052 }
10053 return false;
10054 }
10055
10056 private bool HandleGroupActiveProposalsRequest(IClientAPI client, Packet Packet)
10057 {
10058 GroupActiveProposalsRequestPacket GroupActiveProposalsRequest =
10059 (GroupActiveProposalsRequestPacket)Packet;
10060 GroupActiveProposalsRequest handlerGroupActiveProposalsRequest = OnGroupActiveProposalsRequest;
10061 if (handlerGroupActiveProposalsRequest != null)
10062 {
10063 handlerGroupActiveProposalsRequest(this, GroupActiveProposalsRequest.AgentData.AgentID,GroupActiveProposalsRequest.AgentData.SessionID,GroupActiveProposalsRequest.GroupData.GroupID,GroupActiveProposalsRequest.TransactionData.TransactionID);
10064 return true;
10065 }
10066 return false;
10067 }
10068
10069 private bool HandleGroupAccountDetailsRequest(IClientAPI client, Packet Packet)
10070 {
10071 GroupAccountDetailsRequestPacket GroupAccountDetailsRequest =
10072 (GroupAccountDetailsRequestPacket)Packet;
10073 GroupAccountDetailsRequest handlerGroupAccountDetailsRequest = OnGroupAccountDetailsRequest;
10074 if (handlerGroupAccountDetailsRequest != null)
10075 {
10076 handlerGroupAccountDetailsRequest(this, GroupAccountDetailsRequest.AgentData.AgentID,GroupAccountDetailsRequest.AgentData.GroupID,GroupAccountDetailsRequest.MoneyData.RequestID,GroupAccountDetailsRequest.AgentData.SessionID);
10077 return true;
10078 }
10079 return false;
10080 }
10081
10082 private bool HandleGroupAccountSummaryRequest(IClientAPI client, Packet Packet)
10083 {
10084 GroupAccountSummaryRequestPacket GroupAccountSummaryRequest =
10085 (GroupAccountSummaryRequestPacket)Packet;
10086 GroupAccountSummaryRequest handlerGroupAccountSummaryRequest = OnGroupAccountSummaryRequest;
10087 if (handlerGroupAccountSummaryRequest != null)
10088 {
10089 handlerGroupAccountSummaryRequest(this, GroupAccountSummaryRequest.AgentData.AgentID,GroupAccountSummaryRequest.AgentData.GroupID);
10090 return true;
10091 }
10092 return false;
10093 }
10094
10095 private bool HandleGroupTransactionsDetailsRequest(IClientAPI client, Packet Packet)
10096 {
10097 GroupAccountTransactionsRequestPacket GroupAccountTransactionsRequest =
10098 (GroupAccountTransactionsRequestPacket)Packet;
10099 GroupAccountTransactionsRequest handlerGroupAccountTransactionsRequest = OnGroupAccountTransactionsRequest;
10100 if (handlerGroupAccountTransactionsRequest != null)
10101 {
10102 handlerGroupAccountTransactionsRequest(this, GroupAccountTransactionsRequest.AgentData.AgentID,GroupAccountTransactionsRequest.AgentData.GroupID,GroupAccountTransactionsRequest.MoneyData.RequestID,GroupAccountTransactionsRequest.AgentData.SessionID);
10103 return true;
10104 }
10105 return false;
10106 }
10107
10108 private bool HandleGroupTitlesRequest(IClientAPI sender, Packet Pack)
10109 {
10110 GroupTitlesRequestPacket groupTitlesRequest =
10111 (GroupTitlesRequestPacket)Pack;
10112
10113 #region Packet Session and User Check
10114 if (m_checkPackets)
10115 {
10116 if (groupTitlesRequest.AgentData.SessionID != SessionId ||
10117 groupTitlesRequest.AgentData.AgentID != AgentId)
10118 return true;
10119 }
10120 #endregion
10121
10122 if (m_GroupsModule != null)
10123 {
10124 GroupTitlesReplyPacket groupTitlesReply = (GroupTitlesReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupTitlesReply);
10125
10126 groupTitlesReply.AgentData =
10127 new GroupTitlesReplyPacket.AgentDataBlock();
10128
10129 groupTitlesReply.AgentData.AgentID = AgentId;
10130 groupTitlesReply.AgentData.GroupID =
10131 groupTitlesRequest.AgentData.GroupID;
10132
10133 groupTitlesReply.AgentData.RequestID =
10134 groupTitlesRequest.AgentData.RequestID;
10135
10136 List<GroupTitlesData> titles =
10137 m_GroupsModule.GroupTitlesRequest(this,
10138 groupTitlesRequest.AgentData.GroupID);
10139
10140 groupTitlesReply.GroupData =
10141 new GroupTitlesReplyPacket.GroupDataBlock[titles.Count];
10142
10143 int i = 0;
10144 foreach (GroupTitlesData d in titles)
10145 {
10146 groupTitlesReply.GroupData[i] =
10147 new GroupTitlesReplyPacket.GroupDataBlock();
10148
10149 groupTitlesReply.GroupData[i].Title =
10150 Util.StringToBytes256(d.Name);
10151 groupTitlesReply.GroupData[i].RoleID =
10152 d.UUID;
10153 groupTitlesReply.GroupData[i].Selected =
10154 d.Selected;
10155 i++;
10156 }
10157
10158 OutPacket(groupTitlesReply, ThrottleOutPacketType.Task);
10159 }
10160 return true;
10161 }
10162 private bool HandleGroupProfileRequest(IClientAPI sender, Packet Pack)
10163 {
10164 GroupProfileRequestPacket groupProfileRequest =
10165 (GroupProfileRequestPacket)Pack;
10166
10167 #region Packet Session and User Check
10168 if (m_checkPackets)
10169 {
10170 if (groupProfileRequest.AgentData.SessionID != SessionId ||
10171 groupProfileRequest.AgentData.AgentID != AgentId)
10172 return true;
10173 }
10174 #endregion
10175
10176 if (m_GroupsModule != null)
10177 {
10178 GroupProfileReplyPacket groupProfileReply = (GroupProfileReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupProfileReply);
10179
10180 groupProfileReply.AgentData = new GroupProfileReplyPacket.AgentDataBlock();
10181 groupProfileReply.GroupData = new GroupProfileReplyPacket.GroupDataBlock();
10182 groupProfileReply.AgentData.AgentID = AgentId;
10183
10184 GroupProfileData d = m_GroupsModule.GroupProfileRequest(this,
10185 groupProfileRequest.GroupData.GroupID);
10186
10187 groupProfileReply.GroupData.GroupID = d.GroupID;
10188 groupProfileReply.GroupData.Name = Util.StringToBytes256(d.Name);
10189 groupProfileReply.GroupData.Charter = Util.StringToBytes1024(d.Charter);
10190 groupProfileReply.GroupData.ShowInList = d.ShowInList;
10191 groupProfileReply.GroupData.MemberTitle = Util.StringToBytes256(d.MemberTitle);
10192 groupProfileReply.GroupData.PowersMask = d.PowersMask;
10193 groupProfileReply.GroupData.InsigniaID = d.InsigniaID;
10194 groupProfileReply.GroupData.FounderID = d.FounderID;
10195 groupProfileReply.GroupData.MembershipFee = d.MembershipFee;
10196 groupProfileReply.GroupData.OpenEnrollment = d.OpenEnrollment;
10197 groupProfileReply.GroupData.Money = d.Money;
10198 groupProfileReply.GroupData.GroupMembershipCount = d.GroupMembershipCount;
10199 groupProfileReply.GroupData.GroupRolesCount = d.GroupRolesCount;
10200 groupProfileReply.GroupData.AllowPublish = d.AllowPublish;
10201 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10202 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10203
10204 Scene scene = (Scene)m_scene;
10205 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
10206 {
10207 ScenePresence p;
10208 if (scene.TryGetScenePresence(sender.AgentId, out p))
10209 {
10210 if (p.GodLevel >= 200)
10211 {
10212 groupProfileReply.GroupData.OpenEnrollment = true;
10213 groupProfileReply.GroupData.MembershipFee = 0;
10214 }
10215 }
10216 }
10217
10218 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10219 }
10220 return true;
10221 }
10222 private bool HandleGroupMembersRequest(IClientAPI sender, Packet Pack)
10223 {
10224 GroupMembersRequestPacket groupMembersRequestPacket =
10225 (GroupMembersRequestPacket)Pack;
10226
10227 #region Packet Session and User Check
10228 if (m_checkPackets)
10229 {
10230 if (groupMembersRequestPacket.AgentData.SessionID != SessionId ||
10231 groupMembersRequestPacket.AgentData.AgentID != AgentId)
10232 return true;
10233 }
10234 #endregion
10235
10236 if (m_GroupsModule != null)
10237 {
10238 List<GroupMembersData> members =
10239 m_GroupsModule.GroupMembersRequest(this, groupMembersRequestPacket.GroupData.GroupID);
10240
10241 int memberCount = members.Count;
10242
10243 while (true)
10244 {
10245 int blockCount = members.Count;
10246 if (blockCount > 40)
10247 blockCount = 40;
10248
10249 GroupMembersReplyPacket groupMembersReply = (GroupMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupMembersReply);
10250
10251 groupMembersReply.AgentData =
10252 new GroupMembersReplyPacket.AgentDataBlock();
10253 groupMembersReply.GroupData =
10254 new GroupMembersReplyPacket.GroupDataBlock();
10255 groupMembersReply.MemberData =
10256 new GroupMembersReplyPacket.MemberDataBlock[
10257 blockCount];
10258
10259 groupMembersReply.AgentData.AgentID = AgentId;
10260 groupMembersReply.GroupData.GroupID =
10261 groupMembersRequestPacket.GroupData.GroupID;
10262 groupMembersReply.GroupData.RequestID =
10263 groupMembersRequestPacket.GroupData.RequestID;
10264 groupMembersReply.GroupData.MemberCount = memberCount;
10265
10266 for (int i = 0; i < blockCount; i++)
10267 {
10268 GroupMembersData m = members[0];
10269 members.RemoveAt(0);
10270
10271 groupMembersReply.MemberData[i] =
10272 new GroupMembersReplyPacket.MemberDataBlock();
10273 groupMembersReply.MemberData[i].AgentID =
10274 m.AgentID;
10275 groupMembersReply.MemberData[i].Contribution =
10276 m.Contribution;
10277 groupMembersReply.MemberData[i].OnlineStatus =
10278 Util.StringToBytes256(m.OnlineStatus);
10279 groupMembersReply.MemberData[i].AgentPowers =
10280 m.AgentPowers;
10281 groupMembersReply.MemberData[i].Title =
10282 Util.StringToBytes256(m.Title);
10283 groupMembersReply.MemberData[i].IsOwner =
10284 m.IsOwner;
10285 }
10286 OutPacket(groupMembersReply, ThrottleOutPacketType.Task);
10287 if (members.Count == 0)
10288 return true;
10289 }
10290 }
10291 return true;
10292 }
10293 private bool HandleGroupRoleDataRequest(IClientAPI sender, Packet Pack)
10294 {
10295 GroupRoleDataRequestPacket groupRolesRequest =
10296 (GroupRoleDataRequestPacket)Pack;
10297
10298 #region Packet Session and User Check
10299 if (m_checkPackets)
10300 {
10301 if (groupRolesRequest.AgentData.SessionID != SessionId ||
10302 groupRolesRequest.AgentData.AgentID != AgentId)
10303 return true;
10304 }
10305 #endregion
10306
10307 if (m_GroupsModule != null)
10308 {
10309 GroupRoleDataReplyPacket groupRolesReply = (GroupRoleDataReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleDataReply);
10310
10311 groupRolesReply.AgentData =
10312 new GroupRoleDataReplyPacket.AgentDataBlock();
10313
10314 groupRolesReply.AgentData.AgentID = AgentId;
10315
10316 groupRolesReply.GroupData =
10317 new GroupRoleDataReplyPacket.GroupDataBlock();
10318
10319 groupRolesReply.GroupData.GroupID =
10320 groupRolesRequest.GroupData.GroupID;
10321
10322 groupRolesReply.GroupData.RequestID =
10323 groupRolesRequest.GroupData.RequestID;
10324
10325 List<GroupRolesData> titles =
10326 m_GroupsModule.GroupRoleDataRequest(this,
10327 groupRolesRequest.GroupData.GroupID);
10328
10329 groupRolesReply.GroupData.RoleCount =
10330 titles.Count;
10331
10332 groupRolesReply.RoleData =
10333 new GroupRoleDataReplyPacket.RoleDataBlock[titles.Count];
10334
10335 int i = 0;
10336 foreach (GroupRolesData d in titles)
10337 {
10338 groupRolesReply.RoleData[i] =
10339 new GroupRoleDataReplyPacket.RoleDataBlock();
10340
10341 groupRolesReply.RoleData[i].RoleID =
10342 d.RoleID;
10343 groupRolesReply.RoleData[i].Name =
10344 Util.StringToBytes256(d.Name);
10345 groupRolesReply.RoleData[i].Title =
10346 Util.StringToBytes256(d.Title);
10347 groupRolesReply.RoleData[i].Description =
10348 Util.StringToBytes1024(d.Description);
10349 groupRolesReply.RoleData[i].Powers =
10350 d.Powers;
10351 groupRolesReply.RoleData[i].Members =
10352 (uint)d.Members;
10353
10354 i++;
10355 }
10356
10357 OutPacket(groupRolesReply, ThrottleOutPacketType.Task);
10358 }
10359 return true;
10360 }
10361 private bool HandleGroupRoleMembersRequest(IClientAPI sender, Packet Pack)
10362 {
10363 GroupRoleMembersRequestPacket groupRoleMembersRequest =
10364 (GroupRoleMembersRequestPacket)Pack;
10365
10366 #region Packet Session and User Check
10367 if (m_checkPackets)
10368 {
10369 if (groupRoleMembersRequest.AgentData.SessionID != SessionId ||
10370 groupRoleMembersRequest.AgentData.AgentID != AgentId)
10371 return true;
10372 }
10373 #endregion
10374
10375 if (m_GroupsModule != null)
10376 {
10377 List<GroupRoleMembersData> mappings =
10378 m_GroupsModule.GroupRoleMembersRequest(this,
10379 groupRoleMembersRequest.GroupData.GroupID);
10380
10381 int mappingsCount = mappings.Count;
10382
10383 while (mappings.Count > 0)
10384 {
10385 int pairs = mappings.Count;
10386 if (pairs > 32)
10387 pairs = 32;
10388
10389 GroupRoleMembersReplyPacket groupRoleMembersReply = (GroupRoleMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleMembersReply);
10390 groupRoleMembersReply.AgentData =
10391 new GroupRoleMembersReplyPacket.AgentDataBlock();
10392 groupRoleMembersReply.AgentData.AgentID =
10393 AgentId;
10394 groupRoleMembersReply.AgentData.GroupID =
10395 groupRoleMembersRequest.GroupData.GroupID;
10396 groupRoleMembersReply.AgentData.RequestID =
10397 groupRoleMembersRequest.GroupData.RequestID;
10398
10399 groupRoleMembersReply.AgentData.TotalPairs =
10400 (uint)mappingsCount;
10401
10402 groupRoleMembersReply.MemberData =
10403 new GroupRoleMembersReplyPacket.MemberDataBlock[pairs];
10404
10405 for (int i = 0; i < pairs; i++)
10406 {
10407 GroupRoleMembersData d = mappings[0];
10408 mappings.RemoveAt(0);
10409
10410 groupRoleMembersReply.MemberData[i] =
10411 new GroupRoleMembersReplyPacket.MemberDataBlock();
10412
10413 groupRoleMembersReply.MemberData[i].RoleID =
10414 d.RoleID;
10415 groupRoleMembersReply.MemberData[i].MemberID =
10416 d.MemberID;
10417 }
10418
10419 OutPacket(groupRoleMembersReply, ThrottleOutPacketType.Task);
10420 }
10421 }
10422 return true;
10423 }
10424 private bool HandleCreateGroupRequest(IClientAPI sender, Packet Pack)
10425 {
10426 CreateGroupRequestPacket createGroupRequest =
10427 (CreateGroupRequestPacket)Pack;
10428
10429 #region Packet Session and User Check
10430 if (m_checkPackets)
10431 {
10432 if (createGroupRequest.AgentData.SessionID != SessionId ||
10433 createGroupRequest.AgentData.AgentID != AgentId)
10434 return true;
10435 }
10436 #endregion
10437
10438 if (m_GroupsModule != null)
10439 {
10440 m_GroupsModule.CreateGroup(this,
10441 Utils.BytesToString(createGroupRequest.GroupData.Name),
10442 Utils.BytesToString(createGroupRequest.GroupData.Charter),
10443 createGroupRequest.GroupData.ShowInList,
10444 createGroupRequest.GroupData.InsigniaID,
10445 createGroupRequest.GroupData.MembershipFee,
10446 createGroupRequest.GroupData.OpenEnrollment,
10447 createGroupRequest.GroupData.AllowPublish,
10448 createGroupRequest.GroupData.MaturePublish);
10449 }
10450 return true;
10451 }
10452 private bool HandleUpdateGroupInfo(IClientAPI sender, Packet Pack)
10453 {
10454 UpdateGroupInfoPacket updateGroupInfo =
10455 (UpdateGroupInfoPacket)Pack;
10456
10457 #region Packet Session and User Check
10458 if (m_checkPackets)
10459 {
10460 if (updateGroupInfo.AgentData.SessionID != SessionId ||
10461 updateGroupInfo.AgentData.AgentID != AgentId)
10462 return true;
10463 }
10464 #endregion
10465
10466 if (m_GroupsModule != null)
10467 {
10468 m_GroupsModule.UpdateGroupInfo(this,
10469 updateGroupInfo.GroupData.GroupID,
10470 Utils.BytesToString(updateGroupInfo.GroupData.Charter),
10471 updateGroupInfo.GroupData.ShowInList,
10472 updateGroupInfo.GroupData.InsigniaID,
10473 updateGroupInfo.GroupData.MembershipFee,
10474 updateGroupInfo.GroupData.OpenEnrollment,
10475 updateGroupInfo.GroupData.AllowPublish,
10476 updateGroupInfo.GroupData.MaturePublish);
10477 }
10478
10479 return true;
10480 }
10481 private bool HandleSetGroupAcceptNotices(IClientAPI sender, Packet Pack)
10482 {
10483 SetGroupAcceptNoticesPacket setGroupAcceptNotices =
10484 (SetGroupAcceptNoticesPacket)Pack;
10485
10486 #region Packet Session and User Check
10487 if (m_checkPackets)
10488 {
10489 if (setGroupAcceptNotices.AgentData.SessionID != SessionId ||
10490 setGroupAcceptNotices.AgentData.AgentID != AgentId)
10491 return true;
10492 }
10493 #endregion
10494
10495 if (m_GroupsModule != null)
10496 {
10497 m_GroupsModule.SetGroupAcceptNotices(this,
10498 setGroupAcceptNotices.Data.GroupID,
10499 setGroupAcceptNotices.Data.AcceptNotices,
10500 setGroupAcceptNotices.NewData.ListInProfile);
10501 }
10502
10503 return true;
10504 }
10505 private bool HandleGroupTitleUpdate(IClientAPI sender, Packet Pack)
10506 {
10507 GroupTitleUpdatePacket groupTitleUpdate =
10508 (GroupTitleUpdatePacket)Pack;
10509
10510 #region Packet Session and User Check
10511 if (m_checkPackets)
10512 {
10513 if (groupTitleUpdate.AgentData.SessionID != SessionId ||
10514 groupTitleUpdate.AgentData.AgentID != AgentId)
10515 return true;
10516 }
10517 #endregion
10518
10519 if (m_GroupsModule != null)
10520 {
10521 m_GroupsModule.GroupTitleUpdate(this,
10522 groupTitleUpdate.AgentData.GroupID,
10523 groupTitleUpdate.AgentData.TitleRoleID);
10524 }
10525
10526 return true;
10527 }
10528 private bool HandleParcelDeedToGroup(IClientAPI sender, Packet Pack)
10529 {
10530 ParcelDeedToGroupPacket parcelDeedToGroup = (ParcelDeedToGroupPacket)Pack;
10531 if (m_GroupsModule != null)
10532 {
10533 ParcelDeedToGroup handlerParcelDeedToGroup = OnParcelDeedToGroup;
10534 if (handlerParcelDeedToGroup != null)
10535 {
10536 handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID, this);
10537
10538 }
10539 }
10540
10541 return true;
10542 }
10543 private bool HandleGroupNoticesListRequest(IClientAPI sender, Packet Pack)
10544 {
10545 GroupNoticesListRequestPacket groupNoticesListRequest =
10546 (GroupNoticesListRequestPacket)Pack;
10547
10548 #region Packet Session and User Check
10549 if (m_checkPackets)
10550 {
10551 if (groupNoticesListRequest.AgentData.SessionID != SessionId ||
10552 groupNoticesListRequest.AgentData.AgentID != AgentId)
10553 return true;
10554 }
10555 #endregion
10556
10557 if (m_GroupsModule != null)
10558 {
10559 GroupNoticeData[] gn =
10560 m_GroupsModule.GroupNoticesListRequest(this,
10561 groupNoticesListRequest.Data.GroupID);
10562
10563 GroupNoticesListReplyPacket groupNoticesListReply = (GroupNoticesListReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupNoticesListReply);
10564 groupNoticesListReply.AgentData =
10565 new GroupNoticesListReplyPacket.AgentDataBlock();
10566 groupNoticesListReply.AgentData.AgentID = AgentId;
10567 groupNoticesListReply.AgentData.GroupID = groupNoticesListRequest.Data.GroupID;
10568
10569 groupNoticesListReply.Data = new GroupNoticesListReplyPacket.DataBlock[gn.Length];
10570
10571 int i = 0;
10572 foreach (GroupNoticeData g in gn)
10573 {
10574 groupNoticesListReply.Data[i] = new GroupNoticesListReplyPacket.DataBlock();
10575 groupNoticesListReply.Data[i].NoticeID =
10576 g.NoticeID;
10577 groupNoticesListReply.Data[i].Timestamp =
10578 g.Timestamp;
10579 groupNoticesListReply.Data[i].FromName =
10580 Util.StringToBytes256(g.FromName);
10581 groupNoticesListReply.Data[i].Subject =
10582 Util.StringToBytes256(g.Subject);
10583 groupNoticesListReply.Data[i].HasAttachment =
10584 g.HasAttachment;
10585 groupNoticesListReply.Data[i].AssetType =
10586 g.AssetType;
10587 i++;
10588 }
10589
10590 OutPacket(groupNoticesListReply, ThrottleOutPacketType.Task);
10591 }
10592
10593 return true;
10594 }
10595 private bool HandleGroupNoticeRequest(IClientAPI sender, Packet Pack)
10596 {
10597 GroupNoticeRequestPacket groupNoticeRequest =
10598 (GroupNoticeRequestPacket)Pack;
10599
10600 #region Packet Session and User Check
10601 if (m_checkPackets)
10602 {
10603 if (groupNoticeRequest.AgentData.SessionID != SessionId ||
10604 groupNoticeRequest.AgentData.AgentID != AgentId)
10605 return true;
10606 }
10607 #endregion
10608
10609 if (m_GroupsModule != null)
10610 {
10611 m_GroupsModule.GroupNoticeRequest(this,
10612 groupNoticeRequest.Data.GroupNoticeID);
10613 }
10614 return true;
10615 }
10616 private bool HandleGroupRoleUpdate(IClientAPI sender, Packet Pack)
10617 {
10618 GroupRoleUpdatePacket groupRoleUpdate =
10619 (GroupRoleUpdatePacket)Pack;
10620
10621 #region Packet Session and User Check
10622 if (m_checkPackets)
10623 {
10624 if (groupRoleUpdate.AgentData.SessionID != SessionId ||
10625 groupRoleUpdate.AgentData.AgentID != AgentId)
10626 return true;
10627 }
10628 #endregion
10629
10630 if (m_GroupsModule != null)
10631 {
10632 foreach (GroupRoleUpdatePacket.RoleDataBlock d in
10633 groupRoleUpdate.RoleData)
10634 {
10635 m_GroupsModule.GroupRoleUpdate(this,
10636 groupRoleUpdate.AgentData.GroupID,
10637 d.RoleID,
10638 Utils.BytesToString(d.Name),
10639 Utils.BytesToString(d.Description),
10640 Utils.BytesToString(d.Title),
10641 d.Powers,
10642 d.UpdateType);
10643 }
10644 m_GroupsModule.NotifyChange(groupRoleUpdate.AgentData.GroupID);
10645 }
10646 return true;
10647 }
10648 private bool HandleGroupRoleChanges(IClientAPI sender, Packet Pack)
10649 {
10650 GroupRoleChangesPacket groupRoleChanges =
10651 (GroupRoleChangesPacket)Pack;
10652
10653 #region Packet Session and User Check
10654 if (m_checkPackets)
10655 {
10656 if (groupRoleChanges.AgentData.SessionID != SessionId ||
10657 groupRoleChanges.AgentData.AgentID != AgentId)
10658 return true;
10659 }
10660 #endregion
10661
10662 if (m_GroupsModule != null)
10663 {
10664 foreach (GroupRoleChangesPacket.RoleChangeBlock d in
10665 groupRoleChanges.RoleChange)
10666 {
10667 m_GroupsModule.GroupRoleChanges(this,
10668 groupRoleChanges.AgentData.GroupID,
10669 d.RoleID,
10670 d.MemberID,
10671 d.Change);
10672 }
10673 m_GroupsModule.NotifyChange(groupRoleChanges.AgentData.GroupID);
10674 }
10675 return true;
10676 }
10677 private bool HandleJoinGroupRequest(IClientAPI sender, Packet Pack)
10678 {
10679 JoinGroupRequestPacket joinGroupRequest =
10680 (JoinGroupRequestPacket)Pack;
10681
10682 #region Packet Session and User Check
10683 if (m_checkPackets)
10684 {
10685 if (joinGroupRequest.AgentData.SessionID != SessionId ||
10686 joinGroupRequest.AgentData.AgentID != AgentId)
10687 return true;
10688 }
10689 #endregion
10690
10691 if (m_GroupsModule != null)
10692 {
10693 m_GroupsModule.JoinGroupRequest(this,
10694 joinGroupRequest.GroupData.GroupID);
10695 }
10696 return true;
10697 }
10698 private bool HandleLeaveGroupRequest(IClientAPI sender, Packet Pack)
10699 {
10700 LeaveGroupRequestPacket leaveGroupRequest =
10701 (LeaveGroupRequestPacket)Pack;
10702
10703 #region Packet Session and User Check
10704 if (m_checkPackets)
10705 {
10706 if (leaveGroupRequest.AgentData.SessionID != SessionId ||
10707 leaveGroupRequest.AgentData.AgentID != AgentId)
10708 return true;
10709 }
10710 #endregion
10711
10712 if (m_GroupsModule != null)
10713 {
10714 m_GroupsModule.LeaveGroupRequest(this,
10715 leaveGroupRequest.GroupData.GroupID);
10716 }
10717 return true;
10718 }
10719 private bool HandleEjectGroupMemberRequest(IClientAPI sender, Packet Pack)
10720 {
10721 EjectGroupMemberRequestPacket ejectGroupMemberRequest =
10722 (EjectGroupMemberRequestPacket)Pack;
10723
10724 #region Packet Session and User Check
10725 if (m_checkPackets)
10726 {
10727 if (ejectGroupMemberRequest.AgentData.SessionID != SessionId ||
10728 ejectGroupMemberRequest.AgentData.AgentID != AgentId)
10729 return true;
10730 }
10731 #endregion
10732
10733 if (m_GroupsModule != null)
10734 {
10735 foreach (EjectGroupMemberRequestPacket.EjectDataBlock e
10736 in ejectGroupMemberRequest.EjectData)
10737 {
10738 m_GroupsModule.EjectGroupMemberRequest(this,
10739 ejectGroupMemberRequest.GroupData.GroupID,
10740 e.EjecteeID);
10741 }
10742 }
10743 return true;
10744 }
10745 private bool HandleInviteGroupRequest(IClientAPI sender, Packet Pack)
10746 {
10747 InviteGroupRequestPacket inviteGroupRequest =
10748 (InviteGroupRequestPacket)Pack;
10749
10750 #region Packet Session and User Check
10751 if (m_checkPackets)
10752 {
10753 if (inviteGroupRequest.AgentData.SessionID != SessionId ||
10754 inviteGroupRequest.AgentData.AgentID != AgentId)
10755 return true;
10756 }
10757 #endregion
10758
10759 if (m_GroupsModule != null)
10760 {
10761 foreach (InviteGroupRequestPacket.InviteDataBlock b in
10762 inviteGroupRequest.InviteData)
10763 {
10764 m_GroupsModule.InviteGroupRequest(this,
10765 inviteGroupRequest.GroupData.GroupID,
10766 b.InviteeID,
10767 b.RoleID);
10768 }
10769 }
10770 return true;
10771 }
10772
10773 #endregion Groups
10774
10775 private bool HandleStartLure(IClientAPI sender, Packet Pack)
10776 {
10777 StartLurePacket startLureRequest = (StartLurePacket)Pack;
10778
10779 #region Packet Session and User Check
10780 if (m_checkPackets)
10781 {
10782 if (startLureRequest.AgentData.SessionID != SessionId ||
10783 startLureRequest.AgentData.AgentID != AgentId)
10784 return true;
10785 }
10786 #endregion
10787
10788 StartLure handlerStartLure = OnStartLure;
10789 if (handlerStartLure != null)
10790 {
10791 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10792 {
10793 handlerStartLure(startLureRequest.Info.LureType,
10794 Utils.BytesToString(
10795 startLureRequest.Info.Message),
10796 startLureRequest.TargetData[i].TargetID,
10797 this);
10798 }
10799 }
10800 return true;
10801 }
10802 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
10803 {
10804 TeleportLureRequestPacket teleportLureRequest =
10805 (TeleportLureRequestPacket)Pack;
10806
10807 #region Packet Session and User Check
10808 if (m_checkPackets)
10809 {
10810 if (teleportLureRequest.Info.SessionID != SessionId ||
10811 teleportLureRequest.Info.AgentID != AgentId)
10812 return true;
10813 }
10814 #endregion
10815
10816 TeleportLureRequest handlerTeleportLureRequest = OnTeleportLureRequest;
10817 if (handlerTeleportLureRequest != null)
10818 handlerTeleportLureRequest(
10819 teleportLureRequest.Info.LureID,
10820 teleportLureRequest.Info.TeleportFlags,
10821 this);
10822 return true;
10823 }
10824 private bool HandleClassifiedInfoRequest(IClientAPI sender, Packet Pack)
10825 {
10826 ClassifiedInfoRequestPacket classifiedInfoRequest =
10827 (ClassifiedInfoRequestPacket)Pack;
10828
10829 #region Packet Session and User Check
10830 if (m_checkPackets)
10831 {
10832 if (classifiedInfoRequest.AgentData.SessionID != SessionId ||
10833 classifiedInfoRequest.AgentData.AgentID != AgentId)
10834 return true;
10835 }
10836 #endregion
10837
10838 ClassifiedInfoRequest handlerClassifiedInfoRequest = OnClassifiedInfoRequest;
10839 if (handlerClassifiedInfoRequest != null)
10840 handlerClassifiedInfoRequest(
10841 classifiedInfoRequest.Data.ClassifiedID,
10842 this);
10843 return true;
10844 }
10845 private bool HandleClassifiedInfoUpdate(IClientAPI sender, Packet Pack)
10846 {
10847 ClassifiedInfoUpdatePacket classifiedInfoUpdate =
10848 (ClassifiedInfoUpdatePacket)Pack;
10849
10850 #region Packet Session and User Check
10851 if (m_checkPackets)
10852 {
10853 if (classifiedInfoUpdate.AgentData.SessionID != SessionId ||
10854 classifiedInfoUpdate.AgentData.AgentID != AgentId)
10855 return true;
10856 }
10857 #endregion
10858
10859 ClassifiedInfoUpdate handlerClassifiedInfoUpdate = OnClassifiedInfoUpdate;
10860 if (handlerClassifiedInfoUpdate != null)
10861 handlerClassifiedInfoUpdate(
10862 classifiedInfoUpdate.Data.ClassifiedID,
10863 classifiedInfoUpdate.Data.Category,
10864 Utils.BytesToString(
10865 classifiedInfoUpdate.Data.Name),
10866 Utils.BytesToString(
10867 classifiedInfoUpdate.Data.Desc),
10868 classifiedInfoUpdate.Data.ParcelID,
10869 classifiedInfoUpdate.Data.ParentEstate,
10870 classifiedInfoUpdate.Data.SnapshotID,
10871 new Vector3(
10872 classifiedInfoUpdate.Data.PosGlobal),
10873 classifiedInfoUpdate.Data.ClassifiedFlags,
10874 classifiedInfoUpdate.Data.PriceForListing,
10875 this);
10876 return true;
10877 }
10878 private bool HandleClassifiedDelete(IClientAPI sender, Packet Pack)
10879 {
10880 ClassifiedDeletePacket classifiedDelete =
10881 (ClassifiedDeletePacket)Pack;
10882
10883 #region Packet Session and User Check
10884 if (m_checkPackets)
10885 {
10886 if (classifiedDelete.AgentData.SessionID != SessionId ||
10887 classifiedDelete.AgentData.AgentID != AgentId)
10888 return true;
10889 }
10890 #endregion
10891
10892 ClassifiedDelete handlerClassifiedDelete = OnClassifiedDelete;
10893 if (handlerClassifiedDelete != null)
10894 handlerClassifiedDelete(
10895 classifiedDelete.Data.ClassifiedID,
10896 this);
10897 return true;
10898 }
10899 private bool HandleClassifiedGodDelete(IClientAPI sender, Packet Pack)
10900 {
10901 ClassifiedGodDeletePacket classifiedGodDelete =
10902 (ClassifiedGodDeletePacket)Pack;
10903
10904 #region Packet Session and User Check
10905 if (m_checkPackets)
10906 {
10907 if (classifiedGodDelete.AgentData.SessionID != SessionId ||
10908 classifiedGodDelete.AgentData.AgentID != AgentId)
10909 return true;
10910 }
10911 #endregion
10912
10913 ClassifiedGodDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
10914 if (handlerClassifiedGodDelete != null)
10915 handlerClassifiedGodDelete(
10916 classifiedGodDelete.Data.ClassifiedID,
10917 classifiedGodDelete.Data.QueryID,
10918 this);
10919 return true;
10920 }
10921 private bool HandleEventGodDelete(IClientAPI sender, Packet Pack)
10922 {
10923 EventGodDeletePacket eventGodDelete =
10924 (EventGodDeletePacket)Pack;
10925
10926 #region Packet Session and User Check
10927 if (m_checkPackets)
10928 {
10929 if (eventGodDelete.AgentData.SessionID != SessionId ||
10930 eventGodDelete.AgentData.AgentID != AgentId)
10931 return true;
10932 }
10933 #endregion
10934
10935 EventGodDelete handlerEventGodDelete = OnEventGodDelete;
10936 if (handlerEventGodDelete != null)
10937 handlerEventGodDelete(
10938 eventGodDelete.EventData.EventID,
10939 eventGodDelete.QueryData.QueryID,
10940 Utils.BytesToString(
10941 eventGodDelete.QueryData.QueryText),
10942 eventGodDelete.QueryData.QueryFlags,
10943 eventGodDelete.QueryData.QueryStart,
10944 this);
10945 return true;
10946 }
10947 private bool HandleEventNotificationAddRequest(IClientAPI sender, Packet Pack)
10948 {
10949 EventNotificationAddRequestPacket eventNotificationAdd =
10950 (EventNotificationAddRequestPacket)Pack;
10951
10952 #region Packet Session and User Check
10953 if (m_checkPackets)
10954 {
10955 if (eventNotificationAdd.AgentData.SessionID != SessionId ||
10956 eventNotificationAdd.AgentData.AgentID != AgentId)
10957 return true;
10958 }
10959 #endregion
10960
10961 EventNotificationAddRequest handlerEventNotificationAddRequest = OnEventNotificationAddRequest;
10962 if (handlerEventNotificationAddRequest != null)
10963 handlerEventNotificationAddRequest(
10964 eventNotificationAdd.EventData.EventID, this);
10965 return true;
10966 }
10967 private bool HandleEventNotificationRemoveRequest(IClientAPI sender, Packet Pack)
10968 {
10969 EventNotificationRemoveRequestPacket eventNotificationRemove =
10970 (EventNotificationRemoveRequestPacket)Pack;
10971
10972 #region Packet Session and User Check
10973 if (m_checkPackets)
10974 {
10975 if (eventNotificationRemove.AgentData.SessionID != SessionId ||
10976 eventNotificationRemove.AgentData.AgentID != AgentId)
10977 return true;
10978 }
10979 #endregion
10980
10981 EventNotificationRemoveRequest handlerEventNotificationRemoveRequest = OnEventNotificationRemoveRequest;
10982 if (handlerEventNotificationRemoveRequest != null)
10983 handlerEventNotificationRemoveRequest(
10984 eventNotificationRemove.EventData.EventID, this);
10985 return true;
10986 }
10987 private bool HandleRetrieveInstantMessages(IClientAPI sender, Packet Pack)
10988 {
10989 RetrieveInstantMessagesPacket rimpInstantMessagePack = (RetrieveInstantMessagesPacket)Pack;
10990
10991 #region Packet Session and User Check
10992 if (m_checkPackets)
10993 {
10994 if (rimpInstantMessagePack.AgentData.SessionID != SessionId ||
10995 rimpInstantMessagePack.AgentData.AgentID != AgentId)
10996 return true;
10997 }
10998 #endregion
10999
11000 RetrieveInstantMessages handlerRetrieveInstantMessages = OnRetrieveInstantMessages;
11001 if (handlerRetrieveInstantMessages != null)
11002 handlerRetrieveInstantMessages(this);
11003 return true;
11004 }
11005 private bool HandlePickDelete(IClientAPI sender, Packet Pack)
11006 {
11007 PickDeletePacket pickDelete =
11008 (PickDeletePacket)Pack;
11009
11010 #region Packet Session and User Check
11011 if (m_checkPackets)
11012 {
11013 if (pickDelete.AgentData.SessionID != SessionId ||
11014 pickDelete.AgentData.AgentID != AgentId)
11015 return true;
11016 }
11017 #endregion
11018
11019 PickDelete handlerPickDelete = OnPickDelete;
11020 if (handlerPickDelete != null)
11021 handlerPickDelete(this, pickDelete.Data.PickID);
11022 return true;
11023 }
11024 private bool HandlePickGodDelete(IClientAPI sender, Packet Pack)
11025 {
11026 PickGodDeletePacket pickGodDelete =
11027 (PickGodDeletePacket)Pack;
11028
11029 #region Packet Session and User Check
11030 if (m_checkPackets)
11031 {
11032 if (pickGodDelete.AgentData.SessionID != SessionId ||
11033 pickGodDelete.AgentData.AgentID != AgentId)
11034 return true;
11035 }
11036 #endregion
11037
11038 PickGodDelete handlerPickGodDelete = OnPickGodDelete;
11039 if (handlerPickGodDelete != null)
11040 handlerPickGodDelete(this,
11041 pickGodDelete.AgentData.AgentID,
11042 pickGodDelete.Data.PickID,
11043 pickGodDelete.Data.QueryID);
11044 return true;
11045 }
11046 private bool HandlePickInfoUpdate(IClientAPI sender, Packet Pack)
11047 {
11048 PickInfoUpdatePacket pickInfoUpdate =
11049 (PickInfoUpdatePacket)Pack;
11050
11051 #region Packet Session and User Check
11052 if (m_checkPackets)
11053 {
11054 if (pickInfoUpdate.AgentData.SessionID != SessionId ||
11055 pickInfoUpdate.AgentData.AgentID != AgentId)
11056 return true;
11057 }
11058 #endregion
11059
11060 PickInfoUpdate handlerPickInfoUpdate = OnPickInfoUpdate;
11061 if (handlerPickInfoUpdate != null)
11062 handlerPickInfoUpdate(this,
11063 pickInfoUpdate.Data.PickID,
11064 pickInfoUpdate.Data.CreatorID,
11065 pickInfoUpdate.Data.TopPick,
11066 Utils.BytesToString(pickInfoUpdate.Data.Name),
11067 Utils.BytesToString(pickInfoUpdate.Data.Desc),
11068 pickInfoUpdate.Data.SnapshotID,
11069 pickInfoUpdate.Data.SortOrder,
11070 pickInfoUpdate.Data.Enabled);
11071 return true;
11072 }
11073 private bool HandleAvatarNotesUpdate(IClientAPI sender, Packet Pack)
11074 {
11075 AvatarNotesUpdatePacket avatarNotesUpdate =
11076 (AvatarNotesUpdatePacket)Pack;
11077
11078 #region Packet Session and User Check
11079 if (m_checkPackets)
11080 {
11081 if (avatarNotesUpdate.AgentData.SessionID != SessionId ||
11082 avatarNotesUpdate.AgentData.AgentID != AgentId)
11083 return true;
11084 }
11085 #endregion
11086
11087 AvatarNotesUpdate handlerAvatarNotesUpdate = OnAvatarNotesUpdate;
11088 if (handlerAvatarNotesUpdate != null)
11089 handlerAvatarNotesUpdate(this,
11090 avatarNotesUpdate.Data.TargetID,
11091 Utils.BytesToString(avatarNotesUpdate.Data.Notes));
11092 return true;
11093 }
11094 private bool HandleAvatarInterestsUpdate(IClientAPI sender, Packet Pack)
11095 {
11096 AvatarInterestsUpdatePacket avatarInterestUpdate =
11097 (AvatarInterestsUpdatePacket)Pack;
11098
11099 #region Packet Session and User Check
11100 if (m_checkPackets)
11101 {
11102 if (avatarInterestUpdate.AgentData.SessionID != SessionId ||
11103 avatarInterestUpdate.AgentData.AgentID != AgentId)
11104 return true;
11105 }
11106 #endregion
11107
11108 AvatarInterestUpdate handlerAvatarInterestUpdate = OnAvatarInterestUpdate;
11109 if (handlerAvatarInterestUpdate != null)
11110 handlerAvatarInterestUpdate(this,
11111 avatarInterestUpdate.PropertiesData.WantToMask,
11112 Utils.BytesToString(avatarInterestUpdate.PropertiesData.WantToText),
11113 avatarInterestUpdate.PropertiesData.SkillsMask,
11114 Utils.BytesToString(avatarInterestUpdate.PropertiesData.SkillsText),
11115 Utils.BytesToString(avatarInterestUpdate.PropertiesData.LanguagesText));
11116 return true;
11117 }
11118 private bool HandleGrantUserRights(IClientAPI sender, Packet Pack)
11119 {
11120 GrantUserRightsPacket GrantUserRights =
11121 (GrantUserRightsPacket)Pack;
11122 #region Packet Session and User Check
11123 if (m_checkPackets)
11124 {
11125 if (GrantUserRights.AgentData.SessionID != SessionId ||
11126 GrantUserRights.AgentData.AgentID != AgentId)
11127 return true;
11128 }
11129 #endregion
11130 GrantUserFriendRights GrantUserRightsHandler = OnGrantUserRights;
11131 if (GrantUserRightsHandler != null)
11132 GrantUserRightsHandler(this,
11133 GrantUserRights.AgentData.AgentID,
11134 GrantUserRights.Rights[0].AgentRelated,
11135 GrantUserRights.Rights[0].RelatedRights);
11136 return true;
11137 }
11138 private bool HandlePlacesQuery(IClientAPI sender, Packet Pack)
11139 {
11140 PlacesQueryPacket placesQueryPacket =
11141 (PlacesQueryPacket)Pack;
11142
11143 PlacesQuery handlerPlacesQuery = OnPlacesQuery;
11144
11145 if (handlerPlacesQuery != null)
11146 handlerPlacesQuery(placesQueryPacket.AgentData.QueryID,
11147 placesQueryPacket.TransactionData.TransactionID,
11148 Utils.BytesToString(
11149 placesQueryPacket.QueryData.QueryText),
11150 placesQueryPacket.QueryData.QueryFlags,
11151 (byte)placesQueryPacket.QueryData.Category,
11152 Utils.BytesToString(
11153 placesQueryPacket.QueryData.SimName),
11154 this);
11155 return true;
11156 }
11157
11158 #endregion Packet Handlers
11159
11160 public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question)
11161 {
11162 ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion);
11163 scriptQuestion.Data = new ScriptQuestionPacket.DataBlock();
11164 // TODO: don't create new blocks if recycling an old packet
11165 scriptQuestion.Data.TaskID = taskID;
11166 scriptQuestion.Data.ItemID = itemID;
11167 scriptQuestion.Data.Questions = question;
11168 scriptQuestion.Data.ObjectName = Util.StringToBytes256(taskName);
11169 scriptQuestion.Data.ObjectOwner = Util.StringToBytes256(ownerName);
11170
11171 OutPacket(scriptQuestion, ThrottleOutPacketType.Task);
11172 }
11173
11174 private void InitDefaultAnimations()
11175 {
11176 using (XmlTextReader reader = new XmlTextReader("data/avataranimations.xml"))
11177 {
11178 XmlDocument doc = new XmlDocument();
11179 doc.Load(reader);
11180 if (doc.DocumentElement != null)
11181 foreach (XmlNode nod in doc.DocumentElement.ChildNodes)
11182 {
11183 if (nod.Attributes["name"] != null)
11184 {
11185 string name = nod.Attributes["name"].Value.ToLower();
11186 string id = nod.InnerText;
11187 m_defaultAnimations.Add(name, (UUID)id);
11188 }
11189 }
11190 }
11191 }
11192
11193 public UUID GetDefaultAnimation(string name)
11194 {
11195 if (m_defaultAnimations.ContainsKey(name))
11196 return m_defaultAnimations[name];
11197 return UUID.Zero;
11198 }
11199
11200 /// <summary>
11201 /// Handler called when we receive a logout packet.
11202 /// </summary>
11203 /// <param name="client"></param>
11204 /// <param name="packet"></param>
11205 /// <returns></returns>
11206 protected virtual bool HandleLogout(IClientAPI client, Packet packet)
11207 {
11208 if (packet.Type == PacketType.LogoutRequest)
11209 {
11210 if (((LogoutRequestPacket)packet).AgentData.SessionID != SessionId) return false;
11211 }
11212
11213 return Logout(client);
11214 }
11215
11216 /// <summary>
11217 ///
11218 /// </summary>
11219 /// <param name="client"></param>
11220 /// <returns></returns>
11221 protected virtual bool Logout(IClientAPI client)
11222 {
11223 m_log.InfoFormat("[CLIENT]: Got a logout request for {0} in {1}", Name, Scene.RegionInfo.RegionName);
11224
11225 Action<IClientAPI> handlerLogout = OnLogout;
11226
11227 if (handlerLogout != null)
11228 {
11229 handlerLogout(client);
11230 }
11231
11232 return true;
11233 }
11234
11235 /// <summary>
11236 /// Send a response back to a client when it asks the asset server (via the region server) if it has
11237 /// its appearance texture cached.
11238 ///
11239 /// At the moment, we always reply that there is no cached texture.
11240 /// </summary>
11241 /// <param name="simclient"></param>
11242 /// <param name="packet"></param>
11243 /// <returns></returns>
11244 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11245 {
11246 //m_log.Debug("texture cached: " + packet.ToString());
11247 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
11248 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
11249
11250 if (cachedtex.AgentData.SessionID != SessionId) return false;
11251
11252 // TODO: don't create new blocks if recycling an old packet
11253 cachedresp.AgentData.AgentID = AgentId;
11254 cachedresp.AgentData.SessionID = m_sessionId;
11255 cachedresp.AgentData.SerialNum = m_cachedTextureSerial;
11256 m_cachedTextureSerial++;
11257 cachedresp.WearableData =
11258 new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length];
11259
11260 for (int i = 0; i < cachedtex.WearableData.Length; i++)
11261 {
11262 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11263 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11264 cachedresp.WearableData[i].TextureID = UUID.Zero;
11265 cachedresp.WearableData[i].HostName = new byte[0];
11266 }
11267
11268 cachedresp.Header.Zerocoded = true;
11269 OutPacket(cachedresp, ThrottleOutPacketType.Task);
11270
11271 return true;
11272 }
11273
11274 protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet)
11275 {
11276 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet;
11277 if (multipleupdate.AgentData.SessionID != SessionId) return false;
11278 // m_log.Debug("new multi update packet " + multipleupdate.ToString());
11279 Scene tScene = (Scene)m_scene;
11280
11281 for (int i = 0; i < multipleupdate.ObjectData.Length; i++)
11282 {
11283 MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i];
11284
11285 // Can't act on Null Data
11286 if (block.Data != null)
11287 {
11288 uint localId = block.ObjectLocalID;
11289 SceneObjectPart part = tScene.GetSceneObjectPart(localId);
11290
11291 if (part == null)
11292 {
11293 // It's a ghost! tell the client to delete it from view.
11294 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
11295 new List<uint>() { localId });
11296 }
11297 else
11298 {
11299 // UUID partId = part.UUID;
11300 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation;
11301
11302 switch (block.Type)
11303 {
11304 case 1:
11305 Vector3 pos1 = new Vector3(block.Data, 0);
11306
11307 UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
11308 if (handlerUpdatePrimSinglePosition != null)
11309 {
11310 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11311 handlerUpdatePrimSinglePosition(localId, pos1, this);
11312 }
11313 break;
11314 case 2:
11315 Quaternion rot1 = new Quaternion(block.Data, 0, true);
11316
11317 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation;
11318 if (handlerUpdatePrimSingleRotation != null)
11319 {
11320 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W);
11321 handlerUpdatePrimSingleRotation(localId, rot1, this);
11322 }
11323 break;
11324 case 3:
11325 Vector3 rotPos = new Vector3(block.Data, 0);
11326 Quaternion rot2 = new Quaternion(block.Data, 12, true);
11327
11328 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition;
11329 if (handlerUpdatePrimSingleRotationPosition != null)
11330 {
11331 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z);
11332 // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W);
11333 handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this);
11334 }
11335 break;
11336 case 4:
11337 case 20:
11338 Vector3 scale4 = new Vector3(block.Data, 0);
11339
11340 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale;
11341 if (handlerUpdatePrimScale != null)
11342 {
11343 // m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z);
11344 handlerUpdatePrimScale(localId, scale4, this);
11345 }
11346 break;
11347 case 5:
11348
11349 Vector3 scale1 = new Vector3(block.Data, 12);
11350 Vector3 pos11 = new Vector3(block.Data, 0);
11351
11352 handlerUpdatePrimScale = OnUpdatePrimScale;
11353 if (handlerUpdatePrimScale != null)
11354 {
11355 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11356 handlerUpdatePrimScale(localId, scale1, this);
11357
11358 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
11359 if (handlerUpdatePrimSinglePosition != null)
11360 {
11361 handlerUpdatePrimSinglePosition(localId, pos11, this);
11362 }
11363 }
11364 break;
11365 case 9:
11366 Vector3 pos2 = new Vector3(block.Data, 0);
11367
11368 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition;
11369
11370 if (handlerUpdateVector != null)
11371 {
11372
11373 handlerUpdateVector(localId, pos2, this);
11374 }
11375 break;
11376 case 10:
11377 Quaternion rot3 = new Quaternion(block.Data, 0, true);
11378
11379 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation;
11380 if (handlerUpdatePrimRotation != null)
11381 {
11382 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W);
11383 handlerUpdatePrimRotation(localId, rot3, this);
11384 }
11385 break;
11386 case 11:
11387 Vector3 pos3 = new Vector3(block.Data, 0);
11388 Quaternion rot4 = new Quaternion(block.Data, 12, true);
11389
11390 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation;
11391 if (handlerUpdatePrimGroupRotation != null)
11392 {
11393 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11394 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W);
11395 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this);
11396 }
11397 break;
11398 case 12:
11399 case 28:
11400 Vector3 scale7 = new Vector3(block.Data, 0);
11401
11402 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
11403 if (handlerUpdatePrimGroupScale != null)
11404 {
11405 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
11406 handlerUpdatePrimGroupScale(localId, scale7, this);
11407 }
11408 break;
11409 case 13:
11410 Vector3 scale2 = new Vector3(block.Data, 12);
11411 Vector3 pos4 = new Vector3(block.Data, 0);
11412
11413 handlerUpdatePrimScale = OnUpdatePrimScale;
11414 if (handlerUpdatePrimScale != null)
11415 {
11416 //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11417 handlerUpdatePrimScale(localId, scale2, this);
11418
11419 // Change the position based on scale (for bug number 246)
11420 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
11421 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11422 if (handlerUpdatePrimSinglePosition != null)
11423 {
11424 handlerUpdatePrimSinglePosition(localId, pos4, this);
11425 }
11426 }
11427 break;
11428 case 29:
11429 Vector3 scale5 = new Vector3(block.Data, 12);
11430 Vector3 pos5 = new Vector3(block.Data, 0);
11431
11432 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
11433 if (handlerUpdatePrimGroupScale != null)
11434 {
11435 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11436 handlerUpdatePrimGroupScale(localId, scale5, this);
11437 handlerUpdateVector = OnUpdatePrimGroupPosition;
11438
11439 if (handlerUpdateVector != null)
11440 {
11441 handlerUpdateVector(localId, pos5, this);
11442 }
11443 }
11444 break;
11445 case 21:
11446 Vector3 scale6 = new Vector3(block.Data, 12);
11447 Vector3 pos6 = new Vector3(block.Data, 0);
11448
11449 handlerUpdatePrimScale = OnUpdatePrimScale;
11450 if (handlerUpdatePrimScale != null)
11451 {
11452 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11453 handlerUpdatePrimScale(localId, scale6, this);
11454 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
11455 if (handlerUpdatePrimSinglePosition != null)
11456 {
11457 handlerUpdatePrimSinglePosition(localId, pos6, this);
11458 }
11459 }
11460 break;
11461 default:
11462 m_log.Debug("[CLIENT] MultipleObjUpdate recieved an unknown packet type: " + (block.Type));
11463 break;
11464 }
11465 }
11466 }
11467 }
11468 return true;
11469 }
11470
11471 public void RequestMapLayer()
11472 {
11473 //should be getting the map layer from the grid server
11474 //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area)
11475 MapLayerReplyPacket mapReply = (MapLayerReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapLayerReply);
11476 // TODO: don't create new blocks if recycling an old packet
11477 mapReply.AgentData.AgentID = AgentId;
11478 mapReply.AgentData.Flags = 0;
11479 mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1];
11480 mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock();
11481 mapReply.LayerData[0].Bottom = 0;
11482 mapReply.LayerData[0].Left = 0;
11483 mapReply.LayerData[0].Top = 30000;
11484 mapReply.LayerData[0].Right = 30000;
11485 mapReply.LayerData[0].ImageID = new UUID("00000000-0000-1111-9999-000000000006");
11486 mapReply.Header.Zerocoded = true;
11487 OutPacket(mapReply, ThrottleOutPacketType.Land);
11488 }
11489
11490 public void RequestMapBlocksX(int minX, int minY, int maxX, int maxY)
11491 {
11492 /*
11493 IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY);
11494 MapBlockReplyPacket mbReply = new MapBlockReplyPacket();
11495 mbReply.AgentData.AgentId = AgentId;
11496 int len;
11497 if (simMapProfiles == null)
11498 len = 0;
11499 else
11500 len = simMapProfiles.Count;
11501
11502 mbReply.Data = new MapBlockReplyPacket.DataBlock[len];
11503 int iii;
11504 for (iii = 0; iii < len; iii++)
11505 {
11506 Hashtable mp = (Hashtable)simMapProfiles[iii];
11507 mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock();
11508 mbReply.Data[iii].Name = Util.UTF8.GetBytes((string)mp["name"]);
11509 mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]);
11510 mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]);
11511 mbReply.Data[iii].MapImageID = new UUID((string)mp["map-image-id"]);
11512 mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]);
11513 mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]);
11514 mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]);
11515 mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]);
11516 }
11517 this.OutPacket(mbReply, ThrottleOutPacketType.Land);
11518 */
11519 }
11520
11521 /// <summary>
11522 /// Sets the throttles from values supplied by the client
11523 /// </summary>
11524 /// <param name="throttles"></param>
11525 public void SetChildAgentThrottle(byte[] throttles)
11526 {
11527 m_udpClient.SetThrottles(throttles);
11528 }
11529
11530 /// <summary>
11531 /// Get the current throttles for this client as a packed byte array
11532 /// </summary>
11533 /// <param name="multiplier">Unused</param>
11534 /// <returns></returns>
11535 public byte[] GetThrottlesPacked(float multiplier)
11536 {
11537 return m_udpClient.GetThrottlesPacked(multiplier);
11538 }
11539
11540 /// <summary>
11541 /// Cruft?
11542 /// </summary>
11543 public virtual void InPacket(object NewPack)
11544 {
11545 throw new NotImplementedException();
11546 }
11547
11548 /// <summary>
11549 /// This is the starting point for sending a simulator packet out to the client
11550 /// </summary>
11551 /// <param name="packet">Packet to send</param>
11552 /// <param name="throttlePacketType">Throttling category for the packet</param>
11553 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType)
11554 {
11555 #region BinaryStats
11556 LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length);
11557 #endregion BinaryStats
11558
11559 OutPacket(packet, throttlePacketType, true);
11560 }
11561
11562 /// <summary>
11563 /// This is the starting point for sending a simulator packet out to the client
11564 /// </summary>
11565 /// <param name="packet">Packet to send</param>
11566 /// <param name="throttlePacketType">Throttling category for the packet</param>
11567 /// <param name="doAutomaticSplitting">True to automatically split oversized
11568 /// packets (the default), or false to disable splitting if the calling code
11569 /// handles splitting manually</param>
11570 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting)
11571 {
11572 OutPacket(packet, throttlePacketType, doAutomaticSplitting, null);
11573 }
11574
11575 /// <summary>
11576 /// This is the starting point for sending a simulator packet out to the client
11577 /// </summary>
11578 /// <param name="packet">Packet to send</param>
11579 /// <param name="throttlePacketType">Throttling category for the packet</param>
11580 /// <param name="doAutomaticSplitting">True to automatically split oversized
11581 /// packets (the default), or false to disable splitting if the calling code
11582 /// handles splitting manually</param>
11583 /// <param name="method">The method to be called in the event this packet is reliable
11584 /// and unacknowledged. The server will provide normal resend capability if you do not
11585 /// provide your own method.</param>
11586 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
11587 {
11588 if (m_debugPacketLevel > 0)
11589 {
11590 bool logPacket = true;
11591
11592 if (m_debugPacketLevel <= 255
11593 && (packet.Type == PacketType.SimStats || packet.Type == PacketType.SimulatorViewerTimeMessage))
11594 logPacket = false;
11595
11596 if (m_debugPacketLevel <= 200
11597 && (packet.Type == PacketType.ImagePacket
11598 || packet.Type == PacketType.ImageData
11599 || packet.Type == PacketType.LayerData
11600 || packet.Type == PacketType.CoarseLocationUpdate))
11601 logPacket = false;
11602
11603 if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect))
11604 logPacket = false;
11605
11606 if (m_debugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate)
11607 logPacket = false;
11608
11609 if (logPacket)
11610 m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type);
11611 }
11612
11613 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method);
11614 }
11615
11616 public bool AddMoney(int debit)
11617 {
11618 if (m_moneyBalance + debit >= 0)
11619 {
11620 m_moneyBalance += debit;
11621 SendMoneyBalance(UUID.Zero, true, Util.StringToBytes256("Poof Poof!"), m_moneyBalance);
11622 return true;
11623 }
11624 return false;
11625 }
11626
11627 /// <summary>
11628 /// Breaks down the genericMessagePacket into specific events
11629 /// </summary>
11630 /// <param name="gmMethod"></param>
11631 /// <param name="gmInvoice"></param>
11632 /// <param name="gmParams"></param>
11633 public void DecipherGenericMessage(string gmMethod, UUID gmInvoice, GenericMessagePacket.ParamListBlock[] gmParams)
11634 {
11635 switch (gmMethod)
11636 {
11637 case "autopilot":
11638 float locx;
11639 float locy;
11640 float locz;
11641
11642 try
11643 {
11644 uint regionX;
11645 uint regionY;
11646 Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY);
11647 locx = Convert.ToSingle(Utils.BytesToString(gmParams[0].Parameter)) - regionX;
11648 locy = Convert.ToSingle(Utils.BytesToString(gmParams[1].Parameter)) - regionY;
11649 locz = Convert.ToSingle(Utils.BytesToString(gmParams[2].Parameter));
11650 }
11651 catch (InvalidCastException)
11652 {
11653 m_log.Error("[CLIENT]: Invalid autopilot request");
11654 return;
11655 }
11656
11657 UpdateVector handlerAutoPilotGo = OnAutoPilotGo;
11658 if (handlerAutoPilotGo != null)
11659 {
11660 handlerAutoPilotGo(0, new Vector3(locx, locy, locz), this);
11661 }
11662 m_log.InfoFormat("[CLIENT]: Client Requests autopilot to position <{0},{1},{2}>", locx, locy, locz);
11663
11664
11665 break;
11666 default:
11667 m_log.Debug("[CLIENT]: Unknown Generic Message, Method: " + gmMethod + ". Invoice: " + gmInvoice + ". Dumping Params:");
11668 for (int hi = 0; hi < gmParams.Length; hi++)
11669 {
11670 Console.WriteLine(gmParams[hi].ToString());
11671 }
11672 //gmpack.MethodData.
11673 break;
11674
11675 }
11676 }
11677
11678 /// <summary>
11679 /// Entryway from the client to the simulator. All UDP packets from the client will end up here
11680 /// </summary>
11681 /// <param name="Pack">OpenMetaverse.packet</param>
11682 public void ProcessInPacket(Packet packet)
11683 {
11684 if (m_debugPacketLevel >= 255)
11685 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11686
11687 if (!ProcessPacketMethod(packet))
11688 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
11689
11690 PacketPool.Instance.ReturnPacket(packet);
11691 }
11692
11693 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
11694 {
11695 PrimitiveBaseShape shape = new PrimitiveBaseShape();
11696
11697 shape.PCode = addPacket.ObjectData.PCode;
11698 shape.State = addPacket.ObjectData.State;
11699 shape.PathBegin = addPacket.ObjectData.PathBegin;
11700 shape.PathEnd = addPacket.ObjectData.PathEnd;
11701 shape.PathScaleX = addPacket.ObjectData.PathScaleX;
11702 shape.PathScaleY = addPacket.ObjectData.PathScaleY;
11703 shape.PathShearX = addPacket.ObjectData.PathShearX;
11704 shape.PathShearY = addPacket.ObjectData.PathShearY;
11705 shape.PathSkew = addPacket.ObjectData.PathSkew;
11706 shape.ProfileBegin = addPacket.ObjectData.ProfileBegin;
11707 shape.ProfileEnd = addPacket.ObjectData.ProfileEnd;
11708 shape.Scale = addPacket.ObjectData.Scale;
11709 shape.PathCurve = addPacket.ObjectData.PathCurve;
11710 shape.ProfileCurve = addPacket.ObjectData.ProfileCurve;
11711 shape.ProfileHollow = addPacket.ObjectData.ProfileHollow;
11712 shape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset;
11713 shape.PathRevolutions = addPacket.ObjectData.PathRevolutions;
11714 shape.PathTaperX = addPacket.ObjectData.PathTaperX;
11715 shape.PathTaperY = addPacket.ObjectData.PathTaperY;
11716 shape.PathTwist = addPacket.ObjectData.PathTwist;
11717 shape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin;
11718 Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("89556747-24cb-43ed-920b-47caed15465f"));
11719 shape.TextureEntry = ntex.GetBytes();
11720 //shape.Textures = ntex;
11721 return shape;
11722 }
11723
11724 public ClientInfo GetClientInfo()
11725 {
11726 ClientInfo info = m_udpClient.GetClientInfo();
11727
11728 info.userEP = m_userEndPoint;
11729 info.proxyEP = null;
11730 info.agentcircuit = RequestClientInfo();
11731
11732 return info;
11733 }
11734
11735 public void SetClientInfo(ClientInfo info)
11736 {
11737 m_udpClient.SetClientInfo(info);
11738 }
11739
11740 public EndPoint GetClientEP()
11741 {
11742 return m_userEndPoint;
11743 }
11744
11745 #region Media Parcel Members
11746
11747 public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time)
11748 {
11749 ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket();
11750 commandMessagePacket.CommandBlock.Flags = flags;
11751 commandMessagePacket.CommandBlock.Command = (uint)command;
11752 commandMessagePacket.CommandBlock.Time = time;
11753
11754 OutPacket(commandMessagePacket, ThrottleOutPacketType.Task);
11755 }
11756
11757 public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID,
11758 byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight,
11759 byte mediaLoop)
11760 {
11761 ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket();
11762 updatePacket.DataBlock.MediaURL = Util.StringToBytes256(mediaUrl);
11763 updatePacket.DataBlock.MediaID = mediaTextureID;
11764 updatePacket.DataBlock.MediaAutoScale = autoScale;
11765
11766 updatePacket.DataBlockExtended.MediaType = Util.StringToBytes256(mediaType);
11767 updatePacket.DataBlockExtended.MediaDesc = Util.StringToBytes256(mediaDesc);
11768 updatePacket.DataBlockExtended.MediaWidth = mediaWidth;
11769 updatePacket.DataBlockExtended.MediaHeight = mediaHeight;
11770 updatePacket.DataBlockExtended.MediaLoop = mediaLoop;
11771
11772 OutPacket(updatePacket, ThrottleOutPacketType.Task);
11773 }
11774
11775 #endregion
11776
11777 #region Camera
11778
11779 public void SendSetFollowCamProperties(UUID objectID, SortedDictionary<int, float> parameters)
11780 {
11781 SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties);
11782 packet.ObjectData.ObjectID = objectID;
11783 SetFollowCamPropertiesPacket.CameraPropertyBlock[] camPropBlock = new SetFollowCamPropertiesPacket.CameraPropertyBlock[parameters.Count];
11784 uint idx = 0;
11785 foreach (KeyValuePair<int, float> pair in parameters)
11786 {
11787 SetFollowCamPropertiesPacket.CameraPropertyBlock block = new SetFollowCamPropertiesPacket.CameraPropertyBlock();
11788 block.Type = pair.Key;
11789 block.Value = pair.Value;
11790
11791 camPropBlock[idx++] = block;
11792 }
11793 packet.CameraProperty = camPropBlock;
11794 OutPacket(packet, ThrottleOutPacketType.Task);
11795 }
11796
11797 public void SendClearFollowCamProperties(UUID objectID)
11798 {
11799 ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties);
11800 packet.ObjectData.ObjectID = objectID;
11801 OutPacket(packet, ThrottleOutPacketType.Task);
11802 }
11803
11804 #endregion
11805
11806 public void SetClientOption(string option, string value)
11807 {
11808 switch (option)
11809 {
11810 default:
11811 break;
11812 }
11813 }
11814
11815 public string GetClientOption(string option)
11816 {
11817 switch (option)
11818 {
11819 default:
11820 break;
11821 }
11822 return string.Empty;
11823 }
11824
11825 public void KillEndDone()
11826 {
11827 }
11828
11829 #region IClientCore
11830
11831 private readonly Dictionary<Type, object> m_clientInterfaces = new Dictionary<Type, object>();
11832
11833 /// <summary>
11834 /// Register an interface on this client, should only be called in the constructor.
11835 /// </summary>
11836 /// <typeparam name="T"></typeparam>
11837 /// <param name="iface"></param>
11838 protected void RegisterInterface<T>(T iface)
11839 {
11840 lock (m_clientInterfaces)
11841 {
11842 if (!m_clientInterfaces.ContainsKey(typeof(T)))
11843 {
11844 m_clientInterfaces.Add(typeof(T), iface);
11845 }
11846 }
11847 }
11848
11849 public bool TryGet<T>(out T iface)
11850 {
11851 if (m_clientInterfaces.ContainsKey(typeof(T)))
11852 {
11853 iface = (T)m_clientInterfaces[typeof(T)];
11854 return true;
11855 }
11856 iface = default(T);
11857 return false;
11858 }
11859
11860 public T Get<T>()
11861 {
11862 return (T)m_clientInterfaces[typeof(T)];
11863 }
11864
11865 public void Disconnect(string reason)
11866 {
11867 Kick(reason);
11868 Thread.Sleep(1000);
11869 Close();
11870 }
11871
11872 public void Disconnect()
11873 {
11874 Close();
11875 }
11876
11877 #endregion
11878
11879 public void RefreshGroupMembership()
11880 {
11881 if (m_GroupsModule != null)
11882 {
11883 GroupMembershipData[] GroupMembership =
11884 m_GroupsModule.GetMembershipData(AgentId);
11885
11886 m_groupPowers.Clear();
11887
11888 if (GroupMembership != null)
11889 {
11890 for (int i = 0; i < GroupMembership.Length; i++)
11891 {
11892 m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers;
11893 }
11894 }
11895 }
11896 }
11897
11898 public string Report()
11899 {
11900 return m_udpClient.GetStats();
11901 }
11902
11903 public string XReport(string uptime, string version)
11904 {
11905 return String.Empty;
11906 }
11907
11908 /// <summary>
11909 /// Make an asset request to the asset service in response to a client request.
11910 /// </summary>
11911 /// <param name="transferRequest"></param>
11912 /// <param name="taskID"></param>
11913 protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID)
11914 {
11915 UUID requestID = UUID.Zero;
11916 if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
11917 {
11918 requestID = new UUID(transferRequest.TransferInfo.Params, 0);
11919 }
11920 else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
11921 {
11922 requestID = new UUID(transferRequest.TransferInfo.Params, 80);
11923 }
11924
11925// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11926
11927
11928 //Note, the bool returned from the below function is useless since it is always false.
11929 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
11930
11931 }
11932
11933 /// <summary>
11934 /// When we get a reply back from the asset service in response to a client request, send back the data.
11935 /// </summary>
11936 /// <param name="id"></param>
11937 /// <param name="sender"></param>
11938 /// <param name="asset"></param>
11939 protected void AssetReceived(string id, Object sender, AssetBase asset)
11940 {
11941 if (asset == null)
11942 return;
11943
11944 TransferRequestPacket transferRequest = (TransferRequestPacket)sender;
11945
11946 UUID requestID = UUID.Zero;
11947 byte source = (byte)SourceType.Asset;
11948
11949 if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
11950 {
11951 requestID = new UUID(transferRequest.TransferInfo.Params, 0);
11952 }
11953 else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
11954 {
11955 requestID = new UUID(transferRequest.TransferInfo.Params, 80);
11956 source = (byte)SourceType.SimInventoryItem;
11957 //m_log.Debug("asset request " + requestID);
11958 }
11959
11960 // Scripts cannot be retrieved by direct request
11961 if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset && asset.Type == 10)
11962 return;
11963
11964 // The asset is known to exist and is in our cache, so add it to the AssetRequests list
11965 AssetRequestToClient req = new AssetRequestToClient();
11966 req.AssetInf = asset;
11967 req.AssetRequestSource = source;
11968 req.IsTextureRequest = false;
11969 req.NumPackets = CalculateNumPackets(asset.Data);
11970 req.Params = transferRequest.TransferInfo.Params;
11971 req.RequestAssetID = requestID;
11972 req.TransferRequestID = transferRequest.TransferInfo.TransferID;
11973
11974 SendAsset(req);
11975 }
11976
11977 /// <summary>
11978 /// Calculate the number of packets required to send the asset to the client.
11979 /// </summary>
11980 /// <param name="data"></param>
11981 /// <returns></returns>
11982 private static int CalculateNumPackets(byte[] data)
11983 {
11984 const uint m_maxPacketSize = 600;
11985 int numPackets = 1;
11986
11987 if (data == null)
11988 return 0;
11989
11990 if (data.LongLength > m_maxPacketSize)
11991 {
11992 // over max number of bytes so split up file
11993 long restData = data.LongLength - m_maxPacketSize;
11994 int restPackets = (int)((restData + m_maxPacketSize - 1) / m_maxPacketSize);
11995 numPackets += restPackets;
11996 }
11997
11998 return numPackets;
11999 }
12000
12001 #region IClientIPEndpoint Members
12002
12003 public IPAddress EndPoint
12004 {
12005 get
12006 {
12007 if (m_userEndPoint is IPEndPoint)
12008 {
12009 IPEndPoint ep = (IPEndPoint)m_userEndPoint;
12010
12011 return ep.Address;
12012 }
12013 return null;
12014 }
12015 }
12016
12017 #endregion
12018
12019 public void SendRebakeAvatarTextures(UUID textureID)
12020 {
12021 RebakeAvatarTexturesPacket pack =
12022 (RebakeAvatarTexturesPacket)PacketPool.Instance.GetPacket(PacketType.RebakeAvatarTextures);
12023
12024 pack.TextureData = new RebakeAvatarTexturesPacket.TextureDataBlock();
12025 pack.TextureData.TextureID = textureID;
12026 OutPacket(pack, ThrottleOutPacketType.Task);
12027 }
12028
12029 public struct PacketProcessor
12030 {
12031 public PacketMethod method;
12032 public bool Async;
12033 }
12034
12035 public class AsyncPacketProcess
12036 {
12037 public bool result = false;
12038 public readonly LLClientView ClientView = null;
12039 public readonly Packet Pack = null;
12040 public readonly PacketMethod Method = null;
12041 public AsyncPacketProcess(LLClientView pClientview, PacketMethod pMethod, Packet pPack)
12042 {
12043 ClientView = pClientview;
12044 Method = pMethod;
12045 Pack = pPack;
12046 }
12047 }
12048
12049 public static OSD BuildEvent(string eventName, OSD eventBody)
12050 {
12051 OSDMap osdEvent = new OSDMap(2);
12052 osdEvent.Add("message", new OSDString(eventName));
12053 osdEvent.Add("body", eventBody);
12054
12055 return osdEvent;
12056 }
12057
12058 public void SendAvatarInterestsReply(UUID avatarID, uint wantMask, string wantText, uint skillsMask, string skillsText, string languages)
12059 {
12060 AvatarInterestsReplyPacket packet = (AvatarInterestsReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarInterestsReply);
12061
12062 packet.AgentData = new AvatarInterestsReplyPacket.AgentDataBlock();
12063 packet.AgentData.AgentID = AgentId;
12064 packet.AgentData.AvatarID = avatarID;
12065
12066 packet.PropertiesData = new AvatarInterestsReplyPacket.PropertiesDataBlock();
12067 packet.PropertiesData.WantToMask = wantMask;
12068 packet.PropertiesData.WantToText = Utils.StringToBytes(wantText);
12069 packet.PropertiesData.SkillsMask = skillsMask;
12070 packet.PropertiesData.SkillsText = Utils.StringToBytes(skillsText);
12071 packet.PropertiesData.LanguagesText = Utils.StringToBytes(languages);
12072 OutPacket(packet, ThrottleOutPacketType.Task);
12073 }
12074
12075 public void SendChangeUserRights(UUID agentID, UUID friendID, int rights)
12076 {
12077 ChangeUserRightsPacket packet = (ChangeUserRightsPacket)PacketPool.Instance.GetPacket(PacketType.ChangeUserRights);
12078
12079 packet.AgentData = new ChangeUserRightsPacket.AgentDataBlock();
12080 packet.AgentData.AgentID = agentID;
12081
12082 packet.Rights = new ChangeUserRightsPacket.RightsBlock[1];
12083 packet.Rights[0] = new ChangeUserRightsPacket.RightsBlock();
12084 packet.Rights[0].AgentRelated = friendID;
12085 packet.Rights[0].RelatedRights = rights;
12086
12087 OutPacket(packet, ThrottleOutPacketType.Task);
12088 }
12089
12090 public void SendTextBoxRequest(string message, int chatChannel, string objectname, string ownerFirstName, string ownerLastName, UUID objectId)
12091 {
12092 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog);
12093 dialog.Data.ObjectID = objectId;
12094 dialog.Data.ChatChannel = chatChannel;
12095 dialog.Data.ImageID = UUID.Zero;
12096 dialog.Data.ObjectName = Util.StringToBytes256(objectname);
12097 // this is the username of the *owner*
12098 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
12099 dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
12100 dialog.Data.Message = Util.StringToBytes256(message);
12101
12102 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[1];
12103 buttons[0] = new ScriptDialogPacket.ButtonsBlock();
12104 buttons[0].ButtonLabel = Util.StringToBytes256("!!llTextBox!!");
12105 dialog.Buttons = buttons;
12106 OutPacket(dialog, ThrottleOutPacketType.Task);
12107 }
12108
12109 public void StopFlying(ISceneEntity p)
12110 {
12111 if (p is ScenePresence)
12112 {
12113 ScenePresence presence = p as ScenePresence;
12114 // It turns out to get the agent to stop flying, you have to feed it stop flying velocities
12115 // There's no explicit message to send the client to tell it to stop flying.. it relies on the
12116 // velocity, collision plane and avatar height
12117
12118 // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air
12119 // when the avatar stands up
12120
12121 Vector3 pos = presence.AbsolutePosition;
12122
12123 if (presence.Appearance.AvatarHeight != 127.0f)
12124 pos += new Vector3(0f, 0f, (presence.Appearance.AvatarHeight/6f));
12125 else
12126 pos += new Vector3(0f, 0f, (1.56f/6f));
12127
12128 presence.AbsolutePosition = pos;
12129
12130 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
12131 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
12132 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
12133 // certain amount.. because the LLClient wouldn't land in that situation anyway.
12134
12135 // why are we still testing for this really old height value default???
12136 if (presence.Appearance.AvatarHeight != 127.0f)
12137 presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - presence.Appearance.AvatarHeight/6f);
12138 else
12139 presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f/6f));
12140
12141
12142 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block =
12143 CreateImprovedTerseBlock(p, false);
12144
12145 const float TIME_DILATION = 1.0f;
12146 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
12147
12148
12149 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
12150 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
12151 packet.RegionData.TimeDilation = timeDilation;
12152 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
12153
12154 packet.ObjectData[0] = block;
12155
12156 OutPacket(packet, ThrottleOutPacketType.Task, true);
12157 }
12158
12159 //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
12160 // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
12161 }
12162
12163 public void SendPlacesReply(UUID queryID, UUID transactionID,
12164 PlacesReplyData[] data)
12165 {
12166 PlacesReplyPacket reply = null;
12167 PlacesReplyPacket.QueryDataBlock[] dataBlocks =
12168 new PlacesReplyPacket.QueryDataBlock[0];
12169
12170 for (int i = 0 ; i < data.Length ; i++)
12171 {
12172 PlacesReplyPacket.QueryDataBlock block =
12173 new PlacesReplyPacket.QueryDataBlock();
12174
12175 block.OwnerID = data[i].OwnerID;
12176 block.Name = Util.StringToBytes256(data[i].Name);
12177 block.Desc = Util.StringToBytes1024(data[i].Desc);
12178 block.ActualArea = data[i].ActualArea;
12179 block.BillableArea = data[i].BillableArea;
12180 block.Flags = data[i].Flags;
12181 block.GlobalX = data[i].GlobalX;
12182 block.GlobalY = data[i].GlobalY;
12183 block.GlobalZ = data[i].GlobalZ;
12184 block.SimName = Util.StringToBytes256(data[i].SimName);
12185 block.SnapshotID = data[i].SnapshotID;
12186 block.Dwell = data[i].Dwell;
12187 block.Price = data[i].Price;
12188
12189 if (reply != null && reply.Length + block.Length > 1400)
12190 {
12191 OutPacket(reply, ThrottleOutPacketType.Task);
12192
12193 reply = null;
12194 dataBlocks = new PlacesReplyPacket.QueryDataBlock[0];
12195 }
12196
12197 if (reply == null)
12198 {
12199 reply = (PlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.PlacesReply);
12200 reply.AgentData = new PlacesReplyPacket.AgentDataBlock();
12201 reply.AgentData.AgentID = AgentId;
12202 reply.AgentData.QueryID = queryID;
12203
12204 reply.TransactionData = new PlacesReplyPacket.TransactionDataBlock();
12205 reply.TransactionData.TransactionID = transactionID;
12206
12207 reply.QueryData = dataBlocks;
12208 }
12209
12210 Array.Resize(ref dataBlocks, dataBlocks.Length + 1);
12211 dataBlocks[dataBlocks.Length - 1] = block;
12212 reply.QueryData = dataBlocks;
12213 }
12214 if (reply != null)
12215 OutPacket(reply, ThrottleOutPacketType.Task);
12216 }
12217 }
12218}
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..95a8e23
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -0,0 +1,707 @@
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 public bool m_deliverPackets = true;
162
163 /// <summary>
164 /// Default constructor
165 /// </summary>
166 /// <param name="server">Reference to the UDP server this client is connected to</param>
167 /// <param name="rates">Default throttling rates and maximum throttle limits</param>
168 /// <param name="parentThrottle">Parent HTB (hierarchical token bucket)
169 /// that the child throttles will be governed by</param>
170 /// <param name="circuitCode">Circuit code for this connection</param>
171 /// <param name="agentID">AgentID for the connected agent</param>
172 /// <param name="remoteEndPoint">Remote endpoint for this connection</param>
173 public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO)
174 {
175 AgentID = agentID;
176 RemoteEndPoint = remoteEndPoint;
177 CircuitCode = circuitCode;
178 m_udpServer = server;
179 if (defaultRTO != 0)
180 m_defaultRTO = defaultRTO;
181 if (maxRTO != 0)
182 m_maxRTO = maxRTO;
183
184 // Create a token bucket throttle for this client that has the scene token bucket as a parent
185 m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled);
186 // Create a token bucket throttle for the total categary with the client bucket as a throttle
187 m_throttleCategory = new TokenBucket(m_throttleClient, 0);
188 // Create an array of token buckets for this clients different throttle categories
189 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
190
191 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
192 {
193 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
194
195 // Initialize the packet outboxes, where packets sit while they are waiting for tokens
196 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
197 // Initialize the token buckets that control the throttling for each category
198 m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type));
199 }
200
201 // Default the retransmission timeout to three seconds
202 RTO = m_defaultRTO;
203
204 // Initialize this to a sane value to prevent early disconnects
205 TickLastPacketReceived = Environment.TickCount & Int32.MaxValue;
206 }
207
208 /// <summary>
209 /// Shuts down this client connection
210 /// </summary>
211 public void Shutdown()
212 {
213 IsConnected = false;
214 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
215 {
216 m_packetOutboxes[i].Clear();
217 m_nextPackets[i] = null;
218 }
219
220 // pull the throttle out of the scene throttle
221 m_throttleClient.Parent.UnregisterRequest(m_throttleClient);
222 OnPacketStats = null;
223 OnQueueEmpty = null;
224 }
225
226 /// <summary>
227 /// Gets information about this client connection
228 /// </summary>
229 /// <returns>Information about the client connection</returns>
230 public ClientInfo GetClientInfo()
231 {
232 // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
233 // of pending and needed ACKs for every client every time some method wants information about
234 // this connection is a recipe for poor performance
235 ClientInfo info = new ClientInfo();
236 info.pendingAcks = new Dictionary<uint, uint>();
237 info.needAck = new Dictionary<uint, byte[]>();
238
239 info.resendThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate;
240 info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
241 info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
242 info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
243 info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
244 info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
245 info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
246 info.totalThrottle = (int)m_throttleCategory.DripRate;
247
248 return info;
249 }
250
251 /// <summary>
252 /// Modifies the UDP throttles
253 /// </summary>
254 /// <param name="info">New throttling values</param>
255 public void SetClientInfo(ClientInfo info)
256 {
257 // TODO: Allowing throttles to be manually set from this function seems like a reasonable
258 // idea. On the other hand, letting external code manipulate our ACK accounting is not
259 // going to happen
260 throw new NotImplementedException();
261 }
262
263 /// <summary>
264 /// Return statistics information about client packet queues.
265 /// </summary>
266 ///
267 /// FIXME: This should really be done in a more sensible manner rather than sending back a formatted string.
268 ///
269 /// <returns></returns>
270 public string GetStats()
271 {
272 return string.Format(
273 "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}",
274 PacketsReceived,
275 PacketsSent,
276 PacketsResent,
277 UnackedBytes,
278 m_packetOutboxes[(int)ThrottleOutPacketType.Resend].Count,
279 m_packetOutboxes[(int)ThrottleOutPacketType.Land].Count,
280 m_packetOutboxes[(int)ThrottleOutPacketType.Wind].Count,
281 m_packetOutboxes[(int)ThrottleOutPacketType.Cloud].Count,
282 m_packetOutboxes[(int)ThrottleOutPacketType.Task].Count,
283 m_packetOutboxes[(int)ThrottleOutPacketType.Texture].Count,
284 m_packetOutboxes[(int)ThrottleOutPacketType.Asset].Count,
285 m_packetOutboxes[(int)ThrottleOutPacketType.State].Count);
286 }
287
288 public void SendPacketStats()
289 {
290 PacketStats callback = OnPacketStats;
291 if (callback != null)
292 {
293 int newPacketsReceived = PacketsReceived - m_packetsReceivedReported;
294 int newPacketsSent = PacketsSent - m_packetsSentReported;
295
296 callback(newPacketsReceived, newPacketsSent, UnackedBytes);
297
298 m_packetsReceivedReported += newPacketsReceived;
299 m_packetsSentReported += newPacketsSent;
300 }
301 }
302
303 public void SetThrottles(byte[] throttleData)
304 {
305 byte[] adjData;
306 int pos = 0;
307
308 if (!BitConverter.IsLittleEndian)
309 {
310 byte[] newData = new byte[7 * 4];
311 Buffer.BlockCopy(throttleData, 0, newData, 0, 7 * 4);
312
313 for (int i = 0; i < 7; i++)
314 Array.Reverse(newData, i * 4, 4);
315
316 adjData = newData;
317 }
318 else
319 {
320 adjData = throttleData;
321 }
322
323 // 0.125f converts from bits to bytes
324 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
325 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
326 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
327 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
328 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
329 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
330 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
331 // State is a subcategory of task that we allocate a percentage to
332 int state = 0;
333
334 // Make sure none of the throttles are set below our packet MTU,
335 // otherwise a throttle could become permanently clogged
336 resend = Math.Max(resend, LLUDPServer.MTU);
337 land = Math.Max(land, LLUDPServer.MTU);
338 wind = Math.Max(wind, LLUDPServer.MTU);
339 cloud = Math.Max(cloud, LLUDPServer.MTU);
340 task = Math.Max(task, LLUDPServer.MTU);
341 texture = Math.Max(texture, LLUDPServer.MTU);
342 asset = Math.Max(asset, LLUDPServer.MTU);
343
344 //int total = resend + land + wind + cloud + task + texture + asset;
345 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
346 // AgentID, resend, land, wind, cloud, task, texture, asset, total);
347
348 // Update the token buckets with new throttle values
349 TokenBucket bucket;
350
351 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
352 bucket.RequestedDripRate = resend;
353
354 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land];
355 bucket.RequestedDripRate = land;
356
357 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind];
358 bucket.RequestedDripRate = wind;
359
360 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud];
361 bucket.RequestedDripRate = cloud;
362
363 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset];
364 bucket.RequestedDripRate = asset;
365
366 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task];
367 bucket.RequestedDripRate = task;
368
369 bucket = m_throttleCategories[(int)ThrottleOutPacketType.State];
370 bucket.RequestedDripRate = state;
371
372 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture];
373 bucket.RequestedDripRate = texture;
374
375 // Reset the packed throttles cached data
376 m_packedThrottles = null;
377 }
378
379 public byte[] GetThrottlesPacked(float multiplier)
380 {
381 byte[] data = m_packedThrottles;
382
383 if (data == null)
384 {
385 float rate;
386
387 data = new byte[7 * 4];
388 int i = 0;
389
390 // multiply by 8 to convert bytes back to bits
391 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier;
392 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
393
394 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier;
395 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
396
397 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * 8 * multiplier;
398 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
399
400 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * 8 * multiplier;
401 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
402
403 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * 8 * multiplier;
404 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
405
406 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * 8 * multiplier;
407 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
408
409 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * 8 * multiplier;
410 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
411
412 m_packedThrottles = data;
413 }
414
415 return data;
416 }
417
418 /// <summary>
419 /// Queue an outgoing packet if appropriate.
420 /// </summary>
421 /// <param name="packet"></param>
422 /// <param name="forceQueue">Always queue the packet if at all possible.</param>
423 /// <returns>
424 /// true if the packet has been queued,
425 /// false if the packet has not been queued and should be sent immediately.
426 /// </returns>
427 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue)
428 {
429 int category = (int)packet.Category;
430
431 if (category >= 0 && category < m_packetOutboxes.Length)
432 {
433 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
434
435 if (m_deliverPackets == false)
436 {
437 queue.Enqueue(packet);
438 return true;
439 }
440
441 TokenBucket bucket = m_throttleCategories[category];
442
443 // Don't send this packet if there is already a packet waiting in the queue
444 // even if we have the tokens to send it, tokens should go to the already
445 // queued packets
446 if (queue.Count > 0)
447 {
448 queue.Enqueue(packet);
449 return true;
450 }
451
452
453 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
454 {
455 // Enough tokens were removed from the bucket, the packet will not be queued
456 return false;
457 }
458 else
459 {
460 // Force queue specified or not enough tokens in the bucket, queue this packet
461 queue.Enqueue(packet);
462 return true;
463 }
464 }
465 else
466 {
467 // We don't have a token bucket for this category, so it will not be queued
468 return false;
469 }
470 }
471
472 /// <summary>
473 /// Loops through all of the packet queues for this client and tries to send
474 /// an outgoing packet from each, obeying the throttling bucket limits
475 /// </summary>
476 ///
477 /// <remarks>
478 /// Packet queues are inspected in ascending numerical order starting from 0. Therefore, queues with a lower
479 /// ThrottleOutPacketType number will see their packet get sent first (e.g. if both Land and Wind queues have
480 /// packets, then the packet at the front of the Land queue will be sent before the packet at the front of the
481 /// wind queue).
482 ///
483 /// This function is only called from a synchronous loop in the
484 /// UDPServer so we don't need to bother making this thread safe
485 /// </remarks>
486 ///
487 /// <returns>True if any packets were sent, otherwise false</returns>
488 public bool DequeueOutgoing()
489 {
490 if (m_deliverPackets == false) return false;
491
492 OutgoingPacket packet;
493 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
494 TokenBucket bucket;
495 bool packetSent = false;
496 ThrottleOutPacketTypeFlags emptyCategories = 0;
497
498 //string queueDebugOutput = String.Empty; // Serious debug business
499
500 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
501 {
502 bucket = m_throttleCategories[i];
503 //queueDebugOutput += m_packetOutboxes[i].Count + " "; // Serious debug business
504
505 if (m_nextPackets[i] != null)
506 {
507 // This bucket was empty the last time we tried to send a packet,
508 // leaving a dequeued packet still waiting to be sent out. Try to
509 // send it again
510 OutgoingPacket nextPacket = m_nextPackets[i];
511 if (bucket.RemoveTokens(nextPacket.Buffer.DataLength))
512 {
513 // Send the packet
514 m_udpServer.SendPacketFinal(nextPacket);
515 m_nextPackets[i] = null;
516 packetSent = true;
517 }
518 }
519 else
520 {
521 // No dequeued packet waiting to be sent, try to pull one off
522 // this queue
523 queue = m_packetOutboxes[i];
524 if (queue.Dequeue(out packet))
525 {
526 // A packet was pulled off the queue. See if we have
527 // enough tokens in the bucket to send it out
528 if (bucket.RemoveTokens(packet.Buffer.DataLength))
529 {
530 // Send the packet
531 m_udpServer.SendPacketFinal(packet);
532 packetSent = true;
533 }
534 else
535 {
536 // Save the dequeued packet for the next iteration
537 m_nextPackets[i] = packet;
538 }
539
540 // If the queue is empty after this dequeue, fire the queue
541 // empty callback now so it has a chance to fill before we
542 // get back here
543 if (queue.Count == 0)
544 emptyCategories |= CategoryToFlag(i);
545 }
546 else
547 {
548 // No packets in this queue. Fire the queue empty callback
549 // if it has not been called recently
550 emptyCategories |= CategoryToFlag(i);
551 }
552 }
553 }
554
555 if (emptyCategories != 0)
556 BeginFireQueueEmpty(emptyCategories);
557
558 //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business
559 return packetSent;
560 }
561
562 /// <summary>
563 /// Called when an ACK packet is received and a round-trip time for a
564 /// packet is calculated. This is used to calculate the smoothed
565 /// round-trip time, round trip time variance, and finally the
566 /// retransmission timeout
567 /// </summary>
568 /// <param name="r">Round-trip time of a single packet and its
569 /// acknowledgement</param>
570 public void UpdateRoundTrip(float r)
571 {
572 const float ALPHA = 0.125f;
573 const float BETA = 0.25f;
574 const float K = 4.0f;
575
576 if (RTTVAR == 0.0f)
577 {
578 // First RTT measurement
579 SRTT = r;
580 RTTVAR = r * 0.5f;
581 }
582 else
583 {
584 // Subsequence RTT measurement
585 RTTVAR = (1.0f - BETA) * RTTVAR + BETA * Math.Abs(SRTT - r);
586 SRTT = (1.0f - ALPHA) * SRTT + ALPHA * r;
587 }
588
589 int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR));
590
591 // Clamp the retransmission timeout to manageable values
592 rto = Utils.Clamp(rto, m_defaultRTO, m_maxRTO);
593
594 RTO = rto;
595
596 //m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " +
597 // RTTVAR + " based on new RTT of " + r + "ms");
598 }
599
600 /// <summary>
601 /// Exponential backoff of the retransmission timeout, per section 5.5
602 /// of RFC 2988
603 /// </summary>
604 public void BackoffRTO()
605 {
606 // Reset SRTT and RTTVAR, we assume they are bogus since things
607 // didn't work out and we're backing off the timeout
608 SRTT = 0.0f;
609 RTTVAR = 0.0f;
610
611 // Double the retransmission timeout
612 RTO = Math.Min(RTO * 2, m_maxRTO);
613 }
614
615 /// <summary>
616 /// Does an early check to see if this queue empty callback is already
617 /// running, then asynchronously firing the event
618 /// </summary>
619 /// <param name="throttleIndex">Throttle category to fire the callback
620 /// for</param>
621 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
622 {
623 if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
624 {
625 // Use a value of 0 to signal that FireQueueEmpty is running
626 m_nextOnQueueEmpty = 0;
627 // Asynchronously run the callback
628 Util.FireAndForget(FireQueueEmpty, categories);
629 }
630 }
631
632 /// <summary>
633 /// Fires the OnQueueEmpty callback and sets the minimum time that it
634 /// can be called again
635 /// </summary>
636 /// <param name="o">Throttle categories to fire the callback for,
637 /// stored as an object to match the WaitCallback delegate
638 /// signature</param>
639 private void FireQueueEmpty(object o)
640 {
641 const int MIN_CALLBACK_MS = 30;
642
643 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
644 QueueEmpty callback = OnQueueEmpty;
645
646 int start = Environment.TickCount & Int32.MaxValue;
647
648 if (callback != null)
649 {
650 try { callback(categories); }
651 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
652 }
653
654 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
655 if (m_nextOnQueueEmpty == 0)
656 m_nextOnQueueEmpty = 1;
657 }
658
659 /// <summary>
660 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a
661 /// flag value
662 /// </summary>
663 /// <param name="i">Throttle category to convert</param>
664 /// <returns>Flag representation of the throttle category</returns>
665 private static ThrottleOutPacketTypeFlags CategoryToFlag(int i)
666 {
667 ThrottleOutPacketType category = (ThrottleOutPacketType)i;
668
669 /*
670 * Land = 1,
671 /// <summary>Wind data</summary>
672 Wind = 2,
673 /// <summary>Cloud data</summary>
674 Cloud = 3,
675 /// <summary>Any packets that do not fit into the other throttles</summary>
676 Task = 4,
677 /// <summary>Texture assets</summary>
678 Texture = 5,
679 /// <summary>Non-texture assets</summary>
680 Asset = 6,
681 /// <summary>Avatar and primitive data</summary>
682 /// <remarks>This is a sub-category of Task</remarks>
683 State = 7,
684 */
685
686 switch (category)
687 {
688 case ThrottleOutPacketType.Land:
689 return ThrottleOutPacketTypeFlags.Land;
690 case ThrottleOutPacketType.Wind:
691 return ThrottleOutPacketTypeFlags.Wind;
692 case ThrottleOutPacketType.Cloud:
693 return ThrottleOutPacketTypeFlags.Cloud;
694 case ThrottleOutPacketType.Task:
695 return ThrottleOutPacketTypeFlags.Task;
696 case ThrottleOutPacketType.Texture:
697 return ThrottleOutPacketTypeFlags.Texture;
698 case ThrottleOutPacketType.Asset:
699 return ThrottleOutPacketTypeFlags.Asset;
700 case ThrottleOutPacketType.State:
701 return ThrottleOutPacketTypeFlags.State;
702 default:
703 return 0;
704 }
705 }
706 }
707}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
new file mode 100644
index 0000000..ab6674d
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -0,0 +1,1276 @@
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(false);
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 m_scene.ThreadAlive(1);
976 try
977 {
978 IncomingPacket incomingPacket = null;
979
980 // HACK: This is a test to try and rate limit packet handling on Mono.
981 // If it works, a more elegant solution can be devised
982 if (Util.FireAndForgetCount() < 2)
983 {
984 //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping");
985 Thread.Sleep(30);
986 }
987
988 if (packetInbox.Dequeue(100, ref incomingPacket))
989 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket);
990 }
991 catch (Exception ex)
992 {
993 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
994 }
995
996 Watchdog.UpdateThread();
997 }
998
999 if (packetInbox.Count > 0)
1000 m_log.Warn("[LLUDPSERVER]: IncomingPacketHandler is shutting down, dropping " + packetInbox.Count + " packets");
1001 packetInbox.Clear();
1002
1003 Watchdog.RemoveThread();
1004 }
1005
1006 private void OutgoingPacketHandler()
1007 {
1008 // Set this culture for the thread that outgoing packets are sent
1009 // on to en-US to avoid number parsing issues
1010 Culture.SetCurrentCulture();
1011
1012 // Typecast the function to an Action<IClientAPI> once here to avoid allocating a new
1013 // Action generic every round
1014 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
1015
1016 while (base.IsRunning)
1017 {
1018 m_scene.ThreadAlive(2);
1019 try
1020 {
1021 m_packetSent = false;
1022
1023 #region Update Timers
1024
1025 m_resendUnacked = false;
1026 m_sendAcks = false;
1027 m_sendPing = false;
1028
1029 // Update elapsed time
1030 int thisTick = Environment.TickCount & Int32.MaxValue;
1031 if (m_tickLastOutgoingPacketHandler > thisTick)
1032 m_elapsedMSOutgoingPacketHandler += ((Int32.MaxValue - m_tickLastOutgoingPacketHandler) + thisTick);
1033 else
1034 m_elapsedMSOutgoingPacketHandler += (thisTick - m_tickLastOutgoingPacketHandler);
1035
1036 m_tickLastOutgoingPacketHandler = thisTick;
1037
1038 // Check for pending outgoing resends every 100ms
1039 if (m_elapsedMSOutgoingPacketHandler >= 100)
1040 {
1041 m_resendUnacked = true;
1042 m_elapsedMSOutgoingPacketHandler = 0;
1043 m_elapsed100MSOutgoingPacketHandler += 1;
1044 }
1045
1046 // Check for pending outgoing ACKs every 500ms
1047 if (m_elapsed100MSOutgoingPacketHandler >= 5)
1048 {
1049 m_sendAcks = true;
1050 m_elapsed100MSOutgoingPacketHandler = 0;
1051 m_elapsed500MSOutgoingPacketHandler += 1;
1052 }
1053
1054 // Send pings to clients every 5000ms
1055 if (m_elapsed500MSOutgoingPacketHandler >= 10)
1056 {
1057 m_sendPing = true;
1058 m_elapsed500MSOutgoingPacketHandler = 0;
1059 }
1060
1061 #endregion Update Timers
1062
1063 // Use this for emergency monitoring -- bug hunting
1064 //if (m_scene.EmergencyMonitoring)
1065 // clientPacketHandler = MonitoredClientOutgoingPacketHandler;
1066 //else
1067 // clientPacketHandler = ClientOutgoingPacketHandler;
1068
1069 // Handle outgoing packets, resends, acknowledgements, and pings for each
1070 // client. m_packetSent will be set to true if a packet is sent
1071 m_scene.ForEachClient(clientPacketHandler);
1072
1073 // If nothing was sent, sleep for the minimum amount of time before a
1074 // token bucket could get more tokens
1075 if (!m_packetSent)
1076 Thread.Sleep((int)TickCountResolution);
1077
1078 Watchdog.UpdateThread();
1079 }
1080 catch (Exception ex)
1081 {
1082 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex);
1083 }
1084
1085 }
1086
1087 Watchdog.RemoveThread();
1088 }
1089
1090 private void ClientOutgoingPacketHandler(IClientAPI client)
1091 {
1092 try
1093 {
1094 if (client is LLClientView)
1095 {
1096 LLUDPClient udpClient = ((LLClientView)client).UDPClient;
1097
1098 if (udpClient.IsConnected)
1099 {
1100 if (m_resendUnacked)
1101 HandleUnacked(udpClient);
1102
1103 if (m_sendAcks)
1104 SendAcks(udpClient);
1105
1106 if (m_sendPing)
1107 SendPing(udpClient);
1108
1109 // Dequeue any outgoing packets that are within the throttle limits
1110 if (udpClient.DequeueOutgoing())
1111 m_packetSent = true;
1112 }
1113 }
1114 }
1115 catch (Exception ex)
1116 {
1117 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name +
1118 " threw an exception: " + ex.Message, ex);
1119 }
1120 }
1121
1122 #region Emergency Monitoring
1123 // Alternative packet handler fuull of instrumentation
1124 // Handy for hunting bugs
1125 private Stopwatch watch1 = new Stopwatch();
1126 private Stopwatch watch2 = new Stopwatch();
1127
1128 private float avgProcessingTicks = 0;
1129 private float avgResendUnackedTicks = 0;
1130 private float avgSendAcksTicks = 0;
1131 private float avgSendPingTicks = 0;
1132 private float avgDequeueTicks = 0;
1133 private long nticks = 0;
1134 private long nticksUnack = 0;
1135 private long nticksAck = 0;
1136 private long nticksPing = 0;
1137 private int npacksSent = 0;
1138 private int npackNotSent = 0;
1139
1140 private void MonitoredClientOutgoingPacketHandler(IClientAPI client)
1141 {
1142 nticks++;
1143 watch1.Start();
1144 try
1145 {
1146 if (client is LLClientView)
1147 {
1148 LLUDPClient udpClient = ((LLClientView)client).UDPClient;
1149
1150 if (udpClient.IsConnected)
1151 {
1152 if (m_resendUnacked)
1153 {
1154 nticksUnack++;
1155 watch2.Start();
1156
1157 HandleUnacked(udpClient);
1158
1159 watch2.Stop();
1160 avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
1161 watch2.Reset();
1162 }
1163
1164 if (m_sendAcks)
1165 {
1166 nticksAck++;
1167 watch2.Start();
1168
1169 SendAcks(udpClient);
1170
1171 watch2.Stop();
1172 avgSendAcksTicks = (nticksAck - 1) / (float)nticksAck * avgSendAcksTicks + (watch2.ElapsedTicks / (float)nticksAck);
1173 watch2.Reset();
1174 }
1175
1176 if (m_sendPing)
1177 {
1178 nticksPing++;
1179 watch2.Start();
1180
1181 SendPing(udpClient);
1182
1183 watch2.Stop();
1184 avgSendPingTicks = (nticksPing - 1) / (float)nticksPing * avgSendPingTicks + (watch2.ElapsedTicks / (float)nticksPing);
1185 watch2.Reset();
1186 }
1187
1188 watch2.Start();
1189 // Dequeue any outgoing packets that are within the throttle limits
1190 if (udpClient.DequeueOutgoing())
1191 {
1192 m_packetSent = true;
1193 npacksSent++;
1194 }
1195 else
1196 npackNotSent++;
1197
1198 watch2.Stop();
1199 avgDequeueTicks = (nticks - 1) / (float)nticks * avgDequeueTicks + (watch2.ElapsedTicks / (float)nticks);
1200 watch2.Reset();
1201
1202 }
1203 else
1204 m_log.WarnFormat("[LLUDPSERVER]: Client is not connected");
1205 }
1206 }
1207 catch (Exception ex)
1208 {
1209 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name +
1210 " threw an exception: " + ex.Message, ex);
1211 }
1212 watch1.Stop();
1213 avgProcessingTicks = (nticks - 1) / (float)nticks * avgProcessingTicks + (watch1.ElapsedTicks / (float)nticks);
1214 watch1.Reset();
1215
1216 // reuse this -- it's every ~100ms
1217 if (m_scene.EmergencyMonitoring && nticks % 100 == 0)
1218 {
1219 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})",
1220 avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent);
1221 npackNotSent = npacksSent = 0;
1222 }
1223
1224 }
1225
1226 #endregion
1227
1228 private void ProcessInPacket(object state)
1229 {
1230 IncomingPacket incomingPacket = (IncomingPacket)state;
1231 Packet packet = incomingPacket.Packet;
1232 LLUDPClient udpClient = incomingPacket.Client;
1233 IClientAPI client;
1234
1235 // Sanity check
1236 if (packet == null || udpClient == null)
1237 {
1238 m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", UDPClient=\"{1}\"",
1239 packet, udpClient);
1240 }
1241
1242 // Make sure this client is still alive
1243 if (m_scene.TryGetClient(udpClient.AgentID, out client))
1244 {
1245 try
1246 {
1247 // Process this packet
1248 client.ProcessInPacket(packet);
1249 }
1250 catch (ThreadAbortException)
1251 {
1252 // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down
1253 m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server");
1254 Stop();
1255 }
1256 catch (Exception e)
1257 {
1258 // Don't let a failure in an individual client thread crash the whole sim.
1259 m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type);
1260 m_log.Error(e.Message, e);
1261 }
1262 }
1263 else
1264 {
1265 m_log.DebugFormat("[LLUDPSERVER]: Dropping incoming {0} packet for dead client {1}", packet.Type, udpClient.AgentID);
1266 }
1267 }
1268
1269 protected void LogoutHandler(IClientAPI client)
1270 {
1271 client.SendLogoutPacket();
1272 if (client.IsActive)
1273 RemoveClient(((LLClientView)client).UDPClient);
1274 }
1275 }
1276}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
new file mode 100644
index 0000000..d2779ba
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -0,0 +1,280 @@
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_udpSocket = new Socket(
105 AddressFamily.InterNetwork,
106 SocketType.Dgram,
107 ProtocolType.Udp);
108
109 try
110 {
111 // This udp socket flag is not supported under mono,
112 // so we'll catch the exception and continue
113 m_udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null);
114 m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag set");
115 }
116 catch (SocketException)
117 {
118 m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag not supported on this platform, ignoring");
119 }
120
121 if (recvBufferSize != 0)
122 m_udpSocket.ReceiveBufferSize = recvBufferSize;
123
124 m_udpSocket.Bind(ipep);
125
126 // we're not shutting down, we're starting up
127 m_shutdownFlag = false;
128
129 // kick off an async receive. The Start() method will return, the
130 // actual receives will occur asynchronously and will be caught in
131 // AsyncEndRecieve().
132 AsyncBeginReceive();
133 }
134 }
135
136 /// <summary>
137 /// Stops the UDP server
138 /// </summary>
139 public void Stop()
140 {
141 if (!m_shutdownFlag)
142 {
143 // wait indefinitely for a writer lock. Once this is called, the .NET runtime
144 // will deny any more reader locks, in effect blocking all other send/receive
145 // threads. Once we have the lock, we set shutdownFlag to inform the other
146 // threads that the socket is closed.
147 m_shutdownFlag = true;
148 m_udpSocket.Close();
149 }
150 }
151
152 private void AsyncBeginReceive()
153 {
154 // allocate a packet buffer
155 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
156 UDPPacketBuffer buf = new UDPPacketBuffer();
157
158 if (!m_shutdownFlag)
159 {
160 try
161 {
162 // kick off an async read
163 m_udpSocket.BeginReceiveFrom(
164 //wrappedBuffer.Instance.Data,
165 buf.Data,
166 0,
167 UDPPacketBuffer.BUFFER_SIZE,
168 SocketFlags.None,
169 ref buf.RemoteEndPoint,
170 AsyncEndReceive,
171 //wrappedBuffer);
172 buf);
173 }
174 catch (SocketException e)
175 {
176 if (e.SocketErrorCode == SocketError.ConnectionReset)
177 {
178 m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort);
179 bool salvaged = false;
180 while (!salvaged)
181 {
182 try
183 {
184 m_udpSocket.BeginReceiveFrom(
185 //wrappedBuffer.Instance.Data,
186 buf.Data,
187 0,
188 UDPPacketBuffer.BUFFER_SIZE,
189 SocketFlags.None,
190 ref buf.RemoteEndPoint,
191 AsyncEndReceive,
192 //wrappedBuffer);
193 buf);
194 salvaged = true;
195 }
196 catch (SocketException) { }
197 catch (ObjectDisposedException) { return; }
198 }
199
200 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
201 }
202 }
203 catch (ObjectDisposedException) { }
204 }
205 }
206
207 private void AsyncEndReceive(IAsyncResult iar)
208 {
209 // Asynchronous receive operations will complete here through the call
210 // to AsyncBeginReceive
211 if (!m_shutdownFlag)
212 {
213 // Asynchronous mode will start another receive before the
214 // callback for this packet is even fired. Very parallel :-)
215 if (m_asyncPacketHandling)
216 AsyncBeginReceive();
217
218 // get the buffer that was created in AsyncBeginReceive
219 // this is the received data
220 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
221 //UDPPacketBuffer buffer = wrappedBuffer.Instance;
222 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
223
224 try
225 {
226 // get the length of data actually read from the socket, store it with the
227 // buffer
228 buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);
229
230 // call the abstract method PacketReceived(), passing the buffer that
231 // has just been filled from the socket read.
232 PacketReceived(buffer);
233 }
234 catch (SocketException) { }
235 catch (ObjectDisposedException) { }
236 finally
237 {
238 //wrappedBuffer.Dispose();
239
240 // Synchronous mode waits until the packet callback completes
241 // before starting the receive to fetch another packet
242 if (!m_asyncPacketHandling)
243 AsyncBeginReceive();
244 }
245
246 }
247 }
248
249 public void AsyncBeginSend(UDPPacketBuffer buf)
250 {
251 if (!m_shutdownFlag)
252 {
253 try
254 {
255 m_udpSocket.BeginSendTo(
256 buf.Data,
257 0,
258 buf.DataLength,
259 SocketFlags.None,
260 buf.RemoteEndPoint,
261 AsyncEndSend,
262 buf);
263 }
264 catch (SocketException) { }
265 catch (ObjectDisposedException) { }
266 }
267 }
268
269 void AsyncEndSend(IAsyncResult result)
270 {
271 try
272 {
273// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState;
274 m_udpSocket.EndSendTo(result);
275 }
276 catch (SocketException) { }
277 catch (ObjectDisposedException) { }
278 }
279 }
280}
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}