aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs923
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs671
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs12
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs29
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs228
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs16
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs296
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs7
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs200
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs1206
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs65
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs219
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs4
14 files changed, 2787 insertions, 1092 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index cc69645..f509d94 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;
@@ -53,14 +54,16 @@ using OSDMap = OpenMetaverse.StructuredData.OSDMap;
53namespace OpenSim.Region.ClientStack.Linden 54namespace OpenSim.Region.ClientStack.Linden
54{ 55{
55 public delegate void UpLoadedAsset( 56 public delegate void UpLoadedAsset(
56 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, 57 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
57 byte[] data, string inventoryType, string assetType); 58 byte[] data, string inventoryType, string assetType,
59 int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
60 bool IsAtestUpload, ref string error);
58 61
59 public delegate UUID UpdateItem(UUID itemID, byte[] data); 62 public delegate UUID UpdateItem(UUID itemID, byte[] data);
60 63
61 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); 64 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors);
62 65
63 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item); 66 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item, uint cost);
64 67
65 public delegate void NewAsset(AssetBase asset); 68 public delegate void NewAsset(AssetBase asset);
66 69
@@ -86,6 +89,7 @@ namespace OpenSim.Region.ClientStack.Linden
86 89
87 private Scene m_Scene; 90 private Scene m_Scene;
88 private Caps m_HostCapsObj; 91 private Caps m_HostCapsObj;
92 private ModelCost m_ModelCost;
89 93
90 private static readonly string m_requestPath = "0000/"; 94 private static readonly string m_requestPath = "0000/";
91 // private static readonly string m_mapLayerPath = "0001/"; 95 // private static readonly string m_mapLayerPath = "0001/";
@@ -96,7 +100,10 @@ namespace OpenSim.Region.ClientStack.Linden
96 // private static readonly string m_fetchInventoryPath = "0006/"; 100 // private static readonly string m_fetchInventoryPath = "0006/";
97 private static readonly string m_copyFromNotecardPath = "0007/"; 101 private static readonly string m_copyFromNotecardPath = "0007/";
98 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. 102 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule.
99 103 private static readonly string m_getObjectPhysicsDataPath = "0101/";
104 private static readonly string m_getObjectCostPath = "0102/";
105 private static readonly string m_ResourceCostSelectedPath = "0103/";
106
100 107
101 // These are callbacks which will be setup by the scene so that we can update scene data when we 108 // These are callbacks which will be setup by the scene so that we can update scene data when we
102 // receive capability calls 109 // receive capability calls
@@ -111,12 +118,50 @@ namespace OpenSim.Region.ClientStack.Linden
111 private IAssetService m_assetService; 118 private IAssetService m_assetService;
112 private bool m_dumpAssetsToFile = false; 119 private bool m_dumpAssetsToFile = false;
113 private string m_regionName; 120 private string m_regionName;
121
114 private int m_levelUpload = 0; 122 private int m_levelUpload = 0;
115 123
124 private bool m_enableFreeTestUpload = false; // allows "TEST-" prefix hack
125 private bool m_ForceFreeTestUpload = false; // forces all uploads to be test
126
127 private bool m_enableModelUploadTextureToInventory = false; // place uploaded textures also in inventory
128 // may not be visible till relog
129
130 private bool m_RestrictFreeTestUploadPerms = false; // reduces also the permitions. Needs a creator defined!!
131 private UUID m_testAssetsCreatorID = UUID.Zero;
132
133 private float m_PrimScaleMin = 0.001f;
134
135 private enum FileAgentInventoryState : int
136 {
137 idle = 0,
138 processRequest = 1,
139 waitUpload = 2,
140 processUpload = 3
141 }
142 private FileAgentInventoryState m_FileAgentInventoryState = FileAgentInventoryState.idle;
143
116 public BunchOfCaps(Scene scene, Caps caps) 144 public BunchOfCaps(Scene scene, Caps caps)
117 { 145 {
118 m_Scene = scene; 146 m_Scene = scene;
119 m_HostCapsObj = caps; 147 m_HostCapsObj = caps;
148
149 // create a model upload cost provider
150 m_ModelCost = new ModelCost();
151 // tell it about scene object limits
152 m_ModelCost.NonPhysicalPrimScaleMax = m_Scene.m_maxNonphys;
153 m_ModelCost.PhysicalPrimScaleMax = m_Scene.m_maxPhys;
154
155// m_ModelCost.ObjectLinkedPartsMax = ??
156// m_ModelCost.PrimScaleMin = ??
157
158 m_PrimScaleMin = m_ModelCost.PrimScaleMin;
159 float modelTextureUploadFactor = m_ModelCost.ModelTextureCostFactor;
160 float modelUploadFactor = m_ModelCost.ModelMeshCostFactor;
161 float modelMinUploadCostFactor = m_ModelCost.ModelMinCostFactor;
162 float modelPrimCreationCost = m_ModelCost.primCreationCost;
163 float modelMeshByteCost = m_ModelCost.bytecost;
164
120 IConfigSource config = m_Scene.Config; 165 IConfigSource config = m_Scene.Config;
121 if (config != null) 166 if (config != null)
122 { 167 {
@@ -131,6 +176,37 @@ namespace OpenSim.Region.ClientStack.Linden
131 { 176 {
132 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); 177 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
133 } 178 }
179 // economy for model upload
180 IConfig EconomyConfig = config.Configs["Economy"];
181 if (EconomyConfig != null)
182 {
183 modelUploadFactor = EconomyConfig.GetFloat("MeshModelUploadCostFactor", modelUploadFactor);
184 modelTextureUploadFactor = EconomyConfig.GetFloat("MeshModelUploadTextureCostFactor", modelTextureUploadFactor);
185 modelMinUploadCostFactor = EconomyConfig.GetFloat("MeshModelMinCostFactor", modelMinUploadCostFactor);
186 // next 2 are normalized so final cost is afected by modelUploadFactor above and normal cost
187 modelPrimCreationCost = EconomyConfig.GetFloat("ModelPrimCreationCost", modelPrimCreationCost);
188 modelMeshByteCost = EconomyConfig.GetFloat("ModelMeshByteCost", modelMeshByteCost);
189
190 m_enableModelUploadTextureToInventory = EconomyConfig.GetBoolean("MeshModelAllowTextureToInventory", m_enableModelUploadTextureToInventory);
191
192 m_RestrictFreeTestUploadPerms = EconomyConfig.GetBoolean("m_RestrictFreeTestUploadPerms", m_RestrictFreeTestUploadPerms);
193 m_enableFreeTestUpload = EconomyConfig.GetBoolean("AllowFreeTestUpload", m_enableFreeTestUpload);
194 m_ForceFreeTestUpload = EconomyConfig.GetBoolean("ForceFreeTestUpload", m_ForceFreeTestUpload);
195 string testcreator = EconomyConfig.GetString("TestAssetsCreatorID", "");
196 if (testcreator != "")
197 {
198 UUID id;
199 UUID.TryParse(testcreator, out id);
200 if (id != null)
201 m_testAssetsCreatorID = id;
202 }
203
204 m_ModelCost.ModelMeshCostFactor = modelUploadFactor;
205 m_ModelCost.ModelTextureCostFactor = modelTextureUploadFactor;
206 m_ModelCost.ModelMinCostFactor = modelMinUploadCostFactor;
207 m_ModelCost.primCreationCost = modelPrimCreationCost;
208 m_ModelCost.bytecost = modelMeshByteCost;
209 }
134 } 210 }
135 211
136 m_assetService = m_Scene.AssetService; 212 m_assetService = m_Scene.AssetService;
@@ -142,6 +218,8 @@ namespace OpenSim.Region.ClientStack.Linden
142 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset; 218 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset;
143 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset; 219 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset;
144 GetClient = m_Scene.SceneGraph.GetControllingClient; 220 GetClient = m_Scene.SceneGraph.GetControllingClient;
221
222 m_FileAgentInventoryState = FileAgentInventoryState.idle;
145 } 223 }
146 224
147 /// <summary> 225 /// <summary>
@@ -187,7 +265,6 @@ namespace OpenSim.Region.ClientStack.Linden
187 { 265 {
188 try 266 try
189 { 267 {
190 // I don't think this one works...
191 m_HostCapsObj.RegisterHandler( 268 m_HostCapsObj.RegisterHandler(
192 "NewFileAgentInventory", 269 "NewFileAgentInventory",
193 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>( 270 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>(
@@ -204,6 +281,12 @@ namespace OpenSim.Region.ClientStack.Linden
204 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); 281 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
205 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); 282 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
206 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); 283 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
284 IRequestHandler getObjectPhysicsDataHandler = new RestStreamHandler("POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData);
285 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
286 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost);
287 m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler);
288 IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected);
289 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
207 290
208 m_HostCapsObj.RegisterHandler( 291 m_HostCapsObj.RegisterHandler(
209 "CopyInventoryFromNotecard", 292 "CopyInventoryFromNotecard",
@@ -386,62 +469,176 @@ namespace OpenSim.Region.ClientStack.Linden
386 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString()); 469 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
387 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type); 470 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
388 471
472 // start by getting the client
473 IClientAPI client = null;
474 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
475
476 // check current state so we only have one service at a time
477 lock (m_ModelCost)
478 {
479 switch (m_FileAgentInventoryState)
480 {
481 case FileAgentInventoryState.processRequest:
482 case FileAgentInventoryState.processUpload:
483 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
484 resperror.message = "Uploader busy processing previus request";
485 resperror.identifier = UUID.Zero;
486
487 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
488 errorResponse.uploader = "";
489 errorResponse.state = "error";
490 errorResponse.error = resperror;
491 return errorResponse;
492 break;
493 case FileAgentInventoryState.waitUpload:
494 // todo stop current uploader server
495 break;
496 case FileAgentInventoryState.idle:
497 default:
498 break;
499 }
500
501 m_FileAgentInventoryState = FileAgentInventoryState.processRequest;
502 }
503
504 int cost = 0;
505 int nreqtextures = 0;
506 int nreqmeshs= 0;
507 int nreqinstances = 0;
508 bool IsAtestUpload = false;
509
510 string assetName = llsdRequest.name;
511
512 LLSDAssetUploadResponseData meshcostdata = new LLSDAssetUploadResponseData();
513
389 if (llsdRequest.asset_type == "texture" || 514 if (llsdRequest.asset_type == "texture" ||
390 llsdRequest.asset_type == "animation" || 515 llsdRequest.asset_type == "animation" ||
516 llsdRequest.asset_type == "mesh" ||
391 llsdRequest.asset_type == "sound") 517 llsdRequest.asset_type == "sound")
392 { 518 {
393 ScenePresence avatar = null; 519 ScenePresence avatar = null;
394 IClientAPI client = null;
395 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar); 520 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar);
396 521
397 // check user level 522 // check user level
398 if (avatar != null) 523 if (avatar != null)
399 { 524 {
400 client = avatar.ControllingClient;
401
402 if (avatar.UserLevel < m_levelUpload) 525 if (avatar.UserLevel < m_levelUpload)
403 { 526 {
404 if (client != null) 527 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
405 client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false); 528 resperror.message = "Insufficient permissions to upload";
529 resperror.identifier = UUID.Zero;
406 530
407 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 531 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
408 errorResponse.uploader = ""; 532 errorResponse.uploader = "";
409 errorResponse.state = "error"; 533 errorResponse.state = "error";
534 errorResponse.error = resperror;
535 lock (m_ModelCost)
536 m_FileAgentInventoryState = FileAgentInventoryState.idle;
410 return errorResponse; 537 return errorResponse;
411 } 538 }
412 } 539 }
413 540
414 // check funds 541 // check test upload and funds
415 if (client != null) 542 if (client != null)
416 { 543 {
417 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>(); 544 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
418 545
546 int baseCost = 0;
419 if (mm != null) 547 if (mm != null)
548 baseCost = mm.UploadCharge;
549
550 string warning = String.Empty;
551
552 if (llsdRequest.asset_type == "mesh")
420 { 553 {
421 if (!mm.UploadCovered(client.AgentId, mm.UploadCharge)) 554 string error;
555 int modelcost;
556
557 if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost,
558 meshcostdata, out error, ref warning))
422 { 559 {
423 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); 560 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
561 resperror.message = error;
562 resperror.identifier = UUID.Zero;
424 563
425 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 564 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
426 errorResponse.uploader = ""; 565 errorResponse.uploader = "";
427 errorResponse.state = "error"; 566 errorResponse.state = "error";
567 errorResponse.error = resperror;
568
569 lock (m_ModelCost)
570 m_FileAgentInventoryState = FileAgentInventoryState.idle;
428 return errorResponse; 571 return errorResponse;
429 } 572 }
573 cost = modelcost;
430 } 574 }
575 else
576 {
577 cost = baseCost;
578 }
579
580 if (cost > 0 && mm != null)
581 {
582 // check for test upload
583
584 if (m_ForceFreeTestUpload) // all are test
585 {
586 if (!(assetName.Length > 5 && assetName.StartsWith("TEST-"))) // has normal name lets change it
587 assetName = "TEST-" + assetName;
588
589 IsAtestUpload = true;
590 }
591
592 else if (m_enableFreeTestUpload) // only if prefixed with "TEST-"
593 {
594
595 IsAtestUpload = (assetName.Length > 5 && assetName.StartsWith("TEST-"));
596 }
597
598
599 if(IsAtestUpload) // let user know, still showing cost estimation
600 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";
601
602 // check funds
603 else
604 {
605 if (!mm.UploadCovered(client.AgentId, (int)cost))
606 {
607 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
608 resperror.message = "Insuficient funds";
609 resperror.identifier = UUID.Zero;
610
611 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
612 errorResponse.uploader = "";
613 errorResponse.state = "error";
614 errorResponse.error = resperror;
615 lock (m_ModelCost)
616 m_FileAgentInventoryState = FileAgentInventoryState.idle;
617 return errorResponse;
618 }
619 }
620 }
621
622 if (client != null && warning != String.Empty)
623 client.SendAgentAlertMessage(warning, true);
431 } 624 }
432 } 625 }
433 626
434 string assetName = llsdRequest.name;
435 string assetDes = llsdRequest.description; 627 string assetDes = llsdRequest.description;
436 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; 628 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
437 UUID newAsset = UUID.Random(); 629 UUID newAsset = UUID.Random();
438 UUID newInvItem = UUID.Random(); 630 UUID newInvItem = UUID.Random();
439 UUID parentFolder = llsdRequest.folder_id; 631 UUID parentFolder = llsdRequest.folder_id;
440 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); 632 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
633 UUID texturesFolder = UUID.Zero;
634
635 if(!IsAtestUpload && m_enableModelUploadTextureToInventory)
636 texturesFolder = llsdRequest.texture_folder_id;
441 637
442 AssetUploader uploader = 638 AssetUploader uploader =
443 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, 639 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
444 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); 640 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost,
641 texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload);
445 642
446 m_HostCapsObj.HttpListener.AddStreamHandler( 643 m_HostCapsObj.HttpListener.AddStreamHandler(
447 new BinaryStreamHandler( 644 new BinaryStreamHandler(
@@ -459,10 +656,22 @@ namespace OpenSim.Region.ClientStack.Linden
459 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + 656 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
460 uploaderPath; 657 uploaderPath;
461 658
659
462 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); 660 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
463 uploadResponse.uploader = uploaderURL; 661 uploadResponse.uploader = uploaderURL;
464 uploadResponse.state = "upload"; 662 uploadResponse.state = "upload";
663 uploadResponse.upload_price = (int)cost;
664
665 if (llsdRequest.asset_type == "mesh")
666 {
667 uploadResponse.data = meshcostdata;
668 }
669
465 uploader.OnUpLoad += UploadCompleteHandler; 670 uploader.OnUpLoad += UploadCompleteHandler;
671
672 lock (m_ModelCost)
673 m_FileAgentInventoryState = FileAgentInventoryState.waitUpload;
674
466 return uploadResponse; 675 return uploadResponse;
467 } 676 }
468 677
@@ -474,8 +683,14 @@ namespace OpenSim.Region.ClientStack.Linden
474 /// <param name="data"></param> 683 /// <param name="data"></param>
475 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, 684 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
476 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, 685 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
477 string assetType) 686 string assetType, int cost,
687 UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
688 bool IsAtestUpload, ref string error)
478 { 689 {
690
691 lock (m_ModelCost)
692 m_FileAgentInventoryState = FileAgentInventoryState.processUpload;
693
479 m_log.DebugFormat( 694 m_log.DebugFormat(
480 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}", 695 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}",
481 assetID, inventoryItem, inventoryType, assetType); 696 assetID, inventoryItem, inventoryType, assetType);
@@ -483,117 +698,247 @@ namespace OpenSim.Region.ClientStack.Linden
483 sbyte assType = 0; 698 sbyte assType = 0;
484 sbyte inType = 0; 699 sbyte inType = 0;
485 700
701 IClientAPI client = null;
702
703 UUID owner_id = m_HostCapsObj.AgentID;
704 UUID creatorID;
705
706 bool istest = IsAtestUpload && m_enableFreeTestUpload && (cost > 0);
707
708 bool restrictPerms = m_RestrictFreeTestUploadPerms && istest;
709
710 if (istest && m_testAssetsCreatorID != UUID.Zero)
711 creatorID = m_testAssetsCreatorID;
712 else
713 creatorID = owner_id;
714
715 string creatorIDstr = creatorID.ToString();
716
717 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
718 if (mm != null)
719 {
720 // make sure client still has enougth credit
721 if (!mm.UploadCovered(m_HostCapsObj.AgentID, (int)cost))
722 {
723 error = "Insufficient funds.";
724 return;
725 }
726 }
727
728 // strings to types
486 if (inventoryType == "sound") 729 if (inventoryType == "sound")
487 { 730 {
488 inType = 1; 731 inType = (sbyte)InventoryType.Sound;
489 assType = 1; 732 assType = (sbyte)AssetType.Sound;
490 } 733 }
491 else if (inventoryType == "animation") 734 else if (inventoryType == "animation")
492 { 735 {
493 inType = 19; 736 inType = (sbyte)InventoryType.Animation;
494 assType = 20; 737 assType = (sbyte)AssetType.Animation;
495 } 738 }
496 else if (inventoryType == "wearable") 739 else if (inventoryType == "wearable")
497 { 740 {
498 inType = 18; 741 inType = (sbyte)InventoryType.Wearable;
499 switch (assetType) 742 switch (assetType)
500 { 743 {
501 case "bodypart": 744 case "bodypart":
502 assType = 13; 745 assType = (sbyte)AssetType.Bodypart;
503 break; 746 break;
504 case "clothing": 747 case "clothing":
505 assType = 5; 748 assType = (sbyte)AssetType.Clothing;
506 break; 749 break;
507 } 750 }
508 } 751 }
509 else if (inventoryType == "object") 752 else if (inventoryType == "object")
510 { 753 {
511 inType = (sbyte)InventoryType.Object; 754 if (assetType == "mesh") // this code for now is for mesh models uploads only
512 assType = (sbyte)AssetType.Object;
513
514 List<Vector3> positions = new List<Vector3>();
515 List<Quaternion> rotations = new List<Quaternion>();
516 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
517 OSDArray instance_list = (OSDArray)request["instance_list"];
518 OSDArray mesh_list = (OSDArray)request["mesh_list"];
519 OSDArray texture_list = (OSDArray)request["texture_list"];
520 SceneObjectGroup grp = null;
521
522 List<UUID> textures = new List<UUID>();
523 for (int i = 0; i < texture_list.Count; i++)
524 { 755 {
525 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, ""); 756 inType = (sbyte)InventoryType.Object;
526 textureAsset.Data = texture_list[i].AsBinary(); 757 assType = (sbyte)AssetType.Object;
527 m_assetService.Store(textureAsset);
528 textures.Add(textureAsset.FullID);
529 }
530 758
531 for (int i = 0; i < mesh_list.Count; i++) 759 List<Vector3> positions = new List<Vector3>();
532 { 760 List<Quaternion> rotations = new List<Quaternion>();
533 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); 761 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
762
763 // compare and get updated information
534 764
535 Primitive.TextureEntry textureEntry 765 bool mismatchError = true;
536 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
537 OSDMap inner_instance_list = (OSDMap)instance_list[i];
538 766
539 OSDArray face_list = (OSDArray)inner_instance_list["face_list"]; 767 while (mismatchError)
540 for (uint face = 0; face < face_list.Count; face++)
541 { 768 {
542 OSDMap faceMap = (OSDMap)face_list[(int)face]; 769 mismatchError = false;
543 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face); 770 }
544 if(faceMap.ContainsKey("fullbright"))
545 f.Fullbright = faceMap["fullbright"].AsBoolean();
546 if (faceMap.ContainsKey ("diffuse_color"))
547 f.RGBA = faceMap["diffuse_color"].AsColor4();
548 771
549 int textureNum = faceMap["image"].AsInteger(); 772 if (mismatchError)
550 float imagerot = faceMap["imagerot"].AsInteger(); 773 {
551 float offsets = (float)faceMap["offsets"].AsReal(); 774 error = "Upload and fee estimation information don't match";
552 float offsett = (float)faceMap["offsett"].AsReal(); 775 lock (m_ModelCost)
553 float scales = (float)faceMap["scales"].AsReal(); 776 m_FileAgentInventoryState = FileAgentInventoryState.idle;
554 float scalet = (float)faceMap["scalet"].AsReal();
555 777
556 if(imagerot != 0) 778 return;
557 f.Rotation = imagerot; 779 }
558 780
559 if(offsets != 0) 781 OSDArray instance_list = (OSDArray)request["instance_list"];
560 f.OffsetU = offsets; 782 OSDArray mesh_list = (OSDArray)request["mesh_list"];
783 OSDArray texture_list = (OSDArray)request["texture_list"];
784 SceneObjectGroup grp = null;
561 785
562 if (offsett != 0) 786 // create and store texture assets
563 f.OffsetV = offsett; 787 bool doTextInv = (!istest && m_enableModelUploadTextureToInventory &&
788 texturesFolder != UUID.Zero);
564 789
565 if (scales != 0)
566 f.RepeatU = scales;
567 790
568 if (scalet != 0) 791 List<UUID> textures = new List<UUID>();
569 f.RepeatV = scalet;
570 792
571 if (textures.Count > textureNum) 793
572 f.TextureID = textures[textureNum]; 794 if (doTextInv)
573 else 795 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
574 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
575 796
576 textureEntry.FaceTextures[face] = f; 797 if(client == null) // don't put textures in inventory if there is no client
798 doTextInv = false;
799
800 for (int i = 0; i < texture_list.Count; i++)
801 {
802 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, creatorIDstr);
803 textureAsset.Data = texture_list[i].AsBinary();
804 if (istest)
805 textureAsset.Local = true;
806 m_assetService.Store(textureAsset);
807 textures.Add(textureAsset.FullID);
808
809 if (doTextInv)
810 {
811 string name = assetName;
812 if (name.Length > 25)
813 name = name.Substring(0, 24);
814 name += "_Texture#" + i.ToString();
815 InventoryItemBase texitem = new InventoryItemBase();
816 texitem.Owner = m_HostCapsObj.AgentID;
817 texitem.CreatorId = creatorIDstr;
818 texitem.CreatorData = String.Empty;
819 texitem.ID = UUID.Random();
820 texitem.AssetID = textureAsset.FullID;
821 texitem.Description = "mesh model texture";
822 texitem.Name = name;
823 texitem.AssetType = (int)AssetType.Texture;
824 texitem.InvType = (int)InventoryType.Texture;
825 texitem.Folder = texturesFolder;
826
827 texitem.CurrentPermissions
828 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
829
830 texitem.BasePermissions = (uint)PermissionMask.All;
831 texitem.EveryOnePermissions = 0;
832 texitem.NextPermissions = (uint)PermissionMask.All;
833 texitem.CreationDate = Util.UnixTimeSinceEpoch();
834
835 m_Scene.AddInventoryItem(client, texitem);
836 texitem = null;
837 }
838 }
839
840 // create and store meshs assets
841 List<UUID> meshAssets = new List<UUID>();
842 for (int i = 0; i < mesh_list.Count; i++)
843 {
844 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, creatorIDstr);
845 meshAsset.Data = mesh_list[i].AsBinary();
846 if (istest)
847 meshAsset.Local = true;
848 m_assetService.Store(meshAsset);
849 meshAssets.Add(meshAsset.FullID);
577 } 850 }
578 851
579 pbs.TextureEntry = textureEntry.GetBytes(); 852 int skipedMeshs = 0;
853 // build prims from instances
854 for (int i = 0; i < instance_list.Count; i++)
855 {
856 OSDMap inner_instance_list = (OSDMap)instance_list[i];
857
858 // skip prims that are 2 small
859 Vector3 scale = inner_instance_list["scale"].AsVector3();
860
861 if (scale.X < m_PrimScaleMin || scale.Y < m_PrimScaleMin || scale.Z < m_PrimScaleMin)
862 {
863 skipedMeshs++;
864 continue;
865 }
866
867 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
868
869 Primitive.TextureEntry textureEntry
870 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
871
872
873 OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
874 for (uint face = 0; face < face_list.Count; face++)
875 {
876 OSDMap faceMap = (OSDMap)face_list[(int)face];
877 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
878 if (faceMap.ContainsKey("fullbright"))
879 f.Fullbright = faceMap["fullbright"].AsBoolean();
880 if (faceMap.ContainsKey("diffuse_color"))
881 f.RGBA = faceMap["diffuse_color"].AsColor4();
882
883 int textureNum = faceMap["image"].AsInteger();
884 float imagerot = faceMap["imagerot"].AsInteger();
885 float offsets = (float)faceMap["offsets"].AsReal();
886 float offsett = (float)faceMap["offsett"].AsReal();
887 float scales = (float)faceMap["scales"].AsReal();
888 float scalet = (float)faceMap["scalet"].AsReal();
580 889
581 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, ""); 890 if (imagerot != 0)
582 meshAsset.Data = mesh_list[i].AsBinary(); 891 f.Rotation = imagerot;
583 m_assetService.Store(meshAsset);
584 892
585 pbs.SculptEntry = true; 893 if (offsets != 0)
586 pbs.SculptTexture = meshAsset.FullID; 894 f.OffsetU = offsets;
587 pbs.SculptType = (byte)SculptType.Mesh;
588 pbs.SculptData = meshAsset.Data;
589 895
590 Vector3 position = inner_instance_list["position"].AsVector3(); 896 if (offsett != 0)
591 Vector3 scale = inner_instance_list["scale"].AsVector3(); 897 f.OffsetV = offsett;
592 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); 898
899 if (scales != 0)
900 f.RepeatU = scales;
901
902 if (scalet != 0)
903 f.RepeatV = scalet;
904
905 if (textures.Count > textureNum)
906 f.TextureID = textures[textureNum];
907 else
908 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
909
910 textureEntry.FaceTextures[face] = f;
911 }
912
913 pbs.TextureEntry = textureEntry.GetBytes();
914
915 bool hasmesh = false;
916 if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ...
917 {
918 int meshindx = inner_instance_list["mesh"].AsInteger();
919 if (meshAssets.Count > meshindx)
920 {
921 pbs.SculptEntry = true;
922 pbs.SculptType = (byte)SculptType.Mesh;
923 pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction
924 // data will be requested from asset on rez (i hope)
925 hasmesh = true;
926 }
927 }
928
929 Vector3 position = inner_instance_list["position"].AsVector3();
930 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
931
932 // for now viwers do send fixed defaults
933 // but this may change
934// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
935 byte physicsShapeType = (byte)PhysShapeType.prim; // default for mesh is simple convex
936 if(hasmesh)
937 physicsShapeType = (byte) PhysShapeType.convex; // default for mesh is simple convex
938// int material = inner_instance_list["material"].AsInteger();
939 byte material = (byte)Material.Wood;
593 940
594// no longer used - begin ------------------------ 941// no longer used - begin ------------------------
595// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
596// int material = inner_instance_list["material"].AsInteger();
597// int mesh = inner_instance_list["mesh"].AsInteger(); 942// int mesh = inner_instance_list["mesh"].AsInteger();
598 943
599// OSDMap permissions = (OSDMap)inner_instance_list["permissions"]; 944// OSDMap permissions = (OSDMap)inner_instance_list["permissions"];
@@ -608,24 +953,42 @@ namespace OpenSim.Region.ClientStack.Linden
608// UUID owner_id = permissions["owner_id"].AsUUID(); 953// UUID owner_id = permissions["owner_id"].AsUUID();
609// int owner_mask = permissions["owner_mask"].AsInteger(); 954// int owner_mask = permissions["owner_mask"].AsInteger();
610// no longer used - end ------------------------ 955// no longer used - end ------------------------
956
957
958 SceneObjectPart prim
959 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
960
961 prim.Scale = scale;
962 rotations.Add(rotation);
963 positions.Add(position);
964 prim.UUID = UUID.Random();
965 prim.CreatorID = creatorID;
966 prim.OwnerID = owner_id;
967 prim.GroupID = UUID.Zero;
968 prim.LastOwnerID = creatorID;
969 prim.CreationDate = Util.UnixTimeSinceEpoch();
970
971 if (grp == null)
972 prim.Name = assetName;
973 else
974 prim.Name = assetName + "#" + i.ToString();
611 975
612 UUID owner_id = m_HostCapsObj.AgentID; 976 if (restrictPerms)
977 {
978 prim.BaseMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
979 prim.EveryoneMask = 0;
980 prim.GroupMask = 0;
981 prim.NextOwnerMask = 0;
982 prim.OwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
983 }
613 984
614 SceneObjectPart prim 985 if(istest)
615 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); 986 prim.Description = "For testing only. Other uses are prohibited";
987 else
988 prim.Description = "";
616 989
617 prim.Scale = scale; 990 prim.Material = material;
618 prim.OffsetPosition = position; 991 prim.PhysicsShapeType = physicsShapeType;
619 rotations.Add(rotation);
620 positions.Add(position);
621 prim.UUID = UUID.Random();
622 prim.CreatorID = owner_id;
623 prim.OwnerID = owner_id;
624 prim.GroupID = UUID.Zero;
625 prim.LastOwnerID = prim.OwnerID;
626 prim.CreationDate = Util.UnixTimeSinceEpoch();
627 prim.Name = assetName;
628 prim.Description = "";
629 992
630// prim.BaseMask = (uint)base_mask; 993// prim.BaseMask = (uint)base_mask;
631// prim.EveryoneMask = (uint)everyone_mask; 994// prim.EveryoneMask = (uint)everyone_mask;
@@ -633,37 +996,64 @@ namespace OpenSim.Region.ClientStack.Linden
633// prim.NextOwnerMask = (uint)next_owner_mask; 996// prim.NextOwnerMask = (uint)next_owner_mask;
634// prim.OwnerMask = (uint)owner_mask; 997// prim.OwnerMask = (uint)owner_mask;
635 998
636 if (grp == null) 999 if (grp == null)
637 grp = new SceneObjectGroup(prim); 1000 {
638 else 1001 grp = new SceneObjectGroup(prim);
639 grp.AddPart(prim); 1002 grp.LastOwnerID = creatorID;
640 } 1003 }
1004 else
1005 grp.AddPart(prim);
1006 }
641 1007
642 // Fix first link number 1008 Vector3 rootPos = positions[0];
643 if (grp.Parts.Length > 1)
644 grp.RootPart.LinkNum++;
645 1009
646 Vector3 rootPos = positions[0]; 1010 if (grp.Parts.Length > 1)
647 grp.AbsolutePosition = rootPos; 1011 {
648 for (int i = 0; i < positions.Count; i++) 1012 // Fix first link number
649 { 1013 grp.RootPart.LinkNum++;
650 Vector3 offset = positions[i] - rootPos; 1014
651 grp.Parts[i].OffsetPosition = offset; 1015 Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]);
1016 Quaternion tmprot;
1017 Vector3 offset;
1018
1019 // fix children rotations and positions
1020 for (int i = 1; i < rotations.Count; i++)
1021 {
1022 tmprot = rotations[i];
1023 tmprot = rootRotConj * tmprot;
1024
1025 grp.Parts[i].RotationOffset = tmprot;
1026
1027 offset = positions[i] - rootPos;
1028
1029 offset *= rootRotConj;
1030 grp.Parts[i].OffsetPosition = offset;
1031 }
1032
1033 grp.AbsolutePosition = rootPos;
1034 grp.UpdateGroupRotationR(rotations[0]);
1035 }
1036 else
1037 {
1038 grp.AbsolutePosition = rootPos;
1039 grp.UpdateGroupRotationR(rotations[0]);
1040 }
1041
1042 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
652 } 1043 }
653 1044
654 for (int i = 0; i < rotations.Count; i++) 1045 else // not a mesh model
655 { 1046 {
656 if (i != 0) 1047 m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload");
657 grp.Parts[i].RotationOffset = rotations[i]; 1048 return;
658 } 1049 }
659
660 grp.UpdateGroupRotationR(rotations[0]);
661 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
662 } 1050 }
663 1051
664 AssetBase asset; 1052 AssetBase asset;
665 asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString()); 1053 asset = new AssetBase(assetID, assetName, assType, creatorIDstr);
666 asset.Data = data; 1054 asset.Data = data;
1055 if (istest)
1056 asset.Local = true;
667 if (AddNewAsset != null) 1057 if (AddNewAsset != null)
668 AddNewAsset(asset); 1058 AddNewAsset(asset);
669 else if (m_assetService != null) 1059 else if (m_assetService != null)
@@ -671,11 +1061,17 @@ namespace OpenSim.Region.ClientStack.Linden
671 1061
672 InventoryItemBase item = new InventoryItemBase(); 1062 InventoryItemBase item = new InventoryItemBase();
673 item.Owner = m_HostCapsObj.AgentID; 1063 item.Owner = m_HostCapsObj.AgentID;
674 item.CreatorId = m_HostCapsObj.AgentID.ToString(); 1064 item.CreatorId = creatorIDstr;
675 item.CreatorData = String.Empty; 1065 item.CreatorData = String.Empty;
676 item.ID = inventoryItem; 1066 item.ID = inventoryItem;
677 item.AssetID = asset.FullID; 1067 item.AssetID = asset.FullID;
678 item.Description = assetDescription; 1068 if (istest)
1069 {
1070 item.Description = "For testing only. Other uses are prohibited";
1071 item.Flags = (uint) (InventoryItemFlags.SharedSingleReference);
1072 }
1073 else
1074 item.Description = assetDescription;
679 item.Name = assetName; 1075 item.Name = assetName;
680 item.AssetType = assType; 1076 item.AssetType = assType;
681 item.InvType = inType; 1077 item.InvType = inType;
@@ -683,18 +1079,60 @@ namespace OpenSim.Region.ClientStack.Linden
683 1079
684 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current 1080 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
685 // (owner) permissions. This becomes a problem if next permissions are changed. 1081 // (owner) permissions. This becomes a problem if next permissions are changed.
686 item.CurrentPermissions
687 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
688 1082
689 item.BasePermissions = (uint)PermissionMask.All; 1083 if (restrictPerms)
690 item.EveryOnePermissions = 0; 1084 {
691 item.NextPermissions = (uint)PermissionMask.All; 1085 item.CurrentPermissions
1086 = (uint)(PermissionMask.Move | PermissionMask.Modify);
1087
1088 item.BasePermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
1089 item.EveryOnePermissions = 0;
1090 item.NextPermissions = 0;
1091 }
1092 else
1093 {
1094 item.CurrentPermissions
1095 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
1096
1097 item.BasePermissions = (uint)PermissionMask.All;
1098 item.EveryOnePermissions = 0;
1099 item.NextPermissions = (uint)PermissionMask.All;
1100 }
1101
692 item.CreationDate = Util.UnixTimeSinceEpoch(); 1102 item.CreationDate = Util.UnixTimeSinceEpoch();
693 1103
1104 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
1105
694 if (AddNewInventoryItem != null) 1106 if (AddNewInventoryItem != null)
695 { 1107 {
696 AddNewInventoryItem(m_HostCapsObj.AgentID, item); 1108 if (istest)
1109 {
1110 m_Scene.AddInventoryItem(client, item);
1111/*
1112 AddNewInventoryItem(m_HostCapsObj.AgentID, item, 0);
1113 if (client != null)
1114 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);
1115 */
1116 }
1117 else
1118 {
1119 AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
1120 if (client != null)
1121 {
1122 // let users see anything.. i don't so far
1123 string str;
1124 if (cost > 0)
1125 // dont remember where is money unit name to put here
1126 str = "Upload complete. charged " + cost.ToString() + "$";
1127 else
1128 str = "Upload complete";
1129 client.SendAgentAlertMessage(str, true);
1130 }
1131 }
697 } 1132 }
1133
1134 lock (m_ModelCost)
1135 m_FileAgentInventoryState = FileAgentInventoryState.idle;
698 } 1136 }
699 1137
700 /// <summary> 1138 /// <summary>
@@ -855,10 +1293,159 @@ namespace OpenSim.Region.ClientStack.Linden
855 response["int_response_code"] = 200; 1293 response["int_response_code"] = 200;
856 return LLSDHelpers.SerialiseLLSDReply(response); 1294 return LLSDHelpers.SerialiseLLSDReply(response);
857 } 1295 }
1296
1297 public string GetObjectPhysicsData(string request, string path,
1298 string param, IOSHttpRequest httpRequest,
1299 IOSHttpResponse httpResponse)
1300 {
1301 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1302 OSDMap resp = new OSDMap();
1303 OSDArray object_ids = (OSDArray)req["object_ids"];
1304
1305 for (int i = 0 ; i < object_ids.Count ; i++)
1306 {
1307 UUID uuid = object_ids[i].AsUUID();
1308
1309 SceneObjectPart obj = m_Scene.GetSceneObjectPart(uuid);
1310 if (obj != null)
1311 {
1312 OSDMap object_data = new OSDMap();
1313
1314 object_data["PhysicsShapeType"] = obj.PhysicsShapeType;
1315 object_data["Density"] = obj.Density;
1316 object_data["Friction"] = obj.Friction;
1317 object_data["Restitution"] = obj.Bounciness;
1318 object_data["GravityMultiplier"] = obj.GravityModifier;
1319
1320 resp[uuid.ToString()] = object_data;
1321 }
1322 }
1323
1324 string response = OSDParser.SerializeLLSDXmlString(resp);
1325 return response;
1326 }
1327
1328 public string GetObjectCost(string request, string path,
1329 string param, IOSHttpRequest httpRequest,
1330 IOSHttpResponse httpResponse)
1331 {
1332 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1333 OSDMap resp = new OSDMap();
1334
1335 OSDArray object_ids = (OSDArray)req["object_ids"];
1336
1337 for (int i = 0; i < object_ids.Count; i++)
1338 {
1339 UUID uuid = object_ids[i].AsUUID();
1340
1341 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1342
1343 if (part != null)
1344 {
1345 SceneObjectGroup grp = part.ParentGroup;
1346 if (grp != null)
1347 {
1348 float linksetCost;
1349 float linksetPhysCost;
1350 float partCost;
1351 float partPhysCost;
1352
1353 grp.GetResourcesCosts(part, out linksetCost, out linksetPhysCost, out partCost, out partPhysCost);
1354
1355 OSDMap object_data = new OSDMap();
1356 object_data["linked_set_resource_cost"] = linksetCost;
1357 object_data["resource_cost"] = partCost;
1358 object_data["physics_cost"] = partPhysCost;
1359 object_data["linked_set_physics_cost"] = linksetPhysCost;
1360
1361 resp[uuid.ToString()] = object_data;
1362 }
1363 }
1364 }
1365
1366 string response = OSDParser.SerializeLLSDXmlString(resp);
1367 return response;
1368 }
1369
1370 public string ResourceCostSelected(string request, string path,
1371 string param, IOSHttpRequest httpRequest,
1372 IOSHttpResponse httpResponse)
1373 {
1374 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1375 OSDMap resp = new OSDMap();
1376
1377
1378 float phys=0;
1379 float stream=0;
1380 float simul=0;
1381
1382 if (req.ContainsKey("selected_roots"))
1383 {
1384 OSDArray object_ids = (OSDArray)req["selected_roots"];
1385
1386 // should go by SOG suming costs for all parts
1387 // ll v3 works ok with several objects select we get the list and adds ok
1388 // FS calls per object so results are wrong guess fs bug
1389 for (int i = 0; i < object_ids.Count; i++)
1390 {
1391 UUID uuid = object_ids[i].AsUUID();
1392 float Physc;
1393 float simulc;
1394 float streamc;
1395
1396 SceneObjectGroup grp = m_Scene.GetGroupByPrim(uuid);
1397 if (grp != null)
1398 {
1399 grp.GetSelectedCosts(out Physc, out streamc, out simulc);
1400 phys += Physc;
1401 stream += streamc;
1402 simul += simulc;
1403 }
1404 }
1405 }
1406 else if (req.ContainsKey("selected_prims"))
1407 {
1408 OSDArray object_ids = (OSDArray)req["selected_prims"];
1409
1410 // don't see in use in any of the 2 viewers
1411 // guess it should be for edit linked but... nothing
1412 // should go to SOP per part
1413 for (int i = 0; i < object_ids.Count; i++)
1414 {
1415 UUID uuid = object_ids[i].AsUUID();
1416
1417 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1418 if (part != null)
1419 {
1420 phys += part.PhysicsCost;
1421 stream += part.StreamingCost;
1422 simul += part.SimulationCost;
1423 }
1424 }
1425 }
1426
1427 if (simul != 0)
1428 {
1429 OSDMap object_data = new OSDMap();
1430
1431 object_data["physics"] = phys;
1432 object_data["streaming"] = stream;
1433 object_data["simulation"] = simul;
1434
1435 resp["selected"] = object_data;
1436 }
1437
1438 string response = OSDParser.SerializeLLSDXmlString(resp);
1439 return response;
1440 }
858 } 1441 }
859 1442
860 public class AssetUploader 1443 public class AssetUploader
861 { 1444 {
1445 private static readonly ILog m_log =
1446 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
1447
1448
862 public event UpLoadedAsset OnUpLoad; 1449 public event UpLoadedAsset OnUpLoad;
863 private UpLoadedAsset handlerUpLoad = null; 1450 private UpLoadedAsset handlerUpLoad = null;
864 1451
@@ -873,10 +1460,21 @@ namespace OpenSim.Region.ClientStack.Linden
873 1460
874 private string m_invType = String.Empty; 1461 private string m_invType = String.Empty;
875 private string m_assetType = String.Empty; 1462 private string m_assetType = String.Empty;
1463 private int m_cost;
1464 private string m_error = String.Empty;
1465
1466 private Timer m_timeoutTimer = new Timer();
1467 private UUID m_texturesFolder;
1468 private int m_nreqtextures;
1469 private int m_nreqmeshs;
1470 private int m_nreqinstances;
1471 private bool m_IsAtestUpload;
876 1472
877 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, 1473 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
878 UUID parentFolderID, string invType, string assetType, string path, 1474 UUID parentFolderID, string invType, string assetType, string path,
879 IHttpServer httpServer, bool dumpAssetsToFile) 1475 IHttpServer httpServer, bool dumpAssetsToFile,
1476 int totalCost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
1477 bool IsAtestUpload)
880 { 1478 {
881 m_assetName = assetName; 1479 m_assetName = assetName;
882 m_assetDes = description; 1480 m_assetDes = description;
@@ -888,6 +1486,18 @@ namespace OpenSim.Region.ClientStack.Linden
888 m_assetType = assetType; 1486 m_assetType = assetType;
889 m_invType = invType; 1487 m_invType = invType;
890 m_dumpAssetsToFile = dumpAssetsToFile; 1488 m_dumpAssetsToFile = dumpAssetsToFile;
1489 m_cost = totalCost;
1490
1491 m_texturesFolder = texturesFolder;
1492 m_nreqtextures = nreqtextures;
1493 m_nreqmeshs = nreqmeshs;
1494 m_nreqinstances = nreqinstances;
1495 m_IsAtestUpload = IsAtestUpload;
1496
1497 m_timeoutTimer.Elapsed += TimedOut;
1498 m_timeoutTimer.Interval = 120000;
1499 m_timeoutTimer.AutoReset = false;
1500 m_timeoutTimer.Start();
891 } 1501 }
892 1502
893 /// <summary> 1503 /// <summary>
@@ -902,12 +1512,14 @@ namespace OpenSim.Region.ClientStack.Linden
902 UUID inv = inventoryItemID; 1512 UUID inv = inventoryItemID;
903 string res = String.Empty; 1513 string res = String.Empty;
904 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); 1514 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
1515/*
905 uploadComplete.new_asset = newAssetID.ToString(); 1516 uploadComplete.new_asset = newAssetID.ToString();
906 uploadComplete.new_inventory_item = inv; 1517 uploadComplete.new_inventory_item = inv;
907 uploadComplete.state = "complete"; 1518 uploadComplete.state = "complete";
908 1519
909 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); 1520 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
910 1521*/
1522 m_timeoutTimer.Stop();
911 httpListener.RemoveStreamHandler("POST", uploaderPath); 1523 httpListener.RemoveStreamHandler("POST", uploaderPath);
912 1524
913 // TODO: probably make this a better set of extensions here 1525 // TODO: probably make this a better set of extensions here
@@ -924,12 +1536,49 @@ namespace OpenSim.Region.ClientStack.Linden
924 handlerUpLoad = OnUpLoad; 1536 handlerUpLoad = OnUpLoad;
925 if (handlerUpLoad != null) 1537 if (handlerUpLoad != null)
926 { 1538 {
927 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType); 1539 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType,
1540 m_cost, m_texturesFolder, m_nreqtextures, m_nreqmeshs, m_nreqinstances, m_IsAtestUpload, ref m_error);
1541 }
1542 if (m_IsAtestUpload)
1543 {
1544 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1545 resperror.message = "Upload SUCESSEFULL for testing purposes only. Other uses are prohibited. Item will not work after 48 hours or on other regions";
1546 resperror.identifier = inv;
1547
1548 uploadComplete.error = resperror;
1549 uploadComplete.state = "Upload4Testing";
928 } 1550 }
1551 else
1552 {
1553 if (m_error == String.Empty)
1554 {
1555 uploadComplete.new_asset = newAssetID.ToString();
1556 uploadComplete.new_inventory_item = inv;
1557 // if (m_texturesFolder != UUID.Zero)
1558 // uploadComplete.new_texture_folder_id = m_texturesFolder;
1559 uploadComplete.state = "complete";
1560 }
1561 else
1562 {
1563 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1564 resperror.message = m_error;
1565 resperror.identifier = inv;
929 1566
1567 uploadComplete.error = resperror;
1568 uploadComplete.state = "failed";
1569 }
1570 }
1571
1572 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
930 return res; 1573 return res;
931 } 1574 }
932 1575
1576 private void TimedOut(object sender, ElapsedEventArgs args)
1577 {
1578 m_log.InfoFormat("[CAPS]: Removing URL and handler for timed out mesh upload");
1579 httpListener.RemoveStreamHandler("POST", uploaderPath);
1580 }
1581
933 ///Left this in and commented in case there are unforseen issues 1582 ///Left this in and commented in case there are unforseen issues
934 //private void SaveAssetToFile(string filename, byte[] data) 1583 //private void SaveAssetToFile(string filename, byte[] data)
935 //{ 1584 //{
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..4a3fae6
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
@@ -0,0 +1,671 @@
1// Proprietary code of Avination Virtual Limited
2// (c) 2012 Melanie Thielker, Leal Duarte
3//
4
5using System;
6using System.IO;
7using System.Collections;
8using System.Collections.Generic;
9using System.Text;
10
11using OpenMetaverse;
12using OpenMetaverse.StructuredData;
13
14using OpenSim.Framework;
15using OpenSim.Region.Framework;
16using OpenSim.Region.Framework.Scenes;
17using OpenSim.Framework.Capabilities;
18
19using ComponentAce.Compression.Libs.zlib;
20
21using OSDArray = OpenMetaverse.StructuredData.OSDArray;
22using OSDMap = OpenMetaverse.StructuredData.OSDMap;
23
24namespace OpenSim.Region.ClientStack.Linden
25{
26 public struct ModelPrimLimits
27 {
28
29 }
30
31 public class ModelCost
32 {
33
34 // upload fee defaults
35 // fees are normalized to 1.0
36 // this parameters scale them to basic cost ( so 1.0 translates to 10 )
37
38 public float ModelMeshCostFactor = 0.0f; // scale total cost relative to basic (excluding textures)
39 public float ModelTextureCostFactor = 1.0f; // scale textures fee to basic.
40 public float ModelMinCostFactor = 0.0f; // 0.5f; // minimum total model free excluding textures
41
42 // itens costs in normalized values
43 // ie will be multiplied by basicCost and factors above
44 public float primCreationCost = 0.002f; // extra cost for each prim creation overhead
45 // weigthed size to normalized cost
46 public float bytecost = 1e-5f;
47
48 // mesh upload fees based on compressed data sizes
49 // several data sections are counted more that once
50 // to promote user optimization
51 // following parameters control how many extra times they are added
52 // to global size.
53 // LOD meshs
54 const float medSizeWth = 1f; // 2x
55 const float lowSizeWth = 1.5f; // 2.5x
56 const float lowestSizeWth = 2f; // 3x
57 // favor potencially physical optimized meshs versus automatic decomposition
58 const float physMeshSizeWth = 6f; // counts 7x
59 const float physHullSizeWth = 8f; // counts 9x
60
61 // stream cost area factors
62 // more or less like SL
63 const float highLodFactor = 17.36f;
64 const float midLodFactor = 277.78f;
65 const float lowLodFactor = 1111.11f;
66
67 // physics cost is below, identical to SL, assuming shape type convex
68 // server cost is below identical to SL assuming non scripted non physical object
69
70 // internal
71 const int bytesPerCoord = 6; // 3 coords, 2 bytes per each
72
73 // control prims dimensions
74 public float PrimScaleMin = 0.001f;
75 public float NonPhysicalPrimScaleMax = 256f;
76 public float PhysicalPrimScaleMax = 10f;
77 public int ObjectLinkedPartsMax = 512;
78
79 // storage for a single mesh asset cost parameters
80 private class ameshCostParam
81 {
82 // LOD sizes for size dependent streaming cost
83 public int highLODSize;
84 public int medLODSize;
85 public int lowLODSize;
86 public int lowestLODSize;
87 // normalized fee based on compressed data sizes
88 public float costFee;
89 // physics cost
90 public float physicsCost;
91 }
92
93 // calculates a mesh model costs
94 // returns false on error, with a reason on parameter error
95 // resources input LLSD request
96 // basicCost input region assets upload cost
97 // totalcost returns model total upload fee
98 // meshcostdata returns detailed costs for viewer
99 public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost,
100 LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning)
101 {
102 totalcost = 0;
103 error = string.Empty;
104
105 if (resources == null ||
106 resources.instance_list == null ||
107 resources.instance_list.Array.Count == 0)
108 {
109 error = "missing model information.";
110 return false;
111 }
112
113 int numberInstances = resources.instance_list.Array.Count;
114
115 if( numberInstances > ObjectLinkedPartsMax )
116 {
117 error = "Model whould have more than " + ObjectLinkedPartsMax.ToString() + " linked prims";
118 return false;
119 }
120
121 meshcostdata.model_streaming_cost = 0.0;
122 meshcostdata.simulation_cost = 0.0;
123 meshcostdata.physics_cost = 0.0;
124 meshcostdata.resource_cost = 0.0;
125
126 meshcostdata.upload_price_breakdown.mesh_instance = 0;
127 meshcostdata.upload_price_breakdown.mesh_physics = 0;
128 meshcostdata.upload_price_breakdown.mesh_streaming = 0;
129 meshcostdata.upload_price_breakdown.model = 0;
130
131 int itmp;
132
133 // textures cost
134 if (resources.texture_list != null && resources.texture_list.Array.Count > 0)
135 {
136 float textures_cost = (float)(resources.texture_list.Array.Count * basicCost);
137 textures_cost *= ModelTextureCostFactor;
138
139 itmp = (int)(textures_cost + 0.5f); // round
140 meshcostdata.upload_price_breakdown.texture = itmp;
141 totalcost += itmp;
142 }
143
144 // meshs assets cost
145 float meshsfee = 0;
146 int numberMeshs = 0;
147 bool haveMeshs = false;
148 List<ameshCostParam> meshsCosts = new List<ameshCostParam>();
149
150 if (resources.mesh_list != null && resources.mesh_list.Array.Count > 0)
151 {
152 numberMeshs = resources.mesh_list.Array.Count;
153
154 for (int i = 0; i < numberMeshs; i++)
155 {
156 ameshCostParam curCost = new ameshCostParam();
157 byte[] data = (byte[])resources.mesh_list.Array[i];
158
159 if (!MeshCost(data, curCost, out error))
160 {
161 return false;
162 }
163 meshsCosts.Add(curCost);
164 meshsfee += curCost.costFee;
165 }
166 haveMeshs = true;
167 }
168
169 // instances (prims) cost
170
171
172 int mesh;
173 int skipedSmall = 0;
174 for (int i = 0; i < numberInstances; i++)
175 {
176 Hashtable inst = (Hashtable)resources.instance_list.Array[i];
177
178 ArrayList ascale = (ArrayList)inst["scale"];
179 Vector3 scale;
180 double tmp;
181 tmp = (double)ascale[0];
182 scale.X = (float)tmp;
183 tmp = (double)ascale[1];
184 scale.Y = (float)tmp;
185 tmp = (double)ascale[2];
186 scale.Z = (float)tmp;
187
188 if (scale.X < PrimScaleMin || scale.Y < PrimScaleMin || scale.Z < PrimScaleMin)
189 {
190 skipedSmall++;
191 continue;
192 }
193
194 if (scale.X > NonPhysicalPrimScaleMax || scale.Y > NonPhysicalPrimScaleMax || scale.Z > NonPhysicalPrimScaleMax)
195 {
196 error = "Model contains parts with sides larger than " + NonPhysicalPrimScaleMax.ToString() + "m. Please ajust scale";
197 return false;
198 }
199
200 if (haveMeshs && inst.ContainsKey("mesh"))
201 {
202 mesh = (int)inst["mesh"];
203
204 if (mesh >= numberMeshs)
205 {
206 error = "Incoerent model information.";
207 return false;
208 }
209
210 // streamming cost
211
212 float sqdiam = scale.LengthSquared();
213
214 ameshCostParam curCost = meshsCosts[mesh];
215 float mesh_streaming = streamingCost(curCost, sqdiam);
216
217 meshcostdata.model_streaming_cost += mesh_streaming;
218 meshcostdata.physics_cost += curCost.physicsCost;
219 }
220 else // instance as no mesh ??
221 {
222 // to do later if needed
223 meshcostdata.model_streaming_cost += 0.5f;
224 meshcostdata.physics_cost += 1.0f;
225 }
226
227 // assume unscripted and static prim server cost
228 meshcostdata.simulation_cost += 0.5f;
229 // charge for prims creation
230 meshsfee += primCreationCost;
231 }
232
233 if (skipedSmall > 0)
234 {
235 if (skipedSmall > numberInstances / 2)
236 {
237 error = "Model contains too many prims smaller than " + PrimScaleMin.ToString() +
238 "m minimum allowed size. Please check scalling";
239 return false;
240 }
241 else
242 warning += skipedSmall.ToString() + " of the requested " +numberInstances.ToString() +
243 " model prims will not upload because they are smaller than " + PrimScaleMin.ToString() +
244 "m minimum allowed size. Please check scalling ";
245 }
246
247 if (meshcostdata.physics_cost <= meshcostdata.model_streaming_cost)
248 meshcostdata.resource_cost = meshcostdata.model_streaming_cost;
249 else
250 meshcostdata.resource_cost = meshcostdata.physics_cost;
251
252 if (meshcostdata.resource_cost < meshcostdata.simulation_cost)
253 meshcostdata.resource_cost = meshcostdata.simulation_cost;
254
255 // scale cost
256 // at this point a cost of 1.0 whould mean basic cost
257 meshsfee *= ModelMeshCostFactor;
258
259 if (meshsfee < ModelMinCostFactor)
260 meshsfee = ModelMinCostFactor;
261
262 // actually scale it to basic cost
263 meshsfee *= (float)basicCost;
264
265 meshsfee += 0.5f; // rounding
266
267 totalcost += (int)meshsfee;
268
269 // breakdown prices
270 // don't seem to be in use so removed code for now
271
272 return true;
273 }
274
275 // single mesh asset cost
276 private bool MeshCost(byte[] data, ameshCostParam cost, out string error)
277 {
278 cost.highLODSize = 0;
279 cost.medLODSize = 0;
280 cost.lowLODSize = 0;
281 cost.lowestLODSize = 0;
282 cost.physicsCost = 0.0f;
283 cost.costFee = 0.0f;
284
285 error = string.Empty;
286
287 if (data == null || data.Length == 0)
288 {
289 error = "Missing model information.";
290 return false;
291 }
292
293 OSD meshOsd = null;
294 int start = 0;
295
296 error = "Invalid model data";
297
298 using (MemoryStream ms = new MemoryStream(data))
299 {
300 try
301 {
302 OSD osd = OSDParser.DeserializeLLSDBinary(ms);
303 if (osd is OSDMap)
304 meshOsd = (OSDMap)osd;
305 else
306 return false;
307 }
308 catch (Exception e)
309 {
310 return false;
311 }
312 start = (int)ms.Position;
313 }
314
315 OSDMap map = (OSDMap)meshOsd;
316 OSDMap tmpmap;
317
318 int highlod_size = 0;
319 int medlod_size = 0;
320 int lowlod_size = 0;
321 int lowestlod_size = 0;
322 int skin_size = 0;
323
324 int hulls_size = 0;
325 int phys_nhulls;
326 int phys_hullsvertices = 0;
327
328 int physmesh_size = 0;
329 int phys_ntriangles = 0;
330
331 int submesh_offset = -1;
332
333 if (map.ContainsKey("physics_convex"))
334 {
335 tmpmap = (OSDMap)map["physics_convex"];
336 if (tmpmap.ContainsKey("offset"))
337 submesh_offset = tmpmap["offset"].AsInteger() + start;
338 if (tmpmap.ContainsKey("size"))
339 hulls_size = tmpmap["size"].AsInteger();
340 }
341
342 if (submesh_offset < 0 || hulls_size == 0)
343 {
344 error = "Missing physics_convex block";
345 return false;
346 }
347
348 if (!hulls(data, submesh_offset, hulls_size, out phys_hullsvertices, out phys_nhulls))
349 {
350 error = "Bad physics_convex block";
351 return false;
352 }
353
354 submesh_offset = -1;
355
356 // only look for LOD meshs sizes
357
358 if (map.ContainsKey("high_lod"))
359 {
360 tmpmap = (OSDMap)map["high_lod"];
361 // see at least if there is a offset for this one
362 if (tmpmap.ContainsKey("offset"))
363 submesh_offset = tmpmap["offset"].AsInteger() + start;
364 if (tmpmap.ContainsKey("size"))
365 highlod_size = tmpmap["size"].AsInteger();
366 }
367
368 if (submesh_offset < 0 || highlod_size <= 0)
369 {
370 error = "Missing high_lod block";
371 return false;
372 }
373
374 bool haveprev = true;
375
376 if (map.ContainsKey("medium_lod"))
377 {
378 tmpmap = (OSDMap)map["medium_lod"];
379 if (tmpmap.ContainsKey("size"))
380 medlod_size = tmpmap["size"].AsInteger();
381 else
382 haveprev = false;
383 }
384
385 if (haveprev && map.ContainsKey("low_lod"))
386 {
387 tmpmap = (OSDMap)map["low_lod"];
388 if (tmpmap.ContainsKey("size"))
389 lowlod_size = tmpmap["size"].AsInteger();
390 else
391 haveprev = false;
392 }
393
394 if (haveprev && map.ContainsKey("lowest_lod"))
395 {
396 tmpmap = (OSDMap)map["lowest_lod"];
397 if (tmpmap.ContainsKey("size"))
398 lowestlod_size = tmpmap["size"].AsInteger();
399 }
400
401 if (map.ContainsKey("skin"))
402 {
403 tmpmap = (OSDMap)map["skin"];
404 if (tmpmap.ContainsKey("size"))
405 skin_size = tmpmap["size"].AsInteger();
406 }
407
408 cost.highLODSize = highlod_size;
409 cost.medLODSize = medlod_size;
410 cost.lowLODSize = lowlod_size;
411 cost.lowestLODSize = lowestlod_size;
412
413 submesh_offset = -1;
414
415 tmpmap = null;
416 if(map.ContainsKey("physics_mesh"))
417 tmpmap = (OSDMap)map["physics_mesh"];
418 else if (map.ContainsKey("physics_shape")) // old naming
419 tmpmap = (OSDMap)map["physics_shape"];
420
421 if(tmpmap != null)
422 {
423 if (tmpmap.ContainsKey("offset"))
424 submesh_offset = tmpmap["offset"].AsInteger() + start;
425 if (tmpmap.ContainsKey("size"))
426 physmesh_size = tmpmap["size"].AsInteger();
427
428 if (submesh_offset >= 0 || physmesh_size > 0)
429 {
430
431 if (!submesh(data, submesh_offset, physmesh_size, out phys_ntriangles))
432 {
433 error = "Model data parsing error";
434 return false;
435 }
436 }
437 }
438
439 // upload is done in convex shape type so only one hull
440 phys_hullsvertices++;
441 cost.physicsCost = 0.04f * phys_hullsvertices;
442
443 float sfee;
444
445 sfee = data.Length; // start with total compressed data size
446
447 // penalize lod meshs that should be more builder optimized
448 sfee += medSizeWth * medlod_size;
449 sfee += lowSizeWth * lowlod_size;
450 sfee += lowestSizeWth * lowlod_size;
451
452 // physics
453 // favor potencial optimized meshs versus automatic decomposition
454 if (physmesh_size != 0)
455 sfee += physMeshSizeWth * (physmesh_size + hulls_size / 4); // reduce cost of mandatory convex hull
456 else
457 sfee += physHullSizeWth * hulls_size;
458
459 // bytes to money
460 sfee *= bytecost;
461
462 cost.costFee = sfee;
463 return true;
464 }
465
466 // parses a LOD or physics mesh component
467 private bool submesh(byte[] data, int offset, int size, out int ntriangles)
468 {
469 ntriangles = 0;
470
471 OSD decodedMeshOsd = new OSD();
472 byte[] meshBytes = new byte[size];
473 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
474 try
475 {
476 using (MemoryStream inMs = new MemoryStream(meshBytes))
477 {
478 using (MemoryStream outMs = new MemoryStream())
479 {
480 using (ZOutputStream zOut = new ZOutputStream(outMs))
481 {
482 byte[] readBuffer = new byte[4096];
483 int readLen = 0;
484 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
485 {
486 zOut.Write(readBuffer, 0, readLen);
487 }
488 zOut.Flush();
489 outMs.Seek(0, SeekOrigin.Begin);
490
491 byte[] decompressedBuf = outMs.GetBuffer();
492 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
493 }
494 }
495 }
496 }
497 catch (Exception e)
498 {
499 return false;
500 }
501
502 OSDArray decodedMeshOsdArray = null;
503 if ((!decodedMeshOsd is OSDArray))
504 return false;
505
506 byte[] dummy;
507
508 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
509 foreach (OSD subMeshOsd in decodedMeshOsdArray)
510 {
511 if (subMeshOsd is OSDMap)
512 {
513 OSDMap subtmpmap = (OSDMap)subMeshOsd;
514 if (subtmpmap.ContainsKey("NoGeometry") && ((OSDBoolean)subtmpmap["NoGeometry"]))
515 continue;
516
517 if (!subtmpmap.ContainsKey("Position"))
518 return false;
519
520 if (subtmpmap.ContainsKey("TriangleList"))
521 {
522 dummy = subtmpmap["TriangleList"].AsBinary();
523 ntriangles += dummy.Length / bytesPerCoord;
524 }
525 else
526 return false;
527 }
528 }
529
530 return true;
531 }
532
533 // parses convex hulls component
534 private bool hulls(byte[] data, int offset, int size, out int nvertices, out int nhulls)
535 {
536 nvertices = 0;
537 nhulls = 1;
538
539 OSD decodedMeshOsd = new OSD();
540 byte[] meshBytes = new byte[size];
541 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
542 try
543 {
544 using (MemoryStream inMs = new MemoryStream(meshBytes))
545 {
546 using (MemoryStream outMs = new MemoryStream())
547 {
548 using (ZOutputStream zOut = new ZOutputStream(outMs))
549 {
550 byte[] readBuffer = new byte[4096];
551 int readLen = 0;
552 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
553 {
554 zOut.Write(readBuffer, 0, readLen);
555 }
556 zOut.Flush();
557 outMs.Seek(0, SeekOrigin.Begin);
558
559 byte[] decompressedBuf = outMs.GetBuffer();
560 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
561 }
562 }
563 }
564 }
565 catch (Exception e)
566 {
567 return false;
568 }
569
570 OSDMap cmap = (OSDMap)decodedMeshOsd;
571 if (cmap == null)
572 return false;
573
574 byte[] dummy;
575
576 // must have one of this
577 if (cmap.ContainsKey("BoundingVerts"))
578 {
579 dummy = cmap["BoundingVerts"].AsBinary();
580 nvertices = dummy.Length / bytesPerCoord;
581 }
582 else
583 return false;
584
585/* upload is done with convex shape type
586 if (cmap.ContainsKey("HullList"))
587 {
588 dummy = cmap["HullList"].AsBinary();
589 nhulls += dummy.Length;
590 }
591
592
593 if (cmap.ContainsKey("Positions"))
594 {
595 dummy = cmap["Positions"].AsBinary();
596 nvertices = dummy.Length / bytesPerCoord;
597 }
598 */
599
600 return true;
601 }
602
603 // returns streaming cost from on mesh LODs sizes in curCost and square of prim size length
604 private float streamingCost(ameshCostParam curCost, float sqdiam)
605 {
606 // compute efective areas
607 float ma = 262144f;
608
609 float mh = sqdiam * highLodFactor;
610 if (mh > ma)
611 mh = ma;
612 float mm = sqdiam * midLodFactor;
613 if (mm > ma)
614 mm = ma;
615
616 float ml = sqdiam * lowLodFactor;
617 if (ml > ma)
618 ml = ma;
619
620 float mlst = ma;
621
622 mlst -= ml;
623 ml -= mm;
624 mm -= mh;
625
626 if (mlst < 1.0f)
627 mlst = 1.0f;
628 if (ml < 1.0f)
629 ml = 1.0f;
630 if (mm < 1.0f)
631 mm = 1.0f;
632 if (mh < 1.0f)
633 mh = 1.0f;
634
635 ma = mlst + ml + mm + mh;
636
637 // get LODs compressed sizes
638 // giving 384 bytes bonus
639 int lst = curCost.lowestLODSize - 384;
640 int l = curCost.lowLODSize - 384;
641 int m = curCost.medLODSize - 384;
642 int h = curCost.highLODSize - 384;
643
644 // use previus higher LOD size on missing ones
645 if (m <= 0)
646 m = h;
647 if (l <= 0)
648 l = m;
649 if (lst <= 0)
650 lst = l;
651
652 // force minumum sizes
653 if (lst < 16)
654 lst = 16;
655 if (l < 16)
656 l = 16;
657 if (m < 16)
658 m = 16;
659 if (h < 16)
660 h = 16;
661
662 // compute cost weighted by relative effective areas
663 float cost = (float)lst * mlst + (float)l * ml + (float)m * mm + (float)h * mh;
664 cost /= ma;
665
666 cost *= 0.004f; // overall tunning parameter
667
668 return cost;
669 }
670 }
671}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index 47cb049..5bbdce8 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -368,7 +368,7 @@ namespace OpenSim.Region.ClientStack.Linden
368 // TODO: Add EventQueueGet name/description for diagnostics 368 // TODO: Add EventQueueGet name/description for diagnostics
369 MainServer.Instance.AddPollServiceHTTPHandler( 369 MainServer.Instance.AddPollServiceHTTPHandler(
370 eventQueueGetPath, 370 eventQueueGetPath,
371 new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID)); 371 new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID, 1000));
372 372
373// m_log.DebugFormat( 373// m_log.DebugFormat(
374// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}", 374// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}",
@@ -410,7 +410,7 @@ namespace OpenSim.Region.ClientStack.Linden
410 } 410 }
411 } 411 }
412 412
413 public Hashtable GetEvents(UUID requestID, UUID pAgentId, string request) 413 public Hashtable GetEvents(UUID requestID, UUID pAgentId)
414 { 414 {
415 if (DebugLevel >= 2) 415 if (DebugLevel >= 2)
416 m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName); 416 m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName);
@@ -822,5 +822,13 @@ namespace OpenSim.Region.ClientStack.Linden
822 { 822 {
823 return EventQueueHelper.BuildEvent(eventName, eventBody); 823 return EventQueueHelper.BuildEvent(eventName, eventBody);
824 } 824 }
825
826 public void partPhysicsProperties(uint localID, byte physhapetype,
827 float density, float friction, float bounce, float gravmod,UUID avatarID)
828 {
829 OSD item = EventQueueHelper.partPhysicsProperties(localID, physhapetype,
830 density, friction, bounce, gravmod);
831 Enqueue(item, avatarID);
832 }
825 } 833 }
826} 834}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
index 3f49aba..7dcf137 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
@@ -151,6 +151,12 @@ namespace OpenSim.Region.ClientStack.Linden
151 ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, 151 ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
152 uint locationID, uint flags, string capsURL, UUID agentID) 152 uint locationID, uint flags, string capsURL, UUID agentID)
153 { 153 {
154 // not sure why flags get overwritten here
155 if ((flags & (uint)TeleportFlags.IsFlying) != 0)
156 flags = (uint)TeleportFlags.ViaLocation | (uint)TeleportFlags.IsFlying;
157 else
158 flags = (uint)TeleportFlags.ViaLocation;
159
154 OSDMap info = new OSDMap(); 160 OSDMap info = new OSDMap();
155 info.Add("AgentID", OSD.FromUUID(agentID)); 161 info.Add("AgentID", OSD.FromUUID(agentID));
156 info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this? 162 info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this?
@@ -159,7 +165,8 @@ namespace OpenSim.Region.ClientStack.Linden
159 info.Add("SimAccess", OSD.FromInteger(simAccess)); 165 info.Add("SimAccess", OSD.FromInteger(simAccess));
160 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes())); 166 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes()));
161 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port)); 167 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port));
162 info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation 168// info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation
169 info.Add("TeleportFlags", OSD.FromUInteger(flags));
163 170
164 OSDArray infoArr = new OSDArray(); 171 OSDArray infoArr = new OSDArray();
165 infoArr.Add(info); 172 infoArr.Add(info);
@@ -395,5 +402,25 @@ namespace OpenSim.Region.ClientStack.Linden
395 return message; 402 return message;
396 } 403 }
397 404
405 public static OSD partPhysicsProperties(uint localID, byte physhapetype,
406 float density, float friction, float bounce, float gravmod)
407 {
408
409 OSDMap physinfo = new OSDMap(6);
410 physinfo["LocalID"] = localID;
411 physinfo["Density"] = density;
412 physinfo["Friction"] = friction;
413 physinfo["GravityMultiplier"] = gravmod;
414 physinfo["Restitution"] = bounce;
415 physinfo["PhysicsShapeType"] = (int)physhapetype;
416
417 OSDArray array = new OSDArray(1);
418 array.Add(physinfo);
419
420 OSDMap llsdBody = new OSDMap(1);
421 llsdBody.Add("ObjectData", array);
422
423 return BuildEvent("ObjectPhysicsProperties", llsdBody);
424 }
398 } 425 }
399} 426}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index 5ae9cc3..d1a1583 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,64 +42,81 @@ 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{
53 49
54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 50 /// <summary>
51 /// This module implements both WebFetchTextureDescendents and FetchTextureDescendents2 capabilities.
52 /// </summary>
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")]
55 public class GetTextureModule : INonSharedRegionModule 54 public class GetTextureModule : INonSharedRegionModule
56 { 55 {
57// private static readonly ILog m_log = 56
58// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 57 struct aPollRequest
59 58 {
59 public PollServiceTextureEventArgs thepoll;
60 public UUID reqID;
61 public Hashtable request;
62 }
63
64 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
65
60 private Scene m_scene; 66 private Scene m_scene;
61 private IAssetService m_assetService;
62 67
63 private bool m_Enabled = false; 68 private static GetTextureHandler m_getTextureHandler;
69
70 private IAssetService m_assetService = null;
64 71
65 // TODO: Change this to a config option 72 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
66 const string REDIRECT_URL = null; 73 private static Thread[] m_workerThreads = null;
67 74
68 private string m_URL; 75 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
76 new OpenMetaverse.BlockingQueue<aPollRequest>();
69 77
70 #region ISharedRegionModule Members 78 #region ISharedRegionModule Members
71 79
72 public void Initialise(IConfigSource source) 80 public void Initialise(IConfigSource source)
73 { 81 {
74 IConfig config = source.Configs["ClientStack.LindenCaps"];
75 if (config == null)
76 return;
77
78 m_URL = config.GetString("Cap_GetTexture", string.Empty);
79 // Cap doesn't exist
80 if (m_URL != string.Empty)
81 m_Enabled = true;
82 } 82 }
83 83
84 public void AddRegion(Scene s) 84 public void AddRegion(Scene s)
85 { 85 {
86 if (!m_Enabled)
87 return;
88
89 m_scene = s; 86 m_scene = s;
87 m_assetService = s.AssetService;
90 } 88 }
91 89
92 public void RemoveRegion(Scene s) 90 public void RemoveRegion(Scene s)
93 { 91 {
94 if (!m_Enabled)
95 return;
96
97 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 92 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
93 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
98 m_scene = null; 94 m_scene = null;
99 } 95 }
100 96
101 public void RegionLoaded(Scene s) 97 public void RegionLoaded(Scene s)
102 { 98 {
103 if (!m_Enabled) 99 // We'll reuse the same handler for all requests.
104 return; 100 m_getTextureHandler = new GetTextureHandler(m_assetService);
105 101
106 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
107 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 102 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
103 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
104
105 if (m_workerThreads == null)
106 {
107 m_workerThreads = new Thread[2];
108
109 for (uint i = 0; i < 2; i++)
110 {
111 m_workerThreads[i] = Watchdog.StartThread(DoTextureRequests,
112 String.Format("TextureWorkerThread{0}", i),
113 ThreadPriority.Normal,
114 false,
115 false,
116 null,
117 int.MaxValue);
118 }
119 }
108 } 120 }
109 121
110 public void PostInitialise() 122 public void PostInitialise()
@@ -122,24 +134,152 @@ namespace OpenSim.Region.ClientStack.Linden
122 134
123 #endregion 135 #endregion
124 136
125 public void RegisterCaps(UUID agentID, Caps caps) 137 ~GetTextureModule()
138 {
139 foreach (Thread t in m_workerThreads)
140 Watchdog.AbortThread(t.ManagedThreadId);
141
142 }
143
144 private class PollServiceTextureEventArgs : PollServiceEventArgs
145 {
146 private List<Hashtable> requests =
147 new List<Hashtable>();
148 private Dictionary<UUID, Hashtable> responses =
149 new Dictionary<UUID, Hashtable>();
150
151 private Scene m_scene;
152
153 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
154 base(null, null, null, null, pId, int.MaxValue)
155 {
156 m_scene = scene;
157
158 HasEvents = (x, y) =>
159 {
160 lock (responses)
161 return responses.ContainsKey(x);
162 };
163 GetEvents = (x, y) =>
164 {
165 lock (responses)
166 {
167 try
168 {
169 return responses[x];
170 }
171 finally
172 {
173 responses.Remove(x);
174 }
175 }
176 };
177
178 Request = (x, y) =>
179 {
180 aPollRequest reqinfo = new aPollRequest();
181 reqinfo.thepoll = this;
182 reqinfo.reqID = x;
183 reqinfo.request = y;
184
185 m_queue.Enqueue(reqinfo);
186 };
187
188 // this should never happen except possible on shutdown
189 NoEvents = (x, y) =>
190 {
191/*
192 lock (requests)
193 {
194 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
195 requests.Remove(request);
196 }
197*/
198 Hashtable response = new Hashtable();
199
200 response["int_response_code"] = 500;
201 response["str_response_string"] = "Script timeout";
202 response["content_type"] = "text/plain";
203 response["keepalive"] = false;
204 response["reusecontext"] = false;
205
206 return response;
207 };
208 }
209
210 public void Process(aPollRequest requestinfo)
211 {
212 Hashtable response;
213
214 UUID requestID = requestinfo.reqID;
215
216 // If the avatar is gone, don't bother to get the texture
217 if (m_scene.GetScenePresence(Id) == null)
218 {
219 response = new Hashtable();
220
221 response["int_response_code"] = 500;
222 response["str_response_string"] = "Script timeout";
223 response["content_type"] = "text/plain";
224 response["keepalive"] = false;
225 response["reusecontext"] = false;
226
227 lock (responses)
228 responses[requestID] = response;
229
230 return;
231 }
232
233 response = m_getTextureHandler.Handle(requestinfo.request);
234 lock (responses)
235 responses[requestID] = response;
236 }
237 }
238
239 private void RegisterCaps(UUID agentID, Caps caps)
126 { 240 {
127 UUID capID = UUID.Random(); 241 string capUrl = "/CAPS/" + UUID.Random() + "/";
242
243 // Register this as a poll service
244 PollServiceTextureEventArgs args = new PollServiceTextureEventArgs(agentID, m_scene);
245
246 args.Type = PollServiceEventArgs.EventType.Texture;
247 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
128 248
129 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); 249 string hostName = m_scene.RegionInfo.ExternalHostName;
130 if (m_URL == "localhost") 250 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
251 string protocol = "http";
252
253 if (MainServer.Instance.UseSSL)
131 { 254 {
132// m_log.DebugFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 255 hostName = MainServer.Instance.SSLCommonName;
133 caps.RegisterHandler( 256 port = MainServer.Instance.SSLPort;
134 "GetTexture", 257 protocol = "https";
135 new GetTextureHandler("/CAPS/" + capID + "/", m_assetService, "GetTexture", agentID.ToString()));
136 } 258 }
137 else 259 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
260
261 m_capsDict[agentID] = capUrl;
262 }
263
264 private void DeregisterCaps(UUID agentID, Caps caps)
265 {
266 string capUrl;
267
268 if (m_capsDict.TryGetValue(agentID, out capUrl))
138 { 269 {
139// m_log.DebugFormat("[GETTEXTURE]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName); 270 MainServer.Instance.RemoveHTTPHandler("", capUrl);
140 caps.RegisterHandler("GetTexture", m_URL); 271 m_capsDict.Remove(agentID);
141 } 272 }
142 } 273 }
143 274
275 private void DoTextureRequests()
276 {
277 while (true)
278 {
279 aPollRequest poolreq = m_queue.Dequeue();
280
281 poolreq.thepoll.Process(poolreq);
282 }
283 }
144 } 284 }
145} 285}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
index 44a6883..0251ac4 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(m_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"] = m_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();
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs
deleted file mode 100644
index 52c4f44..0000000
--- a/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs
+++ /dev/null
@@ -1,296 +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;
47
48namespace OpenSim.Region.ClientStack.Linden
49{
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
51 public class NewFileAgentInventoryVariablePriceModule : INonSharedRegionModule
52 {
53// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
55 private Scene m_scene;
56// private IAssetService m_assetService;
57 private bool m_dumpAssetsToFile = false;
58 private bool m_enabled = true;
59 private int m_levelUpload = 0;
60
61 #region IRegionModuleBase Members
62
63
64 public Type ReplaceableInterface
65 {
66 get { return null; }
67 }
68
69 public void Initialise(IConfigSource source)
70 {
71 IConfig meshConfig = source.Configs["Mesh"];
72 if (meshConfig == null)
73 return;
74
75 m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true);
76 m_levelUpload = meshConfig.GetInt("LevelUpload", 0);
77 }
78
79 public void AddRegion(Scene pScene)
80 {
81 m_scene = pScene;
82 }
83
84 public void RemoveRegion(Scene scene)
85 {
86
87 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
88 m_scene = null;
89 }
90
91 public void RegionLoaded(Scene scene)
92 {
93
94// m_assetService = m_scene.RequestModuleInterface<IAssetService>();
95 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
96 }
97
98 #endregion
99
100
101 #region IRegionModule Members
102
103
104
105 public void Close() { }
106
107 public string Name { get { return "NewFileAgentInventoryVariablePriceModule"; } }
108
109
110 public void RegisterCaps(UUID agentID, Caps caps)
111 {
112 if(!m_enabled)
113 return;
114
115 UUID capID = UUID.Random();
116
117// m_log.Debug("[NEW FILE AGENT INVENTORY VARIABLE PRICE]: /CAPS/" + capID);
118 caps.RegisterHandler(
119 "NewFileAgentInventoryVariablePrice",
120 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDNewFileAngentInventoryVariablePriceReplyResponse>(
121 "POST",
122 "/CAPS/" + capID.ToString(),
123 req => NewAgentInventoryRequest(req, agentID),
124 "NewFileAgentInventoryVariablePrice",
125 agentID.ToString()));
126 }
127
128 #endregion
129
130 public LLSDNewFileAngentInventoryVariablePriceReplyResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest, UUID agentID)
131 {
132 //TODO: The Mesh uploader uploads many types of content. If you're going to implement a Money based limit
133 // you need to be aware of this
134
135 //if (llsdRequest.asset_type == "texture" ||
136 // llsdRequest.asset_type == "animation" ||
137 // llsdRequest.asset_type == "sound")
138 // {
139 // check user level
140
141 ScenePresence avatar = null;
142 IClientAPI client = null;
143 m_scene.TryGetScenePresence(agentID, out avatar);
144
145 if (avatar != null)
146 {
147 client = avatar.ControllingClient;
148
149 if (avatar.UserLevel < m_levelUpload)
150 {
151 if (client != null)
152 client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false);
153
154 LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
155 errorResponse.rsvp = "";
156 errorResponse.state = "error";
157 return errorResponse;
158 }
159 }
160
161 // check funds
162 IMoneyModule mm = m_scene.RequestModuleInterface<IMoneyModule>();
163
164 if (mm != null)
165 {
166 if (!mm.UploadCovered(agentID, mm.UploadCharge))
167 {
168 if (client != null)
169 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
170
171 LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
172 errorResponse.rsvp = "";
173 errorResponse.state = "error";
174 return errorResponse;
175 }
176 }
177
178 // }
179
180 string assetName = llsdRequest.name;
181 string assetDes = llsdRequest.description;
182 string capsBase = "/CAPS/NewFileAgentInventoryVariablePrice/";
183 UUID newAsset = UUID.Random();
184 UUID newInvItem = UUID.Random();
185 UUID parentFolder = llsdRequest.folder_id;
186 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000") + "/";
187
188 AssetUploader uploader =
189 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
190 llsdRequest.asset_type, capsBase + uploaderPath, MainServer.Instance, m_dumpAssetsToFile);
191
192 MainServer.Instance.AddStreamHandler(
193 new BinaryStreamHandler(
194 "POST",
195 capsBase + uploaderPath,
196 uploader.uploaderCaps,
197 "NewFileAgentInventoryVariablePrice",
198 agentID.ToString()));
199
200 string protocol = "http://";
201
202 if (MainServer.Instance.UseSSL)
203 protocol = "https://";
204
205 string uploaderURL = protocol + m_scene.RegionInfo.ExternalHostName + ":" + MainServer.Instance.Port.ToString() + capsBase +
206 uploaderPath;
207
208
209 LLSDNewFileAngentInventoryVariablePriceReplyResponse uploadResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
210
211 uploadResponse.rsvp = uploaderURL;
212 uploadResponse.state = "upload";
213 uploadResponse.resource_cost = 0;
214 uploadResponse.upload_price = 0;
215
216 uploader.OnUpLoad += //UploadCompleteHandler;
217
218 delegate(
219 string passetName, string passetDescription, UUID passetID,
220 UUID pinventoryItem, UUID pparentFolder, byte[] pdata, string pinventoryType,
221 string passetType)
222 {
223 UploadCompleteHandler(passetName, passetDescription, passetID,
224 pinventoryItem, pparentFolder, pdata, pinventoryType,
225 passetType,agentID);
226 };
227
228 return uploadResponse;
229 }
230
231 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
232 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
233 string assetType,UUID AgentID)
234 {
235// m_log.DebugFormat(
236// "[NEW FILE AGENT INVENTORY VARIABLE PRICE MODULE]: Upload complete for {0}", inventoryItem);
237
238 sbyte assType = 0;
239 sbyte inType = 0;
240
241 if (inventoryType == "sound")
242 {
243 inType = 1;
244 assType = 1;
245 }
246 else if (inventoryType == "animation")
247 {
248 inType = 19;
249 assType = 20;
250 }
251 else if (inventoryType == "wearable")
252 {
253 inType = 18;
254 switch (assetType)
255 {
256 case "bodypart":
257 assType = 13;
258 break;
259 case "clothing":
260 assType = 5;
261 break;
262 }
263 }
264 else if (inventoryType == "mesh")
265 {
266 inType = (sbyte)InventoryType.Mesh;
267 assType = (sbyte)AssetType.Mesh;
268 }
269
270 AssetBase asset;
271 asset = new AssetBase(assetID, assetName, assType, AgentID.ToString());
272 asset.Data = data;
273
274 if (m_scene.AssetService != null)
275 m_scene.AssetService.Store(asset);
276
277 InventoryItemBase item = new InventoryItemBase();
278 item.Owner = AgentID;
279 item.CreatorId = AgentID.ToString();
280 item.ID = inventoryItem;
281 item.AssetID = asset.FullID;
282 item.Description = assetDescription;
283 item.Name = assetName;
284 item.AssetType = assType;
285 item.InvType = inType;
286 item.Folder = parentFolder;
287 item.CurrentPermissions
288 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
289 item.BasePermissions = (uint)PermissionMask.All;
290 item.EveryOnePermissions = 0;
291 item.NextPermissions = (uint)PermissionMask.All;
292 item.CreationDate = Util.UnixTimeSinceEpoch();
293 m_scene.AddInventoryItem(item);
294 }
295 }
296}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
index 17c7270..bac71b0 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);
@@ -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/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 2359bd6..0caeddf 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -27,18 +27,22 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
30using System.Reflection; 31using System.Reflection;
32using System.Threading;
31using log4net; 33using log4net;
32using Nini.Config; 34using Nini.Config;
33using Mono.Addins; 35using Mono.Addins;
34using OpenMetaverse; 36using OpenMetaverse;
35using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Framework.Servers;
36using OpenSim.Framework.Servers.HttpServer; 39using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Region.Framework.Interfaces; 40using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces; 42using OpenSim.Services.Interfaces;
40using Caps = OpenSim.Framework.Capabilities.Caps; 43using Caps = OpenSim.Framework.Capabilities.Caps;
41using OpenSim.Capabilities.Handlers; 44using OpenSim.Capabilities.Handlers;
45using OpenSim.Framework.Monitoring;
42 46
43namespace OpenSim.Region.ClientStack.Linden 47namespace OpenSim.Region.ClientStack.Linden
44{ 48{
@@ -48,67 +52,72 @@ namespace OpenSim.Region.ClientStack.Linden
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
49 public class WebFetchInvDescModule : INonSharedRegionModule 53 public class WebFetchInvDescModule : INonSharedRegionModule
50 { 54 {
51// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 struct aPollRequest
56 {
57 public PollServiceInventoryEventArgs thepoll;
58 public UUID reqID;
59 public Hashtable request;
60 }
61
62 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 63
53 private Scene m_scene; 64 private Scene m_scene;
54 65
55 private IInventoryService m_InventoryService; 66 private IInventoryService m_InventoryService;
56 private ILibraryService m_LibraryService; 67 private ILibraryService m_LibraryService;
57 68
58 private bool m_Enabled; 69 private static WebFetchInvDescHandler m_webFetchHandler;
59 70
60 private string m_fetchInventoryDescendents2Url; 71 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
61 private string m_webFetchInventoryDescendentsUrl; 72 private static Thread[] m_workerThreads = null;
62 73
63 private WebFetchInvDescHandler m_webFetchHandler; 74 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
75 new OpenMetaverse.BlockingQueue<aPollRequest>();
64 76
65 #region ISharedRegionModule Members 77 #region ISharedRegionModule Members
66 78
67 public void Initialise(IConfigSource source) 79 public void Initialise(IConfigSource source)
68 { 80 {
69 IConfig config = source.Configs["ClientStack.LindenCaps"];
70 if (config == null)
71 return;
72
73 m_fetchInventoryDescendents2Url = config.GetString("Cap_FetchInventoryDescendents2", string.Empty);
74 m_webFetchInventoryDescendentsUrl = config.GetString("Cap_WebFetchInventoryDescendents", string.Empty);
75
76 if (m_fetchInventoryDescendents2Url != string.Empty || m_webFetchInventoryDescendentsUrl != string.Empty)
77 {
78 m_Enabled = true;
79 }
80 } 81 }
81 82
82 public void AddRegion(Scene s) 83 public void AddRegion(Scene s)
83 { 84 {
84 if (!m_Enabled)
85 return;
86
87 m_scene = s; 85 m_scene = s;
88 } 86 }
89 87
90 public void RemoveRegion(Scene s) 88 public void RemoveRegion(Scene s)
91 { 89 {
92 if (!m_Enabled)
93 return;
94
95 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 90 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
91 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
96 m_scene = null; 92 m_scene = null;
97 } 93 }
98 94
99 public void RegionLoaded(Scene s) 95 public void RegionLoaded(Scene s)
100 { 96 {
101 if (!m_Enabled)
102 return;
103
104 m_InventoryService = m_scene.InventoryService; 97 m_InventoryService = m_scene.InventoryService;
105 m_LibraryService = m_scene.LibraryService; 98 m_LibraryService = m_scene.LibraryService;
106 99
107 // We'll reuse the same handler for all requests. 100 // We'll reuse the same handler for all requests.
108 if (m_fetchInventoryDescendents2Url == "localhost" || m_webFetchInventoryDescendentsUrl == "localhost") 101 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
109 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
110 102
111 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 103 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
104 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
105
106 if (m_workerThreads == null)
107 {
108 m_workerThreads = new Thread[2];
109
110 for (uint i = 0; i < 2; i++)
111 {
112 m_workerThreads[i] = Watchdog.StartThread(DoInventoryRequests,
113 String.Format("InventoryWorkerThread{0}", i),
114 ThreadPriority.Normal,
115 false,
116 true,
117 null,
118 int.MaxValue);
119 }
120 }
112 } 121 }
113 122
114 public void PostInitialise() 123 public void PostInitialise()
@@ -126,43 +135,130 @@ namespace OpenSim.Region.ClientStack.Linden
126 135
127 #endregion 136 #endregion
128 137
129 private void RegisterCaps(UUID agentID, Caps caps) 138 ~WebFetchInvDescModule()
130 { 139 {
131 if (m_webFetchInventoryDescendentsUrl != "") 140 foreach (Thread t in m_workerThreads)
132 RegisterFetchCap(agentID, caps, "WebFetchInventoryDescendents", m_webFetchInventoryDescendentsUrl); 141 Watchdog.AbortThread(t.ManagedThreadId);
133
134 if (m_fetchInventoryDescendents2Url != "")
135 RegisterFetchCap(agentID, caps, "FetchInventoryDescendents2", m_fetchInventoryDescendents2Url);
136 } 142 }
137 143
138 private void RegisterFetchCap(UUID agentID, Caps caps, string capName, string url) 144 private class PollServiceInventoryEventArgs : PollServiceEventArgs
139 { 145 {
140 string capUrl; 146 private Dictionary<UUID, Hashtable> responses =
147 new Dictionary<UUID, Hashtable>();
148
149 public PollServiceInventoryEventArgs(UUID pId) :
150 base(null, null, null, null, pId, int.MaxValue)
151 {
152 HasEvents = (x, y) => { lock (responses) return responses.ContainsKey(x); };
153 GetEvents = (x, y) =>
154 {
155 lock (responses)
156 {
157 try
158 {
159 return responses[x];
160 }
161 finally
162 {
163 responses.Remove(x);
164 }
165 }
166 };
167
168 Request = (x, y) =>
169 {
170 aPollRequest reqinfo = new aPollRequest();
171 reqinfo.thepoll = this;
172 reqinfo.reqID = x;
173 reqinfo.request = y;
174
175 m_queue.Enqueue(reqinfo);
176 };
177
178 NoEvents = (x, y) =>
179 {
180/*
181 lock (requests)
182 {
183 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
184 requests.Remove(request);
185 }
186*/
187 Hashtable response = new Hashtable();
188
189 response["int_response_code"] = 500;
190 response["str_response_string"] = "Script timeout";
191 response["content_type"] = "text/plain";
192 response["keepalive"] = false;
193 response["reusecontext"] = false;
194
195 return response;
196 };
197 }
141 198
142 if (url == "localhost") 199 public void Process(aPollRequest requestinfo)
143 { 200 {
144 capUrl = "/CAPS/" + UUID.Random(); 201 UUID requestID = requestinfo.reqID;
202
203 Hashtable response = new Hashtable();
204
205 response["int_response_code"] = 200;
206 response["content_type"] = "text/plain";
207 response["keepalive"] = false;
208 response["reusecontext"] = false;
145 209
146 IRequestHandler reqHandler 210 response["str_response_string"] = m_webFetchHandler.FetchInventoryDescendentsRequest(
147 = new RestStreamHandler( 211 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
148 "POST",
149 capUrl,
150 m_webFetchHandler.FetchInventoryDescendentsRequest,
151 "FetchInventoryDescendents2",
152 agentID.ToString());
153 212
154 caps.RegisterHandler(capName, reqHandler); 213 lock (responses)
214 responses[requestID] = response;
155 } 215 }
156 else 216 }
217
218 private void RegisterCaps(UUID agentID, Caps caps)
219 {
220 string capUrl = "/CAPS/" + UUID.Random() + "/";
221
222 // Register this as a poll service
223 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(agentID);
224
225 args.Type = PollServiceEventArgs.EventType.Inventory;
226 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
227
228 string hostName = m_scene.RegionInfo.ExternalHostName;
229 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
230 string protocol = "http";
231
232 if (MainServer.Instance.UseSSL)
157 { 233 {
158 capUrl = url; 234 hostName = MainServer.Instance.SSLCommonName;
235 port = MainServer.Instance.SSLPort;
236 protocol = "https";
237 }
238 caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
239
240 m_capsDict[agentID] = capUrl;
241 }
159 242
160 caps.RegisterHandler(capName, capUrl); 243 private void DeregisterCaps(UUID agentID, Caps caps)
244 {
245 string capUrl;
246
247 if (m_capsDict.TryGetValue(agentID, out capUrl))
248 {
249 MainServer.Instance.RemoveHTTPHandler("", capUrl);
250 m_capsDict.Remove(agentID);
161 } 251 }
252 }
162 253
163// m_log.DebugFormat( 254 private void DoInventoryRequests()
164// "[WEB FETCH INV DESC MODULE]: Registered capability {0} at {1} in region {2} for {3}", 255 {
165// capName, capUrl, m_scene.RegionInfo.RegionName, agentID); 256 while (true)
257 {
258 aPollRequest poolreq = m_queue.Dequeue();
259
260 poolreq.thepoll.Process(poolreq);
261 }
166 } 262 }
167 } 263 }
168} \ No newline at end of file 264}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
index afbe56b..3995620 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
@@ -234,6 +234,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
234 m_stopPacket = TexturePacketCount(); 234 m_stopPacket = TexturePacketCount();
235 } 235 }
236 236
237 //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way)
238 if (m_stopPacket == 1 && m_layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++;
239
237 m_currentPacket = StartPacket; 240 m_currentPacket = StartPacket;
238 } 241 }
239 } 242 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 65daca0..f80a00f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -114,6 +114,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
114 public event AvatarPickerRequest OnAvatarPickerRequest; 114 public event AvatarPickerRequest OnAvatarPickerRequest;
115 public event StartAnim OnStartAnim; 115 public event StartAnim OnStartAnim;
116 public event StopAnim OnStopAnim; 116 public event StopAnim OnStopAnim;
117 public event ChangeAnim OnChangeAnim;
117 public event Action<IClientAPI> OnRequestAvatarsData; 118 public event Action<IClientAPI> OnRequestAvatarsData;
118 public event LinkObjects OnLinkObjects; 119 public event LinkObjects OnLinkObjects;
119 public event DelinkObjects OnDelinkObjects; 120 public event DelinkObjects OnDelinkObjects;
@@ -141,6 +142,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
141 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; 142 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
142 public event UpdatePrimFlags OnUpdatePrimFlags; 143 public event UpdatePrimFlags OnUpdatePrimFlags;
143 public event UpdatePrimTexture OnUpdatePrimTexture; 144 public event UpdatePrimTexture OnUpdatePrimTexture;
145 public event ClientChangeObject onClientChangeObject;
144 public event UpdateVector OnUpdatePrimGroupPosition; 146 public event UpdateVector OnUpdatePrimGroupPosition;
145 public event UpdateVector OnUpdatePrimSinglePosition; 147 public event UpdateVector OnUpdatePrimSinglePosition;
146 public event UpdatePrimRotation OnUpdatePrimGroupRotation; 148 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
@@ -174,6 +176,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
174 public event RequestTaskInventory OnRequestTaskInventory; 176 public event RequestTaskInventory OnRequestTaskInventory;
175 public event UpdateInventoryItem OnUpdateInventoryItem; 177 public event UpdateInventoryItem OnUpdateInventoryItem;
176 public event CopyInventoryItem OnCopyInventoryItem; 178 public event CopyInventoryItem OnCopyInventoryItem;
179 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
177 public event MoveInventoryItem OnMoveInventoryItem; 180 public event MoveInventoryItem OnMoveInventoryItem;
178 public event RemoveInventoryItem OnRemoveInventoryItem; 181 public event RemoveInventoryItem OnRemoveInventoryItem;
179 public event RemoveInventoryFolder OnRemoveInventoryFolder; 182 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -272,7 +275,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
272 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 275 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
273 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 276 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
274 public event ClassifiedDelete OnClassifiedDelete; 277 public event ClassifiedDelete OnClassifiedDelete;
275 public event ClassifiedDelete OnClassifiedGodDelete; 278 public event ClassifiedGodDelete OnClassifiedGodDelete;
276 public event EventNotificationAddRequest OnEventNotificationAddRequest; 279 public event EventNotificationAddRequest OnEventNotificationAddRequest;
277 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 280 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
278 public event EventGodDelete OnEventGodDelete; 281 public event EventGodDelete OnEventGodDelete;
@@ -303,6 +306,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
303 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 306 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
304 public event SimWideDeletesDelegate OnSimWideDeletes; 307 public event SimWideDeletesDelegate OnSimWideDeletes;
305 public event SendPostcard OnSendPostcard; 308 public event SendPostcard OnSendPostcard;
309 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
306 public event MuteListEntryUpdate OnUpdateMuteListEntry; 310 public event MuteListEntryUpdate OnUpdateMuteListEntry;
307 public event MuteListEntryRemove OnRemoveMuteListEntry; 311 public event MuteListEntryRemove OnRemoveMuteListEntry;
308 public event GodlikeMessage onGodlikeMessage; 312 public event GodlikeMessage onGodlikeMessage;
@@ -341,6 +345,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
341 private Prioritizer m_prioritizer; 345 private Prioritizer m_prioritizer;
342 private bool m_disableFacelights = false; 346 private bool m_disableFacelights = false;
343 347
348 private const uint MaxTransferBytesPerPacket = 600;
349
350
344 /// <value> 351 /// <value>
345 /// List used in construction of data blocks for an object update packet. This is to stop us having to 352 /// List used in construction of data blocks for an object update packet. This is to stop us having to
346 /// continually recreate it. 353 /// continually recreate it.
@@ -352,14 +359,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
352 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 359 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
353 /// ownerless phantom. 360 /// ownerless phantom.
354 /// 361 ///
355 /// All manipulation of this set has to occur under a lock 362 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
356 /// 363 ///
357 /// </value> 364 /// </value>
358 protected HashSet<uint> m_killRecord; 365// protected HashSet<uint> m_killRecord;
359 366
360// protected HashSet<uint> m_attachmentsSent; 367// protected HashSet<uint> m_attachmentsSent;
361 368
362 private int m_moneyBalance; 369 private int m_moneyBalance;
370 private bool m_deliverPackets = true;
363 private int m_animationSequenceNumber = 1; 371 private int m_animationSequenceNumber = 1;
364 private bool m_SendLogoutPacketWhenClosing = true; 372 private bool m_SendLogoutPacketWhenClosing = true;
365 373
@@ -406,6 +414,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
406 get { return m_startpos; } 414 get { return m_startpos; }
407 set { m_startpos = value; } 415 set { m_startpos = value; }
408 } 416 }
417 public bool DeliverPackets
418 {
419 get { return m_deliverPackets; }
420 set {
421 m_deliverPackets = value;
422 m_udpClient.m_deliverPackets = value;
423 }
424 }
409 public UUID AgentId { get { return m_agentId; } } 425 public UUID AgentId { get { return m_agentId; } }
410 public ISceneAgent SceneAgent { get; set; } 426 public ISceneAgent SceneAgent { get; set; }
411 public UUID ActiveGroupId { get { return m_activeGroupID; } } 427 public UUID ActiveGroupId { get { return m_activeGroupID; } }
@@ -483,7 +499,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
483 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); 499 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
484 m_entityProps = new PriorityQueue(m_scene.Entities.Count); 500 m_entityProps = new PriorityQueue(m_scene.Entities.Count);
485 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); 501 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
486 m_killRecord = new HashSet<uint>(); 502// m_killRecord = new HashSet<uint>();
487// m_attachmentsSent = new HashSet<uint>(); 503// m_attachmentsSent = new HashSet<uint>();
488 504
489 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 505 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
@@ -513,12 +529,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
513 529
514 #region Client Methods 530 #region Client Methods
515 531
532
533 /// <summary>
534 /// Close down the client view
535 /// </summary>
516 public void Close() 536 public void Close()
517 { 537 {
518 Close(false); 538 Close(true, false);
519 } 539 }
520 540
521 public void Close(bool force) 541 public void Close(bool sendStop, bool force)
522 { 542 {
523 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 543 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
524 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 544 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
@@ -530,7 +550,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
530 return; 550 return;
531 551
532 IsActive = false; 552 IsActive = false;
533 CloseWithoutChecks(); 553 CloseWithoutChecks(sendStop);
534 } 554 }
535 } 555 }
536 556
@@ -543,12 +563,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
543 /// 563 ///
544 /// Callers must lock ClosingSyncLock before calling. 564 /// Callers must lock ClosingSyncLock before calling.
545 /// </remarks> 565 /// </remarks>
546 public void CloseWithoutChecks() 566 public void CloseWithoutChecks(bool sendStop)
547 { 567 {
548 m_log.DebugFormat( 568 m_log.DebugFormat(
549 "[CLIENT]: Close has been called for {0} attached to scene {1}", 569 "[CLIENT]: Close has been called for {0} attached to scene {1}",
550 Name, m_scene.RegionInfo.RegionName); 570 Name, m_scene.RegionInfo.RegionName);
551 571
572 if (sendStop)
573 {
574 // Send the STOP packet
575 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
576 OutPacket(disable, ThrottleOutPacketType.Unknown);
577 }
578
552 // Shutdown the image manager 579 // Shutdown the image manager
553 ImageManager.Close(); 580 ImageManager.Close();
554 581
@@ -806,7 +833,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
806 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType); 833 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType);
807 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes; 834 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes;
808 835
809 OutPacket(handshake, ThrottleOutPacketType.Task); 836// OutPacket(handshake, ThrottleOutPacketType.Task);
837 // use same as MoveAgentIntoRegion (both should be task )
838 OutPacket(handshake, ThrottleOutPacketType.Unknown);
810 } 839 }
811 840
812 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) 841 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
@@ -845,7 +874,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
845 reply.ChatData.OwnerID = fromAgentID; 874 reply.ChatData.OwnerID = fromAgentID;
846 reply.ChatData.SourceID = fromAgentID; 875 reply.ChatData.SourceID = fromAgentID;
847 876
848 OutPacket(reply, ThrottleOutPacketType.Task); 877 OutPacket(reply, ThrottleOutPacketType.Unknown);
849 } 878 }
850 879
851 /// <summary> 880 /// <summary>
@@ -1131,6 +1160,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1131 public virtual void SendLayerData(float[] map) 1160 public virtual void SendLayerData(float[] map)
1132 { 1161 {
1133 Util.FireAndForget(DoSendLayerData, map); 1162 Util.FireAndForget(DoSendLayerData, map);
1163
1164 // Send it sync, and async. It's not that much data
1165 // and it improves user experience just so much!
1166 DoSendLayerData(map);
1134 } 1167 }
1135 1168
1136 /// <summary> 1169 /// <summary>
@@ -1143,16 +1176,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1143 1176
1144 try 1177 try
1145 { 1178 {
1146 //for (int y = 0; y < 16; y++) 1179 for (int y = 0; y < 16; y++)
1147 //{ 1180 {
1148 // for (int x = 0; x < 16; x++) 1181 for (int x = 0; x < 16; x+=4)
1149 // { 1182 {
1150 // SendLayerData(x, y, map); 1183 SendLayerPacket(x, y, map);
1151 // } 1184 }
1152 //} 1185 }
1153
1154 // Send LayerData in a spiral pattern. Fun!
1155 SendLayerTopRight(map, 0, 0, 15, 15);
1156 } 1186 }
1157 catch (Exception e) 1187 catch (Exception e)
1158 { 1188 {
@@ -1160,51 +1190,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1160 } 1190 }
1161 } 1191 }
1162 1192
1163 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1164 {
1165 // Row
1166 for (int i = x1; i <= x2; i++)
1167 SendLayerData(i, y1, map);
1168
1169 // Column
1170 for (int j = y1 + 1; j <= y2; j++)
1171 SendLayerData(x2, j, map);
1172
1173 if (x2 - x1 > 0)
1174 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1175 }
1176
1177 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1178 {
1179 // Row in reverse
1180 for (int i = x2; i >= x1; i--)
1181 SendLayerData(i, y2, map);
1182
1183 // Column in reverse
1184 for (int j = y2 - 1; j >= y1; j--)
1185 SendLayerData(x1, j, map);
1186
1187 if (x2 - x1 > 0)
1188 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1189 }
1190
1191 /// <summary> 1193 /// <summary>
1192 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1194 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1193 /// </summary> 1195 /// </summary>
1194 /// <param name="map">heightmap</param> 1196 /// <param name="map">heightmap</param>
1195 /// <param name="px">X coordinate for patches 0..12</param> 1197 /// <param name="px">X coordinate for patches 0..12</param>
1196 /// <param name="py">Y coordinate for patches 0..15</param> 1198 /// <param name="py">Y coordinate for patches 0..15</param>
1197 // private void SendLayerPacket(float[] map, int y, int x) 1199 private void SendLayerPacket(int x, int y, float[] map)
1198 // { 1200 {
1199 // int[] patches = new int[4]; 1201 int[] patches = new int[4];
1200 // patches[0] = x + 0 + y * 16; 1202 patches[0] = x + 0 + y * 16;
1201 // patches[1] = x + 1 + y * 16; 1203 patches[1] = x + 1 + y * 16;
1202 // patches[2] = x + 2 + y * 16; 1204 patches[2] = x + 2 + y * 16;
1203 // patches[3] = x + 3 + y * 16; 1205 patches[3] = x + 3 + y * 16;
1204 1206
1205 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1207 float[] heightmap = (map.Length == 65536) ?
1206 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1208 map :
1207 // } 1209 LLHeightFieldMoronize(map);
1210
1211 try
1212 {
1213 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1214 OutPacket(layerpack, ThrottleOutPacketType.Land);
1215 }
1216 catch
1217 {
1218 for (int px = x ; px < x + 4 ; px++)
1219 SendLayerData(px, y, map);
1220 }
1221 }
1208 1222
1209 /// <summary> 1223 /// <summary>
1210 /// Sends a specified patch to a client 1224 /// Sends a specified patch to a client
@@ -1224,7 +1238,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1224 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1238 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1225 layerpack.Header.Reliable = true; 1239 layerpack.Header.Reliable = true;
1226 1240
1227 OutPacket(layerpack, ThrottleOutPacketType.Land); 1241 OutPacket(layerpack, ThrottleOutPacketType.Task);
1228 } 1242 }
1229 catch (Exception e) 1243 catch (Exception e)
1230 { 1244 {
@@ -1587,7 +1601,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1587 1601
1588 public void SendKillObject(ulong regionHandle, List<uint> localIDs) 1602 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1589 { 1603 {
1590// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1604// foreach (uint id in localIDs)
1605// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
1591 1606
1592 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1607 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1593 // TODO: don't create new blocks if recycling an old packet 1608 // TODO: don't create new blocks if recycling an old packet
@@ -1609,17 +1624,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1609 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race 1624 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race
1610 // condition where a kill can be processed before an out-of-date update for the same object. 1625 // condition where a kill can be processed before an out-of-date update for the same object.
1611 // ProcessEntityUpdates() also takes the m_killRecord lock. 1626 // ProcessEntityUpdates() also takes the m_killRecord lock.
1612 lock (m_killRecord) 1627// lock (m_killRecord)
1613 { 1628// {
1614 foreach (uint localID in localIDs) 1629// foreach (uint localID in localIDs)
1615 m_killRecord.Add(localID); 1630// m_killRecord.Add(localID);
1616 1631
1617 // The throttle queue used here must match that being used for updates. Otherwise, there is a 1632 // The throttle queue used here must match that being used for updates. Otherwise, there is a
1618 // chance that a kill packet put on a separate queue will be sent to the client before an existing 1633 // chance that a kill packet put on a separate queue will be sent to the client before an existing
1619 // update packet on another queue. Receiving updates after kills results in unowned and undeletable 1634 // update packet on another queue. Receiving updates after kills results in unowned and undeletable
1620 // scene objects in a viewer until that viewer is relogged in. 1635 // scene objects in a viewer until that viewer is relogged in.
1621 OutPacket(kill, ThrottleOutPacketType.Task); 1636 OutPacket(kill, ThrottleOutPacketType.Task);
1622 } 1637// }
1623 } 1638 }
1624 } 1639 }
1625 1640
@@ -2077,9 +2092,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2077 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); 2092 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
2078 } 2093 }
2079 2094
2080 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2081 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) 2095 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
2082 { 2096 {
2097 SendInventoryItemCreateUpdate(Item, UUID.Zero, callbackId);
2098 }
2099
2100 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2101 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
2102 {
2083 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; 2103 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
2084 2104
2085 UpdateCreateInventoryItemPacket InventoryReply 2105 UpdateCreateInventoryItemPacket InventoryReply
@@ -2089,6 +2109,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2089 // TODO: don't create new blocks if recycling an old packet 2109 // TODO: don't create new blocks if recycling an old packet
2090 InventoryReply.AgentData.AgentID = AgentId; 2110 InventoryReply.AgentData.AgentID = AgentId;
2091 InventoryReply.AgentData.SimApproved = true; 2111 InventoryReply.AgentData.SimApproved = true;
2112 InventoryReply.AgentData.TransactionID = transactionID;
2092 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; 2113 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
2093 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); 2114 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
2094 InventoryReply.InventoryData[0].ItemID = Item.ID; 2115 InventoryReply.InventoryData[0].ItemID = Item.ID;
@@ -2158,16 +2179,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2158 replytask.InventoryData.TaskID = taskID; 2179 replytask.InventoryData.TaskID = taskID;
2159 replytask.InventoryData.Serial = serial; 2180 replytask.InventoryData.Serial = serial;
2160 replytask.InventoryData.Filename = fileName; 2181 replytask.InventoryData.Filename = fileName;
2161 OutPacket(replytask, ThrottleOutPacketType.Asset); 2182 OutPacket(replytask, ThrottleOutPacketType.Task);
2162 } 2183 }
2163 2184
2164 public void SendXferPacket(ulong xferID, uint packet, byte[] data) 2185 public void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory)
2165 { 2186 {
2187 ThrottleOutPacketType type = ThrottleOutPacketType.Asset;
2188 if (isTaskInventory)
2189 type = ThrottleOutPacketType.Task;
2190
2166 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket); 2191 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket);
2167 sendXfer.XferID.ID = xferID; 2192 sendXfer.XferID.ID = xferID;
2168 sendXfer.XferID.Packet = packet; 2193 sendXfer.XferID.Packet = packet;
2169 sendXfer.DataPacket.Data = data; 2194 sendXfer.DataPacket.Data = data;
2170 OutPacket(sendXfer, ThrottleOutPacketType.Asset); 2195 OutPacket(sendXfer, type);
2171 } 2196 }
2172 2197
2173 public void SendAbortXferPacket(ulong xferID) 2198 public void SendAbortXferPacket(ulong xferID)
@@ -2349,6 +2374,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2349 OutPacket(sound, ThrottleOutPacketType.Task); 2374 OutPacket(sound, ThrottleOutPacketType.Task);
2350 } 2375 }
2351 2376
2377 public void SendTransferAbort(TransferRequestPacket transferRequest)
2378 {
2379 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2380 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2381 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2382 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2383 OutPacket(abort, ThrottleOutPacketType.Task);
2384 }
2385
2352 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2386 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2353 { 2387 {
2354 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2388 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -2641,6 +2675,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2641 } 2675 }
2642 } 2676 }
2643 2677
2678 public void SendPartPhysicsProprieties(ISceneEntity entity)
2679 {
2680 SceneObjectPart part = (SceneObjectPart)entity;
2681 if (part != null && AgentId != UUID.Zero)
2682 {
2683 try
2684 {
2685 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
2686 if (eq != null)
2687 {
2688 uint localid = part.LocalId;
2689 byte physshapetype = part.PhysicsShapeType;
2690 float density = part.Density;
2691 float friction = part.Friction;
2692 float bounce = part.Bounciness;
2693 float gravmod = part.GravityModifier;
2694
2695 eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId);
2696 }
2697 }
2698 catch (Exception ex)
2699 {
2700 m_log.Error("Unable to send part Physics Proprieties - exception: " + ex.ToString());
2701 }
2702 part.UpdatePhysRequired = false;
2703 }
2704 }
2705
2706
2644 2707
2645 public void SendGroupNameReply(UUID groupLLUID, string GroupName) 2708 public void SendGroupNameReply(UUID groupLLUID, string GroupName)
2646 { 2709 {
@@ -2738,7 +2801,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2738 else 2801 else
2739 { 2802 {
2740 int processedLength = 0; 2803 int processedLength = 0;
2741 int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; 2804// int maxChunkSize = Settings.MAX_PACKET_SIZE - 100;
2805
2806 int maxChunkSize = (int) MaxTransferBytesPerPacket;
2742 int packetNumber = 0; 2807 int packetNumber = 0;
2743 2808
2744 while (processedLength < req.AssetInf.Data.Length) 2809 while (processedLength < req.AssetInf.Data.Length)
@@ -2809,7 +2874,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2809 reply.Data.ParcelID = parcelID; 2874 reply.Data.ParcelID = parcelID;
2810 reply.Data.OwnerID = land.OwnerID; 2875 reply.Data.OwnerID = land.OwnerID;
2811 reply.Data.Name = Utils.StringToBytes(land.Name); 2876 reply.Data.Name = Utils.StringToBytes(land.Name);
2812 reply.Data.Desc = Utils.StringToBytes(land.Description); 2877 if (land != null && land.Description != null && land.Description != String.Empty)
2878 reply.Data.Desc = Utils.StringToBytes(land.Description.Substring(0, land.Description.Length > 254 ? 254: land.Description.Length));
2879 else
2880 reply.Data.Desc = new Byte[0];
2813 reply.Data.ActualArea = land.Area; 2881 reply.Data.ActualArea = land.Area;
2814 reply.Data.BillableArea = land.Area; // TODO: what is this? 2882 reply.Data.BillableArea = land.Area; // TODO: what is this?
2815 2883
@@ -3544,7 +3612,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3544 3612
3545 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); 3613 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance);
3546 // TODO: don't create new blocks if recycling an old packet 3614 // TODO: don't create new blocks if recycling an old packet
3547 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; 3615 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[visualParams.Length];
3548 avp.ObjectData.TextureEntry = textureEntry; 3616 avp.ObjectData.TextureEntry = textureEntry;
3549 3617
3550 AvatarAppearancePacket.VisualParamBlock avblock = null; 3618 AvatarAppearancePacket.VisualParamBlock avblock = null;
@@ -3674,7 +3742,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3674 /// </summary> 3742 /// </summary>
3675 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3743 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3676 { 3744 {
3677 //double priority = m_prioritizer.GetUpdatePriority(this, entity); 3745 if (entity is SceneObjectPart)
3746 {
3747 SceneObjectPart e = (SceneObjectPart)entity;
3748 SceneObjectGroup g = e.ParentGroup;
3749 if (g.RootPart.Shape.State > 30) // HUD
3750 if (g.OwnerID != AgentId)
3751 return; // Don't send updates for other people's HUDs
3752 }
3753
3678 uint priority = m_prioritizer.GetUpdatePriority(this, entity); 3754 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3679 3755
3680 lock (m_entityUpdates.SyncRoot) 3756 lock (m_entityUpdates.SyncRoot)
@@ -3741,27 +3817,74 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3741 3817
3742 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3818 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3743 // condition where a kill can be processed before an out-of-date update for the same object. 3819 // condition where a kill can be processed before an out-of-date update for the same object.
3744 lock (m_killRecord) 3820 float avgTimeDilation = 1.0f;
3821 IEntityUpdate iupdate;
3822 Int32 timeinqueue; // this is just debugging code & can be dropped later
3823
3824 while (updatesThisCall < maxUpdates)
3745 { 3825 {
3746 float avgTimeDilation = 1.0f; 3826 lock (m_entityUpdates.SyncRoot)
3747 IEntityUpdate iupdate; 3827 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3748 Int32 timeinqueue; // this is just debugging code & can be dropped later 3828 break;
3829
3830 EntityUpdate update = (EntityUpdate)iupdate;
3831
3832 avgTimeDilation += update.TimeDilation;
3833 avgTimeDilation *= 0.5f;
3749 3834
3750 while (updatesThisCall < maxUpdates) 3835 if (update.Entity is SceneObjectPart)
3751 { 3836 {
3752 lock (m_entityUpdates.SyncRoot) 3837 SceneObjectPart part = (SceneObjectPart)update.Entity;
3753 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3754 break;
3755 3838
3756 EntityUpdate update = (EntityUpdate)iupdate; 3839 if (part.ParentGroup.IsDeleted)
3757 3840 continue;
3758 avgTimeDilation += update.TimeDilation;
3759 avgTimeDilation *= 0.5f;
3760 3841
3761 if (update.Entity is SceneObjectPart) 3842 if (part.ParentGroup.IsAttachment)
3843 { // Someone else's HUD, why are we getting these?
3844 if (part.ParentGroup.OwnerID != AgentId &&
3845 part.ParentGroup.RootPart.Shape.State > 30)
3846 continue;
3847 ScenePresence sp;
3848 // Owner is not in the sim, don't update it to
3849 // anyone
3850 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3851 continue;
3852
3853 List<SceneObjectGroup> atts = sp.GetAttachments();
3854 bool found = false;
3855 foreach (SceneObjectGroup att in atts)
3856 {
3857 if (att == part.ParentGroup)
3858 {
3859 found = true;
3860 break;
3861 }
3862 }
3863
3864 // It's an attachment of a valid avatar, but
3865 // doesn't seem to be attached, skip
3866 if (!found)
3867 continue;
3868
3869 // On vehicle crossing, the attachments are received
3870 // while the avatar is still a child. Don't send
3871 // updates here because the LocalId has not yet
3872 // been updated and the viewer will derender the
3873 // attachments until the avatar becomes root.
3874 if (sp.IsChildAgent)
3875 continue;
3876
3877 // If the object is an attachment we don't want it to be in the kill
3878 // record. Else attaching from inworld and subsequently dropping
3879 // it will no longer work.
3880// lock (m_killRecord)
3881// {
3882// m_killRecord.Remove(part.LocalId);
3883// m_killRecord.Remove(part.ParentGroup.RootPart.LocalId);
3884// }
3885 }
3886 else
3762 { 3887 {
3763 SceneObjectPart part = (SceneObjectPart)update.Entity;
3764
3765 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client 3888 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3766 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good 3889 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3767 // safety measure. 3890 // safety measure.
@@ -3772,241 +3895,177 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3772 // 3895 //
3773 // This doesn't appear to apply to child prims - a client will happily ignore these updates 3896 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3774 // after the root prim has been deleted. 3897 // after the root prim has been deleted.
3775 if (m_killRecord.Contains(part.LocalId)) 3898 //
3776 { 3899 // We ignore this for attachments because attaching something from inworld breaks unless we do.
3777 // m_log.WarnFormat( 3900// lock (m_killRecord)
3778 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted", 3901// {
3779 // part.LocalId, Name); 3902// if (m_killRecord.Contains(part.LocalId))
3780 continue; 3903// continue;
3781 } 3904// if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3782 3905// continue;
3783 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3906// }
3907 }
3908
3909 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3910 {
3911 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3912 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3784 { 3913 {
3785 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3914 part.Shape.LightEntry = false;
3786 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3787 {
3788 part.Shape.LightEntry = false;
3789 }
3790 } 3915 }
3791 } 3916 }
3792 3917 }
3793 #region UpdateFlags to packet type conversion 3918
3794 3919 ++updatesThisCall;
3795 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; 3920
3796 3921 #region UpdateFlags to packet type conversion
3797 bool canUseCompressed = true; 3922
3798 bool canUseImproved = true; 3923 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3799 3924
3800 // Compressed object updates only make sense for LL primitives 3925 bool canUseCompressed = true;
3801 if (!(update.Entity is SceneObjectPart)) 3926 bool canUseImproved = true;
3927
3928 // Compressed object updates only make sense for LL primitives
3929 if (!(update.Entity is SceneObjectPart))
3930 {
3931 canUseCompressed = false;
3932 }
3933
3934 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3935 {
3936 canUseCompressed = false;
3937 canUseImproved = false;
3938 }
3939 else
3940 {
3941 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3942 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3943 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3944 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3802 { 3945 {
3803 canUseCompressed = false; 3946 canUseCompressed = false;
3804 } 3947 }
3805 3948
3806 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 3949 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3950 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3951 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3952 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3953 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3954 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3955 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3956 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3957 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3958 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3959 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3960 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3961 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3962 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3807 { 3963 {
3808 canUseCompressed = false;
3809 canUseImproved = false; 3964 canUseImproved = false;
3810 } 3965 }
3811 else 3966 }
3812 {
3813 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3814 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3815 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3816 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3817 {
3818 canUseCompressed = false;
3819 }
3820
3821 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3822 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3823 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3824 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3825 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3826 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3827 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3828 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3829 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3830 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3831 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3832 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3833 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3834 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3835 {
3836 canUseImproved = false;
3837 }
3838 }
3839
3840 #endregion UpdateFlags to packet type conversion
3841
3842 #region Block Construction
3843
3844 // TODO: Remove this once we can build compressed updates
3845 canUseCompressed = false;
3846 3967
3847 if (!canUseImproved && !canUseCompressed) 3968 #endregion UpdateFlags to packet type conversion
3848 {
3849 ObjectUpdatePacket.ObjectDataBlock updateBlock;
3850 3969
3851 if (update.Entity is ScenePresence) 3970 #region Block Construction
3852 {
3853 updateBlock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
3854 }
3855 else
3856 {
3857 SceneObjectPart part = (SceneObjectPart)update.Entity;
3858 updateBlock = CreatePrimUpdateBlock(part, AgentId);
3859
3860 // If the part has become a private hud since the update was scheduled then we do not
3861 // want to send it to other avatars.
3862 if (part.ParentGroup.IsAttachment
3863 && part.ParentGroup.HasPrivateAttachmentPoint
3864 && part.ParentGroup.AttachedAvatar != AgentId)
3865 continue;
3866
3867 // If the part has since been deleted, then drop the update. In the case of attachments,
3868 // this is to avoid spurious updates to other viewers since post-processing of attachments
3869 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3870 // of the test above).
3871 //
3872 // Actual deletions (kills) happen in another method.
3873 if (part.ParentGroup.IsDeleted)
3874 continue;
3875 }
3876 3971
3877 objectUpdateBlocks.Value.Add(updateBlock); 3972 // TODO: Remove this once we can build compressed updates
3878 objectUpdates.Value.Add(update); 3973 canUseCompressed = false;
3879 }
3880 else if (!canUseImproved)
3881 {
3882 SceneObjectPart part = (SceneObjectPart)update.Entity;
3883 ObjectUpdateCompressedPacket.ObjectDataBlock compressedBlock
3884 = CreateCompressedUpdateBlock(part, updateFlags);
3885
3886 // If the part has since been deleted, then drop the update. In the case of attachments,
3887 // this is to avoid spurious updates to other viewers since post-processing of attachments
3888 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3889 // of the test above).
3890 //
3891 // Actual deletions (kills) happen in another method.
3892 if (part.ParentGroup.IsDeleted)
3893 continue;
3894 3974
3895 compressedUpdateBlocks.Value.Add(compressedBlock); 3975 if (!canUseImproved && !canUseCompressed)
3896 compressedUpdates.Value.Add(update); 3976 {
3977 if (update.Entity is ScenePresence)
3978 {
3979 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3897 } 3980 }
3898 else 3981 else
3899 { 3982 {
3900 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 3983 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3901 {
3902 // Self updates go into a special list
3903 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3904 terseAgentUpdates.Value.Add(update);
3905 }
3906 else
3907 {
3908 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseUpdateBlock
3909 = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures));
3910
3911 // Everything else goes here
3912 if (update.Entity is SceneObjectPart)
3913 {
3914 SceneObjectPart part = (SceneObjectPart)update.Entity;
3915
3916 // If the part has become a private hud since the update was scheduled then we do not
3917 // want to send it to other avatars.
3918 if (part.ParentGroup.IsAttachment
3919 && part.ParentGroup.HasPrivateAttachmentPoint
3920 && part.ParentGroup.AttachedAvatar != AgentId)
3921 continue;
3922
3923 // If the part has since been deleted, then drop the update. In the case of attachments,
3924 // this is to avoid spurious updates to other viewers since post-processing of attachments
3925 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3926 // of the test above).
3927 //
3928 // Actual deletions (kills) happen in another method.
3929 if (part.ParentGroup.IsDeleted)
3930 continue;
3931 }
3932
3933 terseUpdateBlocks.Value.Add(terseUpdateBlock);
3934 terseUpdates.Value.Add(update);
3935 }
3936 } 3984 }
3937
3938 ++updatesThisCall;
3939
3940 #endregion Block Construction
3941 } 3985 }
3942 3986 else if (!canUseImproved)
3943 #region Packet Sending 3987 {
3944 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 3988 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3945 3989 }
3946 if (terseAgentUpdateBlocks.IsValueCreated) 3990 else
3947 { 3991 {
3948 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3992 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3993 // Self updates go into a special list
3994 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3995 else
3996 // Everything else goes here
3997 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3998 }
3949 3999
3950 ImprovedTerseObjectUpdatePacket packet 4000 #endregion Block Construction
3951 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 4001 }
3952 4002
3953 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4003 #region Packet Sending
3954 packet.RegionData.TimeDilation = timeDilation; 4004
3955 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4005 const float TIME_DILATION = 1.0f;
4006 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
4007
4008 if (terseAgentUpdateBlocks.IsValueCreated)
4009 {
4010 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3956 4011
3957 for (int i = 0; i < blocks.Count; i++) 4012 ImprovedTerseObjectUpdatePacket packet
3958 packet.ObjectData[i] = blocks[i]; 4013 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3959 // If any of the packets created from this call go unacknowledged, all of the updates will be resent 4014 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3960 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); }); 4015 packet.RegionData.TimeDilation = timeDilation;
3961 } 4016 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3962 4017
3963 if (objectUpdateBlocks.IsValueCreated) 4018 for (int i = 0; i < blocks.Count; i++)
3964 { 4019 packet.ObjectData[i] = blocks[i];
3965 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3966
3967 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3968 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3969 packet.RegionData.TimeDilation = timeDilation;
3970 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3971
3972 for (int i = 0; i < blocks.Count; i++)
3973 packet.ObjectData[i] = blocks[i];
3974 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3975 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
3976 }
3977
3978 if (compressedUpdateBlocks.IsValueCreated)
3979 {
3980 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3981
3982 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3983 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3984 packet.RegionData.TimeDilation = timeDilation;
3985 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3986
3987 for (int i = 0; i < blocks.Count; i++)
3988 packet.ObjectData[i] = blocks[i];
3989 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3990 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
3991 }
3992 4020
3993 if (terseUpdateBlocks.IsValueCreated) 4021 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3994 { 4022 }
3995 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3996
3997 ImprovedTerseObjectUpdatePacket packet
3998 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
3999 PacketType.ImprovedTerseObjectUpdate);
4000 4023
4001 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4024 if (objectUpdateBlocks.IsValueCreated)
4002 packet.RegionData.TimeDilation = timeDilation; 4025 {
4003 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4026 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
4004 4027
4005 for (int i = 0; i < blocks.Count; i++) 4028 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
4006 packet.ObjectData[i] = blocks[i]; 4029 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4007 // If any of the packets created from this call go unacknowledged, all of the updates will be resent 4030 packet.RegionData.TimeDilation = timeDilation;
4008 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); 4031 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4009 } 4032
4033 for (int i = 0; i < blocks.Count; i++)
4034 packet.ObjectData[i] = blocks[i];
4035
4036 OutPacket(packet, ThrottleOutPacketType.Task, true);
4037 }
4038
4039 if (compressedUpdateBlocks.IsValueCreated)
4040 {
4041 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
4042
4043 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
4044 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4045 packet.RegionData.TimeDilation = timeDilation;
4046 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
4047
4048 for (int i = 0; i < blocks.Count; i++)
4049 packet.ObjectData[i] = blocks[i];
4050
4051 OutPacket(packet, ThrottleOutPacketType.Task, true);
4052 }
4053
4054 if (terseUpdateBlocks.IsValueCreated)
4055 {
4056 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4057
4058 ImprovedTerseObjectUpdatePacket packet
4059 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4060 PacketType.ImprovedTerseObjectUpdate);
4061 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4062 packet.RegionData.TimeDilation = timeDilation;
4063 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4064
4065 for (int i = 0; i < blocks.Count; i++)
4066 packet.ObjectData[i] = blocks[i];
4067
4068 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4010 } 4069 }
4011 4070
4012 #endregion Packet Sending 4071 #endregion Packet Sending
@@ -4299,11 +4358,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4299 4358
4300 // Pass in the delegate so that if this packet needs to be resent, we send the current properties 4359 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4301 // of the object rather than the properties when the packet was created 4360 // of the object rather than the properties when the packet was created
4302 OutPacket(packet, ThrottleOutPacketType.Task, true, 4361 // HACK : Remove intelligent resending until it's fixed in core
4303 delegate(OutgoingPacket oPacket) 4362 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4304 { 4363 // delegate(OutgoingPacket oPacket)
4305 ResendPropertyUpdates(updates, oPacket); 4364 // {
4306 }); 4365 // ResendPropertyUpdates(updates, oPacket);
4366 // });
4367 OutPacket(packet, ThrottleOutPacketType.Task, true);
4307 4368
4308 // pbcnt += blocks.Count; 4369 // pbcnt += blocks.Count;
4309 // ppcnt++; 4370 // ppcnt++;
@@ -4329,11 +4390,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4329 // of the object rather than the properties when the packet was created 4390 // of the object rather than the properties when the packet was created
4330 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); 4391 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
4331 updates.Add(familyUpdates.Value[i]); 4392 updates.Add(familyUpdates.Value[i]);
4332 OutPacket(packet, ThrottleOutPacketType.Task, true, 4393 // HACK : Remove intelligent resending until it's fixed in core
4333 delegate(OutgoingPacket oPacket) 4394 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4334 { 4395 // delegate(OutgoingPacket oPacket)
4335 ResendPropertyUpdates(updates, oPacket); 4396 // {
4336 }); 4397 // ResendPropertyUpdates(updates, oPacket);
4398 // });
4399 OutPacket(packet, ThrottleOutPacketType.Task, true);
4337 4400
4338 // fpcnt++; 4401 // fpcnt++;
4339 // fbcnt++; 4402 // fbcnt++;
@@ -4705,7 +4768,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4705 4768
4706 if (landData.SimwideArea > 0) 4769 if (landData.SimwideArea > 0)
4707 { 4770 {
4708 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 4771 int simulatorCapacity = (int)((long)landData.SimwideArea * (long)m_scene.RegionInfo.ObjectCapacity * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus / 65536L);
4772 // Never report more than sim total capacity
4773 if (simulatorCapacity > m_scene.RegionInfo.ObjectCapacity)
4774 simulatorCapacity = m_scene.RegionInfo.ObjectCapacity;
4709 updateMessage.SimWideMaxPrims = simulatorCapacity; 4775 updateMessage.SimWideMaxPrims = simulatorCapacity;
4710 } 4776 }
4711 else 4777 else
@@ -4834,14 +4900,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4834 4900
4835 if (notifyCount > 0) 4901 if (notifyCount > 0)
4836 { 4902 {
4837 if (notifyCount > 32) 4903// if (notifyCount > 32)
4838 { 4904// {
4839 m_log.InfoFormat( 4905// m_log.InfoFormat(
4840 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4906// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4841 + " - a developer might want to investigate whether this is a hard limit", 32); 4907// + " - a developer might want to investigate whether this is a hard limit", 32);
4842 4908//
4843 notifyCount = 32; 4909// notifyCount = 32;
4844 } 4910// }
4845 4911
4846 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4912 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4847 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4913 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -4896,9 +4962,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4896 { 4962 {
4897 ScenePresence presence = (ScenePresence)entity; 4963 ScenePresence presence = (ScenePresence)entity;
4898 4964
4965 position = presence.OffsetPosition;
4966 rotation = presence.Rotation;
4967
4968 if (presence.ParentID != 0)
4969 {
4970 SceneObjectPart part = m_scene.GetSceneObjectPart(presence.ParentID);
4971 if (part != null && part != part.ParentGroup.RootPart)
4972 {
4973 position = part.OffsetPosition + presence.OffsetPosition * part.RotationOffset;
4974 rotation = part.RotationOffset * presence.Rotation;
4975 }
4976 }
4977
4899 attachPoint = 0; 4978 attachPoint = 0;
4900 collisionPlane = presence.CollisionPlane; 4979 collisionPlane = presence.CollisionPlane;
4901 position = presence.OffsetPosition;
4902 velocity = presence.Velocity; 4980 velocity = presence.Velocity;
4903 acceleration = Vector3.Zero; 4981 acceleration = Vector3.Zero;
4904 4982
@@ -4908,7 +4986,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4908// acceleration = new Vector3(1, 0, 0); 4986// acceleration = new Vector3(1, 0, 0);
4909 4987
4910 angularVelocity = Vector3.Zero; 4988 angularVelocity = Vector3.Zero;
4911 rotation = presence.Rotation;
4912 4989
4913 if (sendTexture) 4990 if (sendTexture)
4914 textureEntry = presence.Appearance.Texture.GetBytes(); 4991 textureEntry = presence.Appearance.Texture.GetBytes();
@@ -5015,13 +5092,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5015 5092
5016 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) 5093 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
5017 { 5094 {
5095 Vector3 offsetPosition = data.OffsetPosition;
5096 Quaternion rotation = data.Rotation;
5097 uint parentID = data.ParentID;
5098
5099 if (parentID != 0)
5100 {
5101 SceneObjectPart part = m_scene.GetSceneObjectPart(parentID);
5102 if (part != null && part != part.ParentGroup.RootPart)
5103 {
5104 offsetPosition = part.OffsetPosition + data.OffsetPosition * part.RotationOffset;
5105 rotation = part.RotationOffset * data.Rotation;
5106 parentID = part.ParentGroup.RootPart.LocalId;
5107 }
5108 }
5109
5018 byte[] objectData = new byte[76]; 5110 byte[] objectData = new byte[76];
5019 5111
5020 data.CollisionPlane.ToBytes(objectData, 0); 5112 data.CollisionPlane.ToBytes(objectData, 0);
5021 data.OffsetPosition.ToBytes(objectData, 16); 5113 offsetPosition.ToBytes(objectData, 16);
5022// data.Velocity.ToBytes(objectData, 28); 5114// data.Velocity.ToBytes(objectData, 28);
5023// data.Acceleration.ToBytes(objectData, 40); 5115// data.Acceleration.ToBytes(objectData, 40);
5024 data.Rotation.ToBytes(objectData, 52); 5116 rotation.ToBytes(objectData, 52);
5025 //data.AngularVelocity.ToBytes(objectData, 64); 5117 //data.AngularVelocity.ToBytes(objectData, 64);
5026 5118
5027 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5119 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
@@ -5035,7 +5127,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5035 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + 5127 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
5036 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); 5128 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
5037 update.ObjectData = objectData; 5129 update.ObjectData = objectData;
5038 update.ParentID = data.ParentID; 5130 update.ParentID = parentID;
5039 update.PathCurve = 16; 5131 update.PathCurve = 16;
5040 update.PathScaleX = 100; 5132 update.PathScaleX = 100;
5041 update.PathScaleY = 100; 5133 update.PathScaleY = 100;
@@ -5053,10 +5145,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5053 update.TextureEntry = Utils.EmptyBytes; 5145 update.TextureEntry = Utils.EmptyBytes;
5054// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes; 5146// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
5055 5147
5148/* all this flags seem related to prims and not avatars. This allow for wrong viewer side move of a avatar in prim edition mode (anv mantis 854)
5056 update.UpdateFlags = (uint)( 5149 update.UpdateFlags = (uint)(
5057 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | 5150 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
5058 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | 5151 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
5059 PrimFlags.ObjectOwnerModify); 5152 PrimFlags.ObjectOwnerModify);
5153*/
5154 update.UpdateFlags = 0;
5060 5155
5061 return update; 5156 return update;
5062 } 5157 }
@@ -5380,6 +5475,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5380 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5475 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5381 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5476 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5382 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5477 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5478 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5383 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5479 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5384 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5480 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5385 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5481 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5446,6 +5542,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5446 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest); 5542 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest);
5447 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes); 5543 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes);
5448 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard); 5544 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard);
5545 AddLocalPacketHandler(PacketType.ChangeInventoryItemFlags, HandleChangeInventoryItemFlags);
5449 5546
5450 AddGenericPacketHandler("autopilot", HandleAutopilot); 5547 AddGenericPacketHandler("autopilot", HandleAutopilot);
5451 } 5548 }
@@ -5484,6 +5581,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5484 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || 5581 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) ||
5485 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || 5582 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) ||
5486 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || 5583 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) ||
5584 (x.ControlFlags != 0) ||
5487 (x.Far != m_lastAgentUpdateArgs.Far) || 5585 (x.Far != m_lastAgentUpdateArgs.Far) ||
5488 (x.Flags != m_lastAgentUpdateArgs.Flags) || 5586 (x.Flags != m_lastAgentUpdateArgs.Flags) ||
5489 (x.State != m_lastAgentUpdateArgs.State) || 5587 (x.State != m_lastAgentUpdateArgs.State) ||
@@ -6382,6 +6480,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6382 { 6480 {
6383 handlerCompleteMovementToRegion(sender, true); 6481 handlerCompleteMovementToRegion(sender, true);
6384 } 6482 }
6483 else
6484 m_log.Debug("HandleCompleteAgentMovement NULL handler");
6485
6385 handlerCompleteMovementToRegion = null; 6486 handlerCompleteMovementToRegion = null;
6386 6487
6387 return true; 6488 return true;
@@ -6399,7 +6500,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6399 return true; 6500 return true;
6400 } 6501 }
6401 #endregion 6502 #endregion
6402 6503/*
6403 StartAnim handlerStartAnim = null; 6504 StartAnim handlerStartAnim = null;
6404 StopAnim handlerStopAnim = null; 6505 StopAnim handlerStopAnim = null;
6405 6506
@@ -6423,6 +6524,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6423 } 6524 }
6424 } 6525 }
6425 return true; 6526 return true;
6527*/
6528 ChangeAnim handlerChangeAnim = null;
6529
6530 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
6531 {
6532 handlerChangeAnim = OnChangeAnim;
6533 if (handlerChangeAnim != null)
6534 {
6535 handlerChangeAnim(AgentAni.AnimationList[i].AnimID, AgentAni.AnimationList[i].StartAnim, false);
6536 }
6537 }
6538
6539 handlerChangeAnim = OnChangeAnim;
6540 if (handlerChangeAnim != null)
6541 {
6542 handlerChangeAnim(UUID.Zero, false, true);
6543 }
6544
6545 return true;
6426 } 6546 }
6427 6547
6428 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack) 6548 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack)
@@ -7048,10 +7168,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7048 // 46,47,48 are special positions within the packet 7168 // 46,47,48 are special positions within the packet
7049 // This may change so perhaps we need a better way 7169 // This may change so perhaps we need a better way
7050 // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?) 7170 // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?)
7051 bool UsePhysics = (data[46] != 0) ? true : false; 7171 /*
7052 bool IsTemporary = (data[47] != 0) ? true : false; 7172 bool UsePhysics = (data[46] != 0) ? true : false;
7053 bool IsPhantom = (data[48] != 0) ? true : false; 7173 bool IsTemporary = (data[47] != 0) ? true : false;
7054 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this); 7174 bool IsPhantom = (data[48] != 0) ? true : false;
7175 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this);
7176 */
7177 bool UsePhysics = flags.AgentData.UsePhysics;
7178 bool IsPhantom = flags.AgentData.IsPhantom;
7179 bool IsTemporary = flags.AgentData.IsTemporary;
7180 ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks = flags.ExtraPhysics;
7181 ExtraPhysicsData physdata = new ExtraPhysicsData();
7182
7183 if (blocks == null || blocks.Length == 0)
7184 {
7185 physdata.PhysShapeType = PhysShapeType.invalid;
7186 }
7187 else
7188 {
7189 ObjectFlagUpdatePacket.ExtraPhysicsBlock phsblock = blocks[0];
7190 physdata.PhysShapeType = (PhysShapeType)phsblock.PhysicsShapeType;
7191 physdata.Bounce = phsblock.Restitution;
7192 physdata.Density = phsblock.Density;
7193 physdata.Friction = phsblock.Friction;
7194 physdata.GravitationModifier = phsblock.GravityMultiplier;
7195 }
7196
7197 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, this);
7055 } 7198 }
7056 return true; 7199 return true;
7057 } 7200 }
@@ -8652,16 +8795,61 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8652 8795
8653 #region Parcel related packets 8796 #region Parcel related packets
8654 8797
8798 // acumulate several HandleRegionHandleRequest consecutive overlaping requests
8799 // to be done with minimal resources as possible
8800 // variables temporary here while in test
8801
8802 Queue<UUID> RegionHandleRequests = new Queue<UUID>();
8803 bool RegionHandleRequestsInService = false;
8804
8655 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack) 8805 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack)
8656 { 8806 {
8657 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; 8807 UUID currentUUID;
8658 8808
8659 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest; 8809 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest;
8660 if (handlerRegionHandleRequest != null) 8810
8811 if (handlerRegionHandleRequest == null)
8812 return true;
8813
8814 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack;
8815
8816 lock (RegionHandleRequests)
8661 { 8817 {
8662 handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); 8818 if (RegionHandleRequestsInService)
8819 {
8820 // we are already busy doing a previus request
8821 // so enqueue it
8822 RegionHandleRequests.Enqueue(rhrPack.RequestBlock.RegionID);
8823 return true;
8824 }
8825
8826 // else do it
8827 currentUUID = rhrPack.RequestBlock.RegionID;
8828 RegionHandleRequestsInService = true;
8663 } 8829 }
8664 return true; 8830
8831 while (true)
8832 {
8833 handlerRegionHandleRequest(this, currentUUID);
8834
8835 lock (RegionHandleRequests)
8836 {
8837 // exit condition, nothing to do or closed
8838 // current code seems to assume we may loose the handler at anytime,
8839 // so keep checking it
8840 handlerRegionHandleRequest = OnRegionHandleRequest;
8841
8842 if (RegionHandleRequests.Count == 0 || !IsActive || handlerRegionHandleRequest == null)
8843 {
8844 RegionHandleRequests.Clear();
8845 RegionHandleRequestsInService = false;
8846 return true;
8847 }
8848 currentUUID = RegionHandleRequests.Dequeue();
8849 }
8850 }
8851
8852 return true; // actually unreached
8665 } 8853 }
8666 8854
8667 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack) 8855 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack)
@@ -9917,7 +10105,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9917 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 10105 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9918 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 10106 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9919 UpdateMuteListEntry.MuteData.MuteType, 10107 UpdateMuteListEntry.MuteData.MuteType,
9920 UpdateMuteListEntry.AgentData.AgentID); 10108 UpdateMuteListEntry.MuteData.MuteFlags);
9921 return true; 10109 return true;
9922 } 10110 }
9923 return false; 10111 return false;
@@ -9932,8 +10120,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9932 { 10120 {
9933 handlerRemoveMuteListEntry(this, 10121 handlerRemoveMuteListEntry(this,
9934 RemoveMuteListEntry.MuteData.MuteID, 10122 RemoveMuteListEntry.MuteData.MuteID,
9935 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 10123 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9936 RemoveMuteListEntry.AgentData.AgentID);
9937 return true; 10124 return true;
9938 } 10125 }
9939 return false; 10126 return false;
@@ -9977,10 +10164,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9977 return false; 10164 return false;
9978 } 10165 }
9979 10166
10167 private bool HandleChangeInventoryItemFlags(IClientAPI client, Packet packet)
10168 {
10169 ChangeInventoryItemFlagsPacket ChangeInventoryItemFlags =
10170 (ChangeInventoryItemFlagsPacket)packet;
10171 ChangeInventoryItemFlags handlerChangeInventoryItemFlags = OnChangeInventoryItemFlags;
10172 if (handlerChangeInventoryItemFlags != null)
10173 {
10174 foreach(ChangeInventoryItemFlagsPacket.InventoryDataBlock b in ChangeInventoryItemFlags.InventoryData)
10175 handlerChangeInventoryItemFlags(this, b.ItemID, b.Flags);
10176 return true;
10177 }
10178 return false;
10179 }
10180
9980 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack) 10181 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack)
9981 { 10182 {
9982 return true; 10183 return true;
9983 } 10184 }
10185
10186 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
10187 {
10188 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
10189
10190 #region Packet Session and User Check
10191 if (m_checkPackets)
10192 {
10193 if (packet.AgentData.SessionID != SessionId ||
10194 packet.AgentData.AgentID != AgentId)
10195 return true;
10196 }
10197 #endregion
10198 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
10199 List<InventoryItemBase> items = new List<InventoryItemBase>();
10200 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
10201 {
10202 InventoryItemBase b = new InventoryItemBase();
10203 b.ID = n.OldItemID;
10204 b.Folder = n.OldFolderID;
10205 items.Add(b);
10206 }
10207
10208 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
10209 if (handlerMoveItemsAndLeaveCopy != null)
10210 {
10211 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
10212 }
10213
10214 return true;
10215 }
9984 10216
9985 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 10217 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9986 { 10218 {
@@ -10407,6 +10639,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10407 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 10639 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10408 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 10640 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10409 10641
10642 Scene scene = (Scene)m_scene;
10643 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
10644 {
10645 ScenePresence p;
10646 if (scene.TryGetScenePresence(sender.AgentId, out p))
10647 {
10648 if (p.GodLevel >= 200)
10649 {
10650 groupProfileReply.GroupData.OpenEnrollment = true;
10651 groupProfileReply.GroupData.MembershipFee = 0;
10652 }
10653 }
10654 }
10655
10410 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 10656 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10411 } 10657 }
10412 return true; 10658 return true;
@@ -10980,11 +11226,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10980 11226
10981 StartLure handlerStartLure = OnStartLure; 11227 StartLure handlerStartLure = OnStartLure;
10982 if (handlerStartLure != null) 11228 if (handlerStartLure != null)
10983 handlerStartLure(startLureRequest.Info.LureType, 11229 {
10984 Utils.BytesToString( 11230 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10985 startLureRequest.Info.Message), 11231 {
10986 startLureRequest.TargetData[0].TargetID, 11232 handlerStartLure(startLureRequest.Info.LureType,
10987 this); 11233 Utils.BytesToString(
11234 startLureRequest.Info.Message),
11235 startLureRequest.TargetData[i].TargetID,
11236 this);
11237 }
11238 }
10988 return true; 11239 return true;
10989 } 11240 }
10990 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 11241 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -11098,10 +11349,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11098 } 11349 }
11099 #endregion 11350 #endregion
11100 11351
11101 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; 11352 ClassifiedGodDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
11102 if (handlerClassifiedGodDelete != null) 11353 if (handlerClassifiedGodDelete != null)
11103 handlerClassifiedGodDelete( 11354 handlerClassifiedGodDelete(
11104 classifiedGodDelete.Data.ClassifiedID, 11355 classifiedGodDelete.Data.ClassifiedID,
11356 classifiedGodDelete.Data.QueryID,
11105 this); 11357 this);
11106 return true; 11358 return true;
11107 } 11359 }
@@ -11467,209 +11719,147 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11467 } 11719 }
11468 else 11720 else
11469 { 11721 {
11470// m_log.DebugFormat( 11722 ClientChangeObject updatehandler = onClientChangeObject;
11471// "[CLIENT]: Processing block {0} type {1} for {2} {3}",
11472// i, block.Type, part.Name, part.LocalId);
11473 11723
11474// // Do this once since fetch parts creates a new array. 11724 if (updatehandler != null)
11475// SceneObjectPart[] parts = part.ParentGroup.Parts; 11725 {
11476// for (int j = 0; j < parts.Length; j++) 11726 ObjectChangeData udata = new ObjectChangeData();
11477// {
11478// part.StoreUndoState();
11479// parts[j].IgnoreUndoUpdate = true;
11480// }
11481 11727
11482 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; 11728 /*ubit from ll JIRA:
11729 * 0x01 position
11730 * 0x02 rotation
11731 * 0x04 scale
11732
11733 * 0x08 LINK_SET
11734 * 0x10 UNIFORM for scale
11735 */
11483 11736
11484 switch (block.Type) 11737 // translate to internal changes
11485 { 11738 // not all cases .. just the ones older code did
11486 case 1:
11487 Vector3 pos1 = new Vector3(block.Data, 0);
11488 11739
11489 UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11740 switch (block.Type)
11490 if (handlerUpdatePrimSinglePosition != null) 11741 {
11491 { 11742 case 1: //change position sp
11492 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 11743 udata.position = new Vector3(block.Data, 0);
11493 handlerUpdatePrimSinglePosition(localId, pos1, this);
11494 }
11495 break;
11496 11744
11497 case 2: 11745 udata.change = ObjectChangeType.primP;
11498 Quaternion rot1 = new Quaternion(block.Data, 0, true); 11746 updatehandler(localId, udata, this);
11747 break;
11499 11748
11500 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; 11749 case 2: // rotation sp
11501 if (handlerUpdatePrimSingleRotation != null) 11750 udata.rotation = new Quaternion(block.Data, 0, true);
11502 {
11503 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W);
11504 handlerUpdatePrimSingleRotation(localId, rot1, this);
11505 }
11506 break;
11507 11751
11508 case 3: 11752 udata.change = ObjectChangeType.primR;
11509 Vector3 rotPos = new Vector3(block.Data, 0); 11753 updatehandler(localId, udata, this);
11510 Quaternion rot2 = new Quaternion(block.Data, 12, true); 11754 break;
11511 11755
11512 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; 11756 case 3: // position plus rotation
11513 if (handlerUpdatePrimSingleRotationPosition != null) 11757 udata.position = new Vector3(block.Data, 0);
11514 { 11758 udata.rotation = new Quaternion(block.Data, 12, true);
11515 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z);
11516 // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W);
11517 handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this);
11518 }
11519 break;
11520 11759
11521 case 4: 11760 udata.change = ObjectChangeType.primPR;
11522 case 20: 11761 updatehandler(localId, udata, this);
11523 Vector3 scale4 = new Vector3(block.Data, 0); 11762 break;
11524 11763
11525 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; 11764 case 4: // scale sp
11526 if (handlerUpdatePrimScale != null) 11765 udata.scale = new Vector3(block.Data, 0);
11527 { 11766 udata.change = ObjectChangeType.primS;
11528 // m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z);
11529 handlerUpdatePrimScale(localId, scale4, this);
11530 }
11531 break;
11532 11767
11533 case 5: 11768 updatehandler(localId, udata, this);
11534 Vector3 scale1 = new Vector3(block.Data, 12); 11769 break;
11535 Vector3 pos11 = new Vector3(block.Data, 0);
11536 11770
11537 handlerUpdatePrimScale = OnUpdatePrimScale; 11771 case 0x14: // uniform scale sp
11538 if (handlerUpdatePrimScale != null) 11772 udata.scale = new Vector3(block.Data, 0);
11539 {
11540 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11541 handlerUpdatePrimScale(localId, scale1, this);
11542 11773
11543 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11774 udata.change = ObjectChangeType.primUS;
11544 if (handlerUpdatePrimSinglePosition != null) 11775 updatehandler(localId, udata, this);
11545 { 11776 break;
11546 handlerUpdatePrimSinglePosition(localId, pos11, this);
11547 }
11548 }
11549 break;
11550 11777
11551 case 9: 11778 case 5: // scale and position sp
11552 Vector3 pos2 = new Vector3(block.Data, 0); 11779 udata.position = new Vector3(block.Data, 0);
11780 udata.scale = new Vector3(block.Data, 12);
11553 11781
11554 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; 11782 udata.change = ObjectChangeType.primPS;
11783 updatehandler(localId, udata, this);
11784 break;
11555 11785
11556 if (handlerUpdateVector != null) 11786 case 0x15: //uniform scale and position
11557 { 11787 udata.position = new Vector3(block.Data, 0);
11558 handlerUpdateVector(localId, pos2, this); 11788 udata.scale = new Vector3(block.Data, 12);
11559 }
11560 break;
11561 11789
11562 case 10: 11790 udata.change = ObjectChangeType.primPUS;
11563 Quaternion rot3 = new Quaternion(block.Data, 0, true); 11791 updatehandler(localId, udata, this);
11792 break;
11564 11793
11565 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; 11794 // now group related (bit 4)
11566 if (handlerUpdatePrimRotation != null) 11795 case 9: //( 8 + 1 )group position
11567 { 11796 udata.position = new Vector3(block.Data, 0);
11568 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W);
11569 handlerUpdatePrimRotation(localId, rot3, this);
11570 }
11571 break;
11572 11797
11573 case 11: 11798 udata.change = ObjectChangeType.groupP;
11574 Vector3 pos3 = new Vector3(block.Data, 0); 11799 updatehandler(localId, udata, this);
11575 Quaternion rot4 = new Quaternion(block.Data, 12, true); 11800 break;
11576 11801
11577 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; 11802 case 0x0A: // (8 + 2) group rotation
11578 if (handlerUpdatePrimGroupRotation != null) 11803 udata.rotation = new Quaternion(block.Data, 0, true);
11579 {
11580 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11581 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W);
11582 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this);
11583 }
11584 break;
11585 case 12:
11586 case 28:
11587 Vector3 scale7 = new Vector3(block.Data, 0);
11588 11804
11589 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 11805 udata.change = ObjectChangeType.groupR;
11590 if (handlerUpdatePrimGroupScale != null) 11806 updatehandler(localId, udata, this);
11591 { 11807 break;
11592 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
11593 handlerUpdatePrimGroupScale(localId, scale7, this);
11594 }
11595 break;
11596 11808
11597 case 13: 11809 case 0x0B: //( 8 + 2 + 1) group rotation and position
11598 Vector3 scale2 = new Vector3(block.Data, 12); 11810 udata.position = new Vector3(block.Data, 0);
11599 Vector3 pos4 = new Vector3(block.Data, 0); 11811 udata.rotation = new Quaternion(block.Data, 12, true);
11600 11812
11601 handlerUpdatePrimScale = OnUpdatePrimScale; 11813 udata.change = ObjectChangeType.groupPR;
11602 if (handlerUpdatePrimScale != null) 11814 updatehandler(localId, udata, this);
11603 { 11815 break;
11604 //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11605 handlerUpdatePrimScale(localId, scale2, this);
11606 11816
11607 // Change the position based on scale (for bug number 246) 11817 case 0x0C: // (8 + 4) group scale
11608 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11818 // only afects root prim and only sent by viewer editor object tab scaling
11609 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 11819 // mouse edition only allows uniform scaling
11610 if (handlerUpdatePrimSinglePosition != null) 11820 // SL MAY CHANGE THIS in viewers
11611 {
11612 handlerUpdatePrimSinglePosition(localId, pos4, this);
11613 }
11614 }
11615 break;
11616 11821
11617 case 29: 11822 udata.scale = new Vector3(block.Data, 0);
11618 Vector3 scale5 = new Vector3(block.Data, 12);
11619 Vector3 pos5 = new Vector3(block.Data, 0);
11620 11823
11621 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 11824 udata.change = ObjectChangeType.groupS;
11622 if (handlerUpdatePrimGroupScale != null) 11825 updatehandler(localId, udata, this);
11623 {
11624 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11625 part.StoreUndoState(true);
11626 part.IgnoreUndoUpdate = true;
11627 handlerUpdatePrimGroupScale(localId, scale5, this);
11628 handlerUpdateVector = OnUpdatePrimGroupPosition;
11629 11826
11630 if (handlerUpdateVector != null) 11827 break;
11631 {
11632 handlerUpdateVector(localId, pos5, this);
11633 }
11634 11828
11635 part.IgnoreUndoUpdate = false; 11829 case 0x0D: //(8 + 4 + 1) group scale and position
11636 } 11830 // exception as above
11637 11831
11638 break; 11832 udata.position = new Vector3(block.Data, 0);
11833 udata.scale = new Vector3(block.Data, 12);
11639 11834
11640 case 21: 11835 udata.change = ObjectChangeType.groupPS;
11641 Vector3 scale6 = new Vector3(block.Data, 12); 11836 updatehandler(localId, udata, this);
11642 Vector3 pos6 = new Vector3(block.Data, 0); 11837 break;
11643 11838
11644 handlerUpdatePrimScale = OnUpdatePrimScale; 11839 case 0x1C: // (0x10 + 8 + 4 ) group scale UNIFORM
11645 if (handlerUpdatePrimScale != null) 11840 udata.scale = new Vector3(block.Data, 0);
11646 {
11647 part.StoreUndoState(false);
11648 part.IgnoreUndoUpdate = true;
11649 11841
11650 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); 11842 udata.change = ObjectChangeType.groupUS;
11651 handlerUpdatePrimScale(localId, scale6, this); 11843 updatehandler(localId, udata, this);
11652 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11844 break;
11653 if (handlerUpdatePrimSinglePosition != null)
11654 {
11655 handlerUpdatePrimSinglePosition(localId, pos6, this);
11656 }
11657 11845
11658 part.IgnoreUndoUpdate = false; 11846 case 0x1D: // (UNIFORM + GROUP + SCALE + POS)
11659 } 11847 udata.position = new Vector3(block.Data, 0);
11660 break; 11848 udata.scale = new Vector3(block.Data, 12);
11661 11849
11662 default: 11850 udata.change = ObjectChangeType.groupPUS;
11663 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); 11851 updatehandler(localId, udata, this);
11664 break; 11852 break;
11853
11854 default:
11855 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type));
11856 break;
11857 }
11665 } 11858 }
11666 11859
11667// for (int j = 0; j < parts.Length; j++)
11668// parts[j].IgnoreUndoUpdate = false;
11669 } 11860 }
11670 } 11861 }
11671 } 11862 }
11672
11673 return true; 11863 return true;
11674 } 11864 }
11675 11865
@@ -12117,7 +12307,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12117// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}", 12307// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}",
12118// requestID, taskID, (SourceType)sourceType, Name); 12308// requestID, taskID, (SourceType)sourceType, Name);
12119 12309
12310
12311 //Note, the bool returned from the below function is useless since it is always false.
12120 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 12312 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
12313
12121 } 12314 }
12122 12315
12123 /// <summary> 12316 /// <summary>
@@ -12183,7 +12376,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12183 /// <returns></returns> 12376 /// <returns></returns>
12184 private static int CalculateNumPackets(byte[] data) 12377 private static int CalculateNumPackets(byte[] data)
12185 { 12378 {
12186 const uint m_maxPacketSize = 600; 12379// const uint m_maxPacketSize = 600;
12380 uint m_maxPacketSize = MaxTransferBytesPerPacket;
12187 int numPackets = 1; 12381 int numPackets = 1;
12188 12382
12189 if (data == null) 12383 if (data == null)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index 8963756..c472176 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -158,6 +158,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
158 158
159 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC 159 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
160 private int m_maxRTO = 60000; 160 private int m_maxRTO = 60000;
161 public bool m_deliverPackets = true;
161 162
162 /// <summary> 163 /// <summary>
163 /// Default constructor 164 /// Default constructor
@@ -440,6 +441,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
440 if (category >= 0 && category < m_packetOutboxes.Length) 441 if (category >= 0 && category < m_packetOutboxes.Length)
441 { 442 {
442 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 443 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
444
445 if (m_deliverPackets == false)
446 {
447 queue.Enqueue(packet);
448 return true;
449 }
450
443 TokenBucket bucket = m_throttleCategories[category]; 451 TokenBucket bucket = m_throttleCategories[category];
444 452
445 // Don't send this packet if there is already a packet waiting in the queue 453 // Don't send this packet if there is already a packet waiting in the queue
@@ -489,7 +497,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
489 /// <returns>True if any packets were sent, otherwise false</returns> 497 /// <returns>True if any packets were sent, otherwise false</returns>
490 public bool DequeueOutgoing() 498 public bool DequeueOutgoing()
491 { 499 {
492 OutgoingPacket packet; 500 if (m_deliverPackets == false) return false;
501
502 OutgoingPacket packet = null;
493 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 503 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
494 TokenBucket bucket; 504 TokenBucket bucket;
495 bool packetSent = false; 505 bool packetSent = false;
@@ -521,32 +531,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
521 // No dequeued packet waiting to be sent, try to pull one off 531 // No dequeued packet waiting to be sent, try to pull one off
522 // this queue 532 // this queue
523 queue = m_packetOutboxes[i]; 533 queue = m_packetOutboxes[i];
524 if (queue.Dequeue(out packet)) 534 if (queue != null)
525 { 535 {
526 // A packet was pulled off the queue. See if we have 536 bool success = false;
527 // enough tokens in the bucket to send it out 537 try
528 if (bucket.RemoveTokens(packet.Buffer.DataLength))
529 { 538 {
530 // Send the packet 539 success = queue.Dequeue(out packet);
531 m_udpServer.SendPacketFinal(packet);
532 packetSent = true;
533 } 540 }
534 else 541 catch
535 { 542 {
536 // Save the dequeued packet for the next iteration 543 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
537 m_nextPackets[i] = packet;
538 } 544 }
539 545 if (success)
540 // If the queue is empty after this dequeue, fire the queue 546 {
541 // empty callback now so it has a chance to fill before we 547 // A packet was pulled off the queue. See if we have
542 // get back here 548 // enough tokens in the bucket to send it out
543 if (queue.Count == 0) 549 if (bucket.RemoveTokens(packet.Buffer.DataLength))
550 {
551 // Send the packet
552 m_udpServer.SendPacketFinal(packet);
553 packetSent = true;
554 }
555 else
556 {
557 // Save the dequeued packet for the next iteration
558 m_nextPackets[i] = packet;
559 }
560
561 // If the queue is empty after this dequeue, fire the queue
562 // empty callback now so it has a chance to fill before we
563 // get back here
564 if (queue.Count == 0)
565 emptyCategories |= CategoryToFlag(i);
566 }
567 else
568 {
569 // No packets in this queue. Fire the queue empty callback
570 // if it has not been called recently
544 emptyCategories |= CategoryToFlag(i); 571 emptyCategories |= CategoryToFlag(i);
572 }
545 } 573 }
546 else 574 else
547 { 575 {
548 // No packets in this queue. Fire the queue empty callback 576 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
549 // if it has not been called recently
550 emptyCategories |= CategoryToFlag(i); 577 emptyCategories |= CategoryToFlag(i);
551 } 578 }
552 } 579 }
@@ -704,4 +731,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP
704 } 731 }
705 } 732 }
706 } 733 }
707} \ No newline at end of file 734}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 419de66..df4bbb3 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -113,7 +113,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
113 /// <summary>Handlers for incoming packets</summary> 113 /// <summary>Handlers for incoming packets</summary>
114 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 114 //PacketEventDictionary packetEvents = new PacketEventDictionary();
115 /// <summary>Incoming packets that are awaiting handling</summary> 115 /// <summary>Incoming packets that are awaiting handling</summary>
116 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 116 //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
117
118 private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>();
117 119
118 /// <summary></summary> 120 /// <summary></summary>
119 //private UDPClientCollection m_clients = new UDPClientCollection(); 121 //private UDPClientCollection m_clients = new UDPClientCollection();
@@ -168,6 +170,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
168 /// <summary>Flag to signal when clients should send pings</summary> 170 /// <summary>Flag to signal when clients should send pings</summary>
169 protected bool m_sendPing; 171 protected bool m_sendPing;
170 172
173 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
171 private Pool<IncomingPacket> m_incomingPacketPool; 174 private Pool<IncomingPacket> m_incomingPacketPool;
172 175
173 private int m_defaultRTO = 0; 176 private int m_defaultRTO = 0;
@@ -891,21 +894,46 @@ namespace OpenSim.Region.ClientStack.LindenUDP
891 894
892 #region Packet to Client Mapping 895 #region Packet to Client Mapping
893 896
894 // UseCircuitCode handling 897 // If there is already a client for this endpoint, don't process UseCircuitCode
895 if (packet.Type == PacketType.UseCircuitCode) 898 IClientAPI client = null;
899 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
896 { 900 {
897 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 901 // UseCircuitCode handling
898 // buffer. 902 if (packet.Type == PacketType.UseCircuitCode)
899 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 903 {
904 // And if there is a UseCircuitCode pending, also drop it
905 lock (m_pendingCache)
906 {
907 if (m_pendingCache.Contains(endPoint))
908 return;
900 909
901 Util.FireAndForget(HandleUseCircuitCode, array); 910 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
911 }
902 912
903 return; 913 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
914 // buffer.
915 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
916
917 Util.FireAndForget(HandleUseCircuitCode, array);
918
919 return;
920 }
921 }
922
923 // If this is a pending connection, enqueue, don't process yet
924 lock (m_pendingCache)
925 {
926 Queue<UDPPacketBuffer> queue;
927 if (m_pendingCache.TryGetValue(endPoint, out queue))
928 {
929 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
930 queue.Enqueue(buffer);
931 return;
932 }
904 } 933 }
905 934
906 // Determine which agent this packet came from 935 // Determine which agent this packet came from
907 IClientAPI client; 936 if (client == null || !(client is LLClientView))
908 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
909 { 937 {
910 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 938 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
911 return; 939 return;
@@ -914,7 +942,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
914 udpClient = ((LLClientView)client).UDPClient; 942 udpClient = ((LLClientView)client).UDPClient;
915 943
916 if (!udpClient.IsConnected) 944 if (!udpClient.IsConnected)
945 {
946// m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName);
917 return; 947 return;
948 }
918 949
919 #endregion Packet to Client Mapping 950 #endregion Packet to Client Mapping
920 951
@@ -1044,7 +1075,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1044 incomingPacket = new IncomingPacket((LLClientView)client, packet); 1075 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1045 } 1076 }
1046 1077
1047 packetInbox.Enqueue(incomingPacket); 1078 if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1079 incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1080 packetInbox.EnqueueHigh(incomingPacket);
1081 else
1082 packetInbox.EnqueueLow(incomingPacket);
1048 } 1083 }
1049 1084
1050 #region BinaryStats 1085 #region BinaryStats
@@ -1164,6 +1199,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1164 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1199 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1165 if (client != null) 1200 if (client != null)
1166 client.SceneAgent.SendInitialDataToMe(); 1201 client.SceneAgent.SendInitialDataToMe();
1202
1203 // Now we know we can handle more data
1204 Thread.Sleep(200);
1205
1206 // Obtain the queue and remove it from the cache
1207 Queue<UDPPacketBuffer> queue = null;
1208
1209 lock (m_pendingCache)
1210 {
1211 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1212 {
1213 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1214 return;
1215 }
1216 m_pendingCache.Remove(endPoint);
1217 }
1218
1219 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1220
1221 // Reinject queued packets
1222 while(queue.Count > 0)
1223 {
1224 UDPPacketBuffer buf = queue.Dequeue();
1225 PacketReceived(buf);
1226 }
1227 queue = null;
1167 } 1228 }
1168 else 1229 else
1169 { 1230 {
@@ -1171,6 +1232,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1171 m_log.WarnFormat( 1232 m_log.WarnFormat(
1172 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1233 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1173 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1234 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1235 lock (m_pendingCache)
1236 m_pendingCache.Remove(endPoint);
1174 } 1237 }
1175 1238
1176 // m_log.DebugFormat( 1239 // m_log.DebugFormat(
@@ -1289,7 +1352,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1289 if (!client.SceneAgent.IsChildAgent) 1352 if (!client.SceneAgent.IsChildAgent)
1290 client.Kick("Simulator logged you out due to connection timeout"); 1353 client.Kick("Simulator logged you out due to connection timeout");
1291 1354
1292 client.CloseWithoutChecks(); 1355 client.CloseWithoutChecks(true);
1293 } 1356 }
1294 } 1357 }
1295 1358
@@ -1301,6 +1364,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1301 1364
1302 while (IsRunningInbound) 1365 while (IsRunningInbound)
1303 { 1366 {
1367 m_scene.ThreadAlive(1);
1304 try 1368 try
1305 { 1369 {
1306 IncomingPacket incomingPacket = null; 1370 IncomingPacket incomingPacket = null;
@@ -1348,6 +1412,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1348 1412
1349 while (base.IsRunningOutbound) 1413 while (base.IsRunningOutbound)
1350 { 1414 {
1415 m_scene.ThreadAlive(2);
1351 try 1416 try
1352 { 1417 {
1353 m_packetSent = false; 1418 m_packetSent = false;
@@ -1569,8 +1634,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1569 Packet packet = incomingPacket.Packet; 1634 Packet packet = incomingPacket.Packet;
1570 LLClientView client = incomingPacket.Client; 1635 LLClientView client = incomingPacket.Client;
1571 1636
1572 if (client.IsActive) 1637// if (client.IsActive)
1573 { 1638// {
1574 m_currentIncomingClient = client; 1639 m_currentIncomingClient = client;
1575 1640
1576 try 1641 try
@@ -1597,13 +1662,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1597 { 1662 {
1598 m_currentIncomingClient = null; 1663 m_currentIncomingClient = null;
1599 } 1664 }
1600 } 1665// }
1601 else 1666// else
1602 { 1667// {
1603 m_log.DebugFormat( 1668// m_log.DebugFormat(
1604 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1669// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1605 packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1670// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1606 } 1671// }
1607 } 1672 }
1608 1673
1609 protected void LogoutHandler(IClientAPI client) 1674 protected void LogoutHandler(IClientAPI client)
@@ -1613,8 +1678,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1613 if (!client.IsLoggingOut) 1678 if (!client.IsLoggingOut)
1614 { 1679 {
1615 client.IsLoggingOut = true; 1680 client.IsLoggingOut = true;
1616 client.Close(); 1681 client.Close(false, false);
1682 }
1683 }
1684 }
1685
1686 internal class DoubleQueue<T> where T:class
1687 {
1688 private Queue<T> m_lowQueue = new Queue<T>();
1689 private Queue<T> m_highQueue = new Queue<T>();
1690
1691 private object m_syncRoot = new object();
1692 private Semaphore m_s = new Semaphore(0, 1);
1693
1694 public DoubleQueue()
1695 {
1696 }
1697
1698 public virtual int Count
1699 {
1700 get { return m_highQueue.Count + m_lowQueue.Count; }
1701 }
1702
1703 public virtual void Enqueue(T data)
1704 {
1705 Enqueue(m_lowQueue, data);
1706 }
1707
1708 public virtual void EnqueueLow(T data)
1709 {
1710 Enqueue(m_lowQueue, data);
1711 }
1712
1713 public virtual void EnqueueHigh(T data)
1714 {
1715 Enqueue(m_highQueue, data);
1716 }
1717
1718 private void Enqueue(Queue<T> q, T data)
1719 {
1720 lock (m_syncRoot)
1721 {
1722 m_lowQueue.Enqueue(data);
1723 m_s.WaitOne(0);
1724 m_s.Release();
1725 }
1726 }
1727
1728 public virtual T Dequeue()
1729 {
1730 return Dequeue(Timeout.Infinite);
1731 }
1732
1733 public virtual T Dequeue(int tmo)
1734 {
1735 return Dequeue(TimeSpan.FromMilliseconds(tmo));
1736 }
1737
1738 public virtual T Dequeue(TimeSpan wait)
1739 {
1740 T res = null;
1741
1742 if (!Dequeue(wait, ref res))
1743 return null;
1744
1745 return res;
1746 }
1747
1748 public bool Dequeue(int timeout, ref T res)
1749 {
1750 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
1751 }
1752
1753 public bool Dequeue(TimeSpan wait, ref T res)
1754 {
1755 if (!m_s.WaitOne(wait))
1756 return false;
1757
1758 lock (m_syncRoot)
1759 {
1760 if (m_highQueue.Count > 0)
1761 res = m_highQueue.Dequeue();
1762 else
1763 res = m_lowQueue.Dequeue();
1764
1765 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
1766 return true;
1767
1768 try
1769 {
1770 m_s.Release();
1771 }
1772 catch
1773 {
1774 }
1775
1776 return true;
1777 }
1778 }
1779
1780 public virtual void Clear()
1781 {
1782
1783 lock (m_syncRoot)
1784 {
1785 // Make sure sem count is 0
1786 m_s.WaitOne(0);
1787
1788 m_lowQueue.Clear();
1789 m_highQueue.Clear();
1617 } 1790 }
1618 } 1791 }
1619 } 1792 }
1620} \ No newline at end of file 1793}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 6e6b3ef..e7d8a30 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -118,10 +118,6 @@ namespace OpenMetaverse
118 const int SIO_UDP_CONNRESET = -1744830452; 118 const int SIO_UDP_CONNRESET = -1744830452;
119 119
120 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 120 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
121
122 m_log.DebugFormat(
123 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
124 ipep.Address, ipep.Port);
125 121
126 m_udpSocket = new Socket( 122 m_udpSocket = new Socket(
127 AddressFamily.InterNetwork, 123 AddressFamily.InterNetwork,