aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs269
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs10
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs29
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs223
-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.cs204
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs1190
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs65
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs218
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs4
12 files changed, 1572 insertions, 946 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 185f9ce..580c005 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;
@@ -60,7 +61,7 @@ namespace OpenSim.Region.ClientStack.Linden
60 61
61 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); 62 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors);
62 63
63 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item); 64 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item, uint cost);
64 65
65 public delegate void NewAsset(AssetBase asset); 66 public delegate void NewAsset(AssetBase asset);
66 67
@@ -96,7 +97,10 @@ namespace OpenSim.Region.ClientStack.Linden
96 // private static readonly string m_fetchInventoryPath = "0006/"; 97 // private static readonly string m_fetchInventoryPath = "0006/";
97 private static readonly string m_copyFromNotecardPath = "0007/"; 98 private static readonly string m_copyFromNotecardPath = "0007/";
98 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. 99 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule.
99 100 private static readonly string m_getObjectPhysicsDataPath = "0101/";
101 private static readonly string m_getObjectCostPath = "0102/";
102 private static readonly string m_ResourceCostSelectedPath = "0103/";
103
100 104
101 // These are callbacks which will be setup by the scene so that we can update scene data when we 105 // These are callbacks which will be setup by the scene so that we can update scene data when we
102 // receive capability calls 106 // receive capability calls
@@ -204,6 +208,14 @@ namespace OpenSim.Region.ClientStack.Linden
204 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); 208 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
205 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); 209 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
206 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); 210 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
211 IRequestHandler getObjectPhysicsDataHandler = new RestStreamHandler("POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData);
212 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
213 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost);
214 m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler);
215 IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected);
216 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
217
218
207 219
208 m_HostCapsObj.RegisterHandler( 220 m_HostCapsObj.RegisterHandler(
209 "CopyInventoryFromNotecard", 221 "CopyInventoryFromNotecard",
@@ -375,6 +387,37 @@ namespace OpenSim.Region.ClientStack.Linden
375 return UUID.Zero; 387 return UUID.Zero;
376 } 388 }
377 389
390 private delegate void UploadWithCostCompleteDelegate(string assetName,
391 string assetDescription, UUID assetID, UUID inventoryItem,
392 UUID parentFolder, byte[] data, string inventoryType,
393 string assetType, uint cost);
394
395 private class AssetUploaderWithCost : AssetUploader
396 {
397 private uint m_cost;
398
399 public event UploadWithCostCompleteDelegate OnUpLoad;
400
401 public AssetUploaderWithCost(string assetName, string description, UUID assetID,
402 UUID inventoryItem, UUID parentFolderID, string invType, string assetType,
403 string path, IHttpServer httpServer, bool dumpAssetsToFile, uint cost) :
404 base(assetName, description, assetID, inventoryItem, parentFolderID,
405 invType, assetType, path, httpServer, dumpAssetsToFile)
406 {
407 m_cost = cost;
408
409 base.OnUpLoad += UploadCompleteHandler;
410 }
411
412 private void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
413 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
414 string assetType)
415 {
416 OnUpLoad(assetName, assetDescription, assetID, inventoryItem, parentFolder,
417 data, inventoryType, assetType, m_cost);
418 }
419 }
420
378 /// <summary> 421 /// <summary>
379 /// 422 ///
380 /// </summary> 423 /// </summary>
@@ -385,8 +428,11 @@ namespace OpenSim.Region.ClientStack.Linden
385 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString()); 428 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
386 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type); 429 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
387 430
431 uint cost = 0;
432
388 if (llsdRequest.asset_type == "texture" || 433 if (llsdRequest.asset_type == "texture" ||
389 llsdRequest.asset_type == "animation" || 434 llsdRequest.asset_type == "animation" ||
435 llsdRequest.asset_type == "mesh" ||
390 llsdRequest.asset_type == "sound") 436 llsdRequest.asset_type == "sound")
391 { 437 {
392 ScenePresence avatar = null; 438 ScenePresence avatar = null;
@@ -417,7 +463,33 @@ namespace OpenSim.Region.ClientStack.Linden
417 463
418 if (mm != null) 464 if (mm != null)
419 { 465 {
420 if (!mm.UploadCovered(client.AgentId, mm.UploadCharge)) 466 // XPTO: The cost should be calculated about here
467
468 if (llsdRequest.asset_type == "mesh")
469 {
470 cost += 20; // Constant for now to test showing a price
471
472 if (llsdRequest.asset_resources == null)
473 {
474 client.SendAgentAlertMessage("Unable to upload asset. missing information.", false);
475
476 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
477 errorResponse.uploader = "";
478 errorResponse.state = "error";
479 return errorResponse;
480 }
481
482 uint textures_cost = (uint)llsdRequest.asset_resources.texture_list.Array.Count;
483 textures_cost *= (uint)mm.UploadCharge;
484
485 cost += textures_cost;
486 }
487 else
488 {
489 cost = (uint)mm.UploadCharge;
490 }
491
492 if (!mm.UploadCovered(client.AgentId, (int)cost))
421 { 493 {
422 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); 494 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
423 495
@@ -438,9 +510,9 @@ namespace OpenSim.Region.ClientStack.Linden
438 UUID parentFolder = llsdRequest.folder_id; 510 UUID parentFolder = llsdRequest.folder_id;
439 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); 511 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
440 512
441 AssetUploader uploader = 513 AssetUploaderWithCost uploader =
442 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, 514 new AssetUploaderWithCost(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
443 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); 515 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost);
444 516
445 m_HostCapsObj.HttpListener.AddStreamHandler( 517 m_HostCapsObj.HttpListener.AddStreamHandler(
446 new BinaryStreamHandler( 518 new BinaryStreamHandler(
@@ -458,11 +530,31 @@ namespace OpenSim.Region.ClientStack.Linden
458 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + 530 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
459 uploaderPath; 531 uploaderPath;
460 532
533
461 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); 534 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
462 uploadResponse.uploader = uploaderURL; 535 uploadResponse.uploader = uploaderURL;
463 uploadResponse.state = "upload"; 536 uploadResponse.state = "upload";
537 uploadResponse.upload_price = (int)cost;
538
539 // use fake values for now
540 if (llsdRequest.asset_type == "mesh")
541 {
542 uploadResponse.data = new LLSDAssetUploadResponseData();
543 uploadResponse.data.model_streaming_cost = 1.0;
544 uploadResponse.data.simulation_cost = 1.5;
545
546 uploadResponse.data.physics_cost = 2.0;
547 uploadResponse.data.resource_cost = 3.0;
548 uploadResponse.data.upload_price_breakdown.mesh_instance = 1;
549 uploadResponse.data.upload_price_breakdown.mesh_physics = 2;
550 uploadResponse.data.upload_price_breakdown.mesh_streaming = 3;
551 uploadResponse.data.upload_price_breakdown.texture = 5;
552 uploadResponse.data.upload_price_breakdown.model = 4;
553 }
554
464 uploader.OnUpLoad += UploadCompleteHandler; 555 uploader.OnUpLoad += UploadCompleteHandler;
465 return uploadResponse; 556 return uploadResponse;
557
466 } 558 }
467 559
468 /// <summary> 560 /// <summary>
@@ -473,7 +565,7 @@ namespace OpenSim.Region.ClientStack.Linden
473 /// <param name="data"></param> 565 /// <param name="data"></param>
474 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, 566 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
475 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, 567 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
476 string assetType) 568 string assetType, uint cost)
477 { 569 {
478 m_log.DebugFormat( 570 m_log.DebugFormat(
479 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}", 571 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}",
@@ -692,7 +784,7 @@ namespace OpenSim.Region.ClientStack.Linden
692 784
693 if (AddNewInventoryItem != null) 785 if (AddNewInventoryItem != null)
694 { 786 {
695 AddNewInventoryItem(m_HostCapsObj.AgentID, item); 787 AddNewInventoryItem(m_HostCapsObj.AgentID, item, cost);
696 } 788 }
697 } 789 }
698 790
@@ -854,10 +946,158 @@ namespace OpenSim.Region.ClientStack.Linden
854 response["int_response_code"] = 200; 946 response["int_response_code"] = 200;
855 return LLSDHelpers.SerialiseLLSDReply(response); 947 return LLSDHelpers.SerialiseLLSDReply(response);
856 } 948 }
949
950 public string GetObjectPhysicsData(string request, string path,
951 string param, IOSHttpRequest httpRequest,
952 IOSHttpResponse httpResponse)
953 {
954 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
955 OSDMap resp = new OSDMap();
956 OSDArray object_ids = (OSDArray)req["object_ids"];
957
958 for (int i = 0 ; i < object_ids.Count ; i++)
959 {
960 UUID uuid = object_ids[i].AsUUID();
961
962 SceneObjectPart obj = m_Scene.GetSceneObjectPart(uuid);
963 if (obj != null)
964 {
965 OSDMap object_data = new OSDMap();
966
967 object_data["PhysicsShapeType"] = obj.PhysicsShapeType;
968 object_data["Density"] = obj.Density;
969 object_data["Friction"] = obj.Friction;
970 object_data["Restitution"] = obj.Bounciness;
971 object_data["GravityMultiplier"] = obj.GravityModifier;
972
973 resp[uuid.ToString()] = object_data;
974 }
975 }
976
977 string response = OSDParser.SerializeLLSDXmlString(resp);
978 return response;
979 }
980
981 public string GetObjectCost(string request, string path,
982 string param, IOSHttpRequest httpRequest,
983 IOSHttpResponse httpResponse)
984 {
985 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
986 OSDMap resp = new OSDMap();
987
988 OSDArray object_ids = (OSDArray)req["object_ids"];
989
990 for (int i = 0; i < object_ids.Count; i++)
991 {
992 UUID uuid = object_ids[i].AsUUID();
993
994 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
995
996 if (part != null)
997 {
998 SceneObjectGroup grp = part.ParentGroup;
999 if (grp != null)
1000 {
1001 float linksetCost;
1002 float linksetPhysCost;
1003 float partCost;
1004 float partPhysCost;
1005
1006 grp.GetResourcesCosts(part, out linksetCost, out linksetPhysCost, out partCost, out partPhysCost);
1007
1008 OSDMap object_data = new OSDMap();
1009 object_data["linked_set_resource_cost"] = linksetCost;
1010 object_data["resource_cost"] = partCost;
1011 object_data["physics_cost"] = partPhysCost;
1012 object_data["linked_set_physics_cost"] = linksetPhysCost;
1013
1014 resp[uuid.ToString()] = object_data;
1015 }
1016 }
1017 }
1018
1019 string response = OSDParser.SerializeLLSDXmlString(resp);
1020 return response;
1021 }
1022
1023 public string ResourceCostSelected(string request, string path,
1024 string param, IOSHttpRequest httpRequest,
1025 IOSHttpResponse httpResponse)
1026 {
1027 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1028 OSDMap resp = new OSDMap();
1029
1030
1031 float phys=0;
1032 float stream=0;
1033 float simul=0;
1034
1035 if (req.ContainsKey("selected_roots"))
1036 {
1037 OSDArray object_ids = (OSDArray)req["selected_roots"];
1038
1039 // should go by SOG suming costs for all parts
1040 // ll v3 works ok with several objects select we get the list and adds ok
1041 // FS calls per object so results are wrong guess fs bug
1042 for (int i = 0; i < object_ids.Count; i++)
1043 {
1044 UUID uuid = object_ids[i].AsUUID();
1045 float Physc;
1046 float simulc;
1047 float streamc;
1048
1049 SceneObjectGroup grp = m_Scene.GetGroupByPrim(uuid);
1050 if (grp != null)
1051 {
1052 grp.GetSelectedCosts(out Physc, out streamc, out simulc);
1053 phys += Physc;
1054 stream += streamc;
1055 simul += simulc;
1056 }
1057 }
1058 }
1059 else if (req.ContainsKey("selected_prims"))
1060 {
1061 OSDArray object_ids = (OSDArray)req["selected_prims"];
1062
1063 // don't see in use in any of the 2 viewers
1064 // guess it should be for edit linked but... nothing
1065 // should go to SOP per part
1066 for (int i = 0; i < object_ids.Count; i++)
1067 {
1068 UUID uuid = object_ids[i].AsUUID();
1069
1070 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1071 if (part != null)
1072 {
1073 phys += part.PhysicsCost;
1074 stream += part.StreamingCost;
1075 simul += part.SimulationCost;
1076 }
1077 }
1078 }
1079
1080 if (simul != 0)
1081 {
1082 OSDMap object_data = new OSDMap();
1083
1084 object_data["physics"] = phys;
1085 object_data["streaming"] = stream;
1086 object_data["simulation"] = simul;
1087
1088 resp["selected"] = object_data;
1089 }
1090
1091 string response = OSDParser.SerializeLLSDXmlString(resp);
1092 return response;
1093 }
857 } 1094 }
858 1095
859 public class AssetUploader 1096 public class AssetUploader
860 { 1097 {
1098 private static readonly ILog m_log =
1099 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
1100
861 public event UpLoadedAsset OnUpLoad; 1101 public event UpLoadedAsset OnUpLoad;
862 private UpLoadedAsset handlerUpLoad = null; 1102 private UpLoadedAsset handlerUpLoad = null;
863 1103
@@ -872,6 +1112,7 @@ namespace OpenSim.Region.ClientStack.Linden
872 1112
873 private string m_invType = String.Empty; 1113 private string m_invType = String.Empty;
874 private string m_assetType = String.Empty; 1114 private string m_assetType = String.Empty;
1115 private Timer m_timeoutTimer = new Timer();
875 1116
876 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, 1117 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
877 UUID parentFolderID, string invType, string assetType, string path, 1118 UUID parentFolderID, string invType, string assetType, string path,
@@ -887,6 +1128,11 @@ namespace OpenSim.Region.ClientStack.Linden
887 m_assetType = assetType; 1128 m_assetType = assetType;
888 m_invType = invType; 1129 m_invType = invType;
889 m_dumpAssetsToFile = dumpAssetsToFile; 1130 m_dumpAssetsToFile = dumpAssetsToFile;
1131
1132 m_timeoutTimer.Elapsed += TimedOut;
1133 m_timeoutTimer.Interval = 120000;
1134 m_timeoutTimer.AutoReset = false;
1135 m_timeoutTimer.Start();
890 } 1136 }
891 1137
892 /// <summary> 1138 /// <summary>
@@ -908,6 +1154,7 @@ namespace OpenSim.Region.ClientStack.Linden
908 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); 1154 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
909 1155
910 httpListener.RemoveStreamHandler("POST", uploaderPath); 1156 httpListener.RemoveStreamHandler("POST", uploaderPath);
1157 m_timeoutTimer.Stop();
911 1158
912 // TODO: probably make this a better set of extensions here 1159 // TODO: probably make this a better set of extensions here
913 string extension = ".jp2"; 1160 string extension = ".jp2";
@@ -929,6 +1176,12 @@ namespace OpenSim.Region.ClientStack.Linden
929 return res; 1176 return res;
930 } 1177 }
931 1178
1179 private void TimedOut(object sender, ElapsedEventArgs args)
1180 {
1181 m_log.InfoFormat("[CAPS]: Removing URL and handler for timed out mesh upload");
1182 httpListener.RemoveStreamHandler("POST", uploaderPath);
1183 }
1184
932 ///Left this in and commented in case there are unforseen issues 1185 ///Left this in and commented in case there are unforseen issues
933 //private void SaveAssetToFile(string filename, byte[] data) 1186 //private void SaveAssetToFile(string filename, byte[] data)
934 //{ 1187 //{
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index 594b229..ebfe687 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -377,7 +377,7 @@ namespace OpenSim.Region.ClientStack.Linden
377 // TODO: Add EventQueueGet name/description for diagnostics 377 // TODO: Add EventQueueGet name/description for diagnostics
378 MainServer.Instance.AddPollServiceHTTPHandler( 378 MainServer.Instance.AddPollServiceHTTPHandler(
379 eventQueueGetPath, 379 eventQueueGetPath,
380 new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID)); 380 new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID, 1000));
381 381
382// m_log.DebugFormat( 382// m_log.DebugFormat(
383// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}", 383// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}",
@@ -831,5 +831,13 @@ namespace OpenSim.Region.ClientStack.Linden
831 { 831 {
832 return EventQueueHelper.BuildEvent(eventName, eventBody); 832 return EventQueueHelper.BuildEvent(eventName, eventBody);
833 } 833 }
834
835 public void partPhysicsProperties(uint localID, byte physhapetype,
836 float density, float friction, float bounce, float gravmod,UUID avatarID)
837 {
838 OSD item = EventQueueHelper.partPhysicsProperties(localID, physhapetype,
839 density, friction, bounce, gravmod);
840 Enqueue(item, avatarID);
841 }
834 } 842 }
835} 843}
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..5b125ea 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,73 @@ 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 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
58// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 57
59
60 private Scene m_scene; 58 private Scene m_scene;
61 private IAssetService m_assetService;
62 59
63 private bool m_Enabled = false; 60 private static GetTextureHandler m_getTextureHandler;
61
62 private IAssetService m_assetService = null;
64 63
65 // TODO: Change this to a config option 64 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
66 const string REDIRECT_URL = null; 65 private static Thread[] m_workerThreads = null;
67 66
68 private string m_URL; 67 private static OpenMetaverse.BlockingQueue<PollServiceTextureEventArgs> m_queue =
68 new OpenMetaverse.BlockingQueue<PollServiceTextureEventArgs>();
69 69
70 #region ISharedRegionModule Members 70 #region ISharedRegionModule Members
71 71
72 public void Initialise(IConfigSource source) 72 public void Initialise(IConfigSource source)
73 { 73 {
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 } 74 }
83 75
84 public void AddRegion(Scene s) 76 public void AddRegion(Scene s)
85 { 77 {
86 if (!m_Enabled)
87 return;
88
89 m_scene = s; 78 m_scene = s;
79 m_assetService = s.AssetService;
90 } 80 }
91 81
92 public void RemoveRegion(Scene s) 82 public void RemoveRegion(Scene s)
93 { 83 {
94 if (!m_Enabled)
95 return;
96
97 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 84 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
85 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
98 m_scene = null; 86 m_scene = null;
99 } 87 }
100 88
101 public void RegionLoaded(Scene s) 89 public void RegionLoaded(Scene s)
102 { 90 {
103 if (!m_Enabled) 91 // We'll reuse the same handler for all requests.
104 return; 92 m_getTextureHandler = new GetTextureHandler(m_assetService);
105 93
106 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
107 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 94 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
95 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
96
97 if (m_workerThreads == null)
98 {
99 m_workerThreads = new Thread[4];
100
101 for (uint i = 0; i < 4; i++)
102 {
103 m_workerThreads[i] = Watchdog.StartThread(DoTextureRequests,
104 String.Format("TextureWorkerThread{0}", i),
105 ThreadPriority.Normal,
106 false,
107 true,
108 null,
109 int.MaxValue);
110 }
111 }
108 } 112 }
109 113
110 public void PostInitialise() 114 public void PostInitialise()
@@ -122,24 +126,155 @@ namespace OpenSim.Region.ClientStack.Linden
122 126
123 #endregion 127 #endregion
124 128
125 public void RegisterCaps(UUID agentID, Caps caps) 129 ~GetTextureModule()
130 {
131 foreach (Thread t in m_workerThreads)
132 t.Abort();
133 }
134
135 private class PollServiceTextureEventArgs : PollServiceEventArgs
126 { 136 {
127 UUID capID = UUID.Random(); 137 private List<Hashtable> requests =
138 new List<Hashtable>();
139 private Dictionary<UUID, Hashtable> responses =
140 new Dictionary<UUID, Hashtable>();
141
142 private Scene m_scene;
128 143
129 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); 144 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
130 if (m_URL == "localhost") 145 base(null, null, null, null, pId, 30000)
131 { 146 {
132// m_log.DebugFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 147 m_scene = scene;
133 caps.RegisterHandler( 148
134 "GetTexture", 149 HasEvents = (x, y) => { return this.responses.ContainsKey(x); };
135 new GetTextureHandler("/CAPS/" + capID + "/", m_assetService, "GetTexture", agentID.ToString())); 150 GetEvents = (x, y, s) =>
151 {
152 try
153 {
154 return this.responses[x];
155 }
156 finally
157 {
158 responses.Remove(x);
159 }
160 };
161
162 Request = (x, y) =>
163 {
164 y["RequestID"] = x.ToString();
165 lock (this.requests)
166 this.requests.Add(y);
167
168 m_queue.Enqueue(this);
169 };
170
171 NoEvents = (x, y) =>
172 {
173 lock (this.requests)
174 {
175 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
176 requests.Remove(request);
177 }
178
179 Hashtable response = new Hashtable();
180
181 response["int_response_code"] = 500;
182 response["str_response_string"] = "Script timeout";
183 response["content_type"] = "text/plain";
184 response["keepalive"] = false;
185 response["reusecontext"] = false;
186
187 return response;
188 };
136 } 189 }
137 else 190
191 public void Process()
138 { 192 {
139// m_log.DebugFormat("[GETTEXTURE]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName); 193 Hashtable response;
140 caps.RegisterHandler("GetTexture", m_URL); 194 Hashtable request = null;
195
196 try
197 {
198 lock (this.requests)
199 {
200 request = requests[0];
201 requests.RemoveAt(0);
202 }
203 }
204 catch
205 {
206 return;
207 }
208
209 UUID requestID = new UUID(request["RequestID"].ToString());
210
211 // If the avatar is gone, don't bother to get the texture
212 if (m_scene.GetScenePresence(Id) == null)
213 {
214 response = new Hashtable();
215
216 response["int_response_code"] = 500;
217 response["str_response_string"] = "Script timeout";
218 response["content_type"] = "text/plain";
219 response["keepalive"] = false;
220 response["reusecontext"] = false;
221
222 responses[requestID] = response;
223 return;
224 }
225
226 response = m_getTextureHandler.Handle(request);
227
228 responses[requestID] = response;
229 }
230 }
231
232 private void RegisterCaps(UUID agentID, Caps caps)
233 {
234 string capUrl = "/CAPS/" + UUID.Random() + "/";
235
236 // Register this as a poll service
237 // absurd large timeout to tune later to make a bit less than viewer
238 PollServiceTextureEventArgs args = new PollServiceTextureEventArgs(agentID, m_scene);
239
240 args.Type = PollServiceEventArgs.EventType.Texture;
241 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
242
243 string hostName = m_scene.RegionInfo.ExternalHostName;
244 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
245 string protocol = "http";
246
247 if (MainServer.Instance.UseSSL)
248 {
249 hostName = MainServer.Instance.SSLCommonName;
250 port = MainServer.Instance.SSLPort;
251 protocol = "https";
141 } 252 }
253 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
254
255 m_capsDict[agentID] = capUrl;
142 } 256 }
143 257
258 private void DeregisterCaps(UUID agentID, Caps caps)
259 {
260 string capUrl;
261
262 if (m_capsDict.TryGetValue(agentID, out capUrl))
263 {
264 MainServer.Instance.RemoveHTTPHandler("", capUrl);
265 m_capsDict.Remove(agentID);
266 }
267 }
268
269 private void DoTextureRequests()
270 {
271 while (true)
272 {
273 PollServiceTextureEventArgs args = m_queue.Dequeue();
274
275 args.Process();
276 }
277 }
144 } 278 }
279
145} 280}
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 36af55f..413536d 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..4908c2c 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,65 @@ 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 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 56
53 private Scene m_scene; 57 private Scene m_scene;
54 58
55 private IInventoryService m_InventoryService; 59 private IInventoryService m_InventoryService;
56 private ILibraryService m_LibraryService; 60 private ILibraryService m_LibraryService;
57 61
58 private bool m_Enabled; 62 private static WebFetchInvDescHandler m_webFetchHandler;
59 63
60 private string m_fetchInventoryDescendents2Url; 64 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
61 private string m_webFetchInventoryDescendentsUrl; 65 private static Thread[] m_workerThreads = null;
62 66
63 private WebFetchInvDescHandler m_webFetchHandler; 67 private static OpenMetaverse.BlockingQueue<PollServiceInventoryEventArgs> m_queue =
68 new OpenMetaverse.BlockingQueue<PollServiceInventoryEventArgs>();
64 69
65 #region ISharedRegionModule Members 70 #region ISharedRegionModule Members
66 71
67 public void Initialise(IConfigSource source) 72 public void Initialise(IConfigSource source)
68 { 73 {
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 } 74 }
81 75
82 public void AddRegion(Scene s) 76 public void AddRegion(Scene s)
83 { 77 {
84 if (!m_Enabled)
85 return;
86
87 m_scene = s; 78 m_scene = s;
88 } 79 }
89 80
90 public void RemoveRegion(Scene s) 81 public void RemoveRegion(Scene s)
91 { 82 {
92 if (!m_Enabled)
93 return;
94
95 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 83 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
84 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
96 m_scene = null; 85 m_scene = null;
97 } 86 }
98 87
99 public void RegionLoaded(Scene s) 88 public void RegionLoaded(Scene s)
100 { 89 {
101 if (!m_Enabled)
102 return;
103
104 m_InventoryService = m_scene.InventoryService; 90 m_InventoryService = m_scene.InventoryService;
105 m_LibraryService = m_scene.LibraryService; 91 m_LibraryService = m_scene.LibraryService;
106 92
107 // We'll reuse the same handler for all requests. 93 // We'll reuse the same handler for all requests.
108 if (m_fetchInventoryDescendents2Url == "localhost" || m_webFetchInventoryDescendentsUrl == "localhost") 94 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
109 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
110 95
111 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 96 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
97 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
98
99 if (m_workerThreads == null)
100 {
101 m_workerThreads = new Thread[2];
102
103 for (uint i = 0; i < 2; i++)
104 {
105 m_workerThreads[i] = Watchdog.StartThread(DoInventoryRequests,
106 String.Format("InventoryWorkerThread{0}", i),
107 ThreadPriority.Normal,
108 false,
109 true,
110 null,
111 int.MaxValue);
112 }
113 }
112 } 114 }
113 115
114 public void PostInitialise() 116 public void PostInitialise()
@@ -126,43 +128,141 @@ namespace OpenSim.Region.ClientStack.Linden
126 128
127 #endregion 129 #endregion
128 130
129 private void RegisterCaps(UUID agentID, Caps caps) 131 ~WebFetchInvDescModule()
130 { 132 {
131 if (m_webFetchInventoryDescendentsUrl != "") 133 foreach (Thread t in m_workerThreads)
132 RegisterFetchCap(agentID, caps, "WebFetchInventoryDescendents", m_webFetchInventoryDescendentsUrl); 134 t.Abort();
133
134 if (m_fetchInventoryDescendents2Url != "")
135 RegisterFetchCap(agentID, caps, "FetchInventoryDescendents2", m_fetchInventoryDescendents2Url);
136 } 135 }
137 136
138 private void RegisterFetchCap(UUID agentID, Caps caps, string capName, string url) 137 private class PollServiceInventoryEventArgs : PollServiceEventArgs
139 { 138 {
140 string capUrl; 139 private List<Hashtable> requests =
140 new List<Hashtable>();
141 private Dictionary<UUID, Hashtable> responses =
142 new Dictionary<UUID, Hashtable>();
141 143
142 if (url == "localhost") 144 public PollServiceInventoryEventArgs(UUID pId) :
145 base(null, null, null, null, pId, 30000)
143 { 146 {
144 capUrl = "/CAPS/" + UUID.Random(); 147 HasEvents = (x, y) => { return this.responses.ContainsKey(x); };
148 GetEvents = (x, y, s) =>
149 {
150 try
151 {
152 return this.responses[x];
153 }
154 finally
155 {
156 responses.Remove(x);
157 }
158 };
159
160 Request = (x, y) =>
161 {
162 y["RequestID"] = x.ToString();
163 lock (this.requests)
164 this.requests.Add(y);
165
166 m_queue.Enqueue(this);
167 };
168
169 NoEvents = (x, y) =>
170 {
171 lock (this.requests)
172 {
173 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
174 requests.Remove(request);
175 }
176
177 Hashtable response = new Hashtable();
178
179 response["int_response_code"] = 500;
180 response["str_response_string"] = "Script timeout";
181 response["content_type"] = "text/plain";
182 response["keepalive"] = false;
183 response["reusecontext"] = false;
184
185 return response;
186 };
187 }
188
189 public void Process()
190 {
191 Hashtable request = null;
192
193 try
194 {
195 lock (this.requests)
196 {
197 request = requests[0];
198 requests.RemoveAt(0);
199 }
200 }
201 catch
202 {
203 return;
204 }
205
206 UUID requestID = new UUID(request["RequestID"].ToString());
145 207
146 IRequestHandler reqHandler 208 Hashtable response = new Hashtable();
147 = new RestStreamHandler(
148 "POST",
149 capUrl,
150 m_webFetchHandler.FetchInventoryDescendentsRequest,
151 "FetchInventoryDescendents2",
152 agentID.ToString());
153 209
154 caps.RegisterHandler(capName, reqHandler); 210 response["int_response_code"] = 200;
211 response["content_type"] = "text/plain";
212 response["keepalive"] = false;
213 response["reusecontext"] = false;
214
215 response["str_response_string"] = m_webFetchHandler.FetchInventoryDescendentsRequest(request["body"].ToString(), String.Empty, String.Empty, null, null);
216
217 responses[requestID] = response;
155 } 218 }
156 else 219 }
220
221 private void RegisterCaps(UUID agentID, Caps caps)
222 {
223 string capUrl = "/CAPS/" + UUID.Random() + "/";
224
225 // Register this as a poll service
226 // absurd large timeout to tune later to make a bit less than viewer
227 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(agentID);
228
229 args.Type = PollServiceEventArgs.EventType.Inventory;
230 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
231
232 string hostName = m_scene.RegionInfo.ExternalHostName;
233 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
234 string protocol = "http";
235
236 if (MainServer.Instance.UseSSL)
157 { 237 {
158 capUrl = url; 238 hostName = MainServer.Instance.SSLCommonName;
239 port = MainServer.Instance.SSLPort;
240 protocol = "https";
241 }
242 caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
243
244 m_capsDict[agentID] = capUrl;
245 }
159 246
160 caps.RegisterHandler(capName, capUrl); 247 private void DeregisterCaps(UUID agentID, Caps caps)
248 {
249 string capUrl;
250
251 if (m_capsDict.TryGetValue(agentID, out capUrl))
252 {
253 MainServer.Instance.RemoveHTTPHandler("", capUrl);
254 m_capsDict.Remove(agentID);
161 } 255 }
256 }
162 257
163// m_log.DebugFormat( 258 private void DoInventoryRequests()
164// "[WEB FETCH INV DESC MODULE]: Registered capability {0} at {1} in region {2} for {3}", 259 {
165// capName, capUrl, m_scene.RegionInfo.RegionName, agentID); 260 while (true)
261 {
262 PollServiceInventoryEventArgs args = m_queue.Dequeue();
263
264 args.Process();
265 }
166 } 266 }
167 } 267 }
168} \ No newline at end of file 268}
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 d05ffea..74b27d7 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -98,6 +98,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
98 public event AvatarPickerRequest OnAvatarPickerRequest; 98 public event AvatarPickerRequest OnAvatarPickerRequest;
99 public event StartAnim OnStartAnim; 99 public event StartAnim OnStartAnim;
100 public event StopAnim OnStopAnim; 100 public event StopAnim OnStopAnim;
101 public event ChangeAnim OnChangeAnim;
101 public event Action<IClientAPI> OnRequestAvatarsData; 102 public event Action<IClientAPI> OnRequestAvatarsData;
102 public event LinkObjects OnLinkObjects; 103 public event LinkObjects OnLinkObjects;
103 public event DelinkObjects OnDelinkObjects; 104 public event DelinkObjects OnDelinkObjects;
@@ -125,6 +126,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
125 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; 126 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
126 public event UpdatePrimFlags OnUpdatePrimFlags; 127 public event UpdatePrimFlags OnUpdatePrimFlags;
127 public event UpdatePrimTexture OnUpdatePrimTexture; 128 public event UpdatePrimTexture OnUpdatePrimTexture;
129 public event ClientChangeObject onClientChangeObject;
128 public event UpdateVector OnUpdatePrimGroupPosition; 130 public event UpdateVector OnUpdatePrimGroupPosition;
129 public event UpdateVector OnUpdatePrimSinglePosition; 131 public event UpdateVector OnUpdatePrimSinglePosition;
130 public event UpdatePrimRotation OnUpdatePrimGroupRotation; 132 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
@@ -158,6 +160,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
158 public event RequestTaskInventory OnRequestTaskInventory; 160 public event RequestTaskInventory OnRequestTaskInventory;
159 public event UpdateInventoryItem OnUpdateInventoryItem; 161 public event UpdateInventoryItem OnUpdateInventoryItem;
160 public event CopyInventoryItem OnCopyInventoryItem; 162 public event CopyInventoryItem OnCopyInventoryItem;
163 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
161 public event MoveInventoryItem OnMoveInventoryItem; 164 public event MoveInventoryItem OnMoveInventoryItem;
162 public event RemoveInventoryItem OnRemoveInventoryItem; 165 public event RemoveInventoryItem OnRemoveInventoryItem;
163 public event RemoveInventoryFolder OnRemoveInventoryFolder; 166 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -256,7 +259,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
256 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 259 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
257 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 260 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
258 public event ClassifiedDelete OnClassifiedDelete; 261 public event ClassifiedDelete OnClassifiedDelete;
259 public event ClassifiedDelete OnClassifiedGodDelete; 262 public event ClassifiedGodDelete OnClassifiedGodDelete;
260 public event EventNotificationAddRequest OnEventNotificationAddRequest; 263 public event EventNotificationAddRequest OnEventNotificationAddRequest;
261 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 264 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
262 public event EventGodDelete OnEventGodDelete; 265 public event EventGodDelete OnEventGodDelete;
@@ -287,6 +290,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
287 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 290 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
288 public event SimWideDeletesDelegate OnSimWideDeletes; 291 public event SimWideDeletesDelegate OnSimWideDeletes;
289 public event SendPostcard OnSendPostcard; 292 public event SendPostcard OnSendPostcard;
293 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
290 public event MuteListEntryUpdate OnUpdateMuteListEntry; 294 public event MuteListEntryUpdate OnUpdateMuteListEntry;
291 public event MuteListEntryRemove OnRemoveMuteListEntry; 295 public event MuteListEntryRemove OnRemoveMuteListEntry;
292 public event GodlikeMessage onGodlikeMessage; 296 public event GodlikeMessage onGodlikeMessage;
@@ -325,6 +329,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
325 private Prioritizer m_prioritizer; 329 private Prioritizer m_prioritizer;
326 private bool m_disableFacelights = false; 330 private bool m_disableFacelights = false;
327 331
332 private const uint MaxTransferBytesPerPacket = 600;
333
334
328 /// <value> 335 /// <value>
329 /// List used in construction of data blocks for an object update packet. This is to stop us having to 336 /// List used in construction of data blocks for an object update packet. This is to stop us having to
330 /// continually recreate it. 337 /// continually recreate it.
@@ -336,14 +343,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
336 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 343 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
337 /// ownerless phantom. 344 /// ownerless phantom.
338 /// 345 ///
339 /// All manipulation of this set has to occur under a lock 346 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
340 /// 347 ///
341 /// </value> 348 /// </value>
342 protected HashSet<uint> m_killRecord; 349// protected HashSet<uint> m_killRecord;
343 350
344// protected HashSet<uint> m_attachmentsSent; 351// protected HashSet<uint> m_attachmentsSent;
345 352
346 private int m_moneyBalance; 353 private int m_moneyBalance;
354 private bool m_deliverPackets = true;
347 private int m_animationSequenceNumber = 1; 355 private int m_animationSequenceNumber = 1;
348 private bool m_SendLogoutPacketWhenClosing = true; 356 private bool m_SendLogoutPacketWhenClosing = true;
349 private AgentUpdateArgs lastarg; 357 private AgentUpdateArgs lastarg;
@@ -380,6 +388,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
380 get { return m_startpos; } 388 get { return m_startpos; }
381 set { m_startpos = value; } 389 set { m_startpos = value; }
382 } 390 }
391 public bool DeliverPackets
392 {
393 get { return m_deliverPackets; }
394 set {
395 m_deliverPackets = value;
396 m_udpClient.m_deliverPackets = value;
397 }
398 }
383 public UUID AgentId { get { return m_agentId; } } 399 public UUID AgentId { get { return m_agentId; } }
384 public ISceneAgent SceneAgent { get; set; } 400 public ISceneAgent SceneAgent { get; set; }
385 public UUID ActiveGroupId { get { return m_activeGroupID; } } 401 public UUID ActiveGroupId { get { return m_activeGroupID; } }
@@ -457,7 +473,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
457 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); 473 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
458 m_entityProps = new PriorityQueue(m_scene.Entities.Count); 474 m_entityProps = new PriorityQueue(m_scene.Entities.Count);
459 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); 475 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
460 m_killRecord = new HashSet<uint>(); 476// m_killRecord = new HashSet<uint>();
461// m_attachmentsSent = new HashSet<uint>(); 477// m_attachmentsSent = new HashSet<uint>();
462 478
463 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 479 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
@@ -487,12 +503,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
487 503
488 #region Client Methods 504 #region Client Methods
489 505
506
507 /// <summary>
508 /// Close down the client view
509 /// </summary>
490 public void Close() 510 public void Close()
491 { 511 {
492 Close(false); 512 Close(true, false);
493 } 513 }
494 514
495 public void Close(bool force) 515 public void Close(bool sendStop, bool force)
496 { 516 {
497 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 517 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
498 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 518 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
@@ -504,7 +524,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
504 return; 524 return;
505 525
506 IsActive = false; 526 IsActive = false;
507 CloseWithoutChecks(); 527 CloseWithoutChecks(sendStop);
508 } 528 }
509 } 529 }
510 530
@@ -517,12 +537,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
517 /// 537 ///
518 /// Callers must lock ClosingSyncLock before calling. 538 /// Callers must lock ClosingSyncLock before calling.
519 /// </remarks> 539 /// </remarks>
520 public void CloseWithoutChecks() 540 public void CloseWithoutChecks(bool sendStop)
521 { 541 {
522 m_log.DebugFormat( 542 m_log.DebugFormat(
523 "[CLIENT]: Close has been called for {0} attached to scene {1}", 543 "[CLIENT]: Close has been called for {0} attached to scene {1}",
524 Name, m_scene.RegionInfo.RegionName); 544 Name, m_scene.RegionInfo.RegionName);
525 545
546 if (sendStop)
547 {
548 // Send the STOP packet
549 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
550 OutPacket(disable, ThrottleOutPacketType.Unknown);
551 }
552
526 // Shutdown the image manager 553 // Shutdown the image manager
527 ImageManager.Close(); 554 ImageManager.Close();
528 555
@@ -780,7 +807,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
780 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType); 807 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType);
781 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes; 808 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes;
782 809
783 OutPacket(handshake, ThrottleOutPacketType.Task); 810// OutPacket(handshake, ThrottleOutPacketType.Task);
811 // use same as MoveAgentIntoRegion (both should be task )
812 OutPacket(handshake, ThrottleOutPacketType.Unknown);
784 } 813 }
785 814
786 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) 815 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
@@ -819,7 +848,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
819 reply.ChatData.OwnerID = fromAgentID; 848 reply.ChatData.OwnerID = fromAgentID;
820 reply.ChatData.SourceID = fromAgentID; 849 reply.ChatData.SourceID = fromAgentID;
821 850
822 OutPacket(reply, ThrottleOutPacketType.Task); 851 OutPacket(reply, ThrottleOutPacketType.Unknown);
823 } 852 }
824 853
825 /// <summary> 854 /// <summary>
@@ -1105,6 +1134,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1105 public virtual void SendLayerData(float[] map) 1134 public virtual void SendLayerData(float[] map)
1106 { 1135 {
1107 Util.FireAndForget(DoSendLayerData, map); 1136 Util.FireAndForget(DoSendLayerData, map);
1137
1138 // Send it sync, and async. It's not that much data
1139 // and it improves user experience just so much!
1140 DoSendLayerData(map);
1108 } 1141 }
1109 1142
1110 /// <summary> 1143 /// <summary>
@@ -1117,16 +1150,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1117 1150
1118 try 1151 try
1119 { 1152 {
1120 //for (int y = 0; y < 16; y++) 1153 for (int y = 0; y < 16; y++)
1121 //{ 1154 {
1122 // for (int x = 0; x < 16; x++) 1155 for (int x = 0; x < 16; x+=4)
1123 // { 1156 {
1124 // SendLayerData(x, y, map); 1157 SendLayerPacket(x, y, map);
1125 // } 1158 }
1126 //} 1159 }
1127
1128 // Send LayerData in a spiral pattern. Fun!
1129 SendLayerTopRight(map, 0, 0, 15, 15);
1130 } 1160 }
1131 catch (Exception e) 1161 catch (Exception e)
1132 { 1162 {
@@ -1134,51 +1164,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1134 } 1164 }
1135 } 1165 }
1136 1166
1137 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1138 {
1139 // Row
1140 for (int i = x1; i <= x2; i++)
1141 SendLayerData(i, y1, map);
1142
1143 // Column
1144 for (int j = y1 + 1; j <= y2; j++)
1145 SendLayerData(x2, j, map);
1146
1147 if (x2 - x1 > 0)
1148 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1149 }
1150
1151 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1152 {
1153 // Row in reverse
1154 for (int i = x2; i >= x1; i--)
1155 SendLayerData(i, y2, map);
1156
1157 // Column in reverse
1158 for (int j = y2 - 1; j >= y1; j--)
1159 SendLayerData(x1, j, map);
1160
1161 if (x2 - x1 > 0)
1162 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1163 }
1164
1165 /// <summary> 1167 /// <summary>
1166 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1168 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1167 /// </summary> 1169 /// </summary>
1168 /// <param name="map">heightmap</param> 1170 /// <param name="map">heightmap</param>
1169 /// <param name="px">X coordinate for patches 0..12</param> 1171 /// <param name="px">X coordinate for patches 0..12</param>
1170 /// <param name="py">Y coordinate for patches 0..15</param> 1172 /// <param name="py">Y coordinate for patches 0..15</param>
1171 // private void SendLayerPacket(float[] map, int y, int x) 1173 private void SendLayerPacket(int x, int y, float[] map)
1172 // { 1174 {
1173 // int[] patches = new int[4]; 1175 int[] patches = new int[4];
1174 // patches[0] = x + 0 + y * 16; 1176 patches[0] = x + 0 + y * 16;
1175 // patches[1] = x + 1 + y * 16; 1177 patches[1] = x + 1 + y * 16;
1176 // patches[2] = x + 2 + y * 16; 1178 patches[2] = x + 2 + y * 16;
1177 // patches[3] = x + 3 + y * 16; 1179 patches[3] = x + 3 + y * 16;
1178 1180
1179 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1181 float[] heightmap = (map.Length == 65536) ?
1180 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1182 map :
1181 // } 1183 LLHeightFieldMoronize(map);
1184
1185 try
1186 {
1187 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1188 OutPacket(layerpack, ThrottleOutPacketType.Land);
1189 }
1190 catch
1191 {
1192 for (int px = x ; px < x + 4 ; px++)
1193 SendLayerData(px, y, map);
1194 }
1195 }
1182 1196
1183 /// <summary> 1197 /// <summary>
1184 /// Sends a specified patch to a client 1198 /// Sends a specified patch to a client
@@ -1198,7 +1212,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1198 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1212 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1199 layerpack.Header.Reliable = true; 1213 layerpack.Header.Reliable = true;
1200 1214
1201 OutPacket(layerpack, ThrottleOutPacketType.Land); 1215 OutPacket(layerpack, ThrottleOutPacketType.Task);
1202 } 1216 }
1203 catch (Exception e) 1217 catch (Exception e)
1204 { 1218 {
@@ -1561,7 +1575,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1561 1575
1562 public void SendKillObject(ulong regionHandle, List<uint> localIDs) 1576 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1563 { 1577 {
1564// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1578// foreach (uint id in localIDs)
1579// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
1565 1580
1566 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1581 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1567 // TODO: don't create new blocks if recycling an old packet 1582 // TODO: don't create new blocks if recycling an old packet
@@ -1583,17 +1598,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1583 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race 1598 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race
1584 // condition where a kill can be processed before an out-of-date update for the same object. 1599 // condition where a kill can be processed before an out-of-date update for the same object.
1585 // ProcessEntityUpdates() also takes the m_killRecord lock. 1600 // ProcessEntityUpdates() also takes the m_killRecord lock.
1586 lock (m_killRecord) 1601// lock (m_killRecord)
1587 { 1602// {
1588 foreach (uint localID in localIDs) 1603// foreach (uint localID in localIDs)
1589 m_killRecord.Add(localID); 1604// m_killRecord.Add(localID);
1590 1605
1591 // The throttle queue used here must match that being used for updates. Otherwise, there is a 1606 // The throttle queue used here must match that being used for updates. Otherwise, there is a
1592 // chance that a kill packet put on a separate queue will be sent to the client before an existing 1607 // chance that a kill packet put on a separate queue will be sent to the client before an existing
1593 // update packet on another queue. Receiving updates after kills results in unowned and undeletable 1608 // update packet on another queue. Receiving updates after kills results in unowned and undeletable
1594 // scene objects in a viewer until that viewer is relogged in. 1609 // scene objects in a viewer until that viewer is relogged in.
1595 OutPacket(kill, ThrottleOutPacketType.Task); 1610 OutPacket(kill, ThrottleOutPacketType.Task);
1596 } 1611// }
1597 } 1612 }
1598 } 1613 }
1599 1614
@@ -2132,16 +2147,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2132 replytask.InventoryData.TaskID = taskID; 2147 replytask.InventoryData.TaskID = taskID;
2133 replytask.InventoryData.Serial = serial; 2148 replytask.InventoryData.Serial = serial;
2134 replytask.InventoryData.Filename = fileName; 2149 replytask.InventoryData.Filename = fileName;
2135 OutPacket(replytask, ThrottleOutPacketType.Asset); 2150 OutPacket(replytask, ThrottleOutPacketType.Task);
2136 } 2151 }
2137 2152
2138 public void SendXferPacket(ulong xferID, uint packet, byte[] data) 2153 public void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory)
2139 { 2154 {
2155 ThrottleOutPacketType type = ThrottleOutPacketType.Asset;
2156 if (isTaskInventory)
2157 type = ThrottleOutPacketType.Task;
2158
2140 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket); 2159 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket);
2141 sendXfer.XferID.ID = xferID; 2160 sendXfer.XferID.ID = xferID;
2142 sendXfer.XferID.Packet = packet; 2161 sendXfer.XferID.Packet = packet;
2143 sendXfer.DataPacket.Data = data; 2162 sendXfer.DataPacket.Data = data;
2144 OutPacket(sendXfer, ThrottleOutPacketType.Asset); 2163 OutPacket(sendXfer, type);
2145 } 2164 }
2146 2165
2147 public void SendAbortXferPacket(ulong xferID) 2166 public void SendAbortXferPacket(ulong xferID)
@@ -2323,6 +2342,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2323 OutPacket(sound, ThrottleOutPacketType.Task); 2342 OutPacket(sound, ThrottleOutPacketType.Task);
2324 } 2343 }
2325 2344
2345 public void SendTransferAbort(TransferRequestPacket transferRequest)
2346 {
2347 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2348 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2349 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2350 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2351 OutPacket(abort, ThrottleOutPacketType.Task);
2352 }
2353
2326 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2354 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2327 { 2355 {
2328 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2356 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -2615,6 +2643,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2615 } 2643 }
2616 } 2644 }
2617 2645
2646 public void SendPartPhysicsProprieties(ISceneEntity entity)
2647 {
2648 SceneObjectPart part = (SceneObjectPart)entity;
2649 if (part != null && AgentId != UUID.Zero)
2650 {
2651 try
2652 {
2653 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
2654 if (eq != null)
2655 {
2656 uint localid = part.LocalId;
2657 byte physshapetype = part.PhysicsShapeType;
2658 float density = part.Density;
2659 float friction = part.Friction;
2660 float bounce = part.Bounciness;
2661 float gravmod = part.GravityModifier;
2662
2663 eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId);
2664 }
2665 }
2666 catch (Exception ex)
2667 {
2668 m_log.Error("Unable to send part Physics Proprieties - exception: " + ex.ToString());
2669 }
2670 part.UpdatePhysRequired = false;
2671 }
2672 }
2673
2674
2618 2675
2619 public void SendGroupNameReply(UUID groupLLUID, string GroupName) 2676 public void SendGroupNameReply(UUID groupLLUID, string GroupName)
2620 { 2677 {
@@ -2712,7 +2769,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2712 else 2769 else
2713 { 2770 {
2714 int processedLength = 0; 2771 int processedLength = 0;
2715 int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; 2772// int maxChunkSize = Settings.MAX_PACKET_SIZE - 100;
2773
2774 int maxChunkSize = (int) MaxTransferBytesPerPacket;
2716 int packetNumber = 0; 2775 int packetNumber = 0;
2717 2776
2718 while (processedLength < req.AssetInf.Data.Length) 2777 while (processedLength < req.AssetInf.Data.Length)
@@ -2783,7 +2842,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2783 reply.Data.ParcelID = parcelID; 2842 reply.Data.ParcelID = parcelID;
2784 reply.Data.OwnerID = land.OwnerID; 2843 reply.Data.OwnerID = land.OwnerID;
2785 reply.Data.Name = Utils.StringToBytes(land.Name); 2844 reply.Data.Name = Utils.StringToBytes(land.Name);
2786 reply.Data.Desc = Utils.StringToBytes(land.Description); 2845 if (land != null && land.Description != null && land.Description != String.Empty)
2846 reply.Data.Desc = Utils.StringToBytes(land.Description.Substring(0, land.Description.Length > 254 ? 254: land.Description.Length));
2847 else
2848 reply.Data.Desc = new Byte[0];
2787 reply.Data.ActualArea = land.Area; 2849 reply.Data.ActualArea = land.Area;
2788 reply.Data.BillableArea = land.Area; // TODO: what is this? 2850 reply.Data.BillableArea = land.Area; // TODO: what is this?
2789 2851
@@ -3518,7 +3580,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3518 3580
3519 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); 3581 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance);
3520 // TODO: don't create new blocks if recycling an old packet 3582 // TODO: don't create new blocks if recycling an old packet
3521 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; 3583 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[visualParams.Length];
3522 avp.ObjectData.TextureEntry = textureEntry; 3584 avp.ObjectData.TextureEntry = textureEntry;
3523 3585
3524 AvatarAppearancePacket.VisualParamBlock avblock = null; 3586 AvatarAppearancePacket.VisualParamBlock avblock = null;
@@ -3648,7 +3710,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3648 /// </summary> 3710 /// </summary>
3649 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3711 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3650 { 3712 {
3651 //double priority = m_prioritizer.GetUpdatePriority(this, entity); 3713 if (entity is SceneObjectPart)
3714 {
3715 SceneObjectPart e = (SceneObjectPart)entity;
3716 SceneObjectGroup g = e.ParentGroup;
3717 if (g.RootPart.Shape.State > 30) // HUD
3718 if (g.OwnerID != AgentId)
3719 return; // Don't send updates for other people's HUDs
3720 }
3721
3652 uint priority = m_prioritizer.GetUpdatePriority(this, entity); 3722 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3653 3723
3654 lock (m_entityUpdates.SyncRoot) 3724 lock (m_entityUpdates.SyncRoot)
@@ -3715,27 +3785,74 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3715 3785
3716 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3786 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3717 // condition where a kill can be processed before an out-of-date update for the same object. 3787 // condition where a kill can be processed before an out-of-date update for the same object.
3718 lock (m_killRecord) 3788 float avgTimeDilation = 1.0f;
3789 IEntityUpdate iupdate;
3790 Int32 timeinqueue; // this is just debugging code & can be dropped later
3791
3792 while (updatesThisCall < maxUpdates)
3719 { 3793 {
3720 float avgTimeDilation = 1.0f; 3794 lock (m_entityUpdates.SyncRoot)
3721 IEntityUpdate iupdate; 3795 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3722 Int32 timeinqueue; // this is just debugging code & can be dropped later 3796 break;
3723 3797
3724 while (updatesThisCall < maxUpdates) 3798 EntityUpdate update = (EntityUpdate)iupdate;
3799
3800 avgTimeDilation += update.TimeDilation;
3801 avgTimeDilation *= 0.5f;
3802
3803 if (update.Entity is SceneObjectPart)
3725 { 3804 {
3726 lock (m_entityUpdates.SyncRoot) 3805 SceneObjectPart part = (SceneObjectPart)update.Entity;
3727 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3728 break;
3729 3806
3730 EntityUpdate update = (EntityUpdate)iupdate; 3807 if (part.ParentGroup.IsDeleted)
3731 3808 continue;
3732 avgTimeDilation += update.TimeDilation;
3733 avgTimeDilation *= 0.5f;
3734 3809
3735 if (update.Entity is SceneObjectPart) 3810 if (part.ParentGroup.IsAttachment)
3811 { // Someone else's HUD, why are we getting these?
3812 if (part.ParentGroup.OwnerID != AgentId &&
3813 part.ParentGroup.RootPart.Shape.State > 30)
3814 continue;
3815 ScenePresence sp;
3816 // Owner is not in the sim, don't update it to
3817 // anyone
3818 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3819 continue;
3820
3821 List<SceneObjectGroup> atts = sp.GetAttachments();
3822 bool found = false;
3823 foreach (SceneObjectGroup att in atts)
3824 {
3825 if (att == part.ParentGroup)
3826 {
3827 found = true;
3828 break;
3829 }
3830 }
3831
3832 // It's an attachment of a valid avatar, but
3833 // doesn't seem to be attached, skip
3834 if (!found)
3835 continue;
3836
3837 // On vehicle crossing, the attachments are received
3838 // while the avatar is still a child. Don't send
3839 // updates here because the LocalId has not yet
3840 // been updated and the viewer will derender the
3841 // attachments until the avatar becomes root.
3842 if (sp.IsChildAgent)
3843 continue;
3844
3845 // If the object is an attachment we don't want it to be in the kill
3846 // record. Else attaching from inworld and subsequently dropping
3847 // it will no longer work.
3848// lock (m_killRecord)
3849// {
3850// m_killRecord.Remove(part.LocalId);
3851// m_killRecord.Remove(part.ParentGroup.RootPart.LocalId);
3852// }
3853 }
3854 else
3736 { 3855 {
3737 SceneObjectPart part = (SceneObjectPart)update.Entity;
3738
3739 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client 3856 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3740 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good 3857 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3741 // safety measure. 3858 // safety measure.
@@ -3746,236 +3863,174 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3746 // 3863 //
3747 // This doesn't appear to apply to child prims - a client will happily ignore these updates 3864 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3748 // after the root prim has been deleted. 3865 // after the root prim has been deleted.
3749 if (m_killRecord.Contains(part.LocalId)) 3866 //
3750 { 3867 // We ignore this for attachments because attaching something from inworld breaks unless we do.
3751 // m_log.WarnFormat( 3868// lock (m_killRecord)
3752 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted", 3869// {
3753 // part.LocalId, Name); 3870// if (m_killRecord.Contains(part.LocalId))
3754 continue; 3871// continue;
3755 } 3872// if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3756 3873// continue;
3757 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3874// }
3875 }
3876
3877 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3878 {
3879 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3880 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3758 { 3881 {
3759 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3882 part.Shape.LightEntry = false;
3760 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3761 {
3762 part.Shape.LightEntry = false;
3763 }
3764 } 3883 }
3765 } 3884 }
3766 3885 }
3767 #region UpdateFlags to packet type conversion 3886
3768 3887 ++updatesThisCall;
3769 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; 3888
3770 3889 #region UpdateFlags to packet type conversion
3771 bool canUseCompressed = true; 3890
3772 bool canUseImproved = true; 3891 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3773 3892
3774 // Compressed object updates only make sense for LL primitives 3893 bool canUseCompressed = true;
3775 if (!(update.Entity is SceneObjectPart)) 3894 bool canUseImproved = true;
3895
3896 // Compressed object updates only make sense for LL primitives
3897 if (!(update.Entity is SceneObjectPart))
3898 {
3899 canUseCompressed = false;
3900 }
3901
3902 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3903 {
3904 canUseCompressed = false;
3905 canUseImproved = false;
3906 }
3907 else
3908 {
3909 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3910 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3911 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3912 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3776 { 3913 {
3777 canUseCompressed = false; 3914 canUseCompressed = false;
3778 } 3915 }
3779 3916
3780 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 3917 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3918 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3919 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3920 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3921 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3922 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3923 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3924 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3925 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3926 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3927 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3928 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3929 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3930 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3781 { 3931 {
3782 canUseCompressed = false;
3783 canUseImproved = false; 3932 canUseImproved = false;
3784 } 3933 }
3785 else 3934 }
3786 {
3787 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3788 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3789 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3790 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3791 {
3792 canUseCompressed = false;
3793 }
3794
3795 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3796 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3797 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3798 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3799 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3800 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3801 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3802 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3803 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3804 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3805 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3806 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3807 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3808 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3809 {
3810 canUseImproved = false;
3811 }
3812 }
3813
3814 #endregion UpdateFlags to packet type conversion
3815
3816 #region Block Construction
3817
3818 // TODO: Remove this once we can build compressed updates
3819 canUseCompressed = false;
3820 3935
3821 if (!canUseImproved && !canUseCompressed) 3936 #endregion UpdateFlags to packet type conversion
3822 {
3823 ObjectUpdatePacket.ObjectDataBlock updateBlock;
3824 3937
3825 if (update.Entity is ScenePresence) 3938 #region Block Construction
3826 {
3827 updateBlock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
3828 }
3829 else
3830 {
3831 SceneObjectPart part = (SceneObjectPart)update.Entity;
3832 updateBlock = CreatePrimUpdateBlock(part, AgentId);
3833
3834 // If the part has become a private hud since the update was scheduled then we do not
3835 // want to send it to other avatars.
3836 if (part.ParentGroup.IsAttachment
3837 && part.ParentGroup.HasPrivateAttachmentPoint
3838 && part.ParentGroup.AttachedAvatar != AgentId)
3839 continue;
3840
3841 // If the part has since been deleted, then drop the update. In the case of attachments,
3842 // this is to avoid spurious updates to other viewers since post-processing of attachments
3843 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3844 // of the test above).
3845 //
3846 // Actual deletions (kills) happen in another method.
3847 if (part.ParentGroup.IsDeleted)
3848 continue;
3849 }
3850 3939
3851 objectUpdateBlocks.Value.Add(updateBlock); 3940 // TODO: Remove this once we can build compressed updates
3852 objectUpdates.Value.Add(update); 3941 canUseCompressed = false;
3853 }
3854 else if (!canUseImproved)
3855 {
3856 SceneObjectPart part = (SceneObjectPart)update.Entity;
3857 ObjectUpdateCompressedPacket.ObjectDataBlock compressedBlock
3858 = CreateCompressedUpdateBlock(part, updateFlags);
3859
3860 // If the part has since been deleted, then drop the update. In the case of attachments,
3861 // this is to avoid spurious updates to other viewers since post-processing of attachments
3862 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3863 // of the test above).
3864 //
3865 // Actual deletions (kills) happen in another method.
3866 if (part.ParentGroup.IsDeleted)
3867 continue;
3868 3942
3869 compressedUpdateBlocks.Value.Add(compressedBlock); 3943 if (!canUseImproved && !canUseCompressed)
3870 compressedUpdates.Value.Add(update); 3944 {
3945 if (update.Entity is ScenePresence)
3946 {
3947 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3871 } 3948 }
3872 else 3949 else
3873 { 3950 {
3874 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 3951 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3875 {
3876 // Self updates go into a special list
3877 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3878 terseAgentUpdates.Value.Add(update);
3879 }
3880 else
3881 {
3882 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseUpdateBlock
3883 = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures));
3884
3885 // Everything else goes here
3886 if (update.Entity is SceneObjectPart)
3887 {
3888 SceneObjectPart part = (SceneObjectPart)update.Entity;
3889
3890 // If the part has become a private hud since the update was scheduled then we do not
3891 // want to send it to other avatars.
3892 if (part.ParentGroup.IsAttachment
3893 && part.ParentGroup.HasPrivateAttachmentPoint
3894 && part.ParentGroup.AttachedAvatar != AgentId)
3895 continue;
3896
3897 // If the part has since been deleted, then drop the update. In the case of attachments,
3898 // this is to avoid spurious updates to other viewers since post-processing of attachments
3899 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3900 // of the test above).
3901 //
3902 // Actual deletions (kills) happen in another method.
3903 if (part.ParentGroup.IsDeleted)
3904 continue;
3905 }
3906
3907 terseUpdateBlocks.Value.Add(terseUpdateBlock);
3908 terseUpdates.Value.Add(update);
3909 }
3910 } 3952 }
3953 }
3954 else if (!canUseImproved)
3955 {
3956 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3957 }
3958 else
3959 {
3960 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3961 // Self updates go into a special list
3962 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3963 else
3964 // Everything else goes here
3965 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3966 }
3967
3968 #endregion Block Construction
3969 }
3911 3970
3912 ++updatesThisCall; 3971 #region Packet Sending
3913 3972
3914 #endregion Block Construction 3973 const float TIME_DILATION = 1.0f;
3915 } 3974 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3916 3975
3917 #region Packet Sending 3976 if (terseAgentUpdateBlocks.IsValueCreated)
3918 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 3977 {
3978 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3919 3979
3920 if (terseAgentUpdateBlocks.IsValueCreated) 3980 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3921 { 3981 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3922 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3982 packet.RegionData.TimeDilation = timeDilation;
3983 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3923 3984
3924 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3985 for (int i = 0; i < blocks.Count; i++)
3925 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3986 packet.ObjectData[i] = blocks[i];
3926 packet.RegionData.TimeDilation = timeDilation;
3927 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3928 3987
3929 for (int i = 0; i < blocks.Count; i++) 3988 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3930 packet.ObjectData[i] = blocks[i]; 3989 }
3931 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3932 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); });
3933 }
3934 3990
3935 if (objectUpdateBlocks.IsValueCreated) 3991 if (objectUpdateBlocks.IsValueCreated)
3936 { 3992 {
3937 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; 3993 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3938 3994
3939 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3995 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3940 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3996 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3941 packet.RegionData.TimeDilation = timeDilation; 3997 packet.RegionData.TimeDilation = timeDilation;
3942 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3998 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3943 3999
3944 for (int i = 0; i < blocks.Count; i++) 4000 for (int i = 0; i < blocks.Count; i++)
3945 packet.ObjectData[i] = blocks[i]; 4001 packet.ObjectData[i] = blocks[i];
3946 // If any of the packets created from this call go unacknowledged, all of the updates will be resent 4002
3947 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); }); 4003 OutPacket(packet, ThrottleOutPacketType.Task, true);
3948 } 4004 }
3949 4005
3950 if (compressedUpdateBlocks.IsValueCreated) 4006 if (compressedUpdateBlocks.IsValueCreated)
3951 { 4007 {
3952 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value; 4008 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3953 4009
3954 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed); 4010 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3955 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4011 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3956 packet.RegionData.TimeDilation = timeDilation; 4012 packet.RegionData.TimeDilation = timeDilation;
3957 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count]; 4013 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3958
3959 for (int i = 0; i < blocks.Count; i++)
3960 packet.ObjectData[i] = blocks[i];
3961 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3962 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
3963 }
3964 4014
3965 if (terseUpdateBlocks.IsValueCreated) 4015 for (int i = 0; i < blocks.Count; i++)
3966 { 4016 packet.ObjectData[i] = blocks[i];
3967 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; 4017
3968 4018 OutPacket(packet, ThrottleOutPacketType.Task, true);
3969 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 4019 }
3970 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4020
3971 packet.RegionData.TimeDilation = timeDilation; 4021 if (terseUpdateBlocks.IsValueCreated)
3972 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4022 {
3973 4023 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3974 for (int i = 0; i < blocks.Count; i++) 4024
3975 packet.ObjectData[i] = blocks[i]; 4025 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3976 // If any of the packets created from this call go unacknowledged, all of the updates will be resent 4026 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3977 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); 4027 packet.RegionData.TimeDilation = timeDilation;
3978 } 4028 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4029
4030 for (int i = 0; i < blocks.Count; i++)
4031 packet.ObjectData[i] = blocks[i];
4032
4033 OutPacket(packet, ThrottleOutPacketType.Task, true);
3979 } 4034 }
3980 4035
3981 #endregion Packet Sending 4036 #endregion Packet Sending
@@ -4268,11 +4323,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4268 4323
4269 // Pass in the delegate so that if this packet needs to be resent, we send the current properties 4324 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4270 // of the object rather than the properties when the packet was created 4325 // of the object rather than the properties when the packet was created
4271 OutPacket(packet, ThrottleOutPacketType.Task, true, 4326 // HACK : Remove intelligent resending until it's fixed in core
4272 delegate(OutgoingPacket oPacket) 4327 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4273 { 4328 // delegate(OutgoingPacket oPacket)
4274 ResendPropertyUpdates(updates, oPacket); 4329 // {
4275 }); 4330 // ResendPropertyUpdates(updates, oPacket);
4331 // });
4332 OutPacket(packet, ThrottleOutPacketType.Task, true);
4276 4333
4277 // pbcnt += blocks.Count; 4334 // pbcnt += blocks.Count;
4278 // ppcnt++; 4335 // ppcnt++;
@@ -4298,11 +4355,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4298 // of the object rather than the properties when the packet was created 4355 // of the object rather than the properties when the packet was created
4299 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); 4356 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
4300 updates.Add(familyUpdates.Value[i]); 4357 updates.Add(familyUpdates.Value[i]);
4301 OutPacket(packet, ThrottleOutPacketType.Task, true, 4358 // HACK : Remove intelligent resending until it's fixed in core
4302 delegate(OutgoingPacket oPacket) 4359 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4303 { 4360 // delegate(OutgoingPacket oPacket)
4304 ResendPropertyUpdates(updates, oPacket); 4361 // {
4305 }); 4362 // ResendPropertyUpdates(updates, oPacket);
4363 // });
4364 OutPacket(packet, ThrottleOutPacketType.Task, true);
4306 4365
4307 // fpcnt++; 4366 // fpcnt++;
4308 // fbcnt++; 4367 // fbcnt++;
@@ -4674,7 +4733,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4674 4733
4675 if (landData.SimwideArea > 0) 4734 if (landData.SimwideArea > 0)
4676 { 4735 {
4677 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 4736 int simulatorCapacity = (int)((long)landData.SimwideArea * (long)m_scene.RegionInfo.ObjectCapacity * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus / 65536L);
4737 // Never report more than sim total capacity
4738 if (simulatorCapacity > m_scene.RegionInfo.ObjectCapacity)
4739 simulatorCapacity = m_scene.RegionInfo.ObjectCapacity;
4678 updateMessage.SimWideMaxPrims = simulatorCapacity; 4740 updateMessage.SimWideMaxPrims = simulatorCapacity;
4679 } 4741 }
4680 else 4742 else
@@ -4803,14 +4865,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4803 4865
4804 if (notifyCount > 0) 4866 if (notifyCount > 0)
4805 { 4867 {
4806 if (notifyCount > 32) 4868// if (notifyCount > 32)
4807 { 4869// {
4808 m_log.InfoFormat( 4870// m_log.InfoFormat(
4809 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4871// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4810 + " - a developer might want to investigate whether this is a hard limit", 32); 4872// + " - a developer might want to investigate whether this is a hard limit", 32);
4811 4873//
4812 notifyCount = 32; 4874// notifyCount = 32;
4813 } 4875// }
4814 4876
4815 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4877 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4816 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4878 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -4865,9 +4927,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4865 { 4927 {
4866 ScenePresence presence = (ScenePresence)entity; 4928 ScenePresence presence = (ScenePresence)entity;
4867 4929
4930 position = presence.OffsetPosition;
4931 rotation = presence.Rotation;
4932
4933 if (presence.ParentID != 0)
4934 {
4935 SceneObjectPart part = m_scene.GetSceneObjectPart(presence.ParentID);
4936 if (part != null && part != part.ParentGroup.RootPart)
4937 {
4938 position = part.OffsetPosition + presence.OffsetPosition * part.RotationOffset;
4939 rotation = part.RotationOffset * presence.Rotation;
4940 }
4941 }
4942
4868 attachPoint = 0; 4943 attachPoint = 0;
4869 collisionPlane = presence.CollisionPlane; 4944 collisionPlane = presence.CollisionPlane;
4870 position = presence.OffsetPosition;
4871 velocity = presence.Velocity; 4945 velocity = presence.Velocity;
4872 acceleration = Vector3.Zero; 4946 acceleration = Vector3.Zero;
4873 4947
@@ -4877,7 +4951,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4877// acceleration = new Vector3(1, 0, 0); 4951// acceleration = new Vector3(1, 0, 0);
4878 4952
4879 angularVelocity = Vector3.Zero; 4953 angularVelocity = Vector3.Zero;
4880 rotation = presence.Rotation;
4881 4954
4882 if (sendTexture) 4955 if (sendTexture)
4883 textureEntry = presence.Appearance.Texture.GetBytes(); 4956 textureEntry = presence.Appearance.Texture.GetBytes();
@@ -4982,13 +5055,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4982 5055
4983 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) 5056 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
4984 { 5057 {
5058 Vector3 offsetPosition = data.OffsetPosition;
5059 Quaternion rotation = data.Rotation;
5060 uint parentID = data.ParentID;
5061
5062 if (parentID != 0)
5063 {
5064 SceneObjectPart part = m_scene.GetSceneObjectPart(parentID);
5065 if (part != null && part != part.ParentGroup.RootPart)
5066 {
5067 offsetPosition = part.OffsetPosition + data.OffsetPosition * part.RotationOffset;
5068 rotation = part.RotationOffset * data.Rotation;
5069 parentID = part.ParentGroup.RootPart.LocalId;
5070 }
5071 }
5072
4985 byte[] objectData = new byte[76]; 5073 byte[] objectData = new byte[76];
4986 5074
4987 data.CollisionPlane.ToBytes(objectData, 0); 5075 data.CollisionPlane.ToBytes(objectData, 0);
4988 data.OffsetPosition.ToBytes(objectData, 16); 5076 offsetPosition.ToBytes(objectData, 16);
4989// data.Velocity.ToBytes(objectData, 28); 5077// data.Velocity.ToBytes(objectData, 28);
4990// data.Acceleration.ToBytes(objectData, 40); 5078// data.Acceleration.ToBytes(objectData, 40);
4991 data.Rotation.ToBytes(objectData, 52); 5079 rotation.ToBytes(objectData, 52);
4992 //data.AngularVelocity.ToBytes(objectData, 64); 5080 //data.AngularVelocity.ToBytes(objectData, 64);
4993 5081
4994 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5082 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
@@ -5002,7 +5090,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5002 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + 5090 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
5003 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); 5091 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
5004 update.ObjectData = objectData; 5092 update.ObjectData = objectData;
5005 update.ParentID = data.ParentID; 5093 update.ParentID = parentID;
5006 update.PathCurve = 16; 5094 update.PathCurve = 16;
5007 update.PathScaleX = 100; 5095 update.PathScaleX = 100;
5008 update.PathScaleY = 100; 5096 update.PathScaleY = 100;
@@ -5020,10 +5108,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5020 update.TextureEntry = Utils.EmptyBytes; 5108 update.TextureEntry = Utils.EmptyBytes;
5021// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes; 5109// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
5022 5110
5111/* 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)
5023 update.UpdateFlags = (uint)( 5112 update.UpdateFlags = (uint)(
5024 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | 5113 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
5025 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | 5114 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
5026 PrimFlags.ObjectOwnerModify); 5115 PrimFlags.ObjectOwnerModify);
5116*/
5117 update.UpdateFlags = 0;
5027 5118
5028 return update; 5119 return update;
5029 } 5120 }
@@ -5343,6 +5434,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5343 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5434 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5344 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5435 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5345 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5436 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5437 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5346 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5438 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5347 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5439 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5348 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5440 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5409,6 +5501,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5409 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest); 5501 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest);
5410 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes); 5502 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes);
5411 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard); 5503 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard);
5504 AddLocalPacketHandler(PacketType.ChangeInventoryItemFlags, HandleChangeInventoryItemFlags);
5412 5505
5413 AddGenericPacketHandler("autopilot", HandleAutopilot); 5506 AddGenericPacketHandler("autopilot", HandleAutopilot);
5414 } 5507 }
@@ -5444,6 +5537,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5444 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5537 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5445 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5538 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5446 (x.ControlFlags != lastarg.ControlFlags) || 5539 (x.ControlFlags != lastarg.ControlFlags) ||
5540 (x.ControlFlags != 0) ||
5447 (x.Far != lastarg.Far) || 5541 (x.Far != lastarg.Far) ||
5448 (x.Flags != lastarg.Flags) || 5542 (x.Flags != lastarg.Flags) ||
5449 (x.State != lastarg.State) || 5543 (x.State != lastarg.State) ||
@@ -6341,6 +6435,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6341 { 6435 {
6342 handlerCompleteMovementToRegion(sender, true); 6436 handlerCompleteMovementToRegion(sender, true);
6343 } 6437 }
6438 else
6439 m_log.Debug("HandleCompleteAgentMovement NULL handler");
6440
6344 handlerCompleteMovementToRegion = null; 6441 handlerCompleteMovementToRegion = null;
6345 6442
6346 return true; 6443 return true;
@@ -6358,7 +6455,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6358 return true; 6455 return true;
6359 } 6456 }
6360 #endregion 6457 #endregion
6361 6458/*
6362 StartAnim handlerStartAnim = null; 6459 StartAnim handlerStartAnim = null;
6363 StopAnim handlerStopAnim = null; 6460 StopAnim handlerStopAnim = null;
6364 6461
@@ -6382,6 +6479,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6382 } 6479 }
6383 } 6480 }
6384 return true; 6481 return true;
6482*/
6483 ChangeAnim handlerChangeAnim = null;
6484
6485 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
6486 {
6487 handlerChangeAnim = OnChangeAnim;
6488 if (handlerChangeAnim != null)
6489 {
6490 handlerChangeAnim(AgentAni.AnimationList[i].AnimID, AgentAni.AnimationList[i].StartAnim, false);
6491 }
6492 }
6493
6494 handlerChangeAnim = OnChangeAnim;
6495 if (handlerChangeAnim != null)
6496 {
6497 handlerChangeAnim(UUID.Zero, false, true);
6498 }
6499
6500 return true;
6385 } 6501 }
6386 6502
6387 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack) 6503 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack)
@@ -7007,10 +7123,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7007 // 46,47,48 are special positions within the packet 7123 // 46,47,48 are special positions within the packet
7008 // This may change so perhaps we need a better way 7124 // This may change so perhaps we need a better way
7009 // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?) 7125 // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?)
7010 bool UsePhysics = (data[46] != 0) ? true : false; 7126 /*
7011 bool IsTemporary = (data[47] != 0) ? true : false; 7127 bool UsePhysics = (data[46] != 0) ? true : false;
7012 bool IsPhantom = (data[48] != 0) ? true : false; 7128 bool IsTemporary = (data[47] != 0) ? true : false;
7013 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this); 7129 bool IsPhantom = (data[48] != 0) ? true : false;
7130 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this);
7131 */
7132 bool UsePhysics = flags.AgentData.UsePhysics;
7133 bool IsPhantom = flags.AgentData.IsPhantom;
7134 bool IsTemporary = flags.AgentData.IsTemporary;
7135 ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks = flags.ExtraPhysics;
7136 ExtraPhysicsData physdata = new ExtraPhysicsData();
7137
7138 if (blocks == null || blocks.Length == 0)
7139 {
7140 physdata.PhysShapeType = PhysShapeType.invalid;
7141 }
7142 else
7143 {
7144 ObjectFlagUpdatePacket.ExtraPhysicsBlock phsblock = blocks[0];
7145 physdata.PhysShapeType = (PhysShapeType)phsblock.PhysicsShapeType;
7146 physdata.Bounce = phsblock.Restitution;
7147 physdata.Density = phsblock.Density;
7148 physdata.Friction = phsblock.Friction;
7149 physdata.GravitationModifier = phsblock.GravityMultiplier;
7150 }
7151
7152 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, this);
7014 } 7153 }
7015 return true; 7154 return true;
7016 } 7155 }
@@ -8611,16 +8750,61 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8611 8750
8612 #region Parcel related packets 8751 #region Parcel related packets
8613 8752
8753 // acumulate several HandleRegionHandleRequest consecutive overlaping requests
8754 // to be done with minimal resources as possible
8755 // variables temporary here while in test
8756
8757 Queue<UUID> RegionHandleRequests = new Queue<UUID>();
8758 bool RegionHandleRequestsInService = false;
8759
8614 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack) 8760 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack)
8615 { 8761 {
8616 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; 8762 UUID currentUUID;
8617 8763
8618 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest; 8764 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest;
8619 if (handlerRegionHandleRequest != null) 8765
8766 if (handlerRegionHandleRequest == null)
8767 return true;
8768
8769 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack;
8770
8771 lock (RegionHandleRequests)
8620 { 8772 {
8621 handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); 8773 if (RegionHandleRequestsInService)
8774 {
8775 // we are already busy doing a previus request
8776 // so enqueue it
8777 RegionHandleRequests.Enqueue(rhrPack.RequestBlock.RegionID);
8778 return true;
8779 }
8780
8781 // else do it
8782 currentUUID = rhrPack.RequestBlock.RegionID;
8783 RegionHandleRequestsInService = true;
8622 } 8784 }
8623 return true; 8785
8786 while (true)
8787 {
8788 handlerRegionHandleRequest(this, currentUUID);
8789
8790 lock (RegionHandleRequests)
8791 {
8792 // exit condition, nothing to do or closed
8793 // current code seems to assume we may loose the handler at anytime,
8794 // so keep checking it
8795 handlerRegionHandleRequest = OnRegionHandleRequest;
8796
8797 if (RegionHandleRequests.Count == 0 || !IsActive || handlerRegionHandleRequest == null)
8798 {
8799 RegionHandleRequests.Clear();
8800 RegionHandleRequestsInService = false;
8801 return true;
8802 }
8803 currentUUID = RegionHandleRequests.Dequeue();
8804 }
8805 }
8806
8807 return true; // actually unreached
8624 } 8808 }
8625 8809
8626 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack) 8810 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack)
@@ -9864,7 +10048,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9864 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 10048 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9865 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 10049 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9866 UpdateMuteListEntry.MuteData.MuteType, 10050 UpdateMuteListEntry.MuteData.MuteType,
9867 UpdateMuteListEntry.AgentData.AgentID); 10051 UpdateMuteListEntry.MuteData.MuteFlags);
9868 return true; 10052 return true;
9869 } 10053 }
9870 return false; 10054 return false;
@@ -9879,8 +10063,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9879 { 10063 {
9880 handlerRemoveMuteListEntry(this, 10064 handlerRemoveMuteListEntry(this,
9881 RemoveMuteListEntry.MuteData.MuteID, 10065 RemoveMuteListEntry.MuteData.MuteID,
9882 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 10066 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9883 RemoveMuteListEntry.AgentData.AgentID);
9884 return true; 10067 return true;
9885 } 10068 }
9886 return false; 10069 return false;
@@ -9924,10 +10107,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9924 return false; 10107 return false;
9925 } 10108 }
9926 10109
10110 private bool HandleChangeInventoryItemFlags(IClientAPI client, Packet packet)
10111 {
10112 ChangeInventoryItemFlagsPacket ChangeInventoryItemFlags =
10113 (ChangeInventoryItemFlagsPacket)packet;
10114 ChangeInventoryItemFlags handlerChangeInventoryItemFlags = OnChangeInventoryItemFlags;
10115 if (handlerChangeInventoryItemFlags != null)
10116 {
10117 foreach(ChangeInventoryItemFlagsPacket.InventoryDataBlock b in ChangeInventoryItemFlags.InventoryData)
10118 handlerChangeInventoryItemFlags(this, b.ItemID, b.Flags);
10119 return true;
10120 }
10121 return false;
10122 }
10123
9927 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack) 10124 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack)
9928 { 10125 {
9929 return true; 10126 return true;
9930 } 10127 }
10128
10129 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
10130 {
10131 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
10132
10133 #region Packet Session and User Check
10134 if (m_checkPackets)
10135 {
10136 if (packet.AgentData.SessionID != SessionId ||
10137 packet.AgentData.AgentID != AgentId)
10138 return true;
10139 }
10140 #endregion
10141 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
10142 List<InventoryItemBase> items = new List<InventoryItemBase>();
10143 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
10144 {
10145 InventoryItemBase b = new InventoryItemBase();
10146 b.ID = n.OldItemID;
10147 b.Folder = n.OldFolderID;
10148 items.Add(b);
10149 }
10150
10151 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
10152 if (handlerMoveItemsAndLeaveCopy != null)
10153 {
10154 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
10155 }
10156
10157 return true;
10158 }
9931 10159
9932 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 10160 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9933 { 10161 {
@@ -10354,6 +10582,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10354 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 10582 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10355 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 10583 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10356 10584
10585 Scene scene = (Scene)m_scene;
10586 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
10587 {
10588 ScenePresence p;
10589 if (scene.TryGetScenePresence(sender.AgentId, out p))
10590 {
10591 if (p.GodLevel >= 200)
10592 {
10593 groupProfileReply.GroupData.OpenEnrollment = true;
10594 groupProfileReply.GroupData.MembershipFee = 0;
10595 }
10596 }
10597 }
10598
10357 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 10599 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10358 } 10600 }
10359 return true; 10601 return true;
@@ -10927,11 +11169,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10927 11169
10928 StartLure handlerStartLure = OnStartLure; 11170 StartLure handlerStartLure = OnStartLure;
10929 if (handlerStartLure != null) 11171 if (handlerStartLure != null)
10930 handlerStartLure(startLureRequest.Info.LureType, 11172 {
10931 Utils.BytesToString( 11173 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10932 startLureRequest.Info.Message), 11174 {
10933 startLureRequest.TargetData[0].TargetID, 11175 handlerStartLure(startLureRequest.Info.LureType,
10934 this); 11176 Utils.BytesToString(
11177 startLureRequest.Info.Message),
11178 startLureRequest.TargetData[i].TargetID,
11179 this);
11180 }
11181 }
10935 return true; 11182 return true;
10936 } 11183 }
10937 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 11184 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -11045,10 +11292,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11045 } 11292 }
11046 #endregion 11293 #endregion
11047 11294
11048 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; 11295 ClassifiedGodDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
11049 if (handlerClassifiedGodDelete != null) 11296 if (handlerClassifiedGodDelete != null)
11050 handlerClassifiedGodDelete( 11297 handlerClassifiedGodDelete(
11051 classifiedGodDelete.Data.ClassifiedID, 11298 classifiedGodDelete.Data.ClassifiedID,
11299 classifiedGodDelete.Data.QueryID,
11052 this); 11300 this);
11053 return true; 11301 return true;
11054 } 11302 }
@@ -11414,209 +11662,147 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11414 } 11662 }
11415 else 11663 else
11416 { 11664 {
11417// m_log.DebugFormat( 11665 ClientChangeObject updatehandler = onClientChangeObject;
11418// "[CLIENT]: Processing block {0} type {1} for {2} {3}",
11419// i, block.Type, part.Name, part.LocalId);
11420 11666
11421// // Do this once since fetch parts creates a new array. 11667 if (updatehandler != null)
11422// SceneObjectPart[] parts = part.ParentGroup.Parts; 11668 {
11423// for (int j = 0; j < parts.Length; j++) 11669 ObjectChangeData udata = new ObjectChangeData();
11424// {
11425// part.StoreUndoState();
11426// parts[j].IgnoreUndoUpdate = true;
11427// }
11428 11670
11429 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; 11671 /*ubit from ll JIRA:
11672 * 0x01 position
11673 * 0x02 rotation
11674 * 0x04 scale
11675
11676 * 0x08 LINK_SET
11677 * 0x10 UNIFORM for scale
11678 */
11430 11679
11431 switch (block.Type) 11680 // translate to internal changes
11432 { 11681 // not all cases .. just the ones older code did
11433 case 1:
11434 Vector3 pos1 = new Vector3(block.Data, 0);
11435 11682
11436 UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11683 switch (block.Type)
11437 if (handlerUpdatePrimSinglePosition != null) 11684 {
11438 { 11685 case 1: //change position sp
11439 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 11686 udata.position = new Vector3(block.Data, 0);
11440 handlerUpdatePrimSinglePosition(localId, pos1, this);
11441 }
11442 break;
11443 11687
11444 case 2: 11688 udata.change = ObjectChangeType.primP;
11445 Quaternion rot1 = new Quaternion(block.Data, 0, true); 11689 updatehandler(localId, udata, this);
11690 break;
11446 11691
11447 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; 11692 case 2: // rotation sp
11448 if (handlerUpdatePrimSingleRotation != null) 11693 udata.rotation = new Quaternion(block.Data, 0, true);
11449 {
11450 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W);
11451 handlerUpdatePrimSingleRotation(localId, rot1, this);
11452 }
11453 break;
11454 11694
11455 case 3: 11695 udata.change = ObjectChangeType.primR;
11456 Vector3 rotPos = new Vector3(block.Data, 0); 11696 updatehandler(localId, udata, this);
11457 Quaternion rot2 = new Quaternion(block.Data, 12, true); 11697 break;
11458 11698
11459 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; 11699 case 3: // position plus rotation
11460 if (handlerUpdatePrimSingleRotationPosition != null) 11700 udata.position = new Vector3(block.Data, 0);
11461 { 11701 udata.rotation = new Quaternion(block.Data, 12, true);
11462 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z);
11463 // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W);
11464 handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this);
11465 }
11466 break;
11467 11702
11468 case 4: 11703 udata.change = ObjectChangeType.primPR;
11469 case 20: 11704 updatehandler(localId, udata, this);
11470 Vector3 scale4 = new Vector3(block.Data, 0); 11705 break;
11471 11706
11472 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; 11707 case 4: // scale sp
11473 if (handlerUpdatePrimScale != null) 11708 udata.scale = new Vector3(block.Data, 0);
11474 { 11709 udata.change = ObjectChangeType.primS;
11475 // m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z);
11476 handlerUpdatePrimScale(localId, scale4, this);
11477 }
11478 break;
11479 11710
11480 case 5: 11711 updatehandler(localId, udata, this);
11481 Vector3 scale1 = new Vector3(block.Data, 12); 11712 break;
11482 Vector3 pos11 = new Vector3(block.Data, 0);
11483 11713
11484 handlerUpdatePrimScale = OnUpdatePrimScale; 11714 case 0x14: // uniform scale sp
11485 if (handlerUpdatePrimScale != null) 11715 udata.scale = new Vector3(block.Data, 0);
11486 {
11487 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11488 handlerUpdatePrimScale(localId, scale1, this);
11489 11716
11490 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11717 udata.change = ObjectChangeType.primUS;
11491 if (handlerUpdatePrimSinglePosition != null) 11718 updatehandler(localId, udata, this);
11492 { 11719 break;
11493 handlerUpdatePrimSinglePosition(localId, pos11, this);
11494 }
11495 }
11496 break;
11497 11720
11498 case 9: 11721 case 5: // scale and position sp
11499 Vector3 pos2 = new Vector3(block.Data, 0); 11722 udata.position = new Vector3(block.Data, 0);
11723 udata.scale = new Vector3(block.Data, 12);
11500 11724
11501 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; 11725 udata.change = ObjectChangeType.primPS;
11726 updatehandler(localId, udata, this);
11727 break;
11502 11728
11503 if (handlerUpdateVector != null) 11729 case 0x15: //uniform scale and position
11504 { 11730 udata.position = new Vector3(block.Data, 0);
11505 handlerUpdateVector(localId, pos2, this); 11731 udata.scale = new Vector3(block.Data, 12);
11506 }
11507 break;
11508 11732
11509 case 10: 11733 udata.change = ObjectChangeType.primPUS;
11510 Quaternion rot3 = new Quaternion(block.Data, 0, true); 11734 updatehandler(localId, udata, this);
11735 break;
11511 11736
11512 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; 11737 // now group related (bit 4)
11513 if (handlerUpdatePrimRotation != null) 11738 case 9: //( 8 + 1 )group position
11514 { 11739 udata.position = new Vector3(block.Data, 0);
11515 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W);
11516 handlerUpdatePrimRotation(localId, rot3, this);
11517 }
11518 break;
11519 11740
11520 case 11: 11741 udata.change = ObjectChangeType.groupP;
11521 Vector3 pos3 = new Vector3(block.Data, 0); 11742 updatehandler(localId, udata, this);
11522 Quaternion rot4 = new Quaternion(block.Data, 12, true); 11743 break;
11523 11744
11524 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; 11745 case 0x0A: // (8 + 2) group rotation
11525 if (handlerUpdatePrimGroupRotation != null) 11746 udata.rotation = new Quaternion(block.Data, 0, true);
11526 {
11527 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11528 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W);
11529 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this);
11530 }
11531 break;
11532 case 12:
11533 case 28:
11534 Vector3 scale7 = new Vector3(block.Data, 0);
11535 11747
11536 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 11748 udata.change = ObjectChangeType.groupR;
11537 if (handlerUpdatePrimGroupScale != null) 11749 updatehandler(localId, udata, this);
11538 { 11750 break;
11539 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
11540 handlerUpdatePrimGroupScale(localId, scale7, this);
11541 }
11542 break;
11543 11751
11544 case 13: 11752 case 0x0B: //( 8 + 2 + 1) group rotation and position
11545 Vector3 scale2 = new Vector3(block.Data, 12); 11753 udata.position = new Vector3(block.Data, 0);
11546 Vector3 pos4 = new Vector3(block.Data, 0); 11754 udata.rotation = new Quaternion(block.Data, 12, true);
11547 11755
11548 handlerUpdatePrimScale = OnUpdatePrimScale; 11756 udata.change = ObjectChangeType.groupPR;
11549 if (handlerUpdatePrimScale != null) 11757 updatehandler(localId, udata, this);
11550 { 11758 break;
11551 //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11552 handlerUpdatePrimScale(localId, scale2, this);
11553 11759
11554 // Change the position based on scale (for bug number 246) 11760 case 0x0C: // (8 + 4) group scale
11555 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11761 // only afects root prim and only sent by viewer editor object tab scaling
11556 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 11762 // mouse edition only allows uniform scaling
11557 if (handlerUpdatePrimSinglePosition != null) 11763 // SL MAY CHANGE THIS in viewers
11558 {
11559 handlerUpdatePrimSinglePosition(localId, pos4, this);
11560 }
11561 }
11562 break;
11563 11764
11564 case 29: 11765 udata.scale = new Vector3(block.Data, 0);
11565 Vector3 scale5 = new Vector3(block.Data, 12);
11566 Vector3 pos5 = new Vector3(block.Data, 0);
11567 11766
11568 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 11767 udata.change = ObjectChangeType.groupS;
11569 if (handlerUpdatePrimGroupScale != null) 11768 updatehandler(localId, udata, this);
11570 {
11571 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11572 part.StoreUndoState(true);
11573 part.IgnoreUndoUpdate = true;
11574 handlerUpdatePrimGroupScale(localId, scale5, this);
11575 handlerUpdateVector = OnUpdatePrimGroupPosition;
11576 11769
11577 if (handlerUpdateVector != null) 11770 break;
11578 {
11579 handlerUpdateVector(localId, pos5, this);
11580 }
11581 11771
11582 part.IgnoreUndoUpdate = false; 11772 case 0x0D: //(8 + 4 + 1) group scale and position
11583 } 11773 // exception as above
11584 11774
11585 break; 11775 udata.position = new Vector3(block.Data, 0);
11776 udata.scale = new Vector3(block.Data, 12);
11586 11777
11587 case 21: 11778 udata.change = ObjectChangeType.groupPS;
11588 Vector3 scale6 = new Vector3(block.Data, 12); 11779 updatehandler(localId, udata, this);
11589 Vector3 pos6 = new Vector3(block.Data, 0); 11780 break;
11590 11781
11591 handlerUpdatePrimScale = OnUpdatePrimScale; 11782 case 0x1C: // (0x10 + 8 + 4 ) group scale UNIFORM
11592 if (handlerUpdatePrimScale != null) 11783 udata.scale = new Vector3(block.Data, 0);
11593 {
11594 part.StoreUndoState(false);
11595 part.IgnoreUndoUpdate = true;
11596 11784
11597 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); 11785 udata.change = ObjectChangeType.groupUS;
11598 handlerUpdatePrimScale(localId, scale6, this); 11786 updatehandler(localId, udata, this);
11599 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11787 break;
11600 if (handlerUpdatePrimSinglePosition != null)
11601 {
11602 handlerUpdatePrimSinglePosition(localId, pos6, this);
11603 }
11604 11788
11605 part.IgnoreUndoUpdate = false; 11789 case 0x1D: // (UNIFORM + GROUP + SCALE + POS)
11606 } 11790 udata.position = new Vector3(block.Data, 0);
11607 break; 11791 udata.scale = new Vector3(block.Data, 12);
11608 11792
11609 default: 11793 udata.change = ObjectChangeType.groupPUS;
11610 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); 11794 updatehandler(localId, udata, this);
11611 break; 11795 break;
11796
11797 default:
11798 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type));
11799 break;
11800 }
11612 } 11801 }
11613 11802
11614// for (int j = 0; j < parts.Length; j++)
11615// parts[j].IgnoreUndoUpdate = false;
11616 } 11803 }
11617 } 11804 }
11618 } 11805 }
11619
11620 return true; 11806 return true;
11621 } 11807 }
11622 11808
@@ -12066,7 +12252,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12066// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}", 12252// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}",
12067// requestID, taskID, (SourceType)sourceType, Name); 12253// requestID, taskID, (SourceType)sourceType, Name);
12068 12254
12255
12256 //Note, the bool returned from the below function is useless since it is always false.
12069 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 12257 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
12258
12070 } 12259 }
12071 12260
12072 /// <summary> 12261 /// <summary>
@@ -12132,7 +12321,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12132 /// <returns></returns> 12321 /// <returns></returns>
12133 private static int CalculateNumPackets(byte[] data) 12322 private static int CalculateNumPackets(byte[] data)
12134 { 12323 {
12135 const uint m_maxPacketSize = 600; 12324// const uint m_maxPacketSize = 600;
12325 uint m_maxPacketSize = MaxTransferBytesPerPacket;
12136 int numPackets = 1; 12326 int numPackets = 1;
12137 12327
12138 if (data == null) 12328 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 55780d6..60ab70e 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -110,7 +110,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
110 /// <summary>Handlers for incoming packets</summary> 110 /// <summary>Handlers for incoming packets</summary>
111 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 111 //PacketEventDictionary packetEvents = new PacketEventDictionary();
112 /// <summary>Incoming packets that are awaiting handling</summary> 112 /// <summary>Incoming packets that are awaiting handling</summary>
113 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 113 //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
114
115 private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>();
116
114 /// <summary></summary> 117 /// <summary></summary>
115 //private UDPClientCollection m_clients = new UDPClientCollection(); 118 //private UDPClientCollection m_clients = new UDPClientCollection();
116 /// <summary>Bandwidth throttle for this UDP server</summary> 119 /// <summary>Bandwidth throttle for this UDP server</summary>
@@ -155,6 +158,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
155 /// <summary>Flag to signal when clients should send pings</summary> 158 /// <summary>Flag to signal when clients should send pings</summary>
156 protected bool m_sendPing; 159 protected bool m_sendPing;
157 160
161 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
162
158 private int m_defaultRTO = 0; 163 private int m_defaultRTO = 0;
159 private int m_maxRTO = 0; 164 private int m_maxRTO = 0;
160 private int m_ackTimeout = 0; 165 private int m_ackTimeout = 0;
@@ -765,19 +770,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
765 770
766 #region Packet to Client Mapping 771 #region Packet to Client Mapping
767 772
768 // UseCircuitCode handling 773 // If there is already a client for this endpoint, don't process UseCircuitCode
769 if (packet.Type == PacketType.UseCircuitCode) 774 IClientAPI client = null;
775 if (!m_scene.TryGetClient(address, out client))
770 { 776 {
771 object[] array = new object[] { buffer, packet }; 777 // UseCircuitCode handling
778 if (packet.Type == PacketType.UseCircuitCode)
779 {
780 // And if there is a UseCircuitCode pending, also drop it
781 lock (m_pendingCache)
782 {
783 if (m_pendingCache.Contains(address))
784 return;
772 785
773 Util.FireAndForget(HandleUseCircuitCode, array); 786 m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60);
787 }
774 788
775 return; 789 object[] array = new object[] { buffer, packet };
790
791 Util.FireAndForget(HandleUseCircuitCode, array);
792
793 return;
794 }
795 }
796
797 // If this is a pending connection, enqueue, don't process yet
798 lock (m_pendingCache)
799 {
800 Queue<UDPPacketBuffer> queue;
801 if (m_pendingCache.TryGetValue(address, out queue))
802 {
803 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
804 queue.Enqueue(buffer);
805 return;
806 }
776 } 807 }
777 808
778 // Determine which agent this packet came from 809 // Determine which agent this packet came from
779 IClientAPI client; 810 if (client == null || !(client is LLClientView))
780 if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView))
781 { 811 {
782 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 812 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
783 return; 813 return;
@@ -786,7 +816,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
786 udpClient = ((LLClientView)client).UDPClient; 816 udpClient = ((LLClientView)client).UDPClient;
787 817
788 if (!udpClient.IsConnected) 818 if (!udpClient.IsConnected)
819 {
820// m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName);
789 return; 821 return;
822 }
790 823
791 #endregion Packet to Client Mapping 824 #endregion Packet to Client Mapping
792 825
@@ -889,7 +922,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
889 #endregion Ping Check Handling 922 #endregion Ping Check Handling
890 923
891 // Inbox insertion 924 // Inbox insertion
892 packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); 925 if (packet.Type == PacketType.AgentUpdate ||
926 packet.Type == PacketType.ChatFromViewer)
927 packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet));
928 else
929 packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet));
930// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
893 } 931 }
894 932
895 #region BinaryStats 933 #region BinaryStats
@@ -1011,6 +1049,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1011 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1049 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1012 if (client != null) 1050 if (client != null)
1013 client.SceneAgent.SendInitialDataToMe(); 1051 client.SceneAgent.SendInitialDataToMe();
1052
1053 // Now we know we can handle more data
1054 Thread.Sleep(200);
1055
1056 // Obtain the queue and remove it from the cache
1057 Queue<UDPPacketBuffer> queue = null;
1058
1059 lock (m_pendingCache)
1060 {
1061 if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue))
1062 {
1063 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1064 return;
1065 }
1066 m_pendingCache.Remove(remoteEndPoint);
1067 }
1068
1069 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1070
1071 // Reinject queued packets
1072 while(queue.Count > 0)
1073 {
1074 UDPPacketBuffer buf = queue.Dequeue();
1075 PacketReceived(buf);
1076 }
1077 queue = null;
1014 } 1078 }
1015 else 1079 else
1016 { 1080 {
@@ -1018,6 +1082,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1018 m_log.WarnFormat( 1082 m_log.WarnFormat(
1019 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1083 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1020 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); 1084 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint);
1085 lock (m_pendingCache)
1086 m_pendingCache.Remove(remoteEndPoint);
1021 } 1087 }
1022 1088
1023 // m_log.DebugFormat( 1089 // m_log.DebugFormat(
@@ -1136,7 +1202,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1136 if (!client.SceneAgent.IsChildAgent) 1202 if (!client.SceneAgent.IsChildAgent)
1137 client.Kick("Simulator logged you out due to connection timeout"); 1203 client.Kick("Simulator logged you out due to connection timeout");
1138 1204
1139 client.CloseWithoutChecks(); 1205 client.CloseWithoutChecks(true);
1140 } 1206 }
1141 } 1207 }
1142 1208
@@ -1148,6 +1214,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1148 1214
1149 while (base.IsRunning) 1215 while (base.IsRunning)
1150 { 1216 {
1217 m_scene.ThreadAlive(1);
1151 try 1218 try
1152 { 1219 {
1153 IncomingPacket incomingPacket = null; 1220 IncomingPacket incomingPacket = null;
@@ -1190,6 +1257,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1190 1257
1191 while (base.IsRunning) 1258 while (base.IsRunning)
1192 { 1259 {
1260 m_scene.ThreadAlive(2);
1193 try 1261 try
1194 { 1262 {
1195 m_packetSent = false; 1263 m_packetSent = false;
@@ -1411,8 +1479,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1411 Packet packet = incomingPacket.Packet; 1479 Packet packet = incomingPacket.Packet;
1412 LLClientView client = incomingPacket.Client; 1480 LLClientView client = incomingPacket.Client;
1413 1481
1414 if (client.IsActive) 1482// if (client.IsActive)
1415 { 1483// {
1416 m_currentIncomingClient = client; 1484 m_currentIncomingClient = client;
1417 1485
1418 try 1486 try
@@ -1439,13 +1507,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1439 { 1507 {
1440 m_currentIncomingClient = null; 1508 m_currentIncomingClient = null;
1441 } 1509 }
1442 } 1510// }
1443 else 1511// else
1444 { 1512// {
1445 m_log.DebugFormat( 1513// m_log.DebugFormat(
1446 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1514// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1447 packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1515// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1448 } 1516// }
1449 } 1517 }
1450 1518
1451 protected void LogoutHandler(IClientAPI client) 1519 protected void LogoutHandler(IClientAPI client)
@@ -1455,8 +1523,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1455 if (!client.IsLoggingOut) 1523 if (!client.IsLoggingOut)
1456 { 1524 {
1457 client.IsLoggingOut = true; 1525 client.IsLoggingOut = true;
1458 client.Close(); 1526 client.Close(false, false);
1527 }
1528 }
1529 }
1530
1531 internal class DoubleQueue<T> where T:class
1532 {
1533 private Queue<T> m_lowQueue = new Queue<T>();
1534 private Queue<T> m_highQueue = new Queue<T>();
1535
1536 private object m_syncRoot = new object();
1537 private Semaphore m_s = new Semaphore(0, 1);
1538
1539 public DoubleQueue()
1540 {
1541 }
1542
1543 public virtual int Count
1544 {
1545 get { return m_highQueue.Count + m_lowQueue.Count; }
1546 }
1547
1548 public virtual void Enqueue(T data)
1549 {
1550 Enqueue(m_lowQueue, data);
1551 }
1552
1553 public virtual void EnqueueLow(T data)
1554 {
1555 Enqueue(m_lowQueue, data);
1556 }
1557
1558 public virtual void EnqueueHigh(T data)
1559 {
1560 Enqueue(m_highQueue, data);
1561 }
1562
1563 private void Enqueue(Queue<T> q, T data)
1564 {
1565 lock (m_syncRoot)
1566 {
1567 m_lowQueue.Enqueue(data);
1568 m_s.WaitOne(0);
1569 m_s.Release();
1570 }
1571 }
1572
1573 public virtual T Dequeue()
1574 {
1575 return Dequeue(Timeout.Infinite);
1576 }
1577
1578 public virtual T Dequeue(int tmo)
1579 {
1580 return Dequeue(TimeSpan.FromMilliseconds(tmo));
1581 }
1582
1583 public virtual T Dequeue(TimeSpan wait)
1584 {
1585 T res = null;
1586
1587 if (!Dequeue(wait, ref res))
1588 return null;
1589
1590 return res;
1591 }
1592
1593 public bool Dequeue(int timeout, ref T res)
1594 {
1595 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
1596 }
1597
1598 public bool Dequeue(TimeSpan wait, ref T res)
1599 {
1600 if (!m_s.WaitOne(wait))
1601 return false;
1602
1603 lock (m_syncRoot)
1604 {
1605 if (m_highQueue.Count > 0)
1606 res = m_highQueue.Dequeue();
1607 else
1608 res = m_lowQueue.Dequeue();
1609
1610 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
1611 return true;
1612
1613 try
1614 {
1615 m_s.Release();
1616 }
1617 catch
1618 {
1619 }
1620
1621 return true;
1622 }
1623 }
1624
1625 public virtual void Clear()
1626 {
1627
1628 lock (m_syncRoot)
1629 {
1630 // Make sure sem count is 0
1631 m_s.WaitOne(0);
1632
1633 m_lowQueue.Clear();
1634 m_highQueue.Clear();
1459 } 1635 }
1460 } 1636 }
1461 } 1637 }
1462} \ No newline at end of file 1638}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 039379d..cfe7c9d 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -100,10 +100,6 @@ namespace OpenMetaverse
100 const int SIO_UDP_CONNRESET = -1744830452; 100 const int SIO_UDP_CONNRESET = -1744830452;
101 101
102 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 102 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
103
104 m_log.DebugFormat(
105 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
106 ipep.Address, ipep.Port);
107 103
108 m_udpSocket = new Socket( 104 m_udpSocket = new Socket(
109 AddressFamily.InterNetwork, 105 AddressFamily.InterNetwork,