aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs978
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs703
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs490
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs22
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs410
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs427
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs18
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs297
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs20
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs184
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs12
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs1694
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs303
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs423
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs10
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs12
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs219
19 files changed, 4629 insertions, 1605 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 774202e..4e6d196 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Timers;
29using System.Collections; 30using System.Collections;
30using System.Collections.Generic; 31using System.Collections.Generic;
31using System.IO; 32using System.IO;
@@ -55,14 +56,16 @@ using PermissionMask = OpenSim.Framework.PermissionMask;
55namespace OpenSim.Region.ClientStack.Linden 56namespace OpenSim.Region.ClientStack.Linden
56{ 57{
57 public delegate void UpLoadedAsset( 58 public delegate void UpLoadedAsset(
58 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, 59 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
59 byte[] data, string inventoryType, string assetType); 60 byte[] data, string inventoryType, string assetType,
61 int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
62 bool IsAtestUpload, ref string error);
60 63
61 public delegate UUID UpdateItem(UUID itemID, byte[] data); 64 public delegate UUID UpdateItem(UUID itemID, byte[] data);
62 65
63 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); 66 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors);
64 67
65 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item); 68 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item, uint cost);
66 69
67 public delegate void NewAsset(AssetBase asset); 70 public delegate void NewAsset(AssetBase asset);
68 71
@@ -88,6 +91,7 @@ namespace OpenSim.Region.ClientStack.Linden
88 91
89 private Scene m_Scene; 92 private Scene m_Scene;
90 private Caps m_HostCapsObj; 93 private Caps m_HostCapsObj;
94 private ModelCost m_ModelCost;
91 95
92 private static readonly string m_requestPath = "0000/"; 96 private static readonly string m_requestPath = "0000/";
93 // private static readonly string m_mapLayerPath = "0001/"; 97 // private static readonly string m_mapLayerPath = "0001/";
@@ -99,8 +103,10 @@ namespace OpenSim.Region.ClientStack.Linden
99 private static readonly string m_copyFromNotecardPath = "0007/"; 103 private static readonly string m_copyFromNotecardPath = "0007/";
100 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. 104 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule.
101 private static readonly string m_getObjectPhysicsDataPath = "0101/"; 105 private static readonly string m_getObjectPhysicsDataPath = "0101/";
102 /* 0102 - 0103 RESERVED */ 106 private static readonly string m_getObjectCostPath = "0102/";
107 private static readonly string m_ResourceCostSelectedPath = "0103/";
103 private static readonly string m_UpdateAgentInformationPath = "0500/"; 108 private static readonly string m_UpdateAgentInformationPath = "0500/";
109 private static readonly string m_animSetTaskUpdatePath = "0260/";
104 110
105 // These are callbacks which will be setup by the scene so that we can update scene data when we 111 // These are callbacks which will be setup by the scene so that we can update scene data when we
106 // receive capability calls 112 // receive capability calls
@@ -115,12 +121,50 @@ namespace OpenSim.Region.ClientStack.Linden
115 private IAssetService m_assetService; 121 private IAssetService m_assetService;
116 private bool m_dumpAssetsToFile = false; 122 private bool m_dumpAssetsToFile = false;
117 private string m_regionName; 123 private string m_regionName;
124
118 private int m_levelUpload = 0; 125 private int m_levelUpload = 0;
119 126
127 private bool m_enableFreeTestUpload = false; // allows "TEST-" prefix hack
128 private bool m_ForceFreeTestUpload = false; // forces all uploads to be test
129
130 private bool m_enableModelUploadTextureToInventory = false; // place uploaded textures also in inventory
131 // may not be visible till relog
132
133 private bool m_RestrictFreeTestUploadPerms = false; // reduces also the permitions. Needs a creator defined!!
134 private UUID m_testAssetsCreatorID = UUID.Zero;
135
136 private float m_PrimScaleMin = 0.001f;
137
138 private enum FileAgentInventoryState : int
139 {
140 idle = 0,
141 processRequest = 1,
142 waitUpload = 2,
143 processUpload = 3
144 }
145 private FileAgentInventoryState m_FileAgentInventoryState = FileAgentInventoryState.idle;
146
120 public BunchOfCaps(Scene scene, Caps caps) 147 public BunchOfCaps(Scene scene, Caps caps)
121 { 148 {
122 m_Scene = scene; 149 m_Scene = scene;
123 m_HostCapsObj = caps; 150 m_HostCapsObj = caps;
151
152 // create a model upload cost provider
153 m_ModelCost = new ModelCost();
154 // tell it about scene object limits
155 m_ModelCost.NonPhysicalPrimScaleMax = m_Scene.m_maxNonphys;
156 m_ModelCost.PhysicalPrimScaleMax = m_Scene.m_maxPhys;
157
158// m_ModelCost.ObjectLinkedPartsMax = ??
159// m_ModelCost.PrimScaleMin = ??
160
161 m_PrimScaleMin = m_ModelCost.PrimScaleMin;
162 float modelTextureUploadFactor = m_ModelCost.ModelTextureCostFactor;
163 float modelUploadFactor = m_ModelCost.ModelMeshCostFactor;
164 float modelMinUploadCostFactor = m_ModelCost.ModelMinCostFactor;
165 float modelPrimCreationCost = m_ModelCost.primCreationCost;
166 float modelMeshByteCost = m_ModelCost.bytecost;
167
124 IConfigSource config = m_Scene.Config; 168 IConfigSource config = m_Scene.Config;
125 if (config != null) 169 if (config != null)
126 { 170 {
@@ -135,6 +179,37 @@ namespace OpenSim.Region.ClientStack.Linden
135 { 179 {
136 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); 180 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
137 } 181 }
182 // economy for model upload
183 IConfig EconomyConfig = config.Configs["Economy"];
184 if (EconomyConfig != null)
185 {
186 modelUploadFactor = EconomyConfig.GetFloat("MeshModelUploadCostFactor", modelUploadFactor);
187 modelTextureUploadFactor = EconomyConfig.GetFloat("MeshModelUploadTextureCostFactor", modelTextureUploadFactor);
188 modelMinUploadCostFactor = EconomyConfig.GetFloat("MeshModelMinCostFactor", modelMinUploadCostFactor);
189 // next 2 are normalized so final cost is afected by modelUploadFactor above and normal cost
190 modelPrimCreationCost = EconomyConfig.GetFloat("ModelPrimCreationCost", modelPrimCreationCost);
191 modelMeshByteCost = EconomyConfig.GetFloat("ModelMeshByteCost", modelMeshByteCost);
192
193 m_enableModelUploadTextureToInventory = EconomyConfig.GetBoolean("MeshModelAllowTextureToInventory", m_enableModelUploadTextureToInventory);
194
195 m_RestrictFreeTestUploadPerms = EconomyConfig.GetBoolean("m_RestrictFreeTestUploadPerms", m_RestrictFreeTestUploadPerms);
196 m_enableFreeTestUpload = EconomyConfig.GetBoolean("AllowFreeTestUpload", m_enableFreeTestUpload);
197 m_ForceFreeTestUpload = EconomyConfig.GetBoolean("ForceFreeTestUpload", m_ForceFreeTestUpload);
198 string testcreator = EconomyConfig.GetString("TestAssetsCreatorID", "");
199 if (testcreator != "")
200 {
201 UUID id;
202 UUID.TryParse(testcreator, out id);
203 if (id != null)
204 m_testAssetsCreatorID = id;
205 }
206
207 m_ModelCost.ModelMeshCostFactor = modelUploadFactor;
208 m_ModelCost.ModelTextureCostFactor = modelTextureUploadFactor;
209 m_ModelCost.ModelMinCostFactor = modelMinUploadCostFactor;
210 m_ModelCost.primCreationCost = modelPrimCreationCost;
211 m_ModelCost.bytecost = modelMeshByteCost;
212 }
138 } 213 }
139 214
140 m_assetService = m_Scene.AssetService; 215 m_assetService = m_Scene.AssetService;
@@ -146,6 +221,8 @@ namespace OpenSim.Region.ClientStack.Linden
146 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset; 221 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset;
147 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset; 222 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset;
148 GetClient = m_Scene.SceneGraph.GetControllingClient; 223 GetClient = m_Scene.SceneGraph.GetControllingClient;
224
225 m_FileAgentInventoryState = FileAgentInventoryState.idle;
149 } 226 }
150 227
151 /// <summary> 228 /// <summary>
@@ -173,13 +250,31 @@ namespace OpenSim.Region.ClientStack.Linden
173 //m_capsHandlers["MapLayer"] = 250 //m_capsHandlers["MapLayer"] =
174 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST", 251 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
175 // capsBase + m_mapLayerPath, 252 // capsBase + m_mapLayerPath,
176 // GetMapLayer); 253 // GetMapLayer);
254
255 IRequestHandler getObjectPhysicsDataHandler
256 = new RestStreamHandler(
257 "POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData, "GetObjectPhysicsData", null);
258 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
259
260 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost);
261 m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler);
262 IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected);
263 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
264
265
177 IRequestHandler req 266 IRequestHandler req
178 = new RestStreamHandler( 267 = new RestStreamHandler(
179 "POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory, "UpdateScript", null); 268 "POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory, "UpdateScript", null);
180 269
181 m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req); 270 m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req);
182 m_HostCapsObj.RegisterHandler("UpdateScriptTask", req); 271 m_HostCapsObj.RegisterHandler("UpdateScriptTask", req);
272
273// IRequestHandler animSetRequestHandler
274// = new RestStreamHandler(
275// "POST", capsBase + m_animSetTaskUpdatePath, AnimSetTaskInventory, "UpdateScript", null);
276
277// m_HostCapsObj.RegisterHandler("UpdateAnimSetTaskInventory", animSetRequestHandler);
183 } 278 }
184 catch (Exception e) 279 catch (Exception e)
185 { 280 {
@@ -191,7 +286,6 @@ namespace OpenSim.Region.ClientStack.Linden
191 { 286 {
192 try 287 try
193 { 288 {
194 // I don't think this one works...
195 m_HostCapsObj.RegisterHandler( 289 m_HostCapsObj.RegisterHandler(
196 "NewFileAgentInventory", 290 "NewFileAgentInventory",
197 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>( 291 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>(
@@ -206,13 +300,11 @@ namespace OpenSim.Region.ClientStack.Linden
206 "POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory, "Update*", null); 300 "POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory, "Update*", null);
207 301
208 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); 302 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
303 m_HostCapsObj.RegisterHandler("UpdateAnimSetAgentInventory", req);
209 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); 304 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
210 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); 305 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
211 306
212 IRequestHandler getObjectPhysicsDataHandler 307
213 = new RestStreamHandler(
214 "POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData, "GetObjectPhysicsData", null);
215 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
216 308
217 IRequestHandler UpdateAgentInformationHandler 309 IRequestHandler UpdateAgentInformationHandler
218 = new RestStreamHandler( 310 = new RestStreamHandler(
@@ -271,6 +363,9 @@ namespace OpenSim.Region.ClientStack.Linden
271// m_log.DebugFormat( 363// m_log.DebugFormat(
272// "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID); 364// "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID);
273 365
366 if (!m_HostCapsObj.WaitForActivation())
367 return string.Empty;
368
274 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) 369 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
275 { 370 {
276 m_log.WarnFormat( 371 m_log.WarnFormat(
@@ -400,62 +495,178 @@ namespace OpenSim.Region.ClientStack.Linden
400 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString()); 495 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
401 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type); 496 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
402 497
498 // start by getting the client
499 IClientAPI client = null;
500 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
501
502 // check current state so we only have one service at a time
503 lock (m_ModelCost)
504 {
505 switch (m_FileAgentInventoryState)
506 {
507 case FileAgentInventoryState.processRequest:
508 case FileAgentInventoryState.processUpload:
509 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
510 resperror.message = "Uploader busy processing previus request";
511 resperror.identifier = UUID.Zero;
512
513 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
514 errorResponse.uploader = "";
515 errorResponse.state = "error";
516 errorResponse.error = resperror;
517 return errorResponse;
518 break;
519 case FileAgentInventoryState.waitUpload:
520 // todo stop current uploader server
521 break;
522 case FileAgentInventoryState.idle:
523 default:
524 break;
525 }
526
527 m_FileAgentInventoryState = FileAgentInventoryState.processRequest;
528 }
529
530 int cost = 0;
531 int nreqtextures = 0;
532 int nreqmeshs= 0;
533 int nreqinstances = 0;
534 bool IsAtestUpload = false;
535
536 string assetName = llsdRequest.name;
537
538 LLSDAssetUploadResponseData meshcostdata = new LLSDAssetUploadResponseData();
539
403 if (llsdRequest.asset_type == "texture" || 540 if (llsdRequest.asset_type == "texture" ||
404 llsdRequest.asset_type == "animation" || 541 llsdRequest.asset_type == "animation" ||
542 llsdRequest.asset_type == "animatn" || // this is the asset name actually used by viewers
543 llsdRequest.asset_type == "mesh" ||
405 llsdRequest.asset_type == "sound") 544 llsdRequest.asset_type == "sound")
406 { 545 {
407 ScenePresence avatar = null; 546 ScenePresence avatar = null;
408 IClientAPI client = null;
409 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar); 547 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar);
410 548
411 // check user level 549 // check user level
412 if (avatar != null) 550 if (avatar != null)
413 { 551 {
414 client = avatar.ControllingClient;
415
416 if (avatar.UserLevel < m_levelUpload) 552 if (avatar.UserLevel < m_levelUpload)
417 { 553 {
418 if (client != null) 554 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
419 client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false); 555 resperror.message = "Insufficient permissions to upload";
556 resperror.identifier = UUID.Zero;
420 557
421 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 558 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
422 errorResponse.uploader = ""; 559 errorResponse.uploader = "";
423 errorResponse.state = "error"; 560 errorResponse.state = "error";
561 errorResponse.error = resperror;
562 lock (m_ModelCost)
563 m_FileAgentInventoryState = FileAgentInventoryState.idle;
424 return errorResponse; 564 return errorResponse;
425 } 565 }
426 } 566 }
427 567
428 // check funds 568 // check test upload and funds
429 if (client != null) 569 if (client != null)
430 { 570 {
431 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>(); 571 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
432 572
573 int baseCost = 0;
433 if (mm != null) 574 if (mm != null)
575 baseCost = mm.UploadCharge;
576
577 string warning = String.Empty;
578
579 if (llsdRequest.asset_type == "mesh")
434 { 580 {
435 if (!mm.UploadCovered(client.AgentId, mm.UploadCharge)) 581 string error;
582 int modelcost;
583
584
585 if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost,
586 meshcostdata, out error, ref warning))
436 { 587 {
437 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); 588 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
589 resperror.message = error;
590 resperror.identifier = UUID.Zero;
438 591
439 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 592 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
440 errorResponse.uploader = ""; 593 errorResponse.uploader = "";
441 errorResponse.state = "error"; 594 errorResponse.state = "error";
595 errorResponse.error = resperror;
596
597 lock (m_ModelCost)
598 m_FileAgentInventoryState = FileAgentInventoryState.idle;
442 return errorResponse; 599 return errorResponse;
443 } 600 }
601 cost = modelcost;
444 } 602 }
603 else
604 {
605 cost = baseCost;
606 }
607
608 if (cost > 0 && mm != null)
609 {
610 // check for test upload
611
612 if (m_ForceFreeTestUpload) // all are test
613 {
614 if (!(assetName.Length > 5 && assetName.StartsWith("TEST-"))) // has normal name lets change it
615 assetName = "TEST-" + assetName;
616
617 IsAtestUpload = true;
618 }
619
620 else if (m_enableFreeTestUpload) // only if prefixed with "TEST-"
621 {
622
623 IsAtestUpload = (assetName.Length > 5 && assetName.StartsWith("TEST-"));
624 }
625
626
627 if(IsAtestUpload) // let user know, still showing cost estimation
628 warning += "Upload will have no cost, for testing purposes only. Other uses are prohibited. Items will not work after 48 hours or on other regions";
629
630 // check funds
631 else
632 {
633 if (!mm.UploadCovered(client.AgentId, (int)cost))
634 {
635 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
636 resperror.message = "Insuficient funds";
637 resperror.identifier = UUID.Zero;
638
639 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
640 errorResponse.uploader = "";
641 errorResponse.state = "error";
642 errorResponse.error = resperror;
643 lock (m_ModelCost)
644 m_FileAgentInventoryState = FileAgentInventoryState.idle;
645 return errorResponse;
646 }
647 }
648 }
649
650 if (client != null && warning != String.Empty)
651 client.SendAgentAlertMessage(warning, true);
445 } 652 }
446 } 653 }
447 654
448 string assetName = llsdRequest.name;
449 string assetDes = llsdRequest.description; 655 string assetDes = llsdRequest.description;
450 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; 656 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
451 UUID newAsset = UUID.Random(); 657 UUID newAsset = UUID.Random();
452 UUID newInvItem = UUID.Random(); 658 UUID newInvItem = UUID.Random();
453 UUID parentFolder = llsdRequest.folder_id; 659 UUID parentFolder = llsdRequest.folder_id;
454 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); 660 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
661 UUID texturesFolder = UUID.Zero;
662
663 if(!IsAtestUpload && m_enableModelUploadTextureToInventory)
664 texturesFolder = llsdRequest.texture_folder_id;
455 665
456 AssetUploader uploader = 666 AssetUploader uploader =
457 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, 667 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
458 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); 668 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost,
669 texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload);
459 670
460 m_HostCapsObj.HttpListener.AddStreamHandler( 671 m_HostCapsObj.HttpListener.AddStreamHandler(
461 new BinaryStreamHandler( 672 new BinaryStreamHandler(
@@ -473,10 +684,22 @@ namespace OpenSim.Region.ClientStack.Linden
473 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + 684 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
474 uploaderPath; 685 uploaderPath;
475 686
687
476 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); 688 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
477 uploadResponse.uploader = uploaderURL; 689 uploadResponse.uploader = uploaderURL;
478 uploadResponse.state = "upload"; 690 uploadResponse.state = "upload";
691 uploadResponse.upload_price = (int)cost;
692
693 if (llsdRequest.asset_type == "mesh")
694 {
695 uploadResponse.data = meshcostdata;
696 }
697
479 uploader.OnUpLoad += UploadCompleteHandler; 698 uploader.OnUpLoad += UploadCompleteHandler;
699
700 lock (m_ModelCost)
701 m_FileAgentInventoryState = FileAgentInventoryState.waitUpload;
702
480 return uploadResponse; 703 return uploadResponse;
481 } 704 }
482 705
@@ -488,8 +711,14 @@ namespace OpenSim.Region.ClientStack.Linden
488 /// <param name="data"></param> 711 /// <param name="data"></param>
489 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, 712 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
490 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, 713 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
491 string assetType) 714 string assetType, int cost,
715 UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
716 bool IsAtestUpload, ref string error)
492 { 717 {
718
719 lock (m_ModelCost)
720 m_FileAgentInventoryState = FileAgentInventoryState.processUpload;
721
493 m_log.DebugFormat( 722 m_log.DebugFormat(
494 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}", 723 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}",
495 assetID, inventoryItem, inventoryType, assetType); 724 assetID, inventoryItem, inventoryType, assetType);
@@ -497,6 +726,34 @@ namespace OpenSim.Region.ClientStack.Linden
497 sbyte assType = 0; 726 sbyte assType = 0;
498 sbyte inType = 0; 727 sbyte inType = 0;
499 728
729 IClientAPI client = null;
730
731 UUID owner_id = m_HostCapsObj.AgentID;
732 UUID creatorID;
733
734 bool istest = IsAtestUpload && m_enableFreeTestUpload && (cost > 0);
735
736 bool restrictPerms = m_RestrictFreeTestUploadPerms && istest;
737
738 if (istest && m_testAssetsCreatorID != UUID.Zero)
739 creatorID = m_testAssetsCreatorID;
740 else
741 creatorID = owner_id;
742
743 string creatorIDstr = creatorID.ToString();
744
745 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
746 if (mm != null)
747 {
748 // make sure client still has enougth credit
749 if (!mm.UploadCovered(m_HostCapsObj.AgentID, (int)cost))
750 {
751 error = "Insufficient funds.";
752 return;
753 }
754 }
755
756 // strings to types
500 if (inventoryType == "sound") 757 if (inventoryType == "sound")
501 { 758 {
502 inType = (sbyte)InventoryType.Sound; 759 inType = (sbyte)InventoryType.Sound;
@@ -511,6 +768,12 @@ namespace OpenSim.Region.ClientStack.Linden
511 inType = (sbyte)InventoryType.Animation; 768 inType = (sbyte)InventoryType.Animation;
512 assType = (sbyte)AssetType.Animation; 769 assType = (sbyte)AssetType.Animation;
513 } 770 }
771 else if (inventoryType == "animset")
772 {
773 inType = (sbyte)CustomInventoryType.AnimationSet;
774 assType = (sbyte)CustomAssetType.AnimationSet;
775 m_log.Debug("got animset upload request");
776 }
514 else if (inventoryType == "wearable") 777 else if (inventoryType == "wearable")
515 { 778 {
516 inType = (sbyte)InventoryType.Wearable; 779 inType = (sbyte)InventoryType.Wearable;
@@ -526,6 +789,7 @@ namespace OpenSim.Region.ClientStack.Linden
526 } 789 }
527 else if (inventoryType == "object") 790 else if (inventoryType == "object")
528 { 791 {
792<<<<<<< HEAD
529 inType = (sbyte)InventoryType.Object; 793 inType = (sbyte)InventoryType.Object;
530 assType = (sbyte)AssetType.Object; 794 assType = (sbyte)AssetType.Object;
531 795
@@ -612,73 +876,255 @@ namespace OpenSim.Region.ClientStack.Linden
612 { 876 {
613 clientInv.SendBulkUpdateInventory(foldersToUpdate.ToArray(), itemsToUpdate.ToArray()); 877 clientInv.SendBulkUpdateInventory(foldersToUpdate.ToArray(), itemsToUpdate.ToArray());
614 } 878 }
615 879=======
616 for (int i = 0; i < mesh_list.Count; i++) 880 if (assetType == "mesh") // this code for now is for mesh models uploads only
617 { 881 {
618 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); 882 inType = (sbyte)InventoryType.Object;
883 assType = (sbyte)AssetType.Object;
884>>>>>>> avn/ubitvar
619 885
620 Primitive.TextureEntry textureEntry 886 List<Vector3> positions = new List<Vector3>();
621 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE); 887 List<Quaternion> rotations = new List<Quaternion>();
622 OSDMap inner_instance_list = (OSDMap)instance_list[i]; 888 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
889
890 // compare and get updated information
891/* does nothing still we do need something to avoid special viewer to upload something diferent from the cost estimation
892 bool mismatchError = true;
893
894 while (mismatchError)
895 {
896 mismatchError = false;
897 }
623 898
624 OSDArray face_list = (OSDArray)inner_instance_list["face_list"]; 899 if (mismatchError)
625 for (uint face = 0; face < face_list.Count; face++)
626 { 900 {
627 OSDMap faceMap = (OSDMap)face_list[(int)face]; 901 error = "Upload and fee estimation information don't match";
628 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face); 902 lock (m_ModelCost)
629 if(faceMap.ContainsKey("fullbright")) 903 m_FileAgentInventoryState = FileAgentInventoryState.idle;
630 f.Fullbright = faceMap["fullbright"].AsBoolean();
631 if (faceMap.ContainsKey ("diffuse_color"))
632 f.RGBA = faceMap["diffuse_color"].AsColor4();
633 904
634 int textureNum = faceMap["image"].AsInteger(); 905 return;
635 float imagerot = faceMap["imagerot"].AsInteger(); 906 }
636 float offsets = (float)faceMap["offsets"].AsReal(); 907*/
637 float offsett = (float)faceMap["offsett"].AsReal(); 908 OSDArray instance_list = (OSDArray)request["instance_list"];
638 float scales = (float)faceMap["scales"].AsReal(); 909 OSDArray mesh_list = (OSDArray)request["mesh_list"];
639 float scalet = (float)faceMap["scalet"].AsReal(); 910 OSDArray texture_list = (OSDArray)request["texture_list"];
911 SceneObjectGroup grp = null;
640 912
641 if(imagerot != 0) 913 // create and store texture assets
642 f.Rotation = imagerot; 914 bool doTextInv = (!istest && m_enableModelUploadTextureToInventory &&
915 texturesFolder != UUID.Zero);
643 916
644 if(offsets != 0)
645 f.OffsetU = offsets;
646 917
647 if (offsett != 0) 918 List<UUID> textures = new List<UUID>();
648 f.OffsetV = offsett;
649 919
650 if (scales != 0) 920
651 f.RepeatU = scales; 921// if (doTextInv)
922 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
652 923
653 if (scalet != 0) 924 if(client == null) // don't put textures in inventory if there is no client
654 f.RepeatV = scalet; 925 doTextInv = false;
655 926
656 if (textures.Count > textureNum) 927 for (int i = 0; i < texture_list.Count; i++)
657 f.TextureID = textures[textureNum]; 928 {
658 else 929 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, creatorIDstr);
659 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE; 930 textureAsset.Data = texture_list[i].AsBinary();
931 if (istest)
932 textureAsset.Local = true;
933 m_assetService.Store(textureAsset);
934 textures.Add(textureAsset.FullID);
935
936 if (doTextInv)
937 {
938 string name = assetName;
939 if (name.Length > 25)
940 name = name.Substring(0, 24);
941 name += "_Texture#" + i.ToString();
942 InventoryItemBase texitem = new InventoryItemBase();
943 texitem.Owner = m_HostCapsObj.AgentID;
944 texitem.CreatorId = creatorIDstr;
945 texitem.CreatorData = String.Empty;
946 texitem.ID = UUID.Random();
947 texitem.AssetID = textureAsset.FullID;
948 texitem.Description = "mesh model texture";
949 texitem.Name = name;
950 texitem.AssetType = (int)AssetType.Texture;
951 texitem.InvType = (int)InventoryType.Texture;
952 texitem.Folder = texturesFolder;
953
954 texitem.CurrentPermissions
955 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Export);
956
957 texitem.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
958 texitem.EveryOnePermissions = 0;
959 texitem.NextPermissions = (uint)PermissionMask.All;
960 texitem.CreationDate = Util.UnixTimeSinceEpoch();
961
962 m_Scene.AddInventoryItem(client, texitem);
963 texitem = null;
964 }
965 }
966
967 // create and store meshs assets
968 List<UUID> meshAssets = new List<UUID>();
969 List<bool> meshAvatarSkeletons = new List<bool>();
970 List<bool> meshAvatarColliders = new List<bool>();
971
972 bool curAvSkeleton;
973 bool curAvCollider;
974 for (int i = 0; i < mesh_list.Count; i++)
975 {
976 curAvSkeleton = false;
977 curAvCollider = false;
660 978
661 textureEntry.FaceTextures[face] = f; 979 // we do need to parse the mesh now
980 OSD osd = OSDParser.DeserializeLLSDBinary(mesh_list[i]);
981 if (osd is OSDMap)
982 {
983 OSDMap mosd = (OSDMap)osd;
984 if (mosd.ContainsKey("skeleton"))
985 {
986 OSDMap skeleton = (OSDMap)mosd["skeleton"];
987 int sksize = skeleton["size"].AsInteger();
988 if (sksize > 0)
989 curAvSkeleton = true;
990 }
991 }
992
993 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, creatorIDstr);
994 meshAsset.Data = mesh_list[i].AsBinary();
995 if (istest)
996 meshAsset.Local = true;
997 m_assetService.Store(meshAsset);
998 meshAssets.Add(meshAsset.FullID);
999 meshAvatarSkeletons.Add(curAvSkeleton);
1000 meshAvatarColliders.Add(curAvCollider);
1001
1002 // test code
1003 if (curAvSkeleton && client != null)
1004 {
1005 string name = assetName;
1006 if (name.Length > 25)
1007 name = name.Substring(0, 24);
1008 name += "_Mesh#" + i.ToString();
1009 InventoryItemBase meshitem = new InventoryItemBase();
1010 meshitem.Owner = m_HostCapsObj.AgentID;
1011 meshitem.CreatorId = creatorIDstr;
1012 meshitem.CreatorData = String.Empty;
1013 meshitem.ID = UUID.Random();
1014 meshitem.AssetID = meshAsset.FullID;
1015 meshitem.Description = "mesh ";
1016 meshitem.Name = name;
1017 meshitem.AssetType = (int)AssetType.Mesh;
1018 meshitem.InvType = (int)InventoryType.Mesh;
1019 // meshitem.Folder = UUID.Zero; // send to default
1020
1021 meshitem.Folder = parentFolder; // dont let it go to folder Meshes that viewers dont show
1022
1023 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
1024 // (owner) permissions. This becomes a problem if next permissions are changed.
1025 meshitem.CurrentPermissions
1026 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
1027
1028 meshitem.BasePermissions = (uint)PermissionMask.All;
1029 meshitem.EveryOnePermissions = 0;
1030 meshitem.NextPermissions = (uint)PermissionMask.All;
1031 meshitem.CreationDate = Util.UnixTimeSinceEpoch();
1032
1033 m_Scene.AddInventoryItem(client, meshitem);
1034 meshitem = null;
1035 }
662 } 1036 }
663 1037
664 pbs.TextureEntry = textureEntry.GetBytes(); 1038 int skipedMeshs = 0;
1039 // build prims from instances
1040 for (int i = 0; i < instance_list.Count; i++)
1041 {
1042 OSDMap inner_instance_list = (OSDMap)instance_list[i];
665 1043
666 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, ""); 1044 // skip prims that are 2 small
667 meshAsset.Data = mesh_list[i].AsBinary(); 1045 Vector3 scale = inner_instance_list["scale"].AsVector3();
668 m_assetService.Store(meshAsset);
669 1046
670 pbs.SculptEntry = true; 1047 if (scale.X < m_PrimScaleMin || scale.Y < m_PrimScaleMin || scale.Z < m_PrimScaleMin)
671 pbs.SculptTexture = meshAsset.FullID; 1048 {
672 pbs.SculptType = (byte)SculptType.Mesh; 1049 skipedMeshs++;
673 pbs.SculptData = meshAsset.Data; 1050 continue;
1051 }
1052
1053 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
1054
1055 Primitive.TextureEntry textureEntry
1056 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
1057
1058
1059 OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
1060 for (uint face = 0; face < face_list.Count; face++)
1061 {
1062 OSDMap faceMap = (OSDMap)face_list[(int)face];
1063 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
1064 if (faceMap.ContainsKey("fullbright"))
1065 f.Fullbright = faceMap["fullbright"].AsBoolean();
1066 if (faceMap.ContainsKey("diffuse_color"))
1067 f.RGBA = faceMap["diffuse_color"].AsColor4();
1068
1069 int textureNum = faceMap["image"].AsInteger();
1070 float imagerot = faceMap["imagerot"].AsInteger();
1071 float offsets = (float)faceMap["offsets"].AsReal();
1072 float offsett = (float)faceMap["offsett"].AsReal();
1073 float scales = (float)faceMap["scales"].AsReal();
1074 float scalet = (float)faceMap["scalet"].AsReal();
1075
1076 if (imagerot != 0)
1077 f.Rotation = imagerot;
1078
1079 if (offsets != 0)
1080 f.OffsetU = offsets;
674 1081
675 Vector3 position = inner_instance_list["position"].AsVector3(); 1082 if (offsett != 0)
676 Vector3 scale = inner_instance_list["scale"].AsVector3(); 1083 f.OffsetV = offsett;
677 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); 1084
1085 if (scales != 0)
1086 f.RepeatU = scales;
1087
1088 if (scalet != 0)
1089 f.RepeatV = scalet;
1090
1091 if (textures.Count > textureNum)
1092 f.TextureID = textures[textureNum];
1093 else
1094 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
1095
1096 textureEntry.FaceTextures[face] = f;
1097 }
1098
1099 pbs.TextureEntry = textureEntry.GetBytes();
1100
1101 bool hasmesh = false;
1102 if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ...
1103 {
1104 int meshindx = inner_instance_list["mesh"].AsInteger();
1105 if (meshAssets.Count > meshindx)
1106 {
1107 pbs.SculptEntry = true;
1108 pbs.SculptType = (byte)SculptType.Mesh;
1109 pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction
1110 // data will be requested from asset on rez (i hope)
1111 hasmesh = true;
1112 }
1113 }
1114
1115 Vector3 position = inner_instance_list["position"].AsVector3();
1116 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
1117
1118 // for now viwers do send fixed defaults
1119 // but this may change
1120// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
1121 byte physicsShapeType = (byte)PhysShapeType.prim; // default for mesh is simple convex
1122 if(hasmesh)
1123 physicsShapeType = (byte) PhysShapeType.convex; // default for mesh is simple convex
1124// int material = inner_instance_list["material"].AsInteger();
1125 byte material = (byte)Material.Wood;
678 1126
679// no longer used - begin ------------------------ 1127// no longer used - begin ------------------------
680// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
681// int material = inner_instance_list["material"].AsInteger();
682// int mesh = inner_instance_list["mesh"].AsInteger(); 1128// int mesh = inner_instance_list["mesh"].AsInteger();
683 1129
684// OSDMap permissions = (OSDMap)inner_instance_list["permissions"]; 1130// OSDMap permissions = (OSDMap)inner_instance_list["permissions"];
@@ -693,24 +1139,49 @@ namespace OpenSim.Region.ClientStack.Linden
693// UUID owner_id = permissions["owner_id"].AsUUID(); 1139// UUID owner_id = permissions["owner_id"].AsUUID();
694// int owner_mask = permissions["owner_mask"].AsInteger(); 1140// int owner_mask = permissions["owner_mask"].AsInteger();
695// no longer used - end ------------------------ 1141// no longer used - end ------------------------
1142
1143
1144 SceneObjectPart prim
1145 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
1146
1147 prim.Scale = scale;
1148 rotations.Add(rotation);
1149 positions.Add(position);
1150 prim.UUID = UUID.Random();
1151 prim.CreatorID = creatorID;
1152 prim.OwnerID = owner_id;
1153 prim.GroupID = UUID.Zero;
1154 prim.LastOwnerID = creatorID;
1155 prim.CreationDate = Util.UnixTimeSinceEpoch();
1156
1157 if (grp == null)
1158 prim.Name = assetName;
1159 else
1160 prim.Name = assetName + "#" + i.ToString();
696 1161
697 UUID owner_id = m_HostCapsObj.AgentID; 1162 prim.EveryoneMask = 0;
1163 prim.GroupMask = 0;
1164
1165 if (restrictPerms)
1166 {
1167 prim.BaseMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
1168 prim.OwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
1169 prim.NextOwnerMask = 0;
1170 }
1171 else
1172 {
1173 prim.BaseMask = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1174 prim.OwnerMask = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1175 prim.NextOwnerMask = (uint)PermissionMask.Transfer;
1176 }
698 1177
699 SceneObjectPart prim 1178 if(istest)
700 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); 1179 prim.Description = "For testing only. Other uses are prohibited";
1180 else
1181 prim.Description = "";
701 1182
702 prim.Scale = scale; 1183 prim.Material = material;
703 //prim.OffsetPosition = position; 1184 prim.PhysicsShapeType = physicsShapeType;
704 rotations.Add(rotation);
705 positions.Add(position);
706 prim.UUID = UUID.Random();
707 prim.CreatorID = owner_id;
708 prim.OwnerID = owner_id;
709 prim.GroupID = UUID.Zero;
710 prim.LastOwnerID = prim.OwnerID;
711 prim.CreationDate = Util.UnixTimeSinceEpoch();
712 prim.Name = assetName;
713 prim.Description = "";
714 1185
715// prim.BaseMask = (uint)base_mask; 1186// prim.BaseMask = (uint)base_mask;
716// prim.EveryoneMask = (uint)everyone_mask; 1187// prim.EveryoneMask = (uint)everyone_mask;
@@ -718,52 +1189,64 @@ namespace OpenSim.Region.ClientStack.Linden
718// prim.NextOwnerMask = (uint)next_owner_mask; 1189// prim.NextOwnerMask = (uint)next_owner_mask;
719// prim.OwnerMask = (uint)owner_mask; 1190// prim.OwnerMask = (uint)owner_mask;
720 1191
721 if (grp == null) 1192 if (grp == null)
722 grp = new SceneObjectGroup(prim); 1193 {
723 else 1194 grp = new SceneObjectGroup(prim);
724 grp.AddPart(prim); 1195 grp.LastOwnerID = creatorID;
725 } 1196 }
1197 else
1198 grp.AddPart(prim);
1199 }
726 1200
727 Vector3 rootPos = positions[0]; 1201 Vector3 rootPos = positions[0];
728 1202
729 if (grp.Parts.Length > 1) 1203 if (grp.Parts.Length > 1)
730 { 1204 {
731 // Fix first link number 1205 // Fix first link number
732 grp.RootPart.LinkNum++; 1206 grp.RootPart.LinkNum++;
733 1207
734 Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]); 1208 Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]);
735 Quaternion tmprot; 1209 Quaternion tmprot;
736 Vector3 offset; 1210 Vector3 offset;
737 1211
738 // fix children rotations and positions 1212 // fix children rotations and positions
739 for (int i = 1; i < rotations.Count; i++) 1213 for (int i = 1; i < rotations.Count; i++)
740 { 1214 {
741 tmprot = rotations[i]; 1215 tmprot = rotations[i];
742 tmprot = rootRotConj * tmprot; 1216 tmprot = rootRotConj * tmprot;
1217
1218 grp.Parts[i].RotationOffset = tmprot;
743 1219
744 grp.Parts[i].RotationOffset = tmprot; 1220 offset = positions[i] - rootPos;
745 1221
746 offset = positions[i] - rootPos; 1222 offset *= rootRotConj;
1223 grp.Parts[i].OffsetPosition = offset;
1224 }
747 1225
748 offset *= rootRotConj; 1226 grp.AbsolutePosition = rootPos;
749 grp.Parts[i].OffsetPosition = offset; 1227 grp.UpdateGroupRotationR(rotations[0]);
1228 }
1229 else
1230 {
1231 grp.AbsolutePosition = rootPos;
1232 grp.UpdateGroupRotationR(rotations[0]);
750 } 1233 }
751 1234
752 grp.AbsolutePosition = rootPos; 1235 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
753 grp.UpdateGroupRotationR(rotations[0]);
754 } 1236 }
755 else 1237
1238 else // not a mesh model
756 { 1239 {
757 grp.AbsolutePosition = rootPos; 1240 m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload");
758 grp.UpdateGroupRotationR(rotations[0]); 1241 return;
759 } 1242 }
760
761 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
762 } 1243 }
763 1244
764 AssetBase asset; 1245 AssetBase asset;
765 asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString()); 1246 asset = new AssetBase(assetID, assetName, assType, creatorIDstr);
766 asset.Data = data; 1247 asset.Data = data;
1248 if (istest)
1249 asset.Local = true;
767 if (AddNewAsset != null) 1250 if (AddNewAsset != null)
768 AddNewAsset(asset); 1251 AddNewAsset(asset);
769 else if (m_assetService != null) 1252 else if (m_assetService != null)
@@ -771,11 +1254,17 @@ namespace OpenSim.Region.ClientStack.Linden
771 1254
772 InventoryItemBase item = new InventoryItemBase(); 1255 InventoryItemBase item = new InventoryItemBase();
773 item.Owner = m_HostCapsObj.AgentID; 1256 item.Owner = m_HostCapsObj.AgentID;
774 item.CreatorId = m_HostCapsObj.AgentID.ToString(); 1257 item.CreatorId = creatorIDstr;
775 item.CreatorData = String.Empty; 1258 item.CreatorData = String.Empty;
776 item.ID = inventoryItem; 1259 item.ID = inventoryItem;
777 item.AssetID = asset.FullID; 1260 item.AssetID = asset.FullID;
778 item.Description = assetDescription; 1261 if (istest)
1262 {
1263 item.Description = "For testing only. Other uses are prohibited";
1264 item.Flags = (uint) (InventoryItemFlags.SharedSingleReference);
1265 }
1266 else
1267 item.Description = assetDescription;
779 item.Name = assetName; 1268 item.Name = assetName;
780 item.AssetType = assType; 1269 item.AssetType = assType;
781 item.InvType = inType; 1270 item.InvType = inType;
@@ -783,18 +1272,61 @@ namespace OpenSim.Region.ClientStack.Linden
783 1272
784 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current 1273 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
785 // (owner) permissions. This becomes a problem if next permissions are changed. 1274 // (owner) permissions. This becomes a problem if next permissions are changed.
786 item.CurrentPermissions
787 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Export);
788 1275
789 item.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export; 1276 if (inType == (sbyte)CustomInventoryType.AnimationSet)
790 item.EveryOnePermissions = 0; 1277 {
791 item.NextPermissions = (uint)PermissionMask.All; 1278 AnimationSet.setCreateItemPermitions(item);
1279 }
1280
1281 else if (restrictPerms)
1282 {
1283 item.BasePermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
1284 item.CurrentPermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
1285 item.EveryOnePermissions = 0;
1286 item.NextPermissions = 0;
1287 }
1288 else
1289 {
1290 item.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1291 item.CurrentPermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1292 item.EveryOnePermissions = 0;
1293 item.NextPermissions = (uint)PermissionMask.Transfer;
1294 }
1295
792 item.CreationDate = Util.UnixTimeSinceEpoch(); 1296 item.CreationDate = Util.UnixTimeSinceEpoch();
793 1297
1298 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
1299
794 if (AddNewInventoryItem != null) 1300 if (AddNewInventoryItem != null)
795 { 1301 {
796 AddNewInventoryItem(m_HostCapsObj.AgentID, item); 1302 if (istest)
1303 {
1304 m_Scene.AddInventoryItem(client, item);
1305/*
1306 AddNewInventoryItem(m_HostCapsObj.AgentID, item, 0);
1307 if (client != null)
1308 client.SendAgentAlertMessage("Upload will have no cost, for personal test purposes only. Other uses are forbiden. Items may not work on a another region" , true);
1309 */
1310 }
1311 else
1312 {
1313 AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
1314// if (client != null)
1315// {
1316// // let users see anything.. i don't so far
1317// string str;
1318// if (cost > 0)
1319// // dont remember where is money unit name to put here
1320// str = "Upload complete. charged " + cost.ToString() + "$";
1321// else
1322// str = "Upload complete";
1323// client.SendAgentAlertMessage(str, true);
1324// }
1325 }
797 } 1326 }
1327
1328 lock (m_ModelCost)
1329 m_FileAgentInventoryState = FileAgentInventoryState.idle;
798 } 1330 }
799 1331
800 /// <summary> 1332 /// <summary>
@@ -995,6 +1527,131 @@ namespace OpenSim.Region.ClientStack.Linden
995 return response; 1527 return response;
996 } 1528 }
997 1529
1530 public string GetObjectCost(string request, string path,
1531 string param, IOSHttpRequest httpRequest,
1532 IOSHttpResponse httpResponse)
1533 {
1534 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1535 OSDMap resp = new OSDMap();
1536
1537 OSDArray object_ids = (OSDArray)req["object_ids"];
1538
1539 for (int i = 0; i < object_ids.Count; i++)
1540 {
1541 UUID uuid = object_ids[i].AsUUID();
1542
1543 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1544
1545 if (part != null)
1546 {
1547 SceneObjectGroup grp = part.ParentGroup;
1548 if (grp != null)
1549 {
1550 float linksetCost;
1551 float linksetPhysCost;
1552 float partCost;
1553 float partPhysCost;
1554
1555 grp.GetResourcesCosts(part, out linksetCost, out linksetPhysCost, out partCost, out partPhysCost);
1556
1557 OSDMap object_data = new OSDMap();
1558 object_data["linked_set_resource_cost"] = linksetCost;
1559 object_data["resource_cost"] = partCost;
1560 object_data["physics_cost"] = partPhysCost;
1561 object_data["linked_set_physics_cost"] = linksetPhysCost;
1562
1563 resp[uuid.ToString()] = object_data;
1564 }
1565 else
1566 {
1567 OSDMap object_data = new OSDMap();
1568 object_data["linked_set_resource_cost"] = 0;
1569 object_data["resource_cost"] = 0;
1570 object_data["physics_cost"] = 0;
1571 object_data["linked_set_physics_cost"] = 0;
1572
1573 resp[uuid.ToString()] = object_data;
1574 }
1575
1576 }
1577 }
1578
1579 string response = OSDParser.SerializeLLSDXmlString(resp);
1580 return response;
1581 }
1582
1583 public string ResourceCostSelected(string request, string path,
1584 string param, IOSHttpRequest httpRequest,
1585 IOSHttpResponse httpResponse)
1586 {
1587 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1588 OSDMap resp = new OSDMap();
1589
1590
1591 float phys=0;
1592 float stream=0;
1593 float simul=0;
1594
1595 if (req.ContainsKey("selected_roots"))
1596 {
1597 OSDArray object_ids = (OSDArray)req["selected_roots"];
1598
1599 // should go by SOG suming costs for all parts
1600 // ll v3 works ok with several objects select we get the list and adds ok
1601 // FS calls per object so results are wrong guess fs bug
1602 for (int i = 0; i < object_ids.Count; i++)
1603 {
1604 UUID uuid = object_ids[i].AsUUID();
1605 float Physc;
1606 float simulc;
1607 float streamc;
1608
1609 SceneObjectGroup grp = m_Scene.GetGroupByPrim(uuid);
1610 if (grp != null)
1611 {
1612 grp.GetSelectedCosts(out Physc, out streamc, out simulc);
1613 phys += Physc;
1614 stream += streamc;
1615 simul += simulc;
1616 }
1617 }
1618 }
1619 else if (req.ContainsKey("selected_prims"))
1620 {
1621 OSDArray object_ids = (OSDArray)req["selected_prims"];
1622
1623 // don't see in use in any of the 2 viewers
1624 // guess it should be for edit linked but... nothing
1625 // should go to SOP per part
1626 for (int i = 0; i < object_ids.Count; i++)
1627 {
1628 UUID uuid = object_ids[i].AsUUID();
1629
1630 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1631 if (part != null)
1632 {
1633 phys += part.PhysicsCost;
1634 stream += part.StreamingCost;
1635 simul += part.SimulationCost;
1636 }
1637 }
1638 }
1639
1640 // if (simul != 0)
1641 {
1642 OSDMap object_data = new OSDMap();
1643
1644 object_data["physics"] = phys;
1645 object_data["streaming"] = stream;
1646 object_data["simulation"] = simul;
1647
1648 resp["selected"] = object_data;
1649 }
1650
1651 string response = OSDParser.SerializeLLSDXmlString(resp);
1652 return response;
1653 }
1654
998 public string UpdateAgentInformation(string request, string path, 1655 public string UpdateAgentInformation(string request, string path,
999 string param, IOSHttpRequest httpRequest, 1656 string param, IOSHttpRequest httpRequest,
1000 IOSHttpResponse httpResponse) 1657 IOSHttpResponse httpResponse)
@@ -1015,6 +1672,10 @@ namespace OpenSim.Region.ClientStack.Linden
1015 1672
1016 public class AssetUploader 1673 public class AssetUploader
1017 { 1674 {
1675 private static readonly ILog m_log =
1676 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
1677
1678
1018 public event UpLoadedAsset OnUpLoad; 1679 public event UpLoadedAsset OnUpLoad;
1019 private UpLoadedAsset handlerUpLoad = null; 1680 private UpLoadedAsset handlerUpLoad = null;
1020 1681
@@ -1029,10 +1690,21 @@ namespace OpenSim.Region.ClientStack.Linden
1029 1690
1030 private string m_invType = String.Empty; 1691 private string m_invType = String.Empty;
1031 private string m_assetType = String.Empty; 1692 private string m_assetType = String.Empty;
1032 1693 private int m_cost;
1694 private string m_error = String.Empty;
1695
1696 private Timer m_timeoutTimer = new Timer();
1697 private UUID m_texturesFolder;
1698 private int m_nreqtextures;
1699 private int m_nreqmeshs;
1700 private int m_nreqinstances;
1701 private bool m_IsAtestUpload;
1702
1033 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, 1703 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
1034 UUID parentFolderID, string invType, string assetType, string path, 1704 UUID parentFolderID, string invType, string assetType, string path,
1035 IHttpServer httpServer, bool dumpAssetsToFile) 1705 IHttpServer httpServer, bool dumpAssetsToFile,
1706 int totalCost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
1707 bool IsAtestUpload)
1036 { 1708 {
1037 m_assetName = assetName; 1709 m_assetName = assetName;
1038 m_assetDes = description; 1710 m_assetDes = description;
@@ -1044,6 +1716,18 @@ namespace OpenSim.Region.ClientStack.Linden
1044 m_assetType = assetType; 1716 m_assetType = assetType;
1045 m_invType = invType; 1717 m_invType = invType;
1046 m_dumpAssetsToFile = dumpAssetsToFile; 1718 m_dumpAssetsToFile = dumpAssetsToFile;
1719 m_cost = totalCost;
1720
1721 m_texturesFolder = texturesFolder;
1722 m_nreqtextures = nreqtextures;
1723 m_nreqmeshs = nreqmeshs;
1724 m_nreqinstances = nreqinstances;
1725 m_IsAtestUpload = IsAtestUpload;
1726
1727 m_timeoutTimer.Elapsed += TimedOut;
1728 m_timeoutTimer.Interval = 120000;
1729 m_timeoutTimer.AutoReset = false;
1730 m_timeoutTimer.Start();
1047 } 1731 }
1048 1732
1049 /// <summary> 1733 /// <summary>
@@ -1058,12 +1742,14 @@ namespace OpenSim.Region.ClientStack.Linden
1058 UUID inv = inventoryItemID; 1742 UUID inv = inventoryItemID;
1059 string res = String.Empty; 1743 string res = String.Empty;
1060 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); 1744 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
1745/*
1061 uploadComplete.new_asset = newAssetID.ToString(); 1746 uploadComplete.new_asset = newAssetID.ToString();
1062 uploadComplete.new_inventory_item = inv; 1747 uploadComplete.new_inventory_item = inv;
1063 uploadComplete.state = "complete"; 1748 uploadComplete.state = "complete";
1064 1749
1065 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); 1750 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
1066 1751*/
1752 m_timeoutTimer.Stop();
1067 httpListener.RemoveStreamHandler("POST", uploaderPath); 1753 httpListener.RemoveStreamHandler("POST", uploaderPath);
1068 1754
1069 // TODO: probably make this a better set of extensions here 1755 // TODO: probably make this a better set of extensions here
@@ -1080,12 +1766,50 @@ namespace OpenSim.Region.ClientStack.Linden
1080 handlerUpLoad = OnUpLoad; 1766 handlerUpLoad = OnUpLoad;
1081 if (handlerUpLoad != null) 1767 if (handlerUpLoad != null)
1082 { 1768 {
1083 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType); 1769 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType,
1770 m_cost, m_texturesFolder, m_nreqtextures, m_nreqmeshs, m_nreqinstances, m_IsAtestUpload,
1771 ref m_error);
1084 } 1772 }
1773 if (m_IsAtestUpload)
1774 {
1775 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1776 resperror.message = "Upload SUCESSEFULL for testing purposes only. Other uses are prohibited. Item will not work after 48 hours or on other regions";
1777 resperror.identifier = inv;
1778
1779 uploadComplete.error = resperror;
1780 uploadComplete.state = "Upload4Testing";
1781 }
1782 else
1783 {
1784 if (m_error == String.Empty)
1785 {
1786 uploadComplete.new_asset = newAssetID.ToString();
1787 uploadComplete.new_inventory_item = inv;
1788 // if (m_texturesFolder != UUID.Zero)
1789 // uploadComplete.new_texture_folder_id = m_texturesFolder;
1790 uploadComplete.state = "complete";
1791 }
1792 else
1793 {
1794 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1795 resperror.message = m_error;
1796 resperror.identifier = inv;
1085 1797
1798 uploadComplete.error = resperror;
1799 uploadComplete.state = "failed";
1800 }
1801 }
1802
1803 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
1086 return res; 1804 return res;
1087 } 1805 }
1088 1806
1807 private void TimedOut(object sender, ElapsedEventArgs args)
1808 {
1809 m_log.InfoFormat("[CAPS]: Removing URL and handler for timed out mesh upload");
1810 httpListener.RemoveStreamHandler("POST", uploaderPath);
1811 }
1812
1089 ///Left this in and commented in case there are unforseen issues 1813 ///Left this in and commented in case there are unforseen issues
1090 //private void SaveAssetToFile(string filename, byte[] data) 1814 //private void SaveAssetToFile(string filename, byte[] data)
1091 //{ 1815 //{
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
new file mode 100644
index 0000000..546bcd9
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
@@ -0,0 +1,703 @@
1// Proprietary code of Avination Virtual Limited
2// (c) 2012 Melanie Thielker, Leal Duarte
3//
4
5using System;
6using System.IO;
7using System.Collections;
8using System.Collections.Generic;
9using System.Text;
10
11using OpenMetaverse;
12using OpenMetaverse.StructuredData;
13
14using OpenSim.Framework;
15using OpenSim.Region.Framework;
16using OpenSim.Region.Framework.Scenes;
17using OpenSim.Framework.Capabilities;
18
19using ComponentAce.Compression.Libs.zlib;
20
21using OSDArray = OpenMetaverse.StructuredData.OSDArray;
22using OSDMap = OpenMetaverse.StructuredData.OSDMap;
23
24namespace OpenSim.Region.ClientStack.Linden
25{
26 public struct ModelPrimLimits
27 {
28
29 }
30
31 public class ModelCost
32 {
33
34 // upload fee defaults
35 // fees are normalized to 1.0
36 // this parameters scale them to basic cost ( so 1.0 translates to 10 )
37
38 public float ModelMeshCostFactor = 0.0f; // scale total cost relative to basic (excluding textures)
39 public float ModelTextureCostFactor = 1.0f; // scale textures fee to basic.
40 public float ModelMinCostFactor = 0.0f; // 0.5f; // minimum total model free excluding textures
41
42 // itens costs in normalized values
43 // ie will be multiplied by basicCost and factors above
44 public float primCreationCost = 0.002f; // extra cost for each prim creation overhead
45 // weigthed size to normalized cost
46 public float bytecost = 1e-5f;
47
48 // mesh upload fees based on compressed data sizes
49 // several data sections are counted more that once
50 // to promote user optimization
51 // following parameters control how many extra times they are added
52 // to global size.
53 // LOD meshs
54 const float medSizeWth = 1f; // 2x
55 const float lowSizeWth = 1.5f; // 2.5x
56 const float lowestSizeWth = 2f; // 3x
57 // favor potencially physical optimized meshs versus automatic decomposition
58 const float physMeshSizeWth = 6f; // counts 7x
59 const float physHullSizeWth = 8f; // counts 9x
60
61 // stream cost area factors
62 // more or less like SL
63 const float highLodFactor = 17.36f;
64 const float midLodFactor = 277.78f;
65 const float lowLodFactor = 1111.11f;
66
67 // physics cost is below, identical to SL, assuming shape type convex
68 // server cost is below identical to SL assuming non scripted non physical object
69
70 // internal
71 const int bytesPerCoord = 6; // 3 coords, 2 bytes per each
72
73 // control prims dimensions
74 public float PrimScaleMin = 0.001f;
75 public float NonPhysicalPrimScaleMax = 256f;
76 public float PhysicalPrimScaleMax = 10f;
77 public int ObjectLinkedPartsMax = 512;
78
79 // storage for a single mesh asset cost parameters
80 private class ameshCostParam
81 {
82 // LOD sizes for size dependent streaming cost
83 public int highLODSize;
84 public int medLODSize;
85 public int lowLODSize;
86 public int lowestLODSize;
87 // normalized fee based on compressed data sizes
88 public float costFee;
89 // physics cost
90 public float physicsCost;
91 }
92
93 // calculates a mesh model costs
94 // returns false on error, with a reason on parameter error
95 // resources input LLSD request
96 // basicCost input region assets upload cost
97 // totalcost returns model total upload fee
98 // meshcostdata returns detailed costs for viewer
99 // avatarSkeleton if mesh includes a avatar skeleton
100 // useAvatarCollider if we should use physics mesh for avatar
101 public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost,
102 LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning)
103 {
104 totalcost = 0;
105 error = string.Empty;
106
107 bool avatarSkeleton = false;
108
109 if (resources == null ||
110 resources.instance_list == null ||
111 resources.instance_list.Array.Count == 0)
112 {
113 error = "missing model information.";
114 return false;
115 }
116
117 int numberInstances = resources.instance_list.Array.Count;
118
119 if( numberInstances > ObjectLinkedPartsMax )
120 {
121 error = "Model whould have more than " + ObjectLinkedPartsMax.ToString() + " linked prims";
122 return false;
123 }
124
125 meshcostdata.model_streaming_cost = 0.0;
126 meshcostdata.simulation_cost = 0.0;
127 meshcostdata.physics_cost = 0.0;
128 meshcostdata.resource_cost = 0.0;
129
130 meshcostdata.upload_price_breakdown.mesh_instance = 0;
131 meshcostdata.upload_price_breakdown.mesh_physics = 0;
132 meshcostdata.upload_price_breakdown.mesh_streaming = 0;
133 meshcostdata.upload_price_breakdown.model = 0;
134
135 int itmp;
136
137 // textures cost
138 if (resources.texture_list != null && resources.texture_list.Array.Count > 0)
139 {
140 float textures_cost = (float)(resources.texture_list.Array.Count * basicCost);
141 textures_cost *= ModelTextureCostFactor;
142
143 itmp = (int)(textures_cost + 0.5f); // round
144 meshcostdata.upload_price_breakdown.texture = itmp;
145 totalcost += itmp;
146 }
147
148 // meshs assets cost
149 float meshsfee = 0;
150 int numberMeshs = 0;
151 bool haveMeshs = false;
152
153 bool curskeleton;
154 bool curAvatarPhys;
155
156 List<ameshCostParam> meshsCosts = new List<ameshCostParam>();
157
158 if (resources.mesh_list != null && resources.mesh_list.Array.Count > 0)
159 {
160 numberMeshs = resources.mesh_list.Array.Count;
161
162 for (int i = 0; i < numberMeshs; i++)
163 {
164 ameshCostParam curCost = new ameshCostParam();
165 byte[] data = (byte[])resources.mesh_list.Array[i];
166
167 if (!MeshCost(data, curCost,out curskeleton, out curAvatarPhys, out error))
168 {
169 return false;
170 }
171
172 if (curskeleton)
173 {
174 if (avatarSkeleton)
175 {
176 error = "model can only contain a avatar skeleton";
177 return false;
178 }
179 avatarSkeleton = true;
180 }
181 meshsCosts.Add(curCost);
182 meshsfee += curCost.costFee;
183 }
184 haveMeshs = true;
185 }
186
187 // instances (prims) cost
188
189
190 int mesh;
191 int skipedSmall = 0;
192 for (int i = 0; i < numberInstances; i++)
193 {
194 Hashtable inst = (Hashtable)resources.instance_list.Array[i];
195
196 ArrayList ascale = (ArrayList)inst["scale"];
197 Vector3 scale;
198 double tmp;
199 tmp = (double)ascale[0];
200 scale.X = (float)tmp;
201 tmp = (double)ascale[1];
202 scale.Y = (float)tmp;
203 tmp = (double)ascale[2];
204 scale.Z = (float)tmp;
205
206 if (scale.X < PrimScaleMin || scale.Y < PrimScaleMin || scale.Z < PrimScaleMin)
207 {
208 skipedSmall++;
209 continue;
210 }
211
212 if (scale.X > NonPhysicalPrimScaleMax || scale.Y > NonPhysicalPrimScaleMax || scale.Z > NonPhysicalPrimScaleMax)
213 {
214 error = "Model contains parts with sides larger than " + NonPhysicalPrimScaleMax.ToString() + "m. Please ajust scale";
215 return false;
216 }
217
218 if (haveMeshs && inst.ContainsKey("mesh"))
219 {
220 mesh = (int)inst["mesh"];
221
222 if (mesh >= numberMeshs)
223 {
224 error = "Incoerent model information.";
225 return false;
226 }
227
228 // streamming cost
229
230 float sqdiam = scale.LengthSquared();
231
232 ameshCostParam curCost = meshsCosts[mesh];
233 float mesh_streaming = streamingCost(curCost, sqdiam);
234
235 meshcostdata.model_streaming_cost += mesh_streaming;
236 meshcostdata.physics_cost += curCost.physicsCost;
237 }
238 else // instance as no mesh ??
239 {
240 // to do later if needed
241 meshcostdata.model_streaming_cost += 0.5f;
242 meshcostdata.physics_cost += 1.0f;
243 }
244
245 // assume unscripted and static prim server cost
246 meshcostdata.simulation_cost += 0.5f;
247 // charge for prims creation
248 meshsfee += primCreationCost;
249 }
250
251 if (skipedSmall > 0)
252 {
253 if (skipedSmall > numberInstances / 2)
254 {
255 error = "Model contains too many prims smaller than " + PrimScaleMin.ToString() +
256 "m minimum allowed size. Please check scalling";
257 return false;
258 }
259 else
260 warning += skipedSmall.ToString() + " of the requested " +numberInstances.ToString() +
261 " model prims will not upload because they are smaller than " + PrimScaleMin.ToString() +
262 "m minimum allowed size. Please check scalling ";
263 }
264
265 if (meshcostdata.physics_cost <= meshcostdata.model_streaming_cost)
266 meshcostdata.resource_cost = meshcostdata.model_streaming_cost;
267 else
268 meshcostdata.resource_cost = meshcostdata.physics_cost;
269
270 if (meshcostdata.resource_cost < meshcostdata.simulation_cost)
271 meshcostdata.resource_cost = meshcostdata.simulation_cost;
272
273 // scale cost
274 // at this point a cost of 1.0 whould mean basic cost
275 meshsfee *= ModelMeshCostFactor;
276
277 if (meshsfee < ModelMinCostFactor)
278 meshsfee = ModelMinCostFactor;
279
280 // actually scale it to basic cost
281 meshsfee *= (float)basicCost;
282
283 meshsfee += 0.5f; // rounding
284
285 totalcost += (int)meshsfee;
286
287 // breakdown prices
288 // don't seem to be in use so removed code for now
289
290 return true;
291 }
292
293 // single mesh asset cost
294 private bool MeshCost(byte[] data, ameshCostParam cost,out bool skeleton, out bool avatarPhys, out string error)
295 {
296 cost.highLODSize = 0;
297 cost.medLODSize = 0;
298 cost.lowLODSize = 0;
299 cost.lowestLODSize = 0;
300 cost.physicsCost = 0.0f;
301 cost.costFee = 0.0f;
302
303 error = string.Empty;
304
305 skeleton = false;
306 avatarPhys = false;
307
308 if (data == null || data.Length == 0)
309 {
310 error = "Missing model information.";
311 return false;
312 }
313
314 OSD meshOsd = null;
315 int start = 0;
316
317 error = "Invalid model data";
318
319 using (MemoryStream ms = new MemoryStream(data))
320 {
321 try
322 {
323 OSD osd = OSDParser.DeserializeLLSDBinary(ms);
324 if (osd is OSDMap)
325 meshOsd = (OSDMap)osd;
326 else
327 return false;
328 }
329 catch (Exception e)
330 {
331 return false;
332 }
333 start = (int)ms.Position;
334 }
335
336 OSDMap map = (OSDMap)meshOsd;
337 OSDMap tmpmap;
338
339 int highlod_size = 0;
340 int medlod_size = 0;
341 int lowlod_size = 0;
342 int lowestlod_size = 0;
343 int skin_size = 0;
344
345 int hulls_size = 0;
346 int phys_nhulls;
347 int phys_hullsvertices = 0;
348
349 int physmesh_size = 0;
350 int phys_ntriangles = 0;
351
352 int submesh_offset = -1;
353
354 if (map.ContainsKey("skeleton"))
355 {
356 tmpmap = (OSDMap)map["skeleton"];
357 if (tmpmap.ContainsKey("offset") && tmpmap.ContainsKey("size"))
358 {
359 int sksize = tmpmap["size"].AsInteger();
360 if(sksize > 0)
361 skeleton = true;
362 }
363 }
364
365 if (map.ContainsKey("physics_convex"))
366 {
367 tmpmap = (OSDMap)map["physics_convex"];
368 if (tmpmap.ContainsKey("offset"))
369 submesh_offset = tmpmap["offset"].AsInteger() + start;
370 if (tmpmap.ContainsKey("size"))
371 hulls_size = tmpmap["size"].AsInteger();
372 }
373
374 if (submesh_offset < 0 || hulls_size == 0)
375 {
376 error = "Missing physics_convex block";
377 return false;
378 }
379
380 if (!hulls(data, submesh_offset, hulls_size, out phys_hullsvertices, out phys_nhulls))
381 {
382 error = "Bad physics_convex block";
383 return false;
384 }
385
386 submesh_offset = -1;
387
388 // only look for LOD meshs sizes
389
390 if (map.ContainsKey("high_lod"))
391 {
392 tmpmap = (OSDMap)map["high_lod"];
393 // see at least if there is a offset for this one
394 if (tmpmap.ContainsKey("offset"))
395 submesh_offset = tmpmap["offset"].AsInteger() + start;
396 if (tmpmap.ContainsKey("size"))
397 highlod_size = tmpmap["size"].AsInteger();
398 }
399
400 if (submesh_offset < 0 || highlod_size <= 0)
401 {
402 error = "Missing high_lod block";
403 return false;
404 }
405
406 bool haveprev = true;
407
408 if (map.ContainsKey("medium_lod"))
409 {
410 tmpmap = (OSDMap)map["medium_lod"];
411 if (tmpmap.ContainsKey("size"))
412 medlod_size = tmpmap["size"].AsInteger();
413 else
414 haveprev = false;
415 }
416
417 if (haveprev && map.ContainsKey("low_lod"))
418 {
419 tmpmap = (OSDMap)map["low_lod"];
420 if (tmpmap.ContainsKey("size"))
421 lowlod_size = tmpmap["size"].AsInteger();
422 else
423 haveprev = false;
424 }
425
426 if (haveprev && map.ContainsKey("lowest_lod"))
427 {
428 tmpmap = (OSDMap)map["lowest_lod"];
429 if (tmpmap.ContainsKey("size"))
430 lowestlod_size = tmpmap["size"].AsInteger();
431 }
432
433 if (map.ContainsKey("skin"))
434 {
435 tmpmap = (OSDMap)map["skin"];
436 if (tmpmap.ContainsKey("size"))
437 skin_size = tmpmap["size"].AsInteger();
438 }
439
440 cost.highLODSize = highlod_size;
441 cost.medLODSize = medlod_size;
442 cost.lowLODSize = lowlod_size;
443 cost.lowestLODSize = lowestlod_size;
444
445 submesh_offset = -1;
446
447 tmpmap = null;
448 if(map.ContainsKey("physics_mesh"))
449 tmpmap = (OSDMap)map["physics_mesh"];
450 else if (map.ContainsKey("physics_shape")) // old naming
451 tmpmap = (OSDMap)map["physics_shape"];
452
453 if(tmpmap != null)
454 {
455 if (tmpmap.ContainsKey("offset"))
456 submesh_offset = tmpmap["offset"].AsInteger() + start;
457 if (tmpmap.ContainsKey("size"))
458 physmesh_size = tmpmap["size"].AsInteger();
459
460 if (submesh_offset >= 0 || physmesh_size > 0)
461 {
462
463 if (!submesh(data, submesh_offset, physmesh_size, out phys_ntriangles))
464 {
465 error = "Model data parsing error";
466 return false;
467 }
468 }
469 }
470
471 // upload is done in convex shape type so only one hull
472 phys_hullsvertices++;
473 cost.physicsCost = 0.04f * phys_hullsvertices;
474
475 float sfee;
476
477 sfee = data.Length; // start with total compressed data size
478
479 // penalize lod meshs that should be more builder optimized
480 sfee += medSizeWth * medlod_size;
481 sfee += lowSizeWth * lowlod_size;
482 sfee += lowestSizeWth * lowlod_size;
483
484 // physics
485 // favor potencial optimized meshs versus automatic decomposition
486 if (physmesh_size != 0)
487 sfee += physMeshSizeWth * (physmesh_size + hulls_size / 4); // reduce cost of mandatory convex hull
488 else
489 sfee += physHullSizeWth * hulls_size;
490
491 // bytes to money
492 sfee *= bytecost;
493
494 cost.costFee = sfee;
495 return true;
496 }
497
498 // parses a LOD or physics mesh component
499 private bool submesh(byte[] data, int offset, int size, out int ntriangles)
500 {
501 ntriangles = 0;
502
503 OSD decodedMeshOsd = new OSD();
504 byte[] meshBytes = new byte[size];
505 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
506 try
507 {
508 using (MemoryStream inMs = new MemoryStream(meshBytes))
509 {
510 using (MemoryStream outMs = new MemoryStream())
511 {
512 using (ZOutputStream zOut = new ZOutputStream(outMs))
513 {
514 byte[] readBuffer = new byte[4096];
515 int readLen = 0;
516 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
517 {
518 zOut.Write(readBuffer, 0, readLen);
519 }
520 zOut.Flush();
521 outMs.Seek(0, SeekOrigin.Begin);
522
523 byte[] decompressedBuf = outMs.GetBuffer();
524 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
525 }
526 }
527 }
528 }
529 catch (Exception e)
530 {
531 return false;
532 }
533
534 OSDArray decodedMeshOsdArray = null;
535 if ((!decodedMeshOsd is OSDArray))
536 return false;
537
538 byte[] dummy;
539
540 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
541 foreach (OSD subMeshOsd in decodedMeshOsdArray)
542 {
543 if (subMeshOsd is OSDMap)
544 {
545 OSDMap subtmpmap = (OSDMap)subMeshOsd;
546 if (subtmpmap.ContainsKey("NoGeometry") && ((OSDBoolean)subtmpmap["NoGeometry"]))
547 continue;
548
549 if (!subtmpmap.ContainsKey("Position"))
550 return false;
551
552 if (subtmpmap.ContainsKey("TriangleList"))
553 {
554 dummy = subtmpmap["TriangleList"].AsBinary();
555 ntriangles += dummy.Length / bytesPerCoord;
556 }
557 else
558 return false;
559 }
560 }
561
562 return true;
563 }
564
565 // parses convex hulls component
566 private bool hulls(byte[] data, int offset, int size, out int nvertices, out int nhulls)
567 {
568 nvertices = 0;
569 nhulls = 1;
570
571 OSD decodedMeshOsd = new OSD();
572 byte[] meshBytes = new byte[size];
573 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
574 try
575 {
576 using (MemoryStream inMs = new MemoryStream(meshBytes))
577 {
578 using (MemoryStream outMs = new MemoryStream())
579 {
580 using (ZOutputStream zOut = new ZOutputStream(outMs))
581 {
582 byte[] readBuffer = new byte[4096];
583 int readLen = 0;
584 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
585 {
586 zOut.Write(readBuffer, 0, readLen);
587 }
588 zOut.Flush();
589 outMs.Seek(0, SeekOrigin.Begin);
590
591 byte[] decompressedBuf = outMs.GetBuffer();
592 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
593 }
594 }
595 }
596 }
597 catch (Exception e)
598 {
599 return false;
600 }
601
602 OSDMap cmap = (OSDMap)decodedMeshOsd;
603 if (cmap == null)
604 return false;
605
606 byte[] dummy;
607
608 // must have one of this
609 if (cmap.ContainsKey("BoundingVerts"))
610 {
611 dummy = cmap["BoundingVerts"].AsBinary();
612 nvertices = dummy.Length / bytesPerCoord;
613 }
614 else
615 return false;
616
617/* upload is done with convex shape type
618 if (cmap.ContainsKey("HullList"))
619 {
620 dummy = cmap["HullList"].AsBinary();
621 nhulls += dummy.Length;
622 }
623
624
625 if (cmap.ContainsKey("Positions"))
626 {
627 dummy = cmap["Positions"].AsBinary();
628 nvertices = dummy.Length / bytesPerCoord;
629 }
630 */
631
632 return true;
633 }
634
635 // returns streaming cost from on mesh LODs sizes in curCost and square of prim size length
636 private float streamingCost(ameshCostParam curCost, float sqdiam)
637 {
638 // compute efective areas
639 float ma = 262144f;
640
641 float mh = sqdiam * highLodFactor;
642 if (mh > ma)
643 mh = ma;
644 float mm = sqdiam * midLodFactor;
645 if (mm > ma)
646 mm = ma;
647
648 float ml = sqdiam * lowLodFactor;
649 if (ml > ma)
650 ml = ma;
651
652 float mlst = ma;
653
654 mlst -= ml;
655 ml -= mm;
656 mm -= mh;
657
658 if (mlst < 1.0f)
659 mlst = 1.0f;
660 if (ml < 1.0f)
661 ml = 1.0f;
662 if (mm < 1.0f)
663 mm = 1.0f;
664 if (mh < 1.0f)
665 mh = 1.0f;
666
667 ma = mlst + ml + mm + mh;
668
669 // get LODs compressed sizes
670 // giving 384 bytes bonus
671 int lst = curCost.lowestLODSize - 384;
672 int l = curCost.lowLODSize - 384;
673 int m = curCost.medLODSize - 384;
674 int h = curCost.highLODSize - 384;
675
676 // use previus higher LOD size on missing ones
677 if (m <= 0)
678 m = h;
679 if (l <= 0)
680 l = m;
681 if (lst <= 0)
682 lst = l;
683
684 // force minumum sizes
685 if (lst < 16)
686 lst = 16;
687 if (l < 16)
688 l = 16;
689 if (m < 16)
690 m = 16;
691 if (h < 16)
692 h = 16;
693
694 // compute cost weighted by relative effective areas
695 float cost = (float)lst * mlst + (float)l * ml + (float)m * mm + (float)h * mh;
696 cost /= ma;
697
698 cost *= 0.004f; // overall tunning parameter
699
700 return cost;
701 }
702 }
703}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index 9b9f6a7..5fb028c 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -78,7 +78,6 @@ namespace OpenSim.Region.ClientStack.Linden
78 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>(); 78 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
79 79
80 private Dictionary<UUID, Queue<OSD>> queues = new Dictionary<UUID, Queue<OSD>>(); 80 private Dictionary<UUID, Queue<OSD>> queues = new Dictionary<UUID, Queue<OSD>>();
81 private Dictionary<UUID, UUID> m_QueueUUIDAvatarMapping = new Dictionary<UUID, UUID>();
82 private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>(); 81 private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>();
83 82
84 #region INonSharedRegionModule methods 83 #region INonSharedRegionModule methods
@@ -178,6 +177,7 @@ namespace OpenSim.Region.ClientStack.Linden
178 } 177 }
179 178
180 /// <summary> 179 /// <summary>
180<<<<<<< HEAD
181 /// Always returns a valid queue 181 /// Always returns a valid queue
182 /// </summary> 182 /// </summary>
183 /// <param name="agentId"></param> 183 /// <param name="agentId"></param>
@@ -201,6 +201,8 @@ namespace OpenSim.Region.ClientStack.Linden
201 } 201 }
202 202
203 /// <summary> 203 /// <summary>
204=======
205>>>>>>> avn/ubitvar
204 /// May return a null queue 206 /// May return a null queue
205 /// </summary> 207 /// </summary>
206 /// <param name="agentId"></param> 208 /// <param name="agentId"></param>
@@ -263,28 +265,13 @@ namespace OpenSim.Region.ClientStack.Linden
263 lock (queues) 265 lock (queues)
264 queues.Remove(agentID); 266 queues.Remove(agentID);
265 267
266 List<UUID> removeitems = new List<UUID>();
267 lock (m_AvatarQueueUUIDMapping) 268 lock (m_AvatarQueueUUIDMapping)
268 m_AvatarQueueUUIDMapping.Remove(agentID); 269 m_AvatarQueueUUIDMapping.Remove(agentID);
269 270
270 UUID searchval = UUID.Zero; 271 lock (m_ids)
271
272 removeitems.Clear();
273
274 lock (m_QueueUUIDAvatarMapping)
275 { 272 {
276 foreach (UUID ky in m_QueueUUIDAvatarMapping.Keys) 273 if (!m_ids.ContainsKey(agentID))
277 { 274 m_ids.Remove(agentID);
278 searchval = m_QueueUUIDAvatarMapping[ky];
279
280 if (searchval == agentID)
281 {
282 removeitems.Add(ky);
283 }
284 }
285
286 foreach (UUID ky in removeitems)
287 m_QueueUUIDAvatarMapping.Remove(ky);
288 } 275 }
289 276
290 // m_log.DebugFormat("[EVENTQUEUE]: Deleted queues for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); 277 // m_log.DebugFormat("[EVENTQUEUE]: Deleted queues for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
@@ -303,61 +290,107 @@ namespace OpenSim.Region.ClientStack.Linden
303 public void OnRegisterCaps(UUID agentID, Caps caps) 290 public void OnRegisterCaps(UUID agentID, Caps caps)
304 { 291 {
305 // Register an event queue for the client 292 // Register an event queue for the client
293<<<<<<< HEAD
306 294
307 if (DebugLevel > 0) 295 if (DebugLevel > 0)
308 m_log.DebugFormat( 296 m_log.DebugFormat(
309 "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}", 297 "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
310 agentID, caps, m_scene.RegionInfo.RegionName); 298 agentID, caps, m_scene.RegionInfo.RegionName);
311 299=======
312 // Let's instantiate a Queue for this agent right now 300 m_log.DebugFormat(
313 TryGetQueue(agentID); 301 "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
302 agentID, caps, m_scene.RegionInfo.RegionName);
303>>>>>>> avn/ubitvar
314 304
315 UUID eventQueueGetUUID; 305 UUID eventQueueGetUUID;
306 Queue<OSD> queue;
307 Random rnd = new Random(Environment.TickCount);
308 int nrnd = rnd.Next(30000000);
309 if (nrnd < 0)
310 nrnd = -nrnd;
316 311
317 lock (m_AvatarQueueUUIDMapping) 312 lock (queues)
318 { 313 {
319 // Reuse open queues. The client does! 314 if (queues.ContainsKey(agentID))
320 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID)) 315 queue = queues[agentID];
316 else
317 queue = null;
318
319 if (queue == null)
321 { 320 {
322 //m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!"); 321 queue = new Queue<OSD>();
323 eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID]; 322 queues[agentID] = queue;
323
324 // push markers to handle old responses still waiting
325 // this will cost at most viewer getting two forced noevents
326 // even being a new queue better be safe
327 queue.Enqueue(null);
328 queue.Enqueue(null); // one should be enough
329
330 lock (m_AvatarQueueUUIDMapping)
331 {
332 eventQueueGetUUID = UUID.Random();
333 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
334 {
335 // oops this should not happen ?
336 m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID without a queue");
337 eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
338 }
339 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
340 }
341 lock (m_ids)
342 {
343 if (!m_ids.ContainsKey(agentID))
344 m_ids.Add(agentID, nrnd);
345 else
346 m_ids[agentID] = nrnd;
347 }
324 } 348 }
325 else 349 else
326 { 350 {
327 eventQueueGetUUID = UUID.Random(); 351 // push markers to handle old responses still waiting
328 //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!"); 352 // this will cost at most viewer getting two forced noevents
353 // even being a new queue better be safe
354 queue.Enqueue(null);
355 queue.Enqueue(null); // one should be enough
356
357 // reuse or not to reuse TODO FIX
358 lock (m_AvatarQueueUUIDMapping)
359 {
360 // Reuse open queues. The client does!
361 // Its reuse caps path not queues those are been reused already
362 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
363 {
364 m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
365 eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
366 }
367 else
368 {
369 eventQueueGetUUID = UUID.Random();
370 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
371 m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
372 }
373 }
374 lock (m_ids)
375 {
376 // change to negative numbers so they are changed at end of sending first marker
377 // old data on a queue may be sent on a response for a new caps
378 // but at least will be sent with coerent IDs
379 if (!m_ids.ContainsKey(agentID))
380 m_ids.Add(agentID, -nrnd); // should not happen
381 else
382 m_ids[agentID] = -m_ids[agentID];
383 }
329 } 384 }
330 } 385 }
331 386
332 lock (m_QueueUUIDAvatarMapping)
333 {
334 if (!m_QueueUUIDAvatarMapping.ContainsKey(eventQueueGetUUID))
335 m_QueueUUIDAvatarMapping.Add(eventQueueGetUUID, agentID);
336 }
337
338 lock (m_AvatarQueueUUIDMapping)
339 {
340 if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID))
341 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
342 }
343
344 caps.RegisterPollHandler( 387 caps.RegisterPollHandler(
345 "EventQueueGet", 388 "EventQueueGet",
346 new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS)); 389 new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS));
347
348 Random rnd = new Random(Environment.TickCount);
349 lock (m_ids)
350 {
351 if (!m_ids.ContainsKey(agentID))
352 m_ids.Add(agentID, rnd.Next(30000000));
353 }
354 } 390 }
355 391
356 public bool HasEvents(UUID requestID, UUID agentID) 392 public bool HasEvents(UUID requestID, UUID agentID)
357 { 393 {
358 // Don't use this, because of race conditions at agent closing time
359 //Queue<OSD> queue = TryGetQueue(agentID);
360
361 Queue<OSD> queue = GetQueue(agentID); 394 Queue<OSD> queue = GetQueue(agentID);
362 if (queue != null) 395 if (queue != null)
363 lock (queue) 396 lock (queue)
@@ -366,7 +399,8 @@ namespace OpenSim.Region.ClientStack.Linden
366 return queue.Count > 0; 399 return queue.Count > 0;
367 } 400 }
368 401
369 return false; 402 //m_log.WarnFormat("POLLED FOR EVENTS BY {0} unknown agent", agentID);
403 return true;
370 } 404 }
371 405
372 /// <summary> 406 /// <summary>
@@ -395,55 +429,65 @@ namespace OpenSim.Region.ClientStack.Linden
395 return NoEvents(requestID, pAgentId); 429 return NoEvents(requestID, pAgentId);
396 } 430 }
397 431
398 OSD element; 432 OSD element = null;;
433 OSDArray array = new OSDArray();
434 int thisID = 0;
435 bool negativeID = false;
436
399 lock (queue) 437 lock (queue)
400 { 438 {
401 if (queue.Count == 0) 439 if (queue.Count == 0)
402 return NoEvents(requestID, pAgentId); 440 return NoEvents(requestID, pAgentId);
403 element = queue.Dequeue(); // 15s timeout
404 }
405
406 int thisID = 0;
407 lock (m_ids)
408 thisID = m_ids[pAgentId];
409
410 OSDArray array = new OSDArray();
411 if (element == null) // didn't have an event in 15s
412 {
413 // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
414 array.Add(EventQueueHelper.KeepAliveEvent());
415 //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", pAgentId, m_scene.RegionInfo.RegionName);
416 }
417 else
418 {
419 if (DebugLevel > 0)
420 LogOutboundDebugMessage(element, pAgentId);
421 441
422 array.Add(element); 442 lock (m_ids)
443 thisID = m_ids[pAgentId];
423 444
424 lock (queue) 445 if (thisID < 0)
425 { 446 {
426 while (queue.Count > 0) 447 negativeID = true;
427 { 448 thisID = -thisID;
428 element = queue.Dequeue(); 449 }
450
451 while (queue.Count > 0)
452 {
453 element = queue.Dequeue();
454 // add elements until a marker is found
455 // so they get into a response
456 if (element == null)
457 break;
458 if (DebugLevel > 0)
459 LogOutboundDebugMessage(element, pAgentId);
460 array.Add(element);
461 thisID++;
462 }
463 }
429 464
430 if (DebugLevel > 0) 465 OSDMap events = null;
431 LogOutboundDebugMessage(element, pAgentId);
432 466
433 array.Add(element); 467 if (array.Count > 0)
434 thisID++; 468 {
435 } 469 events = new OSDMap();
436 } 470 events.Add("events", array);
471 events.Add("id", new OSDInteger(thisID));
437 } 472 }
438 473
439 OSDMap events = new OSDMap(); 474 if (negativeID && element == null)
440 events.Add("events", array); 475 {
476 Random rnd = new Random(Environment.TickCount);
477 thisID = rnd.Next(30000000);
478 if (thisID < 0)
479 thisID = -thisID;
480 }
441 481
442 events.Add("id", new OSDInteger(thisID));
443 lock (m_ids) 482 lock (m_ids)
444 { 483 {
445 m_ids[pAgentId] = thisID + 1; 484 m_ids[pAgentId] = thisID + 1;
446 } 485 }
486
487 // if there where no elements before a marker send a NoEvents
488 if (array.Count == 0)
489 return NoEvents(requestID, pAgentId);
490
447 Hashtable responsedata = new Hashtable(); 491 Hashtable responsedata = new Hashtable();
448 responsedata["int_response_code"] = 200; 492 responsedata["int_response_code"] = 200;
449 responsedata["content_type"] = "application/xml"; 493 responsedata["content_type"] = "application/xml";
@@ -461,260 +505,12 @@ namespace OpenSim.Region.ClientStack.Linden
461 responsedata["content_type"] = "text/plain"; 505 responsedata["content_type"] = "text/plain";
462 responsedata["keepalive"] = false; 506 responsedata["keepalive"] = false;
463 responsedata["reusecontext"] = false; 507 responsedata["reusecontext"] = false;
464 responsedata["str_response_string"] = "Upstream error: "; 508 responsedata["str_response_string"] = "<llsd></llsd>";
465 responsedata["error_status_text"] = "Upstream error:"; 509 responsedata["error_status_text"] = "<llsd></llsd>";
466 responsedata["http_protocol_version"] = "HTTP/1.0"; 510 responsedata["http_protocol_version"] = "HTTP/1.0";
467 return responsedata; 511 return responsedata;
468 } 512 }
469 513
470// public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps)
471// {
472// // TODO: this has to be redone to not busy-wait (and block the thread),
473// // TODO: as soon as we have a non-blocking way to handle HTTP-requests.
474//
475//// if (m_log.IsDebugEnabled)
476//// {
477//// String debug = "[EVENTQUEUE]: Got request for agent {0} in region {1} from thread {2}: [ ";
478//// foreach (object key in request.Keys)
479//// {
480//// debug += key.ToString() + "=" + request[key].ToString() + " ";
481//// }
482//// m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name);
483//// }
484//
485// Queue<OSD> queue = TryGetQueue(agentID);
486// OSD element;
487//
488// lock (queue)
489// element = queue.Dequeue(); // 15s timeout
490//
491// Hashtable responsedata = new Hashtable();
492//
493// int thisID = 0;
494// lock (m_ids)
495// thisID = m_ids[agentID];
496//
497// if (element == null)
498// {
499// //m_log.ErrorFormat("[EVENTQUEUE]: Nothing to process in " + m_scene.RegionInfo.RegionName);
500// if (thisID == -1) // close-request
501// {
502// m_log.ErrorFormat("[EVENTQUEUE]: 404 in " + m_scene.RegionInfo.RegionName);
503// responsedata["int_response_code"] = 404; //501; //410; //404;
504// responsedata["content_type"] = "text/plain";
505// responsedata["keepalive"] = false;
506// responsedata["str_response_string"] = "Closed EQG";
507// return responsedata;
508// }
509// responsedata["int_response_code"] = 502;
510// responsedata["content_type"] = "text/plain";
511// responsedata["keepalive"] = false;
512// responsedata["str_response_string"] = "Upstream error: ";
513// responsedata["error_status_text"] = "Upstream error:";
514// responsedata["http_protocol_version"] = "HTTP/1.0";
515// return responsedata;
516// }
517//
518// OSDArray array = new OSDArray();
519// if (element == null) // didn't have an event in 15s
520// {
521// // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
522// array.Add(EventQueueHelper.KeepAliveEvent());
523// //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
524// }
525// else
526// {
527// array.Add(element);
528//
529// if (element is OSDMap)
530// {
531// OSDMap ev = (OSDMap)element;
532// m_log.DebugFormat(
533// "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
534// ev["message"], m_scene.GetScenePresence(agentID).Name);
535// }
536//
537// lock (queue)
538// {
539// while (queue.Count > 0)
540// {
541// element = queue.Dequeue();
542//
543// if (element is OSDMap)
544// {
545// OSDMap ev = (OSDMap)element;
546// m_log.DebugFormat(
547// "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
548// ev["message"], m_scene.GetScenePresence(agentID).Name);
549// }
550//
551// array.Add(element);
552// thisID++;
553// }
554// }
555// }
556//
557// OSDMap events = new OSDMap();
558// events.Add("events", array);
559//
560// events.Add("id", new OSDInteger(thisID));
561// lock (m_ids)
562// {
563// m_ids[agentID] = thisID + 1;
564// }
565//
566// responsedata["int_response_code"] = 200;
567// responsedata["content_type"] = "application/xml";
568// responsedata["keepalive"] = false;
569// responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
570//
571// m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
572//
573// return responsedata;
574// }
575
576// public Hashtable EventQueuePath2(Hashtable request)
577// {
578// string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/","");
579// // pull off the last "/" in the path.
580// Hashtable responsedata = new Hashtable();
581// capuuid = capuuid.Substring(0, capuuid.Length - 1);
582// capuuid = capuuid.Replace("/CAPS/EQG/", "");
583// UUID AvatarID = UUID.Zero;
584// UUID capUUID = UUID.Zero;
585//
586// // parse the path and search for the avatar with it registered
587// if (UUID.TryParse(capuuid, out capUUID))
588// {
589// lock (m_QueueUUIDAvatarMapping)
590// {
591// if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
592// {
593// AvatarID = m_QueueUUIDAvatarMapping[capUUID];
594// }
595// }
596//
597// if (AvatarID != UUID.Zero)
598// {
599// return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsForUser(AvatarID));
600// }
601// else
602// {
603// responsedata["int_response_code"] = 404;
604// responsedata["content_type"] = "text/plain";
605// responsedata["keepalive"] = false;
606// responsedata["str_response_string"] = "Not Found";
607// responsedata["error_status_text"] = "Not Found";
608// responsedata["http_protocol_version"] = "HTTP/1.0";
609// return responsedata;
610// // return 404
611// }
612// }
613// else
614// {
615// responsedata["int_response_code"] = 404;
616// responsedata["content_type"] = "text/plain";
617// responsedata["keepalive"] = false;
618// responsedata["str_response_string"] = "Not Found";
619// responsedata["error_status_text"] = "Not Found";
620// responsedata["http_protocol_version"] = "HTTP/1.0";
621// return responsedata;
622// // return 404
623// }
624// }
625
626 public OSD EventQueueFallBack(string path, OSD request, string endpoint)
627 {
628 // This is a fallback element to keep the client from loosing EventQueueGet
629 // Why does CAPS fail sometimes!?
630 m_log.Warn("[EVENTQUEUE]: In the Fallback handler! We lost the Queue in the rest handler!");
631 string capuuid = path.Replace("/CAPS/EQG/","");
632 capuuid = capuuid.Substring(0, capuuid.Length - 1);
633
634// UUID AvatarID = UUID.Zero;
635 UUID capUUID = UUID.Zero;
636 if (UUID.TryParse(capuuid, out capUUID))
637 {
638/* Don't remove this yet code cleaners!
639 * Still testing this!
640 *
641 lock (m_QueueUUIDAvatarMapping)
642 {
643 if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
644 {
645 AvatarID = m_QueueUUIDAvatarMapping[capUUID];
646 }
647 }
648
649
650 if (AvatarID != UUID.Zero)
651 {
652 // Repair the CAP!
653 //OpenSim.Framework.Capabilities.Caps caps = m_scene.GetCapsHandlerForUser(AvatarID);
654 //string capsBase = "/CAPS/EQG/";
655 //caps.RegisterHandler("EventQueueGet",
656 //new RestHTTPHandler("POST", capsBase + capUUID.ToString() + "/",
657 //delegate(Hashtable m_dhttpMethod)
658 //{
659 // return ProcessQueue(m_dhttpMethod, AvatarID, caps);
660 //}));
661 // start new ID sequence.
662 Random rnd = new Random(System.Environment.TickCount);
663 lock (m_ids)
664 {
665 if (!m_ids.ContainsKey(AvatarID))
666 m_ids.Add(AvatarID, rnd.Next(30000000));
667 }
668
669
670 int thisID = 0;
671 lock (m_ids)
672 thisID = m_ids[AvatarID];
673
674 BlockingLLSDQueue queue = GetQueue(AvatarID);
675 OSDArray array = new OSDArray();
676 LLSD element = queue.Dequeue(15000); // 15s timeout
677 if (element == null)
678 {
679
680 array.Add(EventQueueHelper.KeepAliveEvent());
681 }
682 else
683 {
684 array.Add(element);
685 while (queue.Count() > 0)
686 {
687 array.Add(queue.Dequeue(1));
688 thisID++;
689 }
690 }
691 OSDMap events = new OSDMap();
692 events.Add("events", array);
693
694 events.Add("id", new LLSDInteger(thisID));
695
696 lock (m_ids)
697 {
698 m_ids[AvatarID] = thisID + 1;
699 }
700
701 return events;
702 }
703 else
704 {
705 return new LLSD();
706 }
707*
708*/
709 }
710 else
711 {
712 //return new LLSD();
713 }
714
715 return new OSDString("shutdown404!");
716 }
717
718 public void DisableSimulator(ulong handle, UUID avatarID) 514 public void DisableSimulator(ulong handle, UUID avatarID)
719 { 515 {
720 OSD item = EventQueueHelper.DisableSimulator(handle); 516 OSD item = EventQueueHelper.DisableSimulator(handle);
@@ -723,9 +519,14 @@ namespace OpenSim.Region.ClientStack.Linden
723 519
724 public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY) 520 public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY)
725 { 521 {
522<<<<<<< HEAD
726 if (DebugLevel > 0) 523 if (DebugLevel > 0)
727 m_log.DebugFormat("{0} EnableSimulator. handle={1}, endPoint={2}, avatarID={3}", 524 m_log.DebugFormat("{0} EnableSimulator. handle={1}, endPoint={2}, avatarID={3}",
728 LogHeader, handle, endPoint, avatarID, regionSizeX, regionSizeY); 525 LogHeader, handle, endPoint, avatarID, regionSizeX, regionSizeY);
526=======
527 m_log.DebugFormat("{0} EnableSimulator. handle={1}, avatarID={2}, regionSize={3},{4}>",
528 LogHeader, handle, avatarID, regionSizeX, regionSizeY);
529>>>>>>> avn/ubitvar
729 530
730 OSD item = EventQueueHelper.EnableSimulator(handle, endPoint, regionSizeX, regionSizeY); 531 OSD item = EventQueueHelper.EnableSimulator(handle, endPoint, regionSizeX, regionSizeY);
731 Enqueue(item, avatarID); 532 Enqueue(item, avatarID);
@@ -734,10 +535,15 @@ namespace OpenSim.Region.ClientStack.Linden
734 public virtual void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath, 535 public virtual void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath,
735 ulong regionHandle, int regionSizeX, int regionSizeY) 536 ulong regionHandle, int regionSizeX, int regionSizeY)
736 { 537 {
538<<<<<<< HEAD
737 if (DebugLevel > 0) 539 if (DebugLevel > 0)
738 m_log.DebugFormat("{0} EstablishAgentCommunication. handle={1}, endPoint={2}, avatarID={3}", 540 m_log.DebugFormat("{0} EstablishAgentCommunication. handle={1}, endPoint={2}, avatarID={3}",
739 LogHeader, regionHandle, endPoint, avatarID, regionSizeX, regionSizeY); 541 LogHeader, regionHandle, endPoint, avatarID, regionSizeX, regionSizeY);
740 542
543=======
544 m_log.DebugFormat("{0} EstablishAgentCommunication. handle={1}, avatarID={2}, regionSize={3},{4}>",
545 LogHeader, regionHandle, avatarID, regionSizeX, regionSizeY);
546>>>>>>> avn/ubitvar
741 OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath, regionHandle, regionSizeX, regionSizeY); 547 OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath, regionHandle, regionSizeX, regionSizeY);
742 Enqueue(item, avatarID); 548 Enqueue(item, avatarID);
743 } 549 }
@@ -747,9 +553,14 @@ namespace OpenSim.Region.ClientStack.Linden
747 uint locationID, uint flags, string capsURL, 553 uint locationID, uint flags, string capsURL,
748 UUID avatarID, int regionSizeX, int regionSizeY) 554 UUID avatarID, int regionSizeX, int regionSizeY)
749 { 555 {
556<<<<<<< HEAD
750 if (DebugLevel > 0) 557 if (DebugLevel > 0)
751 m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, endPoint={2}, avatarID={3}", 558 m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, endPoint={2}, avatarID={3}",
752 LogHeader, regionHandle, regionExternalEndPoint, avatarID, regionSizeX, regionSizeY); 559 LogHeader, regionHandle, regionExternalEndPoint, avatarID, regionSizeX, regionSizeY);
560=======
561 m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, avatarID={2}, regionSize={3},{4}>",
562 LogHeader, regionHandle, avatarID, regionSizeX, regionSizeY);
563>>>>>>> avn/ubitvar
753 564
754 OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint, 565 OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint,
755 locationID, flags, capsURL, avatarID, regionSizeX, regionSizeY); 566 locationID, flags, capsURL, avatarID, regionSizeX, regionSizeY);
@@ -760,9 +571,14 @@ namespace OpenSim.Region.ClientStack.Linden
760 IPEndPoint newRegionExternalEndPoint, 571 IPEndPoint newRegionExternalEndPoint,
761 string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY) 572 string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY)
762 { 573 {
574<<<<<<< HEAD
763 if (DebugLevel > 0) 575 if (DebugLevel > 0)
764 m_log.DebugFormat("{0} CrossRegion. handle={1}, avatarID={2}, regionSize={3},{4}>", 576 m_log.DebugFormat("{0} CrossRegion. handle={1}, avatarID={2}, regionSize={3},{4}>",
765 LogHeader, handle, avatarID, regionSizeX, regionSizeY); 577 LogHeader, handle, avatarID, regionSizeX, regionSizeY);
578=======
579 m_log.DebugFormat("{0} CrossRegion. handle={1}, avatarID={2}, regionSize={3},{4}>",
580 LogHeader, handle, avatarID, regionSizeX, regionSizeY);
581>>>>>>> avn/ubitvar
766 582
767 OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint, 583 OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint,
768 capsURL, avatarID, sessionID, regionSizeX, regionSizeY); 584 capsURL, avatarID, sessionID, regionSizeX, regionSizeY);
@@ -827,4 +643,4 @@ namespace OpenSim.Region.ClientStack.Linden
827 Enqueue(item, avatarID); 643 Enqueue(item, avatarID);
828 } 644 }
829 } 645 }
830} \ No newline at end of file 646}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
index 384af74..8b7e4c1 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
@@ -77,8 +77,13 @@ namespace OpenSim.Region.ClientStack.Linden
77 llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle))); 77 llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle)));
78 llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes())); 78 llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes()));
79 llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port)); 79 llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port));
80<<<<<<< HEAD
80 llsdSimInfo.Add("RegionSizeX", OSD.FromUInteger((uint) regionSizeX)); 81 llsdSimInfo.Add("RegionSizeX", OSD.FromUInteger((uint) regionSizeX));
81 llsdSimInfo.Add("RegionSizeY", OSD.FromUInteger((uint) regionSizeY)); 82 llsdSimInfo.Add("RegionSizeY", OSD.FromUInteger((uint) regionSizeY));
83=======
84 llsdSimInfo.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX));
85 llsdSimInfo.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY));
86>>>>>>> avn/ubitvar
82 87
83 OSDArray arr = new OSDArray(1); 88 OSDArray arr = new OSDArray(1);
84 arr.Add(llsdSimInfo); 89 arr.Add(llsdSimInfo);
@@ -157,6 +162,12 @@ namespace OpenSim.Region.ClientStack.Linden
157 uint locationID, uint flags, string capsURL, UUID agentID, 162 uint locationID, uint flags, string capsURL, UUID agentID,
158 int regionSizeX, int regionSizeY) 163 int regionSizeX, int regionSizeY)
159 { 164 {
165 // not sure why flags get overwritten here
166 if ((flags & (uint)TeleportFlags.IsFlying) != 0)
167 flags = (uint)TeleportFlags.ViaLocation | (uint)TeleportFlags.IsFlying;
168 else
169 flags = (uint)TeleportFlags.ViaLocation;
170
160 OSDMap info = new OSDMap(); 171 OSDMap info = new OSDMap();
161 info.Add("AgentID", OSD.FromUUID(agentID)); 172 info.Add("AgentID", OSD.FromUUID(agentID));
162 info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this? 173 info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this?
@@ -165,7 +176,12 @@ namespace OpenSim.Region.ClientStack.Linden
165 info.Add("SimAccess", OSD.FromInteger(simAccess)); 176 info.Add("SimAccess", OSD.FromInteger(simAccess));
166 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes())); 177 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes()));
167 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port)); 178 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port));
179<<<<<<< HEAD
168 info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation 180 info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation
181=======
182// info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation
183 info.Add("TeleportFlags", OSD.FromUInteger(flags));
184>>>>>>> avn/ubitvar
169 info.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX)); 185 info.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX));
170 info.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY)); 186 info.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY));
171 187
@@ -204,8 +220,8 @@ namespace OpenSim.Region.ClientStack.Linden
204 {"sim-ip-and-port", new OSDString(simIpAndPort)}, 220 {"sim-ip-and-port", new OSDString(simIpAndPort)},
205 {"seed-capability", new OSDString(seedcap)}, 221 {"seed-capability", new OSDString(seedcap)},
206 {"region-handle", OSD.FromULong(regionHandle)}, 222 {"region-handle", OSD.FromULong(regionHandle)},
207 {"region-size-x", OSD.FromInteger(regionSizeX)}, 223 {"region-size-x", OSD.FromUInteger((uint)regionSizeX)},
208 {"region-size-y", OSD.FromInteger(regionSizeY)} 224 {"region-size-y", OSD.FromUInteger((uint)regionSizeY)}
209 }; 225 };
210 226
211 return BuildEvent("EstablishAgentCommunication", body); 227 return BuildEvent("EstablishAgentCommunication", body);
@@ -412,7 +428,7 @@ namespace OpenSim.Region.ClientStack.Linden
412 public static OSD partPhysicsProperties(uint localID, byte physhapetype, 428 public static OSD partPhysicsProperties(uint localID, byte physhapetype,
413 float density, float friction, float bounce, float gravmod) 429 float density, float friction, float bounce, float gravmod)
414 { 430 {
415 431
416 OSDMap physinfo = new OSDMap(6); 432 OSDMap physinfo = new OSDMap(6);
417 physinfo["LocalID"] = localID; 433 physinfo["LocalID"] = localID;
418 physinfo["Density"] = density; 434 physinfo["Density"] = density;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
index f57d857..91efe8a 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
@@ -27,11 +27,14 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
30using System.Collections.Specialized; 31using System.Collections.Specialized;
31using System.Reflection; 32using System.Reflection;
32using System.IO; 33using System.IO;
34using System.Threading;
33using System.Web; 35using System.Web;
34using Mono.Addins; 36using Mono.Addins;
37using OpenSim.Framework.Monitoring;
35using log4net; 38using log4net;
36using Nini.Config; 39using Nini.Config;
37using OpenMetaverse; 40using OpenMetaverse;
@@ -57,12 +60,51 @@ namespace OpenSim.Region.ClientStack.Linden
57 private IAssetService m_AssetService; 60 private IAssetService m_AssetService;
58 private bool m_Enabled = true; 61 private bool m_Enabled = true;
59 private string m_URL; 62 private string m_URL;
63<<<<<<< HEAD
60 private string m_URL2; 64 private string m_URL2;
61 private string m_RedirectURL = null; 65 private string m_RedirectURL = null;
62 private string m_RedirectURL2 = null; 66 private string m_RedirectURL2 = null;
67=======
68
69 struct aPollRequest
70 {
71 public PollServiceMeshEventArgs thepoll;
72 public UUID reqID;
73 public Hashtable request;
74 }
75
76 public class aPollResponse
77 {
78 public Hashtable response;
79 public int bytes;
80 public int lod;
81 }
82
83
84 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
85
86 private static GetMeshHandler m_getMeshHandler;
87
88 private IAssetService m_assetService = null;
89
90 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
91 private static Thread[] m_workerThreads = null;
92
93 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
94 new OpenMetaverse.BlockingQueue<aPollRequest>();
95
96 private Dictionary<UUID, PollServiceMeshEventArgs> m_pollservices = new Dictionary<UUID, PollServiceMeshEventArgs>();
97>>>>>>> avn/ubitvar
63 98
64 #region Region Module interfaceBase Members 99 #region Region Module interfaceBase Members
65 100
101 ~GetMeshModule()
102 {
103 foreach (Thread t in m_workerThreads)
104 Watchdog.AbortThread(t.ManagedThreadId);
105
106 }
107
66 public Type ReplaceableInterface 108 public Type ReplaceableInterface
67 { 109 {
68 get { return null; } 110 get { return null; }
@@ -87,8 +129,12 @@ namespace OpenSim.Region.ClientStack.Linden
87 if (m_URL2 != string.Empty) 129 if (m_URL2 != string.Empty)
88 { 130 {
89 m_Enabled = true; 131 m_Enabled = true;
132<<<<<<< HEAD
90 m_RedirectURL2 = config.GetString("GetMesh2RedirectURL"); 133 m_RedirectURL2 = config.GetString("GetMesh2RedirectURL");
91 } 134 }
135=======
136
137>>>>>>> avn/ubitvar
92 } 138 }
93 139
94 public void AddRegion(Scene pScene) 140 public void AddRegion(Scene pScene)
@@ -97,6 +143,8 @@ namespace OpenSim.Region.ClientStack.Linden
97 return; 143 return;
98 144
99 m_scene = pScene; 145 m_scene = pScene;
146
147 m_assetService = pScene.AssetService;
100 } 148 }
101 149
102 public void RemoveRegion(Scene scene) 150 public void RemoveRegion(Scene scene)
@@ -105,6 +153,9 @@ namespace OpenSim.Region.ClientStack.Linden
105 return; 153 return;
106 154
107 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 155 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
156 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
157 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
158
108 m_scene = null; 159 m_scene = null;
109 } 160 }
110 161
@@ -115,6 +166,27 @@ namespace OpenSim.Region.ClientStack.Linden
115 166
116 m_AssetService = m_scene.RequestModuleInterface<IAssetService>(); 167 m_AssetService = m_scene.RequestModuleInterface<IAssetService>();
117 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 168 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
169 // We'll reuse the same handler for all requests.
170 m_getMeshHandler = new GetMeshHandler(m_assetService);
171 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
172 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
173
174 if (m_workerThreads == null)
175 {
176 m_workerThreads = new Thread[2];
177
178 for (uint i = 0; i < 2; i++)
179 {
180 m_workerThreads[i] = Watchdog.StartThread(DoMeshRequests,
181 String.Format("MeshWorkerThread{0}", i),
182 ThreadPriority.Normal,
183 false,
184 false,
185 null,
186 int.MaxValue);
187 }
188 }
189
118 } 190 }
119 191
120 192
@@ -124,9 +196,147 @@ namespace OpenSim.Region.ClientStack.Linden
124 196
125 #endregion 197 #endregion
126 198
199 private void DoMeshRequests()
200 {
201 while (true)
202 {
203 aPollRequest poolreq = m_queue.Dequeue();
204
205 poolreq.thepoll.Process(poolreq);
206 }
207 }
208
209 // Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent.
210 public void ThrottleUpdate(ScenePresence p)
211 {
212 UUID user = p.UUID;
213 int imagethrottle = p.ControllingClient.GetAgentThrottleSilent((int)ThrottleOutPacketType.Asset);
214 PollServiceMeshEventArgs args;
215 if (m_pollservices.TryGetValue(user, out args))
216 {
217 args.UpdateThrottle(imagethrottle, p);
218 }
219 }
220
221 private class PollServiceMeshEventArgs : PollServiceEventArgs
222 {
223 private List<Hashtable> requests =
224 new List<Hashtable>();
225 private Dictionary<UUID, aPollResponse> responses =
226 new Dictionary<UUID, aPollResponse>();
227
228 private Scene m_scene;
229 private MeshCapsDataThrottler m_throttler;
230 public PollServiceMeshEventArgs(string uri, UUID pId, Scene scene) :
231 base(null, uri, null, null, null, pId, int.MaxValue)
232 {
233 m_scene = scene;
234 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId);
235 // x is request id, y is userid
236 HasEvents = (x, y) =>
237 {
238 lock (responses)
239 {
240 bool ret = m_throttler.hasEvents(x, responses);
241 m_throttler.ProcessTime();
242 return ret;
243
244 }
245 };
246 GetEvents = (x, y) =>
247 {
248 lock (responses)
249 {
250 try
251 {
252 return responses[x].response;
253 }
254 finally
255 {
256 m_throttler.ProcessTime();
257 responses.Remove(x);
258 }
259 }
260 };
261 // x is request id, y is request data hashtable
262 Request = (x, y) =>
263 {
264 aPollRequest reqinfo = new aPollRequest();
265 reqinfo.thepoll = this;
266 reqinfo.reqID = x;
267 reqinfo.request = y;
268
269 m_queue.Enqueue(reqinfo);
270 };
271
272 // this should never happen except possible on shutdown
273 NoEvents = (x, y) =>
274 {
275 /*
276 lock (requests)
277 {
278 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
279 requests.Remove(request);
280 }
281 */
282 Hashtable response = new Hashtable();
283
284 response["int_response_code"] = 500;
285 response["str_response_string"] = "Script timeout";
286 response["content_type"] = "text/plain";
287 response["keepalive"] = false;
288 response["reusecontext"] = false;
289
290 return response;
291 };
292 }
293
294 public void Process(aPollRequest requestinfo)
295 {
296 Hashtable response;
297
298 UUID requestID = requestinfo.reqID;
299
300 // If the avatar is gone, don't bother to get the texture
301 if (m_scene.GetScenePresence(Id) == null)
302 {
303 response = new Hashtable();
304
305 response["int_response_code"] = 500;
306 response["str_response_string"] = "Script timeout";
307 response["content_type"] = "text/plain";
308 response["keepalive"] = false;
309 response["reusecontext"] = false;
310
311 lock (responses)
312 responses[requestID] = new aPollResponse() { bytes = 0, response = response, lod = 0 };
313
314 return;
315 }
316
317 response = m_getMeshHandler.Handle(requestinfo.request);
318 lock (responses)
319 {
320 responses[requestID] = new aPollResponse()
321 {
322 bytes = (int)response["int_bytes"],
323 lod = (int)response["int_lod"],
324 response = response
325 };
326
327 }
328 m_throttler.ProcessTime();
329 }
330
331 internal void UpdateThrottle(int pimagethrottle, ScenePresence p)
332 {
333 m_throttler.UpdateThrottle(pimagethrottle, p);
334 }
335 }
127 336
128 public void RegisterCaps(UUID agentID, Caps caps) 337 public void RegisterCaps(UUID agentID, Caps caps)
129 { 338 {
339<<<<<<< HEAD
130 UUID capID = UUID.Random(); 340 UUID capID = UUID.Random();
131 bool getMeshRegistered = false; 341 bool getMeshRegistered = false;
132 342
@@ -140,6 +350,35 @@ namespace OpenSim.Region.ClientStack.Linden
140 caps.RegisterHandler( 350 caps.RegisterHandler(
141 "GetMesh", 351 "GetMesh",
142 new GetMeshHandler("/CAPS/" + capID + "/", m_AssetService, "GetMesh", agentID.ToString(), m_RedirectURL)); 352 new GetMeshHandler("/CAPS/" + capID + "/", m_AssetService, "GetMesh", agentID.ToString(), m_RedirectURL));
353=======
354// UUID capID = UUID.Random();
355 if (m_URL == "localhost")
356 {
357 string capUrl = "/CAPS/" + UUID.Random() + "/";
358
359 // Register this as a poll service
360 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(capUrl, agentID, m_scene);
361
362 args.Type = PollServiceEventArgs.EventType.Mesh;
363 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
364
365 string hostName = m_scene.RegionInfo.ExternalHostName;
366 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
367 string protocol = "http";
368
369 if (MainServer.Instance.UseSSL)
370 {
371 hostName = MainServer.Instance.SSLCommonName;
372 port = MainServer.Instance.SSLPort;
373 protocol = "https";
374 }
375 caps.RegisterHandler("GetMesh", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
376 m_pollservices[agentID] = args;
377 m_capsDict[agentID] = capUrl;
378
379
380
381>>>>>>> avn/ubitvar
143 } 382 }
144 else 383 else
145 { 384 {
@@ -164,6 +403,177 @@ namespace OpenSim.Region.ClientStack.Linden
164 caps.RegisterHandler("GetMesh2", m_URL2); 403 caps.RegisterHandler("GetMesh2", m_URL2);
165 } 404 }
166 } 405 }
406 private void DeregisterCaps(UUID agentID, Caps caps)
407 {
408 string capUrl;
409 PollServiceMeshEventArgs args;
410 if (m_capsDict.TryGetValue(agentID, out capUrl))
411 {
412 MainServer.Instance.RemoveHTTPHandler("", capUrl);
413 m_capsDict.Remove(agentID);
414 }
415 if (m_pollservices.TryGetValue(agentID, out args))
416 {
417 m_pollservices.Remove(agentID);
418 }
419 }
420
421 internal sealed class MeshCapsDataThrottler
422 {
423
424 private volatile int currenttime = 0;
425 private volatile int lastTimeElapsed = 0;
426 private volatile int BytesSent = 0;
427 private int Lod3 = 0;
428 private int Lod2 = 0;
429 private int Lod1 = 0;
430 private int UserSetThrottle = 0;
431 private int UDPSetThrottle = 0;
432 private int CapSetThrottle = 0;
433 private float CapThrottleDistributon = 0.30f;
434 private readonly Scene m_scene;
435 private ThrottleOutPacketType Throttle;
436 private readonly UUID User;
437
438 public MeshCapsDataThrottler(int pBytes, int max, int min, Scene pScene, UUID puser)
439 {
440 ThrottleBytes = pBytes;
441 lastTimeElapsed = Util.EnvironmentTickCount();
442 Throttle = ThrottleOutPacketType.Asset;
443 m_scene = pScene;
444 User = puser;
445 }
446
447
448 public bool hasEvents(UUID key, Dictionary<UUID, aPollResponse> responses)
449 {
450 const float ThirtyPercent = 0.30f;
451 const float FivePercent = 0.05f;
452 PassTime();
453 // Note, this is called IN LOCK
454 bool haskey = responses.ContainsKey(key);
455
456 if (responses.Count > 2)
457 {
458 SplitThrottle(ThirtyPercent);
459 }
460 else
461 {
462 SplitThrottle(FivePercent);
463 }
464
465 if (!haskey)
466 {
467 return false;
468 }
469 aPollResponse response;
470 if (responses.TryGetValue(key, out response))
471 {
472 float LOD3Over = (((ThrottleBytes*CapThrottleDistributon)%50000) + 1);
473 float LOD2Over = (((ThrottleBytes*CapThrottleDistributon)%10000) + 1);
474 // Normal
475 if (BytesSent + response.bytes <= ThrottleBytes)
476 {
477 BytesSent += response.bytes;
478
479 return true;
480 }
481 // Lod3 Over Throttle protection to keep things processing even when the throttle bandwidth is set too little.
482 else if (response.bytes > ThrottleBytes && Lod3 <= ((LOD3Over < 1)? 1: LOD3Over) )
483 {
484 Interlocked.Increment(ref Lod3);
485 BytesSent += response.bytes;
486
487 return true;
488 }
489 // Lod2 Over Throttle protection to keep things processing even when the throttle bandwidth is set too little.
490 else if (response.bytes > ThrottleBytes && Lod2 <= ((LOD2Over < 1) ? 1 : LOD2Over))
491 {
492 Interlocked.Increment(ref Lod2);
493 BytesSent += response.bytes;
494
495 return true;
496 }
497 else
498 {
499 return false;
500 }
501 }
502
503 return haskey;
504 }
505 public void SubtractBytes(int bytes,int lod)
506 {
507 BytesSent -= bytes;
508 }
509 private void SplitThrottle(float percentMultiplier)
510 {
511
512 if (CapThrottleDistributon != percentMultiplier) // don't switch it if it's already set at the % multipler
513 {
514 CapThrottleDistributon = percentMultiplier;
515 ScenePresence p;
516 if (m_scene.TryGetScenePresence(User, out p)) // If we don't get a user they're not here anymore.
517 {
518// AlterThrottle(UserSetThrottle, p);
519 UpdateThrottle(UserSetThrottle, p);
520 }
521 }
522 }
523
524 public void ProcessTime()
525 {
526 PassTime();
527 }
528
529
530 private void PassTime()
531 {
532 currenttime = Util.EnvironmentTickCount();
533 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
534 //processTimeBasedActions(responses);
535 if (currenttime - timeElapsed >= 1000)
536 {
537 lastTimeElapsed = Util.EnvironmentTickCount();
538 BytesSent -= ThrottleBytes;
539 if (BytesSent < 0) BytesSent = 0;
540 if (BytesSent < ThrottleBytes)
541 {
542 Lod3 = 0;
543 Lod2 = 0;
544 Lod1 = 0;
545 }
546 }
547 }
548 private void AlterThrottle(int setting, ScenePresence p)
549 {
550 p.ControllingClient.SetAgentThrottleSilent((int)Throttle,setting);
551 }
552
553 public int ThrottleBytes
554 {
555 get { return CapSetThrottle; }
556 set { CapSetThrottle = value; }
557 }
558
559 internal void UpdateThrottle(int pimagethrottle, ScenePresence p)
560 {
561 // Client set throttle !
562 UserSetThrottle = pimagethrottle;
563 CapSetThrottle = (int)(pimagethrottle*CapThrottleDistributon);
564// UDPSetThrottle = (int) (pimagethrottle*(100 - CapThrottleDistributon));
565
566 float udp = 1.0f - CapThrottleDistributon;
567 if(udp < 0.7f)
568 udp = 0.7f;
569 UDPSetThrottle = (int) ((float)pimagethrottle * udp);
570 if (CapSetThrottle < 4068)
571 CapSetThrottle = 4068; // at least two discovery mesh
572 p.ControllingClient.SetAgentThrottleSilent((int) Throttle, UDPSetThrottle);
573 ProcessTime();
574
575 }
576 }
167 577
168 } 578 }
169} 579}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index bb932f2..b9396b7 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -27,18 +27,13 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Specialized; 30using System.Collections.Generic;
31using System.Drawing;
32using System.Drawing.Imaging;
33using System.Reflection; 31using System.Reflection;
34using System.IO; 32using System.Threading;
35using System.Web;
36using log4net; 33using log4net;
37using Nini.Config; 34using Nini.Config;
38using Mono.Addins; 35using Mono.Addins;
39using OpenMetaverse; 36using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41using OpenMetaverse.Imaging;
42using OpenSim.Framework; 37using OpenSim.Framework;
43using OpenSim.Framework.Servers; 38using OpenSim.Framework.Servers;
44using OpenSim.Framework.Servers.HttpServer; 39using OpenSim.Framework.Servers.HttpServer;
@@ -47,6 +42,7 @@ using OpenSim.Region.Framework.Scenes;
47using OpenSim.Services.Interfaces; 42using OpenSim.Services.Interfaces;
48using Caps = OpenSim.Framework.Capabilities.Caps; 43using Caps = OpenSim.Framework.Capabilities.Caps;
49using OpenSim.Capabilities.Handlers; 44using OpenSim.Capabilities.Handlers;
45using OpenSim.Framework.Monitoring;
50 46
51namespace OpenSim.Region.ClientStack.Linden 47namespace OpenSim.Region.ClientStack.Linden
52{ 48{
@@ -54,16 +50,44 @@ namespace OpenSim.Region.ClientStack.Linden
54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")] 50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")]
55 public class GetTextureModule : INonSharedRegionModule 51 public class GetTextureModule : INonSharedRegionModule
56 { 52 {
57// private static readonly ILog m_log = 53
58// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 struct aPollRequest
59 55 {
56 public PollServiceTextureEventArgs thepoll;
57 public UUID reqID;
58 public Hashtable request;
59 public bool send503;
60 }
61
62 public class aPollResponse
63 {
64 public Hashtable response;
65 public int bytes;
66 }
67
68
69 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
70
60 private Scene m_scene; 71 private Scene m_scene;
61 private IAssetService m_assetService;
62 72
63 private bool m_Enabled = false; 73 private static GetTextureHandler m_getTextureHandler;
74
75 private IAssetService m_assetService = null;
76
77 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
78 private static Thread[] m_workerThreads = null;
79
80 private string m_Url = "localhost";
81
82 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
83 new OpenMetaverse.BlockingQueue<aPollRequest>();
64 84
85<<<<<<< HEAD
65 // TODO: Change this to a config option 86 // TODO: Change this to a config option
66 private string m_RedirectURL = null; 87 private string m_RedirectURL = null;
88=======
89 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>();
90>>>>>>> avn/ubitvar
67 91
68 private string m_URL; 92 private string m_URL;
69 93
@@ -72,6 +96,7 @@ namespace OpenSim.Region.ClientStack.Linden
72 public void Initialise(IConfigSource source) 96 public void Initialise(IConfigSource source)
73 { 97 {
74 IConfig config = source.Configs["ClientStack.LindenCaps"]; 98 IConfig config = source.Configs["ClientStack.LindenCaps"];
99<<<<<<< HEAD
75 if (config == null) 100 if (config == null)
76 return; 101 return;
77 102
@@ -82,32 +107,100 @@ namespace OpenSim.Region.ClientStack.Linden
82 m_Enabled = true; 107 m_Enabled = true;
83 m_RedirectURL = config.GetString("GetTextureRedirectURL"); 108 m_RedirectURL = config.GetString("GetTextureRedirectURL");
84 } 109 }
110=======
111 if (config != null)
112 m_Url = config.GetString("Cap_GetTexture", "localhost");
113>>>>>>> avn/ubitvar
85 } 114 }
86 115
87 public void AddRegion(Scene s) 116 public void AddRegion(Scene s)
88 { 117 {
89 if (!m_Enabled)
90 return;
91
92 m_scene = s; 118 m_scene = s;
119 m_assetService = s.AssetService;
93 } 120 }
94 121
95 public void RemoveRegion(Scene s) 122 public void RemoveRegion(Scene s)
96 { 123 {
97 if (!m_Enabled)
98 return;
99
100 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 124 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
125 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
126 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
101 m_scene = null; 127 m_scene = null;
102 } 128 }
103 129
104 public void RegionLoaded(Scene s) 130 public void RegionLoaded(Scene s)
105 { 131 {
106 if (!m_Enabled) 132 // We'll reuse the same handler for all requests.
107 return; 133 m_getTextureHandler = new GetTextureHandler(m_assetService);
108 134
109 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
110 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 135 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
136 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
137 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
138
139 if (m_workerThreads == null)
140 {
141 m_workerThreads = new Thread[2];
142
143 for (uint i = 0; i < 2; i++)
144 {
145 m_workerThreads[i] = Watchdog.StartThread(DoTextureRequests,
146 String.Format("TextureWorkerThread{0}", i),
147 ThreadPriority.Normal,
148 false,
149 false,
150 null,
151 int.MaxValue);
152 }
153 }
154 }
155 private int ExtractImageThrottle(byte[] pthrottles)
156 {
157
158 byte[] adjData;
159 int pos = 0;
160
161 if (!BitConverter.IsLittleEndian)
162 {
163 byte[] newData = new byte[7 * 4];
164 Buffer.BlockCopy(pthrottles, 0, newData, 0, 7 * 4);
165
166 for (int i = 0; i < 7; i++)
167 Array.Reverse(newData, i * 4, 4);
168
169 adjData = newData;
170 }
171 else
172 {
173 adjData = pthrottles;
174 }
175
176 // 0.125f converts from bits to bytes
177 //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
178 //pos += 4;
179 // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
180 //pos += 4;
181 // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
182 // pos += 4;
183 // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
184 // pos += 4;
185 // int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
186 // pos += 4;
187 pos = pos + 20;
188 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); //pos += 4;
189 //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
190 return texture;
191 }
192
193 // Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent.
194 public void ThrottleUpdate(ScenePresence p)
195 {
196 byte[] throttles = p.ControllingClient.GetThrottlesPacked(1);
197 UUID user = p.UUID;
198 int imagethrottle = ExtractImageThrottle(throttles);
199 PollServiceTextureEventArgs args;
200 if (m_pollservices.TryGetValue(user,out args))
201 {
202 args.UpdateThrottle(imagethrottle);
203 }
111 } 204 }
112 205
113 public void PostInitialise() 206 public void PostInitialise()
@@ -125,28 +218,306 @@ namespace OpenSim.Region.ClientStack.Linden
125 218
126 #endregion 219 #endregion
127 220
128 public void RegisterCaps(UUID agentID, Caps caps) 221 ~GetTextureModule()
129 { 222 {
130 UUID capID = UUID.Random(); 223 foreach (Thread t in m_workerThreads)
224 Watchdog.AbortThread(t.ManagedThreadId);
131 225
132 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); 226 }
133 if (m_URL == "localhost") 227
228 private class PollServiceTextureEventArgs : PollServiceEventArgs
229 {
230 private List<Hashtable> requests =
231 new List<Hashtable>();
232 private Dictionary<UUID, aPollResponse> responses =
233 new Dictionary<UUID, aPollResponse>();
234
235 private Scene m_scene;
236 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000);
237 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
238 base(null, "", null, null, null, pId, int.MaxValue)
134 { 239 {
240<<<<<<< HEAD
135// m_log.DebugFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 241// m_log.DebugFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
136 caps.RegisterHandler( 242 caps.RegisterHandler(
137 "GetTexture", 243 "GetTexture",
138 new GetTextureHandler("/CAPS/" + capID + "/", m_assetService, "GetTexture", agentID.ToString(), m_RedirectURL)); 244 new GetTextureHandler("/CAPS/" + capID + "/", m_assetService, "GetTexture", agentID.ToString(), m_RedirectURL));
245=======
246 m_scene = scene;
247 // x is request id, y is userid
248 HasEvents = (x, y) =>
249 {
250 lock (responses)
251 {
252 bool ret = m_throttler.hasEvents(x, responses);
253 m_throttler.ProcessTime();
254 return ret;
255
256 }
257 };
258 GetEvents = (x, y) =>
259 {
260 lock (responses)
261 {
262 try
263 {
264 return responses[x].response;
265 }
266 finally
267 {
268 responses.Remove(x);
269 }
270 }
271 };
272 // x is request id, y is request data hashtable
273 Request = (x, y) =>
274 {
275 aPollRequest reqinfo = new aPollRequest();
276 reqinfo.thepoll = this;
277 reqinfo.reqID = x;
278 reqinfo.request = y;
279 reqinfo.send503 = false;
280
281 lock (responses)
282 {
283 if (responses.Count > 0)
284 {
285 if (m_queue.Count >= 4)
286 {
287 // Never allow more than 4 fetches to wait
288 reqinfo.send503 = true;
289 }
290 }
291 }
292 m_queue.Enqueue(reqinfo);
293 };
294
295 // this should never happen except possible on shutdown
296 NoEvents = (x, y) =>
297 {
298/*
299 lock (requests)
300 {
301 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
302 requests.Remove(request);
303 }
304*/
305 Hashtable response = new Hashtable();
306
307 response["int_response_code"] = 500;
308 response["str_response_string"] = "Script timeout";
309 response["content_type"] = "text/plain";
310 response["keepalive"] = false;
311 response["reusecontext"] = false;
312
313 return response;
314 };
315>>>>>>> avn/ubitvar
139 } 316 }
140 else 317
318 public void Process(aPollRequest requestinfo)
141 { 319 {
142// m_log.DebugFormat("[GETTEXTURE]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName); 320 Hashtable response;
321
322 UUID requestID = requestinfo.reqID;
323
324 if (requestinfo.send503)
325 {
326 response = new Hashtable();
327
328
329 response["int_response_code"] = 503;
330 response["str_response_string"] = "Throttled";
331 response["content_type"] = "text/plain";
332 response["keepalive"] = false;
333 response["reusecontext"] = false;
334
335 Hashtable headers = new Hashtable();
336 headers["Retry-After"] = 30;
337 response["headers"] = headers;
338
339 lock (responses)
340 responses[requestID] = new aPollResponse() {bytes = 0, response = response};
341
342 return;
343 }
344
345 // If the avatar is gone, don't bother to get the texture
346 if (m_scene.GetScenePresence(Id) == null)
347 {
348 response = new Hashtable();
349
350 response["int_response_code"] = 500;
351 response["str_response_string"] = "Script timeout";
352 response["content_type"] = "text/plain";
353 response["keepalive"] = false;
354 response["reusecontext"] = false;
355
356 lock (responses)
357 responses[requestID] = new aPollResponse() {bytes = 0, response = response};
358
359 return;
360 }
361
362 response = m_getTextureHandler.Handle(requestinfo.request);
363 lock (responses)
364 {
365 responses[requestID] = new aPollResponse()
366 {
367 bytes = (int) response["int_bytes"],
368 response = response
369 };
370
371 }
372 m_throttler.ProcessTime();
373 }
374
375 internal void UpdateThrottle(int pimagethrottle)
376 {
377 m_throttler.ThrottleBytes = pimagethrottle;
378 }
379 }
380
381 private void RegisterCaps(UUID agentID, Caps caps)
382 {
383 if (m_Url == "localhost")
384 {
385 string capUrl = "/CAPS/" + UUID.Random() + "/";
386
387 // Register this as a poll service
388 PollServiceTextureEventArgs args = new PollServiceTextureEventArgs(agentID, m_scene);
389
390 args.Type = PollServiceEventArgs.EventType.Texture;
391 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
392
393 string hostName = m_scene.RegionInfo.ExternalHostName;
394 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
395 string protocol = "http";
396
397 if (MainServer.Instance.UseSSL)
398 {
399 hostName = MainServer.Instance.SSLCommonName;
400 port = MainServer.Instance.SSLPort;
401 protocol = "https";
402 }
143 IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>(); 403 IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>();
144 if (handler != null) 404 if (handler != null)
405<<<<<<< HEAD
145 handler.RegisterExternalUserCapsHandler(agentID,caps,"GetTexture", m_URL); 406 handler.RegisterExternalUserCapsHandler(agentID,caps,"GetTexture", m_URL);
407=======
408 handler.RegisterExternalUserCapsHandler(agentID, caps, "GetTexture", capUrl);
409>>>>>>> avn/ubitvar
146 else 410 else
147 caps.RegisterHandler("GetTexture", m_URL); 411 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
412 m_pollservices[agentID] = args;
413 m_capsDict[agentID] = capUrl;
414 }
415 else
416 {
417 caps.RegisterHandler("GetTexture", m_Url);
148 } 418 }
149 } 419 }
150 420
421 private void DeregisterCaps(UUID agentID, Caps caps)
422 {
423 PollServiceTextureEventArgs args;
424
425 MainServer.Instance.RemoveHTTPHandler("", m_URL);
426 m_capsDict.Remove(agentID);
427
428 if (m_pollservices.TryGetValue(agentID, out args))
429 {
430 m_pollservices.Remove(agentID);
431 }
432 }
433
434 private void DoTextureRequests()
435 {
436 while (true)
437 {
438 aPollRequest poolreq = m_queue.Dequeue();
439
440 poolreq.thepoll.Process(poolreq);
441 }
442 }
443 internal sealed class CapsDataThrottler
444 {
445
446 private volatile int currenttime = 0;
447 private volatile int lastTimeElapsed = 0;
448 private volatile int BytesSent = 0;
449 private int oversizedImages = 0;
450 public CapsDataThrottler(int pBytes, int max, int min)
451 {
452 ThrottleBytes = pBytes;
453 lastTimeElapsed = Util.EnvironmentTickCount();
454 }
455 public bool hasEvents(UUID key, Dictionary<UUID, GetTextureModule.aPollResponse> responses)
456 {
457 PassTime();
458 // Note, this is called IN LOCK
459 bool haskey = responses.ContainsKey(key);
460 if (!haskey)
461 {
462 return false;
463 }
464 GetTextureModule.aPollResponse response;
465 if (responses.TryGetValue(key, out response))
466 {
467 // This is any error response
468 if (response.bytes == 0)
469 return true;
470
471 // Normal
472 if (BytesSent + response.bytes <= ThrottleBytes)
473 {
474 BytesSent += response.bytes;
475 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false };
476 //m_actions.Add(timeBasedAction);
477 return true;
478 }
479 // Big textures
480 else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes % 50000) + 1))
481 {
482 Interlocked.Increment(ref oversizedImages);
483 BytesSent += response.bytes;
484 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false };
485 //m_actions.Add(timeBasedAction);
486 return true;
487 }
488 else
489 {
490 return false;
491 }
492 }
493
494 return haskey;
495 }
496
497 public void ProcessTime()
498 {
499 PassTime();
500 }
501
502 private void PassTime()
503 {
504 currenttime = Util.EnvironmentTickCount();
505 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
506 //processTimeBasedActions(responses);
507 if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000)
508 {
509 lastTimeElapsed = Util.EnvironmentTickCount();
510 BytesSent -= ThrottleBytes;
511 if (BytesSent < 0) BytesSent = 0;
512 if (BytesSent < ThrottleBytes)
513 {
514 oversizedImages = 0;
515 }
516 }
517 }
518 public int ThrottleBytes;
519 }
151 } 520 }
521
522
152} 523}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
index 45d33cd..1b68603 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
@@ -129,15 +129,15 @@ namespace OpenSim.Region.ClientStack.Linden
129// m_log.DebugFormat("[MESH UPLOAD FLAG MODULE]: MeshUploadFlag request"); 129// m_log.DebugFormat("[MESH UPLOAD FLAG MODULE]: MeshUploadFlag request");
130 130
131 OSDMap data = new OSDMap(); 131 OSDMap data = new OSDMap();
132 ScenePresence sp = m_scene.GetScenePresence(agentID); 132// ScenePresence sp = m_scene.GetScenePresence(m_agentID);
133 data["username"] = sp.Firstname + "." + sp.Lastname; 133// data["username"] = sp.Firstname + "." + sp.Lastname;
134 data["display_name_next_update"] = new OSDDate(DateTime.Now); 134// data["display_name_next_update"] = new OSDDate(DateTime.Now);
135 data["legacy_first_name"] = sp.Firstname; 135// data["legacy_first_name"] = sp.Firstname;
136 data["mesh_upload_status"] = "valid"; 136 data["mesh_upload_status"] = "valid";
137 data["display_name"] = sp.Firstname + " " + sp.Lastname; 137// data["display_name"] = sp.Firstname + " " + sp.Lastname;
138 data["legacy_last_name"] = sp.Lastname; 138// data["legacy_last_name"] = sp.Lastname;
139 data["id"] = agentID; 139// data["id"] = m_agentID;
140 data["is_display_name_default"] = true; 140// data["is_display_name_default"] = true;
141 141
142 //Send back data 142 //Send back data
143 Hashtable responsedata = new Hashtable(); 143 Hashtable responsedata = new Hashtable();
@@ -148,4 +148,4 @@ namespace OpenSim.Region.ClientStack.Linden
148 return responsedata; 148 return responsedata;
149 } 149 }
150 } 150 }
151} \ No newline at end of file 151}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs
deleted file mode 100644
index f69a0bb..0000000
--- a/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs
+++ /dev/null
@@ -1,297 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
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;
47using PermissionMask = OpenSim.Framework.PermissionMask;
48
49namespace OpenSim.Region.ClientStack.Linden
50{
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "NewFileAgentInventoryVariablePriceModule")]
52 public class NewFileAgentInventoryVariablePriceModule : INonSharedRegionModule
53 {
54// private static readonly ILog m_log = 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 private int m_levelUpload = 0;
61
62 #region Region Module interfaceBase Members
63
64
65 public Type ReplaceableInterface
66 {
67 get { return null; }
68 }
69
70 public void Initialise(IConfigSource source)
71 {
72 IConfig meshConfig = source.Configs["Mesh"];
73 if (meshConfig == null)
74 return;
75
76 m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true);
77 m_levelUpload = meshConfig.GetInt("LevelUpload", 0);
78 }
79
80 public void AddRegion(Scene pScene)
81 {
82 m_scene = pScene;
83 }
84
85 public void RemoveRegion(Scene scene)
86 {
87
88 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
89 m_scene = null;
90 }
91
92 public void RegionLoaded(Scene scene)
93 {
94
95// m_assetService = m_scene.RequestModuleInterface<IAssetService>();
96 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
97 }
98
99 #endregion
100
101
102 #region Region Module interface
103
104
105
106 public void Close() { }
107
108 public string Name { get { return "NewFileAgentInventoryVariablePriceModule"; } }
109
110
111 public void RegisterCaps(UUID agentID, Caps caps)
112 {
113 if(!m_enabled)
114 return;
115
116 UUID capID = UUID.Random();
117
118// m_log.Debug("[NEW FILE AGENT INVENTORY VARIABLE PRICE]: /CAPS/" + capID);
119 caps.RegisterHandler(
120 "NewFileAgentInventoryVariablePrice",
121 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDNewFileAngentInventoryVariablePriceReplyResponse>(
122 "POST",
123 "/CAPS/" + capID.ToString(),
124 req => NewAgentInventoryRequest(req, agentID),
125 "NewFileAgentInventoryVariablePrice",
126 agentID.ToString()));
127 }
128
129 #endregion
130
131 public LLSDNewFileAngentInventoryVariablePriceReplyResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest, UUID agentID)
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
135
136 //if (llsdRequest.asset_type == "texture" ||
137 // llsdRequest.asset_type == "animation" ||
138 // llsdRequest.asset_type == "sound")
139 // {
140 // check user level
141
142 ScenePresence avatar = null;
143 IClientAPI client = null;
144 m_scene.TryGetScenePresence(agentID, out avatar);
145
146 if (avatar != null)
147 {
148 client = avatar.ControllingClient;
149
150 if (avatar.UserLevel < m_levelUpload)
151 {
152 if (client != null)
153 client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false);
154
155 LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
156 errorResponse.rsvp = "";
157 errorResponse.state = "error";
158 return errorResponse;
159 }
160 }
161
162 // check funds
163 IMoneyModule mm = m_scene.RequestModuleInterface<IMoneyModule>();
164
165 if (mm != null)
166 {
167 if (!mm.UploadCovered(agentID, mm.UploadCharge))
168 {
169 if (client != null)
170 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
171
172 LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
173 errorResponse.rsvp = "";
174 errorResponse.state = "error";
175 return errorResponse;
176 }
177 }
178
179 // }
180
181 string assetName = llsdRequest.name;
182 string assetDes = llsdRequest.description;
183 string capsBase = "/CAPS/NewFileAgentInventoryVariablePrice/";
184 UUID newAsset = UUID.Random();
185 UUID newInvItem = UUID.Random();
186 UUID parentFolder = llsdRequest.folder_id;
187 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000") + "/";
188
189 AssetUploader uploader =
190 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
191 llsdRequest.asset_type, capsBase + uploaderPath, MainServer.Instance, m_dumpAssetsToFile);
192
193 MainServer.Instance.AddStreamHandler(
194 new BinaryStreamHandler(
195 "POST",
196 capsBase + uploaderPath,
197 uploader.uploaderCaps,
198 "NewFileAgentInventoryVariablePrice",
199 agentID.ToString()));
200
201 string protocol = "http://";
202
203 if (MainServer.Instance.UseSSL)
204 protocol = "https://";
205
206 string uploaderURL = protocol + m_scene.RegionInfo.ExternalHostName + ":" + MainServer.Instance.Port.ToString() + capsBase +
207 uploaderPath;
208
209
210 LLSDNewFileAngentInventoryVariablePriceReplyResponse uploadResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
211
212 uploadResponse.rsvp = uploaderURL;
213 uploadResponse.state = "upload";
214 uploadResponse.resource_cost = 0;
215 uploadResponse.upload_price = 0;
216
217 uploader.OnUpLoad += //UploadCompleteHandler;
218
219 delegate(
220 string passetName, string passetDescription, UUID passetID,
221 UUID pinventoryItem, UUID pparentFolder, byte[] pdata, string pinventoryType,
222 string passetType)
223 {
224 UploadCompleteHandler(passetName, passetDescription, passetID,
225 pinventoryItem, pparentFolder, pdata, pinventoryType,
226 passetType,agentID);
227 };
228
229 return uploadResponse;
230 }
231
232 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
233 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
234 string assetType,UUID AgentID)
235 {
236// m_log.DebugFormat(
237// "[NEW FILE AGENT INVENTORY VARIABLE PRICE MODULE]: Upload complete for {0}", inventoryItem);
238
239 sbyte assType = 0;
240 sbyte inType = 0;
241
242 if (inventoryType == "sound")
243 {
244 inType = 1;
245 assType = 1;
246 }
247 else if (inventoryType == "animation")
248 {
249 inType = 19;
250 assType = 20;
251 }
252 else if (inventoryType == "wearable")
253 {
254 inType = 18;
255 switch (assetType)
256 {
257 case "bodypart":
258 assType = 13;
259 break;
260 case "clothing":
261 assType = 5;
262 break;
263 }
264 }
265 else if (inventoryType == "mesh")
266 {
267 inType = (sbyte)InventoryType.Mesh;
268 assType = (sbyte)AssetType.Mesh;
269 }
270
271 AssetBase asset;
272 asset = new AssetBase(assetID, assetName, assType, AgentID.ToString());
273 asset.Data = data;
274
275 if (m_scene.AssetService != null)
276 m_scene.AssetService.Store(asset);
277
278 InventoryItemBase item = new InventoryItemBase();
279 item.Owner = AgentID;
280 item.CreatorId = AgentID.ToString();
281 item.ID = inventoryItem;
282 item.AssetID = asset.FullID;
283 item.Description = assetDescription;
284 item.Name = assetName;
285 item.AssetType = assType;
286 item.InvType = inType;
287 item.Folder = parentFolder;
288 item.CurrentPermissions
289 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
290 item.BasePermissions = (uint)PermissionMask.All;
291 item.EveryOnePermissions = 0;
292 item.NextPermissions = (uint)PermissionMask.All;
293 item.CreationDate = Util.UnixTimeSinceEpoch();
294 m_scene.AddInventoryItem(item);
295 }
296 }
297}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
index a133a69..5196368 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
@@ -64,6 +64,8 @@ namespace OpenSim.Region.ClientStack.Linden
64 private Commands m_commands = new Commands(); 64 private Commands m_commands = new Commands();
65 public ICommands Commands { get { return m_commands; } } 65 public ICommands Commands { get { return m_commands; } }
66 66
67 public event ConsoleMessage OnConsoleMessage;
68
67 public void Initialise(IConfigSource source) 69 public void Initialise(IConfigSource source)
68 { 70 {
69 m_commands.AddCommand( "Help", false, "help", "help [<item>]", "Display help on a particular command or on a list of commands in a category", Help); 71 m_commands.AddCommand( "Help", false, "help", "help [<item>]", "Display help on a particular command or on a list of commands in a category", Help);
@@ -102,7 +104,7 @@ namespace OpenSim.Region.ClientStack.Linden
102 104
103 public void RegisterCaps(UUID agentID, Caps caps) 105 public void RegisterCaps(UUID agentID, Caps caps)
104 { 106 {
105 if (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(agentID)) 107 if (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(agentID) && !m_scene.Permissions.IsGod(agentID))
106 return; 108 return;
107 109
108 UUID capID = UUID.Random(); 110 UUID capID = UUID.Random();
@@ -118,6 +120,11 @@ namespace OpenSim.Region.ClientStack.Linden
118 OSD osd = OSD.FromString(message); 120 OSD osd = OSD.FromString(message);
119 121
120 m_eventQueue.Enqueue(EventQueueHelper.BuildEvent("SimConsoleResponse", osd), agentID); 122 m_eventQueue.Enqueue(EventQueueHelper.BuildEvent("SimConsoleResponse", osd), agentID);
123
124 ConsoleMessage handlerConsoleMessage = OnConsoleMessage;
125
126 if (handlerConsoleMessage != null)
127 handlerConsoleMessage( agentID, message);
121 } 128 }
122 129
123 public bool RunCommand(string command, UUID invokerID) 130 public bool RunCommand(string command, UUID invokerID)
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
index e258bcb..54542c9 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
@@ -155,8 +155,13 @@ namespace OpenSim.Region.ClientStack.Linden
155 m_features["MeshRezEnabled"] = true; 155 m_features["MeshRezEnabled"] = true;
156 m_features["MeshUploadEnabled"] = true; 156 m_features["MeshUploadEnabled"] = true;
157 m_features["MeshXferEnabled"] = true; 157 m_features["MeshXferEnabled"] = true;
158
158 m_features["PhysicsMaterialsEnabled"] = true; 159 m_features["PhysicsMaterialsEnabled"] = true;
160<<<<<<< HEAD
159 161
162=======
163
164>>>>>>> avn/ubitvar
160 OSDMap typesMap = new OSDMap(); 165 OSDMap typesMap = new OSDMap();
161 typesMap["convex"] = true; 166 typesMap["convex"] = true;
162 typesMap["none"] = true; 167 typesMap["none"] = true;
@@ -164,6 +169,7 @@ namespace OpenSim.Region.ClientStack.Linden
164 m_features["PhysicsShapeTypes"] = typesMap; 169 m_features["PhysicsShapeTypes"] = typesMap;
165 170
166 // Extra information for viewers that want to use it 171 // Extra information for viewers that want to use it
172<<<<<<< HEAD
167 // TODO: Take these out of here into their respective modules, like map-server-url 173 // TODO: Take these out of here into their respective modules, like map-server-url
168 OSDMap extrasMap; 174 OSDMap extrasMap;
169 if(m_features.ContainsKey("OpenSimExtras")) 175 if(m_features.ContainsKey("OpenSimExtras"))
@@ -173,6 +179,15 @@ namespace OpenSim.Region.ClientStack.Linden
173 else 179 else
174 extrasMap = new OSDMap(); 180 extrasMap = new OSDMap();
175 181
182=======
183
184 OSDMap extrasMap = new OSDMap();
185
186 extrasMap["AvatarSkeleton"] = true;
187 extrasMap["AnimationSet"] = true;
188
189 // TODO: Take these out of here into their respective modules, like map-server-url
190>>>>>>> avn/ubitvar
176 if (m_SearchURL != string.Empty) 191 if (m_SearchURL != string.Empty)
177 extrasMap["search-server-url"] = m_SearchURL; 192 extrasMap["search-server-url"] = m_SearchURL;
178 if (!string.IsNullOrEmpty(m_DestinationGuideURL)) 193 if (!string.IsNullOrEmpty(m_DestinationGuideURL))
@@ -184,8 +199,13 @@ namespace OpenSim.Region.ClientStack.Linden
184 if (m_GridName != string.Empty) 199 if (m_GridName != string.Empty)
185 extrasMap["GridName"] = m_GridName; 200 extrasMap["GridName"] = m_GridName;
186 201
202<<<<<<< HEAD
187 if (extrasMap.Count > 0) 203 if (extrasMap.Count > 0)
188 m_features["OpenSimExtras"] = extrasMap; 204 m_features["OpenSimExtras"] = extrasMap;
205=======
206 m_features["OpenSimExtras"] = extrasMap;
207
208>>>>>>> avn/ubitvar
189 } 209 }
190 } 210 }
191 211
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
index 8cdebcd..c27d101 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
@@ -67,6 +67,8 @@ namespace OpenSim.Region.ClientStack.Linden
67 67
68 private IBakedTextureModule m_BakedTextureModule; 68 private IBakedTextureModule m_BakedTextureModule;
69 69
70 private IBakedTextureModule m_BakedTextureModule;
71
70 public void Initialise(IConfigSource source) 72 public void Initialise(IConfigSource source)
71 { 73 {
72 IConfig appearanceConfig = source.Configs["Appearance"]; 74 IConfig appearanceConfig = source.Configs["Appearance"];
@@ -89,7 +91,11 @@ namespace OpenSim.Region.ClientStack.Linden
89 s.EventManager.OnRemovePresence -= DeRegisterPresence; 91 s.EventManager.OnRemovePresence -= DeRegisterPresence;
90 m_BakedTextureModule = null; 92 m_BakedTextureModule = null;
91 m_scene = null; 93 m_scene = null;
94<<<<<<< HEAD
92 } 95 }
96=======
97 }
98>>>>>>> avn/ubitvar
93 99
94 100
95 101
@@ -103,6 +109,7 @@ namespace OpenSim.Region.ClientStack.Linden
103 109
104 private void DeRegisterPresence(UUID agentId) 110 private void DeRegisterPresence(UUID agentId)
105 { 111 {
112<<<<<<< HEAD
106 ScenePresence presence = null; 113 ScenePresence presence = null;
107 if (m_scene.TryGetScenePresence(agentId, out presence)) 114 if (m_scene.TryGetScenePresence(agentId, out presence))
108 { 115 {
@@ -261,8 +268,162 @@ namespace OpenSim.Region.ClientStack.Linden
261 } 268 }
262 } 269 }
263 } 270 }
271=======
272// ScenePresence presence = null;
273// if (m_scene.TryGetScenePresence(agentId, out presence))
274 {
275// presence.ControllingClient.OnSetAppearance -= CaptureAppearanceSettings;
276 }
277
278>>>>>>> avn/ubitvar
279 }
280
281 private void RegisterNewPresence(ScenePresence presence)
282 {
283// presence.ControllingClient.OnSetAppearance += CaptureAppearanceSettings;
264 } 284 }
265 285
286/* not in use. work done in AvatarFactoryModule ValidateBakedTextureCache() and UpdateBakedTextureCache()
287 private void CaptureAppearanceSettings(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems)
288 {
289 // if cacheItems.Length > 0 viewer is giving us current textures information.
290 // baked ones should had been uploaded and in assets cache as local itens
291
292
293 if (cacheItems.Length == 0)
294 return; // no textures information, nothing to do
295
296 ScenePresence p = null;
297 if (!m_scene.TryGetScenePresence(remoteClient.AgentId, out p))
298 return; // what are we doing if there is no presence to cache for?
299
300 if (p.IsDeleted)
301 return; // does this really work?
302
303 int maxCacheitemsLoop = cacheItems.Length;
304 if (maxCacheitemsLoop > 20)
305 {
306 maxCacheitemsLoop = AvatarWearable.MAX_WEARABLES;
307 m_log.WarnFormat("[CACHEDBAKES]: Too Many Cache items Provided {0}, the max is {1}. Truncating!", cacheItems.Length, AvatarWearable.MAX_WEARABLES);
308 }
309
310 m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
311
312
313 // some nice debug
314 m_log.Debug("[Cacheitems]: " + cacheItems.Length);
315 for (int iter = 0; iter < maxCacheitemsLoop; iter++)
316 {
317 m_log.Debug("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" +
318 cacheItems[iter].TextureID);
319 }
320
321 // p.Appearance.WearableCacheItems is in memory primary cashID to textures mapper
322
323 WearableCacheItem[] existingitems = p.Appearance.WearableCacheItems;
324
325 if (existingitems == null)
326 {
327 if (m_BakedTextureModule != null)
328 {
329 WearableCacheItem[] savedcache = null;
330 try
331 {
332 if (p.Appearance.WearableCacheItemsDirty)
333 {
334 savedcache = m_BakedTextureModule.Get(p.UUID);
335 p.Appearance.WearableCacheItems = savedcache;
336 p.Appearance.WearableCacheItemsDirty = false;
337 }
338 }
339
340 catch (Exception)
341 {
342 // The service logs a sufficient error message.
343 }
344
345
346 if (savedcache != null)
347 existingitems = savedcache;
348 }
349 }
350
351 // Existing items null means it's a fully new appearance
352 if (existingitems == null)
353 {
354 for (int i = 0; i < maxCacheitemsLoop; i++)
355 {
356 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
357 {
358 Primitive.TextureEntryFace face = textureEntry.FaceTextures[cacheItems[i].TextureIndex];
359 if (face == null)
360 {
361 textureEntry.CreateFace(cacheItems[i].TextureIndex);
362 textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID =
363 AppearanceManager.DEFAULT_AVATAR_TEXTURE;
364 continue;
365 }
366 cacheItems[i].TextureID = face.TextureID;
367 if (m_scene.AssetService != null)
368 cacheItems[i].TextureAsset =
369 m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString());
370 }
371 else
372 {
373 m_log.WarnFormat("[CACHEDBAKES]: Invalid Texture Index Provided, Texture doesn't exist or hasn't been uploaded yet {0}, the max is {1}. Skipping!", cacheItems[i].TextureIndex, textureEntry.FaceTextures.Length);
374 }
375 }
376 }
377 else
378 {
379 for (int i = 0; i < maxCacheitemsLoop; i++)
380 {
381 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
382 {
383 Primitive.TextureEntryFace face = textureEntry.FaceTextures[cacheItems[i].TextureIndex];
384 if (face == null)
385 {
386 textureEntry.CreateFace(cacheItems[i].TextureIndex);
387 textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID =
388 AppearanceManager.DEFAULT_AVATAR_TEXTURE;
389 continue;
390 }
391 cacheItems[i].TextureID =
392 face.TextureID;
393 }
394 else
395 {
396 m_log.WarnFormat("[CACHEDBAKES]: Invalid Texture Index Provided, Texture doesn't exist or hasn't been uploaded yet {0}, the max is {1}. Skipping!", cacheItems[i].TextureIndex, textureEntry.FaceTextures.Length);
397 }
398 }
399
400 for (int i = 0; i < maxCacheitemsLoop; i++)
401 {
402 if (cacheItems[i].TextureAsset == null)
403 {
404 cacheItems[i].TextureAsset =
405 m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString());
406 }
407 }
408 }
409 p.Appearance.WearableCacheItems = cacheItems;
410
411 if (m_BakedTextureModule != null)
412 {
413 m_BakedTextureModule.Store(remoteClient.AgentId, cacheItems);
414 p.Appearance.WearableCacheItemsDirty = true;
415
416 }
417 else
418 p.Appearance.WearableCacheItemsDirty = false;
419
420 for (int iter = 0; iter < maxCacheitemsLoop; iter++)
421 {
422 m_log.Debug("[CacheitemsLeaving] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" +
423 cacheItems[iter].TextureID);
424 }
425 }
426 */
266 public void PostInitialise() 427 public void PostInitialise()
267 { 428 {
268 } 429 }
@@ -283,6 +444,7 @@ namespace OpenSim.Region.ClientStack.Linden
283 UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler( 444 UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler(
284 caps, m_scene.AssetService, m_persistBakedTextures); 445 caps, m_scene.AssetService, m_persistBakedTextures);
285 446
447<<<<<<< HEAD
286 448
287 449
288 caps.RegisterHandler( 450 caps.RegisterHandler(
@@ -297,6 +459,28 @@ namespace OpenSim.Region.ClientStack.Linden
297 459
298 460
299 461
462=======
463 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture));
464 if (m_URL == "localhost")
465 {
466 UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler(
467 caps, m_scene.AssetService, m_persistBakedTextures);
468
469 caps.RegisterHandler(
470 "UploadBakedTexture",
471 new RestStreamHandler(
472 "POST",
473 "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
474 avatarhandler.UploadBakedTexture,
475 "UploadBakedTexture",
476 agentID.ToString()));
477
478 }
479 else
480 {
481 caps.RegisterHandler("UploadBakedTexture", m_URL);
482 }
483>>>>>>> avn/ubitvar
300 } 484 }
301 } 485 }
302} 486}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 025ffea..92f8c51 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -34,9 +34,7 @@ using log4net;
34using Nini.Config; 34using Nini.Config;
35using Mono.Addins; 35using Mono.Addins;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework; 37using OpenSim.Framework;
39using OpenSim.Framework.Monitoring;
40using OpenSim.Framework.Servers; 38using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer; 39using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.Framework.Interfaces; 40using OpenSim.Region.Framework.Interfaces;
@@ -45,6 +43,9 @@ using OpenSim.Framework.Capabilities;
45using OpenSim.Services.Interfaces; 43using OpenSim.Services.Interfaces;
46using Caps = OpenSim.Framework.Capabilities.Caps; 44using Caps = OpenSim.Framework.Capabilities.Caps;
47using OpenSim.Capabilities.Handlers; 45using OpenSim.Capabilities.Handlers;
46using OpenSim.Framework.Monitoring;
47using OpenMetaverse;
48using OpenMetaverse.StructuredData;
48 49
49namespace OpenSim.Region.ClientStack.Linden 50namespace OpenSim.Region.ClientStack.Linden
50{ 51{
@@ -63,7 +64,11 @@ namespace OpenSim.Region.ClientStack.Linden
63 public List<UUID> folders; 64 public List<UUID> folders;
64 } 65 }
65 66
67<<<<<<< HEAD
66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 68 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
69=======
70 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
71>>>>>>> avn/ubitvar
67 72
68 /// <summary> 73 /// <summary>
69 /// Control whether requests will be processed asynchronously. 74 /// Control whether requests will be processed asynchronously.
@@ -312,7 +317,8 @@ namespace OpenSim.Region.ClientStack.Linden
312 { 317 {
313 if (!reqinfo.folders.Contains(folderID)) 318 if (!reqinfo.folders.Contains(folderID))
314 { 319 {
315 //TODO: Port COF handling from Avination 320 if (sp.COF != UUID.Zero && sp.COF == folderID)
321 highPriority = true;
316 reqinfo.folders.Add(folderID); 322 reqinfo.folders.Add(folderID);
317 } 323 }
318 } 324 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
index 4d0568d..15d6f7f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
@@ -234,6 +234,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
234 m_stopPacket = TexturePacketCount(); 234 m_stopPacket = TexturePacketCount();
235 } 235 }
236 236
237 //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way)
238 if (m_stopPacket == 1 && m_layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++;
239
237 m_currentPacket = StartPacket; 240 m_currentPacket = StartPacket;
238 } 241 }
239 } 242 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index e7dd9d3..806269f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -100,6 +100,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
100 public event AvatarPickerRequest OnAvatarPickerRequest; 100 public event AvatarPickerRequest OnAvatarPickerRequest;
101 public event StartAnim OnStartAnim; 101 public event StartAnim OnStartAnim;
102 public event StopAnim OnStopAnim; 102 public event StopAnim OnStopAnim;
103 public event ChangeAnim OnChangeAnim;
103 public event Action<IClientAPI> OnRequestAvatarsData; 104 public event Action<IClientAPI> OnRequestAvatarsData;
104 public event LinkObjects OnLinkObjects; 105 public event LinkObjects OnLinkObjects;
105 public event DelinkObjects OnDelinkObjects; 106 public event DelinkObjects OnDelinkObjects;
@@ -127,6 +128,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
127 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; 128 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
128 public event UpdatePrimFlags OnUpdatePrimFlags; 129 public event UpdatePrimFlags OnUpdatePrimFlags;
129 public event UpdatePrimTexture OnUpdatePrimTexture; 130 public event UpdatePrimTexture OnUpdatePrimTexture;
131 public event ClientChangeObject onClientChangeObject;
130 public event UpdateVector OnUpdatePrimGroupPosition; 132 public event UpdateVector OnUpdatePrimGroupPosition;
131 public event UpdateVector OnUpdatePrimSinglePosition; 133 public event UpdateVector OnUpdatePrimSinglePosition;
132 public event UpdatePrimRotation OnUpdatePrimGroupRotation; 134 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
@@ -156,6 +158,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
156 public event RequestTaskInventory OnRequestTaskInventory; 158 public event RequestTaskInventory OnRequestTaskInventory;
157 public event UpdateInventoryItem OnUpdateInventoryItem; 159 public event UpdateInventoryItem OnUpdateInventoryItem;
158 public event CopyInventoryItem OnCopyInventoryItem; 160 public event CopyInventoryItem OnCopyInventoryItem;
161 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
159 public event MoveInventoryItem OnMoveInventoryItem; 162 public event MoveInventoryItem OnMoveInventoryItem;
160 public event RemoveInventoryItem OnRemoveInventoryItem; 163 public event RemoveInventoryItem OnRemoveInventoryItem;
161 public event RemoveInventoryFolder OnRemoveInventoryFolder; 164 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -250,7 +253,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
250 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 253 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
251 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 254 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
252 public event ClassifiedDelete OnClassifiedDelete; 255 public event ClassifiedDelete OnClassifiedDelete;
253 public event ClassifiedDelete OnClassifiedGodDelete; 256 public event ClassifiedGodDelete OnClassifiedGodDelete;
254 public event EventNotificationAddRequest OnEventNotificationAddRequest; 257 public event EventNotificationAddRequest OnEventNotificationAddRequest;
255 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 258 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
256 public event EventGodDelete OnEventGodDelete; 259 public event EventGodDelete OnEventGodDelete;
@@ -281,10 +284,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
281 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 284 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
282 public event SimWideDeletesDelegate OnSimWideDeletes; 285 public event SimWideDeletesDelegate OnSimWideDeletes;
283 public event SendPostcard OnSendPostcard; 286 public event SendPostcard OnSendPostcard;
287 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
284 public event MuteListEntryUpdate OnUpdateMuteListEntry; 288 public event MuteListEntryUpdate OnUpdateMuteListEntry;
285 public event MuteListEntryRemove OnRemoveMuteListEntry; 289 public event MuteListEntryRemove OnRemoveMuteListEntry;
286 public event GodlikeMessage onGodlikeMessage; 290 public event GodlikeMessage onGodlikeMessage;
287 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 291 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
292 public event GenericCall2 OnUpdateThrottles;
288 293
289#pragma warning disable 0067 294#pragma warning disable 0067
290 public event GenericMessage OnGenericMessage; 295 public event GenericMessage OnGenericMessage;
@@ -333,7 +338,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
333 private PriorityQueue m_entityProps; 338 private PriorityQueue m_entityProps;
334 private Prioritizer m_prioritizer; 339 private Prioritizer m_prioritizer;
335 private bool m_disableFacelights = false; 340 private bool m_disableFacelights = false;
336 private volatile bool m_justEditedTerrain = false; 341
342 private bool m_VelocityInterpolate = false;
343 private const uint MaxTransferBytesPerPacket = 600;
344
337 /// <value> 345 /// <value>
338 /// List used in construction of data blocks for an object update packet. This is to stop us having to 346 /// List used in construction of data blocks for an object update packet. This is to stop us having to
339 /// continually recreate it. 347 /// continually recreate it.
@@ -345,14 +353,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
345 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 353 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
346 /// ownerless phantom. 354 /// ownerless phantom.
347 /// 355 ///
348 /// All manipulation of this set has to occur under a lock 356 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
349 /// 357 ///
350 /// </value> 358 /// </value>
351 protected HashSet<uint> m_killRecord; 359// protected HashSet<uint> m_killRecord;
352 360
353// protected HashSet<uint> m_attachmentsSent; 361// protected HashSet<uint> m_attachmentsSent;
354 362
355 private int m_animationSequenceNumber = 1; 363 private bool m_deliverPackets = true;
364
356 private bool m_SendLogoutPacketWhenClosing = true; 365 private bool m_SendLogoutPacketWhenClosing = true;
357 366
358 /// <summary> 367 /// <summary>
@@ -398,6 +407,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
398 get { return m_startpos; } 407 get { return m_startpos; }
399 set { m_startpos = value; } 408 set { m_startpos = value; }
400 } 409 }
410 public bool DeliverPackets
411 {
412 get { return m_deliverPackets; }
413 set {
414 m_deliverPackets = value;
415 m_udpClient.m_deliverPackets = value;
416 }
417 }
401 public UUID AgentId { get { return m_agentId; } } 418 public UUID AgentId { get { return m_agentId; } }
402 public ISceneAgent SceneAgent { get; set; } 419 public ISceneAgent SceneAgent { get; set; }
403 public UUID ActiveGroupId { get { return m_activeGroupID; } private set { m_activeGroupID = value; } } 420 public UUID ActiveGroupId { get { return m_activeGroupID; } private set { m_activeGroupID = value; } }
@@ -405,6 +422,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
405 public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } private set { m_activeGroupPowers = value; } } 422 public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } private set { m_activeGroupPowers = value; } }
406 public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } 423 public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
407 424
425 public int PingTimeMS
426 {
427 get
428 {
429 if (UDPClient != null)
430 return UDPClient.PingTimeMS;
431 return 0;
432 }
433 }
434
408 /// <summary> 435 /// <summary>
409 /// Entity update queues 436 /// Entity update queues
410 /// </summary> 437 /// </summary>
@@ -426,7 +453,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
426 public string Name { get { return FirstName + " " + LastName; } } 453 public string Name { get { return FirstName + " " + LastName; } }
427 454
428 public uint CircuitCode { get { return m_circuitCode; } } 455 public uint CircuitCode { get { return m_circuitCode; } }
429 public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } 456 public int NextAnimationSequenceNumber
457 {
458 get { return m_udpServer.NextAnimationSequenceNumber; }
459 }
430 460
431 /// <summary> 461 /// <summary>
432 /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to 462 /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to
@@ -447,7 +477,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
447 set { m_disableFacelights = value; } 477 set { m_disableFacelights = value; }
448 } 478 }
449 479
480 public List<uint> SelectedObjects {get; private set;}
481
450 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } } 482 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
483
451 484
452 #endregion Properties 485 #endregion Properties
453 486
@@ -465,6 +498,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
465// DebugPacketLevel = 1; 498// DebugPacketLevel = 1;
466 499
467 CloseSyncLock = new Object(); 500 CloseSyncLock = new Object();
501 SelectedObjects = new List<uint>();
468 502
469 RegisterInterface<IClientIM>(this); 503 RegisterInterface<IClientIM>(this);
470 RegisterInterface<IClientInventory>(this); 504 RegisterInterface<IClientInventory>(this);
@@ -474,7 +508,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
474 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); 508 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
475 m_entityProps = new PriorityQueue(m_scene.Entities.Count); 509 m_entityProps = new PriorityQueue(m_scene.Entities.Count);
476 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); 510 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
477 m_killRecord = new HashSet<uint>(); 511// m_killRecord = new HashSet<uint>();
478// m_attachmentsSent = new HashSet<uint>(); 512// m_attachmentsSent = new HashSet<uint>();
479 513
480 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 514 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
@@ -504,12 +538,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
504 538
505 #region Client Methods 539 #region Client Methods
506 540
541
542 /// <summary>
543 /// Close down the client view
544 /// </summary>
507 public void Close() 545 public void Close()
508 { 546 {
509 Close(false); 547 Close(true, false);
510 } 548 }
511 549
512 public void Close(bool force) 550 public void Close(bool sendStop, bool force)
513 { 551 {
514 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 552 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
515 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 553 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
@@ -526,7 +564,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
526 } 564 }
527 565
528 IsActive = false; 566 IsActive = false;
529 CloseWithoutChecks(); 567 CloseWithoutChecks(sendStop);
530 } 568 }
531 } 569 }
532 570
@@ -539,12 +577,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
539 /// 577 ///
540 /// Callers must lock ClosingSyncLock before calling. 578 /// Callers must lock ClosingSyncLock before calling.
541 /// </remarks> 579 /// </remarks>
542 public void CloseWithoutChecks() 580 public void CloseWithoutChecks(bool sendStop)
543 { 581 {
544 m_log.DebugFormat( 582 m_log.DebugFormat(
545 "[CLIENT]: Close has been called for {0} attached to scene {1}", 583 "[CLIENT]: Close has been called for {0} attached to scene {1}",
546 Name, m_scene.RegionInfo.RegionName); 584 Name, m_scene.RegionInfo.RegionName);
547 585
586 if (sendStop)
587 {
588 // Send the STOP packet
589 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
590 OutPacket(disable, ThrottleOutPacketType.Unknown);
591 }
592
548 // Shutdown the image manager 593 // Shutdown the image manager
549 ImageManager.Close(); 594 ImageManager.Close();
550 595
@@ -566,7 +611,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
566 611
567 // Disable UDP handling for this client 612 // Disable UDP handling for this client
568 m_udpClient.Shutdown(); 613 m_udpClient.Shutdown();
569 614
615
570 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 616 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
571 //GC.Collect(); 617 //GC.Collect();
572 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true)); 618 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
@@ -677,7 +723,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
677 if (!m_packetHandlers.ContainsKey(packetType)) 723 if (!m_packetHandlers.ContainsKey(packetType))
678 { 724 {
679 m_packetHandlers.Add( 725 m_packetHandlers.Add(
726<<<<<<< HEAD
680 packetType, new PacketProcessor() { method = handler, Async = doAsync, InEngine = inEngine }); 727 packetType, new PacketProcessor() { method = handler, Async = doAsync, InEngine = inEngine });
728=======
729 packetType, new PacketProcessor() { method = handler, Async = doAsync });
730>>>>>>> avn/ubitvar
681 result = true; 731 result = true;
682 } 732 }
683 } 733 }
@@ -858,6 +908,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
858 908
859 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) 909 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
860 { 910 {
911 m_thisAgentUpdateArgs.CameraAtAxis.X = float.MinValue;
912 m_thisAgentUpdateArgs.ControlFlags = uint.MaxValue;
913
861 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete); 914 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete);
862 mov.SimData.ChannelVersion = m_channelVersion; 915 mov.SimData.ChannelVersion = m_channelVersion;
863 mov.AgentData.SessionID = m_sessionId; 916 mov.AgentData.SessionID = m_sessionId;
@@ -893,7 +946,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
893 reply.ChatData.OwnerID = ownerID; 946 reply.ChatData.OwnerID = ownerID;
894 reply.ChatData.SourceID = fromAgentID; 947 reply.ChatData.SourceID = fromAgentID;
895 948
896 OutPacket(reply, ThrottleOutPacketType.Task); 949 OutPacket(reply, ThrottleOutPacketType.Unknown);
897 } 950 }
898 951
899 /// <summary> 952 /// <summary>
@@ -926,32 +979,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
926 msg.MessageBlock.Message = Util.StringToBytes1024(im.message); 979 msg.MessageBlock.Message = Util.StringToBytes1024(im.message);
927 msg.MessageBlock.BinaryBucket = im.binaryBucket; 980 msg.MessageBlock.BinaryBucket = im.binaryBucket;
928 981
929 if (im.message.StartsWith("[grouptest]")) 982 OutPacket(msg, ThrottleOutPacketType.Task);
930 { // this block is test code for implementing group IM - delete when group IM is finished
931 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
932 if (eq != null)
933 {
934 im.dialog = 17;
935
936 //eq.ChatterboxInvitation(
937 // new UUID("00000000-68f9-1111-024e-222222111123"),
938 // "OpenSimulator Testing", im.fromAgentID, im.message, im.toAgentID, im.fromAgentName, im.dialog, 0,
939 // false, 0, new Vector3(), 1, im.imSessionID, im.fromGroup, im.binaryBucket);
940
941 eq.ChatterboxInvitation(
942 new UUID("00000000-68f9-1111-024e-222222111123"),
943 "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0,
944 false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Util.StringToBytes256("OpenSimulator Testing"));
945
946 eq.ChatterBoxSessionAgentListUpdates(
947 new UUID("00000000-68f9-1111-024e-222222111123"),
948 new UUID(im.fromAgentID), new UUID(im.toAgentID), false, false, false);
949 }
950
951 Console.WriteLine("SendInstantMessage: " + msg);
952 }
953 else
954 OutPacket(msg, ThrottleOutPacketType.Task);
955 } 983 }
956 } 984 }
957 985
@@ -1182,6 +1210,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1182 OutPacket(GATRP, ThrottleOutPacketType.Task); 1210 OutPacket(GATRP, ThrottleOutPacketType.Task);
1183 } 1211 }
1184 1212
1213
1214 public virtual bool CanSendLayerData()
1215 {
1216 int n = m_udpClient.GetCatBytesInSendQueue(ThrottleOutPacketType.Land);
1217 if ( n > 100000)
1218 return false;
1219 return true;
1220 }
1221
1185 /// <summary> 1222 /// <summary>
1186 /// Send the region heightmap to the client 1223 /// Send the region heightmap to the client
1187 /// This method is only called when not doing intellegent terrain patch sending and 1224 /// This method is only called when not doing intellegent terrain patch sending and
@@ -1191,7 +1228,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1191 /// <param name="map">heightmap</param> 1228 /// <param name="map">heightmap</param>
1192 public virtual void SendLayerData(float[] map) 1229 public virtual void SendLayerData(float[] map)
1193 { 1230 {
1231<<<<<<< HEAD
1194 Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData(), "LLClientView.DoSendLayerData"); 1232 Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData(), "LLClientView.DoSendLayerData");
1233=======
1234 Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData());
1235
1236 // Send it sync, and async. It's not that much data
1237 // and it improves user experience just so much!
1238// DoSendLayerData(map);
1239>>>>>>> avn/ubitvar
1195 } 1240 }
1196 1241
1197 /// <summary> 1242 /// <summary>
@@ -1205,6 +1250,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1205 try 1250 try
1206 { 1251 {
1207 // Send LayerData in typerwriter pattern 1252 // Send LayerData in typerwriter pattern
1253<<<<<<< HEAD
1208 //for (int y = 0; y < 16; y++) 1254 //for (int y = 0; y < 16; y++)
1209 //{ 1255 //{
1210 // for (int x = 0; x < 16; x++) 1256 // for (int x = 0; x < 16; x++)
@@ -1215,6 +1261,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1215 1261
1216 // Send LayerData in a spiral pattern. Fun! 1262 // Send LayerData in a spiral pattern. Fun!
1217 SendLayerTopRight(map, 0, 0, map.SizeX/Constants.TerrainPatchSize-1, map.SizeY/Constants.TerrainPatchSize-1); 1263 SendLayerTopRight(map, 0, 0, map.SizeX/Constants.TerrainPatchSize-1, map.SizeY/Constants.TerrainPatchSize-1);
1264=======
1265 for (int y = 0; y < 16; y++)
1266 {
1267 for (int x = 0; x < 16; x++)
1268 {
1269 SendLayerData(x, y, map);
1270 }
1271 }
1272>>>>>>> avn/ubitvar
1218 } 1273 }
1219 catch (Exception e) 1274 catch (Exception e)
1220 { 1275 {
@@ -1222,16 +1277,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1222 } 1277 }
1223 } 1278 }
1224 1279
1280<<<<<<< HEAD
1225 private void SendLayerTopRight(TerrainData map, int x1, int y1, int x2, int y2) 1281 private void SendLayerTopRight(TerrainData map, int x1, int y1, int x2, int y2)
1282=======
1283 // Legacy form of invocation that passes around a bare data array.
1284 // Just ignore what was passed and use the real terrain info that is part of the scene.
1285 // As a HORRIBLE kludge in an attempt to not change the definition of IClientAPI,
1286 // there is a special form for specifying multiple terrain patches to send.
1287 // The form is to pass 'px' as negative the number of patches to send and to
1288 // pass the float array as pairs of patch X and Y coordinates. So, passing 'px'
1289 // as -2 and map= [3, 5, 8, 4] would mean to send two terrain heightmap patches
1290 // and the patches to send are <3,5> and <8,4>.
1291 public void SendLayerData(int px, int py, float[] map)
1292>>>>>>> avn/ubitvar
1226 { 1293 {
1227 // Row 1294 if (px >= 0)
1228 for (int i = x1; i <= x2; i++) 1295 {
1229 SendLayerData(i, y1, map); 1296 SendLayerData(px, py, m_scene.Heightmap.GetTerrainData());
1297 }
1298 else
1299 {
1300 int numPatches = -px;
1301 int[] xPatches = new int[numPatches];
1302 int[] yPatches = new int[numPatches];
1303 for (int pp = 0; pp < numPatches; pp++)
1304 {
1305 xPatches[pp] = (int)map[pp * 2];
1306 yPatches[pp] = (int)map[pp * 2 + 1];
1307 }
1230 1308
1231 // Column 1309 // DebugSendingPatches("SendLayerData", xPatches, yPatches);
1232 for (int j = y1 + 1; j <= y2; j++)
1233 SendLayerData(x2, j, map);
1234 1310
1311<<<<<<< HEAD
1235 if (x2 - x1 > 0 && y2 - y1 > 0) 1312 if (x2 - x1 > 0 && y2 - y1 > 0)
1236 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2); 1313 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1237 } 1314 }
@@ -1316,6 +1393,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1316 } 1393 }
1317 1394
1318 /// <summary> 1395 /// <summary>
1396=======
1397 SendLayerData(xPatches, yPatches, m_scene.Heightmap.GetTerrainData());
1398 }
1399 }
1400
1401 private void DebugSendingPatches(string pWho, int[] pX, int[] pY)
1402 {
1403 if (m_log.IsDebugEnabled)
1404 {
1405 int numPatches = pX.Length;
1406 string Xs = "";
1407 string Ys = "";
1408 for (int pp = 0; pp < numPatches; pp++)
1409 {
1410 Xs += String.Format("{0}", (int)pX[pp]) + ",";
1411 Ys += String.Format("{0}", (int)pY[pp]) + ",";
1412 }
1413 m_log.DebugFormat("{0} {1}: numPatches={2}, X={3}, Y={4}", LogHeader, pWho, numPatches, Xs, Ys);
1414 }
1415 }
1416
1417 /// <summary>
1418>>>>>>> avn/ubitvar
1319 /// Sends a terrain packet for the point specified. 1419 /// Sends a terrain packet for the point specified.
1320 /// This is a legacy call that has refarbed the terrain into a flat map of floats. 1420 /// This is a legacy call that has refarbed the terrain into a flat map of floats.
1321 /// We just use the terrain from the region we know about. 1421 /// We just use the terrain from the region we know about.
@@ -1367,6 +1467,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1367 } 1467 }
1368 } 1468 }
1369 1469
1470<<<<<<< HEAD
1370 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a 1471 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a
1371 // sub optimal editing experience. To alleviate this issue, when the user edits the terrain, we 1472 // sub optimal editing experience. To alleviate this issue, when the user edits the terrain, we
1372 // start skipping the queues until they're done editing the terrain. We also make them 1473 // start skipping the queues until they're done editing the terrain. We also make them
@@ -1395,6 +1496,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1395 layerpack.Header.Reliable = true; 1496 layerpack.Header.Reliable = true;
1396 OutPacket(layerpack, ThrottleOutPacketType.Land); 1497 OutPacket(layerpack, ThrottleOutPacketType.Land);
1397 } 1498 }
1499=======
1500 private void SendTheLayerPacket(LayerDataPacket layerpack)
1501 {
1502 OutPacket(layerpack, ThrottleOutPacketType.Land);
1503>>>>>>> avn/ubitvar
1398 } 1504 }
1399 1505
1400 /// <summary> 1506 /// <summary>
@@ -1735,11 +1841,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1735 pc.PingID.OldestUnacked = 0; 1841 pc.PingID.OldestUnacked = 0;
1736 1842
1737 OutPacket(pc, ThrottleOutPacketType.Unknown); 1843 OutPacket(pc, ThrottleOutPacketType.Unknown);
1844 UDPClient.m_lastStartpingTimeMS = Util.EnvironmentTickCount();
1738 } 1845 }
1739 1846
1740 public void SendKillObject(List<uint> localIDs) 1847 public void SendKillObject(List<uint> localIDs)
1741 { 1848 {
1742// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1849 // think we do need this
1850 // foreach (uint id in localIDs)
1851 // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
1852
1853 // remove pending entities
1854 lock (m_entityProps.SyncRoot)
1855 m_entityProps.Remove(localIDs);
1856 lock (m_entityUpdates.SyncRoot)
1857 m_entityUpdates.Remove(localIDs);
1743 1858
1744 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1859 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1745 // TODO: don't create new blocks if recycling an old packet 1860 // TODO: don't create new blocks if recycling an old packet
@@ -1752,28 +1867,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1752 kill.Header.Reliable = true; 1867 kill.Header.Reliable = true;
1753 kill.Header.Zerocoded = true; 1868 kill.Header.Zerocoded = true;
1754 1869
1755 if (localIDs.Count == 1 && m_scene.GetScenePresence(localIDs[0]) != null) 1870 OutPacket(kill, ThrottleOutPacketType.Task);
1756 { 1871 }
1757 OutPacket(kill, ThrottleOutPacketType.Task);
1758 }
1759 else
1760 {
1761 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race
1762 // condition where a kill can be processed before an out-of-date update for the same object.
1763 // ProcessEntityUpdates() also takes the m_killRecord lock.
1764 lock (m_killRecord)
1765 {
1766 foreach (uint localID in localIDs)
1767 m_killRecord.Add(localID);
1768
1769 // The throttle queue used here must match that being used for updates. Otherwise, there is a
1770 // chance that a kill packet put on a separate queue will be sent to the client before an existing
1771 // update packet on another queue. Receiving updates after kills results in unowned and undeletable
1772 // scene objects in a viewer until that viewer is relogged in.
1773 OutPacket(kill, ThrottleOutPacketType.Task);
1774 }
1775 }
1776 }
1777 1872
1778 /// <summary> 1873 /// <summary>
1779 /// Send information about the items contained in a folder to the client. 1874 /// Send information about the items contained in a folder to the client.
@@ -1895,7 +1990,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1895 newBlock.CreationDate = item.CreationDate; 1990 newBlock.CreationDate = item.CreationDate;
1896 newBlock.SalePrice = item.SalePrice; 1991 newBlock.SalePrice = item.SalePrice;
1897 newBlock.SaleType = item.SaleType; 1992 newBlock.SaleType = item.SaleType;
1898 newBlock.Flags = item.Flags; 1993 newBlock.Flags = item.Flags & 0x2000ff;
1899 1994
1900 newBlock.CRC = 1995 newBlock.CRC =
1901 Helpers.InventoryCRC(newBlock.CreationDate, newBlock.SaleType, 1996 Helpers.InventoryCRC(newBlock.CreationDate, newBlock.SaleType,
@@ -2151,7 +2246,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2151 itemBlock.GroupID = item.GroupID; 2246 itemBlock.GroupID = item.GroupID;
2152 itemBlock.GroupOwned = item.GroupOwned; 2247 itemBlock.GroupOwned = item.GroupOwned;
2153 itemBlock.GroupMask = item.GroupPermissions; 2248 itemBlock.GroupMask = item.GroupPermissions;
2154 itemBlock.Flags = item.Flags; 2249 itemBlock.Flags = item.Flags & 0x2000ff;
2155 itemBlock.SalePrice = item.SalePrice; 2250 itemBlock.SalePrice = item.SalePrice;
2156 itemBlock.SaleType = item.SaleType; 2251 itemBlock.SaleType = item.SaleType;
2157 itemBlock.CreationDate = item.CreationDate; 2252 itemBlock.CreationDate = item.CreationDate;
@@ -2218,7 +2313,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2218 bulkUpdate.ItemData[0].GroupID = item.GroupID; 2313 bulkUpdate.ItemData[0].GroupID = item.GroupID;
2219 bulkUpdate.ItemData[0].GroupOwned = item.GroupOwned; 2314 bulkUpdate.ItemData[0].GroupOwned = item.GroupOwned;
2220 bulkUpdate.ItemData[0].GroupMask = item.GroupPermissions; 2315 bulkUpdate.ItemData[0].GroupMask = item.GroupPermissions;
2221 bulkUpdate.ItemData[0].Flags = item.Flags; 2316 bulkUpdate.ItemData[0].Flags = item.Flags & 0x2000ff;
2222 bulkUpdate.ItemData[0].SalePrice = item.SalePrice; 2317 bulkUpdate.ItemData[0].SalePrice = item.SalePrice;
2223 bulkUpdate.ItemData[0].SaleType = item.SaleType; 2318 bulkUpdate.ItemData[0].SaleType = item.SaleType;
2224 2319
@@ -2234,9 +2329,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2234 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); 2329 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
2235 } 2330 }
2236 2331
2237 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2238 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) 2332 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
2239 { 2333 {
2334 SendInventoryItemCreateUpdate(Item, UUID.Zero, callbackId);
2335 }
2336
2337 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2338 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
2339 {
2240 const uint FULL_MASK_PERMISSIONS = (uint)0x7fffffff; 2340 const uint FULL_MASK_PERMISSIONS = (uint)0x7fffffff;
2241 2341
2242 UpdateCreateInventoryItemPacket InventoryReply 2342 UpdateCreateInventoryItemPacket InventoryReply
@@ -2246,6 +2346,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2246 // TODO: don't create new blocks if recycling an old packet 2346 // TODO: don't create new blocks if recycling an old packet
2247 InventoryReply.AgentData.AgentID = AgentId; 2347 InventoryReply.AgentData.AgentID = AgentId;
2248 InventoryReply.AgentData.SimApproved = true; 2348 InventoryReply.AgentData.SimApproved = true;
2349 InventoryReply.AgentData.TransactionID = transactionID;
2249 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; 2350 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
2250 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); 2351 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
2251 InventoryReply.InventoryData[0].ItemID = Item.ID; 2352 InventoryReply.InventoryData[0].ItemID = Item.ID;
@@ -2266,7 +2367,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2266 InventoryReply.InventoryData[0].GroupID = Item.GroupID; 2367 InventoryReply.InventoryData[0].GroupID = Item.GroupID;
2267 InventoryReply.InventoryData[0].GroupOwned = Item.GroupOwned; 2368 InventoryReply.InventoryData[0].GroupOwned = Item.GroupOwned;
2268 InventoryReply.InventoryData[0].GroupMask = Item.GroupPermissions; 2369 InventoryReply.InventoryData[0].GroupMask = Item.GroupPermissions;
2269 InventoryReply.InventoryData[0].Flags = Item.Flags; 2370 InventoryReply.InventoryData[0].Flags = Item.Flags & 0x2000ff;
2270 InventoryReply.InventoryData[0].SalePrice = Item.SalePrice; 2371 InventoryReply.InventoryData[0].SalePrice = Item.SalePrice;
2271 InventoryReply.InventoryData[0].SaleType = Item.SaleType; 2372 InventoryReply.InventoryData[0].SaleType = Item.SaleType;
2272 InventoryReply.InventoryData[0].CreationDate = Item.CreationDate; 2373 InventoryReply.InventoryData[0].CreationDate = Item.CreationDate;
@@ -2315,16 +2416,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2315 replytask.InventoryData.TaskID = taskID; 2416 replytask.InventoryData.TaskID = taskID;
2316 replytask.InventoryData.Serial = serial; 2417 replytask.InventoryData.Serial = serial;
2317 replytask.InventoryData.Filename = fileName; 2418 replytask.InventoryData.Filename = fileName;
2318 OutPacket(replytask, ThrottleOutPacketType.Asset); 2419 OutPacket(replytask, ThrottleOutPacketType.Task);
2319 } 2420 }
2320 2421
2321 public void SendXferPacket(ulong xferID, uint packet, byte[] data) 2422 public void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory)
2322 { 2423 {
2424 ThrottleOutPacketType type = ThrottleOutPacketType.Asset;
2425 if (isTaskInventory)
2426 type = ThrottleOutPacketType.Task;
2427
2323 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket); 2428 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket);
2324 sendXfer.XferID.ID = xferID; 2429 sendXfer.XferID.ID = xferID;
2325 sendXfer.XferID.Packet = packet; 2430 sendXfer.XferID.Packet = packet;
2326 sendXfer.DataPacket.Data = data; 2431 sendXfer.DataPacket.Data = data;
2327 OutPacket(sendXfer, ThrottleOutPacketType.Asset); 2432 OutPacket(sendXfer, type);
2328 } 2433 }
2329 2434
2330 public void SendAbortXferPacket(ulong xferID) 2435 public void SendAbortXferPacket(ulong xferID)
@@ -2385,9 +2490,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2385 { 2490 {
2386 if (agentid == AgentId) 2491 if (agentid == AgentId)
2387 { 2492 {
2493<<<<<<< HEAD
2388 ActiveGroupId = activegroupid; 2494 ActiveGroupId = activegroupid;
2389 ActiveGroupName = groupname; 2495 ActiveGroupName = groupname;
2390 ActiveGroupPowers = grouppowers; 2496 ActiveGroupPowers = grouppowers;
2497=======
2498 m_activeGroupID = activegroupid;
2499 m_activeGroupName = groupname;
2500 m_activeGroupPowers = grouppowers;
2501>>>>>>> avn/ubitvar
2391 } 2502 }
2392 2503
2393 AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate); 2504 AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate);
@@ -2514,6 +2625,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2514 OutPacket(sound, ThrottleOutPacketType.Task); 2625 OutPacket(sound, ThrottleOutPacketType.Task);
2515 } 2626 }
2516 2627
2628 public void SendTransferAbort(TransferRequestPacket transferRequest)
2629 {
2630 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2631 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2632 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2633 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2634 OutPacket(abort, ThrottleOutPacketType.Task);
2635 }
2636
2517 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2637 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2518 { 2638 {
2519 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2639 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -2819,6 +2939,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2819 float friction = part.Friction; 2939 float friction = part.Friction;
2820 float bounce = part.Restitution; 2940 float bounce = part.Restitution;
2821 float gravmod = part.GravityModifier; 2941 float gravmod = part.GravityModifier;
2942
2822 eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId); 2943 eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId);
2823 } 2944 }
2824 } 2945 }
@@ -2889,8 +3010,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2889 LogHeader, req.AssetInf.ID, req.AssetInf.Metadata.ContentType); 3010 LogHeader, req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
2890 return; 3011 return;
2891 } 3012 }
3013 int WearableOut = 0;
3014 bool isWearable = false;
3015
3016 if (req.AssetInf != null)
3017 isWearable =
3018 ((AssetType) req.AssetInf.Type ==
3019 AssetType.Bodypart || (AssetType) req.AssetInf.Type == AssetType.Clothing);
2892 3020
2893 //m_log.Debug("sending asset " + req.RequestAssetID); 3021
3022 //m_log.Debug("sending asset " + req.RequestAssetID + ", iswearable: " + isWearable);
3023
3024
3025 //if (isWearable)
3026 // m_log.Debug((AssetType)req.AssetInf.Type);
3027
2894 TransferInfoPacket Transfer = new TransferInfoPacket(); 3028 TransferInfoPacket Transfer = new TransferInfoPacket();
2895 Transfer.TransferInfo.ChannelType = 2; 3029 Transfer.TransferInfo.ChannelType = 2;
2896 Transfer.TransferInfo.Status = 0; 3030 Transfer.TransferInfo.Status = 0;
@@ -2912,7 +3046,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2912 Transfer.TransferInfo.Size = req.AssetInf.Data.Length; 3046 Transfer.TransferInfo.Size = req.AssetInf.Data.Length;
2913 Transfer.TransferInfo.TransferID = req.TransferRequestID; 3047 Transfer.TransferInfo.TransferID = req.TransferRequestID;
2914 Transfer.Header.Zerocoded = true; 3048 Transfer.Header.Zerocoded = true;
2915 OutPacket(Transfer, ThrottleOutPacketType.Asset); 3049 OutPacket(Transfer, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset);
2916 3050
2917 if (req.NumPackets == 1) 3051 if (req.NumPackets == 1)
2918 { 3052 {
@@ -2923,12 +3057,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2923 TransferPacket.TransferData.Data = req.AssetInf.Data; 3057 TransferPacket.TransferData.Data = req.AssetInf.Data;
2924 TransferPacket.TransferData.Status = 1; 3058 TransferPacket.TransferData.Status = 1;
2925 TransferPacket.Header.Zerocoded = true; 3059 TransferPacket.Header.Zerocoded = true;
2926 OutPacket(TransferPacket, ThrottleOutPacketType.Asset); 3060 OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset);
2927 } 3061 }
2928 else 3062 else
2929 { 3063 {
2930 int processedLength = 0; 3064 int processedLength = 0;
2931 int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; 3065// int maxChunkSize = Settings.MAX_PACKET_SIZE - 100;
3066
3067 int maxChunkSize = (int) MaxTransferBytesPerPacket;
2932 int packetNumber = 0; 3068 int packetNumber = 0;
2933 3069
2934 while (processedLength < req.AssetInf.Data.Length) 3070 while (processedLength < req.AssetInf.Data.Length)
@@ -2954,7 +3090,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2954 TransferPacket.TransferData.Status = 1; 3090 TransferPacket.TransferData.Status = 1;
2955 } 3091 }
2956 TransferPacket.Header.Zerocoded = true; 3092 TransferPacket.Header.Zerocoded = true;
2957 OutPacket(TransferPacket, ThrottleOutPacketType.Asset); 3093 OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset);
2958 3094
2959 processedLength += chunkSize; 3095 processedLength += chunkSize;
2960 packetNumber++; 3096 packetNumber++;
@@ -2999,7 +3135,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2999 reply.Data.ParcelID = parcelID; 3135 reply.Data.ParcelID = parcelID;
3000 reply.Data.OwnerID = land.OwnerID; 3136 reply.Data.OwnerID = land.OwnerID;
3001 reply.Data.Name = Utils.StringToBytes(land.Name); 3137 reply.Data.Name = Utils.StringToBytes(land.Name);
3002 reply.Data.Desc = Utils.StringToBytes(land.Description); 3138 if (land != null && land.Description != null && land.Description != String.Empty)
3139 reply.Data.Desc = Utils.StringToBytes(land.Description.Substring(0, land.Description.Length > 254 ? 254: land.Description.Length));
3140 else
3141 reply.Data.Desc = new Byte[0];
3003 reply.Data.ActualArea = land.Area; 3142 reply.Data.ActualArea = land.Area;
3004 reply.Data.BillableArea = land.Area; // TODO: what is this? 3143 reply.Data.BillableArea = land.Area; // TODO: what is this?
3005 3144
@@ -3706,24 +3845,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3706 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count]; 3845 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count];
3707 AgentWearablesUpdatePacket.WearableDataBlock awb; 3846 AgentWearablesUpdatePacket.WearableDataBlock awb;
3708 int idx = 0; 3847 int idx = 0;
3709 for (int i = 0; i < wearables.Length; i++) 3848
3710 { 3849 for (int i = 0; i < wearables.Length; i++)
3711 for (int j = 0; j < wearables[i].Count; j++) 3850 {
3712 { 3851 for (int j = 0; j < wearables[i].Count; j++)
3713 awb = new AgentWearablesUpdatePacket.WearableDataBlock(); 3852 {
3714 awb.WearableType = (byte)i; 3853 awb = new AgentWearablesUpdatePacket.WearableDataBlock();
3715 awb.AssetID = wearables[i][j].AssetID; 3854 awb.WearableType = (byte) i;
3716 awb.ItemID = wearables[i][j].ItemID; 3855 awb.AssetID = wearables[i][j].AssetID;
3717 aw.WearableData[idx] = awb; 3856 awb.ItemID = wearables[i][j].ItemID;
3718 idx++; 3857 aw.WearableData[idx] = awb;
3719 3858 idx++;
3720// m_log.DebugFormat( 3859
3721// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", 3860 // m_log.DebugFormat(
3722// awb.ItemID, awb.AssetID, i, Name); 3861 // "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}",
3723 } 3862 // awb.ItemID, awb.AssetID, i, Name);
3724 } 3863 }
3864 }
3725 3865
3726 OutPacket(aw, ThrottleOutPacketType.Task); 3866 OutPacket(aw, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3727 } 3867 }
3728 3868
3729 public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) 3869 public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry)
@@ -3748,9 +3888,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3748 avp.Sender.IsTrial = false; 3888 avp.Sender.IsTrial = false;
3749 avp.Sender.ID = agentID; 3889 avp.Sender.ID = agentID;
3750 avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0]; 3890 avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0];
3891<<<<<<< HEAD
3751 avp.AppearanceHover = new AvatarAppearancePacket.AppearanceHoverBlock[0]; 3892 avp.AppearanceHover = new AvatarAppearancePacket.AppearanceHoverBlock[0];
3893=======
3894
3895 // this need be use in future
3896 // avp.AppearanceData[0].AppearanceVersion = 0;
3897 // avp.AppearanceData[0].CofVersion = 0;
3898
3899>>>>>>> avn/ubitvar
3752 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); 3900 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString());
3753 OutPacket(avp, ThrottleOutPacketType.Task); 3901 OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3754 } 3902 }
3755 3903
3756 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 3904 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
@@ -3778,7 +3926,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3778 ani.AnimationSourceList[i].ObjectID = objectIDs[i]; 3926 ani.AnimationSourceList[i].ObjectID = objectIDs[i];
3779 } 3927 }
3780 ani.Header.Reliable = false; 3928 ani.Header.Reliable = false;
3781 OutPacket(ani, ThrottleOutPacketType.Task); 3929 OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3782 } 3930 }
3783 3931
3784 #endregion 3932 #endregion
@@ -3807,7 +3955,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3807 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; 3955 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3808 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); 3956 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence);
3809 3957
3810 OutPacket(objupdate, ThrottleOutPacketType.Task); 3958 OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3811 3959
3812 // We need to record the avatar local id since the root prim of an attachment points to this. 3960 // We need to record the avatar local id since the root prim of an attachment points to this.
3813// m_attachmentsSent.Add(avatar.LocalId); 3961// m_attachmentsSent.Add(avatar.LocalId);
@@ -3866,10 +4014,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3866 /// </summary> 4014 /// </summary>
3867 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 4015 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3868 { 4016 {
4017<<<<<<< HEAD
3869 if (entity.UUID == m_agentId && !updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 4018 if (entity.UUID == m_agentId && !updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3870 { 4019 {
3871 ImprovedTerseObjectUpdatePacket packet 4020 ImprovedTerseObjectUpdatePacket packet
3872 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 4021 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
4022=======
4023 if (entity is SceneObjectPart)
4024 {
4025 SceneObjectPart e = (SceneObjectPart)entity;
4026 SceneObjectGroup g = e.ParentGroup;
4027 if (g.HasPrivateAttachmentPoint && g.OwnerID != AgentId)
4028 return; // Don't send updates for other people's HUDs
4029 }
4030
4031 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
4032>>>>>>> avn/ubitvar
3873 4033
3874 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4034 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3875 packet.RegionData.TimeDilation = Utils.FloatToUInt16(1, 0.0f, 1.0f); 4035 packet.RegionData.TimeDilation = Utils.FloatToUInt16(1, 0.0f, 1.0f);
@@ -3887,6 +4047,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3887 } 4047 }
3888 } 4048 }
3889 4049
4050
3890 /// <summary> 4051 /// <summary>
3891 /// Requeue an EntityUpdate when it was not acknowledged by the client. 4052 /// Requeue an EntityUpdate when it was not acknowledged by the client.
3892 /// We will update the priority and put it in the correct queue, merging update flags 4053 /// We will update the priority and put it in the correct queue, merging update flags
@@ -3894,8 +4055,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3894 /// The original update time is used for the merged update. 4055 /// The original update time is used for the merged update.
3895 /// </summary> 4056 /// </summary>
3896 private void ResendPrimUpdate(EntityUpdate update) 4057 private void ResendPrimUpdate(EntityUpdate update)
3897 { 4058 {
3898 // If the update exists in priority queue, it will be updated. 4059 // If the update exists in priority queue, it will be updated.
3899 // If it does not exist then it will be added with the current (rather than its original) priority 4060 // If it does not exist then it will be added with the current (rather than its original) priority
3900 uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity); 4061 uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity);
3901 4062
@@ -3919,7 +4080,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3919 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); 4080 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
3920 4081
3921 // Count this as a resent packet since we are going to requeue all of the updates contained in it 4082 // Count this as a resent packet since we are going to requeue all of the updates contained in it
3922 Interlocked.Increment(ref m_udpClient.PacketsResent); 4083 Interlocked.Increment(ref m_udpClient.PacketsResent);
3923 4084
3924 // We're not going to worry about interlock yet since its not currently critical that this total count 4085 // We're not going to worry about interlock yet since its not currently critical that this total count
3925 // is 100% correct 4086 // is 100% correct
@@ -3928,18 +4089,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3928 foreach (EntityUpdate update in updates) 4089 foreach (EntityUpdate update in updates)
3929 ResendPrimUpdate(update); 4090 ResendPrimUpdate(update);
3930 } 4091 }
3931 4092
3932// OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
3933// OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
3934// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3935// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3936//
3937// OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3938// OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3939// OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3940// OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3941
3942
3943 private void ProcessEntityUpdates(int maxUpdates) 4093 private void ProcessEntityUpdates(int maxUpdates)
3944 { 4094 {
3945 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); 4095 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@@ -3952,15 +4102,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3952 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 4102 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3953 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 4103 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3954 4104
3955// objectUpdateBlocks.Value.Clear();
3956// compressedUpdateBlocks.Value.Clear();
3957// terseUpdateBlocks.Value.Clear();
3958// terseAgentUpdateBlocks.Value.Clear();
3959// objectUpdates.Value.Clear();
3960// compressedUpdates.Value.Clear();
3961// terseUpdates.Value.Clear();
3962// terseAgentUpdates.Value.Clear();
3963
3964 // Check to see if this is a flush 4105 // Check to see if this is a flush
3965 if (maxUpdates <= 0) 4106 if (maxUpdates <= 0)
3966 { 4107 {
@@ -3971,54 +4112,72 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3971 4112
3972 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 4113 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3973 // condition where a kill can be processed before an out-of-date update for the same object. 4114 // condition where a kill can be processed before an out-of-date update for the same object.
3974 lock (m_killRecord) 4115 float avgTimeDilation = 1.0f;
4116 IEntityUpdate iupdate;
4117 Int32 timeinqueue; // this is just debugging code & can be dropped later
4118
4119 while (updatesThisCall < maxUpdates)
3975 { 4120 {
3976 float avgTimeDilation = 1.0f; 4121 lock (m_entityUpdates.SyncRoot)
3977 IEntityUpdate iupdate; 4122 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3978 Int32 timeinqueue; // this is just debugging code & can be dropped later 4123 break;
4124
4125 EntityUpdate update = (EntityUpdate)iupdate;
4126
4127 avgTimeDilation += update.TimeDilation;
4128 avgTimeDilation *= 0.5f;
3979 4129
3980 while (updatesThisCall < maxUpdates) 4130 if (update.Entity is SceneObjectPart)
3981 { 4131 {
3982 lock (m_entityUpdates.SyncRoot) 4132 SceneObjectPart part = (SceneObjectPart)update.Entity;
3983 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3984 break;
3985 4133
3986 EntityUpdate update = (EntityUpdate)iupdate; 4134 if (part.ParentGroup.IsDeleted || part.ParentGroup.inTransit)
3987 4135 continue;
3988 avgTimeDilation += update.TimeDilation;
3989 avgTimeDilation *= 0.5f;
3990 4136
3991 if (update.Entity is SceneObjectPart) 4137 if (part.ParentGroup.IsAttachment)
3992 { 4138 { // Someone else's HUD, why are we getting these?
3993 SceneObjectPart part = (SceneObjectPart)update.Entity; 4139 if (part.ParentGroup.OwnerID != AgentId && part.ParentGroup.HasPrivateAttachmentPoint)
3994
3995 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3996 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3997 // safety measure.
3998 //
3999 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
4000 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
4001 // updates and kills on different threads with different scheduling strategies, hence this protection.
4002 //
4003 // This doesn't appear to apply to child prims - a client will happily ignore these updates
4004 // after the root prim has been deleted.
4005 if (m_killRecord.Contains(part.LocalId))
4006 {
4007 // m_log.WarnFormat(
4008 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted",
4009 // part.LocalId, Name);
4010 continue; 4140 continue;
4011 } 4141 ScenePresence sp;
4012 4142 // Owner is not in the sim, don't update it to
4013 if (part.ParentGroup.IsAttachment && m_disableFacelights) 4143 // anyone
4144 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
4145 continue;
4146
4147 List<SceneObjectGroup> atts = sp.GetAttachments();
4148 bool found = false;
4149 foreach (SceneObjectGroup att in atts)
4014 { 4150 {
4015 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 4151 if (att == part.ParentGroup)
4016 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
4017 { 4152 {
4018 part.Shape.LightEntry = false; 4153 found = true;
4154 break;
4019 } 4155 }
4020 } 4156 }
4021 4157
4158 // It's an attachment of a valid avatar, but
4159 // doesn't seem to be attached, skip
4160 if (!found)
4161 continue;
4162
4163 // On vehicle crossing, the attachments are received
4164 // while the avatar is still a child. Don't send
4165 // updates here because the LocalId has not yet
4166 // been updated and the viewer will derender the
4167 // attachments until the avatar becomes root.
4168 if (sp.IsChildAgent)
4169 continue;
4170
4171 }
4172
4173 if (part.ParentGroup.IsAttachment && m_disableFacelights)
4174 {
4175 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
4176 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
4177 {
4178 part.Shape.LightEntry = false;
4179 }
4180
4022 if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh)) 4181 if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh))
4023 { 4182 {
4024 // Ensure that mesh has at least 8 valid faces 4183 // Ensure that mesh has at least 8 valid faces
@@ -4027,233 +4186,216 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4027 part.Shape.ProfileHollow = 27500; 4186 part.Shape.ProfileHollow = 27500;
4028 } 4187 }
4029 } 4188 }
4030 4189
4031 #region UpdateFlags to packet type conversion 4190 if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh))
4032
4033 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
4034
4035 bool canUseCompressed = true;
4036 bool canUseImproved = true;
4037
4038 // Compressed object updates only make sense for LL primitives
4039 if (!(update.Entity is SceneObjectPart))
4040 { 4191 {
4041 canUseCompressed = false; 4192 // Ensure that mesh has at least 8 valid faces
4193 part.Shape.ProfileBegin = 12500;
4194 part.Shape.ProfileEnd = 0;
4195 part.Shape.ProfileHollow = 27500;
4042 } 4196 }
4043 4197 }
4044 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 4198 else if (update.Entity is ScenePresence)
4199 {
4200 ScenePresence presence = (ScenePresence)update.Entity;
4201 if (presence.IsDeleted)
4202 continue;
4203 // If ParentUUID is not UUID.Zero and ParentID is 0, this
4204 // avatar is in the process of crossing regions while
4205 // sat on an object. In this state, we don't want any
4206 // updates because they will visually orbit the avatar.
4207 // Update will be forced once crossing is completed anyway.
4208 if (presence.ParentUUID != UUID.Zero && presence.ParentID == 0)
4209 continue;
4210 }
4211
4212 ++updatesThisCall;
4213
4214 #region UpdateFlags to packet type conversion
4215
4216 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
4217
4218 bool canUseCompressed = true;
4219 bool canUseImproved = true;
4220
4221 // Compressed object updates only make sense for LL primitives
4222 if (!(update.Entity is SceneObjectPart))
4223 {
4224 canUseCompressed = false;
4225 }
4226
4227 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
4228 {
4229 canUseCompressed = false;
4230 canUseImproved = false;
4231 }
4232 else
4233 {
4234 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
4235 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
4236 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
4237 updateFlags.HasFlag(PrimUpdateFlags.Joint))
4045 { 4238 {
4046 canUseCompressed = false; 4239 canUseCompressed = false;
4047 canUseImproved = false;
4048 } 4240 }
4049 else 4241
4242 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
4243 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
4244 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
4245 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
4246 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
4247 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
4248 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
4249 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
4250 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
4251 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
4252 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
4253 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
4254 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
4255 updateFlags.HasFlag(PrimUpdateFlags.Joint))
4050 { 4256 {
4051 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || 4257 canUseImproved = false;
4052 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
4053 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
4054 updateFlags.HasFlag(PrimUpdateFlags.Joint))
4055 {
4056 canUseCompressed = false;
4057 }
4058
4059 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
4060 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
4061 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
4062 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
4063 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
4064 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
4065 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
4066 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
4067 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
4068 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
4069 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
4070 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
4071 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
4072 updateFlags.HasFlag(PrimUpdateFlags.Joint))
4073 {
4074 canUseImproved = false;
4075 }
4076 } 4258 }
4259 }
4077 4260
4078 #endregion UpdateFlags to packet type conversion 4261 #endregion UpdateFlags to packet type conversion
4079
4080 #region Block Construction
4081
4082 // TODO: Remove this once we can build compressed updates
4083 canUseCompressed = false;
4084
4085 if (!canUseImproved && !canUseCompressed)
4086 {
4087 ObjectUpdatePacket.ObjectDataBlock updateBlock;
4088 4262
4089 if (update.Entity is ScenePresence) 4263 #region Block Construction
4090 {
4091 updateBlock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
4092 }
4093 else
4094 {
4095 SceneObjectPart part = (SceneObjectPart)update.Entity;
4096 updateBlock = CreatePrimUpdateBlock(part, AgentId);
4097
4098 // If the part has become a private hud since the update was scheduled then we do not
4099 // want to send it to other avatars.
4100 if (part.ParentGroup.IsAttachment
4101 && part.ParentGroup.HasPrivateAttachmentPoint
4102 && part.ParentGroup.AttachedAvatar != AgentId)
4103 continue;
4104
4105 // If the part has since been deleted, then drop the update. In the case of attachments,
4106 // this is to avoid spurious updates to other viewers since post-processing of attachments
4107 // has to change the IsAttachment flag for various reasons (which will end up in a pass
4108 // of the test above).
4109 //
4110 // Actual deletions (kills) happen in another method.
4111 if (part.ParentGroup.IsDeleted)
4112 continue;
4113 }
4114 4264
4115 objectUpdateBlocks.Value.Add(updateBlock); 4265 // TODO: Remove this once we can build compressed updates
4116 objectUpdates.Value.Add(update); 4266 canUseCompressed = false;
4117 }
4118 else if (!canUseImproved)
4119 {
4120 SceneObjectPart part = (SceneObjectPart)update.Entity;
4121 ObjectUpdateCompressedPacket.ObjectDataBlock compressedBlock
4122 = CreateCompressedUpdateBlock(part, updateFlags);
4123
4124 // If the part has since been deleted, then drop the update. In the case of attachments,
4125 // this is to avoid spurious updates to other viewers since post-processing of attachments
4126 // has to change the IsAttachment flag for various reasons (which will end up in a pass
4127 // of the test above).
4128 //
4129 // Actual deletions (kills) happen in another method.
4130 if (part.ParentGroup.IsDeleted)
4131 continue;
4132 4267
4133 compressedUpdateBlocks.Value.Add(compressedBlock); 4268 if (!canUseImproved && !canUseCompressed)
4134 compressedUpdates.Value.Add(update); 4269 {
4270 if (update.Entity is ScenePresence)
4271 {
4272 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
4135 } 4273 }
4136 else 4274 else
4137 { 4275 {
4138 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 4276 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
4139 { 4277 }
4140 // Self updates go into a special list 4278 }
4141 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); 4279 else if (!canUseImproved)
4142 terseAgentUpdates.Value.Add(update); 4280 {
4143 } 4281 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
4144 else 4282 }
4145 { 4283 else
4146 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseUpdateBlock 4284 {
4147 = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)); 4285 if (update.Entity is ScenePresence)
4286 // ALL presence updates go into a special list
4287 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
4288 else
4289 // Everything else goes here
4290 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
4291 }
4148 4292
4149 // Everything else goes here 4293 #endregion Block Construction
4150 if (update.Entity is SceneObjectPart) 4294 }
4151 {
4152 SceneObjectPart part = (SceneObjectPart)update.Entity;
4153
4154 // If the part has become a private hud since the update was scheduled then we do not
4155 // want to send it to other avatars.
4156 if (part.ParentGroup.IsAttachment
4157 && part.ParentGroup.HasPrivateAttachmentPoint
4158 && part.ParentGroup.AttachedAvatar != AgentId)
4159 continue;
4160
4161 // If the part has since been deleted, then drop the update. In the case of attachments,
4162 // this is to avoid spurious updates to other viewers since post-processing of attachments
4163 // has to change the IsAttachment flag for various reasons (which will end up in a pass
4164 // of the test above).
4165 //
4166 // Actual deletions (kills) happen in another method.
4167 if (part.ParentGroup.IsDeleted)
4168 continue;
4169 }
4170 4295
4171 terseUpdateBlocks.Value.Add(terseUpdateBlock); 4296 #region Packet Sending
4172 terseUpdates.Value.Add(update); 4297
4173 } 4298// const float TIME_DILATION = 1.0f;
4174 } 4299 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
4300
4301 if (terseAgentUpdateBlocks.IsValueCreated)
4302 {
4303 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
4304
4305 ImprovedTerseObjectUpdatePacket packet
4306 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
4307 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4308 packet.RegionData.TimeDilation = timeDilation;
4309 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4175 4310
4176 ++updatesThisCall; 4311 for (int i = 0; i < blocks.Count; i++)
4312 packet.ObjectData[i] = blocks[i];
4313
4314 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4315 }
4316
4317 if (objectUpdateBlocks.IsValueCreated)
4318 {
4319 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
4177 4320
4178 #endregion Block Construction 4321 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
4179 } 4322 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4323 packet.RegionData.TimeDilation = timeDilation;
4324 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4180 4325
4181 #region Packet Sending 4326 for (int i = 0; i < blocks.Count; i++)
4182 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 4327 packet.ObjectData[i] = blocks[i];
4328
4329 OutPacket(packet, ThrottleOutPacketType.Task, true);
4330 }
4331
4332 if (compressedUpdateBlocks.IsValueCreated)
4333 {
4334 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
4335
4336 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
4337 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4338 packet.RegionData.TimeDilation = timeDilation;
4339 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
4183 4340
4184 if (terseAgentUpdateBlocks.IsValueCreated) 4341 for (int i = 0; i < blocks.Count; i++)
4185 { 4342 packet.ObjectData[i] = blocks[i];
4186 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 4343
4344 OutPacket(packet, ThrottleOutPacketType.Task, true);
4345 }
4346
4347 if (terseUpdateBlocks.IsValueCreated)
4348 {
4349 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4350
4351 ImprovedTerseObjectUpdatePacket packet
4352 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4353 PacketType.ImprovedTerseObjectUpdate);
4354 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4355 packet.RegionData.TimeDilation = timeDilation;
4356 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4357
4358 for (int i = 0; i < blocks.Count; i++)
4359 packet.ObjectData[i] = blocks[i];
4187 4360
4188 ImprovedTerseObjectUpdatePacket packet 4361 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4189 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 4362 }
4190 4363
4191 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4364 #endregion Packet Sending
4192 packet.RegionData.TimeDilation = timeDilation; 4365 }
4193 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4194 4366
4195 for (int i = 0; i < blocks.Count; i++) 4367 // hack.. dont use
4196 packet.ObjectData[i] = blocks[i]; 4368 public void SendPartFullUpdate(ISceneEntity ent, uint? parentID)
4197 // If any of the packets created from this call go unacknowledged, all of the updates will be resent 4369 {
4198 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); }); 4370 if (ent is SceneObjectPart)
4199 } 4371 {
4372 SceneObjectPart part = (SceneObjectPart)ent;
4373 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
4374 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4375 packet.RegionData.TimeDilation = 1;
4376 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
4200 4377
4201 if (objectUpdateBlocks.IsValueCreated) 4378 ObjectUpdatePacket.ObjectDataBlock blk = CreatePrimUpdateBlock(part, this.m_agentId);
4379 if (parentID.HasValue)
4202 { 4380 {
4203 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; 4381 blk.ParentID = parentID.Value;
4204
4205 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
4206 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4207 packet.RegionData.TimeDilation = timeDilation;
4208 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4209
4210 for (int i = 0; i < blocks.Count; i++)
4211 packet.ObjectData[i] = blocks[i];
4212 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
4213 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
4214 }
4215
4216 if (compressedUpdateBlocks.IsValueCreated)
4217 {
4218 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
4219
4220 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
4221 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4222 packet.RegionData.TimeDilation = timeDilation;
4223 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
4224
4225 for (int i = 0; i < blocks.Count; i++)
4226 packet.ObjectData[i] = blocks[i];
4227 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
4228 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
4229 } 4382 }
4230 4383
4231 if (terseUpdateBlocks.IsValueCreated) 4384 packet.ObjectData[0] = blk;
4232 {
4233 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4234
4235 ImprovedTerseObjectUpdatePacket packet
4236 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4237 PacketType.ImprovedTerseObjectUpdate);
4238 4385
4239 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4386 OutPacket(packet, ThrottleOutPacketType.Task, true);
4240 packet.RegionData.TimeDilation = timeDilation;
4241 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4242
4243 for (int i = 0; i < blocks.Count; i++)
4244 packet.ObjectData[i] = blocks[i];
4245 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
4246 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4247 }
4248 } 4387 }
4388<<<<<<< HEAD
4249 4389
4250// m_log.DebugFormat( 4390// m_log.DebugFormat(
4251// "[LLCLIENTVIEW]: Sent {0} updates in ProcessEntityUpdates() for {1} {2} in {3}", 4391// "[LLCLIENTVIEW]: Sent {0} updates in ProcessEntityUpdates() for {1} {2} in {3}",
4252// updatesThisCall, Name, SceneAgent.IsChildAgent ? "child" : "root", Scene.Name); 4392// updatesThisCall, Name, SceneAgent.IsChildAgent ? "child" : "root", Scene.Name);
4253// 4393//
4254 #endregion Packet Sending 4394 #endregion Packet Sending
4395=======
4396>>>>>>> avn/ubitvar
4255 } 4397 }
4256 4398
4257 public void ReprioritizeUpdates() 4399 public void ReprioritizeUpdates()
4258 { 4400 {
4259 lock (m_entityUpdates.SyncRoot) 4401 lock (m_entityUpdates.SyncRoot)
@@ -4572,11 +4714,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4572 4714
4573 // Pass in the delegate so that if this packet needs to be resent, we send the current properties 4715 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4574 // of the object rather than the properties when the packet was created 4716 // of the object rather than the properties when the packet was created
4575 OutPacket(packet, ThrottleOutPacketType.Task, true, 4717 // HACK : Remove intelligent resending until it's fixed in core
4576 delegate(OutgoingPacket oPacket) 4718 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4577 { 4719 // delegate(OutgoingPacket oPacket)
4578 ResendPropertyUpdates(updates, oPacket); 4720 // {
4579 }); 4721 // ResendPropertyUpdates(updates, oPacket);
4722 // });
4723 OutPacket(packet, ThrottleOutPacketType.Task, true);
4580 4724
4581 // pbcnt += blocks.Count; 4725 // pbcnt += blocks.Count;
4582 // ppcnt++; 4726 // ppcnt++;
@@ -4602,11 +4746,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4602 // of the object rather than the properties when the packet was created 4746 // of the object rather than the properties when the packet was created
4603 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); 4747 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
4604 updates.Add(familyUpdates.Value[i]); 4748 updates.Add(familyUpdates.Value[i]);
4605 OutPacket(packet, ThrottleOutPacketType.Task, true, 4749 // HACK : Remove intelligent resending until it's fixed in core
4606 delegate(OutgoingPacket oPacket) 4750 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4607 { 4751 // delegate(OutgoingPacket oPacket)
4608 ResendPropertyUpdates(updates, oPacket); 4752 // {
4609 }); 4753 // ResendPropertyUpdates(updates, oPacket);
4754 // });
4755 OutPacket(packet, ThrottleOutPacketType.Task, true);
4610 4756
4611 // fpcnt++; 4757 // fpcnt++;
4612 // fbcnt++; 4758 // fbcnt++;
@@ -4939,7 +5085,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4939 packet.ParcelData.Data = data; 5085 packet.ParcelData.Data = data;
4940 packet.ParcelData.SequenceID = sequence_id; 5086 packet.ParcelData.SequenceID = sequence_id;
4941 packet.Header.Zerocoded = true; 5087 packet.Header.Zerocoded = true;
4942 OutPacket(packet, ThrottleOutPacketType.Task); 5088// OutPacket(packet, ThrottleOutPacketType.Task);
5089 OutPacket(packet, ThrottleOutPacketType.Land);
4943 } 5090 }
4944 5091
4945 public void SendLandProperties( 5092 public void SendLandProperties(
@@ -5004,7 +5151,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5004 5151
5005 if (landData.SimwideArea > 0) 5152 if (landData.SimwideArea > 0)
5006 { 5153 {
5007 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 5154 int simulatorCapacity = (int)((long)landData.SimwideArea * (long)m_scene.RegionInfo.ObjectCapacity * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus / 65536L);
5155 // Never report more than sim total capacity
5156 if (simulatorCapacity > m_scene.RegionInfo.ObjectCapacity)
5157 simulatorCapacity = m_scene.RegionInfo.ObjectCapacity;
5008 updateMessage.SimWideMaxPrims = simulatorCapacity; 5158 updateMessage.SimWideMaxPrims = simulatorCapacity;
5009 } 5159 }
5010 else 5160 else
@@ -5039,7 +5189,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5039 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>(); 5189 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
5040 if (eq != null) 5190 if (eq != null)
5041 { 5191 {
5042 eq.ParcelProperties(updateMessage, this.AgentId); 5192
5193 OSD message_body = updateMessage.Serialize();
5194 // Add new fields here until OMV has them
5195 OSDMap bodyMap = (OSDMap)message_body;
5196 OSDArray parcelDataArray = (OSDArray)bodyMap["ParcelData"];
5197 OSDMap parcelData = (OSDMap)parcelDataArray[0];
5198 parcelData["SeeAVs"] = OSD.FromBoolean(landData.SeeAVs);
5199 parcelData["AnyAVSounds"] = OSD.FromBoolean(landData.AnyAVSounds);
5200 parcelData["GroupAVSounds"] = OSD.FromBoolean(landData.GroupAVSounds);
5201 OSDMap message = new OSDMap();
5202 message.Add("message", OSD.FromString("ParcelProperties"));
5203 message.Add("body", message_body);
5204
5205 eq.Enqueue (message, this.AgentId);
5206
5207// eq.ParcelProperties(updateMessage, this.AgentId);
5043 } 5208 }
5044 else 5209 else
5045 { 5210 {
@@ -5133,14 +5298,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5133 5298
5134 if (notifyCount > 0) 5299 if (notifyCount > 0)
5135 { 5300 {
5136 if (notifyCount > 32) 5301// if (notifyCount > 32)
5137 { 5302// {
5138 m_log.InfoFormat( 5303// m_log.InfoFormat(
5139 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 5304// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
5140 + " - a developer might want to investigate whether this is a hard limit", 32); 5305// + " - a developer might want to investigate whether this is a hard limit", 32);
5141 5306//
5142 notifyCount = 32; 5307// notifyCount = 32;
5143 } 5308// }
5144 5309
5145 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 5310 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
5146 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 5311 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -5195,41 +5360,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5195 { 5360 {
5196 ScenePresence presence = (ScenePresence)entity; 5361 ScenePresence presence = (ScenePresence)entity;
5197 5362
5363<<<<<<< HEAD
5198// m_log.DebugFormat( 5364// m_log.DebugFormat(
5199// "[LLCLIENTVIEW]: Sending terse update to {0} with pos {1}, vel {2} in {3}", 5365// "[LLCLIENTVIEW]: Sending terse update to {0} with pos {1}, vel {2} in {3}",
5200// Name, presence.OffsetPosition, presence.Velocity, m_scene.Name); 5366// Name, presence.OffsetPosition, presence.Velocity, m_scene.Name);
5201 5367=======
5202 attachPoint = presence.State;
5203 collisionPlane = presence.CollisionPlane;
5204 position = presence.OffsetPosition; 5368 position = presence.OffsetPosition;
5205 velocity = presence.Velocity; 5369 rotation = presence.Rotation;
5206 acceleration = Vector3.Zero;
5207
5208 // Interestingly, sending this to non-zero will cause the client's avatar to start moving & accelerating
5209 // in that direction, even though we don't model this on the server. Implementing this in the future
5210 // may improve movement smoothness.
5211// acceleration = new Vector3(1, 0, 0);
5212
5213 angularVelocity = presence.AngularVelocity; 5370 angularVelocity = presence.AngularVelocity;
5214
5215 // Whilst not in mouselook, an avatar will transmit only the Z rotation as this is the only axis
5216 // it rotates around.
5217 // In mouselook, X and Y co-ordinate will also be sent but when used in Rotation, these cause unwanted
5218 // excessive up and down movements of the camera when looking up and down.
5219 // See http://opensimulator.org/mantis/view.php?id=3274
5220 // This does not affect head movement, since this is controlled entirely by camera movement rather than
5221 // body rotation. We still need to transmit X and Y for sitting avatars but mouselook does not change
5222 // the rotation in this case.
5223 rotation = presence.Rotation; 5371 rotation = presence.Rotation;
5224 5372
5225 if (!presence.IsSatOnObject) 5373 attachPoint = 0;
5226 { 5374// m_log.DebugFormat(
5227 rotation.X = 0; 5375// "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
5228 rotation.Y = 0; 5376>>>>>>> avn/ubitvar
5229 } 5377
5378 // attachPoint = presence.State; // Core: commented
5379 collisionPlane = presence.CollisionPlane;
5380 velocity = presence.Velocity;
5381 acceleration = Vector3.Zero;
5230 5382
5231 if (sendTexture) 5383 if (sendTexture)
5384 {
5232 textureEntry = presence.Appearance.Texture.GetBytes(); 5385 textureEntry = presence.Appearance.Texture.GetBytes();
5386 }
5233 else 5387 else
5234 textureEntry = null; 5388 textureEntry = null;
5235 } 5389 }
@@ -5333,10 +5487,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5333 5487
5334 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) 5488 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
5335 { 5489 {
5490 Vector3 offsetPosition = data.OffsetPosition;
5491 Quaternion rotation = data.Rotation;
5492 uint parentID = data.ParentID;
5493
5336// m_log.DebugFormat( 5494// m_log.DebugFormat(
5337// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name); 5495// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name);
5338 5496
5339 byte[] objectData = new byte[76]; 5497 byte[] objectData = new byte[76];
5498<<<<<<< HEAD
5340 5499
5341 data.CollisionPlane.ToBytes(objectData, 0); 5500 data.CollisionPlane.ToBytes(objectData, 0);
5342 data.OffsetPosition.ToBytes(objectData, 16); 5501 data.OffsetPosition.ToBytes(objectData, 16);
@@ -5352,15 +5511,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5352 // body rotation. We still need to transmit X and Y for sitting avatars but mouselook does not change 5511 // body rotation. We still need to transmit X and Y for sitting avatars but mouselook does not change
5353 // the rotation in this case. 5512 // the rotation in this case.
5354 Quaternion rot = data.Rotation; 5513 Quaternion rot = data.Rotation;
5514=======
5515>>>>>>> avn/ubitvar
5355 5516
5356 if (!data.IsSatOnObject) 5517 Vector3 velocity = new Vector3(0, 0, 0);
5357 { 5518 Vector3 acceleration = new Vector3(0, 0, 0);
5358 rot.X = 0; 5519 rotation.Normalize();
5359 rot.Y = 0;
5360 }
5361 5520
5362 rot.ToBytes(objectData, 52); 5521 data.CollisionPlane.ToBytes(objectData, 0);
5363 //data.AngularVelocity.ToBytes(objectData, 64); 5522 offsetPosition.ToBytes(objectData, 16);
5523 velocity.ToBytes(objectData, 28);
5524 acceleration.ToBytes(objectData, 40);
5525 rotation.ToBytes(objectData, 52);
5526 data.AngularVelocity.ToBytes(objectData, 64);
5364 5527
5365 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5528 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
5366 5529
@@ -5386,7 +5549,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5386 update.PCode = (byte)PCode.Avatar; 5549 update.PCode = (byte)PCode.Avatar;
5387 update.ProfileCurve = 1; 5550 update.ProfileCurve = 1;
5388 update.PSBlock = Utils.EmptyBytes; 5551 update.PSBlock = Utils.EmptyBytes;
5389 update.Scale = new Vector3(0.45f, 0.6f, 1.9f); 5552 update.Scale = data.Appearance.AvatarSize;
5553// update.Scale.Z -= 0.2f;
5554
5390 update.Text = Utils.EmptyBytes; 5555 update.Text = Utils.EmptyBytes;
5391 update.TextColor = new byte[4]; 5556 update.TextColor = new byte[4];
5392 5557
@@ -5397,10 +5562,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5397 update.TextureEntry = Utils.EmptyBytes; 5562 update.TextureEntry = Utils.EmptyBytes;
5398// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes; 5563// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
5399 5564
5565/* all this flags seem related to prims and not avatars. This allow for wrong viewer side move of a avatar in prim edition mode (anv mantis 854)
5400 update.UpdateFlags = (uint)( 5566 update.UpdateFlags = (uint)(
5401 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | 5567 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
5402 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | 5568 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
5403 PrimFlags.ObjectOwnerModify); 5569 PrimFlags.ObjectOwnerModify);
5570*/
5571 update.UpdateFlags = 0;
5404 5572
5405 return update; 5573 return update;
5406 } 5574 }
@@ -5411,15 +5579,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5411 data.RelativePosition.ToBytes(objectData, 0); 5579 data.RelativePosition.ToBytes(objectData, 0);
5412 data.Velocity.ToBytes(objectData, 12); 5580 data.Velocity.ToBytes(objectData, 12);
5413 data.Acceleration.ToBytes(objectData, 24); 5581 data.Acceleration.ToBytes(objectData, 24);
5414 try 5582
5415 { 5583 Quaternion rotation = data.RotationOffset;
5416 data.RotationOffset.ToBytes(objectData, 36); 5584 rotation.Normalize();
5417 } 5585 rotation.ToBytes(objectData, 36);
5418 catch (Exception e)
5419 {
5420 m_log.Warn("[LLClientView]: exception converting quaternion to bytes, using Quaternion.Identity. Exception: " + e.ToString());
5421 OpenMetaverse.Quaternion.Identity.ToBytes(objectData, 36);
5422 }
5423 data.AngularVelocity.ToBytes(objectData, 48); 5586 data.AngularVelocity.ToBytes(objectData, 48);
5424 5587
5425 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5588 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
@@ -5433,7 +5596,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5433 //update.JointType = 0; 5596 //update.JointType = 0;
5434 update.Material = data.Material; 5597 update.Material = data.Material;
5435 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim 5598 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
5599<<<<<<< HEAD
5436 5600
5601=======
5602/*
5603>>>>>>> avn/ubitvar
5437 if (data.ParentGroup.IsAttachment) 5604 if (data.ParentGroup.IsAttachment)
5438 { 5605 {
5439 update.NameValue 5606 update.NameValue
@@ -5458,6 +5625,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5458 // case for attachments may contain conflicting values that can end up crashing the viewer. 5625 // case for attachments may contain conflicting values that can end up crashing the viewer.
5459 update.State = data.ParentGroup.RootPart.Shape.State; 5626 update.State = data.ParentGroup.RootPart.Shape.State;
5460 } 5627 }
5628 */
5629
5630 if (data.ParentGroup.IsAttachment)
5631 {
5632 if (data.IsRoot)
5633 {
5634 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.ParentGroup.FromItemID);
5635 }
5636 else
5637 update.NameValue = Utils.EmptyBytes;
5638
5639 int st = (int)data.ParentGroup.AttachmentPoint;
5640 update.State = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ;
5641 }
5642 else
5643 {
5644 update.NameValue = Utils.EmptyBytes;
5645 update.State = data.Shape.State; // not sure about this
5646 }
5647
5461 5648
5462 update.ObjectData = objectData; 5649 update.ObjectData = objectData;
5463 update.ParentID = data.ParentID; 5650 update.ParentID = data.ParentID;
@@ -5579,8 +5766,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5579 // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs 5766 // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs
5580 // for each AgentUpdate packet. 5767 // for each AgentUpdate packet.
5581 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); 5768 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
5582 5769
5583 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); 5770 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
5771 AddLocalPacketHandler(PacketType.VelocityInterpolateOff, HandleVelocityInterpolateOff, false);
5772 AddLocalPacketHandler(PacketType.VelocityInterpolateOn, HandleVelocityInterpolateOn, false);
5584 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); 5773 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
5585 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); 5774 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
5586 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); 5775 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false);
@@ -5732,6 +5921,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5732 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5921 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5733 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5922 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5734 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5923 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5924 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5735 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5925 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5736 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5926 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5737 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5927 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5798,6 +5988,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5798 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest); 5988 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest);
5799 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes); 5989 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes);
5800 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard); 5990 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard);
5991 AddLocalPacketHandler(PacketType.ChangeInventoryItemFlags, HandleChangeInventoryItemFlags);
5801 5992
5802 AddGenericPacketHandler("autopilot", HandleAutopilot); 5993 AddGenericPacketHandler("autopilot", HandleAutopilot);
5803 } 5994 }
@@ -5809,7 +6000,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5809 #region Scene/Avatar 6000 #region Scene/Avatar
5810 6001
5811 // Threshold for body rotation to be a significant agent update 6002 // Threshold for body rotation to be a significant agent update
5812 private const float QDELTA = 0.000001f; 6003 // use the abs of cos
6004 private const float QDELTABody = 1.0f - 0.0001f;
6005 private const float QDELTAHead = 1.0f - 0.0001f;
5813 // Threshold for camera rotation to be a significant agent update 6006 // Threshold for camera rotation to be a significant agent update
5814 private const float VDELTA = 0.01f; 6007 private const float VDELTA = 0.01f;
5815 6008
@@ -5832,18 +6025,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5832 /// <param name='x'></param> 6025 /// <param name='x'></param>
5833 private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) 6026 private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5834 { 6027 {
5835 float qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2); 6028 float qdelta1 = Math.Abs(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation));
5836 //qdelta2 = 1 - (float)Math.Pow(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation), 2); 6029 //qdelta2 = Math.Abs(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation));
5837 6030
5838 bool movementSignificant = 6031 bool movementSignificant =
5839 (qdelta1 > QDELTA) // significant if body rotation above threshold 6032 (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed
5840 // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack
5841 // || (qdelta2 > QDELTA * 10) // significant if head rotation above threshold
5842 || (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed
5843 || (x.ControlFlags != (byte)AgentManager.ControlFlags.NONE) // significant if user supplying any movement update commands 6033 || (x.ControlFlags != (byte)AgentManager.ControlFlags.NONE) // significant if user supplying any movement update commands
5844 || (x.Far != m_thisAgentUpdateArgs.Far) // significant if far distance changed
5845 || (x.Flags != m_thisAgentUpdateArgs.Flags) // significant if Flags changed 6034 || (x.Flags != m_thisAgentUpdateArgs.Flags) // significant if Flags changed
5846 || (x.State != m_thisAgentUpdateArgs.State) // significant if Stats changed 6035 || (x.State != m_thisAgentUpdateArgs.State) // significant if Stats changed
6036 || (qdelta1 < QDELTABody) // significant if body rotation above(below cos) threshold
6037 // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack
6038 // || (qdelta2 < QDELTAHead) // significant if head rotation above(below cos) threshold
6039 || (Math.Abs(x.Far - m_thisAgentUpdateArgs.Far) >= 32) // significant if far distance changed
5847 ; 6040 ;
5848 //if (movementSignificant) 6041 //if (movementSignificant)
5849 //{ 6042 //{
@@ -5886,55 +6079,63 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5886 return cameraSignificant; 6079 return cameraSignificant;
5887 } 6080 }
5888 6081
5889 private bool HandleAgentUpdate(IClientAPI sener, Packet packet) 6082 private bool HandleAgentUpdate(IClientAPI sender, Packet packet)
5890 { 6083 {
5891 // We got here, which means that something in agent update was significant 6084 // We got here, which means that something in agent update was significant
5892 6085
5893 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; 6086 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5894 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; 6087 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
5895 6088
5896 if (x.AgentID != AgentId || x.SessionID != SessionId) 6089 if (x.AgentID != AgentId || x.SessionID != SessionId)
6090 {
6091 PacketPool.Instance.ReturnPacket(packet);
5897 return false; 6092 return false;
6093 }
6094
6095 TotalAgentUpdates++;
5898 6096
5899 // Before we update the current m_thisAgentUpdateArgs, let's check this again
5900 // to see what exactly changed
5901 bool movement = CheckAgentMovementUpdateSignificance(x); 6097 bool movement = CheckAgentMovementUpdateSignificance(x);
5902 bool camera = CheckAgentCameraUpdateSignificance(x); 6098 bool camera = CheckAgentCameraUpdateSignificance(x);
5903 6099
5904 m_thisAgentUpdateArgs.AgentID = x.AgentID;
5905 m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation;
5906 m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
5907 m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter;
5908 m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
5909 m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
5910 m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags;
5911 m_thisAgentUpdateArgs.Far = x.Far;
5912 m_thisAgentUpdateArgs.Flags = x.Flags;
5913 m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation;
5914 m_thisAgentUpdateArgs.SessionID = x.SessionID;
5915 m_thisAgentUpdateArgs.State = x.State;
5916
5917 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5918 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5919 UpdateAgent handlerAgentCameraUpdate = OnAgentCameraUpdate;
5920
5921 // Was there a significant movement/state change? 6100 // Was there a significant movement/state change?
5922 if (movement) 6101 if (movement)
5923 { 6102 {
6103 m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation;
6104 m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags;
6105 m_thisAgentUpdateArgs.Far = x.Far;
6106 m_thisAgentUpdateArgs.Flags = x.Flags;
6107 m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation;
6108// m_thisAgentUpdateArgs.SessionID = x.SessionID;
6109 m_thisAgentUpdateArgs.State = x.State;
6110
6111 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
6112 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
6113
5924 if (handlerPreAgentUpdate != null) 6114 if (handlerPreAgentUpdate != null)
5925 OnPreAgentUpdate(this, m_thisAgentUpdateArgs); 6115 OnPreAgentUpdate(this, m_thisAgentUpdateArgs);
5926 6116
5927 if (handlerAgentUpdate != null) 6117 if (handlerAgentUpdate != null)
5928 OnAgentUpdate(this, m_thisAgentUpdateArgs); 6118 OnAgentUpdate(this, m_thisAgentUpdateArgs);
6119
6120 handlerAgentUpdate = null;
6121 handlerPreAgentUpdate = null;
5929 } 6122 }
6123
5930 // Was there a significant camera(s) change? 6124 // Was there a significant camera(s) change?
5931 if (camera) 6125 if (camera)
6126 {
6127 m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
6128 m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter;
6129 m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
6130 m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
6131
6132 UpdateAgent handlerAgentCameraUpdate = OnAgentCameraUpdate;
6133
5932 if (handlerAgentCameraUpdate != null) 6134 if (handlerAgentCameraUpdate != null)
5933 handlerAgentCameraUpdate(this, m_thisAgentUpdateArgs); 6135 handlerAgentCameraUpdate(this, m_thisAgentUpdateArgs);
5934 6136
5935 handlerAgentUpdate = null; 6137 handlerAgentCameraUpdate = null;
5936 handlerPreAgentUpdate = null; 6138 }
5937 handlerAgentCameraUpdate = null;
5938 6139
5939 PacketPool.Instance.ReturnPacket(packet); 6140 PacketPool.Instance.ReturnPacket(packet);
5940 6141
@@ -6150,6 +6351,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6150 return true; 6351 return true;
6151 } 6352 }
6152 6353
6354 private bool HandleVelocityInterpolateOff(IClientAPI sender, Packet Pack)
6355 {
6356 VelocityInterpolateOffPacket p = (VelocityInterpolateOffPacket)Pack;
6357 if (p.AgentData.SessionID != SessionId ||
6358 p.AgentData.AgentID != AgentId)
6359 return true;
6360
6361 m_VelocityInterpolate = false;
6362 return true;
6363 }
6364
6365 private bool HandleVelocityInterpolateOn(IClientAPI sender, Packet Pack)
6366 {
6367 VelocityInterpolateOnPacket p = (VelocityInterpolateOnPacket)Pack;
6368 if (p.AgentData.SessionID != SessionId ||
6369 p.AgentData.AgentID != AgentId)
6370 return true;
6371
6372 m_VelocityInterpolate = true;
6373 return true;
6374 }
6375
6376
6153 private bool HandleAvatarPropertiesRequest(IClientAPI sender, Packet Pack) 6377 private bool HandleAvatarPropertiesRequest(IClientAPI sender, Packet Pack)
6154 { 6378 {
6155 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; 6379 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack;
@@ -6503,7 +6727,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6503 { 6727 {
6504 // Note: the ModifyTerrain event handler sends out updated packets before the end of this event. Therefore, 6728 // Note: the ModifyTerrain event handler sends out updated packets before the end of this event. Therefore,
6505 // a simple boolean value should work and perhaps queue up just a few terrain patch packets at the end of the edit. 6729 // a simple boolean value should work and perhaps queue up just a few terrain patch packets at the end of the edit.
6506 m_justEditedTerrain = true; // Prevent terrain packet (Land layer) from being queued, make it unreliable
6507 if (OnModifyTerrain != null) 6730 if (OnModifyTerrain != null)
6508 { 6731 {
6509 for (int i = 0; i < modify.ParcelData.Length; i++) 6732 for (int i = 0; i < modify.ParcelData.Length; i++)
@@ -6519,7 +6742,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6519 } 6742 }
6520 } 6743 }
6521 } 6744 }
6522 m_justEditedTerrain = false; // Queue terrain packet (Land layer) if necessary, make it reliable again
6523 } 6745 }
6524 6746
6525 return true; 6747 return true;
@@ -6581,16 +6803,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6581 for (int i = 0; i < appear.VisualParam.Length; i++) 6803 for (int i = 0; i < appear.VisualParam.Length; i++)
6582 visualparams[i] = appear.VisualParam[i].ParamValue; 6804 visualparams[i] = appear.VisualParam[i].ParamValue;
6583 //var b = appear.WearableData[0]; 6805 //var b = appear.WearableData[0];
6584 6806
6585 Primitive.TextureEntry te = null; 6807 Primitive.TextureEntry te = null;
6586 if (appear.ObjectData.TextureEntry.Length > 1) 6808 if (appear.ObjectData.TextureEntry.Length > 1)
6587 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); 6809 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length);
6588 6810
6589 WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length]; 6811 WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length];
6590 for (int i=0; i<appear.WearableData.Length;i++) 6812 for (int i=0; i<appear.WearableData.Length;i++)
6591 cacheitems[i] = new WearableCacheItem(){CacheId = appear.WearableData[i].CacheID,TextureIndex=Convert.ToUInt32(appear.WearableData[i].TextureIndex)}; 6813 cacheitems[i] = new WearableCacheItem(){
6592 6814 CacheId = appear.WearableData[i].CacheID,
6815 TextureIndex=Convert.ToUInt32(appear.WearableData[i].TextureIndex)
6816 };
6593 6817
6818
6594 6819
6595 handlerSetAppearance(sender, te, visualparams,avSize, cacheitems); 6820 handlerSetAppearance(sender, te, visualparams,avSize, cacheitems);
6596 } 6821 }
@@ -6794,13 +7019,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6794 return true; 7019 return true;
6795 } 7020 }
6796 7021
6797 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack) 7022 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack)
6798 { 7023 {
7024 m_log.DebugFormat("[LLClientView] HandleCompleteAgentMovement");
7025
6799 Action<IClientAPI, bool> handlerCompleteMovementToRegion = OnCompleteMovementToRegion; 7026 Action<IClientAPI, bool> handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
6800 if (handlerCompleteMovementToRegion != null) 7027 if (handlerCompleteMovementToRegion != null)
6801 { 7028 {
6802 handlerCompleteMovementToRegion(sender, true); 7029 handlerCompleteMovementToRegion(sender, true);
6803 } 7030 }
7031 else
7032 m_log.Debug("HandleCompleteAgentMovement NULL handler");
7033
6804 handlerCompleteMovementToRegion = null; 7034 handlerCompleteMovementToRegion = null;
6805 7035
6806 return true; 7036 return true;
@@ -6818,7 +7048,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6818 return true; 7048 return true;
6819 } 7049 }
6820 #endregion 7050 #endregion
6821 7051/*
6822 StartAnim handlerStartAnim = null; 7052 StartAnim handlerStartAnim = null;
6823 StopAnim handlerStopAnim = null; 7053 StopAnim handlerStopAnim = null;
6824 7054
@@ -6842,6 +7072,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6842 } 7072 }
6843 } 7073 }
6844 return true; 7074 return true;
7075*/
7076 ChangeAnim handlerChangeAnim = null;
7077
7078 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
7079 {
7080 handlerChangeAnim = OnChangeAnim;
7081 if (handlerChangeAnim != null)
7082 {
7083 handlerChangeAnim(AgentAni.AnimationList[i].AnimID, AgentAni.AnimationList[i].StartAnim, false);
7084 }
7085 }
7086
7087 handlerChangeAnim = OnChangeAnim;
7088 if (handlerChangeAnim != null)
7089 {
7090 handlerChangeAnim(UUID.Zero, false, true);
7091 }
7092
7093 return true;
6845 } 7094 }
6846 7095
6847 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack) 7096 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack)
@@ -7087,6 +7336,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7087 #endregion 7336 #endregion
7088 7337
7089 m_udpClient.SetThrottles(atpack.Throttle.Throttles); 7338 m_udpClient.SetThrottles(atpack.Throttle.Throttles);
7339 GenericCall2 handler = OnUpdateThrottles;
7340 if (handler != null)
7341 {
7342 handler();
7343 }
7090 return true; 7344 return true;
7091 } 7345 }
7092 7346
@@ -7359,6 +7613,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7359 7613
7360 for (int i = 0; i < incomingselect.ObjectData.Length; i++) 7614 for (int i = 0; i < incomingselect.ObjectData.Length; i++)
7361 { 7615 {
7616 if (!SelectedObjects.Contains(incomingselect.ObjectData[i].ObjectLocalID))
7617 SelectedObjects.Add(incomingselect.ObjectData[i].ObjectLocalID);
7362 handlerObjectSelect = OnObjectSelect; 7618 handlerObjectSelect = OnObjectSelect;
7363 if (handlerObjectSelect != null) 7619 if (handlerObjectSelect != null)
7364 { 7620 {
@@ -7385,6 +7641,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7385 7641
7386 for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) 7642 for (int i = 0; i < incomingdeselect.ObjectData.Length; i++)
7387 { 7643 {
7644 if (!SelectedObjects.Contains(incomingdeselect.ObjectData[i].ObjectLocalID))
7645 SelectedObjects.Add(incomingdeselect.ObjectData[i].ObjectLocalID);
7388 handlerObjectDeselect = OnObjectDeselect; 7646 handlerObjectDeselect = OnObjectDeselect;
7389 if (handlerObjectDeselect != null) 7647 if (handlerObjectDeselect != null)
7390 { 7648 {
@@ -7511,7 +7769,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7511 physdata.Bounce = phsblock.Restitution; 7769 physdata.Bounce = phsblock.Restitution;
7512 physdata.Density = phsblock.Density; 7770 physdata.Density = phsblock.Density;
7513 physdata.Friction = phsblock.Friction; 7771 physdata.Friction = phsblock.Friction;
7514 physdata.GravitationModifier = phsblock.GravityMultiplier; 7772 physdata.GravitationModifier = phsblock.GravityMultiplier;
7515 } 7773 }
7516 7774
7517 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, this); 7775 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, this);
@@ -8097,6 +8355,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8097 // surrounding scene 8355 // surrounding scene
8098 if ((ImageType)block.Type == ImageType.Baked) 8356 if ((ImageType)block.Type == ImageType.Baked)
8099 args.Priority *= 2.0f; 8357 args.Priority *= 2.0f;
8358 int wearableout = 0;
8100 8359
8101 ImageManager.EnqueueReq(args); 8360 ImageManager.EnqueueReq(args);
8102 } 8361 }
@@ -9106,7 +9365,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9106 if ((locX >= m_scene.RegionInfo.WorldLocX) 9365 if ((locX >= m_scene.RegionInfo.WorldLocX)
9107 && (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX)) 9366 && (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX))
9108 && (locY >= m_scene.RegionInfo.WorldLocY) 9367 && (locY >= m_scene.RegionInfo.WorldLocY)
9368<<<<<<< HEAD
9109 && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)) ) 9369 && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)) )
9370=======
9371 && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)))
9372>>>>>>> avn/ubitvar
9110 { 9373 {
9111 tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle; 9374 tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle;
9112 tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX; 9375 tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX;
@@ -9146,16 +9409,61 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9146 9409
9147 #region Parcel related packets 9410 #region Parcel related packets
9148 9411
9412 // acumulate several HandleRegionHandleRequest consecutive overlaping requests
9413 // to be done with minimal resources as possible
9414 // variables temporary here while in test
9415
9416 Queue<UUID> RegionHandleRequests = new Queue<UUID>();
9417 bool RegionHandleRequestsInService = false;
9418
9149 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack) 9419 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack)
9150 { 9420 {
9151 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; 9421 UUID currentUUID;
9152 9422
9153 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest; 9423 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest;
9154 if (handlerRegionHandleRequest != null) 9424
9425 if (handlerRegionHandleRequest == null)
9426 return true;
9427
9428 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack;
9429
9430 lock (RegionHandleRequests)
9431 {
9432 if (RegionHandleRequestsInService)
9433 {
9434 // we are already busy doing a previus request
9435 // so enqueue it
9436 RegionHandleRequests.Enqueue(rhrPack.RequestBlock.RegionID);
9437 return true;
9438 }
9439
9440 // else do it
9441 currentUUID = rhrPack.RequestBlock.RegionID;
9442 RegionHandleRequestsInService = true;
9443 }
9444
9445 while (true)
9155 { 9446 {
9156 handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); 9447 handlerRegionHandleRequest(this, currentUUID);
9448
9449 lock (RegionHandleRequests)
9450 {
9451 // exit condition, nothing to do or closed
9452 // current code seems to assume we may loose the handler at anytime,
9453 // so keep checking it
9454 handlerRegionHandleRequest = OnRegionHandleRequest;
9455
9456 if (RegionHandleRequests.Count == 0 || !IsActive || handlerRegionHandleRequest == null)
9457 {
9458 RegionHandleRequests.Clear();
9459 RegionHandleRequestsInService = false;
9460 return true;
9461 }
9462 currentUUID = RegionHandleRequests.Dequeue();
9463 }
9157 } 9464 }
9158 return true; 9465
9466 return true; // actually unreached
9159 } 9467 }
9160 9468
9161 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack) 9469 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack)
@@ -10425,7 +10733,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10425 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 10733 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
10426 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 10734 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
10427 UpdateMuteListEntry.MuteData.MuteType, 10735 UpdateMuteListEntry.MuteData.MuteType,
10428 UpdateMuteListEntry.AgentData.AgentID); 10736 UpdateMuteListEntry.MuteData.MuteFlags);
10429 return true; 10737 return true;
10430 } 10738 }
10431 return false; 10739 return false;
@@ -10440,8 +10748,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10440 { 10748 {
10441 handlerRemoveMuteListEntry(this, 10749 handlerRemoveMuteListEntry(this,
10442 RemoveMuteListEntry.MuteData.MuteID, 10750 RemoveMuteListEntry.MuteData.MuteID,
10443 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 10751 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
10444 RemoveMuteListEntry.AgentData.AgentID);
10445 return true; 10752 return true;
10446 } 10753 }
10447 return false; 10754 return false;
@@ -10485,10 +10792,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10485 return false; 10792 return false;
10486 } 10793 }
10487 10794
10795 private bool HandleChangeInventoryItemFlags(IClientAPI client, Packet packet)
10796 {
10797 ChangeInventoryItemFlagsPacket ChangeInventoryItemFlags =
10798 (ChangeInventoryItemFlagsPacket)packet;
10799 ChangeInventoryItemFlags handlerChangeInventoryItemFlags = OnChangeInventoryItemFlags;
10800 if (handlerChangeInventoryItemFlags != null)
10801 {
10802 foreach(ChangeInventoryItemFlagsPacket.InventoryDataBlock b in ChangeInventoryItemFlags.InventoryData)
10803 handlerChangeInventoryItemFlags(this, b.ItemID, b.Flags);
10804 return true;
10805 }
10806 return false;
10807 }
10808
10488 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack) 10809 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack)
10489 { 10810 {
10490 return true; 10811 return true;
10491 } 10812 }
10813
10814 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
10815 {
10816 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
10817
10818 #region Packet Session and User Check
10819 if (m_checkPackets)
10820 {
10821 if (packet.AgentData.SessionID != SessionId ||
10822 packet.AgentData.AgentID != AgentId)
10823 return true;
10824 }
10825 #endregion
10826 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
10827 List<InventoryItemBase> items = new List<InventoryItemBase>();
10828 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
10829 {
10830 InventoryItemBase b = new InventoryItemBase();
10831 b.ID = n.OldItemID;
10832 b.Folder = n.OldFolderID;
10833 items.Add(b);
10834 }
10835
10836 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
10837 if (handlerMoveItemsAndLeaveCopy != null)
10838 {
10839 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
10840 }
10841
10842 return true;
10843 }
10492 10844
10493 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 10845 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
10494 { 10846 {
@@ -10915,6 +11267,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10915 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 11267 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10916 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 11268 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10917 11269
11270 Scene scene = (Scene)m_scene;
11271 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
11272 {
11273 ScenePresence p;
11274 if (scene.TryGetScenePresence(sender.AgentId, out p))
11275 {
11276 if (p.GodLevel >= 200)
11277 {
11278 groupProfileReply.GroupData.OpenEnrollment = true;
11279 groupProfileReply.GroupData.MembershipFee = 0;
11280 }
11281 }
11282 }
11283
10918 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 11284 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10919 } 11285 }
10920 return true; 11286 return true;
@@ -11488,11 +11854,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11488 11854
11489 StartLure handlerStartLure = OnStartLure; 11855 StartLure handlerStartLure = OnStartLure;
11490 if (handlerStartLure != null) 11856 if (handlerStartLure != null)
11491 handlerStartLure(startLureRequest.Info.LureType, 11857 {
11492 Utils.BytesToString( 11858 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
11493 startLureRequest.Info.Message), 11859 {
11494 startLureRequest.TargetData[0].TargetID, 11860 handlerStartLure(startLureRequest.Info.LureType,
11495 this); 11861 Utils.BytesToString(
11862 startLureRequest.Info.Message),
11863 startLureRequest.TargetData[i].TargetID,
11864 this);
11865 }
11866 }
11496 return true; 11867 return true;
11497 } 11868 }
11498 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 11869 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -11606,10 +11977,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11606 } 11977 }
11607 #endregion 11978 #endregion
11608 11979
11609 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; 11980 ClassifiedGodDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
11610 if (handlerClassifiedGodDelete != null) 11981 if (handlerClassifiedGodDelete != null)
11611 handlerClassifiedGodDelete( 11982 handlerClassifiedGodDelete(
11612 classifiedGodDelete.Data.ClassifiedID, 11983 classifiedGodDelete.Data.ClassifiedID,
11984 classifiedGodDelete.Data.QueryID,
11613 this); 11985 this);
11614 return true; 11986 return true;
11615 } 11987 }
@@ -11912,13 +12284,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11912 /// <param name="simclient"></param> 12284 /// <param name="simclient"></param>
11913 /// <param name="packet"></param> 12285 /// <param name="packet"></param>
11914 /// <returns></returns> 12286 /// <returns></returns>
11915 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet) 12287 // TODO: Convert old handler to use new method
12288 /*protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11916 { 12289 {
11917 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; 12290 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
11918 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); 12291 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
11919 12292
11920 if (cachedtex.AgentData.SessionID != SessionId) 12293 if (cachedtex.AgentData.SessionID != SessionId)
11921 return false; 12294 return false;
12295
11922 12296
11923 12297
11924 // TODO: don't create new blocks if recycling an old packet 12298 // TODO: don't create new blocks if recycling an old packet
@@ -11966,6 +12340,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11966 } 12340 }
11967 } 12341 }
11968 12342
12343<<<<<<< HEAD
11969 if (cacheItems != null) 12344 if (cacheItems != null)
11970 { 12345 {
11971 // We need to make sure the asset stored in the bake is available on this server also by its assetid before we map it to a Cacheid. 12346 // We need to make sure the asset stored in the bake is available on this server also by its assetid before we map it to a Cacheid.
@@ -11985,13 +12360,69 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11985 { 12360 {
11986 WearableCacheItem item = 12361 WearableCacheItem item =
11987 WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex, cacheItems); 12362 WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex, cacheItems);
12363=======
12364 CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest;
12365 if (handlerCachedTextureRequest != null)
12366 {
12367 handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs);
12368 }
12369
12370 return true;
12371 }*/
12372
12373 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
12374 {
12375 //m_log.Debug("texture cached: " + packet.ToString());
12376 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
12377 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
12378
12379 if (cachedtex.AgentData.SessionID != SessionId)
12380 return false;
12381
12382 // TODO: don't create new blocks if recycling an old packet
12383 cachedresp.AgentData.AgentID = AgentId;
12384 cachedresp.AgentData.SessionID = m_sessionId;
12385 cachedresp.AgentData.SerialNum = cachedtex.AgentData.SerialNum;
12386 cachedresp.WearableData =
12387 new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length];
12388
12389 int maxWearablesLoop = cachedtex.WearableData.Length;
12390 if (maxWearablesLoop > AvatarWearable.MAX_WEARABLES)
12391 maxWearablesLoop = AvatarWearable.MAX_WEARABLES;
12392
12393 int cacheHits = 0;
12394
12395 // We need to make sure the asset stored in the bake is available on this server also by it's assetid before we map it to a Cacheid
12396
12397 WearableCacheItem[] cacheItems = null;
12398
12399 ScenePresence p = m_scene.GetScenePresence(AgentId);
12400
12401 if (p != null && p.Appearance != null)
12402 {
12403 cacheItems = p.Appearance.WearableCacheItems;
12404 }
12405
12406 if (cacheItems != null)
12407 {
12408 for (int i = 0; i < maxWearablesLoop; i++)
12409 {
12410 int idx = cachedtex.WearableData[i].TextureIndex;
12411>>>>>>> avn/ubitvar
11988 12412
11989 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); 12413 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11990 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; 12414 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11991 cachedresp.WearableData[i].HostName = new byte[0]; 12415 cachedresp.WearableData[i].HostName = new byte[0];
12416<<<<<<< HEAD
11992 if (item != null && cachedtex.WearableData[i].ID == item.CacheId) 12417 if (item != null && cachedtex.WearableData[i].ID == item.CacheId)
11993 { 12418 {
11994 cachedresp.WearableData[i].TextureID = item.TextureID; 12419 cachedresp.WearableData[i].TextureID = item.TextureID;
12420=======
12421 if (cachedtex.WearableData[i].ID == cacheItems[idx].CacheId)
12422 {
12423 cachedresp.WearableData[i].TextureID = cacheItems[idx].TextureID;
12424 cacheHits++;
12425>>>>>>> avn/ubitvar
11995 } 12426 }
11996 else 12427 else
11997 { 12428 {
@@ -12001,22 +12432,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12001 } 12432 }
12002 else 12433 else
12003 { 12434 {
12435<<<<<<< HEAD
12004 // Cached textures not available 12436 // Cached textures not available
12437=======
12438>>>>>>> avn/ubitvar
12005 for (int i = 0; i < maxWearablesLoop; i++) 12439 for (int i = 0; i < maxWearablesLoop; i++)
12006 { 12440 {
12007 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); 12441 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
12008 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; 12442 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
12009 cachedresp.WearableData[i].TextureID = UUID.Zero; 12443 cachedresp.WearableData[i].TextureID = UUID.Zero;
12444<<<<<<< HEAD
12010 cachedresp.WearableData[i].HostName = new byte[0]; 12445 cachedresp.WearableData[i].HostName = new byte[0];
12011 } 12446 }
12012 } 12447 }
12013 12448
12449=======
12450 //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
12451 cachedresp.WearableData[i].HostName = new byte[0];
12452 }
12453 }
12454
12455 m_log.DebugFormat("texture cached: hits {0}", cacheHits);
12456
12457>>>>>>> avn/ubitvar
12014 cachedresp.Header.Zerocoded = true; 12458 cachedresp.Header.Zerocoded = true;
12015 OutPacket(cachedresp, ThrottleOutPacketType.Task); 12459 OutPacket(cachedresp, ThrottleOutPacketType.Task);
12016 12460
12017 return true; 12461 return true;
12018 } 12462 }
12019 12463
12020 /// <summary> 12464 /// <summary>
12021 /// Send a response back to a client when it asks the asset server (via the region server) if it has 12465 /// Send a response back to a client when it asks the asset server (via the region server) if it has
12022 /// its appearance texture cached. 12466 /// its appearance texture cached.
@@ -12080,209 +12524,147 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12080 } 12524 }
12081 else 12525 else
12082 { 12526 {
12083// m_log.DebugFormat( 12527 ClientChangeObject updatehandler = onClientChangeObject;
12084// "[CLIENT]: Processing block {0} type {1} for {2} {3}",
12085// i, block.Type, part.Name, part.LocalId);
12086 12528
12087// // Do this once since fetch parts creates a new array. 12529 if (updatehandler != null)
12088// SceneObjectPart[] parts = part.ParentGroup.Parts; 12530 {
12089// for (int j = 0; j < parts.Length; j++) 12531 ObjectChangeData udata = new ObjectChangeData();
12090// {
12091// part.StoreUndoState();
12092// parts[j].IgnoreUndoUpdate = true;
12093// }
12094 12532
12095 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; 12533 /*ubit from ll JIRA:
12534 * 0x01 position
12535 * 0x02 rotation
12536 * 0x04 scale
12537
12538 * 0x08 LINK_SET
12539 * 0x10 UNIFORM for scale
12540 */
12096 12541
12097 switch (block.Type) 12542 // translate to internal changes
12098 { 12543 // not all cases .. just the ones older code did
12099 case 1:
12100 Vector3 pos1 = new Vector3(block.Data, 0);
12101 12544
12102 UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 12545 switch (block.Type)
12103 if (handlerUpdatePrimSinglePosition != null) 12546 {
12104 { 12547 case 1: //change position sp
12105 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 12548 udata.position = new Vector3(block.Data, 0);
12106 handlerUpdatePrimSinglePosition(localId, pos1, this);
12107 }
12108 break;
12109 12549
12110 case 2: 12550 udata.change = ObjectChangeType.primP;
12111 Quaternion rot1 = new Quaternion(block.Data, 0, true); 12551 updatehandler(localId, udata, this);
12552 break;
12112 12553
12113 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; 12554 case 2: // rotation sp
12114 if (handlerUpdatePrimSingleRotation != null) 12555 udata.rotation = new Quaternion(block.Data, 0, true);
12115 {
12116 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W);
12117 handlerUpdatePrimSingleRotation(localId, rot1, this);
12118 }
12119 break;
12120 12556
12121 case 3: 12557 udata.change = ObjectChangeType.primR;
12122 Vector3 rotPos = new Vector3(block.Data, 0); 12558 updatehandler(localId, udata, this);
12123 Quaternion rot2 = new Quaternion(block.Data, 12, true); 12559 break;
12124 12560
12125 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; 12561 case 3: // position plus rotation
12126 if (handlerUpdatePrimSingleRotationPosition != null) 12562 udata.position = new Vector3(block.Data, 0);
12127 { 12563 udata.rotation = new Quaternion(block.Data, 12, true);
12128 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z);
12129 // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W);
12130 handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this);
12131 }
12132 break;
12133 12564
12134 case 4: 12565 udata.change = ObjectChangeType.primPR;
12135 case 20: 12566 updatehandler(localId, udata, this);
12136 Vector3 scale4 = new Vector3(block.Data, 0); 12567 break;
12137 12568
12138 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; 12569 case 4: // scale sp
12139 if (handlerUpdatePrimScale != null) 12570 udata.scale = new Vector3(block.Data, 0);
12140 { 12571 udata.change = ObjectChangeType.primS;
12141 // m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z);
12142 handlerUpdatePrimScale(localId, scale4, this);
12143 }
12144 break;
12145 12572
12146 case 5: 12573 updatehandler(localId, udata, this);
12147 Vector3 scale1 = new Vector3(block.Data, 12); 12574 break;
12148 Vector3 pos11 = new Vector3(block.Data, 0);
12149 12575
12150 handlerUpdatePrimScale = OnUpdatePrimScale; 12576 case 0x14: // uniform scale sp
12151 if (handlerUpdatePrimScale != null) 12577 udata.scale = new Vector3(block.Data, 0);
12152 {
12153 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
12154 handlerUpdatePrimScale(localId, scale1, this);
12155 12578
12156 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 12579 udata.change = ObjectChangeType.primUS;
12157 if (handlerUpdatePrimSinglePosition != null) 12580 updatehandler(localId, udata, this);
12158 { 12581 break;
12159 handlerUpdatePrimSinglePosition(localId, pos11, this);
12160 }
12161 }
12162 break;
12163 12582
12164 case 9: 12583 case 5: // scale and position sp
12165 Vector3 pos2 = new Vector3(block.Data, 0); 12584 udata.position = new Vector3(block.Data, 0);
12585 udata.scale = new Vector3(block.Data, 12);
12166 12586
12167 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; 12587 udata.change = ObjectChangeType.primPS;
12588 updatehandler(localId, udata, this);
12589 break;
12168 12590
12169 if (handlerUpdateVector != null) 12591 case 0x15: //uniform scale and position
12170 { 12592 udata.position = new Vector3(block.Data, 0);
12171 handlerUpdateVector(localId, pos2, this); 12593 udata.scale = new Vector3(block.Data, 12);
12172 }
12173 break;
12174 12594
12175 case 10: 12595 udata.change = ObjectChangeType.primPUS;
12176 Quaternion rot3 = new Quaternion(block.Data, 0, true); 12596 updatehandler(localId, udata, this);
12597 break;
12177 12598
12178 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; 12599 // now group related (bit 4)
12179 if (handlerUpdatePrimRotation != null) 12600 case 9: //( 8 + 1 )group position
12180 { 12601 udata.position = new Vector3(block.Data, 0);
12181 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W);
12182 handlerUpdatePrimRotation(localId, rot3, this);
12183 }
12184 break;
12185 12602
12186 case 11: 12603 udata.change = ObjectChangeType.groupP;
12187 Vector3 pos3 = new Vector3(block.Data, 0); 12604 updatehandler(localId, udata, this);
12188 Quaternion rot4 = new Quaternion(block.Data, 12, true); 12605 break;
12189 12606
12190 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; 12607 case 0x0A: // (8 + 2) group rotation
12191 if (handlerUpdatePrimGroupRotation != null) 12608 udata.rotation = new Quaternion(block.Data, 0, true);
12192 {
12193 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
12194 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W);
12195 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this);
12196 }
12197 break;
12198 case 12:
12199 case 28:
12200 Vector3 scale7 = new Vector3(block.Data, 0);
12201 12609
12202 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 12610 udata.change = ObjectChangeType.groupR;
12203 if (handlerUpdatePrimGroupScale != null) 12611 updatehandler(localId, udata, this);
12204 { 12612 break;
12205 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
12206 handlerUpdatePrimGroupScale(localId, scale7, this);
12207 }
12208 break;
12209 12613
12210 case 13: 12614 case 0x0B: //( 8 + 2 + 1) group rotation and position
12211 Vector3 scale2 = new Vector3(block.Data, 12); 12615 udata.position = new Vector3(block.Data, 0);
12212 Vector3 pos4 = new Vector3(block.Data, 0); 12616 udata.rotation = new Quaternion(block.Data, 12, true);
12213 12617
12214 handlerUpdatePrimScale = OnUpdatePrimScale; 12618 udata.change = ObjectChangeType.groupPR;
12215 if (handlerUpdatePrimScale != null) 12619 updatehandler(localId, udata, this);
12216 { 12620 break;
12217 //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
12218 handlerUpdatePrimScale(localId, scale2, this);
12219 12621
12220 // Change the position based on scale (for bug number 246) 12622 case 0x0C: // (8 + 4) group scale
12221 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 12623 // only afects root prim and only sent by viewer editor object tab scaling
12222 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 12624 // mouse edition only allows uniform scaling
12223 if (handlerUpdatePrimSinglePosition != null) 12625 // SL MAY CHANGE THIS in viewers
12224 {
12225 handlerUpdatePrimSinglePosition(localId, pos4, this);
12226 }
12227 }
12228 break;
12229 12626
12230 case 29: 12627 udata.scale = new Vector3(block.Data, 0);
12231 Vector3 scale5 = new Vector3(block.Data, 12);
12232 Vector3 pos5 = new Vector3(block.Data, 0);
12233 12628
12234 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 12629 udata.change = ObjectChangeType.groupS;
12235 if (handlerUpdatePrimGroupScale != null) 12630 updatehandler(localId, udata, this);
12236 {
12237 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
12238 part.StoreUndoState(true);
12239 part.IgnoreUndoUpdate = true;
12240 handlerUpdatePrimGroupScale(localId, scale5, this);
12241 handlerUpdateVector = OnUpdatePrimGroupPosition;
12242 12631
12243 if (handlerUpdateVector != null) 12632 break;
12244 {
12245 handlerUpdateVector(localId, pos5, this);
12246 }
12247 12633
12248 part.IgnoreUndoUpdate = false; 12634 case 0x0D: //(8 + 4 + 1) group scale and position
12249 } 12635 // exception as above
12250 12636
12251 break; 12637 udata.position = new Vector3(block.Data, 0);
12638 udata.scale = new Vector3(block.Data, 12);
12252 12639
12253 case 21: 12640 udata.change = ObjectChangeType.groupPS;
12254 Vector3 scale6 = new Vector3(block.Data, 12); 12641 updatehandler(localId, udata, this);
12255 Vector3 pos6 = new Vector3(block.Data, 0); 12642 break;
12256 12643
12257 handlerUpdatePrimScale = OnUpdatePrimScale; 12644 case 0x1C: // (0x10 + 8 + 4 ) group scale UNIFORM
12258 if (handlerUpdatePrimScale != null) 12645 udata.scale = new Vector3(block.Data, 0);
12259 {
12260 part.StoreUndoState(false);
12261 part.IgnoreUndoUpdate = true;
12262 12646
12263 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); 12647 udata.change = ObjectChangeType.groupUS;
12264 handlerUpdatePrimScale(localId, scale6, this); 12648 updatehandler(localId, udata, this);
12265 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 12649 break;
12266 if (handlerUpdatePrimSinglePosition != null)
12267 {
12268 handlerUpdatePrimSinglePosition(localId, pos6, this);
12269 }
12270 12650
12271 part.IgnoreUndoUpdate = false; 12651 case 0x1D: // (UNIFORM + GROUP + SCALE + POS)
12272 } 12652 udata.position = new Vector3(block.Data, 0);
12273 break; 12653 udata.scale = new Vector3(block.Data, 12);
12274 12654
12275 default: 12655 udata.change = ObjectChangeType.groupPUS;
12276 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); 12656 updatehandler(localId, udata, this);
12277 break; 12657 break;
12658
12659 default:
12660 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type));
12661 break;
12662 }
12278 } 12663 }
12279 12664
12280// for (int j = 0; j < parts.Length; j++)
12281// parts[j].IgnoreUndoUpdate = false;
12282 } 12665 }
12283 } 12666 }
12284 } 12667 }
12285
12286 return true; 12668 return true;
12287 } 12669 }
12288 12670
@@ -12342,7 +12724,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12342 /// <param name="throttles"></param> 12724 /// <param name="throttles"></param>
12343 public void SetChildAgentThrottle(byte[] throttles) 12725 public void SetChildAgentThrottle(byte[] throttles)
12344 { 12726 {
12345 m_udpClient.SetThrottles(throttles); 12727 SetChildAgentThrottle(throttles, 1.0f);
12728 }
12729
12730 public void SetChildAgentThrottle(byte[] throttles,float factor)
12731 {
12732 m_udpClient.SetThrottles(throttles, factor);
12733 GenericCall2 handler = OnUpdateThrottles;
12734 if (handler != null)
12735 {
12736 handler();
12737 }
12738 }
12739
12740 /// <summary>
12741 /// Sets the throttles from values supplied caller
12742 /// </summary>
12743 /// <param name="throttles"></param>
12744 public void SetAgentThrottleSilent(int throttle, int setting)
12745 {
12746 m_udpClient.ForceThrottleSetting(throttle,setting);
12747 }
12748
12749 public int GetAgentThrottleSilent(int throttle)
12750 {
12751 return m_udpClient.GetThrottleSetting(throttle);
12346 } 12752 }
12347 12753
12348 /// <summary> 12754 /// <summary>
@@ -12450,8 +12856,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12450 uint regionY = 0; 12856 uint regionY = 0;
12451 12857
12452 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out regionX, out regionY); 12858 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out regionX, out regionY);
12453 locx = Convert.ToSingle(args[0]) - (float)regionX; 12859 locx = (float)(Convert.ToDouble(args[0]) - (double)regionX);
12454 locy = Convert.ToSingle(args[1]) - (float)regionY; 12860 locy = (float)(Convert.ToDouble(args[1]) - (double)regionY);
12455 locz = Convert.ToSingle(args[2]); 12861 locz = Convert.ToSingle(args[2]);
12456 12862
12457 Action<Vector3, bool, bool> handlerAutoPilotGo = OnAutoPilotGo; 12863 Action<Vector3, bool, bool> handlerAutoPilotGo = OnAutoPilotGo;
@@ -12736,7 +13142,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12736// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}", 13142// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}",
12737// requestID, taskID, (SourceType)sourceType, Name); 13143// requestID, taskID, (SourceType)sourceType, Name);
12738 13144
13145
13146 //Note, the bool returned from the below function is useless since it is always false.
12739 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 13147 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
13148
12740 } 13149 }
12741 13150
12742 /// <summary> 13151 /// <summary>
@@ -12819,7 +13228,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12819 /// <returns></returns> 13228 /// <returns></returns>
12820 private static int CalculateNumPackets(byte[] data) 13229 private static int CalculateNumPackets(byte[] data)
12821 { 13230 {
12822 const uint m_maxPacketSize = 600; 13231// const uint m_maxPacketSize = 600;
13232 uint m_maxPacketSize = MaxTransferBytesPerPacket;
12823 int numPackets = 1; 13233 int numPackets = 1;
12824 13234
12825 if (data == null) 13235 if (data == null)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index 0394e54..9293882 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -129,7 +129,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
129 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); 129 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
130 130
131 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary> 131 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
132 public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>(); 132 public readonly DoubleLocklessQueue<uint> PendingAcks = new DoubleLocklessQueue<uint>();
133 133
134 /// <summary>Current packet sequence number</summary> 134 /// <summary>Current packet sequence number</summary>
135 public int CurrentSequence; 135 public int CurrentSequence;
@@ -181,7 +181,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
181 /// <summary>Throttle buckets for each packet category</summary> 181 /// <summary>Throttle buckets for each packet category</summary>
182 private readonly TokenBucket[] m_throttleCategories; 182 private readonly TokenBucket[] m_throttleCategories;
183 /// <summary>Outgoing queues for throttled packets</summary> 183 /// <summary>Outgoing queues for throttled packets</summary>
184 private readonly OpenSim.Framework.LocklessQueue<OutgoingPacket>[] m_packetOutboxes = new OpenSim.Framework.LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT]; 184 private readonly DoubleLocklessQueue<OutgoingPacket>[] m_packetOutboxes = new DoubleLocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT];
185 /// <summary>A container that can hold one packet for each outbox, used to store 185 /// <summary>A container that can hold one packet for each outbox, used to store
186 /// dequeued packets that are being held for throttling</summary> 186 /// dequeued packets that are being held for throttling</summary>
187 private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; 187 private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT];
@@ -193,6 +193,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
193 193
194 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC 194 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
195 private int m_maxRTO = 60000; 195 private int m_maxRTO = 60000;
196 public bool m_deliverPackets = true;
197
198 private float m_burstTime;
199
200 public int m_lastStartpingTimeMS;
201 public int m_pingMS;
202
203 public int PingTimeMS
204 {
205 get
206 {
207 if (m_pingMS < 10)
208 return 10;
209 if(m_pingMS > 2000)
210 return 2000;
211 return m_pingMS;
212 }
213 }
196 214
197 /// <summary> 215 /// <summary>
198 /// This is the percentage of the udp texture queue to add to the task queue since 216 /// This is the percentage of the udp texture queue to add to the task queue since
@@ -232,6 +250,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
232 if (maxRTO != 0) 250 if (maxRTO != 0)
233 m_maxRTO = maxRTO; 251 m_maxRTO = maxRTO;
234 252
253<<<<<<< HEAD
235 ProcessUnackedSends = true; 254 ProcessUnackedSends = true;
236 255
237 // Create a token bucket throttle for this client that has the scene token bucket as a parent 256 // Create a token bucket throttle for this client that has the scene token bucket as a parent
@@ -240,16 +259,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
240 string.Format("adaptive throttle for {0} in {1}", AgentID, server.Scene.Name), 259 string.Format("adaptive throttle for {0} in {1}", AgentID, server.Scene.Name),
241 parentThrottle, 0, rates.Total, rates.MinimumAdaptiveThrottleRate, rates.AdaptiveThrottlesEnabled); 260 parentThrottle, 0, rates.Total, rates.MinimumAdaptiveThrottleRate, rates.AdaptiveThrottlesEnabled);
242 261
262=======
263 m_burstTime = rates.BrustTime;
264 float m_burst = rates.ClientMaxRate * m_burstTime;
265
266 // Create a token bucket throttle for this client that has the scene token bucket as a parent
267 m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.ClientMaxRate, m_burst, rates.AdaptiveThrottlesEnabled);
268>>>>>>> avn/ubitvar
243 // Create an array of token buckets for this clients different throttle categories 269 // Create an array of token buckets for this clients different throttle categories
244 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 270 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
245 271
246 m_cannibalrate = rates.CannibalizeTextureRate; 272 m_cannibalrate = rates.CannibalizeTextureRate;
247 273
274 m_burst = rates.Total * rates.BrustTime;
275
248 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 276 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
249 { 277 {
250 ThrottleOutPacketType type = (ThrottleOutPacketType)i; 278 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
251 279
252 // Initialize the packet outboxes, where packets sit while they are waiting for tokens 280 // Initialize the packet outboxes, where packets sit while they are waiting for tokens
281<<<<<<< HEAD
253 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); 282 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
254 283
255 // Initialize the token buckets that control the throttling for each category 284 // Initialize the token buckets that control the throttling for each category
@@ -257,6 +286,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
257 = new TokenBucket( 286 = new TokenBucket(
258 string.Format("{0} throttle for {1} in {2}", type, AgentID, server.Scene.Name), 287 string.Format("{0} throttle for {1} in {2}", type, AgentID, server.Scene.Name),
259 m_throttleClient, rates.GetRate(type), 0); 288 m_throttleClient, rates.GetRate(type), 0);
289=======
290 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
291 // Initialize the token buckets that control the throttling for each category
292 m_throttleCategories[i] = new TokenBucket(m_throttleClient, rates.GetRate(type), m_burst);
293>>>>>>> avn/ubitvar
260 } 294 }
261 295
262 // Default the retransmission timeout to one second 296 // Default the retransmission timeout to one second
@@ -264,6 +298,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
264 298
265 // Initialize this to a sane value to prevent early disconnects 299 // Initialize this to a sane value to prevent early disconnects
266 TickLastPacketReceived = Environment.TickCount & Int32.MaxValue; 300 TickLastPacketReceived = Environment.TickCount & Int32.MaxValue;
301 m_pingMS = (int)(3.0 * server.TickCountResolution); // so filter doesnt start at 0;
267 } 302 }
268 303
269 /// <summary> 304 /// <summary>
@@ -302,8 +337,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
302 m_info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; 337 m_info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
303 m_info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; 338 m_info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
304 m_info.totalThrottle = (int)m_throttleClient.DripRate; 339 m_info.totalThrottle = (int)m_throttleClient.DripRate;
340<<<<<<< HEAD
305 m_info.targetThrottle = (int)m_throttleClient.TargetDripRate; 341 m_info.targetThrottle = (int)m_throttleClient.TargetDripRate;
306 m_info.maxThrottle = (int)m_throttleClient.MaxDripRate; 342 m_info.maxThrottle = (int)m_throttleClient.MaxDripRate;
343=======
344>>>>>>> avn/ubitvar
307 345
308 return m_info; 346 return m_info;
309 } 347 }
@@ -389,6 +427,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
389 427
390 public void SetThrottles(byte[] throttleData) 428 public void SetThrottles(byte[] throttleData)
391 { 429 {
430 SetThrottles(throttleData, 1.0f);
431 }
432
433 public void SetThrottles(byte[] throttleData, float factor)
434 {
392 byte[] adjData; 435 byte[] adjData;
393 int pos = 0; 436 int pos = 0;
394 437
@@ -408,13 +451,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
408 } 451 }
409 452
410 // 0.125f converts from bits to bytes 453 // 0.125f converts from bits to bytes
411 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 454 float scale = 0.125f * factor;
412 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 455 int resend = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
413 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 456 int land = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
414 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 457 int wind = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
415 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 458 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
416 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 459 int task = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
417 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); 460 int texture = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
461 int asset = (int)(BitConverter.ToSingle(adjData, pos) * scale);
418 462
419 if (ThrottleDebugLevel > 0) 463 if (ThrottleDebugLevel > 0)
420 { 464 {
@@ -426,6 +470,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
426 470
427 // Make sure none of the throttles are set below our packet MTU, 471 // Make sure none of the throttles are set below our packet MTU,
428 // otherwise a throttle could become permanently clogged 472 // otherwise a throttle could become permanently clogged
473
474/* not using floats
429 resend = Math.Max(resend, LLUDPServer.MTU); 475 resend = Math.Max(resend, LLUDPServer.MTU);
430 land = Math.Max(land, LLUDPServer.MTU); 476 land = Math.Max(land, LLUDPServer.MTU);
431 wind = Math.Max(wind, LLUDPServer.MTU); 477 wind = Math.Max(wind, LLUDPServer.MTU);
@@ -433,12 +479,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
433 task = Math.Max(task, LLUDPServer.MTU); 479 task = Math.Max(task, LLUDPServer.MTU);
434 texture = Math.Max(texture, LLUDPServer.MTU); 480 texture = Math.Max(texture, LLUDPServer.MTU);
435 asset = Math.Max(asset, LLUDPServer.MTU); 481 asset = Math.Max(asset, LLUDPServer.MTU);
482*/
436 483
437 // Since most textures are now delivered through http, make it possible 484 // Since most textures are now delivered through http, make it possible
438 // to cannibalize some of the bw from the texture throttle to use for 485 // to cannibalize some of the bw from the texture throttle to use for
439 // the task queue (e.g. object updates) 486 // the task queue (e.g. object updates)
440 task = task + (int)(m_cannibalrate * texture); 487 task = task + (int)(m_cannibalrate * texture);
441 texture = (int)((1 - m_cannibalrate) * texture); 488 texture = (int)((1 - m_cannibalrate) * texture);
489<<<<<<< HEAD
442 490
443 //int total = resend + land + wind + cloud + task + texture + asset; 491 //int total = resend + land + wind + cloud + task + texture + asset;
444 492
@@ -449,6 +497,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
449 "[LLUDPCLIENT]: {0} is setting throttles in {1} to Resend={2}, Land={3}, Wind={4}, Cloud={5}, Task={6}, Texture={7}, Asset={8}, TOTAL = {9}", 497 "[LLUDPCLIENT]: {0} is setting throttles in {1} to Resend={2}, Land={3}, Wind={4}, Cloud={5}, Task={6}, Texture={7}, Asset={8}, TOTAL = {9}",
450 AgentID, m_udpServer.Scene.Name, resend, land, wind, cloud, task, texture, asset, total); 498 AgentID, m_udpServer.Scene.Name, resend, land, wind, cloud, task, texture, asset, total);
451 } 499 }
500=======
501
502 int total = resend + land + wind + cloud + task + texture + asset;
503
504 float m_burst = total * m_burstTime;
505
506 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
507 // AgentID, resend, land, wind, cloud, task, texture, asset, total);
508>>>>>>> avn/ubitvar
452 509
453 // Update the token buckets with new throttle values 510 // Update the token buckets with new throttle values
454 if (m_throttleClient.AdaptiveEnabled) 511 if (m_throttleClient.AdaptiveEnabled)
@@ -461,24 +518,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
461 518
462 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; 519 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
463 bucket.RequestedDripRate = resend; 520 bucket.RequestedDripRate = resend;
521 bucket.RequestedBurst = m_burst;
464 522
465 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land]; 523 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land];
466 bucket.RequestedDripRate = land; 524 bucket.RequestedDripRate = land;
525 bucket.RequestedBurst = m_burst;
467 526
468 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind]; 527 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind];
469 bucket.RequestedDripRate = wind; 528 bucket.RequestedDripRate = wind;
529 bucket.RequestedBurst = m_burst;
470 530
471 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud]; 531 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud];
472 bucket.RequestedDripRate = cloud; 532 bucket.RequestedDripRate = cloud;
533 bucket.RequestedBurst = m_burst;
473 534
474 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset]; 535 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset];
475 bucket.RequestedDripRate = asset; 536 bucket.RequestedDripRate = asset;
537 bucket.RequestedBurst = m_burst;
476 538
477 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task]; 539 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task];
478 bucket.RequestedDripRate = task; 540 bucket.RequestedDripRate = task;
541 bucket.RequestedBurst = m_burst;
479 542
480 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture]; 543 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture];
481 bucket.RequestedDripRate = texture; 544 bucket.RequestedDripRate = texture;
545 bucket.RequestedBurst = m_burst;
482 546
483 // Reset the packed throttles cached data 547 // Reset the packed throttles cached data
484 m_packedThrottles = null; 548 m_packedThrottles = null;
@@ -496,25 +560,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
496 int i = 0; 560 int i = 0;
497 561
498 // multiply by 8 to convert bytes back to bits 562 // multiply by 8 to convert bytes back to bits
499 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier; 563 multiplier *= 8;
564
565 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * multiplier;
500 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 566 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
501 567
502 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier; 568 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * multiplier;
503 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 569 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
504 570
505 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * 8 * multiplier; 571 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * multiplier;
506 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 572 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
507 573
508 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * 8 * multiplier; 574 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * multiplier;
509 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 575 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
510 576
511 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * 8 * multiplier; 577 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * multiplier;
512 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 578 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
513 579
514 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * 8 * multiplier; 580 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * multiplier;
515 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 581 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
516 582
517 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * 8 * multiplier; 583 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * multiplier;
518 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 584 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
519 585
520 m_packedThrottles = data; 586 m_packedThrottles = data;
@@ -523,6 +589,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
523 return data; 589 return data;
524 } 590 }
525 591
592 public int GetCatBytesInSendQueue(ThrottleOutPacketType cat)
593 {
594 ;
595 int icat = (int)cat;
596 if (icat > 0 && icat < THROTTLE_CATEGORY_COUNT)
597 {
598 TokenBucket bucket = m_throttleCategories[icat];
599 return m_packetOutboxes[icat].Count;
600 }
601 else
602 return 0;
603 }
604
605
606 public int GetCatBytesCanSend(ThrottleOutPacketType cat, int timeMS)
607 {
608 int icat = (int)cat;
609 if (icat > 0 && icat < THROTTLE_CATEGORY_COUNT)
610 {
611 TokenBucket bucket = m_throttleCategories[icat];
612 return bucket.GetCatBytesCanSend(timeMS);
613 }
614 else
615 return 0;
616 }
617
526 /// <summary> 618 /// <summary>
527 /// Queue an outgoing packet if appropriate. 619 /// Queue an outgoing packet if appropriate.
528 /// </summary> 620 /// </summary>
@@ -534,32 +626,41 @@ namespace OpenSim.Region.ClientStack.LindenUDP
534 /// </returns> 626 /// </returns>
535 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue) 627 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue)
536 { 628 {
629 return EnqueueOutgoing(packet, forceQueue, false);
630 }
631
632 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue, bool highPriority)
633 {
537 int category = (int)packet.Category; 634 int category = (int)packet.Category;
538 635
539 if (category >= 0 && category < m_packetOutboxes.Length) 636 if (category >= 0 && category < m_packetOutboxes.Length)
540 { 637 {
541 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 638 DoubleLocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
639
640 if (m_deliverPackets == false)
641 {
642 queue.Enqueue(packet, highPriority);
643 return true;
644 }
645
542 TokenBucket bucket = m_throttleCategories[category]; 646 TokenBucket bucket = m_throttleCategories[category];
543 647
544 // Don't send this packet if there is already a packet waiting in the queue 648 // Don't send this packet if queue is not empty
545 // even if we have the tokens to send it, tokens should go to the already 649 if (queue.Count > 0 || m_nextPackets[category] != null)
546 // queued packets
547 if (queue.Count > 0)
548 { 650 {
549 queue.Enqueue(packet); 651 queue.Enqueue(packet, highPriority);
550 return true; 652 return true;
551 } 653 }
552 654
553
554 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength)) 655 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
555 { 656 {
556 // Enough tokens were removed from the bucket, the packet will not be queued 657 // enough tokens so it can be sent imediatly by caller
557 return false; 658 return false;
558 } 659 }
559 else 660 else
560 { 661 {
561 // Force queue specified or not enough tokens in the bucket, queue this packet 662 // Force queue specified or not enough tokens in the bucket, queue this packet
562 queue.Enqueue(packet); 663 queue.Enqueue(packet, highPriority);
563 return true; 664 return true;
564 } 665 }
565 } 666 }
@@ -588,8 +689,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
588 /// <returns>True if any packets were sent, otherwise false</returns> 689 /// <returns>True if any packets were sent, otherwise false</returns>
589 public bool DequeueOutgoing() 690 public bool DequeueOutgoing()
590 { 691 {
591 OutgoingPacket packet; 692// if (m_deliverPackets == false) return false;
592 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 693
694 OutgoingPacket packet = null;
695 DoubleLocklessQueue<OutgoingPacket> queue;
593 TokenBucket bucket; 696 TokenBucket bucket;
594 bool packetSent = false; 697 bool packetSent = false;
595 ThrottleOutPacketTypeFlags emptyCategories = 0; 698 ThrottleOutPacketTypeFlags emptyCategories = 0;
@@ -613,6 +716,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
613 m_udpServer.SendPacketFinal(nextPacket); 716 m_udpServer.SendPacketFinal(nextPacket);
614 m_nextPackets[i] = null; 717 m_nextPackets[i] = null;
615 packetSent = true; 718 packetSent = true;
719
720 if (m_packetOutboxes[i].Count < 5)
721 emptyCategories |= CategoryToFlag(i);
616 } 722 }
617 } 723 }
618 else 724 else
@@ -620,32 +726,47 @@ namespace OpenSim.Region.ClientStack.LindenUDP
620 // No dequeued packet waiting to be sent, try to pull one off 726 // No dequeued packet waiting to be sent, try to pull one off
621 // this queue 727 // this queue
622 queue = m_packetOutboxes[i]; 728 queue = m_packetOutboxes[i];
623 if (queue.Dequeue(out packet)) 729 if (queue != null)
624 { 730 {
625 // A packet was pulled off the queue. See if we have 731 bool success = false;
626 // enough tokens in the bucket to send it out 732 try
627 if (bucket.RemoveTokens(packet.Buffer.DataLength))
628 { 733 {
629 // Send the packet 734 success = queue.Dequeue(out packet);
630 m_udpServer.SendPacketFinal(packet);
631 packetSent = true;
632 } 735 }
633 else 736 catch
634 { 737 {
635 // Save the dequeued packet for the next iteration 738 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
636 m_nextPackets[i] = packet;
637 } 739 }
740 if (success)
741 {
742 // A packet was pulled off the queue. See if we have
743 // enough tokens in the bucket to send it out
744 if (bucket.RemoveTokens(packet.Buffer.DataLength))
745 {
746 // Send the packet
747 m_udpServer.SendPacketFinal(packet);
748 packetSent = true;
749
750 if (queue.Count < 5)
751 emptyCategories |= CategoryToFlag(i);
752 }
753 else
754 {
755 // Save the dequeued packet for the next iteration
756 m_nextPackets[i] = packet;
757 }
638 758
639 // If the queue is empty after this dequeue, fire the queue 759 }
640 // empty callback now so it has a chance to fill before we 760 else
641 // get back here 761 {
642 if (queue.Count == 0) 762 // No packets in this queue. Fire the queue empty callback
763 // if it has not been called recently
643 emptyCategories |= CategoryToFlag(i); 764 emptyCategories |= CategoryToFlag(i);
765 }
644 } 766 }
645 else 767 else
646 { 768 {
647 // No packets in this queue. Fire the queue empty callback 769 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
648 // if it has not been called recently
649 emptyCategories |= CategoryToFlag(i); 770 emptyCategories |= CategoryToFlag(i);
650 } 771 }
651 } 772 }
@@ -712,6 +833,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
712 RTO = Math.Min(RTO * 2, m_maxRTO); 833 RTO = Math.Min(RTO * 2, m_maxRTO);
713 } 834 }
714 835
836
837 const int MIN_CALLBACK_MS = 10;
838
715 /// <summary> 839 /// <summary>
716 /// Does an early check to see if this queue empty callback is already 840 /// Does an early check to see if this queue empty callback is already
717 /// running, then asynchronously firing the event 841 /// running, then asynchronously firing the event
@@ -719,24 +843,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
719 /// <param name="categories">Throttle categories to fire the callback for</param> 843 /// <param name="categories">Throttle categories to fire the callback for</param>
720 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories) 844 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
721 { 845 {
722// if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) 846 if (!m_isQueueEmptyRunning)
723 if (!m_isQueueEmptyRunning && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
724 { 847 {
725 m_isQueueEmptyRunning = true;
726
727 int start = Environment.TickCount & Int32.MaxValue; 848 int start = Environment.TickCount & Int32.MaxValue;
728 const int MIN_CALLBACK_MS = 30; 849
850 if (start < m_nextOnQueueEmpty)
851 return;
852
853 m_isQueueEmptyRunning = true;
729 854
730 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; 855 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
731 if (m_nextOnQueueEmpty == 0) 856 if (m_nextOnQueueEmpty == 0)
732 m_nextOnQueueEmpty = 1; 857 m_nextOnQueueEmpty = 1;
733 858
734 // Use a value of 0 to signal that FireQueueEmpty is running 859 if (HasUpdates(categories))
735// m_nextOnQueueEmpty = 0;
736
737 m_categories = categories;
738
739 if (HasUpdates(m_categories))
740 { 860 {
741 if (!m_udpServer.OqrEngine.IsRunning) 861 if (!m_udpServer.OqrEngine.IsRunning)
742 { 862 {
@@ -756,7 +876,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
756 } 876 }
757 877
758 private bool m_isQueueEmptyRunning; 878 private bool m_isQueueEmptyRunning;
759 private ThrottleOutPacketTypeFlags m_categories = 0; 879
760 880
761 /// <summary> 881 /// <summary>
762 /// Fires the OnQueueEmpty callback and sets the minimum time that it 882 /// Fires the OnQueueEmpty callback and sets the minimum time that it
@@ -767,6 +887,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
767 /// signature</param> 887 /// signature</param>
768 public void FireQueueEmpty(object o) 888 public void FireQueueEmpty(object o)
769 { 889 {
890<<<<<<< HEAD
770// m_log.DebugFormat("[LLUDPCLIENT]: FireQueueEmpty for {0} in {1}", AgentID, m_udpServer.Scene.Name); 891// m_log.DebugFormat("[LLUDPCLIENT]: FireQueueEmpty for {0} in {1}", AgentID, m_udpServer.Scene.Name);
771 892
772// int start = Environment.TickCount & Int32.MaxValue; 893// int start = Environment.TickCount & Int32.MaxValue;
@@ -776,24 +897,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
776// { 897// {
777 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; 898 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
778 QueueEmpty callback = OnQueueEmpty; 899 QueueEmpty callback = OnQueueEmpty;
900=======
901 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
902 QueueEmpty callback = OnQueueEmpty;
903>>>>>>> avn/ubitvar
779 904
780 if (callback != null) 905 if (callback != null)
781 { 906 {
782// if (m_udpServer.IsRunningOutbound) 907 // if (m_udpServer.IsRunningOutbound)
783// { 908 // {
784 try { callback(categories); } 909 try { callback(categories); }
785 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); } 910 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
786// } 911 // }
787 } 912 }
788// }
789 913
790// m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; 914 m_isQueueEmptyRunning = false;
791// if (m_nextOnQueueEmpty == 0) 915 }
792// m_nextOnQueueEmpty = 1;
793 916
794// } 917 internal void ForceThrottleSetting(int throttle, int setting)
918 {
919 if (throttle > 0 && throttle < THROTTLE_CATEGORY_COUNT)
920 m_throttleCategories[throttle].RequestedDripRate = Math.Max(setting, LLUDPServer.MTU);
921 }
795 922
796 m_isQueueEmptyRunning = false; 923 internal int GetThrottleSetting(int throttle)
924 {
925 if (throttle > 0 && throttle < THROTTLE_CATEGORY_COUNT)
926 return (int)m_throttleCategories[throttle].RequestedDripRate;
927 else
928 return 0;
797 } 929 }
798 930
799 /// <summary> 931 /// <summary>
@@ -839,4 +971,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
839 } 971 }
840 } 972 }
841 } 973 }
974
975 public class DoubleLocklessQueue<T> : OpenSim.Framework.LocklessQueue<T>
976 {
977 OpenSim.Framework.LocklessQueue<T> highQueue = new OpenSim.Framework.LocklessQueue<T>();
978
979 public override int Count
980 {
981 get
982 {
983 return base.Count + highQueue.Count;
984 }
985 }
986
987 public override bool Dequeue(out T item)
988 {
989 if (highQueue.Dequeue(out item))
990 return true;
991
992 return base.Dequeue(out item);
993 }
994
995 public void Enqueue(T item, bool highPriority)
996 {
997 if (highPriority)
998 highQueue.Enqueue(item);
999 else
1000 Enqueue(item);
1001 }
1002 }
842} 1003}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 76be91a..41e19fd 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -241,7 +241,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
241 /// <summary>Handlers for incoming packets</summary> 241 /// <summary>Handlers for incoming packets</summary>
242 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 242 //PacketEventDictionary packetEvents = new PacketEventDictionary();
243 /// <summary>Incoming packets that are awaiting handling</summary> 243 /// <summary>Incoming packets that are awaiting handling</summary>
244 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 244 //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
245
246 private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>();
245 247
246 /// <summary>Bandwidth throttle for this UDP server</summary> 248 /// <summary>Bandwidth throttle for this UDP server</summary>
247 public TokenBucket Throttle { get; private set; } 249 public TokenBucket Throttle { get; private set; }
@@ -299,14 +301,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
299 /// <summary>Flag to signal when clients should send pings</summary> 301 /// <summary>Flag to signal when clients should send pings</summary>
300 protected bool m_sendPing; 302 protected bool m_sendPing;
301 303
304 private int m_animationSequenceNumber;
305
306 public int NextAnimationSequenceNumber
307 {
308 get
309 {
310 m_animationSequenceNumber++;
311 if (m_animationSequenceNumber > 2147482624)
312 m_animationSequenceNumber = 1;
313 return m_animationSequenceNumber;
314 }
315 }
316
317
318
319 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
320
302 /// <summary> 321 /// <summary>
303 /// Event used to signal when queued packets are available for sending. 322 /// Event used to signal when queued packets are available for sending.
304 /// </summary> 323 /// </summary>
305 /// <remarks> 324 /// <remarks>
306 /// This allows the outbound loop to only operate when there is data to send rather than continuously polling. 325 /// This allows the outbound loop to only operate when there is data to send rather than continuously polling.
307 /// Some data is sent immediately and not queued. That data would not trigger this event. 326 /// Some data is sent immediately and not queued. That data would not trigger this event.
327 /// WRONG use. May be usefull in future revision
308 /// </remarks> 328 /// </remarks>
309 private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false); 329// private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false);
310 330
311 private Pool<IncomingPacket> m_incomingPacketPool; 331 private Pool<IncomingPacket> m_incomingPacketPool;
312 332
@@ -388,16 +408,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
388 408
389 // Measure the resolution of Environment.TickCount 409 // Measure the resolution of Environment.TickCount
390 TickCountResolution = 0f; 410 TickCountResolution = 0f;
391 for (int i = 0; i < 5; i++) 411 for (int i = 0; i < 10; i++)
392 { 412 {
393 int start = Environment.TickCount; 413 int start = Environment.TickCount;
394 int now = start; 414 int now = start;
395 while (now == start) 415 while (now == start)
396 now = Environment.TickCount; 416 now = Environment.TickCount;
397 TickCountResolution += (float)(now - start) * 0.2f; 417 TickCountResolution += (float)(now - start) * 0.1f;
398 } 418 }
399 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms");
400 TickCountResolution = (float)Math.Ceiling(TickCountResolution); 419 TickCountResolution = (float)Math.Ceiling(TickCountResolution);
420 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms");
401 421
402 #endregion Environment.TickCount Measurement 422 #endregion Environment.TickCount Measurement
403 423
@@ -405,6 +425,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
405 int sceneThrottleBps = 0; 425 int sceneThrottleBps = 0;
406 bool usePools = false; 426 bool usePools = false;
407 427
428
429
408 IConfig config = configSource.Configs["ClientStack.LindenUDP"]; 430 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
409 if (config != null) 431 if (config != null)
410 { 432 {
@@ -451,6 +473,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
451 } 473 }
452 #endregion BinaryStats 474 #endregion BinaryStats
453 475
476<<<<<<< HEAD
454 // FIXME: Can't add info here because don't know scene yet. 477 // FIXME: Can't add info here because don't know scene yet.
455// m_throttle 478// m_throttle
456// = new TokenBucket( 479// = new TokenBucket(
@@ -458,8 +481,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
458 481
459 Throttle = new TokenBucket("server throttle bucket", null, 0, sceneThrottleBps); 482 Throttle = new TokenBucket("server throttle bucket", null, 0, sceneThrottleBps);
460 483
484=======
485 m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps * 10e-3f);
486>>>>>>> avn/ubitvar
461 ThrottleRates = new ThrottleRates(configSource); 487 ThrottleRates = new ThrottleRates(configSource);
462 488
489 Random rnd = new Random(Util.EnvironmentTickCount());
490 m_animationSequenceNumber = rnd.Next(11474826);
491
463 if (usePools) 492 if (usePools)
464 EnablePools(); 493 EnablePools();
465 } 494 }
@@ -755,8 +784,151 @@ namespace OpenSim.Region.ClientStack.LindenUDP
755 if (UsePools) 784 if (UsePools)
756 EnablePoolStats(); 785 EnablePoolStats();
757 786
787<<<<<<< HEAD
758 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this); 788 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this);
759 commands.Register(); 789 commands.Register();
790=======
791 MainConsole.Instance.Commands.AddCommand(
792 "Debug", false, "debug lludp packet",
793 "debug lludp packet [--default] <level> [<avatar-first-name> <avatar-last-name>]",
794 "Turn on packet debugging",
795 "If level > 255 then all incoming and outgoing packets are logged.\n"
796 + "If level <= 255 then incoming AgentUpdate and outgoing SimStats and SimulatorViewerTimeMessage packets are not logged.\n"
797 + "If level <= 200 then incoming RequestImage and outgoing ImagePacket, ImageData, LayerData and CoarseLocationUpdate packets are not logged.\n"
798 + "If level <= 100 then incoming ViewerEffect and AgentAnimation and outgoing ViewerEffect and AvatarAnimation packets are not logged.\n"
799 + "If level <= 50 then outgoing ImprovedTerseObjectUpdate packets are not logged.\n"
800 + "If level <= 0 then no packets are logged.\n"
801 + "If --default is specified then the level becomes the default logging level for all subsequent agents.\n"
802 + "In this case, you cannot also specify an avatar name.\n"
803 + "If an avatar name is given then only packets from that avatar are logged.",
804 HandlePacketCommand);
805
806 MainConsole.Instance.Commands.AddCommand(
807 "Debug",
808 false,
809 "debug lludp start",
810 "debug lludp start <in|out|all>",
811 "Control LLUDP packet processing.",
812 "No effect if packet processing has already started.\n"
813 + "in - start inbound processing.\n"
814 + "out - start outbound processing.\n"
815 + "all - start in and outbound processing.\n",
816 HandleStartCommand);
817
818 MainConsole.Instance.Commands.AddCommand(
819 "Debug",
820 false,
821 "debug lludp stop",
822 "debug lludp stop <in|out|all>",
823 "Stop LLUDP packet processing.",
824 "No effect if packet processing has already stopped.\n"
825 + "in - stop inbound processing.\n"
826 + "out - stop outbound processing.\n"
827 + "all - stop in and outbound processing.\n",
828 HandleStopCommand);
829
830 MainConsole.Instance.Commands.AddCommand(
831 "Debug",
832 false,
833 "debug lludp pool",
834 "debug lludp pool <on|off>",
835 "Turn object pooling within the lludp component on or off.",
836 HandlePoolCommand);
837
838 MainConsole.Instance.Commands.AddCommand(
839 "Debug",
840 false,
841 "debug lludp status",
842 "debug lludp status",
843 "Return status of LLUDP packet processing.",
844 HandleStatusCommand);
845/* disabled
846 MainConsole.Instance.Commands.AddCommand(
847 "Debug",
848 false,
849 "debug lludp toggle agentupdate",
850 "debug lludp toggle agentupdate",
851 "Toggle whether agentupdate packets are processed or simply discarded.",
852 HandleAgentUpdateCommand);
853 */
854 }
855
856 private void HandlePacketCommand(string module, string[] args)
857 {
858 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
859 return;
860
861 bool setAsDefaultLevel = false;
862 OptionSet optionSet = new OptionSet().Add("default", o => setAsDefaultLevel = o != null);
863 List<string> filteredArgs = optionSet.Parse(args);
864
865 string name = null;
866
867 if (filteredArgs.Count == 6)
868 {
869 if (!setAsDefaultLevel)
870 {
871 name = string.Format("{0} {1}", filteredArgs[4], filteredArgs[5]);
872 }
873 else
874 {
875 MainConsole.Instance.OutputFormat("ERROR: Cannot specify a user name when setting default logging level");
876 return;
877 }
878 }
879
880 if (filteredArgs.Count > 3)
881 {
882 int newDebug;
883 if (int.TryParse(filteredArgs[3], out newDebug))
884 {
885 if (setAsDefaultLevel)
886 {
887 DefaultClientPacketDebugLevel = newDebug;
888 MainConsole.Instance.OutputFormat(
889 "Debug packet debug for new clients set to {0} in {1}", DefaultClientPacketDebugLevel, m_scene.Name);
890 }
891 else
892 {
893 m_scene.ForEachScenePresence(sp =>
894 {
895 if (name == null || sp.Name == name)
896 {
897 MainConsole.Instance.OutputFormat(
898 "Packet debug for {0} ({1}) set to {2} in {3}",
899 sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, m_scene.Name);
900
901 sp.ControllingClient.DebugPacketLevel = newDebug;
902 }
903 });
904 }
905 }
906 else
907 {
908 MainConsole.Instance.Output("Usage: debug lludp packet [--default] 0..255 [<first-name> <last-name>]");
909 }
910 }
911 }
912
913 private void HandleStartCommand(string module, string[] args)
914 {
915 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
916 return;
917
918 if (args.Length != 4)
919 {
920 MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>");
921 return;
922 }
923
924 string subCommand = args[3];
925
926 if (subCommand == "in" || subCommand == "all")
927 StartInbound();
928
929 if (subCommand == "out" || subCommand == "all")
930 StartOutbound();
931>>>>>>> avn/ubitvar
760 } 932 }
761 933
762 public bool HandlesRegion(Location x) 934 public bool HandlesRegion(Location x)
@@ -864,8 +1036,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
864 1036
865 PacketPool.Instance.ReturnPacket(packet); 1037 PacketPool.Instance.ReturnPacket(packet);
866 1038
867 if (packetQueued) 1039 /// WRONG use. May be usefull in future revision
868 m_dataPresentEvent.Set(); 1040// if (packetQueued)
1041// m_dataPresentEvent.Set();
869 } 1042 }
870 1043
871 /// <summary> 1044 /// <summary>
@@ -936,6 +1109,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
936 1109
937 #region Queue or Send 1110 #region Queue or Send
938 1111
1112 bool highPriority = false;
1113
1114 if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0)
1115 {
1116 category = (ThrottleOutPacketType)((int)category & 127);
1117 highPriority = true;
1118 }
1119
939 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); 1120 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
940 1121
941 // If we were not provided a method for handling unacked, use the UDPServer default method 1122 // If we were not provided a method for handling unacked, use the UDPServer default method
@@ -945,6 +1126,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
945 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will 1126 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
946 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object 1127 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object
947 // packet so that it isn't sent before a queued update packet. 1128 // packet so that it isn't sent before a queued update packet.
1129<<<<<<< HEAD
948 bool forceQueue = (type == PacketType.KillObject); 1130 bool forceQueue = (type == PacketType.KillObject);
949 1131
950// if (type == PacketType.ImprovedTerseObjectUpdate) 1132// if (type == PacketType.ImprovedTerseObjectUpdate)
@@ -956,15 +1138,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
956// else 1138// else
957// { 1139// {
958 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forceQueue)) 1140 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forceQueue))
1141=======
1142 bool requestQueue = type == PacketType.KillObject;
1143 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority))
1144>>>>>>> avn/ubitvar
959 { 1145 {
960 SendPacketFinal(outgoingPacket); 1146 SendPacketFinal(outgoingPacket);
961 return true; 1147 return true;
962 } 1148 }
1149<<<<<<< HEAD
963 else 1150 else
964 { 1151 {
965 return false; 1152 return false;
966 } 1153 }
967// } 1154// }
1155=======
1156
1157 return false;
1158>>>>>>> avn/ubitvar
968 1159
969 #endregion Queue or Send 1160 #endregion Queue or Send
970 } 1161 }
@@ -1005,6 +1196,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1005 pc.PingID.OldestUnacked = 0; 1196 pc.PingID.OldestUnacked = 0;
1006 1197
1007 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null); 1198 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null);
1199 udpClient.m_lastStartpingTimeMS = Util.EnvironmentTickCount();
1008 } 1200 }
1009 1201
1010 public void CompletePing(LLUDPClient udpClient, byte pingID) 1202 public void CompletePing(LLUDPClient udpClient, byte pingID)
@@ -1102,7 +1294,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1102 int dataLength = buffer.DataLength; 1294 int dataLength = buffer.DataLength;
1103 1295
1104 // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here 1296 // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here
1105 if (!isZerocoded) 1297 if (!isZerocoded && !isResend && outgoingPacket.UnackedMethod == null)
1106 { 1298 {
1107 // Keep appending ACKs until there is no room left in the buffer or there are 1299 // Keep appending ACKs until there is no room left in the buffer or there are
1108 // no more ACKs to append 1300 // no more ACKs to append
@@ -1268,35 +1460,76 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1268 1460
1269 #region Packet to Client Mapping 1461 #region Packet to Client Mapping
1270 1462
1271 // UseCircuitCode handling 1463 // If there is already a client for this endpoint, don't process UseCircuitCode
1272 if (packet.Type == PacketType.UseCircuitCode) 1464 IClientAPI client = null;
1465 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
1273 { 1466 {
1274 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1467 // UseCircuitCode handling
1275 // buffer. 1468 if (packet.Type == PacketType.UseCircuitCode)
1276 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 1469 {
1470 // And if there is a UseCircuitCode pending, also drop it
1471 lock (m_pendingCache)
1472 {
1473 if (m_pendingCache.Contains(endPoint))
1474 return;
1277 1475
1476<<<<<<< HEAD
1278 Util.FireAndForget(HandleUseCircuitCode, array, "LLUDPServer.HandleUseCircuitCode"); 1477 Util.FireAndForget(HandleUseCircuitCode, array, "LLUDPServer.HandleUseCircuitCode");
1478=======
1479 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
1480 }
1481>>>>>>> avn/ubitvar
1279 1482
1280 return; 1483 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1484 // buffer.
1485 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1486
1487 Util.FireAndForget(HandleUseCircuitCode, array);
1488
1489 return;
1490 }
1281 } 1491 }
1282 else if (packet.Type == PacketType.CompleteAgentMovement) 1492
1493 // If this is a pending connection, enqueue, don't process yet
1494 lock (m_pendingCache)
1283 { 1495 {
1284 // Send ack straight away to let the viewer know that we got it. 1496 Queue<UDPPacketBuffer> queue;
1285 SendAckImmediate(endPoint, packet.Header.Sequence); 1497 if (m_pendingCache.TryGetValue(endPoint, out queue))
1498 {
1499 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
1500 queue.Enqueue(buffer);
1501 return;
1502 }
1286 1503
1287 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1504/*
1288 // buffer. 1505 else if (packet.Type == PacketType.CompleteAgentMovement)
1289 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 1506 {
1507 // Send ack straight away to let the viewer know that we got it.
1508 SendAckImmediate(endPoint, packet.Header.Sequence);
1290 1509
1510<<<<<<< HEAD
1291 Util.FireAndForget( 1511 Util.FireAndForget(
1292 HandleCompleteMovementIntoRegion, array, "LLUDPServer.HandleCompleteMovementIntoRegion"); 1512 HandleCompleteMovementIntoRegion, array, "LLUDPServer.HandleCompleteMovementIntoRegion");
1513=======
1514 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1515 // buffer.
1516 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1517>>>>>>> avn/ubitvar
1293 1518
1294 return; 1519 Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
1520
1521 return;
1522 }
1523 */
1295 } 1524 }
1296 1525
1297 // Determine which agent this packet came from 1526 // Determine which agent this packet came from
1527<<<<<<< HEAD
1298 IClientAPI client; 1528 IClientAPI client;
1299 if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) 1529 if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
1530=======
1531 if (client == null || !(client is LLClientView))
1532>>>>>>> avn/ubitvar
1300 { 1533 {
1301 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 1534 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
1302 1535
@@ -1313,7 +1546,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1313 udpClient = ((LLClientView)client).UDPClient; 1546 udpClient = ((LLClientView)client).UDPClient;
1314 1547
1315 if (!udpClient.IsConnected) 1548 if (!udpClient.IsConnected)
1549 {
1550 m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName);
1316 return; 1551 return;
1552 }
1317 1553
1318 #endregion Packet to Client Mapping 1554 #endregion Packet to Client Mapping
1319 1555
@@ -1416,6 +1652,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1416 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); 1652 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
1417 #endregion BinaryStats 1653 #endregion BinaryStats
1418 1654
1655<<<<<<< HEAD
1419 if (packet.Type == PacketType.AgentUpdate) 1656 if (packet.Type == PacketType.AgentUpdate)
1420 { 1657 {
1421 if (DiscardInboundAgentUpdates) 1658 if (DiscardInboundAgentUpdates)
@@ -1434,6 +1671,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1434 return; 1671 return;
1435 } 1672 }
1436 } 1673 }
1674=======
1675// AgentUpdate mess removed from here
1676>>>>>>> avn/ubitvar
1437 1677
1438 #region Ping Check Handling 1678 #region Ping Check Handling
1439 1679
@@ -1444,7 +1684,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1444 // We don't need to do anything else with ping checks 1684 // We don't need to do anything else with ping checks
1445 StartPingCheckPacket startPing = (StartPingCheckPacket)packet; 1685 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
1446 CompletePing(udpClient, startPing.PingID.PingID); 1686 CompletePing(udpClient, startPing.PingID.PingID);
1447 1687
1448 if ((Environment.TickCount - m_elapsedMSSinceLastStatReport) >= 3000) 1688 if ((Environment.TickCount - m_elapsedMSSinceLastStatReport) >= 3000)
1449 { 1689 {
1450 udpClient.SendPacketStats(); 1690 udpClient.SendPacketStats();
@@ -1454,7 +1694,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1454 } 1694 }
1455 else if (packet.Type == PacketType.CompletePingCheck) 1695 else if (packet.Type == PacketType.CompletePingCheck)
1456 { 1696 {
1457 // We don't currently track client ping times 1697 int t = Util.EnvironmentTickCountSubtract(udpClient.m_lastStartpingTimeMS);
1698 int c = udpClient.m_pingMS;
1699 c = 800 * c + 200 * t;
1700 c /= 1000;
1701 udpClient.m_pingMS = c;
1458 return; 1702 return;
1459 } 1703 }
1460 1704
@@ -1474,7 +1718,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1474 incomingPacket = new IncomingPacket((LLClientView)client, packet); 1718 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1475 } 1719 }
1476 1720
1477 packetInbox.Enqueue(incomingPacket); 1721// if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1722// incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1723 if (incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1724 packetInbox.EnqueueHigh(incomingPacket);
1725 else
1726 packetInbox.EnqueueLow(incomingPacket);
1727
1478 } 1728 }
1479 1729
1480 #region BinaryStats 1730 #region BinaryStats
@@ -1591,7 +1841,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1591 1841
1592 try 1842 try
1593 { 1843 {
1594 // DateTime startTime = DateTime.Now; 1844// DateTime startTime = DateTime.Now;
1595 object[] array = (object[])o; 1845 object[] array = (object[])o;
1596 endPoint = (IPEndPoint)array[0]; 1846 endPoint = (IPEndPoint)array[0];
1597 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 1847 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
@@ -1603,6 +1853,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1603 AuthenticateResponse sessionInfo; 1853 AuthenticateResponse sessionInfo;
1604 if (IsClientAuthorized(uccp, out sessionInfo)) 1854 if (IsClientAuthorized(uccp, out sessionInfo))
1605 { 1855 {
1856 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1857
1606 // Begin the process of adding the client to the simulator 1858 // Begin the process of adding the client to the simulator
1607 client 1859 client
1608 = AddClient( 1860 = AddClient(
@@ -1611,16 +1863,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1611 uccp.CircuitCode.SessionID, 1863 uccp.CircuitCode.SessionID,
1612 endPoint, 1864 endPoint,
1613 sessionInfo); 1865 sessionInfo);
1614 1866
1867 // This will be true if the client is new, e.g. not
1868 // an existing child agent, and there is no circuit data
1869 if (client != null && aCircuit == null)
1870 {
1871 m_scene.CloseAgent(client.AgentId, true);
1872 return;
1873 }
1874
1875 // Now we know we can handle more data
1876 Thread.Sleep(200);
1877
1878 // Obtain the pending queue and remove it from the cache
1879 Queue<UDPPacketBuffer> queue = null;
1880
1881 lock (m_pendingCache)
1882 {
1883 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1884 {
1885 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1886 return;
1887
1888 }
1889 m_pendingCache.Remove(endPoint);
1890 }
1891
1892 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1893
1894 // Reinject queued packets
1895 while (queue.Count > 0)
1896 {
1897 UDPPacketBuffer buf = queue.Dequeue();
1898 PacketReceived(buf);
1899 }
1900
1901 queue = null;
1902
1615 // Send ack straight away to let the viewer know that the connection is active. 1903 // Send ack straight away to let the viewer know that the connection is active.
1616 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use 1904 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use
1617 // circuit code to the existing child agent. This is not particularly obvious. 1905 // circuit code to the existing child agent. This is not particularly obvious.
1618 SendAckImmediate(endPoint, uccp.Header.Sequence); 1906 SendAckImmediate(endPoint, uccp.Header.Sequence);
1619 1907
1620 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1908 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1621 if (client != null) 1909 if (client != null)
1622 { 1910 {
1911<<<<<<< HEAD
1623 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code); 1912 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1913=======
1914>>>>>>> avn/ubitvar
1624 bool tp = (aCircuit.teleportFlags > 0); 1915 bool tp = (aCircuit.teleportFlags > 0);
1625 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from 1916 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from
1626 if (!tp && !client.SceneAgent.SentInitialDataToClient) 1917 if (!tp && !client.SceneAgent.SentInitialDataToClient)
@@ -1632,9 +1923,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1632 // Don't create clients for unauthorized requesters. 1923 // Don't create clients for unauthorized requesters.
1633 m_log.WarnFormat( 1924 m_log.WarnFormat(
1634 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1925 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1926<<<<<<< HEAD
1635 uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1927 uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1636 } 1928 }
1637 1929
1930=======
1931 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1932
1933 lock (m_pendingCache)
1934 m_pendingCache.Remove(endPoint);
1935 }
1936>>>>>>> avn/ubitvar
1638 // m_log.DebugFormat( 1937 // m_log.DebugFormat(
1639 // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", 1938 // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms",
1640 // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); 1939 // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds);
@@ -1651,8 +1950,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1651 e.StackTrace); 1950 e.StackTrace);
1652 } 1951 }
1653 } 1952 }
1654 1953/*
1655 private void HandleCompleteMovementIntoRegion(object o) 1954 private void HandleCompleteMovementIntoRegion(object o)
1656 { 1955 {
1657 IPEndPoint endPoint = null; 1956 IPEndPoint endPoint = null;
1658 IClientAPI client = null; 1957 IClientAPI client = null;
@@ -1761,6 +2060,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1761 e.StackTrace); 2060 e.StackTrace);
1762 } 2061 }
1763 } 2062 }
2063*/
1764 2064
1765 /// <summary> 2065 /// <summary>
1766 /// Send an ack immediately to the given endpoint. 2066 /// Send an ack immediately to the given endpoint.
@@ -1818,6 +2118,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1818 uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) 2118 uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
1819 { 2119 {
1820 IClientAPI client = null; 2120 IClientAPI client = null;
2121 bool createNew = false;
1821 2122
1822 // We currently synchronize this code across the whole scene to avoid issues such as 2123 // We currently synchronize this code across the whole scene to avoid issues such as
1823 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done 2124 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done
@@ -1826,7 +2127,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1826 { 2127 {
1827 if (!Scene.TryGetClient(agentID, out client)) 2128 if (!Scene.TryGetClient(agentID, out client))
1828 { 2129 {
2130<<<<<<< HEAD
1829 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, Throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 2131 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, Throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
2132=======
2133 createNew = true;
2134 }
2135 else
2136 {
2137 if (client.SceneAgent == null)
2138 {
2139 m_scene.CloseAgent(agentID, true);
2140 createNew = true;
2141 }
2142 }
2143
2144 if (createNew)
2145 {
2146 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
2147>>>>>>> avn/ubitvar
1830 2148
1831 client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 2149 client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1832 client.OnLogout += LogoutHandler; 2150 client.OnLogout += LogoutHandler;
@@ -1856,15 +2174,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1856 { 2174 {
1857 ClientLogoutsDueToNoReceives++; 2175 ClientLogoutsDueToNoReceives++;
1858 2176
2177<<<<<<< HEAD
1859 m_log.WarnFormat( 2178 m_log.WarnFormat(
1860 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.", 2179 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.",
1861 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name); 2180 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name);
2181=======
2182 if (client.SceneAgent != null)
2183 {
2184 m_log.WarnFormat(
2185 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.",
2186 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, m_scene.Name);
2187>>>>>>> avn/ubitvar
1862 2188
1863 if (!client.SceneAgent.IsChildAgent) 2189 if (!client.SceneAgent.IsChildAgent)
1864 client.Kick("Simulator logged you out due to connection timeout."); 2190 client.Kick("Simulator logged you out due to connection timeout.");
2191 }
1865 } 2192 }
1866 2193
2194<<<<<<< HEAD
1867 Scene.CloseAgent(client.AgentId, true); 2195 Scene.CloseAgent(client.AgentId, true);
2196=======
2197 if (!m_scene.CloseAgent(client.AgentId, true))
2198 client.Close(true,true);
2199>>>>>>> avn/ubitvar
1868 } 2200 }
1869 2201
1870 private void IncomingPacketHandler() 2202 private void IncomingPacketHandler()
@@ -1877,6 +2209,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1877 2209
1878 while (IsRunningInbound) 2210 while (IsRunningInbound)
1879 { 2211 {
2212 m_scene.ThreadAlive(1);
1880 try 2213 try
1881 { 2214 {
1882 IncomingPacket incomingPacket = null; 2215 IncomingPacket incomingPacket = null;
@@ -1899,7 +2232,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1899 m_incomingPacketPool.ReturnObject(incomingPacket); 2232 m_incomingPacketPool.ReturnObject(incomingPacket);
1900 } 2233 }
1901 } 2234 }
1902 catch (Exception ex) 2235 catch(Exception ex)
1903 { 2236 {
1904 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); 2237 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
1905 } 2238 }
@@ -1928,6 +2261,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1928 2261
1929 while (base.IsRunningOutbound) 2262 while (base.IsRunningOutbound)
1930 { 2263 {
2264 m_scene.ThreadAlive(2);
1931 try 2265 try
1932 { 2266 {
1933 m_packetSent = false; 2267 m_packetSent = false;
@@ -1986,13 +2320,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1986 2320
1987 // If nothing was sent, sleep for the minimum amount of time before a 2321 // If nothing was sent, sleep for the minimum amount of time before a
1988 // token bucket could get more tokens 2322 // token bucket could get more tokens
1989 //if (!m_packetSent) 2323
1990 // Thread.Sleep((int)TickCountResolution);
1991 //
1992 // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with
1993 // modern mono it reduces CPU base load since there is no more continuous polling.
1994 if (!m_packetSent) 2324 if (!m_packetSent)
1995 m_dataPresentEvent.WaitOne(100); 2325 Thread.Sleep((int)TickCountResolution);
2326
2327 // .... wrong core code removed
2328
1996 2329
1997 Watchdog.UpdateThread(); 2330 Watchdog.UpdateThread();
1998 } 2331 }
@@ -2163,8 +2496,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2163 Packet packet = incomingPacket.Packet; 2496 Packet packet = incomingPacket.Packet;
2164 LLClientView client = incomingPacket.Client; 2497 LLClientView client = incomingPacket.Client;
2165 2498
2166 if (client.IsActive) 2499// if (client.IsActive)
2167 { 2500// {
2168 m_currentIncomingClient = client; 2501 m_currentIncomingClient = client;
2169 2502
2170 try 2503 try
@@ -2191,6 +2524,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2191 { 2524 {
2192 m_currentIncomingClient = null; 2525 m_currentIncomingClient = null;
2193 } 2526 }
2527<<<<<<< HEAD
2194 } 2528 }
2195 else 2529 else
2196 { 2530 {
@@ -2198,6 +2532,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2198 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 2532 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
2199 packet.Type, client.Name, Scene.RegionInfo.RegionName); 2533 packet.Type, client.Name, Scene.RegionInfo.RegionName);
2200 } 2534 }
2535=======
2536// }
2537// else
2538// {
2539// m_log.DebugFormat(
2540// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
2541// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
2542// }
2543>>>>>>> avn/ubitvar
2201 2544
2202 IncomingPacketsProcessed++; 2545 IncomingPacketsProcessed++;
2203 } 2546 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index f62dc15..7171974 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -206,16 +206,16 @@ namespace OpenMetaverse
206 const int SIO_UDP_CONNRESET = -1744830452; 206 const int SIO_UDP_CONNRESET = -1744830452;
207 207
208 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 208 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
209
210 m_log.DebugFormat(
211 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
212 ipep.Address, ipep.Port);
213 209
214 m_udpSocket = new Socket( 210 m_udpSocket = new Socket(
215 AddressFamily.InterNetwork, 211 AddressFamily.InterNetwork,
216 SocketType.Dgram, 212 SocketType.Dgram,
217 ProtocolType.Udp); 213 ProtocolType.Udp);
218 214
215 // OpenSim may need this but in AVN, this messes up automated
216 // sim restarts badly
217 //m_udpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, false);
218
219 try 219 try
220 { 220 {
221 if (m_udpSocket.Ttl < 128) 221 if (m_udpSocket.Ttl < 128)
@@ -501,4 +501,4 @@ namespace OpenMetaverse
501 catch (ObjectDisposedException) { } 501 catch (ObjectDisposedException) { }
502 } 502 }
503 } 503 }
504} \ No newline at end of file 504}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
index 7a2756b..076551f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
@@ -69,6 +69,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
69 /// <summary>Amount of the texture throttle to steal for the task throttle</summary> 69 /// <summary>Amount of the texture throttle to steal for the task throttle</summary>
70 public double CannibalizeTextureRate; 70 public double CannibalizeTextureRate;
71 71
72 public int ClientMaxRate;
73 public float BrustTime;
74
72 /// <summary> 75 /// <summary>
73 /// Default constructor 76 /// Default constructor
74 /// </summary> 77 /// </summary>
@@ -88,7 +91,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
88 Texture = throttleConfig.GetInt("texture_default", 18500); 91 Texture = throttleConfig.GetInt("texture_default", 18500);
89 Asset = throttleConfig.GetInt("asset_default", 10500); 92 Asset = throttleConfig.GetInt("asset_default", 10500);
90 93
91 Total = throttleConfig.GetInt("client_throttle_max_bps", 0); 94 Total = Resend + Land + Wind + Cloud + Task + Texture + Asset;
95 // 3000000 bps default max
96 ClientMaxRate = throttleConfig.GetInt("client_throttle_max_bps", 375000);
97 if (ClientMaxRate > 1000000)
98 ClientMaxRate = 1000000; // no more than 8Mbps
99
100 BrustTime = (float)throttleConfig.GetInt("client_throttle_burtsTimeMS", 10);
101 BrustTime *= 1e-3f;
92 102
93 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); 103 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
94 MinimumAdaptiveThrottleRate = throttleConfig.GetInt("adaptive_throttle_min_bps", 32000); 104 MinimumAdaptiveThrottleRate = throttleConfig.GetInt("adaptive_throttle_min_bps", 32000);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
index 4616203..7a42d82 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
@@ -42,6 +42,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
42 public class TokenBucket 42 public class TokenBucket
43 { 43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45<<<<<<< HEAD
45 46
46 public string Identifier { get; private set; } 47 public string Identifier { get; private set; }
47 48
@@ -52,16 +53,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
52 /// are defined over this interval. 53 /// are defined over this interval.
53 /// </summary> 54 /// </summary>
54 protected const Int32 m_ticksPerQuantum = 1000; 55 protected const Int32 m_ticksPerQuantum = 1000;
56=======
57 private static Int32 m_counter = 0;
58
59// private Int32 m_identifier;
60
61 protected const float m_timeScale = 1e-3f;
62>>>>>>> avn/ubitvar
55 63
56 /// <summary> 64 /// <summary>
57 /// This is the number of quantums worth of packets that can 65 /// This is the number of m_minimumDripRate bytes
58 /// be accommodated during a burst 66 /// allowed in a burst
67 /// roughtly, with this settings, the maximum time system will take
68 /// to recheck a bucket in ms
69 ///
59 /// </summary> 70 /// </summary>
60 protected const Double m_quantumsPerBurst = 1.5; 71 protected const float m_quantumsPerBurst = 5;
61 72
62 /// <summary> 73 /// <summary>
63 /// </summary> 74 /// </summary>
75<<<<<<< HEAD
64 protected const Int32 m_minimumDripRate = LLUDPServer.MTU; 76 protected const Int32 m_minimumDripRate = LLUDPServer.MTU;
77=======
78 protected const float m_minimumDripRate = 1400;
79>>>>>>> avn/ubitvar
65 80
66 /// <summary>Time of the last drip, in system ticks</summary> 81 /// <summary>Time of the last drip, in system ticks</summary>
67 protected Int32 m_lastDrip; 82 protected Int32 m_lastDrip;
@@ -70,12 +85,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
70 /// The number of bytes that can be sent at this moment. This is the 85 /// The number of bytes that can be sent at this moment. This is the
71 /// current number of tokens in the bucket 86 /// current number of tokens in the bucket
72 /// </summary> 87 /// </summary>
73 protected Int64 m_tokenCount; 88 protected float m_tokenCount;
74 89
75 /// <summary> 90 /// <summary>
76 /// Map of children buckets and their requested maximum burst rate 91 /// Map of children buckets and their requested maximum burst rate
77 /// </summary> 92 /// </summary>
93<<<<<<< HEAD
78 protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>(); 94 protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>();
95=======
96 protected Dictionary<TokenBucket, float> m_children = new Dictionary<TokenBucket, float>();
97
98#region Properties
99>>>>>>> avn/ubitvar
79 100
80 /// <summary> 101 /// <summary>
81 /// The parent bucket of this bucket, or null if this bucket has no 102 /// The parent bucket of this bucket, or null if this bucket has no
@@ -85,25 +106,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
85 public TokenBucket Parent { get; protected set; } 106 public TokenBucket Parent { get; protected set; }
86 107
87 /// <summary> 108 /// <summary>
88 /// Maximum burst rate in bytes per second. This is the maximum number 109 /// This is the maximum number
89 /// of tokens that can accumulate in the bucket at any one time. This 110 /// of tokens that can accumulate in the bucket at any one time. This
90 /// also sets the total request for leaf nodes 111 /// also sets the total request for leaf nodes
91 /// </summary> 112 /// </summary>
92 protected Int64 m_burstRate; 113 protected float m_burst;
93 public Int64 RequestedBurstRate 114 public float RequestedBurst
94 { 115 {
95 get { return m_burstRate; } 116 get { return m_burst; }
96 set { m_burstRate = (value < 0 ? 0 : value); } 117 set {
118 float rate = (value < 0 ? 0 : value);
119 if (rate < m_minimumDripRate)
120 rate = m_minimumDripRate;
121 else if (rate > m_minimumDripRate * m_quantumsPerBurst)
122 rate = m_minimumDripRate * m_quantumsPerBurst;
123
124 m_burst = rate;
125 }
97 } 126 }
98 127
99 public Int64 BurstRate 128 public float Burst
100 { 129 {
101 get { 130 get {
102 double rate = RequestedBurstRate * BurstRateModifier(); 131 float rate = RequestedBurst * BurstModifier();
103 if (rate < m_minimumDripRate * m_quantumsPerBurst) 132 if (rate < m_minimumDripRate)
104 rate = m_minimumDripRate * m_quantumsPerBurst; 133 rate = m_minimumDripRate;
105 134 return (float)rate;
106 return (Int64) rate;
107 } 135 }
108 } 136 }
109 137
@@ -115,6 +143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
115 /// Can never be above MaxDripRate. 143 /// Can never be above MaxDripRate.
116 /// Tokens are added to the bucket at any time 144 /// Tokens are added to the bucket at any time
117 /// <seealso cref="RemoveTokens"/> is called, at the granularity of 145 /// <seealso cref="RemoveTokens"/> is called, at the granularity of
146<<<<<<< HEAD
118 /// the system tick interval (typically around 15-22ms) 147 /// the system tick interval (typically around 15-22ms)
119 /// FIXME: It is extremely confusing to be able to set a RequestedDripRate of 0 and then receive a positive 148 /// FIXME: It is extremely confusing to be able to set a RequestedDripRate of 0 and then receive a positive
120 /// number on get if TotalDripRequest is set. This also stops us being able to retrieve the fact that 149 /// number on get if TotalDripRequest is set. This also stops us being able to retrieve the fact that
@@ -168,12 +197,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
168 rate = (double)RequestedDripRate * Parent.DripRateModifier(); 197 rate = (double)RequestedDripRate * Parent.DripRateModifier();
169 } 198 }
170 199
200=======
201 /// the system tick interval (typically around 15-22ms)</remarks>
202 protected float m_dripRate;
203 public virtual float RequestedDripRate
204 {
205 get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
206 set {
207 m_dripRate = (value < 0 ? 0 : value);
208 m_totalDripRequest = m_dripRate;
209
210 if (m_parent != null)
211 m_parent.RegisterRequest(this,m_dripRate);
212 }
213 }
214
215 public virtual float DripRate
216 {
217 get {
218 float rate = Math.Min(RequestedDripRate,TotalDripRequest);
219 if (m_parent == null)
220 return rate;
221
222 rate *= m_parent.DripRateModifier();
223>>>>>>> avn/ubitvar
171 if (rate < m_minimumDripRate) 224 if (rate < m_minimumDripRate)
172 rate = m_minimumDripRate; 225 rate = m_minimumDripRate;
173 else if (MaxDripRate > 0 && rate > MaxDripRate) 226 else if (MaxDripRate > 0 && rate > MaxDripRate)
174 rate = MaxDripRate; 227 rate = MaxDripRate;
175 228
176 return (Int64)rate; 229 return (float)rate;
177 } 230 }
178 } 231 }
179 protected Int64 m_dripRate; 232 protected Int64 m_dripRate;
@@ -186,7 +239,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
186 /// <summary> 239 /// <summary>
187 /// The current total of the requested maximum burst rates of children buckets. 240 /// The current total of the requested maximum burst rates of children buckets.
188 /// </summary> 241 /// </summary>
242<<<<<<< HEAD
189 public Int64 TotalDripRequest { get; protected set; } 243 public Int64 TotalDripRequest { get; protected set; }
244=======
245 protected float m_totalDripRequest;
246 public float TotalDripRequest
247 {
248 get { return m_totalDripRequest; }
249 set { m_totalDripRequest = value; }
250 }
251
252#endregion Properties
253
254#region Constructor
255>>>>>>> avn/ubitvar
190 256
191 /// <summary> 257 /// <summary>
192 /// Default constructor 258 /// Default constructor
@@ -194,18 +260,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
194 /// <param name="identifier">Identifier for this token bucket</param> 260 /// <param name="identifier">Identifier for this token bucket</param>
195 /// <param name="parent">Parent bucket if this is a child bucket, or 261 /// <param name="parent">Parent bucket if this is a child bucket, or
196 /// null if this is a root bucket</param> 262 /// null if this is a root bucket</param>
263<<<<<<< HEAD
197 /// <param name="requestedDripRate"> 264 /// <param name="requestedDripRate">
198 /// Requested rate that the bucket fills, in bytes per 265 /// Requested rate that the bucket fills, in bytes per
199 /// second. If zero, the bucket always remains full. 266 /// second. If zero, the bucket always remains full.
200 /// </param> 267 /// </param>
201 public TokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate) 268 public TokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate)
269=======
270 /// <param name="maxBurst">Maximum size of the bucket in bytes, or
271 /// zero if this bucket has no maximum capacity</param>
272 /// <param name="dripRate">Rate that the bucket fills, in bytes per
273 /// second. If zero, the bucket always remains full</param>
274 public TokenBucket(TokenBucket parent, float dripRate, float MaxBurst)
275>>>>>>> avn/ubitvar
202 { 276 {
203 Identifier = identifier; 277 Identifier = identifier;
204 278
205 Parent = parent; 279 Parent = parent;
280<<<<<<< HEAD
206 RequestedDripRate = requestedDripRate; 281 RequestedDripRate = requestedDripRate;
207 MaxDripRate = maxDripRate; 282 MaxDripRate = maxDripRate;
208 m_lastDrip = Util.EnvironmentTickCount(); 283 m_lastDrip = Util.EnvironmentTickCount();
284=======
285 RequestedDripRate = dripRate;
286 RequestedBurst = MaxBurst;
287 // TotalDripRequest = dripRate; // this will be overwritten when a child node registers
288 // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst);
289 m_lastDrip = Util.EnvironmentTickCount() + 100000;
290>>>>>>> avn/ubitvar
209 } 291 }
210 292
211 /// <summary> 293 /// <summary>
@@ -215,8 +297,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
215 /// hierarchy. However, if any of the parents is over-booked, then 297 /// hierarchy. However, if any of the parents is over-booked, then
216 /// the modifier will be less than 1. 298 /// the modifier will be less than 1.
217 /// </summary> 299 /// </summary>
218 protected double DripRateModifier() 300 protected float DripRateModifier()
219 { 301 {
302<<<<<<< HEAD
220 Int64 driprate = DripRate; 303 Int64 driprate = DripRate;
221 double modifier = driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; 304 double modifier = driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest;
222 305
@@ -226,11 +309,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
226// driprate, TotalDripRequest, modifier, Identifier); 309// driprate, TotalDripRequest, modifier, Identifier);
227 310
228 return modifier; 311 return modifier;
312=======
313 float driprate = DripRate;
314 return driprate >= TotalDripRequest ? 1.0f : driprate / TotalDripRequest;
315>>>>>>> avn/ubitvar
229 } 316 }
230 317
231 /// <summary> 318 /// <summary>
232 /// </summary> 319 /// </summary>
233 protected double BurstRateModifier() 320 protected float BurstModifier()
234 { 321 {
235 // for now... burst rate is always m_quantumsPerBurst (constant) 322 // for now... burst rate is always m_quantumsPerBurst (constant)
236 // larger than drip rate so the ratio of burst requests is the 323 // larger than drip rate so the ratio of burst requests is the
@@ -242,15 +329,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
242 /// Register drip rate requested by a child of this throttle. Pass the 329 /// Register drip rate requested by a child of this throttle. Pass the
243 /// changes up the hierarchy. 330 /// changes up the hierarchy.
244 /// </summary> 331 /// </summary>
245 public void RegisterRequest(TokenBucket child, Int64 request) 332 public void RegisterRequest(TokenBucket child, float request)
246 { 333 {
247 lock (m_children) 334 lock (m_children)
248 { 335 {
249 m_children[child] = request; 336 m_children[child] = request;
250 337
338<<<<<<< HEAD
251 TotalDripRequest = 0; 339 TotalDripRequest = 0;
252 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) 340 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
253 TotalDripRequest += cref.Value; 341 TotalDripRequest += cref.Value;
342=======
343 m_totalDripRequest = 0;
344 foreach (KeyValuePair<TokenBucket, float> cref in m_children)
345 m_totalDripRequest += cref.Value;
346>>>>>>> avn/ubitvar
254 } 347 }
255 348
256 // Pass the new values up to the parent 349 // Pass the new values up to the parent
@@ -277,9 +370,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
277 { 370 {
278 m_children.Remove(child); 371 m_children.Remove(child);
279 372
373<<<<<<< HEAD
280 TotalDripRequest = 0; 374 TotalDripRequest = 0;
281 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) 375 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
282 TotalDripRequest += cref.Value; 376 TotalDripRequest += cref.Value;
377=======
378 m_totalDripRequest = 0;
379 foreach (KeyValuePair<TokenBucket, float> cref in m_children)
380 m_totalDripRequest += cref.Value;
381>>>>>>> avn/ubitvar
283 } 382 }
284 383
285 // Pass the new values up to the parent 384 // Pass the new values up to the parent
@@ -293,7 +392,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
293 /// <param name="amount">Number of tokens to remove from the bucket</param> 392 /// <param name="amount">Number of tokens to remove from the bucket</param>
294 /// <returns>True if the requested number of tokens were removed from 393 /// <returns>True if the requested number of tokens were removed from
295 /// the bucket, otherwise false</returns> 394 /// the bucket, otherwise false</returns>
296 public bool RemoveTokens(Int64 amount) 395 public bool RemoveTokens(int amount)
297 { 396 {
298 // Deposit tokens for this interval 397 // Deposit tokens for this interval
299 Drip(); 398 Drip();
@@ -310,19 +409,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
310 return false; 409 return false;
311 } 410 }
312 411
313 /// <summary> 412 public int GetCatBytesCanSend(int timeMS)
314 /// Deposit tokens into the bucket from a child bucket that did
315 /// not use all of its available tokens
316 /// </summary>
317 protected void Deposit(Int64 count)
318 { 413 {
319 m_tokenCount += count; 414// return (int)(m_tokenCount + timeMS * m_dripRate * 1e-3);
320 415 return (int)(timeMS * m_dripRate * 1e-3);
321 // Deposit the overflow in the parent bucket, this is how we share
322 // unused bandwidth
323 Int64 burstrate = BurstRate;
324 if (m_tokenCount > burstrate)
325 m_tokenCount = burstrate;
326 } 416 }
327 417
328 /// <summary> 418 /// <summary>
@@ -341,17 +431,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
341 return; 431 return;
342 } 432 }
343 433
344 // Determine the interval over which we are adding tokens, never add 434 Int32 now = Util.EnvironmentTickCount();
345 // more than a single quantum of tokens 435 Int32 deltaMS = now - m_lastDrip;
346 Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum); 436 m_lastDrip = now;
347 m_lastDrip = Util.EnvironmentTickCount();
348 437
349 // This can be 0 in the very unusual case that the timer wrapped
350 // It can be 0 if we try add tokens at a sub-tick rate
351 if (deltaMS <= 0) 438 if (deltaMS <= 0)
352 return; 439 return;
353 440
354 Deposit(deltaMS * DripRate / m_ticksPerQuantum); 441 m_tokenCount += deltaMS * DripRate * m_timeScale;
442
443 float burst = Burst;
444 if (m_tokenCount > burst)
445 m_tokenCount = burst;
355 } 446 }
356 } 447 }
357 448
@@ -362,6 +453,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
362 public bool AdaptiveEnabled { get; set; } 453 public bool AdaptiveEnabled { get; set; }
363 454
364 /// <summary> 455 /// <summary>
456<<<<<<< HEAD
365 /// Target drip rate for this bucket. 457 /// Target drip rate for this bucket.
366 /// </summary> 458 /// </summary>
367 /// <remarks>Usually set by the client. If adaptive is enabled then throttles will increase until we reach this.</remarks> 459 /// <remarks>Usually set by the client. If adaptive is enabled then throttles will increase until we reach this.</remarks>
@@ -371,6 +463,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
371 set 463 set
372 { 464 {
373 m_targetDripRate = Math.Max(value, m_minimumFlow); 465 m_targetDripRate = Math.Max(value, m_minimumFlow);
466=======
467 /// The minimum rate for flow control. Minimum drip rate is one
468 /// packet per second.
469 /// </summary>
470
471 protected const float m_minimumFlow = 50000;
472
473 // <summary>
474 // The maximum rate for flow control. Drip rate can never be
475 // greater than this.
476 // </summary>
477
478 protected float m_maxDripRate = 0;
479 public float MaxDripRate
480 {
481 get { return (m_maxDripRate == 0 ? m_totalDripRequest : m_maxDripRate); }
482 set
483 {
484 m_maxDripRate = (value == 0 ? m_totalDripRequest : Math.Max(value, m_minimumFlow));
485>>>>>>> avn/ubitvar
374 } 486 }
375 } 487 }
376 protected Int64 m_targetDripRate; 488 protected Int64 m_targetDripRate;
@@ -378,9 +490,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
378 // <summary> 490 // <summary>
379 // Adjust drip rate in response to network conditions. 491 // Adjust drip rate in response to network conditions.
380 // </summary> 492 // </summary>
381 public virtual Int64 AdjustedDripRate 493 public virtual float AdjustedDripRate
382 { 494 {
383 get { return m_dripRate; } 495 get { return m_dripRate; }
496<<<<<<< HEAD
384 set 497 set
385 { 498 {
386 m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value, m_minimumFlow, TargetDripRate); 499 m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value, m_minimumFlow, TargetDripRate);
@@ -388,6 +501,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
388 501
389 if (Parent != null) 502 if (Parent != null)
390 Parent.RegisterRequest(this, m_dripRate); 503 Parent.RegisterRequest(this, m_dripRate);
504=======
505 set {
506 m_dripRate = OpenSim.Framework.Util.Clamp<float>(value,m_minimumFlow,MaxDripRate);
507
508 if (m_parent != null)
509 m_parent.RegisterRequest(this,m_dripRate);
510>>>>>>> avn/ubitvar
391 } 511 }
392 } 512 }
393 513
@@ -396,6 +516,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
396 /// </summary> 516 /// </summary>
397 protected Int64 m_minimumFlow = 32000; 517 protected Int64 m_minimumFlow = 32000;
398 518
519<<<<<<< HEAD
399 /// <summary> 520 /// <summary>
400 /// Constructor for the AdaptiveTokenBucket class 521 /// Constructor for the AdaptiveTokenBucket class
401 /// <param name="identifier">Unique identifier for the client</param> 522 /// <param name="identifier">Unique identifier for the client</param>
@@ -416,6 +537,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
416 TargetDripRate = m_minimumFlow; 537 TargetDripRate = m_minimumFlow;
417 AdjustedDripRate = m_minimumFlow; 538 AdjustedDripRate = m_minimumFlow;
418 } 539 }
540=======
541 // <summary>
542 //
543 // </summary>
544 public AdaptiveTokenBucket(TokenBucket parent, float maxDripRate,float maxBurst, bool enabled)
545 : base(parent, maxDripRate,maxBurst)
546 {
547 m_enabled = enabled;
548
549 MaxDripRate = maxDripRate;
550
551 if (enabled)
552 AdjustedDripRate = m_maxDripRate * .5f;
553 else
554 AdjustedDripRate = m_maxDripRate;
555>>>>>>> avn/ubitvar
419 } 556 }
420 557
421 /// <summary> 558 /// <summary>
@@ -461,4 +598,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP
461 AdjustedDripRate = m_minimumFlow; 598 AdjustedDripRate = m_minimumFlow;
462 } 599 }
463 } 600 }
464} \ No newline at end of file 601}