aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/Caps
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/Caps')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs1070
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs727
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs474
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs21
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs404
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs423
-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.cs5
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs164
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs17
13 files changed, 2606 insertions, 1025 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 774202e..1236e83 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;
@@ -44,7 +45,6 @@ using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.Framework.Scenes.Serialization; 45using OpenSim.Region.Framework.Scenes.Serialization;
45using OpenSim.Framework.Servers; 46using OpenSim.Framework.Servers;
46using OpenSim.Framework.Servers.HttpServer; 47using OpenSim.Framework.Servers.HttpServer;
47using OpenSim.Framework.Client;
48using OpenSim.Services.Interfaces; 48using OpenSim.Services.Interfaces;
49 49
50using Caps = OpenSim.Framework.Capabilities.Caps; 50using Caps = OpenSim.Framework.Capabilities.Caps;
@@ -55,14 +55,16 @@ using PermissionMask = OpenSim.Framework.PermissionMask;
55namespace OpenSim.Region.ClientStack.Linden 55namespace OpenSim.Region.ClientStack.Linden
56{ 56{
57 public delegate void UpLoadedAsset( 57 public delegate void UpLoadedAsset(
58 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, 58 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
59 byte[] data, string inventoryType, string assetType); 59 byte[] data, string inventoryType, string assetType,
60 int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
61 bool IsAtestUpload, ref string error);
60 62
61 public delegate UUID UpdateItem(UUID itemID, byte[] data); 63 public delegate UUID UpdateItem(UUID itemID, byte[] data);
62 64
63 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); 65 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors);
64 66
65 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item); 67 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item, uint cost);
66 68
67 public delegate void NewAsset(AssetBase asset); 69 public delegate void NewAsset(AssetBase asset);
68 70
@@ -88,6 +90,7 @@ namespace OpenSim.Region.ClientStack.Linden
88 90
89 private Scene m_Scene; 91 private Scene m_Scene;
90 private Caps m_HostCapsObj; 92 private Caps m_HostCapsObj;
93 private ModelCost m_ModelCost;
91 94
92 private static readonly string m_requestPath = "0000/"; 95 private static readonly string m_requestPath = "0000/";
93 // private static readonly string m_mapLayerPath = "0001/"; 96 // private static readonly string m_mapLayerPath = "0001/";
@@ -99,8 +102,10 @@ namespace OpenSim.Region.ClientStack.Linden
99 private static readonly string m_copyFromNotecardPath = "0007/"; 102 private static readonly string m_copyFromNotecardPath = "0007/";
100 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. 103 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule.
101 private static readonly string m_getObjectPhysicsDataPath = "0101/"; 104 private static readonly string m_getObjectPhysicsDataPath = "0101/";
102 /* 0102 - 0103 RESERVED */ 105 private static readonly string m_getObjectCostPath = "0102/";
106 private static readonly string m_ResourceCostSelectedPath = "0103/";
103 private static readonly string m_UpdateAgentInformationPath = "0500/"; 107 private static readonly string m_UpdateAgentInformationPath = "0500/";
108 private static readonly string m_animSetTaskUpdatePath = "0260/";
104 109
105 // These are callbacks which will be setup by the scene so that we can update scene data when we 110 // These are callbacks which will be setup by the scene so that we can update scene data when we
106 // receive capability calls 111 // receive capability calls
@@ -115,12 +120,50 @@ namespace OpenSim.Region.ClientStack.Linden
115 private IAssetService m_assetService; 120 private IAssetService m_assetService;
116 private bool m_dumpAssetsToFile = false; 121 private bool m_dumpAssetsToFile = false;
117 private string m_regionName; 122 private string m_regionName;
123
118 private int m_levelUpload = 0; 124 private int m_levelUpload = 0;
119 125
126 private bool m_enableFreeTestUpload = false; // allows "TEST-" prefix hack
127 private bool m_ForceFreeTestUpload = false; // forces all uploads to be test
128
129 private bool m_enableModelUploadTextureToInventory = false; // place uploaded textures also in inventory
130 // may not be visible till relog
131
132 private bool m_RestrictFreeTestUploadPerms = false; // reduces also the permitions. Needs a creator defined!!
133 private UUID m_testAssetsCreatorID = UUID.Zero;
134
135 private float m_PrimScaleMin = 0.001f;
136
137 private enum FileAgentInventoryState : int
138 {
139 idle = 0,
140 processRequest = 1,
141 waitUpload = 2,
142 processUpload = 3
143 }
144 private FileAgentInventoryState m_FileAgentInventoryState = FileAgentInventoryState.idle;
145
120 public BunchOfCaps(Scene scene, Caps caps) 146 public BunchOfCaps(Scene scene, Caps caps)
121 { 147 {
122 m_Scene = scene; 148 m_Scene = scene;
123 m_HostCapsObj = caps; 149 m_HostCapsObj = caps;
150
151 // create a model upload cost provider
152 m_ModelCost = new ModelCost();
153 // tell it about scene object limits
154 m_ModelCost.NonPhysicalPrimScaleMax = m_Scene.m_maxNonphys;
155 m_ModelCost.PhysicalPrimScaleMax = m_Scene.m_maxPhys;
156
157// m_ModelCost.ObjectLinkedPartsMax = ??
158// m_ModelCost.PrimScaleMin = ??
159
160 m_PrimScaleMin = m_ModelCost.PrimScaleMin;
161 float modelTextureUploadFactor = m_ModelCost.ModelTextureCostFactor;
162 float modelUploadFactor = m_ModelCost.ModelMeshCostFactor;
163 float modelMinUploadCostFactor = m_ModelCost.ModelMinCostFactor;
164 float modelPrimCreationCost = m_ModelCost.primCreationCost;
165 float modelMeshByteCost = m_ModelCost.bytecost;
166
124 IConfigSource config = m_Scene.Config; 167 IConfigSource config = m_Scene.Config;
125 if (config != null) 168 if (config != null)
126 { 169 {
@@ -135,6 +178,37 @@ namespace OpenSim.Region.ClientStack.Linden
135 { 178 {
136 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); 179 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
137 } 180 }
181 // economy for model upload
182 IConfig EconomyConfig = config.Configs["Economy"];
183 if (EconomyConfig != null)
184 {
185 modelUploadFactor = EconomyConfig.GetFloat("MeshModelUploadCostFactor", modelUploadFactor);
186 modelTextureUploadFactor = EconomyConfig.GetFloat("MeshModelUploadTextureCostFactor", modelTextureUploadFactor);
187 modelMinUploadCostFactor = EconomyConfig.GetFloat("MeshModelMinCostFactor", modelMinUploadCostFactor);
188 // next 2 are normalized so final cost is afected by modelUploadFactor above and normal cost
189 modelPrimCreationCost = EconomyConfig.GetFloat("ModelPrimCreationCost", modelPrimCreationCost);
190 modelMeshByteCost = EconomyConfig.GetFloat("ModelMeshByteCost", modelMeshByteCost);
191
192 m_enableModelUploadTextureToInventory = EconomyConfig.GetBoolean("MeshModelAllowTextureToInventory", m_enableModelUploadTextureToInventory);
193
194 m_RestrictFreeTestUploadPerms = EconomyConfig.GetBoolean("m_RestrictFreeTestUploadPerms", m_RestrictFreeTestUploadPerms);
195 m_enableFreeTestUpload = EconomyConfig.GetBoolean("AllowFreeTestUpload", m_enableFreeTestUpload);
196 m_ForceFreeTestUpload = EconomyConfig.GetBoolean("ForceFreeTestUpload", m_ForceFreeTestUpload);
197 string testcreator = EconomyConfig.GetString("TestAssetsCreatorID", "");
198 if (testcreator != "")
199 {
200 UUID id;
201 UUID.TryParse(testcreator, out id);
202 if (id != null)
203 m_testAssetsCreatorID = id;
204 }
205
206 m_ModelCost.ModelMeshCostFactor = modelUploadFactor;
207 m_ModelCost.ModelTextureCostFactor = modelTextureUploadFactor;
208 m_ModelCost.ModelMinCostFactor = modelMinUploadCostFactor;
209 m_ModelCost.primCreationCost = modelPrimCreationCost;
210 m_ModelCost.bytecost = modelMeshByteCost;
211 }
138 } 212 }
139 213
140 m_assetService = m_Scene.AssetService; 214 m_assetService = m_Scene.AssetService;
@@ -146,6 +220,8 @@ namespace OpenSim.Region.ClientStack.Linden
146 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset; 220 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset;
147 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset; 221 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset;
148 GetClient = m_Scene.SceneGraph.GetControllingClient; 222 GetClient = m_Scene.SceneGraph.GetControllingClient;
223
224 m_FileAgentInventoryState = FileAgentInventoryState.idle;
149 } 225 }
150 226
151 /// <summary> 227 /// <summary>
@@ -173,13 +249,31 @@ namespace OpenSim.Region.ClientStack.Linden
173 //m_capsHandlers["MapLayer"] = 249 //m_capsHandlers["MapLayer"] =
174 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST", 250 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
175 // capsBase + m_mapLayerPath, 251 // capsBase + m_mapLayerPath,
176 // GetMapLayer); 252 // GetMapLayer);
253
254 IRequestHandler getObjectPhysicsDataHandler
255 = new RestStreamHandler(
256 "POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData, "GetObjectPhysicsData", null);
257 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
258
259 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost);
260 m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler);
261 IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected);
262 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
263
264
177 IRequestHandler req 265 IRequestHandler req
178 = new RestStreamHandler( 266 = new RestStreamHandler(
179 "POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory, "UpdateScript", null); 267 "POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory, "UpdateScript", null);
180 268
181 m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req); 269 m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req);
182 m_HostCapsObj.RegisterHandler("UpdateScriptTask", req); 270 m_HostCapsObj.RegisterHandler("UpdateScriptTask", req);
271
272// IRequestHandler animSetRequestHandler
273// = new RestStreamHandler(
274// "POST", capsBase + m_animSetTaskUpdatePath, AnimSetTaskInventory, "UpdateScript", null);
275
276// m_HostCapsObj.RegisterHandler("UpdateAnimSetTaskInventory", animSetRequestHandler);
183 } 277 }
184 catch (Exception e) 278 catch (Exception e)
185 { 279 {
@@ -191,7 +285,6 @@ namespace OpenSim.Region.ClientStack.Linden
191 { 285 {
192 try 286 try
193 { 287 {
194 // I don't think this one works...
195 m_HostCapsObj.RegisterHandler( 288 m_HostCapsObj.RegisterHandler(
196 "NewFileAgentInventory", 289 "NewFileAgentInventory",
197 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>( 290 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>(
@@ -206,13 +299,11 @@ namespace OpenSim.Region.ClientStack.Linden
206 "POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory, "Update*", null); 299 "POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory, "Update*", null);
207 300
208 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); 301 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
302 m_HostCapsObj.RegisterHandler("UpdateAnimSetAgentInventory", req);
209 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); 303 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
210 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); 304 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
211 305
212 IRequestHandler getObjectPhysicsDataHandler 306
213 = new RestStreamHandler(
214 "POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData, "GetObjectPhysicsData", null);
215 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
216 307
217 IRequestHandler UpdateAgentInformationHandler 308 IRequestHandler UpdateAgentInformationHandler
218 = new RestStreamHandler( 309 = new RestStreamHandler(
@@ -268,8 +359,11 @@ namespace OpenSim.Region.ClientStack.Linden
268 public string SeedCapRequest(string request, string path, string param, 359 public string SeedCapRequest(string request, string path, string param,
269 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 360 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
270 { 361 {
271// m_log.DebugFormat( 362 m_log.DebugFormat(
272// "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID); 363 "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID);
364
365 if (!m_HostCapsObj.WaitForActivation())
366 return string.Empty;
273 367
274 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) 368 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
275 { 369 {
@@ -400,62 +494,178 @@ namespace OpenSim.Region.ClientStack.Linden
400 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString()); 494 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
401 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type); 495 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
402 496
497 // start by getting the client
498 IClientAPI client = null;
499 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
500
501 // check current state so we only have one service at a time
502 lock (m_ModelCost)
503 {
504 switch (m_FileAgentInventoryState)
505 {
506 case FileAgentInventoryState.processRequest:
507 case FileAgentInventoryState.processUpload:
508 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
509 resperror.message = "Uploader busy processing previus request";
510 resperror.identifier = UUID.Zero;
511
512 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
513 errorResponse.uploader = "";
514 errorResponse.state = "error";
515 errorResponse.error = resperror;
516 return errorResponse;
517 break;
518 case FileAgentInventoryState.waitUpload:
519 // todo stop current uploader server
520 break;
521 case FileAgentInventoryState.idle:
522 default:
523 break;
524 }
525
526 m_FileAgentInventoryState = FileAgentInventoryState.processRequest;
527 }
528
529 int cost = 0;
530 int nreqtextures = 0;
531 int nreqmeshs= 0;
532 int nreqinstances = 0;
533 bool IsAtestUpload = false;
534
535 string assetName = llsdRequest.name;
536
537 LLSDAssetUploadResponseData meshcostdata = new LLSDAssetUploadResponseData();
538
403 if (llsdRequest.asset_type == "texture" || 539 if (llsdRequest.asset_type == "texture" ||
404 llsdRequest.asset_type == "animation" || 540 llsdRequest.asset_type == "animation" ||
541 llsdRequest.asset_type == "animatn" || // this is the asset name actually used by viewers
542 llsdRequest.asset_type == "mesh" ||
405 llsdRequest.asset_type == "sound") 543 llsdRequest.asset_type == "sound")
406 { 544 {
407 ScenePresence avatar = null; 545 ScenePresence avatar = null;
408 IClientAPI client = null;
409 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar); 546 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar);
410 547
411 // check user level 548 // check user level
412 if (avatar != null) 549 if (avatar != null)
413 { 550 {
414 client = avatar.ControllingClient;
415
416 if (avatar.UserLevel < m_levelUpload) 551 if (avatar.UserLevel < m_levelUpload)
417 { 552 {
418 if (client != null) 553 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
419 client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false); 554 resperror.message = "Insufficient permissions to upload";
555 resperror.identifier = UUID.Zero;
420 556
421 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 557 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
422 errorResponse.uploader = ""; 558 errorResponse.uploader = "";
423 errorResponse.state = "error"; 559 errorResponse.state = "error";
560 errorResponse.error = resperror;
561 lock (m_ModelCost)
562 m_FileAgentInventoryState = FileAgentInventoryState.idle;
424 return errorResponse; 563 return errorResponse;
425 } 564 }
426 } 565 }
427 566
428 // check funds 567 // check test upload and funds
429 if (client != null) 568 if (client != null)
430 { 569 {
431 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>(); 570 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
432 571
572 int baseCost = 0;
433 if (mm != null) 573 if (mm != null)
574 baseCost = mm.UploadCharge;
575
576 string warning = String.Empty;
577
578 if (llsdRequest.asset_type == "mesh")
434 { 579 {
435 if (!mm.UploadCovered(client.AgentId, mm.UploadCharge)) 580 string error;
581 int modelcost;
582
583
584 if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost,
585 meshcostdata, out error, ref warning))
436 { 586 {
437 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); 587 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
588 resperror.message = error;
589 resperror.identifier = UUID.Zero;
438 590
439 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 591 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
440 errorResponse.uploader = ""; 592 errorResponse.uploader = "";
441 errorResponse.state = "error"; 593 errorResponse.state = "error";
594 errorResponse.error = resperror;
595
596 lock (m_ModelCost)
597 m_FileAgentInventoryState = FileAgentInventoryState.idle;
442 return errorResponse; 598 return errorResponse;
443 } 599 }
600 cost = modelcost;
601 }
602 else
603 {
604 cost = baseCost;
605 }
606
607 if (cost > 0 && mm != null)
608 {
609 // check for test upload
610
611 if (m_ForceFreeTestUpload) // all are test
612 {
613 if (!(assetName.Length > 5 && assetName.StartsWith("TEST-"))) // has normal name lets change it
614 assetName = "TEST-" + assetName;
615
616 IsAtestUpload = true;
617 }
618
619 else if (m_enableFreeTestUpload) // only if prefixed with "TEST-"
620 {
621
622 IsAtestUpload = (assetName.Length > 5 && assetName.StartsWith("TEST-"));
623 }
624
625
626 if(IsAtestUpload) // let user know, still showing cost estimation
627 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";
628
629 // check funds
630 else
631 {
632 if (!mm.UploadCovered(client.AgentId, (int)cost))
633 {
634 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
635 resperror.message = "Insuficient funds";
636 resperror.identifier = UUID.Zero;
637
638 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
639 errorResponse.uploader = "";
640 errorResponse.state = "error";
641 errorResponse.error = resperror;
642 lock (m_ModelCost)
643 m_FileAgentInventoryState = FileAgentInventoryState.idle;
644 return errorResponse;
645 }
646 }
444 } 647 }
648
649 if (client != null && warning != String.Empty)
650 client.SendAgentAlertMessage(warning, true);
445 } 651 }
446 } 652 }
447 653
448 string assetName = llsdRequest.name;
449 string assetDes = llsdRequest.description; 654 string assetDes = llsdRequest.description;
450 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; 655 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
451 UUID newAsset = UUID.Random(); 656 UUID newAsset = UUID.Random();
452 UUID newInvItem = UUID.Random(); 657 UUID newInvItem = UUID.Random();
453 UUID parentFolder = llsdRequest.folder_id; 658 UUID parentFolder = llsdRequest.folder_id;
454 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); 659 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
660 UUID texturesFolder = UUID.Zero;
661
662 if(!IsAtestUpload && m_enableModelUploadTextureToInventory)
663 texturesFolder = llsdRequest.texture_folder_id;
455 664
456 AssetUploader uploader = 665 AssetUploader uploader =
457 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, 666 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
458 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); 667 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost,
668 texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload);
459 669
460 m_HostCapsObj.HttpListener.AddStreamHandler( 670 m_HostCapsObj.HttpListener.AddStreamHandler(
461 new BinaryStreamHandler( 671 new BinaryStreamHandler(
@@ -473,10 +683,22 @@ namespace OpenSim.Region.ClientStack.Linden
473 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + 683 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
474 uploaderPath; 684 uploaderPath;
475 685
686
476 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); 687 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
477 uploadResponse.uploader = uploaderURL; 688 uploadResponse.uploader = uploaderURL;
478 uploadResponse.state = "upload"; 689 uploadResponse.state = "upload";
690 uploadResponse.upload_price = (int)cost;
691
692 if (llsdRequest.asset_type == "mesh")
693 {
694 uploadResponse.data = meshcostdata;
695 }
696
479 uploader.OnUpLoad += UploadCompleteHandler; 697 uploader.OnUpLoad += UploadCompleteHandler;
698
699 lock (m_ModelCost)
700 m_FileAgentInventoryState = FileAgentInventoryState.waitUpload;
701
480 return uploadResponse; 702 return uploadResponse;
481 } 703 }
482 704
@@ -488,8 +710,14 @@ namespace OpenSim.Region.ClientStack.Linden
488 /// <param name="data"></param> 710 /// <param name="data"></param>
489 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, 711 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
490 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, 712 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
491 string assetType) 713 string assetType, int cost,
714 UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
715 bool IsAtestUpload, ref string error)
492 { 716 {
717
718 lock (m_ModelCost)
719 m_FileAgentInventoryState = FileAgentInventoryState.processUpload;
720
493 m_log.DebugFormat( 721 m_log.DebugFormat(
494 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}", 722 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}",
495 assetID, inventoryItem, inventoryType, assetType); 723 assetID, inventoryItem, inventoryType, assetType);
@@ -497,6 +725,34 @@ namespace OpenSim.Region.ClientStack.Linden
497 sbyte assType = 0; 725 sbyte assType = 0;
498 sbyte inType = 0; 726 sbyte inType = 0;
499 727
728 IClientAPI client = null;
729
730 UUID owner_id = m_HostCapsObj.AgentID;
731 UUID creatorID;
732
733 bool istest = IsAtestUpload && m_enableFreeTestUpload && (cost > 0);
734
735 bool restrictPerms = m_RestrictFreeTestUploadPerms && istest;
736
737 if (istest && m_testAssetsCreatorID != UUID.Zero)
738 creatorID = m_testAssetsCreatorID;
739 else
740 creatorID = owner_id;
741
742 string creatorIDstr = creatorID.ToString();
743
744 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
745 if (mm != null)
746 {
747 // make sure client still has enougth credit
748 if (!mm.UploadCovered(m_HostCapsObj.AgentID, (int)cost))
749 {
750 error = "Insufficient funds.";
751 return;
752 }
753 }
754
755 // strings to types
500 if (inventoryType == "sound") 756 if (inventoryType == "sound")
501 { 757 {
502 inType = (sbyte)InventoryType.Sound; 758 inType = (sbyte)InventoryType.Sound;
@@ -511,6 +767,12 @@ namespace OpenSim.Region.ClientStack.Linden
511 inType = (sbyte)InventoryType.Animation; 767 inType = (sbyte)InventoryType.Animation;
512 assType = (sbyte)AssetType.Animation; 768 assType = (sbyte)AssetType.Animation;
513 } 769 }
770 else if (inventoryType == "animset")
771 {
772 inType = (sbyte)CustomInventoryType.AnimationSet;
773 assType = (sbyte)CustomAssetType.AnimationSet;
774 m_log.Debug("got animset upload request");
775 }
514 else if (inventoryType == "wearable") 776 else if (inventoryType == "wearable")
515 { 777 {
516 inType = (sbyte)InventoryType.Wearable; 778 inType = (sbyte)InventoryType.Wearable;
@@ -526,159 +788,253 @@ namespace OpenSim.Region.ClientStack.Linden
526 } 788 }
527 else if (inventoryType == "object") 789 else if (inventoryType == "object")
528 { 790 {
529 inType = (sbyte)InventoryType.Object; 791 if (assetType == "mesh") // this code for now is for mesh models uploads only
530 assType = (sbyte)AssetType.Object;
531
532 List<Vector3> positions = new List<Vector3>();
533 List<Quaternion> rotations = new List<Quaternion>();
534 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
535 OSDArray instance_list = (OSDArray)request["instance_list"];
536 OSDArray mesh_list = (OSDArray)request["mesh_list"];
537 OSDArray texture_list = (OSDArray)request["texture_list"];
538 SceneObjectGroup grp = null;
539
540 InventoryFolderBase textureUploadFolder = null;
541
542 List<InventoryFolderBase> foldersToUpdate = new List<InventoryFolderBase>();
543 List<InventoryItemBase> itemsToUpdate = new List<InventoryItemBase>();
544 IClientInventory clientInv = null;
545
546 if (texture_list.Count > 0)
547 { 792 {
548 ScenePresence avatar = null; 793 inType = (sbyte)InventoryType.Object;
549 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar); 794 assType = (sbyte)AssetType.Object;
795
796 List<Vector3> positions = new List<Vector3>();
797 List<Quaternion> rotations = new List<Quaternion>();
798 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
799
800 // compare and get updated information
801/* does nothing still we do need something to avoid special viewer to upload something diferent from the cost estimation
802 bool mismatchError = true;
550 803
551 if (avatar != null) 804 while (mismatchError)
552 { 805 {
553 IClientCore core = (IClientCore)avatar.ControllingClient; 806 mismatchError = false;
807 }
808
809 if (mismatchError)
810 {
811 error = "Upload and fee estimation information don't match";
812 lock (m_ModelCost)
813 m_FileAgentInventoryState = FileAgentInventoryState.idle;
814
815 return;
816 }
817*/
818 OSDArray instance_list = (OSDArray)request["instance_list"];
819 OSDArray mesh_list = (OSDArray)request["mesh_list"];
820 OSDArray texture_list = (OSDArray)request["texture_list"];
821 SceneObjectGroup grp = null;
822
823 // create and store texture assets
824 bool doTextInv = (!istest && m_enableModelUploadTextureToInventory &&
825 texturesFolder != UUID.Zero);
554 826
555 if (core.TryGet<IClientInventory>(out clientInv)) 827
828 List<UUID> textures = new List<UUID>();
829
830
831// if (doTextInv)
832 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
833
834 if(client == null) // don't put textures in inventory if there is no client
835 doTextInv = false;
836
837 for (int i = 0; i < texture_list.Count; i++)
838 {
839 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, creatorIDstr);
840 textureAsset.Data = texture_list[i].AsBinary();
841 if (istest)
842 textureAsset.Local = true;
843 m_assetService.Store(textureAsset);
844 textures.Add(textureAsset.FullID);
845
846 if (doTextInv)
556 { 847 {
557 var systemTextureFolder = m_Scene.InventoryService.GetFolderForType(m_HostCapsObj.AgentID, FolderType.Texture); 848 string name = assetName;
558 textureUploadFolder = new InventoryFolderBase(UUID.Random(), assetName, m_HostCapsObj.AgentID, (short)FolderType.None, systemTextureFolder.ID, 1); 849 if (name.Length > 25)
559 if (m_Scene.InventoryService.AddFolder(textureUploadFolder)) 850 name = name.Substring(0, 24);
560 { 851 name += "_Texture#" + i.ToString();
561 foldersToUpdate.Add(textureUploadFolder); 852 InventoryItemBase texitem = new InventoryItemBase();
853 texitem.Owner = m_HostCapsObj.AgentID;
854 texitem.CreatorId = creatorIDstr;
855 texitem.CreatorData = String.Empty;
856 texitem.ID = UUID.Random();
857 texitem.AssetID = textureAsset.FullID;
858 texitem.Description = "mesh model texture";
859 texitem.Name = name;
860 texitem.AssetType = (int)AssetType.Texture;
861 texitem.InvType = (int)InventoryType.Texture;
862 texitem.Folder = texturesFolder;
863
864 texitem.CurrentPermissions
865 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Export);
866
867 texitem.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
868 texitem.EveryOnePermissions = 0;
869 texitem.NextPermissions = (uint)PermissionMask.All;
870 texitem.CreationDate = Util.UnixTimeSinceEpoch();
871
872 m_Scene.AddInventoryItem(client, texitem);
873 texitem = null;
874 }
875 }
562 876
563 m_log.DebugFormat( 877 // create and store meshs assets
564 "[BUNCH OF CAPS]: Created new folder '{0}' ({1}) for textures uploaded with mesh object {2}", 878 List<UUID> meshAssets = new List<UUID>();
565 textureUploadFolder.Name, textureUploadFolder.ID, assetName); 879 List<bool> meshAvatarSkeletons = new List<bool>();
566 } 880 List<bool> meshAvatarColliders = new List<bool>();
567 else 881
882 bool curAvSkeleton;
883 bool curAvCollider;
884 for (int i = 0; i < mesh_list.Count; i++)
885 {
886 curAvSkeleton = false;
887 curAvCollider = false;
888
889 // we do need to parse the mesh now
890 OSD osd = OSDParser.DeserializeLLSDBinary(mesh_list[i]);
891 if (osd is OSDMap)
892 {
893 OSDMap mosd = (OSDMap)osd;
894 if (mosd.ContainsKey("skeleton"))
568 { 895 {
569 textureUploadFolder = null; 896 OSDMap skeleton = (OSDMap)mosd["skeleton"];
897 int sksize = skeleton["size"].AsInteger();
898 if (sksize > 0)
899 curAvSkeleton = true;
570 } 900 }
571 } 901 }
572 }
573 }
574 902
575 List<UUID> textures = new List<UUID>(); 903 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, creatorIDstr);
576 for (int i = 0; i < texture_list.Count; i++) 904 meshAsset.Data = mesh_list[i].AsBinary();
577 { 905 if (istest)
578 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, ""); 906 meshAsset.Local = true;
579 textureAsset.Data = texture_list[i].AsBinary(); 907 m_assetService.Store(meshAsset);
580 m_assetService.Store(textureAsset); 908 meshAssets.Add(meshAsset.FullID);
581 textures.Add(textureAsset.FullID); 909 meshAvatarSkeletons.Add(curAvSkeleton);
910 meshAvatarColliders.Add(curAvCollider);
911
912 // test code
913 if (curAvSkeleton && client != null)
914 {
915 string name = assetName;
916 if (name.Length > 25)
917 name = name.Substring(0, 24);
918 name += "_Mesh#" + i.ToString();
919 InventoryItemBase meshitem = new InventoryItemBase();
920 meshitem.Owner = m_HostCapsObj.AgentID;
921 meshitem.CreatorId = creatorIDstr;
922 meshitem.CreatorData = String.Empty;
923 meshitem.ID = UUID.Random();
924 meshitem.AssetID = meshAsset.FullID;
925 meshitem.Description = "mesh ";
926 meshitem.Name = name;
927 meshitem.AssetType = (int)AssetType.Mesh;
928 meshitem.InvType = (int)InventoryType.Mesh;
929 // meshitem.Folder = UUID.Zero; // send to default
930
931 meshitem.Folder = parentFolder; // dont let it go to folder Meshes that viewers dont show
932
933 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
934 // (owner) permissions. This becomes a problem if next permissions are changed.
935 meshitem.CurrentPermissions
936 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
937
938 meshitem.BasePermissions = (uint)PermissionMask.All;
939 meshitem.EveryOnePermissions = 0;
940 meshitem.NextPermissions = (uint)PermissionMask.All;
941 meshitem.CreationDate = Util.UnixTimeSinceEpoch();
942
943 m_Scene.AddInventoryItem(client, meshitem);
944 meshitem = null;
945 }
946 }
582 947
583 if (textureUploadFolder != null) 948 int skipedMeshs = 0;
949 // build prims from instances
950 for (int i = 0; i < instance_list.Count; i++)
584 { 951 {
585 InventoryItemBase textureItem = new InventoryItemBase(); 952 OSDMap inner_instance_list = (OSDMap)instance_list[i];
586 textureItem.Owner = m_HostCapsObj.AgentID;
587 textureItem.CreatorId = m_HostCapsObj.AgentID.ToString();
588 textureItem.CreatorData = String.Empty;
589 textureItem.ID = UUID.Random();
590 textureItem.AssetID = textureAsset.FullID;
591 textureItem.Description = assetDescription;
592 textureItem.Name = assetName + " - Texture " + (i + 1).ToString();
593 textureItem.AssetType = (int)AssetType.Texture;
594 textureItem.InvType = (int)InventoryType.Texture;
595 textureItem.Folder = textureUploadFolder.ID;
596 textureItem.CurrentPermissions
597 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Export);
598 textureItem.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
599 textureItem.EveryOnePermissions = 0;
600 textureItem.NextPermissions = (uint)PermissionMask.All;
601 textureItem.CreationDate = Util.UnixTimeSinceEpoch();
602 m_Scene.InventoryService.AddItem(textureItem);
603 itemsToUpdate.Add(textureItem);
604
605 m_log.DebugFormat(
606 "[BUNCH OF CAPS]: Created new inventory item '{0}' ({1}) for texture uploaded with mesh object {2}",
607 textureItem.Name, textureItem.ID, assetName);
608 }
609 }
610 953
611 if (clientInv != null && (foldersToUpdate.Count > 0 || itemsToUpdate.Count > 0)) 954 // skip prims that are 2 small
612 { 955 Vector3 scale = inner_instance_list["scale"].AsVector3();
613 clientInv.SendBulkUpdateInventory(foldersToUpdate.ToArray(), itemsToUpdate.ToArray());
614 }
615 956
616 for (int i = 0; i < mesh_list.Count; i++) 957 if (scale.X < m_PrimScaleMin || scale.Y < m_PrimScaleMin || scale.Z < m_PrimScaleMin)
617 { 958 {
618 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); 959 skipedMeshs++;
960 continue;
961 }
619 962
620 Primitive.TextureEntry textureEntry 963 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
621 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
622 OSDMap inner_instance_list = (OSDMap)instance_list[i];
623 964
624 OSDArray face_list = (OSDArray)inner_instance_list["face_list"]; 965 Primitive.TextureEntry textureEntry
625 for (uint face = 0; face < face_list.Count; face++) 966 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
626 {
627 OSDMap faceMap = (OSDMap)face_list[(int)face];
628 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
629 if(faceMap.ContainsKey("fullbright"))
630 f.Fullbright = faceMap["fullbright"].AsBoolean();
631 if (faceMap.ContainsKey ("diffuse_color"))
632 f.RGBA = faceMap["diffuse_color"].AsColor4();
633 967
634 int textureNum = faceMap["image"].AsInteger();
635 float imagerot = faceMap["imagerot"].AsInteger();
636 float offsets = (float)faceMap["offsets"].AsReal();
637 float offsett = (float)faceMap["offsett"].AsReal();
638 float scales = (float)faceMap["scales"].AsReal();
639 float scalet = (float)faceMap["scalet"].AsReal();
640 968
641 if(imagerot != 0) 969 OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
642 f.Rotation = imagerot; 970 for (uint face = 0; face < face_list.Count; face++)
971 {
972 OSDMap faceMap = (OSDMap)face_list[(int)face];
973 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
974 if (faceMap.ContainsKey("fullbright"))
975 f.Fullbright = faceMap["fullbright"].AsBoolean();
976 if (faceMap.ContainsKey("diffuse_color"))
977 f.RGBA = faceMap["diffuse_color"].AsColor4();
643 978
644 if(offsets != 0) 979 int textureNum = faceMap["image"].AsInteger();
645 f.OffsetU = offsets; 980 float imagerot = faceMap["imagerot"].AsInteger();
981 float offsets = (float)faceMap["offsets"].AsReal();
982 float offsett = (float)faceMap["offsett"].AsReal();
983 float scales = (float)faceMap["scales"].AsReal();
984 float scalet = (float)faceMap["scalet"].AsReal();
646 985
647 if (offsett != 0) 986 if (imagerot != 0)
648 f.OffsetV = offsett; 987 f.Rotation = imagerot;
649 988
650 if (scales != 0) 989 if (offsets != 0)
651 f.RepeatU = scales; 990 f.OffsetU = offsets;
652 991
653 if (scalet != 0) 992 if (offsett != 0)
654 f.RepeatV = scalet; 993 f.OffsetV = offsett;
655 994
656 if (textures.Count > textureNum) 995 if (scales != 0)
657 f.TextureID = textures[textureNum]; 996 f.RepeatU = scales;
658 else
659 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
660 997
661 textureEntry.FaceTextures[face] = f; 998 if (scalet != 0)
662 } 999 f.RepeatV = scalet;
663 1000
664 pbs.TextureEntry = textureEntry.GetBytes(); 1001 if (textures.Count > textureNum)
1002 f.TextureID = textures[textureNum];
1003 else
1004 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
665 1005
666 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, ""); 1006 textureEntry.FaceTextures[face] = f;
667 meshAsset.Data = mesh_list[i].AsBinary(); 1007 }
668 m_assetService.Store(meshAsset);
669 1008
670 pbs.SculptEntry = true; 1009 pbs.TextureEntry = textureEntry.GetBytes();
671 pbs.SculptTexture = meshAsset.FullID;
672 pbs.SculptType = (byte)SculptType.Mesh;
673 pbs.SculptData = meshAsset.Data;
674 1010
675 Vector3 position = inner_instance_list["position"].AsVector3(); 1011 bool hasmesh = false;
676 Vector3 scale = inner_instance_list["scale"].AsVector3(); 1012 if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ...
677 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); 1013 {
1014 int meshindx = inner_instance_list["mesh"].AsInteger();
1015 if (meshAssets.Count > meshindx)
1016 {
1017 pbs.SculptEntry = true;
1018 pbs.SculptType = (byte)SculptType.Mesh;
1019 pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction
1020 // data will be requested from asset on rez (i hope)
1021 hasmesh = true;
1022 }
1023 }
1024
1025 Vector3 position = inner_instance_list["position"].AsVector3();
1026 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
1027
1028 // for now viwers do send fixed defaults
1029 // but this may change
1030// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
1031 byte physicsShapeType = (byte)PhysShapeType.prim; // default for mesh is simple convex
1032 if(hasmesh)
1033 physicsShapeType = (byte) PhysShapeType.convex; // default for mesh is simple convex
1034// int material = inner_instance_list["material"].AsInteger();
1035 byte material = (byte)Material.Wood;
678 1036
679// no longer used - begin ------------------------ 1037// 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(); 1038// int mesh = inner_instance_list["mesh"].AsInteger();
683 1039
684// OSDMap permissions = (OSDMap)inner_instance_list["permissions"]; 1040// OSDMap permissions = (OSDMap)inner_instance_list["permissions"];
@@ -693,24 +1049,49 @@ namespace OpenSim.Region.ClientStack.Linden
693// UUID owner_id = permissions["owner_id"].AsUUID(); 1049// UUID owner_id = permissions["owner_id"].AsUUID();
694// int owner_mask = permissions["owner_mask"].AsInteger(); 1050// int owner_mask = permissions["owner_mask"].AsInteger();
695// no longer used - end ------------------------ 1051// no longer used - end ------------------------
1052
1053
1054 SceneObjectPart prim
1055 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
1056
1057 prim.Scale = scale;
1058 rotations.Add(rotation);
1059 positions.Add(position);
1060 prim.UUID = UUID.Random();
1061 prim.CreatorID = creatorID;
1062 prim.OwnerID = owner_id;
1063 prim.GroupID = UUID.Zero;
1064 prim.LastOwnerID = creatorID;
1065 prim.CreationDate = Util.UnixTimeSinceEpoch();
1066
1067 if (grp == null)
1068 prim.Name = assetName;
1069 else
1070 prim.Name = assetName + "#" + i.ToString();
696 1071
697 UUID owner_id = m_HostCapsObj.AgentID; 1072 prim.EveryoneMask = 0;
1073 prim.GroupMask = 0;
698 1074
699 SceneObjectPart prim 1075 if (restrictPerms)
700 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); 1076 {
1077 prim.BaseMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
1078 prim.OwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
1079 prim.NextOwnerMask = 0;
1080 }
1081 else
1082 {
1083 prim.BaseMask = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1084 prim.OwnerMask = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1085 prim.NextOwnerMask = (uint)PermissionMask.Transfer;
1086 }
701 1087
702 prim.Scale = scale; 1088 if(istest)
703 //prim.OffsetPosition = position; 1089 prim.Description = "For testing only. Other uses are prohibited";
704 rotations.Add(rotation); 1090 else
705 positions.Add(position); 1091 prim.Description = "";
706 prim.UUID = UUID.Random(); 1092
707 prim.CreatorID = owner_id; 1093 prim.Material = material;
708 prim.OwnerID = owner_id; 1094 prim.PhysicsShapeType = physicsShapeType;
709 prim.GroupID = UUID.Zero;
710 prim.LastOwnerID = prim.OwnerID;
711 prim.CreationDate = Util.UnixTimeSinceEpoch();
712 prim.Name = assetName;
713 prim.Description = "";
714 1095
715// prim.BaseMask = (uint)base_mask; 1096// prim.BaseMask = (uint)base_mask;
716// prim.EveryoneMask = (uint)everyone_mask; 1097// prim.EveryoneMask = (uint)everyone_mask;
@@ -718,52 +1099,64 @@ namespace OpenSim.Region.ClientStack.Linden
718// prim.NextOwnerMask = (uint)next_owner_mask; 1099// prim.NextOwnerMask = (uint)next_owner_mask;
719// prim.OwnerMask = (uint)owner_mask; 1100// prim.OwnerMask = (uint)owner_mask;
720 1101
721 if (grp == null) 1102 if (grp == null)
722 grp = new SceneObjectGroup(prim); 1103 {
723 else 1104 grp = new SceneObjectGroup(prim);
724 grp.AddPart(prim); 1105 grp.LastOwnerID = creatorID;
725 } 1106 }
1107 else
1108 grp.AddPart(prim);
1109 }
726 1110
727 Vector3 rootPos = positions[0]; 1111 Vector3 rootPos = positions[0];
728 1112
729 if (grp.Parts.Length > 1) 1113 if (grp.Parts.Length > 1)
730 { 1114 {
731 // Fix first link number 1115 // Fix first link number
732 grp.RootPart.LinkNum++; 1116 grp.RootPart.LinkNum++;
733 1117
734 Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]); 1118 Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]);
735 Quaternion tmprot; 1119 Quaternion tmprot;
736 Vector3 offset; 1120 Vector3 offset;
737 1121
738 // fix children rotations and positions 1122 // fix children rotations and positions
739 for (int i = 1; i < rotations.Count; i++) 1123 for (int i = 1; i < rotations.Count; i++)
740 { 1124 {
741 tmprot = rotations[i]; 1125 tmprot = rotations[i];
742 tmprot = rootRotConj * tmprot; 1126 tmprot = rootRotConj * tmprot;
743 1127
744 grp.Parts[i].RotationOffset = tmprot; 1128 grp.Parts[i].RotationOffset = tmprot;
745 1129
746 offset = positions[i] - rootPos; 1130 offset = positions[i] - rootPos;
747 1131
748 offset *= rootRotConj; 1132 offset *= rootRotConj;
749 grp.Parts[i].OffsetPosition = offset; 1133 grp.Parts[i].OffsetPosition = offset;
1134 }
1135
1136 grp.AbsolutePosition = rootPos;
1137 grp.UpdateGroupRotationR(rotations[0]);
1138 }
1139 else
1140 {
1141 grp.AbsolutePosition = rootPos;
1142 grp.UpdateGroupRotationR(rotations[0]);
750 } 1143 }
751 1144
752 grp.AbsolutePosition = rootPos; 1145 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
753 grp.UpdateGroupRotationR(rotations[0]);
754 } 1146 }
755 else 1147
1148 else // not a mesh model
756 { 1149 {
757 grp.AbsolutePosition = rootPos; 1150 m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload");
758 grp.UpdateGroupRotationR(rotations[0]); 1151 return;
759 } 1152 }
760
761 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
762 } 1153 }
763 1154
764 AssetBase asset; 1155 AssetBase asset;
765 asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString()); 1156 asset = new AssetBase(assetID, assetName, assType, creatorIDstr);
766 asset.Data = data; 1157 asset.Data = data;
1158 if (istest)
1159 asset.Local = true;
767 if (AddNewAsset != null) 1160 if (AddNewAsset != null)
768 AddNewAsset(asset); 1161 AddNewAsset(asset);
769 else if (m_assetService != null) 1162 else if (m_assetService != null)
@@ -771,11 +1164,17 @@ namespace OpenSim.Region.ClientStack.Linden
771 1164
772 InventoryItemBase item = new InventoryItemBase(); 1165 InventoryItemBase item = new InventoryItemBase();
773 item.Owner = m_HostCapsObj.AgentID; 1166 item.Owner = m_HostCapsObj.AgentID;
774 item.CreatorId = m_HostCapsObj.AgentID.ToString(); 1167 item.CreatorId = creatorIDstr;
775 item.CreatorData = String.Empty; 1168 item.CreatorData = String.Empty;
776 item.ID = inventoryItem; 1169 item.ID = inventoryItem;
777 item.AssetID = asset.FullID; 1170 item.AssetID = asset.FullID;
778 item.Description = assetDescription; 1171 if (istest)
1172 {
1173 item.Description = "For testing only. Other uses are prohibited";
1174 item.Flags = (uint) (InventoryItemFlags.SharedSingleReference);
1175 }
1176 else
1177 item.Description = assetDescription;
779 item.Name = assetName; 1178 item.Name = assetName;
780 item.AssetType = assType; 1179 item.AssetType = assType;
781 item.InvType = inType; 1180 item.InvType = inType;
@@ -783,18 +1182,61 @@ namespace OpenSim.Region.ClientStack.Linden
783 1182
784 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current 1183 // 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. 1184 // (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 1185
789 item.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export; 1186 if (inType == (sbyte)CustomInventoryType.AnimationSet)
790 item.EveryOnePermissions = 0; 1187 {
791 item.NextPermissions = (uint)PermissionMask.All; 1188 AnimationSet.setCreateItemPermitions(item);
1189 }
1190
1191 else if (restrictPerms)
1192 {
1193 item.BasePermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
1194 item.CurrentPermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
1195 item.EveryOnePermissions = 0;
1196 item.NextPermissions = 0;
1197 }
1198 else
1199 {
1200 item.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1201 item.CurrentPermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1202 item.EveryOnePermissions = 0;
1203 item.NextPermissions = (uint)PermissionMask.Transfer;
1204 }
1205
792 item.CreationDate = Util.UnixTimeSinceEpoch(); 1206 item.CreationDate = Util.UnixTimeSinceEpoch();
793 1207
1208 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
1209
794 if (AddNewInventoryItem != null) 1210 if (AddNewInventoryItem != null)
795 { 1211 {
796 AddNewInventoryItem(m_HostCapsObj.AgentID, item); 1212 if (istest)
1213 {
1214 m_Scene.AddInventoryItem(client, item);
1215/*
1216 AddNewInventoryItem(m_HostCapsObj.AgentID, item, 0);
1217 if (client != null)
1218 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);
1219 */
1220 }
1221 else
1222 {
1223 AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
1224// if (client != null)
1225// {
1226// // let users see anything.. i don't so far
1227// string str;
1228// if (cost > 0)
1229// // dont remember where is money unit name to put here
1230// str = "Upload complete. charged " + cost.ToString() + "$";
1231// else
1232// str = "Upload complete";
1233// client.SendAgentAlertMessage(str, true);
1234// }
1235 }
797 } 1236 }
1237
1238 lock (m_ModelCost)
1239 m_FileAgentInventoryState = FileAgentInventoryState.idle;
798 } 1240 }
799 1241
800 /// <summary> 1242 /// <summary>
@@ -935,24 +1377,17 @@ namespace OpenSim.Region.ClientStack.Linden
935 { 1377 {
936 string message; 1378 string message;
937 copyItem = m_Scene.GiveInventoryItem(m_HostCapsObj.AgentID, item.Owner, itemID, folderID, out message); 1379 copyItem = m_Scene.GiveInventoryItem(m_HostCapsObj.AgentID, item.Owner, itemID, folderID, out message);
938 if (client != null) 1380 if (copyItem != null && client != null)
939 { 1381 {
940 if (copyItem != null) 1382 m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, ItemID:{0}, FolderID:{1}", copyItem.ID, copyItem.Folder);
941 { 1383 client.SendBulkUpdateInventory(copyItem);
942 m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, ItemID:{0}, FolderID:{1}", copyItem.ID, copyItem.Folder);
943 client.SendBulkUpdateInventory(copyItem);
944 }
945 else
946 {
947 client.SendAgentAlertMessage(message, false);
948 }
949 } 1384 }
950 } 1385 }
951 else 1386 else
952 { 1387 {
953 m_log.ErrorFormat("[CAPS]: CopyInventoryFromNotecard - Failed to retrieve item {0} from notecard {1}", itemID, notecardID); 1388 m_log.ErrorFormat("[CAPS]: CopyInventoryFromNotecard - Failed to retrieve item {0} from notecard {1}", itemID, notecardID);
954 if (client != null) 1389 if (client != null)
955 client.SendAgentAlertMessage("Failed to retrieve item", false); 1390 client.SendAlertMessage("Failed to retrieve item");
956 } 1391 }
957 } 1392 }
958 catch (Exception e) 1393 catch (Exception e)
@@ -995,18 +1430,142 @@ namespace OpenSim.Region.ClientStack.Linden
995 return response; 1430 return response;
996 } 1431 }
997 1432
998 public string UpdateAgentInformation(string request, string path, 1433 public string GetObjectCost(string request, string path,
1434 string param, IOSHttpRequest httpRequest,
1435 IOSHttpResponse httpResponse)
1436 {
1437 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1438 OSDMap resp = new OSDMap();
1439
1440 OSDArray object_ids = (OSDArray)req["object_ids"];
1441
1442 for (int i = 0; i < object_ids.Count; i++)
1443 {
1444 UUID uuid = object_ids[i].AsUUID();
1445
1446 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1447
1448 if (part != null)
1449 {
1450 SceneObjectGroup grp = part.ParentGroup;
1451 if (grp != null)
1452 {
1453 float linksetCost;
1454 float linksetPhysCost;
1455 float partCost;
1456 float partPhysCost;
1457
1458 grp.GetResourcesCosts(part, out linksetCost, out linksetPhysCost, out partCost, out partPhysCost);
1459
1460 OSDMap object_data = new OSDMap();
1461 object_data["linked_set_resource_cost"] = linksetCost;
1462 object_data["resource_cost"] = partCost;
1463 object_data["physics_cost"] = partPhysCost;
1464 object_data["linked_set_physics_cost"] = linksetPhysCost;
1465
1466 resp[uuid.ToString()] = object_data;
1467 }
1468 else
1469 {
1470 OSDMap object_data = new OSDMap();
1471 object_data["linked_set_resource_cost"] = 0;
1472 object_data["resource_cost"] = 0;
1473 object_data["physics_cost"] = 0;
1474 object_data["linked_set_physics_cost"] = 0;
1475
1476 resp[uuid.ToString()] = object_data;
1477 }
1478
1479 }
1480 }
1481
1482 string response = OSDParser.SerializeLLSDXmlString(resp);
1483 return response;
1484 }
1485
1486 public string ResourceCostSelected(string request, string path,
999 string param, IOSHttpRequest httpRequest, 1487 string param, IOSHttpRequest httpRequest,
1000 IOSHttpResponse httpResponse) 1488 IOSHttpResponse httpResponse)
1001 { 1489 {
1002 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request); 1490 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1003 OSDMap accessPrefs = (OSDMap)req["access_prefs"]; 1491 OSDMap resp = new OSDMap();
1004 string desiredMaturity = accessPrefs["max"]; 1492
1493
1494 float phys=0;
1495 float stream=0;
1496 float simul=0;
1497
1498 if (req.ContainsKey("selected_roots"))
1499 {
1500 OSDArray object_ids = (OSDArray)req["selected_roots"];
1501
1502 // should go by SOG suming costs for all parts
1503 // ll v3 works ok with several objects select we get the list and adds ok
1504 // FS calls per object so results are wrong guess fs bug
1505 for (int i = 0; i < object_ids.Count; i++)
1506 {
1507 UUID uuid = object_ids[i].AsUUID();
1508 float Physc;
1509 float simulc;
1510 float streamc;
1511
1512 SceneObjectGroup grp = m_Scene.GetGroupByPrim(uuid);
1513 if (grp != null)
1514 {
1515 grp.GetSelectedCosts(out Physc, out streamc, out simulc);
1516 phys += Physc;
1517 stream += streamc;
1518 simul += simulc;
1519 }
1520 }
1521 }
1522 else if (req.ContainsKey("selected_prims"))
1523 {
1524 OSDArray object_ids = (OSDArray)req["selected_prims"];
1525
1526 // don't see in use in any of the 2 viewers
1527 // guess it should be for edit linked but... nothing
1528 // should go to SOP per part
1529 for (int i = 0; i < object_ids.Count; i++)
1530 {
1531 UUID uuid = object_ids[i].AsUUID();
1532
1533 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1534 if (part != null)
1535 {
1536 phys += part.PhysicsCost;
1537 stream += part.StreamingCost;
1538 simul += part.SimulationCost;
1539 }
1540 }
1541 }
1542
1543 // if (simul != 0)
1544 {
1545 OSDMap object_data = new OSDMap();
1546
1547 object_data["physics"] = phys;
1548 object_data["streaming"] = stream;
1549 object_data["simulation"] = simul;
1550
1551 resp["selected"] = object_data;
1552 }
1553
1554 string response = OSDParser.SerializeLLSDXmlString(resp);
1555 return response;
1556 }
1005 1557
1558 public string UpdateAgentInformation(string request, string path,
1559 string param, IOSHttpRequest httpRequest,
1560 IOSHttpResponse httpResponse)
1561 {
1562// OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1006 OSDMap resp = new OSDMap(); 1563 OSDMap resp = new OSDMap();
1007 OSDMap respAccessPrefs = new OSDMap(); 1564
1008 respAccessPrefs["max"] = desiredMaturity; // echoing the maturity back means success 1565 OSDMap accessPrefs = new OSDMap();
1009 resp["access_prefs"] = respAccessPrefs; 1566 accessPrefs["max"] = "A";
1567
1568 resp["access_prefs"] = accessPrefs;
1010 1569
1011 string response = OSDParser.SerializeLLSDXmlString(resp); 1570 string response = OSDParser.SerializeLLSDXmlString(resp);
1012 return response; 1571 return response;
@@ -1015,6 +1574,10 @@ namespace OpenSim.Region.ClientStack.Linden
1015 1574
1016 public class AssetUploader 1575 public class AssetUploader
1017 { 1576 {
1577 private static readonly ILog m_log =
1578 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
1579
1580
1018 public event UpLoadedAsset OnUpLoad; 1581 public event UpLoadedAsset OnUpLoad;
1019 private UpLoadedAsset handlerUpLoad = null; 1582 private UpLoadedAsset handlerUpLoad = null;
1020 1583
@@ -1029,10 +1592,21 @@ namespace OpenSim.Region.ClientStack.Linden
1029 1592
1030 private string m_invType = String.Empty; 1593 private string m_invType = String.Empty;
1031 private string m_assetType = String.Empty; 1594 private string m_assetType = String.Empty;
1032 1595 private int m_cost;
1596 private string m_error = String.Empty;
1597
1598 private Timer m_timeoutTimer = new Timer();
1599 private UUID m_texturesFolder;
1600 private int m_nreqtextures;
1601 private int m_nreqmeshs;
1602 private int m_nreqinstances;
1603 private bool m_IsAtestUpload;
1604
1033 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, 1605 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
1034 UUID parentFolderID, string invType, string assetType, string path, 1606 UUID parentFolderID, string invType, string assetType, string path,
1035 IHttpServer httpServer, bool dumpAssetsToFile) 1607 IHttpServer httpServer, bool dumpAssetsToFile,
1608 int totalCost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
1609 bool IsAtestUpload)
1036 { 1610 {
1037 m_assetName = assetName; 1611 m_assetName = assetName;
1038 m_assetDes = description; 1612 m_assetDes = description;
@@ -1044,6 +1618,18 @@ namespace OpenSim.Region.ClientStack.Linden
1044 m_assetType = assetType; 1618 m_assetType = assetType;
1045 m_invType = invType; 1619 m_invType = invType;
1046 m_dumpAssetsToFile = dumpAssetsToFile; 1620 m_dumpAssetsToFile = dumpAssetsToFile;
1621 m_cost = totalCost;
1622
1623 m_texturesFolder = texturesFolder;
1624 m_nreqtextures = nreqtextures;
1625 m_nreqmeshs = nreqmeshs;
1626 m_nreqinstances = nreqinstances;
1627 m_IsAtestUpload = IsAtestUpload;
1628
1629 m_timeoutTimer.Elapsed += TimedOut;
1630 m_timeoutTimer.Interval = 120000;
1631 m_timeoutTimer.AutoReset = false;
1632 m_timeoutTimer.Start();
1047 } 1633 }
1048 1634
1049 /// <summary> 1635 /// <summary>
@@ -1058,12 +1644,14 @@ namespace OpenSim.Region.ClientStack.Linden
1058 UUID inv = inventoryItemID; 1644 UUID inv = inventoryItemID;
1059 string res = String.Empty; 1645 string res = String.Empty;
1060 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); 1646 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
1647/*
1061 uploadComplete.new_asset = newAssetID.ToString(); 1648 uploadComplete.new_asset = newAssetID.ToString();
1062 uploadComplete.new_inventory_item = inv; 1649 uploadComplete.new_inventory_item = inv;
1063 uploadComplete.state = "complete"; 1650 uploadComplete.state = "complete";
1064 1651
1065 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); 1652 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
1066 1653*/
1654 m_timeoutTimer.Stop();
1067 httpListener.RemoveStreamHandler("POST", uploaderPath); 1655 httpListener.RemoveStreamHandler("POST", uploaderPath);
1068 1656
1069 // TODO: probably make this a better set of extensions here 1657 // TODO: probably make this a better set of extensions here
@@ -1080,12 +1668,50 @@ namespace OpenSim.Region.ClientStack.Linden
1080 handlerUpLoad = OnUpLoad; 1668 handlerUpLoad = OnUpLoad;
1081 if (handlerUpLoad != null) 1669 if (handlerUpLoad != null)
1082 { 1670 {
1083 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType); 1671 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType,
1672 m_cost, m_texturesFolder, m_nreqtextures, m_nreqmeshs, m_nreqinstances, m_IsAtestUpload,
1673 ref m_error);
1674 }
1675 if (m_IsAtestUpload)
1676 {
1677 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1678 resperror.message = "Upload SUCESSEFULL for testing purposes only. Other uses are prohibited. Item will not work after 48 hours or on other regions";
1679 resperror.identifier = inv;
1680
1681 uploadComplete.error = resperror;
1682 uploadComplete.state = "Upload4Testing";
1683 }
1684 else
1685 {
1686 if (m_error == String.Empty)
1687 {
1688 uploadComplete.new_asset = newAssetID.ToString();
1689 uploadComplete.new_inventory_item = inv;
1690 // if (m_texturesFolder != UUID.Zero)
1691 // uploadComplete.new_texture_folder_id = m_texturesFolder;
1692 uploadComplete.state = "complete";
1693 }
1694 else
1695 {
1696 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1697 resperror.message = m_error;
1698 resperror.identifier = inv;
1699
1700 uploadComplete.error = resperror;
1701 uploadComplete.state = "failed";
1702 }
1084 } 1703 }
1085 1704
1705 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
1086 return res; 1706 return res;
1087 } 1707 }
1088 1708
1709 private void TimedOut(object sender, ElapsedEventArgs args)
1710 {
1711 m_log.InfoFormat("[CAPS]: Removing URL and handler for timed out mesh upload");
1712 httpListener.RemoveStreamHandler("POST", uploaderPath);
1713 }
1714
1089 ///Left this in and commented in case there are unforseen issues 1715 ///Left this in and commented in case there are unforseen issues
1090 //private void SaveAssetToFile(string filename, byte[] data) 1716 //private void SaveAssetToFile(string filename, byte[] data)
1091 //{ 1717 //{
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..f6a950f
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
@@ -0,0 +1,727 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28
29using System;
30using System.IO;
31using System.Collections;
32using System.Collections.Generic;
33using System.Text;
34
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37
38using OpenSim.Framework;
39using OpenSim.Region.Framework;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Framework.Capabilities;
42
43using ComponentAce.Compression.Libs.zlib;
44
45using OSDArray = OpenMetaverse.StructuredData.OSDArray;
46using OSDMap = OpenMetaverse.StructuredData.OSDMap;
47
48namespace OpenSim.Region.ClientStack.Linden
49{
50 public struct ModelPrimLimits
51 {
52
53 }
54
55 public class ModelCost
56 {
57
58 // upload fee defaults
59 // fees are normalized to 1.0
60 // this parameters scale them to basic cost ( so 1.0 translates to 10 )
61
62 public float ModelMeshCostFactor = 0.0f; // scale total cost relative to basic (excluding textures)
63 public float ModelTextureCostFactor = 1.0f; // scale textures fee to basic.
64 public float ModelMinCostFactor = 0.0f; // 0.5f; // minimum total model free excluding textures
65
66 // itens costs in normalized values
67 // ie will be multiplied by basicCost and factors above
68 public float primCreationCost = 0.002f; // extra cost for each prim creation overhead
69 // weigthed size to normalized cost
70 public float bytecost = 1e-5f;
71
72 // mesh upload fees based on compressed data sizes
73 // several data sections are counted more that once
74 // to promote user optimization
75 // following parameters control how many extra times they are added
76 // to global size.
77 // LOD meshs
78 const float medSizeWth = 1f; // 2x
79 const float lowSizeWth = 1.5f; // 2.5x
80 const float lowestSizeWth = 2f; // 3x
81 // favor potencially physical optimized meshs versus automatic decomposition
82 const float physMeshSizeWth = 6f; // counts 7x
83 const float physHullSizeWth = 8f; // counts 9x
84
85 // stream cost area factors
86 // more or less like SL
87 const float highLodFactor = 17.36f;
88 const float midLodFactor = 277.78f;
89 const float lowLodFactor = 1111.11f;
90
91 // physics cost is below, identical to SL, assuming shape type convex
92 // server cost is below identical to SL assuming non scripted non physical object
93
94 // internal
95 const int bytesPerCoord = 6; // 3 coords, 2 bytes per each
96
97 // control prims dimensions
98 public float PrimScaleMin = 0.001f;
99 public float NonPhysicalPrimScaleMax = 256f;
100 public float PhysicalPrimScaleMax = 10f;
101 public int ObjectLinkedPartsMax = 512;
102
103 // storage for a single mesh asset cost parameters
104 private class ameshCostParam
105 {
106 // LOD sizes for size dependent streaming cost
107 public int highLODSize;
108 public int medLODSize;
109 public int lowLODSize;
110 public int lowestLODSize;
111 // normalized fee based on compressed data sizes
112 public float costFee;
113 // physics cost
114 public float physicsCost;
115 }
116
117 // calculates a mesh model costs
118 // returns false on error, with a reason on parameter error
119 // resources input LLSD request
120 // basicCost input region assets upload cost
121 // totalcost returns model total upload fee
122 // meshcostdata returns detailed costs for viewer
123 // avatarSkeleton if mesh includes a avatar skeleton
124 // useAvatarCollider if we should use physics mesh for avatar
125 public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost,
126 LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning)
127 {
128 totalcost = 0;
129 error = string.Empty;
130
131 bool avatarSkeleton = false;
132
133 if (resources == null ||
134 resources.instance_list == null ||
135 resources.instance_list.Array.Count == 0)
136 {
137 error = "missing model information.";
138 return false;
139 }
140
141 int numberInstances = resources.instance_list.Array.Count;
142
143 if( numberInstances > ObjectLinkedPartsMax )
144 {
145 error = "Model whould have more than " + ObjectLinkedPartsMax.ToString() + " linked prims";
146 return false;
147 }
148
149 meshcostdata.model_streaming_cost = 0.0;
150 meshcostdata.simulation_cost = 0.0;
151 meshcostdata.physics_cost = 0.0;
152 meshcostdata.resource_cost = 0.0;
153
154 meshcostdata.upload_price_breakdown.mesh_instance = 0;
155 meshcostdata.upload_price_breakdown.mesh_physics = 0;
156 meshcostdata.upload_price_breakdown.mesh_streaming = 0;
157 meshcostdata.upload_price_breakdown.model = 0;
158
159 int itmp;
160
161 // textures cost
162 if (resources.texture_list != null && resources.texture_list.Array.Count > 0)
163 {
164 float textures_cost = (float)(resources.texture_list.Array.Count * basicCost);
165 textures_cost *= ModelTextureCostFactor;
166
167 itmp = (int)(textures_cost + 0.5f); // round
168 meshcostdata.upload_price_breakdown.texture = itmp;
169 totalcost += itmp;
170 }
171
172 // meshs assets cost
173 float meshsfee = 0;
174 int numberMeshs = 0;
175 bool haveMeshs = false;
176
177 bool curskeleton;
178 bool curAvatarPhys;
179
180 List<ameshCostParam> meshsCosts = new List<ameshCostParam>();
181
182 if (resources.mesh_list != null && resources.mesh_list.Array.Count > 0)
183 {
184 numberMeshs = resources.mesh_list.Array.Count;
185
186 for (int i = 0; i < numberMeshs; i++)
187 {
188 ameshCostParam curCost = new ameshCostParam();
189 byte[] data = (byte[])resources.mesh_list.Array[i];
190
191 if (!MeshCost(data, curCost,out curskeleton, out curAvatarPhys, out error))
192 {
193 return false;
194 }
195
196 if (curskeleton)
197 {
198 if (avatarSkeleton)
199 {
200 error = "model can only contain a avatar skeleton";
201 return false;
202 }
203 avatarSkeleton = true;
204 }
205 meshsCosts.Add(curCost);
206 meshsfee += curCost.costFee;
207 }
208 haveMeshs = true;
209 }
210
211 // instances (prims) cost
212
213
214 int mesh;
215 int skipedSmall = 0;
216 for (int i = 0; i < numberInstances; i++)
217 {
218 Hashtable inst = (Hashtable)resources.instance_list.Array[i];
219
220 ArrayList ascale = (ArrayList)inst["scale"];
221 Vector3 scale;
222 double tmp;
223 tmp = (double)ascale[0];
224 scale.X = (float)tmp;
225 tmp = (double)ascale[1];
226 scale.Y = (float)tmp;
227 tmp = (double)ascale[2];
228 scale.Z = (float)tmp;
229
230 if (scale.X < PrimScaleMin || scale.Y < PrimScaleMin || scale.Z < PrimScaleMin)
231 {
232 skipedSmall++;
233 continue;
234 }
235
236 if (scale.X > NonPhysicalPrimScaleMax || scale.Y > NonPhysicalPrimScaleMax || scale.Z > NonPhysicalPrimScaleMax)
237 {
238 error = "Model contains parts with sides larger than " + NonPhysicalPrimScaleMax.ToString() + "m. Please ajust scale";
239 return false;
240 }
241
242 if (haveMeshs && inst.ContainsKey("mesh"))
243 {
244 mesh = (int)inst["mesh"];
245
246 if (mesh >= numberMeshs)
247 {
248 error = "Incoerent model information.";
249 return false;
250 }
251
252 // streamming cost
253
254 float sqdiam = scale.LengthSquared();
255
256 ameshCostParam curCost = meshsCosts[mesh];
257 float mesh_streaming = streamingCost(curCost, sqdiam);
258
259 meshcostdata.model_streaming_cost += mesh_streaming;
260 meshcostdata.physics_cost += curCost.physicsCost;
261 }
262 else // instance as no mesh ??
263 {
264 // to do later if needed
265 meshcostdata.model_streaming_cost += 0.5f;
266 meshcostdata.physics_cost += 1.0f;
267 }
268
269 // assume unscripted and static prim server cost
270 meshcostdata.simulation_cost += 0.5f;
271 // charge for prims creation
272 meshsfee += primCreationCost;
273 }
274
275 if (skipedSmall > 0)
276 {
277 if (skipedSmall > numberInstances / 2)
278 {
279 error = "Model contains too many prims smaller than " + PrimScaleMin.ToString() +
280 "m minimum allowed size. Please check scalling";
281 return false;
282 }
283 else
284 warning += skipedSmall.ToString() + " of the requested " +numberInstances.ToString() +
285 " model prims will not upload because they are smaller than " + PrimScaleMin.ToString() +
286 "m minimum allowed size. Please check scalling ";
287 }
288
289 if (meshcostdata.physics_cost <= meshcostdata.model_streaming_cost)
290 meshcostdata.resource_cost = meshcostdata.model_streaming_cost;
291 else
292 meshcostdata.resource_cost = meshcostdata.physics_cost;
293
294 if (meshcostdata.resource_cost < meshcostdata.simulation_cost)
295 meshcostdata.resource_cost = meshcostdata.simulation_cost;
296
297 // scale cost
298 // at this point a cost of 1.0 whould mean basic cost
299 meshsfee *= ModelMeshCostFactor;
300
301 if (meshsfee < ModelMinCostFactor)
302 meshsfee = ModelMinCostFactor;
303
304 // actually scale it to basic cost
305 meshsfee *= (float)basicCost;
306
307 meshsfee += 0.5f; // rounding
308
309 totalcost += (int)meshsfee;
310
311 // breakdown prices
312 // don't seem to be in use so removed code for now
313
314 return true;
315 }
316
317 // single mesh asset cost
318 private bool MeshCost(byte[] data, ameshCostParam cost,out bool skeleton, out bool avatarPhys, out string error)
319 {
320 cost.highLODSize = 0;
321 cost.medLODSize = 0;
322 cost.lowLODSize = 0;
323 cost.lowestLODSize = 0;
324 cost.physicsCost = 0.0f;
325 cost.costFee = 0.0f;
326
327 error = string.Empty;
328
329 skeleton = false;
330 avatarPhys = false;
331
332 if (data == null || data.Length == 0)
333 {
334 error = "Missing model information.";
335 return false;
336 }
337
338 OSD meshOsd = null;
339 int start = 0;
340
341 error = "Invalid model data";
342
343 using (MemoryStream ms = new MemoryStream(data))
344 {
345 try
346 {
347 OSD osd = OSDParser.DeserializeLLSDBinary(ms);
348 if (osd is OSDMap)
349 meshOsd = (OSDMap)osd;
350 else
351 return false;
352 }
353 catch (Exception e)
354 {
355 return false;
356 }
357 start = (int)ms.Position;
358 }
359
360 OSDMap map = (OSDMap)meshOsd;
361 OSDMap tmpmap;
362
363 int highlod_size = 0;
364 int medlod_size = 0;
365 int lowlod_size = 0;
366 int lowestlod_size = 0;
367 int skin_size = 0;
368
369 int hulls_size = 0;
370 int phys_nhulls;
371 int phys_hullsvertices = 0;
372
373 int physmesh_size = 0;
374 int phys_ntriangles = 0;
375
376 int submesh_offset = -1;
377
378 if (map.ContainsKey("skeleton"))
379 {
380 tmpmap = (OSDMap)map["skeleton"];
381 if (tmpmap.ContainsKey("offset") && tmpmap.ContainsKey("size"))
382 {
383 int sksize = tmpmap["size"].AsInteger();
384 if(sksize > 0)
385 skeleton = true;
386 }
387 }
388
389 if (map.ContainsKey("physics_convex"))
390 {
391 tmpmap = (OSDMap)map["physics_convex"];
392 if (tmpmap.ContainsKey("offset"))
393 submesh_offset = tmpmap["offset"].AsInteger() + start;
394 if (tmpmap.ContainsKey("size"))
395 hulls_size = tmpmap["size"].AsInteger();
396 }
397
398 if (submesh_offset < 0 || hulls_size == 0)
399 {
400 error = "Missing physics_convex block";
401 return false;
402 }
403
404 if (!hulls(data, submesh_offset, hulls_size, out phys_hullsvertices, out phys_nhulls))
405 {
406 error = "Bad physics_convex block";
407 return false;
408 }
409
410 submesh_offset = -1;
411
412 // only look for LOD meshs sizes
413
414 if (map.ContainsKey("high_lod"))
415 {
416 tmpmap = (OSDMap)map["high_lod"];
417 // see at least if there is a offset for this one
418 if (tmpmap.ContainsKey("offset"))
419 submesh_offset = tmpmap["offset"].AsInteger() + start;
420 if (tmpmap.ContainsKey("size"))
421 highlod_size = tmpmap["size"].AsInteger();
422 }
423
424 if (submesh_offset < 0 || highlod_size <= 0)
425 {
426 error = "Missing high_lod block";
427 return false;
428 }
429
430 bool haveprev = true;
431
432 if (map.ContainsKey("medium_lod"))
433 {
434 tmpmap = (OSDMap)map["medium_lod"];
435 if (tmpmap.ContainsKey("size"))
436 medlod_size = tmpmap["size"].AsInteger();
437 else
438 haveprev = false;
439 }
440
441 if (haveprev && map.ContainsKey("low_lod"))
442 {
443 tmpmap = (OSDMap)map["low_lod"];
444 if (tmpmap.ContainsKey("size"))
445 lowlod_size = tmpmap["size"].AsInteger();
446 else
447 haveprev = false;
448 }
449
450 if (haveprev && map.ContainsKey("lowest_lod"))
451 {
452 tmpmap = (OSDMap)map["lowest_lod"];
453 if (tmpmap.ContainsKey("size"))
454 lowestlod_size = tmpmap["size"].AsInteger();
455 }
456
457 if (map.ContainsKey("skin"))
458 {
459 tmpmap = (OSDMap)map["skin"];
460 if (tmpmap.ContainsKey("size"))
461 skin_size = tmpmap["size"].AsInteger();
462 }
463
464 cost.highLODSize = highlod_size;
465 cost.medLODSize = medlod_size;
466 cost.lowLODSize = lowlod_size;
467 cost.lowestLODSize = lowestlod_size;
468
469 submesh_offset = -1;
470
471 tmpmap = null;
472 if(map.ContainsKey("physics_mesh"))
473 tmpmap = (OSDMap)map["physics_mesh"];
474 else if (map.ContainsKey("physics_shape")) // old naming
475 tmpmap = (OSDMap)map["physics_shape"];
476
477 if(tmpmap != null)
478 {
479 if (tmpmap.ContainsKey("offset"))
480 submesh_offset = tmpmap["offset"].AsInteger() + start;
481 if (tmpmap.ContainsKey("size"))
482 physmesh_size = tmpmap["size"].AsInteger();
483
484 if (submesh_offset >= 0 || physmesh_size > 0)
485 {
486
487 if (!submesh(data, submesh_offset, physmesh_size, out phys_ntriangles))
488 {
489 error = "Model data parsing error";
490 return false;
491 }
492 }
493 }
494
495 // upload is done in convex shape type so only one hull
496 phys_hullsvertices++;
497 cost.physicsCost = 0.04f * phys_hullsvertices;
498
499 float sfee;
500
501 sfee = data.Length; // start with total compressed data size
502
503 // penalize lod meshs that should be more builder optimized
504 sfee += medSizeWth * medlod_size;
505 sfee += lowSizeWth * lowlod_size;
506 sfee += lowestSizeWth * lowlod_size;
507
508 // physics
509 // favor potencial optimized meshs versus automatic decomposition
510 if (physmesh_size != 0)
511 sfee += physMeshSizeWth * (physmesh_size + hulls_size / 4); // reduce cost of mandatory convex hull
512 else
513 sfee += physHullSizeWth * hulls_size;
514
515 // bytes to money
516 sfee *= bytecost;
517
518 cost.costFee = sfee;
519 return true;
520 }
521
522 // parses a LOD or physics mesh component
523 private bool submesh(byte[] data, int offset, int size, out int ntriangles)
524 {
525 ntriangles = 0;
526
527 OSD decodedMeshOsd = new OSD();
528 byte[] meshBytes = new byte[size];
529 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
530 try
531 {
532 using (MemoryStream inMs = new MemoryStream(meshBytes))
533 {
534 using (MemoryStream outMs = new MemoryStream())
535 {
536 using (ZOutputStream zOut = new ZOutputStream(outMs))
537 {
538 byte[] readBuffer = new byte[4096];
539 int readLen = 0;
540 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
541 {
542 zOut.Write(readBuffer, 0, readLen);
543 }
544 zOut.Flush();
545 outMs.Seek(0, SeekOrigin.Begin);
546
547 byte[] decompressedBuf = outMs.GetBuffer();
548 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
549 }
550 }
551 }
552 }
553 catch (Exception e)
554 {
555 return false;
556 }
557
558 OSDArray decodedMeshOsdArray = null;
559 if ((!decodedMeshOsd is OSDArray))
560 return false;
561
562 byte[] dummy;
563
564 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
565 foreach (OSD subMeshOsd in decodedMeshOsdArray)
566 {
567 if (subMeshOsd is OSDMap)
568 {
569 OSDMap subtmpmap = (OSDMap)subMeshOsd;
570 if (subtmpmap.ContainsKey("NoGeometry") && ((OSDBoolean)subtmpmap["NoGeometry"]))
571 continue;
572
573 if (!subtmpmap.ContainsKey("Position"))
574 return false;
575
576 if (subtmpmap.ContainsKey("TriangleList"))
577 {
578 dummy = subtmpmap["TriangleList"].AsBinary();
579 ntriangles += dummy.Length / bytesPerCoord;
580 }
581 else
582 return false;
583 }
584 }
585
586 return true;
587 }
588
589 // parses convex hulls component
590 private bool hulls(byte[] data, int offset, int size, out int nvertices, out int nhulls)
591 {
592 nvertices = 0;
593 nhulls = 1;
594
595 OSD decodedMeshOsd = new OSD();
596 byte[] meshBytes = new byte[size];
597 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
598 try
599 {
600 using (MemoryStream inMs = new MemoryStream(meshBytes))
601 {
602 using (MemoryStream outMs = new MemoryStream())
603 {
604 using (ZOutputStream zOut = new ZOutputStream(outMs))
605 {
606 byte[] readBuffer = new byte[4096];
607 int readLen = 0;
608 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
609 {
610 zOut.Write(readBuffer, 0, readLen);
611 }
612 zOut.Flush();
613 outMs.Seek(0, SeekOrigin.Begin);
614
615 byte[] decompressedBuf = outMs.GetBuffer();
616 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
617 }
618 }
619 }
620 }
621 catch (Exception e)
622 {
623 return false;
624 }
625
626 OSDMap cmap = (OSDMap)decodedMeshOsd;
627 if (cmap == null)
628 return false;
629
630 byte[] dummy;
631
632 // must have one of this
633 if (cmap.ContainsKey("BoundingVerts"))
634 {
635 dummy = cmap["BoundingVerts"].AsBinary();
636 nvertices = dummy.Length / bytesPerCoord;
637 }
638 else
639 return false;
640
641/* upload is done with convex shape type
642 if (cmap.ContainsKey("HullList"))
643 {
644 dummy = cmap["HullList"].AsBinary();
645 nhulls += dummy.Length;
646 }
647
648
649 if (cmap.ContainsKey("Positions"))
650 {
651 dummy = cmap["Positions"].AsBinary();
652 nvertices = dummy.Length / bytesPerCoord;
653 }
654 */
655
656 return true;
657 }
658
659 // returns streaming cost from on mesh LODs sizes in curCost and square of prim size length
660 private float streamingCost(ameshCostParam curCost, float sqdiam)
661 {
662 // compute efective areas
663 float ma = 262144f;
664
665 float mh = sqdiam * highLodFactor;
666 if (mh > ma)
667 mh = ma;
668 float mm = sqdiam * midLodFactor;
669 if (mm > ma)
670 mm = ma;
671
672 float ml = sqdiam * lowLodFactor;
673 if (ml > ma)
674 ml = ma;
675
676 float mlst = ma;
677
678 mlst -= ml;
679 ml -= mm;
680 mm -= mh;
681
682 if (mlst < 1.0f)
683 mlst = 1.0f;
684 if (ml < 1.0f)
685 ml = 1.0f;
686 if (mm < 1.0f)
687 mm = 1.0f;
688 if (mh < 1.0f)
689 mh = 1.0f;
690
691 ma = mlst + ml + mm + mh;
692
693 // get LODs compressed sizes
694 // giving 384 bytes bonus
695 int lst = curCost.lowestLODSize - 384;
696 int l = curCost.lowLODSize - 384;
697 int m = curCost.medLODSize - 384;
698 int h = curCost.highLODSize - 384;
699
700 // use previus higher LOD size on missing ones
701 if (m <= 0)
702 m = h;
703 if (l <= 0)
704 l = m;
705 if (lst <= 0)
706 lst = l;
707
708 // force minumum sizes
709 if (lst < 16)
710 lst = 16;
711 if (l < 16)
712 l = 16;
713 if (m < 16)
714 m = 16;
715 if (h < 16)
716 h = 16;
717
718 // compute cost weighted by relative effective areas
719 float cost = (float)lst * mlst + (float)l * ml + (float)m * mm + (float)h * mh;
720 cost /= ma;
721
722 cost *= 0.004f; // overall tunning parameter
723
724 return cost;
725 }
726 }
727}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index 9b9f6a7..feb3322 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
@@ -201,6 +200,7 @@ namespace OpenSim.Region.ClientStack.Linden
201 } 200 }
202 201
203 /// <summary> 202 /// <summary>
203
204 /// May return a null queue 204 /// May return a null queue
205 /// </summary> 205 /// </summary>
206 /// <param name="agentId"></param> 206 /// <param name="agentId"></param>
@@ -231,18 +231,12 @@ namespace OpenSim.Region.ClientStack.Linden
231 lock (queue) 231 lock (queue)
232 queue.Enqueue(ev); 232 queue.Enqueue(ev);
233 } 233 }
234 else if (DebugLevel > 0) 234 else
235 { 235 {
236 ScenePresence sp = m_scene.GetScenePresence(avatarID);
237
238 // This assumes that an NPC should never have a queue.
239 if (sp != null && sp.PresenceType != PresenceType.Npc)
240 {
241 OSDMap evMap = (OSDMap)ev; 236 OSDMap evMap = (OSDMap)ev;
242 m_log.WarnFormat( 237 m_log.WarnFormat(
243 "[EVENTQUEUE]: (Enqueue) No queue found for agent {0} {1} when placing message {2} in region {3}", 238 "[EVENTQUEUE]: (Enqueue) No queue found for agent {0} when placing message {1} in region {2}",
244 sp.Name, sp.UUID, evMap["message"], m_scene.Name); 239 avatarID, evMap["message"], m_scene.Name);
245 }
246 } 240 }
247 } 241 }
248 catch (NullReferenceException e) 242 catch (NullReferenceException e)
@@ -263,28 +257,13 @@ namespace OpenSim.Region.ClientStack.Linden
263 lock (queues) 257 lock (queues)
264 queues.Remove(agentID); 258 queues.Remove(agentID);
265 259
266 List<UUID> removeitems = new List<UUID>();
267 lock (m_AvatarQueueUUIDMapping) 260 lock (m_AvatarQueueUUIDMapping)
268 m_AvatarQueueUUIDMapping.Remove(agentID); 261 m_AvatarQueueUUIDMapping.Remove(agentID);
269 262
270 UUID searchval = UUID.Zero; 263 lock (m_ids)
271
272 removeitems.Clear();
273
274 lock (m_QueueUUIDAvatarMapping)
275 { 264 {
276 foreach (UUID ky in m_QueueUUIDAvatarMapping.Keys) 265 if (!m_ids.ContainsKey(agentID))
277 { 266 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 } 267 }
289 268
290 // m_log.DebugFormat("[EVENTQUEUE]: Deleted queues for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); 269 // m_log.DebugFormat("[EVENTQUEUE]: Deleted queues for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
@@ -309,55 +288,95 @@ namespace OpenSim.Region.ClientStack.Linden
309 "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}", 288 "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
310 agentID, caps, m_scene.RegionInfo.RegionName); 289 agentID, caps, m_scene.RegionInfo.RegionName);
311 290
312 // Let's instantiate a Queue for this agent right now
313 TryGetQueue(agentID);
314
315 UUID eventQueueGetUUID; 291 UUID eventQueueGetUUID;
292 Queue<OSD> queue;
293 Random rnd = new Random(Environment.TickCount);
294 int nrnd = rnd.Next(30000000);
295 if (nrnd < 0)
296 nrnd = -nrnd;
316 297
317 lock (m_AvatarQueueUUIDMapping) 298 lock (queues)
318 { 299 {
319 // Reuse open queues. The client does! 300 if (queues.ContainsKey(agentID))
320 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID)) 301 queue = queues[agentID];
302 else
303 queue = null;
304
305 if (queue == null)
321 { 306 {
322 //m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!"); 307 queue = new Queue<OSD>();
323 eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID]; 308 queues[agentID] = queue;
309
310 // push markers to handle old responses still waiting
311 // this will cost at most viewer getting two forced noevents
312 // even being a new queue better be safe
313 queue.Enqueue(null);
314 queue.Enqueue(null); // one should be enough
315
316 lock (m_AvatarQueueUUIDMapping)
317 {
318 eventQueueGetUUID = UUID.Random();
319 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
320 {
321 // oops this should not happen ?
322 m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID without a queue");
323 eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
324 }
325 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
326 }
327 lock (m_ids)
328 {
329 if (!m_ids.ContainsKey(agentID))
330 m_ids.Add(agentID, nrnd);
331 else
332 m_ids[agentID] = nrnd;
333 }
324 } 334 }
325 else 335 else
326 { 336 {
327 eventQueueGetUUID = UUID.Random(); 337 // push markers to handle old responses still waiting
328 //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!"); 338 // this will cost at most viewer getting two forced noevents
339 // even being a new queue better be safe
340 queue.Enqueue(null);
341 queue.Enqueue(null); // one should be enough
342
343 // reuse or not to reuse TODO FIX
344 lock (m_AvatarQueueUUIDMapping)
345 {
346 // Reuse open queues. The client does!
347 // Its reuse caps path not queues those are been reused already
348 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
349 {
350 m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
351 eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
352 }
353 else
354 {
355 eventQueueGetUUID = UUID.Random();
356 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
357 m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
358 }
359 }
360 lock (m_ids)
361 {
362 // change to negative numbers so they are changed at end of sending first marker
363 // old data on a queue may be sent on a response for a new caps
364 // but at least will be sent with coerent IDs
365 if (!m_ids.ContainsKey(agentID))
366 m_ids.Add(agentID, -nrnd); // should not happen
367 else
368 m_ids[agentID] = -m_ids[agentID];
369 }
329 } 370 }
330 } 371 }
331 372
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( 373 caps.RegisterPollHandler(
345 "EventQueueGet", 374 "EventQueueGet",
346 new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS)); 375 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 } 376 }
355 377
356 public bool HasEvents(UUID requestID, UUID agentID) 378 public bool HasEvents(UUID requestID, UUID agentID)
357 { 379 {
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); 380 Queue<OSD> queue = GetQueue(agentID);
362 if (queue != null) 381 if (queue != null)
363 lock (queue) 382 lock (queue)
@@ -366,7 +385,8 @@ namespace OpenSim.Region.ClientStack.Linden
366 return queue.Count > 0; 385 return queue.Count > 0;
367 } 386 }
368 387
369 return false; 388 //m_log.WarnFormat("POLLED FOR EVENTS BY {0} unknown agent", agentID);
389 return true;
370 } 390 }
371 391
372 /// <summary> 392 /// <summary>
@@ -395,55 +415,65 @@ namespace OpenSim.Region.ClientStack.Linden
395 return NoEvents(requestID, pAgentId); 415 return NoEvents(requestID, pAgentId);
396 } 416 }
397 417
398 OSD element; 418 OSD element = null;;
419 OSDArray array = new OSDArray();
420 int thisID = 0;
421 bool negativeID = false;
422
399 lock (queue) 423 lock (queue)
400 { 424 {
401 if (queue.Count == 0) 425 if (queue.Count == 0)
402 return NoEvents(requestID, pAgentId); 426 return NoEvents(requestID, pAgentId);
403 element = queue.Dequeue(); // 15s timeout
404 }
405 427
406 int thisID = 0; 428 lock (m_ids)
407 lock (m_ids) 429 thisID = m_ids[pAgentId];
408 thisID = m_ids[pAgentId];
409 430
410 OSDArray array = new OSDArray(); 431 if (thisID < 0)
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
422 array.Add(element);
423
424 lock (queue)
425 { 432 {
426 while (queue.Count > 0) 433 negativeID = true;
427 { 434 thisID = -thisID;
428 element = queue.Dequeue(); 435 }
436
437 while (queue.Count > 0)
438 {
439 element = queue.Dequeue();
440 // add elements until a marker is found
441 // so they get into a response
442 if (element == null)
443 break;
444 if (DebugLevel > 0)
445 LogOutboundDebugMessage(element, pAgentId);
446 array.Add(element);
447 thisID++;
448 }
449 }
429 450
430 if (DebugLevel > 0) 451 OSDMap events = null;
431 LogOutboundDebugMessage(element, pAgentId);
432 452
433 array.Add(element); 453 if (array.Count > 0)
434 thisID++; 454 {
435 } 455 events = new OSDMap();
436 } 456 events.Add("events", array);
457 events.Add("id", new OSDInteger(thisID));
437 } 458 }
438 459
439 OSDMap events = new OSDMap(); 460 if (negativeID && element == null)
440 events.Add("events", array); 461 {
462 Random rnd = new Random(Environment.TickCount);
463 thisID = rnd.Next(30000000);
464 if (thisID < 0)
465 thisID = -thisID;
466 }
441 467
442 events.Add("id", new OSDInteger(thisID));
443 lock (m_ids) 468 lock (m_ids)
444 { 469 {
445 m_ids[pAgentId] = thisID + 1; 470 m_ids[pAgentId] = thisID + 1;
446 } 471 }
472
473 // if there where no elements before a marker send a NoEvents
474 if (array.Count == 0)
475 return NoEvents(requestID, pAgentId);
476
447 Hashtable responsedata = new Hashtable(); 477 Hashtable responsedata = new Hashtable();
448 responsedata["int_response_code"] = 200; 478 responsedata["int_response_code"] = 200;
449 responsedata["content_type"] = "application/xml"; 479 responsedata["content_type"] = "application/xml";
@@ -461,260 +491,12 @@ namespace OpenSim.Region.ClientStack.Linden
461 responsedata["content_type"] = "text/plain"; 491 responsedata["content_type"] = "text/plain";
462 responsedata["keepalive"] = false; 492 responsedata["keepalive"] = false;
463 responsedata["reusecontext"] = false; 493 responsedata["reusecontext"] = false;
464 responsedata["str_response_string"] = "Upstream error: "; 494 responsedata["str_response_string"] = "<llsd></llsd>";
465 responsedata["error_status_text"] = "Upstream error:"; 495 responsedata["error_status_text"] = "<llsd></llsd>";
466 responsedata["http_protocol_version"] = "HTTP/1.0"; 496 responsedata["http_protocol_version"] = "HTTP/1.0";
467 return responsedata; 497 return responsedata;
468 } 498 }
469 499
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) 500 public void DisableSimulator(ulong handle, UUID avatarID)
719 { 501 {
720 OSD item = EventQueueHelper.DisableSimulator(handle); 502 OSD item = EventQueueHelper.DisableSimulator(handle);
@@ -827,4 +609,4 @@ namespace OpenSim.Region.ClientStack.Linden
827 Enqueue(item, avatarID); 609 Enqueue(item, avatarID);
828 } 610 }
829 } 611 }
830} \ No newline at end of file 612}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
index 384af74..799ad0b 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
@@ -76,9 +76,9 @@ namespace OpenSim.Region.ClientStack.Linden
76 76
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", OSD.FromInteger(endPoint.Port));
80 llsdSimInfo.Add("RegionSizeX", OSD.FromUInteger((uint) regionSizeX)); 80 llsdSimInfo.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX));
81 llsdSimInfo.Add("RegionSizeY", OSD.FromUInteger((uint) regionSizeY)); 81 llsdSimInfo.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY));
82 82
83 OSDArray arr = new OSDArray(1); 83 OSDArray arr = new OSDArray(1);
84 arr.Add(llsdSimInfo); 84 arr.Add(llsdSimInfo);
@@ -157,6 +157,12 @@ namespace OpenSim.Region.ClientStack.Linden
157 uint locationID, uint flags, string capsURL, UUID agentID, 157 uint locationID, uint flags, string capsURL, UUID agentID,
158 int regionSizeX, int regionSizeY) 158 int regionSizeX, int regionSizeY)
159 { 159 {
160 // not sure why flags get overwritten here
161 if ((flags & (uint)TeleportFlags.IsFlying) != 0)
162 flags = (uint)TeleportFlags.ViaLocation | (uint)TeleportFlags.IsFlying;
163 else
164 flags = (uint)TeleportFlags.ViaLocation;
165
160 OSDMap info = new OSDMap(); 166 OSDMap info = new OSDMap();
161 info.Add("AgentID", OSD.FromUUID(agentID)); 167 info.Add("AgentID", OSD.FromUUID(agentID));
162 info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this? 168 info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this?
@@ -165,7 +171,8 @@ namespace OpenSim.Region.ClientStack.Linden
165 info.Add("SimAccess", OSD.FromInteger(simAccess)); 171 info.Add("SimAccess", OSD.FromInteger(simAccess));
166 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes())); 172 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes()));
167 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port)); 173 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port));
168 info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation 174// info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation
175 info.Add("TeleportFlags", OSD.FromUInteger(flags));
169 info.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX)); 176 info.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX));
170 info.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY)); 177 info.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY));
171 178
@@ -204,8 +211,8 @@ namespace OpenSim.Region.ClientStack.Linden
204 {"sim-ip-and-port", new OSDString(simIpAndPort)}, 211 {"sim-ip-and-port", new OSDString(simIpAndPort)},
205 {"seed-capability", new OSDString(seedcap)}, 212 {"seed-capability", new OSDString(seedcap)},
206 {"region-handle", OSD.FromULong(regionHandle)}, 213 {"region-handle", OSD.FromULong(regionHandle)},
207 {"region-size-x", OSD.FromInteger(regionSizeX)}, 214 {"region-size-x", OSD.FromUInteger((uint)regionSizeX)},
208 {"region-size-y", OSD.FromInteger(regionSizeY)} 215 {"region-size-y", OSD.FromUInteger((uint)regionSizeY)}
209 }; 216 };
210 217
211 return BuildEvent("EstablishAgentCommunication", body); 218 return BuildEvent("EstablishAgentCommunication", body);
@@ -412,7 +419,7 @@ namespace OpenSim.Region.ClientStack.Linden
412 public static OSD partPhysicsProperties(uint localID, byte physhapetype, 419 public static OSD partPhysicsProperties(uint localID, byte physhapetype,
413 float density, float friction, float bounce, float gravmod) 420 float density, float friction, float bounce, float gravmod)
414 { 421 {
415 422
416 OSDMap physinfo = new OSDMap(6); 423 OSDMap physinfo = new OSDMap(6);
417 physinfo["LocalID"] = localID; 424 physinfo["LocalID"] = localID;
418 physinfo["Density"] = density; 425 physinfo["Density"] = density;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
index f57d857..b5a70040 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,50 @@ 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
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 struct aPollRequest
69 {
70 public PollServiceMeshEventArgs thepoll;
71 public UUID reqID;
72 public Hashtable request;
73 }
74
75 public class aPollResponse
76 {
77 public Hashtable response;
78 public int bytes;
79 public int lod;
80 }
81
82
83 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
84
85 private static GetMeshHandler m_getMeshHandler;
86
87 private IAssetService m_assetService = null;
88
89 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
90 private static Thread[] m_workerThreads = null;
91
92 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
93 new OpenMetaverse.BlockingQueue<aPollRequest>();
94
95 private Dictionary<UUID, PollServiceMeshEventArgs> m_pollservices = new Dictionary<UUID, PollServiceMeshEventArgs>();
96
63 97
64 #region Region Module interfaceBase Members 98 #region Region Module interfaceBase Members
65 99
100 ~GetMeshModule()
101 {
102 foreach (Thread t in m_workerThreads)
103 Watchdog.AbortThread(t.ManagedThreadId);
104
105 }
106
66 public Type ReplaceableInterface 107 public Type ReplaceableInterface
67 { 108 {
68 get { return null; } 109 get { return null; }
@@ -87,6 +128,7 @@ namespace OpenSim.Region.ClientStack.Linden
87 if (m_URL2 != string.Empty) 128 if (m_URL2 != string.Empty)
88 { 129 {
89 m_Enabled = true; 130 m_Enabled = true;
131
90 m_RedirectURL2 = config.GetString("GetMesh2RedirectURL"); 132 m_RedirectURL2 = config.GetString("GetMesh2RedirectURL");
91 } 133 }
92 } 134 }
@@ -97,6 +139,8 @@ namespace OpenSim.Region.ClientStack.Linden
97 return; 139 return;
98 140
99 m_scene = pScene; 141 m_scene = pScene;
142
143 m_assetService = pScene.AssetService;
100 } 144 }
101 145
102 public void RemoveRegion(Scene scene) 146 public void RemoveRegion(Scene scene)
@@ -105,6 +149,9 @@ namespace OpenSim.Region.ClientStack.Linden
105 return; 149 return;
106 150
107 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 151 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
152 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
153 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
154
108 m_scene = null; 155 m_scene = null;
109 } 156 }
110 157
@@ -115,6 +162,27 @@ namespace OpenSim.Region.ClientStack.Linden
115 162
116 m_AssetService = m_scene.RequestModuleInterface<IAssetService>(); 163 m_AssetService = m_scene.RequestModuleInterface<IAssetService>();
117 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 164 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
165 // We'll reuse the same handler for all requests.
166 m_getMeshHandler = new GetMeshHandler(m_assetService);
167 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
168 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
169
170 if (m_workerThreads == null)
171 {
172 m_workerThreads = new Thread[2];
173
174 for (uint i = 0; i < 2; i++)
175 {
176 m_workerThreads[i] = WorkManager.StartThread(DoMeshRequests,
177 String.Format("MeshWorkerThread{0}", i),
178 ThreadPriority.Normal,
179 false,
180 false,
181 null,
182 int.MaxValue);
183 }
184 }
185
118 } 186 }
119 187
120 188
@@ -124,44 +192,346 @@ namespace OpenSim.Region.ClientStack.Linden
124 192
125 #endregion 193 #endregion
126 194
195 private void DoMeshRequests()
196 {
197 while (true)
198 {
199 aPollRequest poolreq = m_queue.Dequeue();
127 200
128 public void RegisterCaps(UUID agentID, Caps caps) 201 poolreq.thepoll.Process(poolreq);
202 }
203 }
204
205 // 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.
206 public void ThrottleUpdate(ScenePresence p)
207 {
208 UUID user = p.UUID;
209 int imagethrottle = p.ControllingClient.GetAgentThrottleSilent((int)ThrottleOutPacketType.Asset);
210 PollServiceMeshEventArgs args;
211 if (m_pollservices.TryGetValue(user, out args))
212 {
213 args.UpdateThrottle(imagethrottle, p);
214 }
215 }
216
217 private class PollServiceMeshEventArgs : PollServiceEventArgs
129 { 218 {
130 UUID capID = UUID.Random(); 219 private List<Hashtable> requests =
131 bool getMeshRegistered = false; 220 new List<Hashtable>();
221 private Dictionary<UUID, aPollResponse> responses =
222 new Dictionary<UUID, aPollResponse>();
132 223
133 if (m_URL == string.Empty) 224 private Scene m_scene;
225 private MeshCapsDataThrottler m_throttler;
226 public PollServiceMeshEventArgs(string uri, UUID pId, Scene scene) :
227 base(null, uri, null, null, null, pId, int.MaxValue)
134 { 228 {
229 m_scene = scene;
230 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId);
231 // x is request id, y is userid
232 HasEvents = (x, y) =>
233 {
234 lock (responses)
235 {
236 bool ret = m_throttler.hasEvents(x, responses);
237 m_throttler.ProcessTime();
238 return ret;
239
240 }
241 };
242 GetEvents = (x, y) =>
243 {
244 lock (responses)
245 {
246 try
247 {
248 return responses[x].response;
249 }
250 finally
251 {
252 m_throttler.ProcessTime();
253 responses.Remove(x);
254 }
255 }
256 };
257 // x is request id, y is request data hashtable
258 Request = (x, y) =>
259 {
260 aPollRequest reqinfo = new aPollRequest();
261 reqinfo.thepoll = this;
262 reqinfo.reqID = x;
263 reqinfo.request = y;
264
265 m_queue.Enqueue(reqinfo);
266 };
267
268 // this should never happen except possible on shutdown
269 NoEvents = (x, y) =>
270 {
271 /*
272 lock (requests)
273 {
274 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
275 requests.Remove(request);
276 }
277 */
278 Hashtable response = new Hashtable();
279
280 response["int_response_code"] = 500;
281 response["str_response_string"] = "Script timeout";
282 response["content_type"] = "text/plain";
283 response["keepalive"] = false;
284 response["reusecontext"] = false;
285
286 return response;
287 };
288 }
289
290 public void Process(aPollRequest requestinfo)
291 {
292 Hashtable response;
293
294 UUID requestID = requestinfo.reqID;
295
296 // If the avatar is gone, don't bother to get the texture
297 if (m_scene.GetScenePresence(Id) == null)
298 {
299 response = new Hashtable();
300
301 response["int_response_code"] = 500;
302 response["str_response_string"] = "Script timeout";
303 response["content_type"] = "text/plain";
304 response["keepalive"] = false;
305 response["reusecontext"] = false;
306
307 lock (responses)
308 responses[requestID] = new aPollResponse() { bytes = 0, response = response, lod = 0 };
309
310 return;
311 }
312
313 response = m_getMeshHandler.Handle(requestinfo.request);
314 lock (responses)
315 {
316 responses[requestID] = new aPollResponse()
317 {
318 bytes = (int)response["int_bytes"],
319 lod = (int)response["int_lod"],
320 response = response
321 };
135 322
323 }
324 m_throttler.ProcessTime();
136 } 325 }
137 else if (m_URL == "localhost") 326
327 internal void UpdateThrottle(int pimagethrottle, ScenePresence p)
138 { 328 {
139 getMeshRegistered = true; 329 m_throttler.UpdateThrottle(pimagethrottle, p);
140 caps.RegisterHandler( 330 }
141 "GetMesh", 331 }
142 new GetMeshHandler("/CAPS/" + capID + "/", m_AssetService, "GetMesh", agentID.ToString(), m_RedirectURL)); 332
333 public void RegisterCaps(UUID agentID, Caps caps)
334 {
335// UUID capID = UUID.Random();
336 if (m_URL == "localhost")
337 {
338 string capUrl = "/CAPS/" + UUID.Random() + "/";
339
340 // Register this as a poll service
341 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(capUrl, agentID, m_scene);
342
343 args.Type = PollServiceEventArgs.EventType.Mesh;
344 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
345
346 string hostName = m_scene.RegionInfo.ExternalHostName;
347 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
348 string protocol = "http";
349
350 if (MainServer.Instance.UseSSL)
351 {
352 hostName = MainServer.Instance.SSLCommonName;
353 port = MainServer.Instance.SSLPort;
354 protocol = "https";
355 }
356 caps.RegisterHandler("GetMesh", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
357 m_pollservices[agentID] = args;
358 m_capsDict[agentID] = capUrl;
143 } 359 }
144 else 360 else
145 { 361 {
146 caps.RegisterHandler("GetMesh", m_URL); 362 caps.RegisterHandler("GetMesh", m_URL);
147 } 363 }
364 }
365
366 private void DeregisterCaps(UUID agentID, Caps caps)
367 {
368 string capUrl;
369 PollServiceMeshEventArgs args;
370 if (m_capsDict.TryGetValue(agentID, out capUrl))
371 {
372 MainServer.Instance.RemoveHTTPHandler("", capUrl);
373 m_capsDict.Remove(agentID);
374 }
375 if (m_pollservices.TryGetValue(agentID, out args))
376 {
377 m_pollservices.Remove(agentID);
378 }
379 }
380
381 internal sealed class MeshCapsDataThrottler
382 {
383
384 private volatile int currenttime = 0;
385 private volatile int lastTimeElapsed = 0;
386 private volatile int BytesSent = 0;
387 private int Lod3 = 0;
388 private int Lod2 = 0;
389 private int Lod1 = 0;
390 private int UserSetThrottle = 0;
391 private int UDPSetThrottle = 0;
392 private int CapSetThrottle = 0;
393 private float CapThrottleDistributon = 0.30f;
394 private readonly Scene m_scene;
395 private ThrottleOutPacketType Throttle;
396 private readonly UUID User;
397
398 public MeshCapsDataThrottler(int pBytes, int max, int min, Scene pScene, UUID puser)
399 {
400 ThrottleBytes = pBytes;
401 lastTimeElapsed = Util.EnvironmentTickCount();
402 Throttle = ThrottleOutPacketType.Asset;
403 m_scene = pScene;
404 User = puser;
405 }
406
407
408 public bool hasEvents(UUID key, Dictionary<UUID, aPollResponse> responses)
409 {
410 const float ThirtyPercent = 0.30f;
411 const float FivePercent = 0.05f;
412 PassTime();
413 // Note, this is called IN LOCK
414 bool haskey = responses.ContainsKey(key);
415
416 if (responses.Count > 2)
417 {
418 SplitThrottle(ThirtyPercent);
419 }
420 else
421 {
422 SplitThrottle(FivePercent);
423 }
148 424
149 if(m_URL2 == string.Empty) 425 if (!haskey)
426 {
427 return false;
428 }
429 aPollResponse response;
430 if (responses.TryGetValue(key, out response))
431 {
432 float LOD3Over = (((ThrottleBytes*CapThrottleDistributon)%50000) + 1);
433 float LOD2Over = (((ThrottleBytes*CapThrottleDistributon)%10000) + 1);
434 // Normal
435 if (BytesSent + response.bytes <= ThrottleBytes)
436 {
437 BytesSent += response.bytes;
438
439 return true;
440 }
441 // Lod3 Over Throttle protection to keep things processing even when the throttle bandwidth is set too little.
442 else if (response.bytes > ThrottleBytes && Lod3 <= ((LOD3Over < 1)? 1: LOD3Over) )
443 {
444 Interlocked.Increment(ref Lod3);
445 BytesSent += response.bytes;
446
447 return true;
448 }
449 // Lod2 Over Throttle protection to keep things processing even when the throttle bandwidth is set too little.
450 else if (response.bytes > ThrottleBytes && Lod2 <= ((LOD2Over < 1) ? 1 : LOD2Over))
451 {
452 Interlocked.Increment(ref Lod2);
453 BytesSent += response.bytes;
454
455 return true;
456 }
457 else
458 {
459 return false;
460 }
461 }
462
463 return haskey;
464 }
465 public void SubtractBytes(int bytes,int lod)
466 {
467 BytesSent -= bytes;
468 }
469 private void SplitThrottle(float percentMultiplier)
150 { 470 {
151 471
472 if (CapThrottleDistributon != percentMultiplier) // don't switch it if it's already set at the % multipler
473 {
474 CapThrottleDistributon = percentMultiplier;
475 ScenePresence p;
476 if (m_scene.TryGetScenePresence(User, out p)) // If we don't get a user they're not here anymore.
477 {
478// AlterThrottle(UserSetThrottle, p);
479 UpdateThrottle(UserSetThrottle, p);
480 }
481 }
152 } 482 }
153 else if (m_URL2 == "localhost") 483
484 public void ProcessTime()
154 { 485 {
155 if (!getMeshRegistered) 486 PassTime();
487 }
488
489
490 private void PassTime()
491 {
492 currenttime = Util.EnvironmentTickCount();
493 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
494 //processTimeBasedActions(responses);
495 if (currenttime - timeElapsed >= 1000)
156 { 496 {
157 caps.RegisterHandler( 497 lastTimeElapsed = Util.EnvironmentTickCount();
158 "GetMesh2", 498 BytesSent -= ThrottleBytes;
159 new GetMeshHandler("/CAPS/" + capID + "/", m_AssetService, "GetMesh2", agentID.ToString(), m_RedirectURL2)); 499 if (BytesSent < 0) BytesSent = 0;
500 if (BytesSent < ThrottleBytes)
501 {
502 Lod3 = 0;
503 Lod2 = 0;
504 Lod1 = 0;
505 }
160 } 506 }
161 } 507 }
162 else 508 private void AlterThrottle(int setting, ScenePresence p)
509 {
510 p.ControllingClient.SetAgentThrottleSilent((int)Throttle,setting);
511 }
512
513 public int ThrottleBytes
163 { 514 {
164 caps.RegisterHandler("GetMesh2", m_URL2); 515 get { return CapSetThrottle; }
516 set { CapSetThrottle = value; }
517 }
518
519 internal void UpdateThrottle(int pimagethrottle, ScenePresence p)
520 {
521 // Client set throttle !
522 UserSetThrottle = pimagethrottle;
523 CapSetThrottle = (int)(pimagethrottle*CapThrottleDistributon);
524// UDPSetThrottle = (int) (pimagethrottle*(100 - CapThrottleDistributon));
525
526 float udp = 1.0f - CapThrottleDistributon;
527 if(udp < 0.7f)
528 udp = 0.7f;
529 UDPSetThrottle = (int) ((float)pimagethrottle * udp);
530 if (CapSetThrottle < 4068)
531 CapSetThrottle = 4068; // at least two discovery mesh
532 p.ControllingClient.SetAgentThrottleSilent((int) Throttle, UDPSetThrottle);
533 ProcessTime();
534
165 } 535 }
166 } 536 }
167 537
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index bb932f2..12cfa5d 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,27 +50,54 @@ 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>();
84
64 85
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;
67 88
68 private string m_URL; 89 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>();
90
69 91
70 #region ISharedRegionModule Members 92 #region ISharedRegionModule Members
71 93
72 public void Initialise(IConfigSource source) 94 public void Initialise(IConfigSource source)
73 { 95 {
74 IConfig config = source.Configs["ClientStack.LindenCaps"]; 96 IConfig config = source.Configs["ClientStack.LindenCaps"];
97
75 if (config == null) 98 if (config == null)
76 return; 99 return;
77 100/*
78 m_URL = config.GetString("Cap_GetTexture", string.Empty); 101 m_URL = config.GetString("Cap_GetTexture", string.Empty);
79 // Cap doesn't exist 102 // Cap doesn't exist
80 if (m_URL != string.Empty) 103 if (m_URL != string.Empty)
@@ -82,32 +105,98 @@ namespace OpenSim.Region.ClientStack.Linden
82 m_Enabled = true; 105 m_Enabled = true;
83 m_RedirectURL = config.GetString("GetTextureRedirectURL"); 106 m_RedirectURL = config.GetString("GetTextureRedirectURL");
84 } 107 }
108*/
109 m_Url = config.GetString("Cap_GetTexture", "localhost");
85 } 110 }
86 111
87 public void AddRegion(Scene s) 112 public void AddRegion(Scene s)
88 { 113 {
89 if (!m_Enabled)
90 return;
91
92 m_scene = s; 114 m_scene = s;
115 m_assetService = s.AssetService;
93 } 116 }
94 117
95 public void RemoveRegion(Scene s) 118 public void RemoveRegion(Scene s)
96 { 119 {
97 if (!m_Enabled)
98 return;
99
100 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 120 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
121 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
122 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
101 m_scene = null; 123 m_scene = null;
102 } 124 }
103 125
104 public void RegionLoaded(Scene s) 126 public void RegionLoaded(Scene s)
105 { 127 {
106 if (!m_Enabled) 128 // We'll reuse the same handler for all requests.
107 return; 129 m_getTextureHandler = new GetTextureHandler(m_assetService);
108 130
109 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
110 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 131 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
132 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
133 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
134
135 if (m_workerThreads == null)
136 {
137 m_workerThreads = new Thread[2];
138
139 for (uint i = 0; i < 2; i++)
140 {
141 m_workerThreads[i] = WorkManager.StartThread(DoTextureRequests,
142 String.Format("TextureWorkerThread{0}", i),
143 ThreadPriority.Normal,
144 false,
145 false,
146 null,
147 int.MaxValue);
148 }
149 }
150 }
151 private int ExtractImageThrottle(byte[] pthrottles)
152 {
153
154 byte[] adjData;
155 int pos = 0;
156
157 if (!BitConverter.IsLittleEndian)
158 {
159 byte[] newData = new byte[7 * 4];
160 Buffer.BlockCopy(pthrottles, 0, newData, 0, 7 * 4);
161
162 for (int i = 0; i < 7; i++)
163 Array.Reverse(newData, i * 4, 4);
164
165 adjData = newData;
166 }
167 else
168 {
169 adjData = pthrottles;
170 }
171
172 // 0.125f converts from bits to bytes
173 //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
174 //pos += 4;
175 // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
176 //pos += 4;
177 // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
178 // pos += 4;
179 // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
180 // pos += 4;
181 // int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
182 // pos += 4;
183 pos = pos + 20;
184 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); //pos += 4;
185 //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
186 return texture;
187 }
188
189 // 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.
190 public void ThrottleUpdate(ScenePresence p)
191 {
192 byte[] throttles = p.ControllingClient.GetThrottlesPacked(1);
193 UUID user = p.UUID;
194 int imagethrottle = ExtractImageThrottle(throttles);
195 PollServiceTextureEventArgs args;
196 if (m_pollservices.TryGetValue(user,out args))
197 {
198 args.UpdateThrottle(imagethrottle);
199 }
111 } 200 }
112 201
113 public void PostInitialise() 202 public void PostInitialise()
@@ -125,28 +214,294 @@ namespace OpenSim.Region.ClientStack.Linden
125 214
126 #endregion 215 #endregion
127 216
128 public void RegisterCaps(UUID agentID, Caps caps) 217 ~GetTextureModule()
218 {
219 foreach (Thread t in m_workerThreads)
220 Watchdog.AbortThread(t.ManagedThreadId);
221
222 }
223
224 private class PollServiceTextureEventArgs : PollServiceEventArgs
129 { 225 {
130 UUID capID = UUID.Random(); 226 private List<Hashtable> requests =
227 new List<Hashtable>();
228 private Dictionary<UUID, aPollResponse> responses =
229 new Dictionary<UUID, aPollResponse>();
131 230
132 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); 231 private Scene m_scene;
133 if (m_URL == "localhost") 232 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000);
233 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
234 base(null, "", null, null, null, pId, int.MaxValue)
134 { 235 {
135// m_log.DebugFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 236 m_scene = scene;
136 caps.RegisterHandler( 237 // x is request id, y is userid
137 "GetTexture", 238 HasEvents = (x, y) =>
138 new GetTextureHandler("/CAPS/" + capID + "/", m_assetService, "GetTexture", agentID.ToString(), m_RedirectURL)); 239 {
240 lock (responses)
241 {
242 bool ret = m_throttler.hasEvents(x, responses);
243 m_throttler.ProcessTime();
244 return ret;
245
246 }
247 };
248 GetEvents = (x, y) =>
249 {
250 lock (responses)
251 {
252 try
253 {
254 return responses[x].response;
255 }
256 finally
257 {
258 responses.Remove(x);
259 }
260 }
261 };
262 // x is request id, y is request data hashtable
263 Request = (x, y) =>
264 {
265 aPollRequest reqinfo = new aPollRequest();
266 reqinfo.thepoll = this;
267 reqinfo.reqID = x;
268 reqinfo.request = y;
269 reqinfo.send503 = false;
270
271 lock (responses)
272 {
273 if (responses.Count > 0)
274 {
275 if (m_queue.Count >= 4)
276 {
277 // Never allow more than 4 fetches to wait
278 reqinfo.send503 = true;
279 }
280 }
281 }
282 m_queue.Enqueue(reqinfo);
283 };
284
285 // this should never happen except possible on shutdown
286 NoEvents = (x, y) =>
287 {
288/*
289 lock (requests)
290 {
291 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
292 requests.Remove(request);
293 }
294*/
295 Hashtable response = new Hashtable();
296
297 response["int_response_code"] = 500;
298 response["str_response_string"] = "Script timeout";
299 response["content_type"] = "text/plain";
300 response["keepalive"] = false;
301 response["reusecontext"] = false;
302
303 return response;
304 };
305 }
306
307 public void Process(aPollRequest requestinfo)
308 {
309 Hashtable response;
310
311 UUID requestID = requestinfo.reqID;
312
313 if (requestinfo.send503)
314 {
315 response = new Hashtable();
316
317
318 response["int_response_code"] = 503;
319 response["str_response_string"] = "Throttled";
320 response["content_type"] = "text/plain";
321 response["keepalive"] = false;
322 response["reusecontext"] = false;
323
324 Hashtable headers = new Hashtable();
325 headers["Retry-After"] = 30;
326 response["headers"] = headers;
327
328 lock (responses)
329 responses[requestID] = new aPollResponse() {bytes = 0, response = response};
330
331 return;
332 }
333
334 // If the avatar is gone, don't bother to get the texture
335 if (m_scene.GetScenePresence(Id) == null)
336 {
337 response = new Hashtable();
338
339 response["int_response_code"] = 500;
340 response["str_response_string"] = "Script timeout";
341 response["content_type"] = "text/plain";
342 response["keepalive"] = false;
343 response["reusecontext"] = false;
344
345 lock (responses)
346 responses[requestID] = new aPollResponse() {bytes = 0, response = response};
347
348 return;
349 }
350
351 response = m_getTextureHandler.Handle(requestinfo.request);
352 lock (responses)
353 {
354 responses[requestID] = new aPollResponse()
355 {
356 bytes = (int) response["int_bytes"],
357 response = response
358 };
359
360 }
361 m_throttler.ProcessTime();
362 }
363
364 internal void UpdateThrottle(int pimagethrottle)
365 {
366 m_throttler.ThrottleBytes = pimagethrottle;
367 }
368 }
369
370 private void RegisterCaps(UUID agentID, Caps caps)
371 {
372 if (m_Url == "localhost")
373 {
374 string capUrl = "/CAPS/" + UUID.Random() + "/";
375
376 // Register this as a poll service
377 PollServiceTextureEventArgs args = new PollServiceTextureEventArgs(agentID, m_scene);
378
379 args.Type = PollServiceEventArgs.EventType.Texture;
380 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
381
382 string hostName = m_scene.RegionInfo.ExternalHostName;
383 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
384 string protocol = "http";
385
386 if (MainServer.Instance.UseSSL)
387 {
388 hostName = MainServer.Instance.SSLCommonName;
389 port = MainServer.Instance.SSLPort;
390 protocol = "https";
391 }
392 m_pollservices[agentID] = args;
393 m_capsDict[agentID] = capUrl;
139 } 394 }
140 else 395 else
141 { 396 {
142// m_log.DebugFormat("[GETTEXTURE]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName);
143 IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>(); 397 IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>();
144 if (handler != null) 398 if (handler != null)
145 handler.RegisterExternalUserCapsHandler(agentID,caps,"GetTexture", m_URL); 399 handler.RegisterExternalUserCapsHandler(agentID, caps, "GetTexture", m_Url);
146 else 400 else
147 caps.RegisterHandler("GetTexture", m_URL); 401 caps.RegisterHandler("GetTexture", m_Url);
402 }
403 }
404
405 private void DeregisterCaps(UUID agentID, Caps caps)
406 {
407 PollServiceTextureEventArgs args;
408
409 MainServer.Instance.RemoveHTTPHandler("", m_Url);
410 m_capsDict.Remove(agentID);
411
412 if (m_pollservices.TryGetValue(agentID, out args))
413 {
414 m_pollservices.Remove(agentID);
148 } 415 }
149 } 416 }
150 417
418 private void DoTextureRequests()
419 {
420 while (true)
421 {
422 aPollRequest poolreq = m_queue.Dequeue();
423
424 poolreq.thepoll.Process(poolreq);
425 }
426 }
427 internal sealed class CapsDataThrottler
428 {
429
430 private volatile int currenttime = 0;
431 private volatile int lastTimeElapsed = 0;
432 private volatile int BytesSent = 0;
433 private int oversizedImages = 0;
434 public CapsDataThrottler(int pBytes, int max, int min)
435 {
436 ThrottleBytes = pBytes;
437 lastTimeElapsed = Util.EnvironmentTickCount();
438 }
439 public bool hasEvents(UUID key, Dictionary<UUID, GetTextureModule.aPollResponse> responses)
440 {
441 PassTime();
442 // Note, this is called IN LOCK
443 bool haskey = responses.ContainsKey(key);
444 if (!haskey)
445 {
446 return false;
447 }
448 GetTextureModule.aPollResponse response;
449 if (responses.TryGetValue(key, out response))
450 {
451 // This is any error response
452 if (response.bytes == 0)
453 return true;
454
455 // Normal
456 if (BytesSent + response.bytes <= ThrottleBytes)
457 {
458 BytesSent += response.bytes;
459 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false };
460 //m_actions.Add(timeBasedAction);
461 return true;
462 }
463 // Big textures
464 else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes % 50000) + 1))
465 {
466 Interlocked.Increment(ref oversizedImages);
467 BytesSent += response.bytes;
468 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false };
469 //m_actions.Add(timeBasedAction);
470 return true;
471 }
472 else
473 {
474 return false;
475 }
476 }
477
478 return haskey;
479 }
480
481 public void ProcessTime()
482 {
483 PassTime();
484 }
485
486 private void PassTime()
487 {
488 currenttime = Util.EnvironmentTickCount();
489 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
490 //processTimeBasedActions(responses);
491 if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000)
492 {
493 lastTimeElapsed = Util.EnvironmentTickCount();
494 BytesSent -= ThrottleBytes;
495 if (BytesSent < 0) BytesSent = 0;
496 if (BytesSent < ThrottleBytes)
497 {
498 oversizedImages = 0;
499 }
500 }
501 }
502 public int ThrottleBytes;
503 }
151 } 504 }
505
506
152} 507}
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..d07f66e 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
@@ -155,6 +155,7 @@ 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;
159 160
160 OSDMap typesMap = new OSDMap(); 161 OSDMap typesMap = new OSDMap();
@@ -173,6 +174,10 @@ namespace OpenSim.Region.ClientStack.Linden
173 else 174 else
174 extrasMap = new OSDMap(); 175 extrasMap = new OSDMap();
175 176
177 extrasMap["AvatarSkeleton"] = true;
178 extrasMap["AnimationSet"] = true;
179
180 // TODO: Take these out of here into their respective modules, like map-server-url
176 if (m_SearchURL != string.Empty) 181 if (m_SearchURL != string.Empty)
177 extrasMap["search-server-url"] = m_SearchURL; 182 extrasMap["search-server-url"] = m_SearchURL;
178 if (!string.IsNullOrEmpty(m_DestinationGuideURL)) 183 if (!string.IsNullOrEmpty(m_DestinationGuideURL))
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs
index dd4a691..db16ccb 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs
@@ -52,6 +52,7 @@ using OSDMap = OpenMetaverse.StructuredData.OSDMap;
52 52
53namespace OpenSim.Region.ClientStack.Linden.Caps.Tests 53namespace OpenSim.Region.ClientStack.Linden.Caps.Tests
54{ 54{
55 /*
55 [TestFixture] 56 [TestFixture]
56 public class WebFetchInvDescModuleTests : OpenSimTestCase 57 public class WebFetchInvDescModuleTests : OpenSimTestCase
57 { 58 {
@@ -156,4 +157,5 @@ namespace OpenSim.Region.ClientStack.Linden.Caps.Tests
156 Assert.That((int)folderOsd["descendents"], Is.EqualTo(16)); 157 Assert.That((int)folderOsd["descendents"], Is.EqualTo(16));
157 } 158 }
158 } 159 }
160 */
159} \ No newline at end of file 161} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
index 8cdebcd..8fd8d1f 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
@@ -66,14 +66,19 @@ namespace OpenSim.Region.ClientStack.Linden
66 private bool m_persistBakedTextures; 66 private bool m_persistBakedTextures;
67 67
68 private IBakedTextureModule m_BakedTextureModule; 68 private IBakedTextureModule m_BakedTextureModule;
69 private string m_URL;
69 70
70 public void Initialise(IConfigSource source) 71 public void Initialise(IConfigSource source)
71 { 72 {
73 IConfig config = source.Configs["ClientStack.LindenCaps"];
74 if (config == null)
75 return;
76
77 m_URL = config.GetString("Cap_UploadBakedTexture", string.Empty);
78
72 IConfig appearanceConfig = source.Configs["Appearance"]; 79 IConfig appearanceConfig = source.Configs["Appearance"];
73 if (appearanceConfig != null) 80 if (appearanceConfig != null)
74 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); 81 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
75
76
77 } 82 }
78 83
79 public void AddRegion(Scene s) 84 public void AddRegion(Scene s)
@@ -89,9 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden
89 s.EventManager.OnRemovePresence -= DeRegisterPresence; 94 s.EventManager.OnRemovePresence -= DeRegisterPresence;
90 m_BakedTextureModule = null; 95 m_BakedTextureModule = null;
91 m_scene = null; 96 m_scene = null;
92 } 97 }
93
94
95 98
96 public void RegionLoaded(Scene s) 99 public void RegionLoaded(Scene s)
97 { 100 {
@@ -103,44 +106,52 @@ namespace OpenSim.Region.ClientStack.Linden
103 106
104 private void DeRegisterPresence(UUID agentId) 107 private void DeRegisterPresence(UUID agentId)
105 { 108 {
106 ScenePresence presence = null;
107 if (m_scene.TryGetScenePresence(agentId, out presence))
108 {
109 presence.ControllingClient.OnSetAppearance -= CaptureAppearanceSettings;
110 }
111
112 } 109 }
113 110
114 private void RegisterNewPresence(ScenePresence presence) 111 private void RegisterNewPresence(ScenePresence presence)
115 { 112 {
116 presence.ControllingClient.OnSetAppearance += CaptureAppearanceSettings; 113// presence.ControllingClient.OnSetAppearance += CaptureAppearanceSettings;
117
118 } 114 }
119 115
120 private void CaptureAppearanceSettings(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems) 116/* not in use. work done in AvatarFactoryModule ValidateBakedTextureCache() and UpdateBakedTextureCache()
121 { 117 private void CaptureAppearanceSettings(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems)
122 int maxCacheitemsLoop = cacheItems.Length;
123 if (maxCacheitemsLoop > AvatarWearable.MAX_WEARABLES)
124 {
125 maxCacheitemsLoop = AvatarWearable.MAX_WEARABLES;
126 m_log.WarnFormat("[CACHEDBAKES]: Too Many Cache items Provided {0}, the max is {1}. Truncating!", cacheItems.Length, AvatarWearable.MAX_WEARABLES);
127 }
128
129 m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
130 if (cacheItems.Length > 0)
131 {
132// m_log.Debug("[Cacheitems]: " + cacheItems.Length);
133// for (int iter = 0; iter < maxCacheitemsLoop; iter++)
134// {
135// m_log.Debug("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" +
136// cacheItems[iter].TextureID);
137// }
138
139 ScenePresence p = null;
140 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out p))
141 { 118 {
119 // if cacheItems.Length > 0 viewer is giving us current textures information.
120 // baked ones should had been uploaded and in assets cache as local itens
121
122
123 if (cacheItems.Length == 0)
124 return; // no textures information, nothing to do
125
126 ScenePresence p = null;
127 if (!m_scene.TryGetScenePresence(remoteClient.AgentId, out p))
128 return; // what are we doing if there is no presence to cache for?
129
130 if (p.IsDeleted)
131 return; // does this really work?
132
133 int maxCacheitemsLoop = cacheItems.Length;
134 if (maxCacheitemsLoop > 20)
135 {
136 maxCacheitemsLoop = AvatarWearable.MAX_WEARABLES;
137 m_log.WarnFormat("[CACHEDBAKES]: Too Many Cache items Provided {0}, the max is {1}. Truncating!", cacheItems.Length, AvatarWearable.MAX_WEARABLES);
138 }
139
140 m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
141
142
143 // some nice debug
144 m_log.Debug("[Cacheitems]: " + cacheItems.Length);
145 for (int iter = 0; iter < maxCacheitemsLoop; iter++)
146 {
147 m_log.Debug("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" +
148 cacheItems[iter].TextureID);
149 }
150
151 // p.Appearance.WearableCacheItems is in memory primary cashID to textures mapper
142 152
143 WearableCacheItem[] existingitems = p.Appearance.WearableCacheItems; 153 WearableCacheItem[] existingitems = p.Appearance.WearableCacheItems;
154
144 if (existingitems == null) 155 if (existingitems == null)
145 { 156 {
146 if (m_BakedTextureModule != null) 157 if (m_BakedTextureModule != null)
@@ -154,38 +165,22 @@ namespace OpenSim.Region.ClientStack.Linden
154 p.Appearance.WearableCacheItems = savedcache; 165 p.Appearance.WearableCacheItems = savedcache;
155 p.Appearance.WearableCacheItemsDirty = false; 166 p.Appearance.WearableCacheItemsDirty = false;
156 } 167 }
157
158 }
159 /*
160 * The following Catch types DO NOT WORK with m_BakedTextureModule.Get
161 * it jumps to the General Packet Exception Handler if you don't catch Exception!
162 *
163 catch (System.Net.Sockets.SocketException)
164 {
165 cacheItems = null;
166 } 168 }
167 catch (WebException) 169
168 {
169 cacheItems = null;
170 }
171 catch (InvalidOperationException)
172 {
173 cacheItems = null;
174 } */
175 catch (Exception) 170 catch (Exception)
176 { 171 {
177 // The service logs a sufficient error message. 172 // The service logs a sufficient error message.
178 } 173 }
179 174
180 175
181 if (savedcache != null) 176 if (savedcache != null)
182 existingitems = savedcache; 177 existingitems = savedcache;
183 } 178 }
184 } 179 }
180
185 // Existing items null means it's a fully new appearance 181 // Existing items null means it's a fully new appearance
186 if (existingitems == null) 182 if (existingitems == null)
187 { 183 {
188
189 for (int i = 0; i < maxCacheitemsLoop; i++) 184 for (int i = 0; i < maxCacheitemsLoop; i++)
190 { 185 {
191 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex) 186 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
@@ -198,7 +193,7 @@ namespace OpenSim.Region.ClientStack.Linden
198 AppearanceManager.DEFAULT_AVATAR_TEXTURE; 193 AppearanceManager.DEFAULT_AVATAR_TEXTURE;
199 continue; 194 continue;
200 } 195 }
201 cacheItems[i].TextureID =face.TextureID; 196 cacheItems[i].TextureID = face.TextureID;
202 if (m_scene.AssetService != null) 197 if (m_scene.AssetService != null)
203 cacheItems[i].TextureAsset = 198 cacheItems[i].TextureAsset =
204 m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString()); 199 m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString());
@@ -207,15 +202,10 @@ namespace OpenSim.Region.ClientStack.Linden
207 { 202 {
208 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); 203 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);
209 } 204 }
210
211
212 } 205 }
213 } 206 }
214 else 207 else
215 208 {
216
217 {
218 // for each uploaded baked texture
219 for (int i = 0; i < maxCacheitemsLoop; i++) 209 for (int i = 0; i < maxCacheitemsLoop; i++)
220 { 210 {
221 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex) 211 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
@@ -246,23 +236,24 @@ namespace OpenSim.Region.ClientStack.Linden
246 } 236 }
247 } 237 }
248 } 238 }
249
250
251
252 p.Appearance.WearableCacheItems = cacheItems; 239 p.Appearance.WearableCacheItems = cacheItems;
253
254
255 240
256 if (m_BakedTextureModule != null) 241 if (m_BakedTextureModule != null)
257 { 242 {
258 m_BakedTextureModule.Store(remoteClient.AgentId, cacheItems); 243 m_BakedTextureModule.Store(remoteClient.AgentId, cacheItems);
259 p.Appearance.WearableCacheItemsDirty = true; 244 p.Appearance.WearableCacheItemsDirty = true;
260 245
261 } 246 }
262 } 247 else
263 } 248 p.Appearance.WearableCacheItemsDirty = false;
264 }
265 249
250 for (int iter = 0; iter < maxCacheitemsLoop; iter++)
251 {
252 m_log.Debug("[CacheitemsLeaving] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" +
253 cacheItems[iter].TextureID);
254 }
255 }
256 */
266 public void PostInitialise() 257 public void PostInitialise()
267 { 258 {
268 } 259 }
@@ -280,23 +271,26 @@ namespace OpenSim.Region.ClientStack.Linden
280 271
281 public void RegisterCaps(UUID agentID, Caps caps) 272 public void RegisterCaps(UUID agentID, Caps caps)
282 { 273 {
283 UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler( 274 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture));
284 caps, m_scene.AssetService, m_persistBakedTextures); 275 if (m_URL == "localhost")
276 {
277 UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler(
278 caps, m_scene.AssetService, m_persistBakedTextures);
285 279
286 280 caps.RegisterHandler(
287
288 caps.RegisterHandler(
289 "UploadBakedTexture",
290 new RestStreamHandler(
291 "POST",
292 "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
293 avatarhandler.UploadBakedTexture,
294 "UploadBakedTexture", 281 "UploadBakedTexture",
295 agentID.ToString())); 282 new RestStreamHandler(
296 283 "POST",
297 284 "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
298 285 avatarhandler.UploadBakedTexture,
299 286 "UploadBakedTexture",
287 agentID.ToString()));
288
289 }
290 else
291 {
292 caps.RegisterHandler("UploadBakedTexture", m_URL);
293 }
300 } 294 }
301 } 295 }
302} 296}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 025ffea..1a19c1b 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,7 @@ namespace OpenSim.Region.ClientStack.Linden
63 public List<UUID> folders; 64 public List<UUID> folders;
64 } 65 }
65 66
66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 67 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
67 68
68 /// <summary> 69 /// <summary>
69 /// Control whether requests will be processed asynchronously. 70 /// Control whether requests will be processed asynchronously.
@@ -92,7 +93,7 @@ namespace OpenSim.Region.ClientStack.Linden
92 private bool m_Enabled; 93 private bool m_Enabled;
93 94
94 private string m_fetchInventoryDescendents2Url; 95 private string m_fetchInventoryDescendents2Url;
95 private string m_webFetchInventoryDescendentsUrl; 96// private string m_webFetchInventoryDescendentsUrl;
96 97
97 private static FetchInvDescHandler m_webFetchHandler; 98 private static FetchInvDescHandler m_webFetchHandler;
98 99
@@ -117,9 +118,10 @@ namespace OpenSim.Region.ClientStack.Linden
117 return; 118 return;
118 119
119 m_fetchInventoryDescendents2Url = config.GetString("Cap_FetchInventoryDescendents2", string.Empty); 120 m_fetchInventoryDescendents2Url = config.GetString("Cap_FetchInventoryDescendents2", string.Empty);
120 m_webFetchInventoryDescendentsUrl = config.GetString("Cap_WebFetchInventoryDescendents", string.Empty); 121// m_webFetchInventoryDescendentsUrl = config.GetString("Cap_WebFetchInventoryDescendents", string.Empty);
121 122
122 if (m_fetchInventoryDescendents2Url != string.Empty || m_webFetchInventoryDescendentsUrl != string.Empty) 123// if (m_fetchInventoryDescendents2Url != string.Empty || m_webFetchInventoryDescendentsUrl != string.Empty)
124 if (m_fetchInventoryDescendents2Url != string.Empty)
123 { 125 {
124 m_Enabled = true; 126 m_Enabled = true;
125 } 127 }
@@ -312,7 +314,8 @@ namespace OpenSim.Region.ClientStack.Linden
312 { 314 {
313 if (!reqinfo.folders.Contains(folderID)) 315 if (!reqinfo.folders.Contains(folderID))
314 { 316 {
315 //TODO: Port COF handling from Avination 317 if (sp.COF != UUID.Zero && sp.COF == folderID)
318 highPriority = true;
316 reqinfo.folders.Add(folderID); 319 reqinfo.folders.Add(folderID);
317 } 320 }
318 } 321 }