Compare commits
288 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48a5f10be1 | ||
|
|
ecb759c1e5 | ||
|
|
59a29f5f22 | ||
|
|
356d597296 | ||
|
|
b0facd147a | ||
|
|
b6476eaac3 | ||
|
|
2a85372169 | ||
|
|
1c3b0da74a | ||
|
|
c1667d39a6 | ||
|
|
217f47b0d5 | ||
|
|
ed14dac0a3 | ||
|
|
ee7478fa16 | ||
|
|
5d3723a47f | ||
|
|
84b7ae2573 | ||
|
|
423101b425 | ||
|
|
e3453dd9ca | ||
|
|
b6cd3b625e | ||
|
|
8d59385eea | ||
|
|
ec6a195e40 | ||
|
|
2954ceccae | ||
|
|
884d603cac | ||
|
|
9ccb578721 | ||
|
|
d6f54b25cd | ||
|
|
dda999a22c | ||
|
|
3b3d9967b1 | ||
|
|
75ab9b4b88 | ||
|
|
15283d35f1 | ||
|
|
6a0de355e0 | ||
|
|
65a25ee510 | ||
|
|
ca412032e8 | ||
|
|
743437262e | ||
|
|
916e3bf886 | ||
|
|
9c89ad9154 | ||
|
|
33cff9b9d7 | ||
|
|
0e611c47d3 | ||
|
|
fc24563206 | ||
|
|
14d05dc2a9 | ||
|
|
337ea019bd | ||
|
|
cdea572d2e | ||
|
|
11e0ad6dc8 | ||
|
|
c8f0d476d2 | ||
|
|
69a6f6e3cd | ||
|
|
e8347b7095 | ||
|
|
506437b684 | ||
|
|
9f01c3d408 | ||
|
|
58869e5aa0 | ||
|
|
f3134b5cf6 | ||
|
|
eb5ec4a786 | ||
|
|
c8af20f966 | ||
|
|
d6f563794e | ||
|
|
2eaa6d5ace | ||
|
|
1a2ab7bc69 | ||
|
|
a96ac73302 | ||
|
|
57094bd017 | ||
|
|
112cddc9ca | ||
|
|
16d5b79d57 | ||
|
|
1201307c73 | ||
|
|
a85741ac37 | ||
|
|
3bd134474b | ||
|
|
b19ead5f9e | ||
|
|
7ff4eec79c | ||
|
|
7aff238eee | ||
|
|
af9d8de515 | ||
|
|
f1f390cfdf | ||
|
|
74014a3854 | ||
|
|
e4a6611865 | ||
|
|
056c9a59b2 | ||
|
|
ae1f2114f5 | ||
|
|
1b1f841c6a | ||
|
|
43a2da9edb | ||
|
|
f6e5791ecd | ||
|
|
843112340e | ||
|
|
7e73f609e5 | ||
|
|
db9616f7ba | ||
|
|
8674604ff5 | ||
|
|
462f7bccf9 | ||
|
|
510e809aba | ||
|
|
951b45b80f | ||
|
|
7b327848d0 | ||
|
|
2f998fce1f | ||
|
|
1816ecb747 | ||
|
|
eacba4fc0b | ||
|
|
9fac7fd932 | ||
|
|
f2b0377c28 | ||
|
|
d933bdbd59 | ||
|
|
f9fa34408d | ||
|
|
857494f6bd | ||
|
|
dff7cae2ee | ||
|
|
0e3fce9b5c | ||
|
|
4b2b14dad1 | ||
|
|
3769739ca7 | ||
|
|
3717812ce0 | ||
|
|
ae64d089c6 | ||
|
|
58b13d51a7 | ||
|
|
5691a8b860 | ||
|
|
f7b4802577 | ||
|
|
8183c2926d | ||
|
|
3c9b9a848f | ||
|
|
3399596e0e | ||
|
|
d32cf21576 | ||
|
|
1926de5a05 | ||
|
|
a4551b027b | ||
|
|
56c776066c | ||
|
|
0229e90dcc | ||
|
|
e420f815dc | ||
|
|
1a7be7b00e | ||
|
|
0f6b7b6a41 | ||
|
|
f202c36106 | ||
|
|
bfa6896678 | ||
|
|
571fd966cb | ||
|
|
f263d6a910 | ||
|
|
972b0b52f9 | ||
|
|
25baa2d894 | ||
|
|
f9769a9fcb | ||
|
|
bb48060b44 | ||
|
|
d043213317 | ||
|
|
5bec5bcf71 | ||
|
|
87ca820f9b | ||
|
|
0b29877790 | ||
|
|
97437feb06 | ||
|
|
2524517986 | ||
|
|
99954c1498 | ||
|
|
2b82c421ad | ||
|
|
4329cc7b8a | ||
|
|
32a4ce94f0 | ||
|
|
340005c5bf | ||
|
|
4b6c3fd4bb | ||
|
|
988112d446 | ||
|
|
1f22b29ca3 | ||
|
|
5292b8b8be | ||
|
|
854f2a913c | ||
|
|
f5316984ab | ||
|
|
e5b739aaeb | ||
|
|
5301648cff | ||
|
|
6d3ee8bb39 | ||
|
|
78143769bf | ||
|
|
dca04c7b61 | ||
|
|
80a41e670d | ||
|
|
9f3feeff8d | ||
|
|
f907182ab2 | ||
|
|
4cf49369b5 | ||
|
|
fda39c11bf | ||
|
|
798846c5b6 | ||
|
|
06617ffd06 | ||
|
|
d24122b706 | ||
|
|
afcabf5244 | ||
|
|
5709bed548 | ||
|
|
68ea096f1b | ||
|
|
714db90832 | ||
|
|
b23425c7c4 | ||
|
|
9ec9dafae6 | ||
|
|
6c312bce7f | ||
|
|
7b6c0232a5 | ||
|
|
4cfaa01c0a | ||
|
|
6b3f9fcde0 | ||
|
|
625e5e913a | ||
|
|
881e92a726 | ||
|
|
0fa303b1cf | ||
|
|
9737e6d52e | ||
|
|
e23d7ff9c0 | ||
|
|
ef686ead37 | ||
|
|
bc06f3dcaf | ||
|
|
8e7032ece8 | ||
|
|
5c5b359bcb | ||
|
|
fc1522ab60 | ||
|
|
2ed768cbf5 | ||
|
|
7119de56ff | ||
|
|
ed513fc7be | ||
|
|
22f25dfcab | ||
|
|
aaa30dcebc | ||
|
|
c935f03467 | ||
|
|
94517c8d5c | ||
|
|
257b1b517d | ||
|
|
aeed4d3041 | ||
|
|
478acfff34 | ||
|
|
10e87f9cdc | ||
|
|
6993a26ba5 | ||
|
|
93ba0332c4 | ||
|
|
9825861f4a | ||
|
|
f4b02f8e39 | ||
|
|
2c6555021f | ||
|
|
3888b9a670 | ||
|
|
1aa7469253 | ||
|
|
3c3ea19620 | ||
|
|
0d2243a393 | ||
|
|
917d753f1c | ||
|
|
a4290048e5 | ||
|
|
cba8b4f8b8 | ||
|
|
6a77a65675 | ||
|
|
16ffc764bf | ||
|
|
cf080a68d6 | ||
|
|
f726150afd | ||
|
|
1f34c8277d | ||
|
|
66cb533f26 | ||
|
|
5145356467 | ||
|
|
77f579dcc8 | ||
|
|
7c0843aad1 | ||
|
|
4e18e71089 | ||
|
|
94bbbf96c7 | ||
|
|
c6e375291a | ||
|
|
c53c55fed0 | ||
|
|
2ca31a9841 | ||
|
|
1b1f0a2d77 | ||
|
|
b099f26376 | ||
|
|
c89db34fc4 | ||
|
|
8c7149063b | ||
|
|
bab7dab4c5 | ||
|
|
51fe97a00c | ||
|
|
daad0a3e11 | ||
|
|
a927787434 | ||
|
|
cbb5ddd944 | ||
|
|
71ba85137f | ||
|
|
a8a9d13dc0 | ||
|
|
1f3218e53f | ||
|
|
08cd5d2503 | ||
|
|
817f2d341d | ||
|
|
794d184c25 | ||
|
|
f94b92df46 | ||
|
|
c215b1ad16 | ||
|
|
5f4f9f0230 | ||
|
|
d73805d7f4 | ||
|
|
d71c6dea7e | ||
|
|
30f4a33f01 | ||
|
|
5c162ccd57 | ||
|
|
d547bcf8d1 | ||
|
|
af2954898e | ||
|
|
b56673c920 | ||
|
|
0c5fefacb4 | ||
|
|
de87e4871b | ||
|
|
39cb2063bf | ||
|
|
d5cc959683 | ||
|
|
a1e857932a | ||
|
|
7550b97e65 | ||
|
|
98b46d48fe | ||
|
|
514dd85199 | ||
|
|
53c25a4778 | ||
|
|
2b0de66216 | ||
|
|
3b25021180 | ||
|
|
abf94627f6 | ||
|
|
6adc810eaa | ||
|
|
a5410c2c19 | ||
|
|
42179578fc | ||
|
|
008c6a4610 | ||
|
|
01280e9b94 | ||
|
|
96d1ba90d7 | ||
|
|
655625ab87 | ||
|
|
c3d9acc9a9 | ||
|
|
a7f4804f53 | ||
|
|
3229e32b4e | ||
|
|
9707a2d57c | ||
|
|
d9d4fb10d9 | ||
|
|
f94ef37b46 | ||
|
|
5c646e2603 | ||
|
|
729d90173f | ||
|
|
2de5479c3f | ||
|
|
01a2b0b289 | ||
|
|
72219eae7d | ||
|
|
6375db1533 | ||
|
|
4e06a46dc5 | ||
|
|
200376b3c4 | ||
|
|
d34b84b531 | ||
|
|
9ff8efc720 | ||
|
|
d1b5f8d9d7 | ||
|
|
31343aa7c3 | ||
|
|
5f44be99ef | ||
|
|
5cc9b820e5 | ||
|
|
f2c8c7a7b8 | ||
|
|
8333b928fa | ||
|
|
c33c8db825 | ||
|
|
e1f8d2adb0 | ||
|
|
8301f7b17f | ||
|
|
93fa9e8991 | ||
|
|
878b67b333 | ||
|
|
0b02a4d42e | ||
|
|
bf0b8170f7 | ||
|
|
b660c4991b | ||
|
|
79f3ce2e9f | ||
|
|
8f87f55d05 | ||
|
|
7fd38788b4 | ||
|
|
0b72f773c7 | ||
|
|
43a6f28620 | ||
|
|
3ac3be99ae | ||
|
|
33b66009e4 | ||
|
|
d6476b6277 | ||
|
|
f2a5fad18f | ||
|
|
ff53add54d | ||
|
|
120f8145fc | ||
|
|
67ebe80dd9 |
@@ -146,6 +146,7 @@ what it is today.
|
||||
* Stefan_Boom / stoehr
|
||||
* Strawberry Fride
|
||||
* Talun
|
||||
* TechplexEngineer (Blake Bourque)
|
||||
* TBG Renfold
|
||||
* tglion
|
||||
* tlaukkan/Tommil (Tommi S. E. Laukkanen, Bubble Cloud)
|
||||
|
||||
@@ -125,7 +125,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
|
||||
bool changed = m_openSim.PopulateRegionEstateInfo(regionsToLoad[i]);
|
||||
m_openSim.CreateRegion(regionsToLoad[i], true, out scene);
|
||||
if (changed)
|
||||
regionsToLoad[i].EstateSettings.Save();
|
||||
regionsToLoad[i].EstateSettings.Save();
|
||||
|
||||
if (scene != null)
|
||||
{
|
||||
@@ -136,11 +136,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//[TODO]: Temporary fix for an issue after the mono-addis upgrade
|
||||
// PostInilise can fire before the region is loaded, so need to
|
||||
// track down the cause of that
|
||||
Thread.Sleep(300);
|
||||
|
||||
m_openSim.ModuleLoader.PostInitialise();
|
||||
m_openSim.ModuleLoader.ClearCache();
|
||||
}
|
||||
|
||||
@@ -539,7 +539,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||
/// path has not already been registered, the method is added to the active
|
||||
/// handler table.
|
||||
/// </summary>
|
||||
|
||||
public void AddStreamHandler(string httpMethod, string path, RestMethod method)
|
||||
{
|
||||
if (!IsEnabled)
|
||||
|
||||
@@ -101,18 +101,8 @@ namespace OpenSim.Capabilities.Handlers
|
||||
llsdItem.item_id = invItem.ID;
|
||||
llsdItem.name = invItem.Name;
|
||||
llsdItem.parent_id = invItem.Folder;
|
||||
|
||||
try
|
||||
{
|
||||
llsdItem.type = Utils.AssetTypeToString((AssetType)invItem.AssetType);
|
||||
llsdItem.inv_type = Utils.InventoryTypeToString((InventoryType)invItem.InvType);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[WEB FETCH INV DESC HANDLER]: Problem setting asset {0} inventory {1} types while converting inventory item {2}: {3}",
|
||||
invItem.AssetType, invItem.InvType, invItem.Name, e.Message);
|
||||
}
|
||||
llsdItem.type = invItem.AssetType;
|
||||
llsdItem.inv_type = invItem.InvType;
|
||||
|
||||
llsdItem.permissions = new LLSDPermissions();
|
||||
llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
|
||||
@@ -126,21 +116,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||
llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
|
||||
llsdItem.sale_info = new LLSDSaleInfo();
|
||||
llsdItem.sale_info.sale_price = invItem.SalePrice;
|
||||
switch (invItem.SaleType)
|
||||
{
|
||||
default:
|
||||
llsdItem.sale_info.sale_type = "not";
|
||||
break;
|
||||
case 1:
|
||||
llsdItem.sale_info.sale_type = "original";
|
||||
break;
|
||||
case 2:
|
||||
llsdItem.sale_info.sale_type = "copy";
|
||||
break;
|
||||
case 3:
|
||||
llsdItem.sale_info.sale_type = "contents";
|
||||
break;
|
||||
}
|
||||
llsdItem.sale_info.sale_type = invItem.SaleType;
|
||||
|
||||
return llsdItem;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,6 @@ namespace OpenSim.Capabilities.Handlers
|
||||
{
|
||||
m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service");
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
|
||||
return null;
|
||||
}
|
||||
|
||||
UUID textureID;
|
||||
@@ -115,7 +114,6 @@ namespace OpenSim.Capabilities.Handlers
|
||||
// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}",
|
||||
// textureID, httpResponse.StatusCode, httpResponse.ContentLength);
|
||||
|
||||
httpResponse.Send();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,11 +156,12 @@ namespace OpenSim.Capabilities.Handlers
|
||||
inv.Folders = new List<InventoryFolderBase>();
|
||||
inv.Items = new List<InventoryItemBase>();
|
||||
int version = 0;
|
||||
int descendents = 0;
|
||||
|
||||
inv
|
||||
= Fetch(
|
||||
invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
|
||||
invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version);
|
||||
invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
|
||||
|
||||
if (inv != null && inv.Folders != null)
|
||||
{
|
||||
@@ -168,6 +169,8 @@ namespace OpenSim.Capabilities.Handlers
|
||||
{
|
||||
contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
|
||||
}
|
||||
|
||||
descendents += inv.Folders.Count;
|
||||
}
|
||||
|
||||
if (inv != null && inv.Items != null)
|
||||
@@ -178,7 +181,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||
}
|
||||
}
|
||||
|
||||
contents.descendents = contents.items.Array.Count + contents.categories.Array.Count;
|
||||
contents.descendents = descendents;
|
||||
contents.version = version;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
@@ -206,7 +209,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||
/// <returns>An empty InventoryCollection if the inventory look up failed</returns>
|
||||
private InventoryCollection Fetch(
|
||||
UUID agentID, UUID folderID, UUID ownerID,
|
||||
bool fetchFolders, bool fetchItems, int sortOrder, out int version)
|
||||
bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
|
||||
@@ -215,6 +218,8 @@ namespace OpenSim.Capabilities.Handlers
|
||||
// FIXME MAYBE: We're not handling sortOrder!
|
||||
|
||||
version = 0;
|
||||
descendents = 0;
|
||||
|
||||
InventoryFolderImpl fold;
|
||||
if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
|
||||
{
|
||||
@@ -223,6 +228,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||
InventoryCollection ret = new InventoryCollection();
|
||||
ret.Folders = new List<InventoryFolderBase>();
|
||||
ret.Items = fold.RequestListOfItems();
|
||||
descendents = ret.Folders.Count + ret.Items.Count;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -246,24 +252,72 @@ namespace OpenSim.Capabilities.Handlers
|
||||
|
||||
version = containingFolder.Version;
|
||||
|
||||
// if (fetchItems)
|
||||
if (fetchItems)
|
||||
{
|
||||
List<InventoryItemBase> itemsToReturn = contents.Items;
|
||||
List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
|
||||
|
||||
// descendents must only include the links, not the linked items we add
|
||||
descendents = originalItems.Count;
|
||||
|
||||
// Add target items for links in this folder before the links themselves.
|
||||
foreach (InventoryItemBase item in originalItems)
|
||||
{
|
||||
if (item.AssetType == (int)AssetType.Link)
|
||||
{
|
||||
InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
|
||||
|
||||
// Take care of genuinely broken links where the target doesn't exist
|
||||
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
||||
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
||||
// rather than having to keep track of every folder requested in the recursion.
|
||||
if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
|
||||
itemsToReturn.Insert(0, linkedItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Now scan for folder links and insert the items they target and those links at the head of the return data
|
||||
foreach (InventoryItemBase item in originalItems)
|
||||
{
|
||||
if (item.AssetType == (int)AssetType.LinkFolder)
|
||||
{
|
||||
InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
|
||||
List<InventoryItemBase> links = linkedFolderContents.Items;
|
||||
|
||||
itemsToReturn.InsertRange(0, links);
|
||||
|
||||
foreach (InventoryItemBase link in linkedFolderContents.Items)
|
||||
{
|
||||
// Take care of genuinely broken links where the target doesn't exist
|
||||
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
||||
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
||||
// rather than having to keep track of every folder requested in the recursion.
|
||||
if (link != null)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
|
||||
// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
|
||||
|
||||
InventoryItemBase linkedItem
|
||||
= m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
|
||||
|
||||
if (linkedItem != null)
|
||||
itemsToReturn.Insert(0, linkedItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// foreach (InventoryItemBase item in contents.Items)
|
||||
// {
|
||||
// List<InventoryItemBase> linkedItemsToAdd = new List<InventoryItemBase>();
|
||||
//
|
||||
// foreach (InventoryItemBase item in contents.Items)
|
||||
// {
|
||||
// if (item.AssetType == (int)AssetType.Link)
|
||||
// {
|
||||
// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
|
||||
//
|
||||
// // Take care of genuinely broken links where the target doesn't exist
|
||||
// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
||||
// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
||||
// // rather than having to keep track of every folder requested in the recursion.
|
||||
// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
|
||||
// linkedItemsToAdd.Insert(0, linkedItem);
|
||||
// }
|
||||
// }
|
||||
// m_log.DebugFormat(
|
||||
// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
|
||||
// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
|
||||
// }
|
||||
|
||||
// =====
|
||||
|
||||
//
|
||||
// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
|
||||
// {
|
||||
@@ -340,12 +394,8 @@ namespace OpenSim.Capabilities.Handlers
|
||||
llsdFolder.folder_id = invFolder.ID;
|
||||
llsdFolder.parent_id = invFolder.ParentID;
|
||||
llsdFolder.name = invFolder.Name;
|
||||
|
||||
if (invFolder.Type == (short)AssetType.Unknown || !Enum.IsDefined(typeof(AssetType), (sbyte)invFolder.Type))
|
||||
llsdFolder.type = "-1";
|
||||
else
|
||||
llsdFolder.type = Utils.AssetTypeToString((AssetType)invFolder.Type);
|
||||
llsdFolder.preferred_type = "-1";
|
||||
llsdFolder.type = invFolder.Type;
|
||||
llsdFolder.preferred_type = -1;
|
||||
|
||||
return llsdFolder;
|
||||
}
|
||||
@@ -365,18 +415,8 @@ namespace OpenSim.Capabilities.Handlers
|
||||
llsdItem.item_id = invItem.ID;
|
||||
llsdItem.name = invItem.Name;
|
||||
llsdItem.parent_id = invItem.Folder;
|
||||
|
||||
try
|
||||
{
|
||||
llsdItem.type = Utils.AssetTypeToString((AssetType)invItem.AssetType);
|
||||
llsdItem.inv_type = Utils.InventoryTypeToString((InventoryType)invItem.InvType);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[WEB FETCH INV DESC HANDLER]: Problem setting asset {0} inventory {1} types while converting inventory item {2}: {3}",
|
||||
invItem.AssetType, invItem.InvType, invItem.Name, e.Message);
|
||||
}
|
||||
llsdItem.type = invItem.AssetType;
|
||||
llsdItem.inv_type = invItem.InvType;
|
||||
|
||||
llsdItem.permissions = new LLSDPermissions();
|
||||
llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
|
||||
@@ -390,21 +430,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||
llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
|
||||
llsdItem.sale_info = new LLSDSaleInfo();
|
||||
llsdItem.sale_info.sale_price = invItem.SalePrice;
|
||||
switch (invItem.SaleType)
|
||||
{
|
||||
default:
|
||||
llsdItem.sale_info.sale_type = "not";
|
||||
break;
|
||||
case 1:
|
||||
llsdItem.sale_info.sale_type = "original";
|
||||
break;
|
||||
case 2:
|
||||
llsdItem.sale_info.sale_type = "copy";
|
||||
break;
|
||||
case 3:
|
||||
llsdItem.sale_info.sale_type = "contents";
|
||||
break;
|
||||
}
|
||||
llsdItem.sale_info.sale_type = invItem.SaleType;
|
||||
|
||||
return llsdItem;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenSim.Framework.Capabilities
|
||||
public UUID folder_id;
|
||||
public UUID parent_id;
|
||||
public string name;
|
||||
public string type;
|
||||
public string preferred_type;
|
||||
public int type;
|
||||
public int preferred_type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ namespace OpenSim.Framework.Capabilities
|
||||
public UUID asset_id;
|
||||
public UUID item_id;
|
||||
public LLSDPermissions permissions;
|
||||
public string type;
|
||||
public string inv_type;
|
||||
public int type;
|
||||
public int inv_type;
|
||||
public int flags;
|
||||
|
||||
public LLSDSaleInfo sale_info;
|
||||
@@ -65,7 +65,7 @@ namespace OpenSim.Framework.Capabilities
|
||||
public class LLSDSaleInfo
|
||||
{
|
||||
public int sale_price;
|
||||
public string sale_type;
|
||||
public int sale_type;
|
||||
}
|
||||
|
||||
[OSDMap]
|
||||
|
||||
@@ -66,9 +66,7 @@ namespace OpenSim.Framework.Capabilities
|
||||
|
||||
TResponse response = m_method(llsdRequest);
|
||||
|
||||
Encoding encoding = new UTF8Encoding(false);
|
||||
|
||||
return encoding.GetBytes(LLSDHelpers.SerialiseLLSDReply(response));
|
||||
return Util.UTF8NoBomEncoding.GetBytes(LLSDHelpers.SerialiseLLSDReply(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace OpenSim.ConsoleClient
|
||||
|
||||
request.ContentType = "application/x-www-form-urlencoded";
|
||||
|
||||
byte[] buffer = new System.Text.ASCIIEncoding().GetBytes(data);
|
||||
byte[] buffer = Encoding.ASCII.GetBytes(data);
|
||||
int length = (int) buffer.Length;
|
||||
request.ContentLength = length;
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ namespace OpenSim.Data
|
||||
bool Store(PresenceData data);
|
||||
|
||||
PresenceData Get(UUID sessionID);
|
||||
PresenceData Verify(UUID s_sessionID);
|
||||
void LogoutRegionAgents(UUID regionID);
|
||||
bool ReportAgent(UUID sessionID, UUID regionID);
|
||||
PresenceData[] Get(string field, string data);
|
||||
|
||||
@@ -61,17 +61,6 @@ namespace OpenSim.Data.MSSQL
|
||||
return ret[0];
|
||||
}
|
||||
|
||||
public PresenceData Verify(UUID s_sessionID)
|
||||
{
|
||||
PresenceData[] ret = Get("SecureSessionID",
|
||||
s_sessionID.ToString());
|
||||
|
||||
if (ret.Length == 0)
|
||||
return null;
|
||||
|
||||
return ret[0];
|
||||
}
|
||||
|
||||
public void LogoutRegionAgents(UUID regionID)
|
||||
{
|
||||
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
|
||||
|
||||
@@ -61,17 +61,6 @@ namespace OpenSim.Data.MySQL
|
||||
return ret[0];
|
||||
}
|
||||
|
||||
public PresenceData Verify(UUID s_sessionID)
|
||||
{
|
||||
PresenceData[] ret = Get("SecureSessionID",
|
||||
s_sessionID.ToString());
|
||||
|
||||
if (ret.Length == 0)
|
||||
return null;
|
||||
|
||||
return ret[0];
|
||||
}
|
||||
|
||||
public void LogoutRegionAgents(UUID regionID)
|
||||
{
|
||||
using (MySqlCommand cmd = new MySqlCommand())
|
||||
@@ -107,4 +96,4 @@ namespace OpenSim.Data.MySQL
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,19 +79,6 @@ namespace OpenSim.Data.Null
|
||||
return null;
|
||||
}
|
||||
|
||||
public PresenceData Verify(UUID s_sessionID)
|
||||
{
|
||||
if (Instance != this)
|
||||
return Instance.Verify(s_sessionID);
|
||||
|
||||
if (m_presenceData.ContainsKey(s_sessionID))
|
||||
{
|
||||
return m_presenceData[s_sessionID];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void LogoutRegionAgents(UUID regionID)
|
||||
{
|
||||
if (Instance != this)
|
||||
|
||||
@@ -1069,8 +1069,6 @@ namespace OpenSim.Data.Tests
|
||||
regionInfo.RegionLocX = 0;
|
||||
regionInfo.RegionLocY = 0;
|
||||
|
||||
Scene scene = new Scene(regionInfo);
|
||||
|
||||
SceneObjectPart sop = new SceneObjectPart();
|
||||
sop.Name = name;
|
||||
sop.Description = name;
|
||||
@@ -1081,7 +1079,7 @@ namespace OpenSim.Data.Tests
|
||||
sop.Shape = PrimitiveBaseShape.Default;
|
||||
|
||||
SceneObjectGroup sog = new SceneObjectGroup(sop);
|
||||
sog.SetScene(scene);
|
||||
// sog.SetScene(scene);
|
||||
|
||||
return sog;
|
||||
}
|
||||
|
||||
@@ -98,6 +98,11 @@ namespace OpenSim.Framework
|
||||
/// </summary>
|
||||
public string lastname;
|
||||
|
||||
/// <summary>
|
||||
/// Agent's full name.
|
||||
/// </summary>
|
||||
public string Name { get { return string.Format("{0} {1}", firstname, lastname); } }
|
||||
|
||||
/// <summary>
|
||||
/// Random Unique GUID for this session. Client gets this at login and it's
|
||||
/// only supposed to be disclosed over secure channels
|
||||
|
||||
@@ -79,6 +79,16 @@ namespace OpenSim.Framework.Console
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public void AddColumn(string name, int width)
|
||||
{
|
||||
Columns.Add(new ConsoleDisplayTableColumn(name, width));
|
||||
}
|
||||
|
||||
public void AddRow(params string[] cells)
|
||||
{
|
||||
Rows.Add(new ConsoleDisplayTableRow(cells));
|
||||
}
|
||||
|
||||
public void AddToStringBuilder(StringBuilder sb)
|
||||
{
|
||||
string formatString = GetFormatString();
|
||||
@@ -135,5 +145,10 @@ namespace OpenSim.Framework.Console
|
||||
{
|
||||
Cells = cells;
|
||||
}
|
||||
|
||||
public ConsoleDisplayTableRow(params string[] cells) : this()
|
||||
{
|
||||
Cells = new List<string>(cells);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -740,14 +740,21 @@ namespace OpenSim.Framework
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <value>
|
||||
/// Determines whether the client thread is doing anything or not.
|
||||
/// </value>
|
||||
/// <summary>
|
||||
/// True if the client is active (sending and receiving new UDP messages). False if the client is being closed.
|
||||
/// </summary>
|
||||
bool IsActive { get; set; }
|
||||
|
||||
/// <value>
|
||||
/// Determines whether the client is or has been removed from a given scene
|
||||
/// </value>
|
||||
/// <summary>
|
||||
/// Set if the client is closing due to a logout request
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Do not use this flag if you want to know if the client is closing, since it will not be set in other
|
||||
/// circumstances (e.g. if a child agent is closed or the agent is kicked off the simulator). Use IsActive
|
||||
/// instead with a IClientAPI.SceneAgent.IsChildAgent check if necessary.
|
||||
///
|
||||
/// Only set for root agents.
|
||||
/// </remarks>
|
||||
bool IsLoggingOut { get; set; }
|
||||
|
||||
bool SendLogoutPacketWhenClosing { set; }
|
||||
@@ -1346,7 +1353,6 @@ namespace OpenSim.Framework
|
||||
void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message);
|
||||
|
||||
void SendLogoutPacket();
|
||||
EndPoint GetClientEP();
|
||||
|
||||
// WARNING WARNING WARNING
|
||||
//
|
||||
@@ -1407,8 +1413,6 @@ namespace OpenSim.Framework
|
||||
|
||||
void SendGroupVoteHistory(UUID groupID, UUID transactionID, GroupVoteHistory[] Votes);
|
||||
|
||||
void KillEndDone();
|
||||
|
||||
bool AddGenericPacketHandler(string MethodName, GenericMessage handler);
|
||||
|
||||
void SendRebakeAvatarTextures(UUID textureID);
|
||||
|
||||
@@ -56,6 +56,11 @@ namespace OpenSim.Framework
|
||||
|
||||
public interface IScene
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of this scene.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
RegionInfo RegionInfo { get; }
|
||||
RegionStatus RegionStatus { get; set; }
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
@@ -71,5 +72,11 @@ namespace OpenSim.Framework
|
||||
/// This includes scene object data and the appearance data of other avatars.
|
||||
/// </remarks>
|
||||
void SendInitialDataToMe();
|
||||
|
||||
/// <summary>
|
||||
/// Direction in which the scene presence is looking.
|
||||
/// </summary>
|
||||
/// <remarks>Will be Vector3.Zero for a child agent.</remarks>
|
||||
Vector3 Lookat { get; }
|
||||
}
|
||||
}
|
||||
@@ -42,9 +42,7 @@ namespace OpenSim.Framework.Serialization.External
|
||||
/// </summary>
|
||||
public class LandDataSerializer
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected static UTF8Encoding m_utf8Encoding = new UTF8Encoding();
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private static Dictionary<string, Action<LandData, XmlTextReader>> m_ldProcessors
|
||||
= new Dictionary<string, Action<LandData, XmlTextReader>>();
|
||||
@@ -163,7 +161,7 @@ namespace OpenSim.Framework.Serialization.External
|
||||
/// <exception cref="System.Xml.XmlException"></exception>
|
||||
public static LandData Deserialize(byte[] serializedLandData)
|
||||
{
|
||||
return Deserialize(m_utf8Encoding.GetString(serializedLandData, 0, serializedLandData.Length));
|
||||
return Deserialize(Encoding.UTF8.GetString(serializedLandData, 0, serializedLandData.Length));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -40,8 +40,6 @@ namespace OpenSim.Framework.Serialization.External
|
||||
/// </summary>
|
||||
public class RegionSettingsSerializer
|
||||
{
|
||||
protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize settings
|
||||
/// </summary>
|
||||
@@ -50,7 +48,7 @@ namespace OpenSim.Framework.Serialization.External
|
||||
/// <exception cref="System.Xml.XmlException"></exception>
|
||||
public static RegionSettings Deserialize(byte[] serializedSettings)
|
||||
{
|
||||
return Deserialize(m_asciiEncoding.GetString(serializedSettings, 0, serializedSettings.Length));
|
||||
return Deserialize(Encoding.ASCII.GetString(serializedSettings, 0, serializedSettings.Length));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace OpenSim.Framework.Serialization.External
|
||||
/// </summary>
|
||||
public class UserInventoryItemSerializer
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private static Dictionary<string, Action<InventoryItemBase, XmlTextReader>> m_InventoryItemXmlProcessors
|
||||
= new Dictionary<string, Action<InventoryItemBase, XmlTextReader>>();
|
||||
|
||||
@@ -53,8 +53,6 @@ namespace OpenSim.Framework.Serialization
|
||||
TYPE_CONTIGUOUS_FILE = 8,
|
||||
}
|
||||
|
||||
protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
|
||||
|
||||
/// <summary>
|
||||
/// Binary reader for the underlying stream
|
||||
/// </summary>
|
||||
@@ -120,13 +118,13 @@ namespace OpenSim.Framework.Serialization
|
||||
if (header[156] == (byte)'L')
|
||||
{
|
||||
int longNameLength = ConvertOctalBytesToDecimal(header, 124, 11);
|
||||
tarHeader.FilePath = m_asciiEncoding.GetString(ReadData(longNameLength));
|
||||
tarHeader.FilePath = Encoding.ASCII.GetString(ReadData(longNameLength));
|
||||
//m_log.DebugFormat("[TAR ARCHIVE READER]: Got long file name {0}", tarHeader.FilePath);
|
||||
header = m_br.ReadBytes(512);
|
||||
}
|
||||
else
|
||||
{
|
||||
tarHeader.FilePath = m_asciiEncoding.GetString(header, 0, 100);
|
||||
tarHeader.FilePath = Encoding.ASCII.GetString(header, 0, 100);
|
||||
tarHeader.FilePath = tarHeader.FilePath.Trim(m_nullCharArray);
|
||||
//m_log.DebugFormat("[TAR ARCHIVE READER]: Got short file name {0}", tarHeader.FilePath);
|
||||
}
|
||||
@@ -205,7 +203,7 @@ namespace OpenSim.Framework.Serialization
|
||||
{
|
||||
// Trim leading white space: ancient tars do that instead
|
||||
// of leading 0s :-( don't ask. really.
|
||||
string oString = m_asciiEncoding.GetString(bytes, startIndex, count).TrimStart(m_spaceCharArray);
|
||||
string oString = Encoding.ASCII.GetString(bytes, startIndex, count).TrimStart(m_spaceCharArray);
|
||||
|
||||
int d = 0;
|
||||
|
||||
|
||||
@@ -41,9 +41,6 @@ namespace OpenSim.Framework.Serialization
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
|
||||
protected static UTF8Encoding m_utf8Encoding = new UTF8Encoding();
|
||||
|
||||
/// <summary>
|
||||
/// Binary writer for the underlying stream
|
||||
/// </summary>
|
||||
@@ -74,7 +71,7 @@ namespace OpenSim.Framework.Serialization
|
||||
/// <param name="data"></param>
|
||||
public void WriteFile(string filePath, string data)
|
||||
{
|
||||
WriteFile(filePath, m_utf8Encoding.GetBytes(data));
|
||||
WriteFile(filePath, Util.UTF8NoBomEncoding.GetBytes(data));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -85,7 +82,7 @@ namespace OpenSim.Framework.Serialization
|
||||
public void WriteFile(string filePath, byte[] data)
|
||||
{
|
||||
if (filePath.Length > 100)
|
||||
WriteEntry("././@LongLink", m_asciiEncoding.GetBytes(filePath), 'L');
|
||||
WriteEntry("././@LongLink", Encoding.ASCII.GetBytes(filePath), 'L');
|
||||
|
||||
char fileType;
|
||||
|
||||
@@ -137,7 +134,7 @@ namespace OpenSim.Framework.Serialization
|
||||
oString = "0" + oString;
|
||||
}
|
||||
|
||||
byte[] oBytes = m_asciiEncoding.GetBytes(oString);
|
||||
byte[] oBytes = Encoding.ASCII.GetBytes(oString);
|
||||
|
||||
return oBytes;
|
||||
}
|
||||
@@ -156,20 +153,20 @@ namespace OpenSim.Framework.Serialization
|
||||
byte[] header = new byte[512];
|
||||
|
||||
// file path field (100)
|
||||
byte[] nameBytes = m_asciiEncoding.GetBytes(filePath);
|
||||
byte[] nameBytes = Encoding.ASCII.GetBytes(filePath);
|
||||
int nameSize = (nameBytes.Length >= 100) ? 100 : nameBytes.Length;
|
||||
Array.Copy(nameBytes, header, nameSize);
|
||||
|
||||
// file mode (8)
|
||||
byte[] modeBytes = m_asciiEncoding.GetBytes("0000777");
|
||||
byte[] modeBytes = Encoding.ASCII.GetBytes("0000777");
|
||||
Array.Copy(modeBytes, 0, header, 100, 7);
|
||||
|
||||
// owner user id (8)
|
||||
byte[] ownerIdBytes = m_asciiEncoding.GetBytes("0000764");
|
||||
byte[] ownerIdBytes = Encoding.ASCII.GetBytes("0000764");
|
||||
Array.Copy(ownerIdBytes, 0, header, 108, 7);
|
||||
|
||||
// group user id (8)
|
||||
byte[] groupIdBytes = m_asciiEncoding.GetBytes("0000764");
|
||||
byte[] groupIdBytes = Encoding.ASCII.GetBytes("0000764");
|
||||
Array.Copy(groupIdBytes, 0, header, 116, 7);
|
||||
|
||||
// file size in bytes (12)
|
||||
@@ -181,17 +178,17 @@ namespace OpenSim.Framework.Serialization
|
||||
Array.Copy(fileSizeBytes, 0, header, 124, 11);
|
||||
|
||||
// last modification time (12)
|
||||
byte[] lastModTimeBytes = m_asciiEncoding.GetBytes("11017037332");
|
||||
byte[] lastModTimeBytes = Encoding.ASCII.GetBytes("11017037332");
|
||||
Array.Copy(lastModTimeBytes, 0, header, 136, 11);
|
||||
|
||||
// entry type indicator (1)
|
||||
header[156] = m_asciiEncoding.GetBytes(new char[] { fileType })[0];
|
||||
header[156] = Encoding.ASCII.GetBytes(new char[] { fileType })[0];
|
||||
|
||||
Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 329, 7);
|
||||
Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 337, 7);
|
||||
Array.Copy(Encoding.ASCII.GetBytes("0000000"), 0, header, 329, 7);
|
||||
Array.Copy(Encoding.ASCII.GetBytes("0000000"), 0, header, 337, 7);
|
||||
|
||||
// check sum for header block (8) [calculated last]
|
||||
Array.Copy(m_asciiEncoding.GetBytes(" "), 0, header, 148, 8);
|
||||
Array.Copy(Encoding.ASCII.GetBytes(" "), 0, header, 148, 8);
|
||||
|
||||
int checksum = 0;
|
||||
foreach (byte b in header)
|
||||
|
||||
@@ -320,7 +320,9 @@ namespace OpenSim.Framework.Servers
|
||||
|
||||
TimeSpan timeTaken = DateTime.Now - m_startuptime;
|
||||
|
||||
m_log.InfoFormat("[STARTUP]: Startup took {0}m {1}s", timeTaken.Minutes, timeTaken.Seconds);
|
||||
m_log.InfoFormat(
|
||||
"[STARTUP]: Non-script portion of startup took {0}m {1}s. PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED.",
|
||||
timeTaken.Minutes, timeTaken.Seconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -589,8 +591,8 @@ namespace OpenSim.Framework.Servers
|
||||
{
|
||||
string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
|
||||
FileStream fs = File.Create(path);
|
||||
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
|
||||
Byte[] buf = enc.GetBytes(pidstring);
|
||||
|
||||
Byte[] buf = Encoding.ASCII.GetBytes(pidstring);
|
||||
fs.Write(buf, 0, buf.Length);
|
||||
fs.Close();
|
||||
m_pidFile = path;
|
||||
|
||||
@@ -53,6 +53,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
|
||||
|
||||
public int DebugLevel { get; set; }
|
||||
|
||||
private volatile int NotSocketErrors = 0;
|
||||
public volatile bool HTTPDRunning = false;
|
||||
|
||||
@@ -79,11 +81,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
private PollServiceRequestManager m_PollServiceManager;
|
||||
|
||||
/// <summary>
|
||||
/// Control the printing of certain debug messages.
|
||||
/// </summary>
|
||||
public int DebugLevel { get; set; }
|
||||
|
||||
public uint SSLPort
|
||||
{
|
||||
get { return m_sslport; }
|
||||
@@ -408,7 +405,10 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
string uriString = request.RawUrl;
|
||||
|
||||
// string reqnum = "unknown";
|
||||
int tickstart = Environment.TickCount;
|
||||
int requestStartTick = Environment.TickCount;
|
||||
|
||||
// Will be adjusted later on.
|
||||
int requestEndTick = requestStartTick;
|
||||
|
||||
IRequestHandler requestHandler = null;
|
||||
|
||||
@@ -433,6 +433,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
if (HandleAgentRequest(agentHandler, request, response))
|
||||
{
|
||||
requestEndTick = Environment.TickCount;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -442,17 +443,15 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
string path = request.RawUrl;
|
||||
string handlerKey = GetHandlerKey(request.HttpMethod, path);
|
||||
byte[] buffer = null;
|
||||
|
||||
if (TryGetStreamHandler(handlerKey, out requestHandler))
|
||||
{
|
||||
if (DebugLevel >= 1)
|
||||
if (DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found stream handler for {0} {1} {2} {3}",
|
||||
request.HttpMethod, request.Url.PathAndQuery, requestHandler.Name, requestHandler.Description);
|
||||
|
||||
// Okay, so this is bad, but should be considered temporary until everything is IStreamHandler.
|
||||
byte[] buffer = null;
|
||||
|
||||
response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
|
||||
|
||||
if (requestHandler is IStreamedRequestHandler)
|
||||
@@ -507,8 +506,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
//m_log.Warn("[HTTP]: " + requestBody);
|
||||
|
||||
}
|
||||
DoHTTPGruntWork(HTTPRequestHandler.Handle(path, keysvals), response);
|
||||
return;
|
||||
|
||||
buffer = DoHTTPGruntWork(HTTPRequestHandler.Handle(path, keysvals), response);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -521,133 +520,99 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
buffer = memoryStream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (request.ContentType)
|
||||
{
|
||||
case null:
|
||||
case "text/html":
|
||||
|
||||
if (DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
buffer = HandleHTTPRequest(request, response);
|
||||
break;
|
||||
|
||||
case "application/llsd+xml":
|
||||
case "application/xml+llsd":
|
||||
case "application/llsd+json":
|
||||
|
||||
if (DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
buffer = HandleLLSDRequests(request, response);
|
||||
break;
|
||||
|
||||
case "text/xml":
|
||||
case "application/xml":
|
||||
case "application/json":
|
||||
default:
|
||||
//m_log.Info("[Debug BASE HTTP SERVER]: in default handler");
|
||||
// Point of note.. the DoWeHaveA methods check for an EXACT path
|
||||
// if (request.RawUrl.Contains("/CAPS/EQG"))
|
||||
// {
|
||||
// int i = 1;
|
||||
// }
|
||||
//m_log.Info("[Debug BASE HTTP SERVER]: Checking for LLSD Handler");
|
||||
if (DoWeHaveALLSDHandler(request.RawUrl))
|
||||
{
|
||||
if (DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
buffer = HandleLLSDRequests(request, response);
|
||||
}
|
||||
// m_log.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl);
|
||||
else if (DoWeHaveAHTTPHandler(request.RawUrl))
|
||||
{
|
||||
if (DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
buffer = HandleHTTPRequest(request, response);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
|
||||
request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
// generic login request.
|
||||
buffer = HandleXmlRpcRequests(request, response);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
request.InputStream.Close();
|
||||
|
||||
// HTTP IN support. The script engine takes it from here
|
||||
// Nothing to worry about for us.
|
||||
//
|
||||
if (buffer == null)
|
||||
return;
|
||||
request.InputStream.Close();
|
||||
|
||||
if (buffer != null)
|
||||
{
|
||||
if (!response.SendChunked)
|
||||
response.ContentLength64 = buffer.LongLength;
|
||||
|
||||
try
|
||||
{
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
//response.OutputStream.Close();
|
||||
}
|
||||
catch (HttpListenerException)
|
||||
{
|
||||
m_log.WarnFormat("[BASE HTTP SERVER]: HTTP request abnormally terminated.");
|
||||
}
|
||||
//response.OutputStream.Close();
|
||||
try
|
||||
{
|
||||
response.Send();
|
||||
//response.FreeContext();
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
// This has to be here to prevent a Linux/Mono crash
|
||||
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}. ", e.Message), e);
|
||||
}
|
||||
|
||||
return;
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
if (request.AcceptTypes != null && request.AcceptTypes.Length > 0)
|
||||
{
|
||||
foreach (string strAccept in request.AcceptTypes)
|
||||
{
|
||||
if (strAccept.Contains("application/llsd+xml") ||
|
||||
strAccept.Contains("application/llsd+json"))
|
||||
{
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found application/llsd+xml accept header handler for {0} {1}",
|
||||
request.HttpMethod, request.Url.PathAndQuery);
|
||||
// Do not include the time taken to actually send the response to the caller in the measurement
|
||||
// time. This is to avoid logging when it's the client that is slow to process rather than the
|
||||
// server
|
||||
requestEndTick = Environment.TickCount;
|
||||
|
||||
HandleLLSDRequests(request, response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
response.Send();
|
||||
|
||||
switch (request.ContentType)
|
||||
{
|
||||
case null:
|
||||
case "text/html":
|
||||
//response.OutputStream.Close();
|
||||
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
HandleHTTPRequest(request, response);
|
||||
return;
|
||||
|
||||
case "application/llsd+xml":
|
||||
case "application/xml+llsd":
|
||||
case "application/llsd+json":
|
||||
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
HandleLLSDRequests(request, response);
|
||||
return;
|
||||
|
||||
case "text/xml":
|
||||
case "application/xml":
|
||||
case "application/json":
|
||||
default:
|
||||
//m_log.Info("[Debug BASE HTTP SERVER]: in default handler");
|
||||
// Point of note.. the DoWeHaveA methods check for an EXACT path
|
||||
// if (request.RawUrl.Contains("/CAPS/EQG"))
|
||||
// {
|
||||
// int i = 1;
|
||||
// }
|
||||
//m_log.Info("[Debug BASE HTTP SERVER]: Checking for LLSD Handler");
|
||||
if (DoWeHaveALLSDHandler(request.RawUrl))
|
||||
{
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
HandleLLSDRequests(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// m_log.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl);
|
||||
if (DoWeHaveAHTTPHandler(request.RawUrl))
|
||||
{
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
HandleHTTPRequest(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
|
||||
request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
// generic login request.
|
||||
HandleXmlRpcRequests(request, response);
|
||||
|
||||
return;
|
||||
}
|
||||
//response.FreeContext();
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
@@ -672,8 +637,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
finally
|
||||
{
|
||||
// Every month or so this will wrap and give bad numbers, not really a problem
|
||||
// since its just for reporting, tickdiff limit can be adjusted
|
||||
int tickdiff = Environment.TickCount - tickstart;
|
||||
// since its just for reporting
|
||||
int tickdiff = requestEndTick - requestStartTick;
|
||||
if (tickdiff > 3000)
|
||||
{
|
||||
m_log.InfoFormat(
|
||||
@@ -805,7 +770,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="response"></param>
|
||||
private void HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response)
|
||||
private byte[] HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response)
|
||||
{
|
||||
Stream requestStream = request.InputStream;
|
||||
|
||||
@@ -824,8 +789,23 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
xmlRprcRequest = (XmlRpcRequest) (new XmlRpcRequestDeserializer()).Deserialize(requestBody);
|
||||
}
|
||||
catch (XmlException)
|
||||
catch (XmlException e)
|
||||
{
|
||||
if (DebugLevel >= 1)
|
||||
{
|
||||
if (DebugLevel >= 2)
|
||||
m_log.Warn(
|
||||
string.Format(
|
||||
"[BASE HTTP SERVER]: Got XMLRPC request with invalid XML from {0}. XML was '{1}'. Sending blank response. Exception ",
|
||||
request.RemoteIPEndPoint, requestBody),
|
||||
e);
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[BASE HTTP SERVER]: Got XMLRPC request with invalid XML from {0}, length {1}. Sending blank response.",
|
||||
request.RemoteIPEndPoint, requestBody.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xmlRprcRequest != null)
|
||||
@@ -895,6 +875,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
String.Format("Requested method [{0}] not found", methodName));
|
||||
}
|
||||
|
||||
response.ContentType = "text/xml";
|
||||
responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse);
|
||||
}
|
||||
else
|
||||
@@ -904,82 +885,25 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
response.StatusCode = 404;
|
||||
response.StatusDescription = "Not Found";
|
||||
response.ProtocolVersion = "HTTP/1.0";
|
||||
byte[] buf = Encoding.UTF8.GetBytes("Not found");
|
||||
responseString = "Not found";
|
||||
response.KeepAlive = false;
|
||||
|
||||
m_log.ErrorFormat(
|
||||
"[BASE HTTP SERVER]: Handler not found for http request {0} {1}",
|
||||
request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
response.SendChunked = false;
|
||||
response.ContentLength64 = buf.Length;
|
||||
response.ContentEncoding = Encoding.UTF8;
|
||||
|
||||
try
|
||||
{
|
||||
response.OutputStream.Write(buf, 0, buf.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
response.Send();
|
||||
//response.FreeContext();
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
// This has to be here to prevent a Linux/Mono crash
|
||||
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0} ", e.Message), e);
|
||||
}
|
||||
}
|
||||
return;
|
||||
//responseString = "Error";
|
||||
}
|
||||
}
|
||||
|
||||
response.ContentType = "text/xml";
|
||||
|
||||
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
|
||||
|
||||
response.SendChunked = false;
|
||||
response.ContentLength64 = buffer.Length;
|
||||
response.ContentEncoding = Encoding.UTF8;
|
||||
try
|
||||
{
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
response.Send();
|
||||
//response.FreeContext();
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
// This has to be here to prevent a Linux/Mono crash
|
||||
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0} ", e.Message), e);
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private void HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response)
|
||||
private byte[] HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response)
|
||||
{
|
||||
//m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request");
|
||||
Stream requestStream = request.InputStream;
|
||||
@@ -1065,34 +989,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
response.ContentEncoding = Encoding.UTF8;
|
||||
response.KeepAlive = true;
|
||||
|
||||
try
|
||||
{
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
//response.OutputStream.Close();
|
||||
try
|
||||
{
|
||||
response.Send();
|
||||
response.OutputStream.Flush();
|
||||
//response.FreeContext();
|
||||
//response.OutputStream.Close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
m_log.Warn(String.Format("[BASE HTTP SERVER]: LLSD IOException {0} ", e.Message), e);
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
// This has to be here to prevent a Linux/Mono crash
|
||||
m_log.Warn(String.Format("[BASE HTTP SERVER]: LLSD issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private byte[] BuildLLSDResponse(OSHttpRequest request, OSHttpResponse response, OSD llsdResponse)
|
||||
@@ -1357,7 +1254,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
}
|
||||
|
||||
public void HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
|
||||
public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[BASE HTTP SERVER]: HandleHTTPRequest for request to {0}, method {1}",
|
||||
@@ -1367,15 +1264,14 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
case "OPTIONS":
|
||||
response.StatusCode = (int)OSHttpStatusCode.SuccessOk;
|
||||
return;
|
||||
return null;
|
||||
|
||||
default:
|
||||
HandleContentVerbs(request, response);
|
||||
return;
|
||||
return HandleContentVerbs(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleContentVerbs(OSHttpRequest request, OSHttpResponse response)
|
||||
private byte[] HandleContentVerbs(OSHttpRequest request, OSHttpResponse response)
|
||||
{
|
||||
// m_log.DebugFormat("[BASE HTTP SERVER]: HandleContentVerbs for request to {0}", request.RawUrl);
|
||||
|
||||
@@ -1391,6 +1287,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
// to display the form, or process it.
|
||||
// a better way would be nifty.
|
||||
|
||||
byte[] buffer;
|
||||
|
||||
Stream requestStream = request.InputStream;
|
||||
|
||||
Encoding encoding = Encoding.UTF8;
|
||||
@@ -1451,14 +1349,14 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
if (foundHandler)
|
||||
{
|
||||
Hashtable responsedata1 = requestprocessor(keysvals);
|
||||
DoHTTPGruntWork(responsedata1,response);
|
||||
buffer = DoHTTPGruntWork(responsedata1,response);
|
||||
|
||||
//SendHTML500(response);
|
||||
}
|
||||
else
|
||||
{
|
||||
// m_log.Warn("[BASE HTTP SERVER]: Handler Not Found");
|
||||
SendHTML404(response, host);
|
||||
buffer = SendHTML404(response, host);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1468,16 +1366,18 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
if (foundHandler)
|
||||
{
|
||||
Hashtable responsedata2 = requestprocessor(keysvals);
|
||||
DoHTTPGruntWork(responsedata2, response);
|
||||
buffer = DoHTTPGruntWork(responsedata2, response);
|
||||
|
||||
//SendHTML500(response);
|
||||
}
|
||||
else
|
||||
{
|
||||
// m_log.Warn("[BASE HTTP SERVER]: Handler Not Found2");
|
||||
SendHTML404(response, host);
|
||||
buffer = SendHTML404(response, host);
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private bool TryGetHTTPHandlerPathBased(string path, out GenericHTTPMethod httpHandler)
|
||||
@@ -1545,14 +1445,13 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
}
|
||||
}
|
||||
|
||||
internal void DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response)
|
||||
internal byte[] DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response)
|
||||
{
|
||||
//m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response");
|
||||
int responsecode = (int)responsedata["int_response_code"];
|
||||
string responseString = (string)responsedata["str_response_string"];
|
||||
string contentType = (string)responsedata["content_type"];
|
||||
|
||||
|
||||
if (responsedata.ContainsKey("error_status_text"))
|
||||
{
|
||||
response.StatusDescription = (string)responsedata["error_status_text"];
|
||||
@@ -1616,38 +1515,10 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
response.ContentLength64 = buffer.Length;
|
||||
response.ContentEncoding = Encoding.UTF8;
|
||||
|
||||
try
|
||||
{
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("[HTTPD]: Error - " + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
//response.OutputStream.Close();
|
||||
try
|
||||
{
|
||||
response.OutputStream.Flush();
|
||||
response.Send();
|
||||
|
||||
//if (!response.KeepAlive && response.ReuseContext)
|
||||
// response.FreeContext();
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
// This has to be here to prevent a Linux/Mono crash
|
||||
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0} ", e.Message), e);
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public void SendHTML404(OSHttpResponse response, string host)
|
||||
public byte[] SendHTML404(OSHttpResponse response, string host)
|
||||
{
|
||||
// I know this statuscode is dumb, but the client doesn't respond to 404s and 500s
|
||||
response.StatusCode = 404;
|
||||
@@ -1660,31 +1531,10 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
response.ContentLength64 = buffer.Length;
|
||||
response.ContentEncoding = Encoding.UTF8;
|
||||
|
||||
try
|
||||
{
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
//response.OutputStream.Close();
|
||||
try
|
||||
{
|
||||
response.Send();
|
||||
//response.FreeContext();
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
// This has to be here to prevent a Linux/Mono crash
|
||||
m_log.Warn(String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public void SendHTML500(OSHttpResponse response)
|
||||
public byte[] SendHTML500(OSHttpResponse response)
|
||||
{
|
||||
// I know this statuscode is dumb, but the client doesn't respond to 404s and 500s
|
||||
response.StatusCode = (int)OSHttpStatusCode.SuccessOk;
|
||||
@@ -1696,28 +1546,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
response.SendChunked = false;
|
||||
response.ContentLength64 = buffer.Length;
|
||||
response.ContentEncoding = Encoding.UTF8;
|
||||
try
|
||||
{
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
//response.OutputStream.Close();
|
||||
try
|
||||
{
|
||||
response.Send();
|
||||
//response.FreeContext();
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
// This has to be here to prevent a Linux/Mono crash
|
||||
m_log.Warn(String.Format("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", e.Message), e);
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
@@ -1727,6 +1557,9 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
private void StartHTTP()
|
||||
{
|
||||
m_log.InfoFormat(
|
||||
"[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port);
|
||||
|
||||
try
|
||||
{
|
||||
//m_httpListener = new HttpListener();
|
||||
|
||||
@@ -128,11 +128,5 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
/// <param name="value">string containing the header field
|
||||
/// value</param>
|
||||
void AddHeader(string key, string value);
|
||||
|
||||
/// <summary>
|
||||
/// Send the response back to the remote client
|
||||
/// </summary>
|
||||
void Send();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -107,7 +107,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
public bool IsSecured
|
||||
{
|
||||
get { return _context.Secured; }
|
||||
get { return _context.IsSecured; }
|
||||
}
|
||||
|
||||
public bool KeepAlive
|
||||
|
||||
@@ -321,13 +321,12 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
_httpResponse.Body.Flush();
|
||||
_httpResponse.Send();
|
||||
|
||||
}
|
||||
|
||||
public void FreeContext()
|
||||
{
|
||||
if (_httpClientContext != null)
|
||||
_httpClientContext.Close();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
public delegate void RequestMethod(UUID requestID, Hashtable request);
|
||||
@@ -44,7 +45,11 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
public NoEventsMethod NoEvents;
|
||||
public RequestMethod Request;
|
||||
public UUID Id;
|
||||
public PollServiceEventArgs(RequestMethod pRequest, HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,UUID pId)
|
||||
|
||||
public PollServiceEventArgs(
|
||||
RequestMethod pRequest,
|
||||
HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,
|
||||
UUID pId)
|
||||
{
|
||||
Request = pRequest;
|
||||
HasEvents = pHasEvents;
|
||||
@@ -53,4 +58,4 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
Id = pId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,6 @@ using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
|
||||
public class PollServiceHttpRequest
|
||||
{
|
||||
public readonly PollServiceEventArgs PollServiceArgs;
|
||||
@@ -39,7 +38,9 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
public readonly IHttpRequest Request;
|
||||
public readonly int RequestTime;
|
||||
public readonly UUID RequestID;
|
||||
public PollServiceHttpRequest(PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest)
|
||||
|
||||
public PollServiceHttpRequest(
|
||||
PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest)
|
||||
{
|
||||
PollServiceArgs = pPollServiceArgs;
|
||||
HttpContext = pHttpContext;
|
||||
@@ -48,4 +49,4 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
RequestID = UUID.Random();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
ThreadPriority.Normal,
|
||||
false,
|
||||
true,
|
||||
null,
|
||||
int.MaxValue);
|
||||
}
|
||||
|
||||
@@ -75,6 +76,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
ThreadPriority.Normal,
|
||||
false,
|
||||
true,
|
||||
null,
|
||||
1000 * 60 * 10);
|
||||
}
|
||||
|
||||
@@ -138,9 +140,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
foreach (object o in m_requests)
|
||||
{
|
||||
PollServiceHttpRequest req = (PollServiceHttpRequest) o;
|
||||
m_server.DoHTTPGruntWork(
|
||||
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id),
|
||||
new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext));
|
||||
PollServiceWorkerThread.DoHTTPGruntWork(
|
||||
m_server, req, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
|
||||
}
|
||||
|
||||
m_requests.Clear();
|
||||
@@ -149,6 +150,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
t.Abort();
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,15 +90,16 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
}
|
||||
|
||||
Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id, str.ReadToEnd());
|
||||
m_server.DoHTTPGruntWork(responsedata,
|
||||
new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request),req.HttpContext));
|
||||
DoHTTPGruntWork(m_server, req, responsedata);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((Environment.TickCount - req.RequestTime) > m_timeout)
|
||||
{
|
||||
m_server.DoHTTPGruntWork(req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id),
|
||||
new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request),req.HttpContext));
|
||||
DoHTTPGruntWork(
|
||||
m_server,
|
||||
req,
|
||||
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -119,5 +120,45 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
m_request.Enqueue(pPollServiceHttpRequest);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// FIXME: This should be part of BaseHttpServer
|
||||
/// </summary>
|
||||
internal static void DoHTTPGruntWork(BaseHttpServer server, PollServiceHttpRequest req, Hashtable responsedata)
|
||||
{
|
||||
OSHttpResponse response
|
||||
= new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext);
|
||||
|
||||
byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
|
||||
|
||||
response.SendChunked = false;
|
||||
response.ContentLength64 = buffer.Length;
|
||||
response.ContentEncoding = Encoding.UTF8;
|
||||
|
||||
try
|
||||
{
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
|
||||
}
|
||||
finally
|
||||
{
|
||||
//response.OutputStream.Close();
|
||||
try
|
||||
{
|
||||
response.OutputStream.Flush();
|
||||
response.Send();
|
||||
|
||||
//if (!response.KeepAlive && response.ReuseContext)
|
||||
// response.FreeContext();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,57 +25,209 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Net;
|
||||
using log4net;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Console;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
|
||||
namespace OpenSim.Framework.Servers
|
||||
{
|
||||
public class MainServer
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private static BaseHttpServer instance = null;
|
||||
private static Dictionary<uint, BaseHttpServer> m_Servers =
|
||||
new Dictionary<uint, BaseHttpServer>();
|
||||
private static Dictionary<uint, BaseHttpServer> m_Servers = new Dictionary<uint, BaseHttpServer>();
|
||||
|
||||
/// <summary>
|
||||
/// Control the printing of certain debug messages.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If DebugLevel >= 1, then short warnings are logged when receiving bad input data.
|
||||
/// If DebugLevel >= 2, then long warnings are logged when receiving bad input data.
|
||||
/// If DebugLevel >= 3, then short notices about all incoming non-poll HTTP requests are logged.
|
||||
/// </remarks>
|
||||
public static int DebugLevel
|
||||
{
|
||||
get { return s_debugLevel; }
|
||||
set
|
||||
{
|
||||
s_debugLevel = value;
|
||||
|
||||
lock (m_Servers)
|
||||
foreach (BaseHttpServer server in m_Servers.Values)
|
||||
server.DebugLevel = s_debugLevel;
|
||||
}
|
||||
}
|
||||
|
||||
private static int s_debugLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Set the main HTTP server instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will be used to register all handlers that listen to the default port.
|
||||
/// </remarks>
|
||||
/// <exception cref='Exception'>
|
||||
/// Thrown if the HTTP server has not already been registered via AddHttpServer()
|
||||
/// </exception>
|
||||
public static BaseHttpServer Instance
|
||||
{
|
||||
get { return instance; }
|
||||
set { instance = value; }
|
||||
|
||||
set
|
||||
{
|
||||
lock (m_Servers)
|
||||
if (!m_Servers.ContainsValue(value))
|
||||
throw new Exception("HTTP server must already have been registered to be set as the main instance");
|
||||
|
||||
instance = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static IHttpServer GetHttpServer(uint port)
|
||||
/// <summary>
|
||||
/// Get all the registered servers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns a copy of the dictionary so this can be iterated through without locking.
|
||||
/// </remarks>
|
||||
/// <value></value>
|
||||
public static Dictionary<uint, BaseHttpServer> Servers
|
||||
{
|
||||
return GetHttpServer(port,null);
|
||||
get { return new Dictionary<uint, BaseHttpServer>(m_Servers); }
|
||||
}
|
||||
|
||||
|
||||
public static void RegisterHttpConsoleCommands(ICommandConsole console)
|
||||
{
|
||||
console.Commands.AddCommand(
|
||||
"Debug", false, "debug http", "debug http [<level>]",
|
||||
"Turn on inbound non-poll http request debugging.",
|
||||
"If level <= 0, then no extra logging is done.\n"
|
||||
+ "If level >= 1, then short warnings are logged when receiving bad input data.\n"
|
||||
+ "If level >= 2, then long warnings are logged when receiving bad input data.\n"
|
||||
+ "If level >= 3, then short notices about all incoming non-poll HTTP requests are logged.\n"
|
||||
+ "If no level is specified then the current level is returned.",
|
||||
HandleDebugHttpCommand);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turn on some debugging values for OpenSim.
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
private static void HandleDebugHttpCommand(string module, string[] args)
|
||||
{
|
||||
if (args.Length == 3)
|
||||
{
|
||||
int newDebug;
|
||||
if (int.TryParse(args[2], out newDebug))
|
||||
{
|
||||
MainServer.DebugLevel = newDebug;
|
||||
MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug);
|
||||
}
|
||||
}
|
||||
else if (args.Length == 2)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("Current debug http level is {0}", MainServer.DebugLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
MainConsole.Instance.Output("Usage: debug http 0..3");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register an already started HTTP server to the collection of known servers.
|
||||
/// </summary>
|
||||
/// <param name='server'></param>
|
||||
public static void AddHttpServer(BaseHttpServer server)
|
||||
{
|
||||
m_Servers.Add(server.Port, server);
|
||||
lock (m_Servers)
|
||||
{
|
||||
if (m_Servers.ContainsKey(server.Port))
|
||||
throw new Exception(string.Format("HTTP server for port {0} already exists.", server.Port));
|
||||
|
||||
m_Servers.Add(server.Port, server);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the http server listening on the given port.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It is the responsibility of the caller to do clean up.
|
||||
/// </remarks>
|
||||
/// <param name='port'></param>
|
||||
/// <returns></returns>
|
||||
public static bool RemoveHttpServer(uint port)
|
||||
{
|
||||
lock (m_Servers)
|
||||
return m_Servers.Remove(port);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does this collection of servers contain one with the given port?
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Unlike GetHttpServer, this will not instantiate a server if one does not exist on that port.
|
||||
/// </remarks>
|
||||
/// <param name='port'></param>
|
||||
/// <returns>true if a server with the given port is registered, false otherwise.</returns>
|
||||
public static bool ContainsHttpServer(uint port)
|
||||
{
|
||||
lock (m_Servers)
|
||||
return m_Servers.ContainsKey(port);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the default http server or an http server for a specific port.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the requested HTTP server doesn't already exist then a new one is instantiated and started.
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
/// <param name='port'>If 0 then the default HTTP server is returned.</param>
|
||||
public static IHttpServer GetHttpServer(uint port)
|
||||
{
|
||||
return GetHttpServer(port, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the default http server, an http server for a specific port
|
||||
/// and/or an http server bound to a specific address
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the requested HTTP server doesn't already exist then a new one is instantiated and started.
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
/// <param name='port'>If 0 then the default HTTP server is returned.</param>
|
||||
/// <param name='ipaddr'>A specific IP address to bind to. If null then the default IP address is used.</param>
|
||||
public static IHttpServer GetHttpServer(uint port, IPAddress ipaddr)
|
||||
{
|
||||
if (port == 0)
|
||||
return Instance;
|
||||
|
||||
if (instance != null && port == Instance.Port)
|
||||
return Instance;
|
||||
|
||||
if (m_Servers.ContainsKey(port))
|
||||
lock (m_Servers)
|
||||
{
|
||||
if (m_Servers.ContainsKey(port))
|
||||
return m_Servers[port];
|
||||
|
||||
m_Servers[port] = new BaseHttpServer(port);
|
||||
|
||||
if (ipaddr != null)
|
||||
m_Servers[port].ListenIPAddress = ipaddr;
|
||||
|
||||
m_Servers[port].Start();
|
||||
|
||||
return m_Servers[port];
|
||||
|
||||
m_Servers[port] = new BaseHttpServer(port);
|
||||
|
||||
if (ipaddr != null)
|
||||
m_Servers[port].ListenIPAddress = ipaddr;
|
||||
|
||||
m_log.InfoFormat("[MAIN HTTP SERVER]: Starting main http server on port {0}", port);
|
||||
m_Servers[port].Start();
|
||||
|
||||
return m_Servers[port];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,14 +34,12 @@ namespace OpenSim.Framework.Statistics
|
||||
{
|
||||
private static AssetStatsCollector assetStats;
|
||||
private static UserStatsCollector userStats;
|
||||
private static SimExtraStatsCollector simExtraStats;
|
||||
private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
|
||||
|
||||
public static AssetStatsCollector AssetStats { get { return assetStats; } }
|
||||
public static UserStatsCollector UserStats { get { return userStats; } }
|
||||
public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
|
||||
|
||||
private StatsManager() {}
|
||||
|
||||
/// <summary>
|
||||
/// Start collecting statistics related to assets.
|
||||
/// Should only be called once.
|
||||
@@ -63,16 +61,5 @@ namespace OpenSim.Framework.Statistics
|
||||
|
||||
return userStats;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start collecting extra sim statistics apart from those collected for the client.
|
||||
/// Should only be called once.
|
||||
/// </summary>
|
||||
public static SimExtraStatsCollector StartCollectingSimExtraStats()
|
||||
{
|
||||
simExtraStats = new SimExtraStatsCollector();
|
||||
|
||||
return simExtraStats;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,6 +73,9 @@ namespace OpenSim.Framework
|
||||
|
||||
private bool _ownerChanged = false;
|
||||
|
||||
// This used ONLY during copy. It can't be relied on at other times!
|
||||
private bool _scriptRunning = true;
|
||||
|
||||
public UUID AssetID {
|
||||
get {
|
||||
return _assetID;
|
||||
@@ -350,6 +353,15 @@ namespace OpenSim.Framework
|
||||
}
|
||||
}
|
||||
|
||||
public bool ScriptRunning {
|
||||
get {
|
||||
return _scriptRunning;
|
||||
}
|
||||
set {
|
||||
_scriptRunning = value;
|
||||
}
|
||||
}
|
||||
|
||||
// See ICloneable
|
||||
|
||||
#region ICloneable Members
|
||||
|
||||
@@ -148,6 +148,7 @@ namespace OpenSim.Framework
|
||||
}
|
||||
|
||||
public static Encoding UTF8 = Encoding.UTF8;
|
||||
public static Encoding UTF8NoBomEncoding = new UTF8Encoding(false);
|
||||
|
||||
/// <value>
|
||||
/// Well known UUID for the blank texture used in the Linden SL viewer version 1.20 (and hopefully onwards)
|
||||
@@ -1236,8 +1237,7 @@ namespace OpenSim.Framework
|
||||
|
||||
public static string Base64ToString(string str)
|
||||
{
|
||||
UTF8Encoding encoder = new UTF8Encoding();
|
||||
Decoder utf8Decode = encoder.GetDecoder();
|
||||
Decoder utf8Decode = Encoding.UTF8.GetDecoder();
|
||||
|
||||
byte[] todecode_byte = Convert.FromBase64String(str);
|
||||
int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
|
||||
|
||||
@@ -41,8 +41,8 @@ namespace OpenSim.Framework
|
||||
/// <summary>Timer interval in milliseconds for the watchdog timer</summary>
|
||||
const double WATCHDOG_INTERVAL_MS = 2500.0d;
|
||||
|
||||
/// <summary>Maximum timeout in milliseconds before a thread is considered dead</summary>
|
||||
const int WATCHDOG_TIMEOUT_MS = 5000;
|
||||
/// <summary>Default timeout in milliseconds before a thread is considered dead</summary>
|
||||
public const int DEFAULT_WATCHDOG_TIMEOUT_MS = 5000;
|
||||
|
||||
[System.Diagnostics.DebuggerDisplay("{Thread.Name}")]
|
||||
public class ThreadWatchdogInfo
|
||||
@@ -58,7 +58,7 @@ namespace OpenSim.Framework
|
||||
public int FirstTick { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// First time this heartbeat update was invoked
|
||||
/// Last time this heartbeat update was invoked
|
||||
/// </summary>
|
||||
public int LastTick { get; set; }
|
||||
|
||||
@@ -77,6 +77,11 @@ namespace OpenSim.Framework
|
||||
/// </summary>
|
||||
public bool AlarmIfTimeout { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Method execute if alarm goes off. If null then no alarm method is fired.
|
||||
/// </summary>
|
||||
public Func<string> AlarmMethod { get; set; }
|
||||
|
||||
public ThreadWatchdogInfo(Thread thread, int timeout)
|
||||
{
|
||||
Thread = thread;
|
||||
@@ -87,27 +92,33 @@ namespace OpenSim.Framework
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event is called whenever a tracked thread is stopped or
|
||||
/// has not called UpdateThread() in time
|
||||
/// </summary>
|
||||
/// <param name="thread">The thread that has been identified as dead</param>
|
||||
/// <param name="lastTick">The last time this thread called UpdateThread()</param>
|
||||
public delegate void WatchdogTimeout(Thread thread, int lastTick);
|
||||
|
||||
/// <summary>This event is called whenever a tracked thread is
|
||||
/// stopped or has not called UpdateThread() in time</summary>
|
||||
public static event WatchdogTimeout OnWatchdogTimeout;
|
||||
/// This event is called whenever a tracked thread is
|
||||
/// stopped or has not called UpdateThread() in time<
|
||||
/// /summary>
|
||||
public static event Action<ThreadWatchdogInfo> OnWatchdogTimeout;
|
||||
|
||||
private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static Dictionary<int, ThreadWatchdogInfo> m_threads;
|
||||
private static System.Timers.Timer m_watchdogTimer;
|
||||
|
||||
/// <summary>
|
||||
/// Last time the watchdog thread ran.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Should run every WATCHDOG_INTERVAL_MS
|
||||
/// </remarks>
|
||||
public static int LastWatchdogThreadTick { get; private set; }
|
||||
|
||||
static Watchdog()
|
||||
{
|
||||
m_threads = new Dictionary<int, ThreadWatchdogInfo>();
|
||||
m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS);
|
||||
m_watchdogTimer.AutoReset = false;
|
||||
m_watchdogTimer.Elapsed += WatchdogTimerElapsed;
|
||||
|
||||
// Set now so we don't get alerted on the first run
|
||||
LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
|
||||
|
||||
m_watchdogTimer.Start();
|
||||
}
|
||||
|
||||
@@ -123,7 +134,7 @@ namespace OpenSim.Framework
|
||||
public static Thread StartThread(
|
||||
ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout)
|
||||
{
|
||||
return StartThread(start, name, priority, isBackground, alarmIfTimeout, WATCHDOG_TIMEOUT_MS);
|
||||
return StartThread(start, name, priority, isBackground, alarmIfTimeout, null, DEFAULT_WATCHDOG_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -135,17 +146,24 @@ namespace OpenSim.Framework
|
||||
/// <param name="isBackground">True to run this thread as a background
|
||||
/// thread, otherwise false</param>
|
||||
/// <param name="alarmIfTimeout">Trigger an alarm function is we have timed out</param>
|
||||
/// <param name="alarmMethod">
|
||||
/// Alarm method to call if alarmIfTimeout is true and there is a timeout.
|
||||
/// Normally, this will just return some useful debugging information.
|
||||
/// </param>
|
||||
/// <param name="timeout">Number of milliseconds to wait until we issue a warning about timeout.</param>
|
||||
/// <returns>The newly created Thread object</returns>
|
||||
public static Thread StartThread(
|
||||
ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout, int timeout)
|
||||
ThreadStart start, string name, ThreadPriority priority, bool isBackground,
|
||||
bool alarmIfTimeout, Func<string> alarmMethod, int timeout)
|
||||
{
|
||||
Thread thread = new Thread(start);
|
||||
thread.Name = name;
|
||||
thread.Priority = priority;
|
||||
thread.IsBackground = isBackground;
|
||||
|
||||
ThreadWatchdogInfo twi = new ThreadWatchdogInfo(thread, timeout) { AlarmIfTimeout = alarmIfTimeout };
|
||||
ThreadWatchdogInfo twi
|
||||
= new ThreadWatchdogInfo(thread, timeout)
|
||||
{ AlarmIfTimeout = alarmIfTimeout, AlarmMethod = alarmMethod };
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[WATCHDOG]: Started tracking thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
|
||||
@@ -258,7 +276,17 @@ namespace OpenSim.Framework
|
||||
/// <param name="e"></param>
|
||||
private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
WatchdogTimeout callback = OnWatchdogTimeout;
|
||||
int now = Environment.TickCount & Int32.MaxValue;
|
||||
int msElapsed = now - LastWatchdogThreadTick;
|
||||
|
||||
if (msElapsed > WATCHDOG_INTERVAL_MS * 2)
|
||||
m_log.WarnFormat(
|
||||
"[WATCHDOG]: {0} ms since Watchdog last ran. Interval should be approximately {1} ms",
|
||||
msElapsed, WATCHDOG_INTERVAL_MS);
|
||||
|
||||
LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
|
||||
|
||||
Action<ThreadWatchdogInfo> callback = OnWatchdogTimeout;
|
||||
|
||||
if (callback != null)
|
||||
{
|
||||
@@ -266,8 +294,6 @@ namespace OpenSim.Framework
|
||||
|
||||
lock (m_threads)
|
||||
{
|
||||
int now = Environment.TickCount & Int32.MaxValue;
|
||||
|
||||
foreach (ThreadWatchdogInfo threadInfo in m_threads.Values)
|
||||
{
|
||||
if (threadInfo.Thread.ThreadState == ThreadState.Stopped)
|
||||
@@ -296,7 +322,7 @@ namespace OpenSim.Framework
|
||||
|
||||
if (callbackInfos != null)
|
||||
foreach (ThreadWatchdogInfo callbackInfo in callbackInfos)
|
||||
callback(callbackInfo.Thread, callbackInfo.LastTick);
|
||||
callback(callbackInfo);
|
||||
}
|
||||
|
||||
m_watchdogTimer.Start();
|
||||
|
||||
@@ -92,9 +92,14 @@ namespace OpenSim
|
||||
m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config");
|
||||
}
|
||||
|
||||
m_log.DebugFormat(
|
||||
m_log.InfoFormat(
|
||||
"[OPENSIM MAIN]: System Locale is {0}", System.Threading.Thread.CurrentThread.CurrentCulture);
|
||||
|
||||
string monoThreadsPerCpu = System.Environment.GetEnvironmentVariable("MONO_THREADS_PER_CPU");
|
||||
|
||||
m_log.InfoFormat(
|
||||
"[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset");
|
||||
|
||||
// Increase the number of IOCP threads available. Mono defaults to a tragically low number
|
||||
int workerThreads, iocpThreads;
|
||||
System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
|
||||
@@ -109,7 +114,6 @@ namespace OpenSim
|
||||
|
||||
// Check if the system is compatible with OpenSimulator.
|
||||
// Ensures that the minimum system requirements are met
|
||||
m_log.Info("Performing compatibility checks... \n");
|
||||
string supported = String.Empty;
|
||||
if (Util.IsEnvironmentSupported(ref supported))
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
@@ -69,6 +70,7 @@ namespace OpenSim
|
||||
private Regex m_consolePromptRegex = new Regex(@"([^\\])\\(\w)", RegexOptions.Compiled);
|
||||
|
||||
private string m_timedScript = "disabled";
|
||||
private int m_timeInterval = 1200;
|
||||
private Timer m_scriptTimer;
|
||||
|
||||
public OpenSim(IConfigSource configSource) : base(configSource)
|
||||
@@ -98,6 +100,10 @@ namespace OpenSim
|
||||
m_consolePort = (uint)networkConfig.GetInt("console_port", 0);
|
||||
|
||||
m_timedScript = startupConfig.GetString("timer_Script", "disabled");
|
||||
if (m_timedScript != "disabled")
|
||||
{
|
||||
m_timeInterval = startupConfig.GetInt("timer_Interval", 1200);
|
||||
}
|
||||
|
||||
if (m_logFileAppender != null)
|
||||
{
|
||||
@@ -138,7 +144,7 @@ namespace OpenSim
|
||||
m_log.Info("====================================================================");
|
||||
m_log.Info("========================= STARTING OPENSIM =========================");
|
||||
m_log.Info("====================================================================");
|
||||
|
||||
|
||||
//m_log.InfoFormat("[OPENSIM MAIN]: GC Is Server GC: {0}", GCSettings.IsServerGC.ToString());
|
||||
// http://msdn.microsoft.com/en-us/library/bb384202.aspx
|
||||
//GCSettings.LatencyMode = GCLatencyMode.Batch;
|
||||
@@ -215,7 +221,7 @@ namespace OpenSim
|
||||
{
|
||||
m_scriptTimer = new Timer();
|
||||
m_scriptTimer.Enabled = true;
|
||||
m_scriptTimer.Interval = 1200*1000;
|
||||
m_scriptTimer.Interval = m_timeInterval*1000;
|
||||
m_scriptTimer.Elapsed += RunAutoTimerScript;
|
||||
}
|
||||
}
|
||||
@@ -225,12 +231,14 @@ namespace OpenSim
|
||||
/// </summary>
|
||||
private void RegisterConsoleCommands()
|
||||
{
|
||||
MainServer.RegisterHttpConsoleCommands(m_console);
|
||||
|
||||
m_console.Commands.AddCommand("Objects", false, "force update",
|
||||
"force update",
|
||||
"Force the update of all objects on clients",
|
||||
HandleForceUpdate);
|
||||
|
||||
m_console.Commands.AddCommand("Comms", false, "debug packet",
|
||||
m_console.Commands.AddCommand("Debug", false, "debug packet",
|
||||
"debug packet <level> [<avatar-first-name> <avatar-last-name>]",
|
||||
"Turn on packet debugging",
|
||||
"If level > 255 then all incoming and outgoing packets are logged.\n"
|
||||
@@ -242,17 +250,9 @@ namespace OpenSim
|
||||
+ "If an avatar name is given then only packets from that avatar are logged",
|
||||
Debug);
|
||||
|
||||
m_console.Commands.AddCommand("Comms", false, "debug http",
|
||||
"debug http <level>",
|
||||
"Turn on inbound http request debugging for everything except the event queue (see debug eq).",
|
||||
"If level >= 2 then the handler used to service the request is logged.\n"
|
||||
+ "If level >= 1 then incoming HTTP requests are logged.\n"
|
||||
+ "If level <= 0 then no extra http logging is done.\n",
|
||||
Debug);
|
||||
m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
|
||||
|
||||
m_console.Commands.AddCommand("Comms", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
|
||||
|
||||
m_console.Commands.AddCommand("Regions", false, "debug scene",
|
||||
m_console.Commands.AddCommand("Debug", false, "debug scene",
|
||||
"debug scene <scripting> <collisions> <physics>",
|
||||
"Turn on scene debugging", Debug);
|
||||
|
||||
@@ -409,10 +409,6 @@ namespace OpenSim
|
||||
m_console.Commands.AddCommand("General", false, "modules unload",
|
||||
"modules unload <name>",
|
||||
"Unload a module", HandleModules);
|
||||
|
||||
m_console.Commands.AddCommand("Objects", false, "kill uuid",
|
||||
"kill uuid <UUID>",
|
||||
"Kill an object by UUID", KillUUID);
|
||||
}
|
||||
|
||||
public override void ShutdownSpecific()
|
||||
@@ -437,12 +433,16 @@ namespace OpenSim
|
||||
}
|
||||
}
|
||||
|
||||
private void WatchdogTimeoutHandler(System.Threading.Thread thread, int lastTick)
|
||||
private void WatchdogTimeoutHandler(Watchdog.ThreadWatchdogInfo twi)
|
||||
{
|
||||
int now = Environment.TickCount & Int32.MaxValue;
|
||||
|
||||
m_log.ErrorFormat("[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago",
|
||||
thread.Name, thread.ThreadState, now - lastTick);
|
||||
m_log.ErrorFormat(
|
||||
"[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago. {3}",
|
||||
twi.Thread.Name,
|
||||
twi.Thread.ThreadState,
|
||||
now - twi.LastTick,
|
||||
twi.AlarmMethod != null ? string.Format("Data: {0}", twi.AlarmMethod()) : "");
|
||||
}
|
||||
|
||||
#region Console Commands
|
||||
@@ -481,10 +481,10 @@ namespace OpenSim
|
||||
else
|
||||
presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n");
|
||||
|
||||
// ...and close on our side
|
||||
presence.Scene.IncomingCloseAgent(presence.UUID);
|
||||
}
|
||||
}
|
||||
|
||||
MainConsole.Instance.Output("");
|
||||
}
|
||||
|
||||
@@ -904,21 +904,6 @@ namespace OpenSim
|
||||
|
||||
break;
|
||||
|
||||
case "http":
|
||||
if (args.Length == 3)
|
||||
{
|
||||
int newDebug;
|
||||
if (int.TryParse(args[2], out newDebug))
|
||||
{
|
||||
MainServer.Instance.DebugLevel = newDebug;
|
||||
MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MainConsole.Instance.Output("Usage: debug http 0..2");
|
||||
break;
|
||||
|
||||
case "scene":
|
||||
if (args.Length == 4)
|
||||
{
|
||||
@@ -970,8 +955,7 @@ namespace OpenSim
|
||||
if (showParams.Length > 1 && showParams[1] == "full")
|
||||
{
|
||||
agents = m_sceneManager.GetCurrentScenePresences();
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
agents = m_sceneManager.GetCurrentSceneAvatars();
|
||||
}
|
||||
@@ -980,7 +964,8 @@ namespace OpenSim
|
||||
|
||||
MainConsole.Instance.Output(
|
||||
String.Format("{0,-16} {1,-16} {2,-37} {3,-11} {4,-16} {5,-30}", "Firstname", "Lastname",
|
||||
"Agent ID", "Root/Child", "Region", "Position"));
|
||||
"Agent ID", "Root/Child", "Region", "Position")
|
||||
);
|
||||
|
||||
foreach (ScenePresence presence in agents)
|
||||
{
|
||||
@@ -990,8 +975,7 @@ namespace OpenSim
|
||||
if (regionInfo == null)
|
||||
{
|
||||
regionName = "Unresolvable";
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
regionName = regionInfo.RegionName;
|
||||
}
|
||||
@@ -1004,43 +988,19 @@ namespace OpenSim
|
||||
presence.UUID,
|
||||
presence.IsChildAgent ? "Child" : "Root",
|
||||
regionName,
|
||||
presence.AbsolutePosition.ToString()));
|
||||
presence.AbsolutePosition.ToString())
|
||||
);
|
||||
}
|
||||
|
||||
MainConsole.Instance.Output(String.Empty);
|
||||
break;
|
||||
|
||||
case "connections":
|
||||
System.Text.StringBuilder connections = new System.Text.StringBuilder("Connections:\n");
|
||||
m_sceneManager.ForEachScene(
|
||||
delegate(Scene scene)
|
||||
{
|
||||
scene.ForEachClient(
|
||||
delegate(IClientAPI client)
|
||||
{
|
||||
connections.AppendFormat("{0}: {1} ({2}) from {3} on circuit {4}\n",
|
||||
scene.RegionInfo.RegionName, client.Name, client.AgentId, client.RemoteEndPoint, client.CircuitCode);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
MainConsole.Instance.Output(connections.ToString());
|
||||
HandleShowConnections();
|
||||
break;
|
||||
|
||||
case "circuits":
|
||||
System.Text.StringBuilder acd = new System.Text.StringBuilder("Agent Circuits:\n");
|
||||
m_sceneManager.ForEachScene(
|
||||
delegate(Scene scene)
|
||||
{
|
||||
//this.HttpServer.
|
||||
acd.AppendFormat("{0}:\n", scene.RegionInfo.RegionName);
|
||||
foreach (AgentCircuitData aCircuit in scene.AuthenticateHandler.GetAgentCircuits().Values)
|
||||
acd.AppendFormat("\t{0} {1} ({2})\n", aCircuit.firstname, aCircuit.lastname, (aCircuit.child ? "Child" : "Root"));
|
||||
}
|
||||
);
|
||||
|
||||
MainConsole.Instance.Output(acd.ToString());
|
||||
HandleShowCircuits();
|
||||
break;
|
||||
|
||||
case "http-handlers":
|
||||
@@ -1078,17 +1038,29 @@ namespace OpenSim
|
||||
}
|
||||
|
||||
m_sceneManager.ForEachScene(
|
||||
delegate(Scene scene)
|
||||
delegate(Scene scene) {
|
||||
m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:");
|
||||
foreach (IRegionModule module in scene.Modules.Values)
|
||||
{
|
||||
m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:");
|
||||
foreach (IRegionModule module in scene.Modules.Values)
|
||||
if (!module.IsSharedModule)
|
||||
{
|
||||
if (!module.IsSharedModule)
|
||||
{
|
||||
m_log.Error("Region Module: " + module.Name);
|
||||
}
|
||||
m_log.Error("Region Module: " + module.Name);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
m_sceneManager.ForEachScene(
|
||||
delegate(Scene scene) {
|
||||
MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:");
|
||||
foreach (IRegionModuleBase module in scene.RegionModules.Values)
|
||||
{
|
||||
Type type = module.GetType().GetInterface("ISharedRegionModule");
|
||||
string module_type = type != null ? "Shared" : "Non-Shared";
|
||||
MainConsole.Instance.OutputFormat("New Region Module ({0}): {1}", module_type, module.Name);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
MainConsole.Instance.Output("");
|
||||
break;
|
||||
@@ -1133,6 +1105,53 @@ namespace OpenSim
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleShowCircuits()
|
||||
{
|
||||
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
|
||||
cdt.AddColumn("Region", 20);
|
||||
cdt.AddColumn("Avatar name", 24);
|
||||
cdt.AddColumn("Type", 5);
|
||||
cdt.AddColumn("Code", 10);
|
||||
cdt.AddColumn("IP", 16);
|
||||
cdt.AddColumn("Viewer Name", 24);
|
||||
|
||||
m_sceneManager.ForEachScene(
|
||||
s =>
|
||||
{
|
||||
foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values)
|
||||
cdt.AddRow(
|
||||
s.Name,
|
||||
aCircuit.Name,
|
||||
aCircuit.child ? "child" : "root",
|
||||
aCircuit.circuitcode.ToString(),
|
||||
aCircuit.IPAddress.ToString(),
|
||||
aCircuit.Viewer);
|
||||
});
|
||||
|
||||
MainConsole.Instance.Output(cdt.ToString());
|
||||
}
|
||||
|
||||
private void HandleShowConnections()
|
||||
{
|
||||
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
|
||||
cdt.AddColumn("Region", 20);
|
||||
cdt.AddColumn("Avatar name", 24);
|
||||
cdt.AddColumn("Circuit code", 12);
|
||||
cdt.AddColumn("Endpoint", 23);
|
||||
cdt.AddColumn("Active?", 7);
|
||||
|
||||
m_sceneManager.ForEachScene(
|
||||
s => s.ForEachClient(
|
||||
c => cdt.AddRow(
|
||||
s.Name,
|
||||
c.Name,
|
||||
c.RemoteEndPoint.ToString(),
|
||||
c.CircuitCode.ToString(),
|
||||
c.IsActive.ToString())));
|
||||
|
||||
MainConsole.Instance.Output(cdt.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use XML2 format to serialize data to a file
|
||||
/// </summary>
|
||||
@@ -1300,58 +1319,6 @@ namespace OpenSim
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Kill an object given its UUID.
|
||||
/// </summary>
|
||||
/// <param name="cmdparams"></param>
|
||||
protected void KillUUID(string module, string[] cmdparams)
|
||||
{
|
||||
if (cmdparams.Length > 2)
|
||||
{
|
||||
UUID id = UUID.Zero;
|
||||
SceneObjectGroup grp = null;
|
||||
Scene sc = null;
|
||||
|
||||
if (!UUID.TryParse(cmdparams[2], out id))
|
||||
{
|
||||
MainConsole.Instance.Output("[KillUUID]: Error bad UUID format!");
|
||||
return;
|
||||
}
|
||||
|
||||
m_sceneManager.ForEachScene(
|
||||
delegate(Scene scene)
|
||||
{
|
||||
SceneObjectPart part = scene.GetSceneObjectPart(id);
|
||||
if (part == null)
|
||||
return;
|
||||
|
||||
grp = part.ParentGroup;
|
||||
sc = scene;
|
||||
});
|
||||
|
||||
if (grp == null)
|
||||
{
|
||||
MainConsole.Instance.Output(String.Format("[KillUUID]: Given UUID {0} not found!", id));
|
||||
}
|
||||
else
|
||||
{
|
||||
MainConsole.Instance.Output(String.Format("[KillUUID]: Found UUID {0} in scene {1}", id, sc.RegionInfo.RegionName));
|
||||
try
|
||||
{
|
||||
sc.DeleteSceneObject(grp, false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[KillUUID]: Error while removing objects from scene: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MainConsole.Instance.Output("[KillUUID]: Usage: kill uuid <UUID>");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ namespace OpenSim
|
||||
|
||||
base.StartupSpecific();
|
||||
|
||||
m_stats = StatsManager.StartCollectingSimExtraStats();
|
||||
m_stats = StatsManager.SimExtraStats;
|
||||
|
||||
// Create a ModuleLoader instance
|
||||
m_moduleLoader = new ModuleLoader(m_config.Source);
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||
scene.EventManager.OnRegisterCaps += OnRegisterCaps;
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"Comms",
|
||||
"Debug",
|
||||
false,
|
||||
"debug eq",
|
||||
"debug eq [0|1|2]",
|
||||
|
||||
@@ -51,7 +51,16 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
MainServer.Instance = new BaseHttpServer(9999, false, 9998, "");
|
||||
uint port = 9999;
|
||||
uint sslPort = 9998;
|
||||
|
||||
// This is an unfortunate bit of clean up we have to do because MainServer manages things through static
|
||||
// variables and the VM is not restarted between tests.
|
||||
MainServer.RemoveHttpServer(port);
|
||||
|
||||
BaseHttpServer server = new BaseHttpServer(port, false, sslPort, "");
|
||||
MainServer.AddHttpServer(server);
|
||||
MainServer.Instance = server;
|
||||
|
||||
IConfigSource config = new IniConfigSource();
|
||||
config.AddConfig("Startup");
|
||||
|
||||
@@ -333,7 +333,6 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||
grp.AbsolutePosition = obj.Position;
|
||||
prim.RotationOffset = obj.Rotation;
|
||||
|
||||
grp.IsAttachment = false;
|
||||
// Required for linking
|
||||
grp.RootPart.ClearUpdateSchedule();
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
public sealed class IncomingPacket
|
||||
{
|
||||
/// <summary>Client this packet came from</summary>
|
||||
public LLUDPClient Client;
|
||||
public LLClientView Client;
|
||||
|
||||
/// <summary>Packet data that has been received</summary>
|
||||
public Packet Packet;
|
||||
|
||||
@@ -48,7 +49,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
/// </summary>
|
||||
/// <param name="client">Reference to the client this packet came from</param>
|
||||
/// <param name="packet">Packet data</param>
|
||||
public IncomingPacket(LLUDPClient client, Packet packet)
|
||||
public IncomingPacket(LLClientView client, Packet packet)
|
||||
{
|
||||
Client = client;
|
||||
Packet = packet;
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
/// Handles new client connections
|
||||
/// Constructor takes a single Packet and authenticates everything
|
||||
/// </summary>
|
||||
public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientInventory, IClientIPEndpoint, IStatsCollector
|
||||
public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientInventory, IStatsCollector
|
||||
{
|
||||
/// <value>
|
||||
/// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details.
|
||||
@@ -357,7 +357,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
protected string m_lastName;
|
||||
protected Thread m_clientThread;
|
||||
protected Vector3 m_startpos;
|
||||
protected EndPoint m_userEndPoint;
|
||||
protected UUID m_activeGroupID;
|
||||
protected string m_activeGroupName = String.Empty;
|
||||
protected ulong m_activeGroupPowers;
|
||||
@@ -442,7 +441,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
|
||||
public LLClientView(Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
|
||||
UUID agentId, UUID sessionId, uint circuitCode)
|
||||
{
|
||||
// DebugPacketLevel = 1;
|
||||
@@ -450,7 +449,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
RegisterInterface<IClientIM>(this);
|
||||
RegisterInterface<IClientInventory>(this);
|
||||
RegisterInterface<IClientChat>(this);
|
||||
RegisterInterface<IClientIPEndpoint>(this);
|
||||
|
||||
m_scene = scene;
|
||||
m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
|
||||
@@ -467,7 +465,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
m_sessionId = sessionId;
|
||||
m_secureSessionId = sessionInfo.LoginInfo.SecureSession;
|
||||
m_circuitCode = circuitCode;
|
||||
m_userEndPoint = remoteEP;
|
||||
m_firstName = sessionInfo.LoginInfo.First;
|
||||
m_lastName = sessionInfo.LoginInfo.Last;
|
||||
m_startpos = sessionInfo.LoginInfo.StartPos;
|
||||
@@ -490,16 +487,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
IsActive = false;
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[CLIENT]: Close has been called for {0} attached to scene {1}",
|
||||
Name, m_scene.RegionInfo.RegionName);
|
||||
|
||||
// Send the STOP packet
|
||||
DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
|
||||
OutPacket(disable, ThrottleOutPacketType.Unknown);
|
||||
|
||||
IsActive = false;
|
||||
|
||||
// Shutdown the image manager
|
||||
ImageManager.Close();
|
||||
|
||||
@@ -2723,6 +2716,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
}
|
||||
}
|
||||
|
||||
public void SendAssetNotFound(AssetRequestToClient req)
|
||||
{
|
||||
TransferInfoPacket Transfer = new TransferInfoPacket();
|
||||
Transfer.TransferInfo.ChannelType = 2;
|
||||
Transfer.TransferInfo.Status = -2;
|
||||
Transfer.TransferInfo.TargetType = 0;
|
||||
Transfer.TransferInfo.Params = req.Params;
|
||||
Transfer.TransferInfo.Size = 0;
|
||||
Transfer.TransferInfo.TransferID = req.TransferRequestID;
|
||||
Transfer.Header.Zerocoded = true;
|
||||
OutPacket(Transfer, ThrottleOutPacketType.Asset);
|
||||
}
|
||||
|
||||
public void SendTexture(AssetBase TextureAsset)
|
||||
{
|
||||
|
||||
@@ -3726,8 +3732,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
}
|
||||
}
|
||||
|
||||
++updatesThisCall;
|
||||
|
||||
#region UpdateFlags to packet type conversion
|
||||
|
||||
PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
|
||||
@@ -3784,20 +3788,53 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
|
||||
if (!canUseImproved && !canUseCompressed)
|
||||
{
|
||||
ObjectUpdatePacket.ObjectDataBlock updateBlock;
|
||||
|
||||
if (update.Entity is ScenePresence)
|
||||
{
|
||||
objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
|
||||
objectUpdates.Value.Add(update);
|
||||
updateBlock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
|
||||
objectUpdates.Value.Add(update);
|
||||
SceneObjectPart part = (SceneObjectPart)update.Entity;
|
||||
updateBlock = CreatePrimUpdateBlock(part, AgentId);
|
||||
|
||||
// If the part has become a private hud since the update was scheduled then we do not
|
||||
// want to send it to other avatars.
|
||||
if (part.ParentGroup.IsAttachment
|
||||
&& part.ParentGroup.HasPrivateAttachmentPoint
|
||||
&& part.ParentGroup.AttachedAvatar != AgentId)
|
||||
continue;
|
||||
|
||||
// If the part has since been deleted, then drop the update. In the case of attachments,
|
||||
// this is to avoid spurious updates to other viewers since post-processing of attachments
|
||||
// has to change the IsAttachment flag for various reasons (which will end up in a pass
|
||||
// of the test above).
|
||||
//
|
||||
// Actual deletions (kills) happen in another method.
|
||||
if (part.ParentGroup.IsDeleted)
|
||||
continue;
|
||||
}
|
||||
|
||||
objectUpdateBlocks.Value.Add(updateBlock);
|
||||
objectUpdates.Value.Add(update);
|
||||
}
|
||||
else if (!canUseImproved)
|
||||
{
|
||||
compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
|
||||
SceneObjectPart part = (SceneObjectPart)update.Entity;
|
||||
ObjectUpdateCompressedPacket.ObjectDataBlock compressedBlock
|
||||
= CreateCompressedUpdateBlock(part, updateFlags);
|
||||
|
||||
// If the part has since been deleted, then drop the update. In the case of attachments,
|
||||
// this is to avoid spurious updates to other viewers since post-processing of attachments
|
||||
// has to change the IsAttachment flag for various reasons (which will end up in a pass
|
||||
// of the test above).
|
||||
//
|
||||
// Actual deletions (kills) happen in another method.
|
||||
if (part.ParentGroup.IsDeleted)
|
||||
continue;
|
||||
|
||||
compressedUpdateBlocks.Value.Add(compressedBlock);
|
||||
compressedUpdates.Value.Add(update);
|
||||
}
|
||||
else
|
||||
@@ -3810,15 +3847,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
}
|
||||
else
|
||||
{
|
||||
ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseUpdateBlock
|
||||
= CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures));
|
||||
|
||||
// Everything else goes here
|
||||
terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
|
||||
if (update.Entity is SceneObjectPart)
|
||||
{
|
||||
SceneObjectPart part = (SceneObjectPart)update.Entity;
|
||||
|
||||
// If the part has become a private hud since the update was scheduled then we do not
|
||||
// want to send it to other avatars.
|
||||
if (part.ParentGroup.IsAttachment
|
||||
&& part.ParentGroup.HasPrivateAttachmentPoint
|
||||
&& part.ParentGroup.AttachedAvatar != AgentId)
|
||||
continue;
|
||||
|
||||
// If the part has since been deleted, then drop the update. In the case of attachments,
|
||||
// this is to avoid spurious updates to other viewers since post-processing of attachments
|
||||
// has to change the IsAttachment flag for various reasons (which will end up in a pass
|
||||
// of the test above).
|
||||
//
|
||||
// Actual deletions (kills) happen in another method.
|
||||
if (part.ParentGroup.IsDeleted)
|
||||
continue;
|
||||
}
|
||||
|
||||
terseUpdateBlocks.Value.Add(terseUpdateBlock);
|
||||
terseUpdates.Value.Add(update);
|
||||
}
|
||||
}
|
||||
|
||||
++updatesThisCall;
|
||||
|
||||
#endregion Block Construction
|
||||
}
|
||||
|
||||
|
||||
#region Packet Sending
|
||||
ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
|
||||
@@ -11654,7 +11716,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect))
|
||||
logPacket = false;
|
||||
|
||||
if (DebugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate)
|
||||
if (DebugPacketLevel <= 50
|
||||
& (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
|
||||
logPacket = false;
|
||||
|
||||
if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
|
||||
@@ -11767,7 +11830,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
{
|
||||
ClientInfo info = m_udpClient.GetClientInfo();
|
||||
|
||||
info.userEP = m_userEndPoint;
|
||||
info.proxyEP = null;
|
||||
info.agentcircuit = RequestClientInfo();
|
||||
|
||||
@@ -11779,11 +11841,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
m_udpClient.SetClientInfo(info);
|
||||
}
|
||||
|
||||
public EndPoint GetClientEP()
|
||||
{
|
||||
return m_userEndPoint;
|
||||
}
|
||||
|
||||
#region Media Parcel Members
|
||||
|
||||
public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time)
|
||||
@@ -11864,10 +11921,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public void KillEndDone()
|
||||
{
|
||||
}
|
||||
|
||||
#region IClientCore
|
||||
|
||||
private readonly Dictionary<Type, object> m_clientInterfaces = new Dictionary<Type, object>();
|
||||
@@ -11985,14 +12038,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
/// <param name="asset"></param>
|
||||
protected void AssetReceived(string id, Object sender, AssetBase asset)
|
||||
{
|
||||
if (asset == null)
|
||||
return;
|
||||
|
||||
TransferRequestPacket transferRequest = (TransferRequestPacket)sender;
|
||||
|
||||
UUID requestID = UUID.Zero;
|
||||
byte source = (byte)SourceType.Asset;
|
||||
|
||||
AssetRequestToClient req = new AssetRequestToClient();
|
||||
|
||||
if (asset == null)
|
||||
{
|
||||
req.AssetInf = null;
|
||||
req.AssetRequestSource = source;
|
||||
req.IsTextureRequest = false;
|
||||
req.NumPackets = 0;
|
||||
req.Params = transferRequest.TransferInfo.Params;
|
||||
req.RequestAssetID = requestID;
|
||||
req.TransferRequestID = transferRequest.TransferInfo.TransferID;
|
||||
|
||||
SendAssetNotFound(req);
|
||||
return;
|
||||
}
|
||||
|
||||
if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
|
||||
{
|
||||
requestID = new UUID(transferRequest.TransferInfo.Params, 0);
|
||||
@@ -12009,7 +12075,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
return;
|
||||
|
||||
// The asset is known to exist and is in our cache, so add it to the AssetRequests list
|
||||
AssetRequestToClient req = new AssetRequestToClient();
|
||||
req.AssetInf = asset;
|
||||
req.AssetRequestSource = source;
|
||||
req.IsTextureRequest = false;
|
||||
@@ -12045,24 +12110,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
return numPackets;
|
||||
}
|
||||
|
||||
#region IClientIPEndpoint Members
|
||||
|
||||
public IPAddress EndPoint
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_userEndPoint is IPEndPoint)
|
||||
{
|
||||
IPEndPoint ep = (IPEndPoint)m_userEndPoint;
|
||||
|
||||
return ep.Address;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void SendRebakeAvatarTextures(UUID textureID)
|
||||
{
|
||||
RebakeAvatarTexturesPacket pack =
|
||||
|
||||
@@ -147,21 +147,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
private int m_elapsed500MSOutgoingPacketHandler;
|
||||
|
||||
/// <summary>Flag to signal when clients should check for resends</summary>
|
||||
private bool m_resendUnacked;
|
||||
protected bool m_resendUnacked;
|
||||
|
||||
/// <summary>Flag to signal when clients should send ACKs</summary>
|
||||
private bool m_sendAcks;
|
||||
protected bool m_sendAcks;
|
||||
|
||||
/// <summary>Flag to signal when clients should send pings</summary>
|
||||
private bool m_sendPing;
|
||||
protected bool m_sendPing;
|
||||
|
||||
private int m_defaultRTO = 0;
|
||||
private int m_maxRTO = 0;
|
||||
|
||||
private int m_ackTimeout = 0;
|
||||
private int m_pausedAckTimeout = 0;
|
||||
private bool m_disableFacelights = false;
|
||||
|
||||
public Socket Server { get { return null; } }
|
||||
|
||||
private int m_malformedCount = 0; // Guard against a spamming attack
|
||||
|
||||
/// <summary>
|
||||
/// Record current outgoing client for monitoring purposes.
|
||||
/// </summary>
|
||||
private IClientAPI m_currentOutgoingClient;
|
||||
|
||||
/// <summary>
|
||||
/// Recording current incoming client for monitoring purposes.
|
||||
/// </summary>
|
||||
private IClientAPI m_currentIncomingClient;
|
||||
|
||||
public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
|
||||
: base(listenIP, (int)port)
|
||||
{
|
||||
@@ -198,11 +211,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
m_defaultRTO = config.GetInt("DefaultRTO", 0);
|
||||
m_maxRTO = config.GetInt("MaxRTO", 0);
|
||||
m_disableFacelights = config.GetBoolean("DisableFacelights", false);
|
||||
m_ackTimeout = 1000 * config.GetInt("AckTimeout", 60);
|
||||
m_pausedAckTimeout = 1000 * config.GetInt("PausedAckTimeout", 300);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrimUpdatesPerCallback = 100;
|
||||
TextureSendLimit = 20;
|
||||
m_ackTimeout = 1000 * 60; // 1 minute
|
||||
m_pausedAckTimeout = 1000 * 300; // 5 minutes
|
||||
}
|
||||
|
||||
#region BinaryStats
|
||||
@@ -239,19 +256,56 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
if (m_scene == null)
|
||||
throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
|
||||
|
||||
m_log.Info("[LLUDPSERVER]: Starting the LLUDP server in " + (m_asyncPacketHandling ? "asynchronous" : "synchronous") + " mode");
|
||||
m_log.InfoFormat(
|
||||
"[LLUDPSERVER]: Starting the LLUDP server in {0} mode",
|
||||
m_asyncPacketHandling ? "asynchronous" : "synchronous");
|
||||
|
||||
base.Start(m_recvBufferSize, m_asyncPacketHandling);
|
||||
|
||||
// Start the packet processing threads
|
||||
Watchdog.StartThread(
|
||||
IncomingPacketHandler, "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true);
|
||||
IncomingPacketHandler,
|
||||
string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
|
||||
ThreadPriority.Normal,
|
||||
false,
|
||||
true,
|
||||
GetWatchdogIncomingAlarmData,
|
||||
Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
|
||||
|
||||
Watchdog.StartThread(
|
||||
OutgoingPacketHandler, "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true);
|
||||
OutgoingPacketHandler,
|
||||
string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName),
|
||||
ThreadPriority.Normal,
|
||||
false,
|
||||
true,
|
||||
GetWatchdogOutgoingAlarmData,
|
||||
Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
|
||||
|
||||
m_elapsedMSSinceLastStatReport = Environment.TickCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private string GetWatchdogIncomingAlarmData()
|
||||
{
|
||||
return string.Format(
|
||||
"Client is {0}",
|
||||
m_currentIncomingClient != null ? m_currentIncomingClient.Name : "none");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private string GetWatchdogOutgoingAlarmData()
|
||||
{
|
||||
return string.Format(
|
||||
"Client is {0}",
|
||||
m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
|
||||
}
|
||||
|
||||
public new void Stop()
|
||||
{
|
||||
m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
|
||||
@@ -485,19 +539,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null);
|
||||
}
|
||||
|
||||
public void HandleUnacked(LLUDPClient udpClient)
|
||||
public void HandleUnacked(LLClientView client)
|
||||
{
|
||||
LLUDPClient udpClient = client.UDPClient;
|
||||
|
||||
if (!udpClient.IsConnected)
|
||||
return;
|
||||
|
||||
// Disconnect an agent if no packets are received for some time
|
||||
//FIXME: Make 60 an .ini setting
|
||||
if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60)
|
||||
{
|
||||
m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
|
||||
StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
|
||||
int timeoutTicks = m_ackTimeout;
|
||||
|
||||
// Allow more slack if the client is "paused" eg file upload dialogue is open
|
||||
// Some sort of limit is needed in case the client crashes, loses its network connection
|
||||
// or some other disaster prevents it from sendung the AgentResume
|
||||
if (udpClient.IsPaused)
|
||||
timeoutTicks = m_pausedAckTimeout;
|
||||
|
||||
if (client.IsActive &&
|
||||
(Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks)
|
||||
{
|
||||
// We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
|
||||
// though it's set later on by LLClientView.Close()
|
||||
client.IsActive = false;
|
||||
|
||||
// Fire this out on a different thread so that we don't hold up outgoing packet processing for
|
||||
// everybody else if this is being called due to an ack timeout.
|
||||
// This is the same as processing as the async process of a logout request.
|
||||
Util.FireAndForget(o => DeactivateClientDueToTimeout(client));
|
||||
|
||||
RemoveClient(udpClient);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -820,7 +889,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
#endregion Ping Check Handling
|
||||
|
||||
// Inbox insertion
|
||||
packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
|
||||
packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
|
||||
}
|
||||
|
||||
#region BinaryStats
|
||||
@@ -917,8 +986,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} from {1}",
|
||||
uccp.CircuitCode.Code, buffer.RemoteEndPoint);
|
||||
"[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
|
||||
uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint);
|
||||
|
||||
remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
|
||||
|
||||
@@ -947,8 +1016,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
{
|
||||
// Don't create clients for unauthorized requesters.
|
||||
m_log.WarnFormat(
|
||||
"[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}",
|
||||
uccp.CircuitCode.ID, uccp.CircuitCode.Code, remoteEndPoint);
|
||||
"[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
|
||||
uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint);
|
||||
}
|
||||
|
||||
// m_log.DebugFormat(
|
||||
@@ -1034,7 +1103,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
{
|
||||
LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
|
||||
|
||||
client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
|
||||
client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
|
||||
client.OnLogout += LogoutHandler;
|
||||
|
||||
((LLClientView)client).DisableFacelights = m_disableFacelights;
|
||||
@@ -1046,15 +1115,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
return client;
|
||||
}
|
||||
|
||||
private void RemoveClient(LLUDPClient udpClient)
|
||||
/// <summary>
|
||||
/// Deactivates the client if we don't receive any packets within a certain amount of time (default 60 seconds).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If a connection is active then we will always receive packets even if nothing else is happening, due to
|
||||
/// regular client pings.
|
||||
/// </remarks>
|
||||
/// <param name='client'></param>
|
||||
private void DeactivateClientDueToTimeout(IClientAPI client)
|
||||
{
|
||||
// Remove this client from the scene
|
||||
IClientAPI client;
|
||||
if (m_scene.TryGetClient(udpClient.AgentID, out client))
|
||||
{
|
||||
client.IsLoggingOut = true;
|
||||
client.Close();
|
||||
}
|
||||
// We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
|
||||
// though it's set later on by LLClientView.Close()
|
||||
client.IsActive = false;
|
||||
|
||||
m_log.WarnFormat(
|
||||
"[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
|
||||
client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
|
||||
|
||||
StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
|
||||
|
||||
if (!client.SceneAgent.IsChildAgent)
|
||||
client.Kick("Simulator logged you out due to connection timeout");
|
||||
|
||||
client.Close();
|
||||
}
|
||||
|
||||
private void IncomingPacketHandler()
|
||||
@@ -1161,6 +1245,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
// client. m_packetSent will be set to true if a packet is sent
|
||||
m_scene.ForEachClient(clientPacketHandler);
|
||||
|
||||
m_currentOutgoingClient = null;
|
||||
|
||||
// If nothing was sent, sleep for the minimum amount of time before a
|
||||
// token bucket could get more tokens
|
||||
if (!m_packetSent)
|
||||
@@ -1177,18 +1263,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
Watchdog.RemoveThread();
|
||||
}
|
||||
|
||||
private void ClientOutgoingPacketHandler(IClientAPI client)
|
||||
protected void ClientOutgoingPacketHandler(IClientAPI client)
|
||||
{
|
||||
m_currentOutgoingClient = client;
|
||||
|
||||
try
|
||||
{
|
||||
if (client is LLClientView)
|
||||
{
|
||||
LLUDPClient udpClient = ((LLClientView)client).UDPClient;
|
||||
LLClientView llClient = (LLClientView)client;
|
||||
LLUDPClient udpClient = llClient.UDPClient;
|
||||
|
||||
if (udpClient.IsConnected)
|
||||
{
|
||||
if (m_resendUnacked)
|
||||
HandleUnacked(udpClient);
|
||||
HandleUnacked(llClient);
|
||||
|
||||
if (m_sendAcks)
|
||||
SendAcks(udpClient);
|
||||
@@ -1204,8 +1293,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name +
|
||||
" threw an exception: " + ex.Message, ex);
|
||||
m_log.Error(
|
||||
string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1231,11 +1320,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
{
|
||||
nticks++;
|
||||
watch1.Start();
|
||||
m_currentOutgoingClient = client;
|
||||
|
||||
try
|
||||
{
|
||||
if (client is LLClientView)
|
||||
{
|
||||
LLUDPClient udpClient = ((LLClientView)client).UDPClient;
|
||||
LLClientView llClient = (LLClientView)client;
|
||||
LLUDPClient udpClient = llClient.UDPClient;
|
||||
|
||||
if (udpClient.IsConnected)
|
||||
{
|
||||
@@ -1244,7 +1336,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
nticksUnack++;
|
||||
watch2.Start();
|
||||
|
||||
HandleUnacked(udpClient);
|
||||
HandleUnacked(llClient);
|
||||
|
||||
watch2.Stop();
|
||||
avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
|
||||
@@ -1315,23 +1407,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
|
||||
#endregion
|
||||
|
||||
private void ProcessInPacket(object state)
|
||||
private void ProcessInPacket(IncomingPacket incomingPacket)
|
||||
{
|
||||
IncomingPacket incomingPacket = (IncomingPacket)state;
|
||||
Packet packet = incomingPacket.Packet;
|
||||
LLUDPClient udpClient = incomingPacket.Client;
|
||||
IClientAPI client;
|
||||
LLClientView client = incomingPacket.Client;
|
||||
|
||||
// Sanity check
|
||||
if (packet == null || udpClient == null)
|
||||
if (client.IsActive)
|
||||
{
|
||||
m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", UDPClient=\"{1}\"",
|
||||
packet, udpClient);
|
||||
}
|
||||
m_currentIncomingClient = client;
|
||||
|
||||
// Make sure this client is still alive
|
||||
if (m_scene.TryGetClient(udpClient.AgentID, out client))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Process this packet
|
||||
@@ -1346,23 +1430,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
catch (Exception e)
|
||||
{
|
||||
// Don't let a failure in an individual client thread crash the whole sim.
|
||||
m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type);
|
||||
m_log.Error(e.Message, e);
|
||||
m_log.Error(
|
||||
string.Format(
|
||||
"[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw ",
|
||||
client.Name, packet.Type),
|
||||
e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_currentIncomingClient = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
|
||||
packet.Type, udpClient.AgentID, m_scene.RegionInfo.RegionName);
|
||||
packet.Type, client.Name, m_scene.RegionInfo.RegionName);
|
||||
}
|
||||
}
|
||||
|
||||
protected void LogoutHandler(IClientAPI client)
|
||||
{
|
||||
client.SendLogoutPacket();
|
||||
if (client.IsActive)
|
||||
RemoveClient(((LLClientView)client).UDPClient);
|
||||
|
||||
if (!client.IsLoggingOut)
|
||||
{
|
||||
client.IsLoggingOut = true;
|
||||
client.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||
[TestFixture]
|
||||
public class BasicCircuitTests
|
||||
{
|
||||
private Scene m_scene;
|
||||
private TestLLUDPServer m_udpServer;
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void FixtureInit()
|
||||
{
|
||||
@@ -61,83 +64,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||
Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Add a client for testing
|
||||
// /// </summary>
|
||||
// /// <param name="scene"></param>
|
||||
// /// <param name="testLLUDPServer"></param>
|
||||
// /// <param name="testPacketServer"></param>
|
||||
// /// <param name="acm">Agent circuit manager used in setting up the stack</param>
|
||||
// protected void SetupStack(
|
||||
// IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
|
||||
// out AgentCircuitManager acm)
|
||||
// {
|
||||
// IConfigSource configSource = new IniConfigSource();
|
||||
// ClientStackUserSettings userSettings = new ClientStackUserSettings();
|
||||
// testLLUDPServer = new TestLLUDPServer();
|
||||
// acm = new AgentCircuitManager();
|
||||
//
|
||||
// uint port = 666;
|
||||
// testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
|
||||
// testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
|
||||
// testLLUDPServer.LocalScene = scene;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Set up a client for tests which aren't concerned with this process itself and where only one client is being
|
||||
// /// tested
|
||||
// /// </summary>
|
||||
// /// <param name="circuitCode"></param>
|
||||
// /// <param name="epSender"></param>
|
||||
// /// <param name="testLLUDPServer"></param>
|
||||
// /// <param name="acm"></param>
|
||||
// protected void AddClient(
|
||||
// uint circuitCode, EndPoint epSender, TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
|
||||
// {
|
||||
// UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
|
||||
// UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
|
||||
//
|
||||
// AddClient(circuitCode, epSender, myAgentUuid, mySessionUuid, testLLUDPServer, acm);
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Set up a client for tests which aren't concerned with this process itself
|
||||
// /// </summary>
|
||||
// /// <param name="circuitCode"></param>
|
||||
// /// <param name="epSender"></param>
|
||||
// /// <param name="agentId"></param>
|
||||
// /// <param name="sessionId"></param>
|
||||
// /// <param name="testLLUDPServer"></param>
|
||||
// /// <param name="acm"></param>
|
||||
// protected void AddClient(
|
||||
// uint circuitCode, EndPoint epSender, UUID agentId, UUID sessionId,
|
||||
// TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
|
||||
// {
|
||||
// AgentCircuitData acd = new AgentCircuitData();
|
||||
// acd.AgentID = agentId;
|
||||
// acd.SessionID = sessionId;
|
||||
//
|
||||
// UseCircuitCodePacket uccp = new UseCircuitCodePacket();
|
||||
//
|
||||
// UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
|
||||
// = new UseCircuitCodePacket.CircuitCodeBlock();
|
||||
// uccpCcBlock.Code = circuitCode;
|
||||
// uccpCcBlock.ID = agentId;
|
||||
// uccpCcBlock.SessionID = sessionId;
|
||||
// uccp.CircuitCode = uccpCcBlock;
|
||||
//
|
||||
// acm.AddNewCircuit(circuitCode, acd);
|
||||
//
|
||||
// testLLUDPServer.LoadReceive(uccp, epSender);
|
||||
// testLLUDPServer.ReceiveData(null);
|
||||
// }
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
m_scene = new SceneHelpers().SetupScene();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build an object name packet for test purposes
|
||||
/// </summary>
|
||||
/// <param name="objectLocalId"></param>
|
||||
/// <param name="objectName"></param>
|
||||
protected ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName)
|
||||
private ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName)
|
||||
{
|
||||
ObjectNamePacket onp = new ObjectNamePacket();
|
||||
ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock();
|
||||
@@ -148,29 +86,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||
|
||||
return onp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test adding a client to the stack
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAddClient()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// XmlConfigurator.Configure();
|
||||
|
||||
TestScene scene = new SceneHelpers().SetupScene();
|
||||
uint myCircuitCode = 123456;
|
||||
private void AddUdpServer()
|
||||
{
|
||||
AddUdpServer(new IniConfigSource());
|
||||
}
|
||||
|
||||
private void AddUdpServer(IniConfigSource configSource)
|
||||
{
|
||||
uint port = 0;
|
||||
AgentCircuitManager acm = m_scene.AuthenticateHandler;
|
||||
|
||||
m_udpServer = new TestLLUDPServer(IPAddress.Any, ref port, 0, false, configSource, acm);
|
||||
m_udpServer.AddScene(m_scene);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used by tests that aren't testing this stage.
|
||||
/// </summary>
|
||||
private ScenePresence AddClient()
|
||||
{
|
||||
UUID myAgentUuid = TestHelpers.ParseTail(0x1);
|
||||
UUID mySessionUuid = TestHelpers.ParseTail(0x2);
|
||||
uint myCircuitCode = 123456;
|
||||
IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
|
||||
|
||||
uint port = 0;
|
||||
AgentCircuitManager acm = scene.AuthenticateHandler;
|
||||
|
||||
TestLLUDPServer llUdpServer
|
||||
= new TestLLUDPServer(IPAddress.Any, ref port, 0, false, new IniConfigSource(), acm);
|
||||
llUdpServer.AddScene(scene);
|
||||
|
||||
UseCircuitCodePacket uccp = new UseCircuitCodePacket();
|
||||
|
||||
UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
|
||||
@@ -185,26 +125,67 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||
upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor.
|
||||
Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);
|
||||
|
||||
llUdpServer.PacketReceived(upb);
|
||||
AgentCircuitData acd = new AgentCircuitData();
|
||||
acd.AgentID = myAgentUuid;
|
||||
acd.SessionID = mySessionUuid;
|
||||
|
||||
m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);
|
||||
|
||||
m_udpServer.PacketReceived(upb);
|
||||
|
||||
return m_scene.GetScenePresence(myAgentUuid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test adding a client to the stack
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAddClient()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// XmlConfigurator.Configure();
|
||||
|
||||
AddUdpServer();
|
||||
|
||||
UUID myAgentUuid = TestHelpers.ParseTail(0x1);
|
||||
UUID mySessionUuid = TestHelpers.ParseTail(0x2);
|
||||
uint myCircuitCode = 123456;
|
||||
IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
|
||||
|
||||
UseCircuitCodePacket uccp = new UseCircuitCodePacket();
|
||||
|
||||
UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
|
||||
= new UseCircuitCodePacket.CircuitCodeBlock();
|
||||
uccpCcBlock.Code = myCircuitCode;
|
||||
uccpCcBlock.ID = myAgentUuid;
|
||||
uccpCcBlock.SessionID = mySessionUuid;
|
||||
uccp.CircuitCode = uccpCcBlock;
|
||||
|
||||
byte[] uccpBytes = uccp.ToBytes();
|
||||
UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length);
|
||||
upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor.
|
||||
Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);
|
||||
|
||||
m_udpServer.PacketReceived(upb);
|
||||
|
||||
// Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet
|
||||
Assert.That(scene.GetScenePresence(myAgentUuid), Is.Null);
|
||||
Assert.That(m_scene.GetScenePresence(myAgentUuid), Is.Null);
|
||||
|
||||
AgentCircuitData acd = new AgentCircuitData();
|
||||
acd.AgentID = myAgentUuid;
|
||||
acd.SessionID = mySessionUuid;
|
||||
|
||||
acm.AddNewCircuit(myCircuitCode, acd);
|
||||
m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);
|
||||
|
||||
llUdpServer.PacketReceived(upb);
|
||||
m_udpServer.PacketReceived(upb);
|
||||
|
||||
// Should succeed now
|
||||
ScenePresence sp = scene.GetScenePresence(myAgentUuid);
|
||||
ScenePresence sp = m_scene.GetScenePresence(myAgentUuid);
|
||||
Assert.That(sp.UUID, Is.EqualTo(myAgentUuid));
|
||||
|
||||
Assert.That(llUdpServer.PacketsSent.Count, Is.EqualTo(1));
|
||||
Assert.That(m_udpServer.PacketsSent.Count, Is.EqualTo(1));
|
||||
|
||||
Packet packet = llUdpServer.PacketsSent[0];
|
||||
Packet packet = m_udpServer.PacketsSent[0];
|
||||
Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket)));
|
||||
|
||||
PacketAckPacket ackPacket = packet as PacketAckPacket;
|
||||
@@ -212,6 +193,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||
Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLogoutClientDueToAck()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
IniConfigSource ics = new IniConfigSource();
|
||||
IConfig config = ics.AddConfig("ClientStack.LindenUDP");
|
||||
config.Set("AckTimeout", -1);
|
||||
AddUdpServer(ics);
|
||||
|
||||
ScenePresence sp = AddClient();
|
||||
m_udpServer.ClientOutgoingPacketHandler(sp.ControllingClient, true, false, false);
|
||||
|
||||
ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
|
||||
Assert.That(spAfterAckTimeout, Is.Null);
|
||||
|
||||
// TestHelpers.DisableLogging();
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Test removing a client from the stack
|
||||
// /// </summary>
|
||||
|
||||
@@ -44,9 +44,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||
}
|
||||
protected int m_objectNameCallsReceived;
|
||||
|
||||
public MockScene()
|
||||
public MockScene() : base(new RegionInfo(1000, 1000, null, null))
|
||||
{
|
||||
m_regInfo = new RegionInfo(1000, 1000, null, null);
|
||||
m_regStatus = RegionStatus.Up;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||
PacketsSent.Add(packet);
|
||||
}
|
||||
|
||||
public void ClientOutgoingPacketHandler(IClientAPI client, bool resendUnacked, bool sendAcks, bool sendPing)
|
||||
{
|
||||
m_resendUnacked = resendUnacked;
|
||||
m_sendAcks = sendAcks;
|
||||
m_sendPing = sendPing;
|
||||
|
||||
ClientOutgoingPacketHandler(client);
|
||||
}
|
||||
|
||||
//// /// <summary>
|
||||
//// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive
|
||||
//// /// </summary>
|
||||
|
||||
@@ -94,22 +94,19 @@ namespace OpenSim.Region.ClientStack
|
||||
m_log.InfoFormat("[REGION SERVER]: Starting HTTP server on port {0}", m_httpServerPort);
|
||||
m_httpServer.Start();
|
||||
|
||||
MainServer.AddHttpServer(m_httpServer);
|
||||
MainServer.Instance = m_httpServer;
|
||||
|
||||
// "OOB" Server
|
||||
if (m_networkServersInfo.ssl_listener)
|
||||
{
|
||||
BaseHttpServer server = null;
|
||||
server = new BaseHttpServer(
|
||||
BaseHttpServer server = new BaseHttpServer(
|
||||
m_networkServersInfo.https_port, m_networkServersInfo.ssl_listener, m_networkServersInfo.cert_path,
|
||||
m_networkServersInfo.cert_pass);
|
||||
// Add the server to m_Servers
|
||||
if(server != null)
|
||||
{
|
||||
m_log.InfoFormat("[REGION SERVER]: Starting HTTPS server on port {0}", server.Port);
|
||||
MainServer.AddHttpServer(server);
|
||||
server.Start();
|
||||
}
|
||||
|
||||
m_log.InfoFormat("[REGION SERVER]: Starting HTTPS server on port {0}", server.Port);
|
||||
MainServer.AddHttpServer(server);
|
||||
server.Start();
|
||||
}
|
||||
|
||||
base.StartupSpecific();
|
||||
|
||||
@@ -42,8 +42,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
||||
public class AssetTransactionModule : INonSharedRegionModule,
|
||||
IAgentAssetTransactions
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(
|
||||
// MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected Scene m_Scene;
|
||||
private bool m_dumpAssetsToFile = false;
|
||||
@@ -209,15 +208,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
||||
/// and comes through this method.
|
||||
/// </summary>
|
||||
/// <param name="remoteClient"></param>
|
||||
/// <param name="part"></param>
|
||||
/// <param name="transactionID"></param>
|
||||
/// <param name="item"></param>
|
||||
public void HandleTaskItemUpdateFromTransaction(IClientAPI remoteClient,
|
||||
SceneObjectPart part, UUID transactionID,
|
||||
TaskInventoryItem item)
|
||||
public void HandleTaskItemUpdateFromTransaction(
|
||||
IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0}",
|
||||
// item.Name);
|
||||
m_log.DebugFormat(
|
||||
"[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}",
|
||||
item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName);
|
||||
|
||||
AgentAssetTransactions transactions =
|
||||
GetUserTransactions(remoteClient.AgentId);
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace Flotsam.RegionModules.AssetCache
|
||||
IConfig assetConfig = source.Configs["AssetCache"];
|
||||
if (assetConfig == null)
|
||||
{
|
||||
m_log.Warn(
|
||||
m_log.Debug(
|
||||
"[FLOTSAM ASSET CACHE]: AssetCache section missing from config (not copied config-include/FlotsamCache.ini.example? Using defaults.");
|
||||
}
|
||||
else
|
||||
|
||||
@@ -48,7 +48,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private Scene m_scene;
|
||||
private IDialogModule m_dialogModule;
|
||||
private IInventoryAccessModule m_invAccessModule;
|
||||
|
||||
/// <summary>
|
||||
@@ -89,7 +88,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
|
||||
m_invAccessModule = m_scene.RequestModuleInterface<IInventoryAccessModule>();
|
||||
}
|
||||
|
||||
@@ -102,6 +100,56 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
|
||||
#region IAttachmentsModule
|
||||
|
||||
public void CopyAttachments(IScenePresence sp, AgentData ad)
|
||||
{
|
||||
lock (sp.AttachmentsSyncLock)
|
||||
{
|
||||
// Attachment objects
|
||||
List<SceneObjectGroup> attachments = sp.GetAttachments();
|
||||
if (attachments.Count > 0)
|
||||
{
|
||||
ad.AttachmentObjects = new List<ISceneObject>();
|
||||
ad.AttachmentObjectStates = new List<string>();
|
||||
// IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
|
||||
sp.InTransitScriptStates.Clear();
|
||||
|
||||
foreach (SceneObjectGroup sog in attachments)
|
||||
{
|
||||
// We need to make a copy and pass that copy
|
||||
// because of transfers withn the same sim
|
||||
ISceneObject clone = sog.CloneForNewScene();
|
||||
// Attachment module assumes that GroupPosition holds the offsets...!
|
||||
((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos;
|
||||
((SceneObjectGroup)clone).IsAttachment = false;
|
||||
ad.AttachmentObjects.Add(clone);
|
||||
string state = sog.GetStateSnapshot();
|
||||
ad.AttachmentObjectStates.Add(state);
|
||||
sp.InTransitScriptStates.Add(state);
|
||||
// Let's remove the scripts of the original object here
|
||||
sog.RemoveScriptInstances(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyAttachments(AgentData ad, IScenePresence sp)
|
||||
{
|
||||
if (ad.AttachmentObjects != null && ad.AttachmentObjects.Count > 0)
|
||||
{
|
||||
lock (sp.AttachmentsSyncLock)
|
||||
sp.ClearAttachments();
|
||||
|
||||
int i = 0;
|
||||
foreach (ISceneObject so in ad.AttachmentObjects)
|
||||
{
|
||||
((SceneObjectGroup)so).LocalId = 0;
|
||||
((SceneObjectGroup)so).RootPart.ClearUpdateSchedule();
|
||||
so.SetState(ad.AttachmentObjectStates[i++], m_scene);
|
||||
m_scene.IncomingCreateObject(Vector3.Zero, so);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RezAttachments. This should only be called upon login on the first region.
|
||||
/// Attachment rezzings on crossings and TPs are done in a different way.
|
||||
@@ -154,31 +202,44 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveChangedAttachments(IScenePresence sp, bool saveAllScripted)
|
||||
public void DeRezAttachments(IScenePresence sp, bool saveChanged, bool saveAllScripted)
|
||||
{
|
||||
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
|
||||
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
foreach (SceneObjectGroup grp in sp.GetAttachments())
|
||||
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
|
||||
|
||||
lock (sp.AttachmentsSyncLock)
|
||||
{
|
||||
grp.IsAttachment = false;
|
||||
grp.AbsolutePosition = grp.RootPart.AttachedPos;
|
||||
UpdateKnownItem(sp, grp, saveAllScripted);
|
||||
grp.IsAttachment = true;
|
||||
foreach (SceneObjectGroup so in sp.GetAttachments())
|
||||
{
|
||||
// We can only remove the script instances from the script engine after we've retrieved their xml state
|
||||
// when we update the attachment item.
|
||||
m_scene.DeleteSceneObject(so, false, false);
|
||||
|
||||
if (saveChanged || saveAllScripted)
|
||||
{
|
||||
so.IsAttachment = false;
|
||||
so.AbsolutePosition = so.RootPart.AttachedPos;
|
||||
UpdateKnownItem(sp, so, saveAllScripted);
|
||||
}
|
||||
|
||||
so.RemoveScriptInstances(true);
|
||||
}
|
||||
|
||||
sp.ClearAttachments();
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
|
||||
// m_scene.RegionInfo.RegionName, sp.Name, silent);
|
||||
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
|
||||
// m_scene.RegionInfo.RegionName, sp.Name, silent);
|
||||
|
||||
foreach (SceneObjectGroup sop in sp.GetAttachments())
|
||||
{
|
||||
sop.Scene.DeleteSceneObject(sop, silent);
|
||||
@@ -194,6 +255,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
|
||||
// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
|
||||
|
||||
if (group.GetSittingAvatarsCount() != 0)
|
||||
{
|
||||
// m_log.WarnFormat(
|
||||
// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it",
|
||||
// group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sp.GetAttachments(attachmentPt).Contains(group))
|
||||
{
|
||||
@@ -235,33 +305,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
|
||||
group.AttachmentPoint = attachmentPt;
|
||||
group.AbsolutePosition = attachPos;
|
||||
|
||||
// We also don't want to do any of the inventory operations for an NPC.
|
||||
|
||||
if (sp.PresenceType != PresenceType.Npc)
|
||||
{
|
||||
// Remove any previous attachments
|
||||
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
|
||||
|
||||
// At the moment we can only deal with a single attachment
|
||||
if (attachments.Count != 0)
|
||||
{
|
||||
UUID oldAttachmentItemID = attachments[0].FromItemID;
|
||||
|
||||
if (oldAttachmentItemID != UUID.Zero)
|
||||
DetachSingleAttachmentToInvInternal(sp, oldAttachmentItemID);
|
||||
else
|
||||
m_log.WarnFormat(
|
||||
"[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
|
||||
attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
|
||||
}
|
||||
|
||||
// Add the new attachment to inventory if we don't already have it.
|
||||
UUID newAttachmentItemID = group.FromItemID;
|
||||
if (newAttachmentItemID == UUID.Zero)
|
||||
newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
|
||||
|
||||
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
|
||||
}
|
||||
UpdateUserInventoryWithAttachment(sp, group, attachmentPt);
|
||||
|
||||
AttachToAgent(sp, group, attachmentPt, attachPos, silent);
|
||||
}
|
||||
@@ -269,7 +315,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
return true;
|
||||
}
|
||||
|
||||
public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
|
||||
private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt)
|
||||
{
|
||||
// Remove any previous attachments
|
||||
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
|
||||
|
||||
// At the moment we can only deal with a single attachment
|
||||
if (attachments.Count != 0)
|
||||
{
|
||||
if (attachments[0].FromItemID != UUID.Zero)
|
||||
DetachSingleAttachmentToInvInternal(sp, attachments[0]);
|
||||
else
|
||||
m_log.WarnFormat(
|
||||
"[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
|
||||
attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
|
||||
}
|
||||
|
||||
// Add the new attachment to inventory if we don't already have it.
|
||||
UUID newAttachmentItemID = group.FromItemID;
|
||||
if (newAttachmentItemID == UUID.Zero)
|
||||
newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
|
||||
|
||||
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
|
||||
}
|
||||
|
||||
public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
|
||||
{
|
||||
if (!Enabled)
|
||||
return null;
|
||||
@@ -308,12 +378,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
return null;
|
||||
}
|
||||
|
||||
SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt);
|
||||
|
||||
if (att == null)
|
||||
DetachSingleAttachmentToInv(sp, itemID);
|
||||
|
||||
return att;
|
||||
return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt);
|
||||
}
|
||||
|
||||
public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
|
||||
@@ -390,18 +455,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
|
||||
}
|
||||
|
||||
public void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID)
|
||||
public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so)
|
||||
{
|
||||
lock (sp.AttachmentsSyncLock)
|
||||
{
|
||||
// Save avatar attachment information
|
||||
// m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID);
|
||||
|
||||
bool changed = sp.Appearance.DetachAttachment(itemID);
|
||||
if (so.AttachedAvatar != sp.UUID)
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[ATTACHMENTS MODULE]: Tried to detach object {0} from {1} {2} but attached avatar id was {3} in {4}",
|
||||
so.Name, sp.Name, sp.UUID, so.AttachedAvatar, m_scene.RegionInfo.RegionName);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool changed = sp.Appearance.DetachAttachment(so.FromItemID);
|
||||
if (changed && m_scene.AvatarFactory != null)
|
||||
m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
|
||||
|
||||
DetachSingleAttachmentToInvInternal(sp, itemID);
|
||||
DetachSingleAttachmentToInvInternal(sp, so);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,17 +484,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
// First we save the
|
||||
// attachment point information, then we update the relative
|
||||
// positioning. Then we have to mark the object as NOT an
|
||||
// attachment. This is necessary in order to correctly save
|
||||
// and retrieve GroupPosition information for the attachment.
|
||||
// Finally, we restore the object's attachment status.
|
||||
uint attachmentPoint = sog.AttachmentPoint;
|
||||
sog.UpdateGroupPosition(pos);
|
||||
sog.IsAttachment = false;
|
||||
sog.AbsolutePosition = sog.RootPart.AttachedPos;
|
||||
sog.AttachmentPoint = attachmentPoint;
|
||||
sog.HasGroupChanged = true;
|
||||
}
|
||||
|
||||
@@ -463,6 +527,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
/// </remarks>
|
||||
/// <param name="sp"></param>
|
||||
/// <param name="grp"></param>
|
||||
/// <param name="saveAllScripted"></param>
|
||||
private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, bool saveAllScripted)
|
||||
{
|
||||
// Saving attachments for NPCs messes them up for the real owner!
|
||||
@@ -502,10 +567,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
|
||||
m_scene.InventoryService.UpdateItem(item);
|
||||
|
||||
// this gets called when the agent logs off!
|
||||
// If the name of the object has been changed whilst attached then we want to update the inventory
|
||||
// item in the viewer.
|
||||
if (sp.ControllingClient != null)
|
||||
sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
|
||||
}
|
||||
|
||||
grp.HasGroupChanged = false; // Prevent it being saved over and over
|
||||
}
|
||||
// else
|
||||
@@ -564,6 +631,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
{
|
||||
m_scene.SendKillObject(new List<uint> { so.RootPart.LocalId });
|
||||
}
|
||||
else if (so.HasPrivateAttachmentPoint)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}",
|
||||
// so.Name, sp.Name, so.AttachmentPoint);
|
||||
|
||||
// As this scene object can now only be seen by the attaching avatar, tell everybody else in the
|
||||
// scene that it's no longer in their awareness.
|
||||
m_scene.ForEachClient(
|
||||
client =>
|
||||
{ if (client.AgentId != so.AttachedAvatar)
|
||||
client.SendKillObject(m_scene.RegionInfo.RegionHandle, new List<uint>() { so.LocalId });
|
||||
});
|
||||
}
|
||||
|
||||
so.IsSelected = false; // fudge....
|
||||
so.ScheduleGroupForFullUpdate();
|
||||
@@ -589,11 +670,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
// "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
|
||||
// grp.Name, grp.LocalId, remoteClient.Name);
|
||||
|
||||
InventoryItemBase newItem = m_invAccessModule.CopyToInventory(
|
||||
DeRezAction.TakeCopy,
|
||||
m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object).ID,
|
||||
new List<SceneObjectGroup> { grp },
|
||||
sp.ControllingClient, true)[0];
|
||||
InventoryItemBase newItem
|
||||
= m_invAccessModule.CopyToInventory(
|
||||
DeRezAction.TakeCopy,
|
||||
m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object).ID,
|
||||
new List<SceneObjectGroup> { grp },
|
||||
sp.ControllingClient, true)[0];
|
||||
|
||||
// sets itemID so client can show item as 'attached' in inventory
|
||||
grp.FromItemID = newItem.ID;
|
||||
@@ -601,46 +683,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
return newItem;
|
||||
}
|
||||
|
||||
// What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards.
|
||||
// To LocalId or UUID, *THAT* is the question. How now Brown UUID??
|
||||
private void DetachSingleAttachmentToInvInternal(IScenePresence sp, UUID itemID)
|
||||
private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so)
|
||||
{
|
||||
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name);
|
||||
|
||||
if (itemID == UUID.Zero) // If this happened, someone made a mistake....
|
||||
return;
|
||||
m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero);
|
||||
sp.RemoveAttachment(so);
|
||||
|
||||
// We can NOT use the dictionries here, as we are looking
|
||||
// for an entity by the fromAssetID, which is NOT the prim UUID
|
||||
EntityBase[] detachEntities = m_scene.GetEntities();
|
||||
SceneObjectGroup group;
|
||||
// We can only remove the script instances from the script engine after we've retrieved their xml state
|
||||
// when we update the attachment item.
|
||||
m_scene.DeleteSceneObject(so, false, false);
|
||||
|
||||
lock (sp.AttachmentsSyncLock)
|
||||
{
|
||||
foreach (EntityBase entity in detachEntities)
|
||||
{
|
||||
if (entity is SceneObjectGroup)
|
||||
{
|
||||
group = (SceneObjectGroup)entity;
|
||||
if (group.FromItemID == itemID)
|
||||
{
|
||||
m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
|
||||
sp.RemoveAttachment(group);
|
||||
// Prepare sog for storage
|
||||
so.AttachedAvatar = UUID.Zero;
|
||||
so.RootPart.SetParentLocalId(0);
|
||||
so.IsAttachment = false;
|
||||
so.AbsolutePosition = so.RootPart.AttachedPos;
|
||||
|
||||
// Prepare sog for storage
|
||||
group.AttachedAvatar = UUID.Zero;
|
||||
group.RootPart.SetParentLocalId(0);
|
||||
group.IsAttachment = false;
|
||||
group.AbsolutePosition = group.RootPart.AttachedPos;
|
||||
|
||||
UpdateKnownItem(sp, group, true);
|
||||
m_scene.DeleteSceneObject(group, false);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateKnownItem(sp, so, true);
|
||||
so.RemoveScriptInstances(true);
|
||||
}
|
||||
|
||||
private SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
|
||||
@@ -662,18 +723,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
|
||||
false, false, sp.UUID, true);
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
|
||||
// objatt.Name, remoteClient.Name, AttachmentPt);
|
||||
|
||||
if (objatt != null)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}",
|
||||
// objatt.Name, sp.Name, attachmentPt, m_scene.Name);
|
||||
|
||||
// HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
|
||||
objatt.HasGroupChanged = false;
|
||||
bool tainted = false;
|
||||
if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
|
||||
tainted = true;
|
||||
|
||||
// FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal
|
||||
// course of events. If not, then it's probably not worth trying to recover the situation
|
||||
// since this is more likely to trigger further exceptions and confuse later debugging. If
|
||||
// exceptions can be thrown in expected error conditions (not NREs) then make this consistent
|
||||
// since other normal error conditions will simply return false instead.
|
||||
// This will throw if the attachment fails
|
||||
try
|
||||
{
|
||||
@@ -744,7 +810,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
item = m_scene.InventoryService.GetItem(item);
|
||||
bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
|
||||
if (changed && m_scene.AvatarFactory != null)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()",
|
||||
// sp.Name, att.Name, AttachmentPt);
|
||||
|
||||
m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -848,8 +920,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
|
||||
ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
|
||||
SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
|
||||
|
||||
if (sp != null && group != null)
|
||||
DetachSingleAttachmentToInv(sp, group.FromItemID);
|
||||
DetachSingleAttachmentToInv(sp, group);
|
||||
}
|
||||
|
||||
private void Client_OnDetachAttachmentIntoInv(UUID itemID, IClientAPI remoteClient)
|
||||
@@ -859,7 +932,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
|
||||
ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
|
||||
if (sp != null)
|
||||
DetachSingleAttachmentToInv(sp, itemID);
|
||||
{
|
||||
lock (sp.AttachmentsSyncLock)
|
||||
{
|
||||
List<SceneObjectGroup> attachments = sp.GetAttachments();
|
||||
|
||||
foreach (SceneObjectGroup group in attachments)
|
||||
{
|
||||
if (group.FromItemID == itemID)
|
||||
{
|
||||
DetachSingleAttachmentToInv(sp, group);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Client_OnObjectDrop(uint soLocalId, IClientAPI remoteClient)
|
||||
|
||||
@@ -31,6 +31,7 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Timers;
|
||||
using System.Xml;
|
||||
using Timer=System.Timers.Timer;
|
||||
using Nini.Config;
|
||||
using NUnit.Framework;
|
||||
@@ -38,11 +39,16 @@ using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Communications;
|
||||
using OpenSim.Region.CoreModules.Avatar.Attachments;
|
||||
using OpenSim.Region.CoreModules.Framework;
|
||||
using OpenSim.Region.CoreModules.Framework.EntityTransfer;
|
||||
using OpenSim.Region.CoreModules.Framework.InventoryAccess;
|
||||
using OpenSim.Region.CoreModules.World.Serialiser;
|
||||
using OpenSim.Region.CoreModules.Scripting.WorldComm;
|
||||
using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
|
||||
using OpenSim.Region.CoreModules.World.Serialiser;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.ScriptEngine.XEngine;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using OpenSim.Tests.Common;
|
||||
using OpenSim.Tests.Common.Mock;
|
||||
|
||||
@@ -52,11 +58,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
/// Attachment tests
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class AttachmentsModuleTests
|
||||
public class AttachmentsModuleTests : OpenSimTestCase
|
||||
{
|
||||
private Scene scene;
|
||||
private AttachmentsModule m_attMod;
|
||||
private ScenePresence m_presence;
|
||||
private AutoResetEvent m_chatEvent = new AutoResetEvent(false);
|
||||
private OSChatMessage m_osChatMessageReceived;
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void FixtureInit()
|
||||
@@ -65,18 +70,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
Util.FireAndForgetMethod = FireAndForgetMethod.None;
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Init()
|
||||
{
|
||||
IConfigSource config = new IniConfigSource();
|
||||
config.AddConfig("Modules");
|
||||
config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
|
||||
|
||||
scene = new SceneHelpers().SetupScene();
|
||||
m_attMod = new AttachmentsModule();
|
||||
SceneHelpers.SetupSceneModules(scene, config, m_attMod, new BasicInventoryAccessModule());
|
||||
}
|
||||
|
||||
[TestFixtureTearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
@@ -85,14 +78,100 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add the standard presence for a test.
|
||||
/// </summary>
|
||||
private void AddPresence()
|
||||
private void OnChatFromWorld(object sender, OSChatMessage oscm)
|
||||
{
|
||||
UUID userId = TestHelpers.ParseTail(0x1);
|
||||
UserAccountHelpers.CreateUserWithInventory(scene, userId);
|
||||
m_presence = SceneHelpers.AddScenePresence(scene, userId);
|
||||
// Console.WriteLine("Got chat [{0}]", oscm.Message);
|
||||
|
||||
m_osChatMessageReceived = oscm;
|
||||
m_chatEvent.Set();
|
||||
}
|
||||
|
||||
private Scene CreateTestScene()
|
||||
{
|
||||
IConfigSource config = new IniConfigSource();
|
||||
List<object> modules = new List<object>();
|
||||
|
||||
AddCommonConfig(config, modules);
|
||||
|
||||
Scene scene
|
||||
= new SceneHelpers().SetupScene(
|
||||
"attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config);
|
||||
SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
private Scene CreateScriptingEnabledTestScene()
|
||||
{
|
||||
IConfigSource config = new IniConfigSource();
|
||||
List<object> modules = new List<object>();
|
||||
|
||||
AddCommonConfig(config, modules);
|
||||
AddScriptingConfig(config, modules);
|
||||
|
||||
Scene scene
|
||||
= new SceneHelpers().SetupScene(
|
||||
"attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config);
|
||||
SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
|
||||
|
||||
scene.StartScripts();
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
private void AddCommonConfig(IConfigSource config, List<object> modules)
|
||||
{
|
||||
config.AddConfig("Modules");
|
||||
config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
|
||||
|
||||
modules.Add(new AttachmentsModule());
|
||||
modules.Add(new BasicInventoryAccessModule());
|
||||
}
|
||||
|
||||
private void AddScriptingConfig(IConfigSource config, List<object> modules)
|
||||
{
|
||||
IConfig startupConfig = config.AddConfig("Startup");
|
||||
startupConfig.Set("DefaultScriptEngine", "XEngine");
|
||||
|
||||
IConfig xEngineConfig = config.AddConfig("XEngine");
|
||||
xEngineConfig.Set("Enabled", "true");
|
||||
xEngineConfig.Set("StartDelay", "0");
|
||||
|
||||
// These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call
|
||||
// to AssemblyResolver.OnAssemblyResolve fails.
|
||||
xEngineConfig.Set("AppDomainLoading", "false");
|
||||
|
||||
modules.Add(new XEngine());
|
||||
|
||||
// Necessary to stop serialization complaining
|
||||
// FIXME: Stop this being necessary if at all possible
|
||||
// modules.Add(new WorldCommModule());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an attachment item in the given user's inventory. Does not attach.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A user with the given ID and an inventory must already exist.
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// The attachment item.
|
||||
/// </returns>
|
||||
/// <param name='scene'></param>
|
||||
/// <param name='userId'></param>
|
||||
/// <param name='attName'></param>
|
||||
/// <param name='rawItemId'></param>
|
||||
/// <param name='rawAssetId'></param>
|
||||
private InventoryItemBase CreateAttachmentItem(
|
||||
Scene scene, UUID userId, string attName, int rawItemId, int rawAssetId)
|
||||
{
|
||||
return UserInventoryHelpers.CreateInventoryItem(
|
||||
scene,
|
||||
attName,
|
||||
TestHelpers.ParseTail(rawItemId),
|
||||
TestHelpers.ParseTail(rawAssetId),
|
||||
userId,
|
||||
InventoryType.Object);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -101,16 +180,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
AddPresence();
|
||||
Scene scene = CreateTestScene();
|
||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
|
||||
|
||||
string attName = "att";
|
||||
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, m_presence.UUID).ParentGroup;
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
|
||||
|
||||
m_attMod.AttachObject(m_presence, so, (uint)AttachmentPoint.Chest, false);
|
||||
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false);
|
||||
|
||||
// Check status on scene presence
|
||||
Assert.That(m_presence.HasAttachments(), Is.True);
|
||||
List<SceneObjectGroup> attachments = m_presence.GetAttachments();
|
||||
Assert.That(sp.HasAttachments(), Is.True);
|
||||
List<SceneObjectGroup> attachments = sp.GetAttachments();
|
||||
Assert.That(attachments.Count, Is.EqualTo(1));
|
||||
SceneObjectGroup attSo = attachments[0];
|
||||
Assert.That(attSo.Name, Is.EqualTo(attName));
|
||||
@@ -121,51 +203,107 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
|
||||
// Check item status
|
||||
Assert.That(
|
||||
m_presence.Appearance.GetAttachpoint(attSo.FromItemID),
|
||||
sp.Appearance.GetAttachpoint(attSo.FromItemID),
|
||||
Is.EqualTo((int)AttachmentPoint.Chest));
|
||||
|
||||
InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
|
||||
Assert.That(attachmentItem, Is.Not.Null);
|
||||
Assert.That(attachmentItem.Name, Is.EqualTo(attName));
|
||||
|
||||
InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(m_presence.UUID, AssetType.Object);
|
||||
InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
|
||||
Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
|
||||
|
||||
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
||||
|
||||
// TestHelpers.DisableLogging();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that we do not attempt to attach an in-world object that someone else is sitting on.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAddAttachmentFromInventory()
|
||||
public void TestAddSatOnAttachmentFromGround()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
Scene scene = CreateTestScene();
|
||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
|
||||
|
||||
string attName = "att";
|
||||
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
|
||||
|
||||
UserAccount ua2 = UserAccountHelpers.CreateUserWithInventory(scene, 0x2);
|
||||
ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, ua2);
|
||||
|
||||
// Put avatar within 10m of the prim so that sit doesn't fail.
|
||||
sp2.AbsolutePosition = new Vector3(0, 0, 0);
|
||||
sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
|
||||
|
||||
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false);
|
||||
|
||||
Assert.That(sp.HasAttachments(), Is.False);
|
||||
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRezAttachmentFromInventory()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
AddPresence();
|
||||
Scene scene = CreateTestScene();
|
||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
|
||||
|
||||
UUID attItemId = TestHelpers.ParseTail(0x2);
|
||||
UUID attAssetId = TestHelpers.ParseTail(0x3);
|
||||
string attName = "att";
|
||||
InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
|
||||
|
||||
UserInventoryHelpers.CreateInventoryItem(
|
||||
scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object);
|
||||
|
||||
m_attMod.RezSingleAttachmentFromInventory(
|
||||
m_presence, attItemId, (uint)AttachmentPoint.Chest);
|
||||
scene.AttachmentsModule.RezSingleAttachmentFromInventory(
|
||||
sp, attItem.ID, (uint)AttachmentPoint.Chest);
|
||||
|
||||
// Check scene presence status
|
||||
Assert.That(m_presence.HasAttachments(), Is.True);
|
||||
List<SceneObjectGroup> attachments = m_presence.GetAttachments();
|
||||
Assert.That(sp.HasAttachments(), Is.True);
|
||||
List<SceneObjectGroup> attachments = sp.GetAttachments();
|
||||
Assert.That(attachments.Count, Is.EqualTo(1));
|
||||
SceneObjectGroup attSo = attachments[0];
|
||||
Assert.That(attSo.Name, Is.EqualTo(attName));
|
||||
Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
|
||||
Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
|
||||
Assert.That(attSo.IsAttachment);
|
||||
Assert.That(attSo.UsesPhysics, Is.False);
|
||||
Assert.That(attSo.IsTemporary, Is.False);
|
||||
|
||||
// Check appearance status
|
||||
Assert.That(m_presence.Appearance.GetAttachments().Count, Is.EqualTo(1));
|
||||
Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest));
|
||||
Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
|
||||
Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
|
||||
|
||||
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test specific conditions associated with rezzing a scripted attachment from inventory.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRezScriptedAttachmentFromInventory()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
Scene scene = CreateTestScene();
|
||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
|
||||
|
||||
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
|
||||
TaskInventoryHelpers.AddScript(scene, so.RootPart);
|
||||
InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
|
||||
|
||||
scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
|
||||
|
||||
// TODO: Need to have a test that checks the script is actually started but this involves a lot more
|
||||
// plumbing of the script engine and either pausing for events or more infrastructure to turn off various
|
||||
// script engine delays/asychronicity that isn't helpful in an automated regression testing context.
|
||||
SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name);
|
||||
Assert.That(attSo.ContainsScripts(), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -174,29 +312,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
AddPresence();
|
||||
Scene scene = CreateTestScene();
|
||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
|
||||
|
||||
UUID attItemId = TestHelpers.ParseTail(0x2);
|
||||
UUID attAssetId = TestHelpers.ParseTail(0x3);
|
||||
string attName = "att";
|
||||
InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
|
||||
|
||||
UserInventoryHelpers.CreateInventoryItem(
|
||||
scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object);
|
||||
|
||||
ISceneEntity so = m_attMod.RezSingleAttachmentFromInventory(
|
||||
m_presence, attItemId, (uint)AttachmentPoint.Chest);
|
||||
m_attMod.DetachSingleAttachmentToGround(m_presence, so.LocalId);
|
||||
ISceneEntity so
|
||||
= scene.AttachmentsModule.RezSingleAttachmentFromInventory(
|
||||
sp, attItem.ID, (uint)AttachmentPoint.Chest);
|
||||
scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId);
|
||||
|
||||
// Check scene presence status
|
||||
Assert.That(m_presence.HasAttachments(), Is.False);
|
||||
List<SceneObjectGroup> attachments = m_presence.GetAttachments();
|
||||
Assert.That(sp.HasAttachments(), Is.False);
|
||||
List<SceneObjectGroup> attachments = sp.GetAttachments();
|
||||
Assert.That(attachments.Count, Is.EqualTo(0));
|
||||
|
||||
// Check appearance status
|
||||
Assert.That(m_presence.Appearance.GetAttachments().Count, Is.EqualTo(0));
|
||||
Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(0));
|
||||
|
||||
// Check item status
|
||||
Assert.That(scene.InventoryService.GetItem(new InventoryItemBase(attItemId)), Is.Null);
|
||||
Assert.That(scene.InventoryService.GetItem(new InventoryItemBase(attItem.ID)), Is.Null);
|
||||
|
||||
// Check object in scene
|
||||
Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null);
|
||||
@@ -206,28 +342,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
public void TestDetachAttachmentToInventory()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
AddPresence();
|
||||
Scene scene = CreateTestScene();
|
||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
|
||||
|
||||
UUID attItemId = TestHelpers.ParseTail(0x2);
|
||||
UUID attAssetId = TestHelpers.ParseTail(0x3);
|
||||
string attName = "att";
|
||||
InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
|
||||
|
||||
UserInventoryHelpers.CreateInventoryItem(
|
||||
scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object);
|
||||
|
||||
m_attMod.RezSingleAttachmentFromInventory(
|
||||
m_presence, attItemId, (uint)AttachmentPoint.Chest);
|
||||
m_attMod.DetachSingleAttachmentToInv(m_presence, attItemId);
|
||||
SceneObjectGroup so
|
||||
= (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(
|
||||
sp, attItem.ID, (uint)AttachmentPoint.Chest);
|
||||
scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so);
|
||||
|
||||
// Check status on scene presence
|
||||
Assert.That(m_presence.HasAttachments(), Is.False);
|
||||
List<SceneObjectGroup> attachments = m_presence.GetAttachments();
|
||||
Assert.That(sp.HasAttachments(), Is.False);
|
||||
List<SceneObjectGroup> attachments = sp.GetAttachments();
|
||||
Assert.That(attachments.Count, Is.EqualTo(0));
|
||||
|
||||
// Check item status
|
||||
Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0));
|
||||
Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0));
|
||||
|
||||
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test specific conditions associated with detaching a scripted attachment from inventory.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestDetachScriptedAttachmentToInventory()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
Scene scene = CreateScriptingEnabledTestScene();
|
||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
|
||||
|
||||
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
|
||||
TaskInventoryHelpers.AddScript(scene, so.RootPart);
|
||||
InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
|
||||
|
||||
// FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running.
|
||||
// In the future, we need to be able to do this programatically more predicably.
|
||||
scene.EventManager.OnChatFromWorld += OnChatFromWorld;
|
||||
|
||||
SceneObjectGroup soRezzed
|
||||
= scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
|
||||
|
||||
// Wait for chat to signal rezzed script has been started.
|
||||
m_chatEvent.WaitOne(60000);
|
||||
|
||||
scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, soRezzed);
|
||||
|
||||
InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem);
|
||||
AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString());
|
||||
|
||||
XmlDocument soXml = new XmlDocument();
|
||||
soXml.LoadXml(Encoding.UTF8.GetString(asset.Data));
|
||||
|
||||
XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState");
|
||||
Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -239,17 +413,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
UUID userId = TestHelpers.ParseTail(0x1);
|
||||
UUID attItemId = TestHelpers.ParseTail(0x2);
|
||||
UUID attAssetId = TestHelpers.ParseTail(0x3);
|
||||
string attName = "att";
|
||||
Scene scene = CreateTestScene();
|
||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||
InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
|
||||
|
||||
UserAccountHelpers.CreateUserWithInventory(scene, userId);
|
||||
InventoryItemBase attItem
|
||||
= UserInventoryHelpers.CreateInventoryItem(
|
||||
scene, attName, attItemId, attAssetId, userId, InventoryType.Object);
|
||||
|
||||
AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
|
||||
AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
|
||||
acd.Appearance = new AvatarAppearance();
|
||||
acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
|
||||
ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
|
||||
@@ -268,17 +436,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
UUID userId = TestHelpers.ParseTail(0x1);
|
||||
UUID attItemId = TestHelpers.ParseTail(0x2);
|
||||
UUID attAssetId = TestHelpers.ParseTail(0x3);
|
||||
string attName = "att";
|
||||
Scene scene = CreateTestScene();
|
||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||
InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
|
||||
|
||||
UserAccountHelpers.CreateUserWithInventory(scene, userId);
|
||||
InventoryItemBase attItem
|
||||
= UserInventoryHelpers.CreateInventoryItem(
|
||||
scene, attName, attItemId, attAssetId, userId, InventoryType.Object);
|
||||
|
||||
AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
|
||||
AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
|
||||
acd.Appearance = new AvatarAppearance();
|
||||
acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
|
||||
ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
|
||||
@@ -288,7 +450,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
|
||||
Assert.That(attachments.Count, Is.EqualTo(1));
|
||||
SceneObjectGroup attSo = attachments[0];
|
||||
Assert.That(attSo.Name, Is.EqualTo(attName));
|
||||
Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
|
||||
Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
|
||||
Assert.That(attSo.IsAttachment);
|
||||
Assert.That(attSo.UsesPhysics, Is.False);
|
||||
@@ -298,9 +460,125 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
List<AvatarAttachment> retreivedAttachments = presence.Appearance.GetAttachments();
|
||||
Assert.That(retreivedAttachments.Count, Is.EqualTo(1));
|
||||
Assert.That(retreivedAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest));
|
||||
Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItemId));
|
||||
Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attAssetId));
|
||||
Assert.That(presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest));
|
||||
Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItem.ID));
|
||||
Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attItem.AssetID));
|
||||
Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
|
||||
|
||||
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUpdateAttachmentPosition()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
Scene scene = CreateTestScene();
|
||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||
InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
|
||||
|
||||
AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
|
||||
acd.Appearance = new AvatarAppearance();
|
||||
acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
|
||||
ScenePresence sp = SceneHelpers.AddScenePresence(scene, acd);
|
||||
|
||||
SceneObjectGroup attSo = sp.GetAttachments()[0];
|
||||
|
||||
Vector3 newPosition = new Vector3(1, 2, 4);
|
||||
|
||||
scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient);
|
||||
|
||||
Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition));
|
||||
Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSameSimulatorNeighbouringRegionsTeleport()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
AttachmentsModule attModA = new AttachmentsModule();
|
||||
AttachmentsModule attModB = new AttachmentsModule();
|
||||
EntityTransferModule etmA = new EntityTransferModule();
|
||||
EntityTransferModule etmB = new EntityTransferModule();
|
||||
LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
|
||||
|
||||
IConfigSource config = new IniConfigSource();
|
||||
IConfig modulesConfig = config.AddConfig("Modules");
|
||||
modulesConfig.Set("EntityTransferModule", etmA.Name);
|
||||
modulesConfig.Set("SimulationServices", lscm.Name);
|
||||
IConfig entityTransferConfig = config.AddConfig("EntityTransfer");
|
||||
|
||||
// In order to run a single threaded regression test we do not want the entity transfer module waiting
|
||||
// for a callback from the destination scene before removing its avatar data.
|
||||
entityTransferConfig.Set("wait_for_callback", false);
|
||||
|
||||
modulesConfig.Set("InventoryAccessModule", "BasicInventoryAccessModule");
|
||||
|
||||
SceneHelpers sh = new SceneHelpers();
|
||||
TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
|
||||
TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000);
|
||||
|
||||
SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
|
||||
SceneHelpers.SetupSceneModules(
|
||||
sceneA, config, new CapabilitiesModule(), etmA, attModA, new BasicInventoryAccessModule());
|
||||
SceneHelpers.SetupSceneModules(
|
||||
sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
|
||||
|
||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
|
||||
ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, ua1.PrincipalID, sh.SceneManager);
|
||||
beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
|
||||
|
||||
InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
|
||||
|
||||
sceneA.AttachmentsModule.RezSingleAttachmentFromInventory(
|
||||
beforeTeleportSp, attItem.ID, (uint)AttachmentPoint.Chest);
|
||||
|
||||
Vector3 teleportPosition = new Vector3(10, 11, 12);
|
||||
Vector3 teleportLookAt = new Vector3(20, 21, 22);
|
||||
|
||||
sceneA.RequestTeleportLocation(
|
||||
beforeTeleportSp.ControllingClient,
|
||||
sceneB.RegionInfo.RegionHandle,
|
||||
teleportPosition,
|
||||
teleportLookAt,
|
||||
(uint)TeleportFlags.ViaLocation);
|
||||
|
||||
((TestClient)beforeTeleportSp.ControllingClient).CompleteTeleportClientSide();
|
||||
|
||||
// Check attachments have made it into sceneB
|
||||
ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID);
|
||||
|
||||
// This is appearance data, as opposed to actually rezzed attachments
|
||||
List<AvatarAttachment> sceneBAttachments = afterTeleportSceneBSp.Appearance.GetAttachments();
|
||||
Assert.That(sceneBAttachments.Count, Is.EqualTo(1));
|
||||
Assert.That(sceneBAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest));
|
||||
Assert.That(sceneBAttachments[0].ItemID, Is.EqualTo(attItem.ID));
|
||||
Assert.That(sceneBAttachments[0].AssetID, Is.EqualTo(attItem.AssetID));
|
||||
Assert.That(afterTeleportSceneBSp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
|
||||
|
||||
// This is the actual attachment
|
||||
List<SceneObjectGroup> actualSceneBAttachments = afterTeleportSceneBSp.GetAttachments();
|
||||
Assert.That(actualSceneBAttachments.Count, Is.EqualTo(1));
|
||||
SceneObjectGroup actualSceneBAtt = actualSceneBAttachments[0];
|
||||
Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name));
|
||||
Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest));
|
||||
|
||||
Assert.That(sceneB.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
||||
|
||||
// Check attachments have been removed from sceneA
|
||||
ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID);
|
||||
|
||||
// Since this is appearance data, it is still present on the child avatar!
|
||||
List<AvatarAttachment> sceneAAttachments = afterTeleportSceneASp.Appearance.GetAttachments();
|
||||
Assert.That(sceneAAttachments.Count, Is.EqualTo(1));
|
||||
Assert.That(afterTeleportSceneASp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
|
||||
|
||||
// This is the actual attachment, which should no longer exist
|
||||
List<SceneObjectGroup> actualSceneAAttachments = afterTeleportSceneASp.GetAttachments();
|
||||
Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0));
|
||||
|
||||
Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
// I'm commenting this test because scene setup NEEDS InventoryService to
|
||||
|
||||
@@ -128,7 +128,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||
/// <param name="visualParam"></param>
|
||||
public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams)
|
||||
{
|
||||
// m_log.InfoFormat("[AVFACTORY]: start SetAppearance for {0}", client.AgentId);
|
||||
// m_log.DebugFormat(
|
||||
// "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}",
|
||||
// sp.Name, textureEntry, visualParams);
|
||||
|
||||
// TODO: This is probably not necessary any longer, just assume the
|
||||
// textureEntry set implies that the appearance transaction is complete
|
||||
|
||||
189
OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
Normal file
189
OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using log4net;
|
||||
using Mono.Addins;
|
||||
using NDesk.Options;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Console;
|
||||
using OpenSim.Framework.Statistics;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.Avatars.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// A module that holds commands for manipulating objects in the scene.
|
||||
/// </summary>
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserCommandsModule")]
|
||||
public class UserCommandsModule : ISharedRegionModule
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public const string TeleportUserCommandSyntax = "teleport user <first-name> <last-name> <destination>";
|
||||
|
||||
public static Regex InterRegionDestinationRegex
|
||||
= new Regex(@"^(?<regionName>.+)/(?<x>\d+)/(?<y>\d+)/(?<z>\d+)$", RegexOptions.Compiled);
|
||||
|
||||
public static Regex WithinRegionDestinationRegex
|
||||
= new Regex(@"^(?<x>\d+)/(?<y>\d+)/(?<z>\d+)$", RegexOptions.Compiled);
|
||||
|
||||
private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
|
||||
|
||||
public string Name { get { return "User Commands Module"; } }
|
||||
|
||||
public Type ReplaceableInterface { get { return null; } }
|
||||
|
||||
public void Initialise(IConfigSource source)
|
||||
{
|
||||
// m_log.DebugFormat("[USER COMMANDS MODULE]: INITIALIZED MODULE");
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
{
|
||||
// m_log.DebugFormat("[USER COMMANDS MODULE]: POST INITIALIZED MODULE");
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
// m_log.DebugFormat("[USER COMMANDS MODULE]: CLOSED MODULE");
|
||||
}
|
||||
|
||||
public void AddRegion(Scene scene)
|
||||
{
|
||||
// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
|
||||
|
||||
lock (m_scenes)
|
||||
m_scenes[scene.RegionInfo.RegionID] = scene;
|
||||
|
||||
scene.AddCommand(
|
||||
"Users",
|
||||
this,
|
||||
"teleport user",
|
||||
TeleportUserCommandSyntax,
|
||||
"Teleport a user in this simulator to the given destination",
|
||||
"<destination> is in format [<region-name>]/<x>/<y>/<z>, e.g. regionone/20/30/40 or just 20/30/40 to teleport within same region."
|
||||
+ "\nIf the region contains a space then the whole destination must be in quotes, e.g. \"region one/20/30/40\"",
|
||||
HandleTeleportUser);
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
|
||||
|
||||
lock (m_scenes)
|
||||
m_scenes.Remove(scene.RegionInfo.RegionID);
|
||||
}
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
|
||||
}
|
||||
|
||||
private ScenePresence GetUser(string firstName, string lastName)
|
||||
{
|
||||
ScenePresence userFound = null;
|
||||
|
||||
lock (m_scenes)
|
||||
{
|
||||
foreach (Scene scene in m_scenes.Values)
|
||||
{
|
||||
ScenePresence user = scene.GetScenePresence(firstName, lastName);
|
||||
if (user != null && !user.IsChildAgent)
|
||||
{
|
||||
userFound = user;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return userFound;
|
||||
}
|
||||
|
||||
private void HandleTeleportUser(string module, string[] cmd)
|
||||
{
|
||||
if (cmd.Length < 5)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("Usage: " + TeleportUserCommandSyntax);
|
||||
return;
|
||||
}
|
||||
|
||||
string firstName = cmd[2];
|
||||
string lastName = cmd[3];
|
||||
string rawDestination = cmd[4];
|
||||
|
||||
ScenePresence user = GetUser(firstName, lastName);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("No user found with name {0} {1}", firstName, lastName);
|
||||
return;
|
||||
}
|
||||
|
||||
// MainConsole.Instance.OutputFormat("rawDestination [{0}]", rawDestination);
|
||||
|
||||
Match m = WithinRegionDestinationRegex.Match(rawDestination);
|
||||
|
||||
if (!m.Success)
|
||||
{
|
||||
m = InterRegionDestinationRegex.Match(rawDestination);
|
||||
|
||||
if (!m.Success)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("Invalid destination {0}", rawDestination);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
string regionName
|
||||
= m.Groups["regionName"].Success ? m.Groups["regionName"].Value : user.Scene.RegionInfo.RegionName;
|
||||
|
||||
MainConsole.Instance.OutputFormat(
|
||||
"Teleporting {0} to {1},{2},{3} in {4}",
|
||||
user.Name,
|
||||
m.Groups["x"], m.Groups["y"], m.Groups["z"],
|
||||
regionName);
|
||||
|
||||
user.Scene.RequestTeleportLocation(
|
||||
user.ControllingClient,
|
||||
regionName,
|
||||
new Vector3(
|
||||
float.Parse(m.Groups["x"].Value),
|
||||
float.Parse(m.Groups["y"].Value),
|
||||
float.Parse(m.Groups["z"].Value)),
|
||||
user.Lookat,
|
||||
(uint)TeleportFlags.ViaLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -415,12 +415,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
|
||||
protected override void StoreBackwards(UUID friendID, UUID agentID)
|
||||
{
|
||||
Boolean agentIsLocal = true;
|
||||
Boolean friendIsLocal = true;
|
||||
bool agentIsLocal = true;
|
||||
// bool friendIsLocal = true;
|
||||
|
||||
if (UserManagementModule != null)
|
||||
{
|
||||
agentIsLocal = UserManagementModule.IsLocalGridUser(agentID);
|
||||
friendIsLocal = UserManagementModule.IsLocalGridUser(friendID);
|
||||
// friendIsLocal = UserManagementModule.IsLocalGridUser(friendID);
|
||||
}
|
||||
|
||||
// Is the requester a local user?
|
||||
@@ -507,7 +508,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
{
|
||||
friendUUI = finfo.Friend;
|
||||
theFriendUUID = friendUUI;
|
||||
UUID utmp = UUID.Zero; String url = String.Empty; String first = String.Empty, last = String.Empty, tmp = String.Empty;
|
||||
UUID utmp = UUID.Zero;
|
||||
string url = String.Empty;
|
||||
string first = String.Empty;
|
||||
string last = String.Empty;
|
||||
|
||||
// If it's confirming the friendship, we already have the full UUI with the secret
|
||||
if (Util.ParseUniversalUserIdentifier(theFriendUUID, out utmp, out url, out first, out last, out secret))
|
||||
{
|
||||
|
||||
@@ -137,13 +137,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
||||
foreach (Scene scene in m_Scenes)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
|
||||
// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
|
||||
// toAgentID.ToString(), scene.RegionInfo.RegionName);
|
||||
|
||||
ScenePresence sp = scene.GetScenePresence(toAgentID);
|
||||
if (sp != null && !sp.IsChildAgent)
|
||||
{
|
||||
// Local message
|
||||
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
|
||||
m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
|
||||
|
||||
sp.ControllingClient.SendInstantMessage(im);
|
||||
|
||||
// Message sent
|
||||
@@ -155,13 +157,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
||||
// try child avatar second
|
||||
foreach (Scene scene in m_Scenes)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
|
||||
m_log.DebugFormat(
|
||||
"[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
|
||||
|
||||
ScenePresence sp = scene.GetScenePresence(toAgentID);
|
||||
if (sp != null)
|
||||
{
|
||||
// Local message
|
||||
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID);
|
||||
m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
|
||||
|
||||
sp.ControllingClient.SendInstantMessage(im);
|
||||
|
||||
// Message sent
|
||||
@@ -170,10 +174,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
||||
}
|
||||
}
|
||||
|
||||
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
|
||||
SendGridInstantMessageViaXMLRPC(im, result);
|
||||
m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
|
||||
|
||||
return;
|
||||
SendGridInstantMessageViaXMLRPC(im, result);
|
||||
}
|
||||
|
||||
private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result)
|
||||
|
||||
@@ -48,7 +48,7 @@ using OpenSim.Tests.Common.Mock;
|
||||
namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class InventoryArchiveTestCase
|
||||
public class InventoryArchiveTestCase : OpenSimTestCase
|
||||
{
|
||||
protected ManualResetEvent mre = new ManualResetEvent(false);
|
||||
|
||||
@@ -84,8 +84,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
|
||||
protected string m_coaItemName = "Coalesced Item";
|
||||
|
||||
[SetUp]
|
||||
public virtual void SetUp()
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
m_iarStream = new MemoryStream(m_iarStreamBytes);
|
||||
}
|
||||
|
||||
|
||||
@@ -297,7 +297,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
|
||||
else if (
|
||||
im.dialog == (byte)InstantMessageDialog.InventoryDeclined
|
||||
|| im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined)
|
||||
{
|
||||
// Here, the recipient is local and we can assume that the
|
||||
// inventory is loaded. Courtesy of the above bulk update,
|
||||
|
||||
@@ -57,14 +57,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
|
||||
|
||||
public void Initialise(IConfigSource config)
|
||||
{
|
||||
// This can be reduced later as the loader will determine
|
||||
// whether we are needed
|
||||
if (config.Configs["Profile"] != null)
|
||||
{
|
||||
if (config.Configs["Profile"].GetString("Module", string.Empty) != "BasicProfileModule")
|
||||
return;
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled");
|
||||
m_Enabled = true;
|
||||
}
|
||||
|
||||
@@ -46,35 +46,12 @@ using Nini.Config;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
{
|
||||
/// <summary>
|
||||
/// The possible states that an agent can be in when its being transferred between regions.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a state machine.
|
||||
///
|
||||
/// [Entry] => Preparing
|
||||
/// Preparing => { Transferring || CleaningUp || [Exit] }
|
||||
/// Transferring => { ReceivedAtDestination || CleaningUp }
|
||||
/// ReceivedAtDestination => CleaningUp
|
||||
/// CleaningUp => [Exit]
|
||||
///
|
||||
/// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp
|
||||
/// However, any state can transition to CleaningUp if the teleport has failed.
|
||||
/// </remarks>
|
||||
enum AgentTransferState
|
||||
{
|
||||
Preparing, // The agent is being prepared for transfer
|
||||
Transferring, // The agent is in the process of being transferred to a destination
|
||||
ReceivedAtDestination, // The destination has notified us that the agent has been successfully received
|
||||
CleaningUp // The agent is being changed to child/removed after a transfer
|
||||
}
|
||||
|
||||
public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public const int DefaultMaxTransferDistance = 4095;
|
||||
public const bool EnableWaitForCallbackFromTeleportDestDefault = true;
|
||||
public const bool WaitForAgentArrivedAtDestinationDefault = true;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum distance, in standard region units (256m) that an agent is allowed to transfer.
|
||||
@@ -85,13 +62,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
/// If true then on a teleport, the source region waits for a callback from the destination region. If
|
||||
/// a callback fails to arrive within a set time then the user is pulled back into the source region.
|
||||
/// </summary>
|
||||
public bool EnableWaitForCallbackFromTeleportDest { get; set; }
|
||||
public bool WaitForAgentArrivedAtDestination { get; set; }
|
||||
|
||||
protected bool m_Enabled = false;
|
||||
|
||||
protected Scene m_scene;
|
||||
public Scene Scene { get; private set; }
|
||||
|
||||
private Dictionary<UUID, AgentTransferState> m_agentsInTransit;
|
||||
/// <summary>
|
||||
/// Handles recording and manipulation of state for entities that are in transfer within or between regions
|
||||
/// (cross or teleport).
|
||||
/// </summary>
|
||||
private EntityTransferStateMachine m_entityTransferStateMachine;
|
||||
|
||||
private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
|
||||
new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
|
||||
@@ -133,8 +114,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
IConfig transferConfig = source.Configs["EntityTransfer"];
|
||||
if (transferConfig != null)
|
||||
{
|
||||
EnableWaitForCallbackFromTeleportDest
|
||||
= transferConfig.GetBoolean("wait_for_callback", EnableWaitForCallbackFromTeleportDestDefault);
|
||||
WaitForAgentArrivedAtDestination
|
||||
= transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault);
|
||||
|
||||
MaxTransferDistance = transferConfig.GetInt("max_distance", DefaultMaxTransferDistance);
|
||||
}
|
||||
@@ -143,7 +124,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
MaxTransferDistance = DefaultMaxTransferDistance;
|
||||
}
|
||||
|
||||
m_agentsInTransit = new Dictionary<UUID, AgentTransferState>();
|
||||
m_entityTransferStateMachine = new EntityTransferStateMachine(this);
|
||||
|
||||
m_Enabled = true;
|
||||
}
|
||||
|
||||
@@ -156,7 +138,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
m_scene = scene;
|
||||
Scene = scene;
|
||||
|
||||
scene.RegisterModuleInterface<IEntityTransferModule>(this);
|
||||
scene.EventManager.OnNewClient += OnNewClient;
|
||||
@@ -177,7 +159,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
m_eqModule = m_scene.RequestModuleInterface<IEventQueue>();
|
||||
m_eqModule = Scene.RequestModuleInterface<IEventQueue>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -226,7 +208,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
e.Message, e.StackTrace);
|
||||
|
||||
// Make sure that we clear the in-transit flag so that future teleport attempts don't always fail.
|
||||
ResetFromTransit(sp.UUID);
|
||||
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
|
||||
|
||||
sp.ControllingClient.SendTeleportFailed("Internal error");
|
||||
}
|
||||
@@ -245,7 +227,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
"[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}",
|
||||
sp.Name, position, sp.Scene.RegionInfo.RegionName);
|
||||
|
||||
if (!SetInTransit(sp.UUID))
|
||||
if (!m_entityTransferStateMachine.SetInTransit(sp.UUID))
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Ignoring within region teleport request of {0} {1} to {2} - agent is already in transit.",
|
||||
@@ -282,7 +264,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
position.Z = newPosZ;
|
||||
}
|
||||
|
||||
UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
|
||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
|
||||
|
||||
sp.ControllingClient.SendTeleportStart(teleportFlags);
|
||||
|
||||
@@ -290,15 +272,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
sp.Velocity = Vector3.Zero;
|
||||
sp.Teleport(position);
|
||||
|
||||
UpdateInTransit(sp.UUID, AgentTransferState.ReceivedAtDestination);
|
||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.ReceivedAtDestination);
|
||||
|
||||
foreach (SceneObjectGroup grp in sp.GetAttachments())
|
||||
{
|
||||
sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT);
|
||||
}
|
||||
|
||||
UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
|
||||
ResetFromTransit(sp.UUID);
|
||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
|
||||
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -316,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
{
|
||||
uint x = 0, y = 0;
|
||||
Utils.LongToUInts(regionHandle, out x, out y);
|
||||
GridRegion reg = m_scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);
|
||||
GridRegion reg = Scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);
|
||||
|
||||
if (reg != null)
|
||||
{
|
||||
@@ -398,7 +380,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
{
|
||||
// Record that this agent is in transit so that we can prevent simultaneous requests and do later detection
|
||||
// of whether the destination region completes the teleport.
|
||||
if (!SetInTransit(sp.UUID))
|
||||
if (!m_entityTransferStateMachine.SetInTransit(sp.UUID))
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.",
|
||||
@@ -410,7 +392,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
if (reg == null || finalDestination == null)
|
||||
{
|
||||
sp.ControllingClient.SendTeleportFailed("Unable to locate destination");
|
||||
ResetFromTransit(sp.UUID);
|
||||
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -431,7 +413,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY,
|
||||
MaxTransferDistance));
|
||||
|
||||
ResetFromTransit(sp.UUID);
|
||||
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -451,7 +433,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
if (endPoint.Address == null)
|
||||
{
|
||||
sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
|
||||
ResetFromTransit(sp.UUID);
|
||||
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -469,11 +451,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
string reason;
|
||||
string version;
|
||||
if (!m_scene.SimulationService.QueryAccess(
|
||||
if (!Scene.SimulationService.QueryAccess(
|
||||
finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason))
|
||||
{
|
||||
sp.ControllingClient.SendTeleportFailed(reason);
|
||||
ResetFromTransit(sp.UUID);
|
||||
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}",
|
||||
@@ -527,7 +509,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
|
||||
{
|
||||
sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
|
||||
ResetFromTransit(sp.UUID);
|
||||
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}",
|
||||
@@ -537,7 +519,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
}
|
||||
|
||||
// Past this point we have to attempt clean up if the teleport fails, so update transfer state.
|
||||
UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
|
||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
|
||||
|
||||
// OK, it got this agent. Let's close some child agents
|
||||
sp.CloseChildAgents(newRegionX, newRegionY);
|
||||
@@ -619,7 +601,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
// TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
|
||||
// trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
|
||||
// that the client contacted the destination before we close things here.
|
||||
if (EnableWaitForCallbackFromTeleportDest && !WaitForCallback(sp.UUID))
|
||||
if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID))
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.",
|
||||
@@ -629,7 +611,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
|
||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
|
||||
|
||||
// For backwards compatibility
|
||||
if (version == "Unknown" || version == string.Empty)
|
||||
@@ -662,7 +644,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
// an agent cannot teleport back to this region if it has teleported away.
|
||||
Thread.Sleep(2000);
|
||||
|
||||
sp.Close();
|
||||
sp.Scene.IncomingCloseAgent(sp.UUID);
|
||||
}
|
||||
else
|
||||
@@ -679,31 +660,34 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
sp.UUID);
|
||||
}
|
||||
|
||||
ResetFromTransit(sp.UUID);
|
||||
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
|
||||
}
|
||||
|
||||
protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout)
|
||||
{
|
||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
|
||||
|
||||
// Client never contacted destination. Let's restore everything back
|
||||
sp.ControllingClient.SendTeleportFailed("Problems connecting to destination.");
|
||||
|
||||
// Fail. Reset it back
|
||||
sp.IsChildAgent = false;
|
||||
ReInstantiateScripts(sp);
|
||||
ResetFromTransit(sp.UUID);
|
||||
|
||||
EnableChildAgents(sp);
|
||||
|
||||
// Finally, kill the agent we just created at the destination.
|
||||
m_scene.SimulationService.CloseAgent(finalDestination, sp.UUID);
|
||||
Scene.SimulationService.CloseAgent(finalDestination, sp.UUID);
|
||||
|
||||
sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout);
|
||||
|
||||
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
|
||||
}
|
||||
|
||||
protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout)
|
||||
{
|
||||
logout = false;
|
||||
bool success = m_scene.SimulationService.CreateAgent(finalDestination, agentCircuit, teleportFlags, out reason);
|
||||
bool success = Scene.SimulationService.CreateAgent(finalDestination, agentCircuit, teleportFlags, out reason);
|
||||
|
||||
if (success)
|
||||
sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout);
|
||||
@@ -713,7 +697,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent)
|
||||
{
|
||||
return m_scene.SimulationService.UpdateAgent(finalDestination, agent);
|
||||
return Scene.SimulationService.UpdateAgent(finalDestination, agent);
|
||||
}
|
||||
|
||||
protected virtual void SetCallbackURL(AgentData agent, RegionInfo region)
|
||||
@@ -725,6 +709,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
agent.CallbackURI, region.RegionName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean up operations once an agent has moved away through cross or teleport.
|
||||
/// </summary>
|
||||
/// <param name='sp'></param>
|
||||
/// <param name='logout'></param>
|
||||
protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout)
|
||||
{
|
||||
if (sp.Scene.AttachmentsModule != null)
|
||||
@@ -776,7 +765,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
/// <param name="position"></param>
|
||||
public virtual void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm)
|
||||
{
|
||||
GridRegion info = m_scene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
|
||||
GridRegion info = Scene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
|
||||
|
||||
if (info == null)
|
||||
{
|
||||
@@ -797,12 +786,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.Name, client.AgentId);
|
||||
|
||||
//OpenSim.Services.Interfaces.PresenceInfo pinfo = m_scene.PresenceService.GetAgent(client.SessionId);
|
||||
GridUserInfo uinfo = m_scene.GridUserService.GetGridUserInfo(client.AgentId.ToString());
|
||||
//OpenSim.Services.Interfaces.PresenceInfo pinfo = Scene.PresenceService.GetAgent(client.SessionId);
|
||||
GridUserInfo uinfo = Scene.GridUserService.GetGridUserInfo(client.AgentId.ToString());
|
||||
|
||||
if (uinfo != null)
|
||||
{
|
||||
GridRegion regionInfo = m_scene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID);
|
||||
GridRegion regionInfo = Scene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID);
|
||||
if (regionInfo == null)
|
||||
{
|
||||
// can't find the Home region: Tell viewer and abort
|
||||
@@ -1111,7 +1100,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
try
|
||||
{
|
||||
SetInTransit(agent.UUID);
|
||||
m_entityTransferStateMachine.SetInTransit(agent.UUID);
|
||||
|
||||
ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
|
||||
|
||||
@@ -1141,16 +1130,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
cAgent.CallbackURI = String.Empty;
|
||||
|
||||
// Beyond this point, extra cleanup is needed beyond removing transit state
|
||||
UpdateInTransit(agent.UUID, AgentTransferState.Transferring);
|
||||
m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring);
|
||||
|
||||
if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent))
|
||||
{
|
||||
// region doesn't take it
|
||||
UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
|
||||
m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
|
||||
|
||||
ReInstantiateScripts(agent);
|
||||
agent.AddToPhysicalScene(isFlying);
|
||||
ResetFromTransit(agent.UUID);
|
||||
m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
|
||||
|
||||
return agent;
|
||||
}
|
||||
@@ -1188,16 +1177,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
}
|
||||
|
||||
// SUCCESS!
|
||||
UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination);
|
||||
m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination);
|
||||
|
||||
// Unlike a teleport, here we do not wait for the destination region to confirm the receipt.
|
||||
UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
|
||||
m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
|
||||
|
||||
agent.MakeChildAgent();
|
||||
|
||||
// FIXME: Possibly this should occur lower down after other commands to close other agents,
|
||||
// but not sure yet what the side effects would be.
|
||||
ResetFromTransit(agent.UUID);
|
||||
m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
|
||||
|
||||
// now we have a child agent in this region. Request all interesting data about other (root) agents
|
||||
agent.SendOtherAgentsAvatarDataToMe();
|
||||
@@ -1240,7 +1229,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
return agent;
|
||||
}
|
||||
|
||||
|
||||
private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
|
||||
{
|
||||
CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
|
||||
@@ -1672,46 +1661,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Agent Arrived
|
||||
|
||||
public void AgentArrivedAtDestination(UUID id)
|
||||
{
|
||||
lock (m_agentsInTransit)
|
||||
{
|
||||
if (!m_agentsInTransit.ContainsKey(id))
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Region {0} received notification of arrival in destination scene of agent {1} but no teleport request is active",
|
||||
m_scene.RegionInfo.RegionName, id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
AgentTransferState currentState = m_agentsInTransit[id];
|
||||
|
||||
if (currentState == AgentTransferState.ReceivedAtDestination)
|
||||
{
|
||||
// An anomoly but don't make this an outright failure - destination region could be overzealous in sending notification.
|
||||
m_log.WarnFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Region {0} received notification of arrival in destination scene of agent {1} but notification has already previously been received",
|
||||
m_scene.RegionInfo.RegionName, id);
|
||||
}
|
||||
else if (currentState != AgentTransferState.Transferring)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Region {0} received notification of arrival in destination scene of agent {1} but agent is in transfer state {2}",
|
||||
m_scene.RegionInfo.RegionName, id, currentState);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_agentsInTransit[id] = AgentTransferState.ReceivedAtDestination;
|
||||
}
|
||||
m_entityTransferStateMachine.SetAgentArrivedAtDestination(id);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Object Transfers
|
||||
|
||||
/// <summary>
|
||||
/// Move the given scene object into a new region depending on which region its absolute position has moved
|
||||
/// into.
|
||||
@@ -1976,8 +1936,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
//// And the new channel...
|
||||
//if (m_interregionCommsOut != null)
|
||||
// successYN = m_interregionCommsOut.SendCreateObject(newRegionHandle, grp, true);
|
||||
if (m_scene.SimulationService != null)
|
||||
successYN = m_scene.SimulationService.CreateObject(destination, newPosition, grp, true);
|
||||
if (Scene.SimulationService != null)
|
||||
successYN = Scene.SimulationService.CreateObject(destination, newPosition, grp, true);
|
||||
|
||||
if (successYN)
|
||||
{
|
||||
@@ -2013,174 +1973,52 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
return successYN;
|
||||
}
|
||||
|
||||
protected bool CrossAttachmentsIntoNewRegion(GridRegion destination, ScenePresence sp, bool silent)
|
||||
/// <summary>
|
||||
/// Cross the attachments for an avatar into the destination region.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is only invoked for simulators released prior to April 2011. Versions of OpenSimulator since then
|
||||
/// transfer attachments in one go as part of the ChildAgentDataUpdate data passed in the update agent call.
|
||||
/// </remarks>
|
||||
/// <param name='destination'></param>
|
||||
/// <param name='sp'></param>
|
||||
/// <param name='silent'></param>
|
||||
protected void CrossAttachmentsIntoNewRegion(GridRegion destination, ScenePresence sp, bool silent)
|
||||
{
|
||||
List<SceneObjectGroup> m_attachments = sp.GetAttachments();
|
||||
List<SceneObjectGroup> attachments = sp.GetAttachments();
|
||||
|
||||
// Validate
|
||||
// foreach (SceneObjectGroup gobj in m_attachments)
|
||||
// {
|
||||
// if (gobj == null || gobj.IsDeleted)
|
||||
// return false;
|
||||
// }
|
||||
// m_log.DebugFormat(
|
||||
// "[ENTITY TRANSFER MODULE]: Crossing {0} attachments into {1} for {2}",
|
||||
// m_attachments.Count, destination.RegionName, sp.Name);
|
||||
|
||||
foreach (SceneObjectGroup gobj in m_attachments)
|
||||
foreach (SceneObjectGroup gobj in attachments)
|
||||
{
|
||||
// If the prim group is null then something must have happened to it!
|
||||
if (gobj != null && !gobj.IsDeleted)
|
||||
{
|
||||
// Set the parent localID to 0 so it transfers over properly.
|
||||
gobj.RootPart.SetParentLocalId(0);
|
||||
gobj.AbsolutePosition = gobj.RootPart.AttachedPos;
|
||||
gobj.IsAttachment = false;
|
||||
SceneObjectGroup clone = (SceneObjectGroup)gobj.CloneForNewScene();
|
||||
clone.RootPart.GroupPosition = gobj.RootPart.AttachedPos;
|
||||
clone.IsAttachment = false;
|
||||
|
||||
//gobj.RootPart.LastOwnerID = gobj.GetFromAssetID();
|
||||
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}", gobj.UUID, destination.RegionName);
|
||||
CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, gobj, silent);
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}",
|
||||
clone.UUID, destination.RegionName);
|
||||
|
||||
CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, clone, silent);
|
||||
}
|
||||
}
|
||||
|
||||
sp.ClearAttachments();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Misc
|
||||
|
||||
private bool WaitForCallback(UUID id)
|
||||
{
|
||||
lock (m_agentsInTransit)
|
||||
{
|
||||
if (!IsInTransit(id))
|
||||
throw new Exception(
|
||||
string.Format(
|
||||
"Asked to wait for destination callback for agent with ID {0} but it is not in transit"));
|
||||
|
||||
AgentTransferState currentState = m_agentsInTransit[id];
|
||||
|
||||
if (currentState != AgentTransferState.Transferring && currentState != AgentTransferState.ReceivedAtDestination)
|
||||
throw new Exception(
|
||||
string.Format(
|
||||
"Asked to wait for destination callback for agent with ID {0} but it is in state {1}",
|
||||
currentState));
|
||||
}
|
||||
|
||||
int count = 200;
|
||||
|
||||
// There should be no race condition here since no other code should be removing the agent transfer or
|
||||
// changing the state to another other than Transferring => ReceivedAtDestination.
|
||||
while (m_agentsInTransit[id] != AgentTransferState.ReceivedAtDestination && count-- > 0)
|
||||
{
|
||||
// m_log.Debug(" >>> Waiting... " + count);
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set that an agent is in transit.
|
||||
/// </summary>
|
||||
/// <param name='id'>The ID of the agent being teleported</param>
|
||||
/// <returns>true if the agent was not already in transit, false if it was</returns>
|
||||
private bool SetInTransit(UUID id)
|
||||
{
|
||||
lock (m_agentsInTransit)
|
||||
{
|
||||
if (!m_agentsInTransit.ContainsKey(id))
|
||||
{
|
||||
m_agentsInTransit[id] = AgentTransferState.Preparing;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the state of an agent that is already in transit.
|
||||
/// </summary>
|
||||
/// <param name='id'></param>
|
||||
/// <param name='newState'></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
|
||||
private void UpdateInTransit(UUID id, AgentTransferState newState)
|
||||
{
|
||||
lock (m_agentsInTransit)
|
||||
{
|
||||
// Illegal to try and update an agent that's not actually in transit.
|
||||
if (!m_agentsInTransit.ContainsKey(id))
|
||||
throw new Exception(string.Format("Agent with ID {0} is not registered as in transit", id));
|
||||
|
||||
AgentTransferState oldState = m_agentsInTransit[id];
|
||||
|
||||
bool transitionOkay = false;
|
||||
|
||||
if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp)
|
||||
transitionOkay = true;
|
||||
else if (newState == AgentTransferState.Transferring && oldState == AgentTransferState.Preparing)
|
||||
transitionOkay = true;
|
||||
else if (newState == AgentTransferState.ReceivedAtDestination && oldState == AgentTransferState.Transferring)
|
||||
transitionOkay = true;
|
||||
|
||||
if (transitionOkay)
|
||||
m_agentsInTransit[id] = newState;
|
||||
else
|
||||
throw new Exception(
|
||||
string.Format(
|
||||
"Agent with ID {0} is not allowed to move from old transit state {1} to new state {2}",
|
||||
id, oldState, newState));
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsInTransit(UUID id)
|
||||
{
|
||||
lock (m_agentsInTransit)
|
||||
return m_agentsInTransit.ContainsKey(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an agent from the transit state machine.
|
||||
/// </summary>
|
||||
/// <param name='id'></param>
|
||||
/// <returns>true if the agent was flagged as being teleported when this method was called, false otherwise</returns>
|
||||
private bool ResetFromTransit(UUID id)
|
||||
{
|
||||
lock (m_agentsInTransit)
|
||||
{
|
||||
if (m_agentsInTransit.ContainsKey(id))
|
||||
{
|
||||
AgentTransferState state = m_agentsInTransit[id];
|
||||
|
||||
if (state == AgentTransferState.Transferring || state == AgentTransferState.ReceivedAtDestination)
|
||||
{
|
||||
// FIXME: For now, we allow exit from any state since a thrown exception in teleport is now guranteed
|
||||
// to be handled properly - ResetFromTransit() could be invoked at any step along the process
|
||||
m_log.WarnFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Agent with ID should not exit directly from state {1}, should go to {2} state first",
|
||||
state, AgentTransferState.CleaningUp);
|
||||
|
||||
// throw new Exception(
|
||||
// "Agent with ID {0} cannot exit directly from state {1}, it must go to {2} state first",
|
||||
// state, AgentTransferState.CleaningUp);
|
||||
}
|
||||
|
||||
m_agentsInTransit.Remove(id);
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Agent {0} cleared from transit in {1}",
|
||||
id, m_scene.RegionInfo.RegionName);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
m_log.WarnFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Agent {0} requested to clear from transit in {1} but was already cleared.",
|
||||
id, m_scene.RegionInfo.RegionName);
|
||||
|
||||
return false;
|
||||
return m_entityTransferStateMachine.IsInTransit(id);
|
||||
}
|
||||
|
||||
protected void ReInstantiateScripts(ScenePresence sp)
|
||||
|
||||
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using OpenMetaverse;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Capabilities;
|
||||
using OpenSim.Framework.Client;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
{
|
||||
/// <summary>
|
||||
/// The possible states that an agent can be in when its being transferred between regions.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a state machine.
|
||||
///
|
||||
/// [Entry] => Preparing
|
||||
/// Preparing => { Transferring || CleaningUp || [Exit] }
|
||||
/// Transferring => { ReceivedAtDestination || CleaningUp }
|
||||
/// ReceivedAtDestination => CleaningUp
|
||||
/// CleaningUp => [Exit]
|
||||
///
|
||||
/// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp
|
||||
/// However, any state can transition to CleaningUp if the teleport has failed.
|
||||
/// </remarks>
|
||||
enum AgentTransferState
|
||||
{
|
||||
Preparing, // The agent is being prepared for transfer
|
||||
Transferring, // The agent is in the process of being transferred to a destination
|
||||
ReceivedAtDestination, // The destination has notified us that the agent has been successfully received
|
||||
CleaningUp // The agent is being changed to child/removed after a transfer
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Records the state of entities when they are in transfer within or between regions (cross or teleport).
|
||||
/// </summary>
|
||||
public class EntityTransferStateMachine
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// If true then on a teleport, the source region waits for a callback from the destination region. If
|
||||
/// a callback fails to arrive within a set time then the user is pulled back into the source region.
|
||||
/// </summary>
|
||||
public bool EnableWaitForAgentArrivedAtDestination { get; set; }
|
||||
|
||||
private EntityTransferModule m_mod;
|
||||
|
||||
private Dictionary<UUID, AgentTransferState> m_agentsInTransit = new Dictionary<UUID, AgentTransferState>();
|
||||
|
||||
public EntityTransferStateMachine(EntityTransferModule module)
|
||||
{
|
||||
m_mod = module;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set that an agent is in transit.
|
||||
/// </summary>
|
||||
/// <param name='id'>The ID of the agent being teleported</param>
|
||||
/// <returns>true if the agent was not already in transit, false if it was</returns>
|
||||
internal bool SetInTransit(UUID id)
|
||||
{
|
||||
lock (m_agentsInTransit)
|
||||
{
|
||||
if (!m_agentsInTransit.ContainsKey(id))
|
||||
{
|
||||
m_agentsInTransit[id] = AgentTransferState.Preparing;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the state of an agent that is already in transit.
|
||||
/// </summary>
|
||||
/// <param name='id'></param>
|
||||
/// <param name='newState'></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
|
||||
internal void UpdateInTransit(UUID id, AgentTransferState newState)
|
||||
{
|
||||
lock (m_agentsInTransit)
|
||||
{
|
||||
// Illegal to try and update an agent that's not actually in transit.
|
||||
if (!m_agentsInTransit.ContainsKey(id))
|
||||
throw new Exception(
|
||||
string.Format(
|
||||
"Agent with ID {0} is not registered as in transit in {1}",
|
||||
id, m_mod.Scene.RegionInfo.RegionName));
|
||||
|
||||
AgentTransferState oldState = m_agentsInTransit[id];
|
||||
|
||||
bool transitionOkay = false;
|
||||
|
||||
if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp)
|
||||
transitionOkay = true;
|
||||
else if (newState == AgentTransferState.Transferring && oldState == AgentTransferState.Preparing)
|
||||
transitionOkay = true;
|
||||
else if (newState == AgentTransferState.ReceivedAtDestination && oldState == AgentTransferState.Transferring)
|
||||
transitionOkay = true;
|
||||
|
||||
if (transitionOkay)
|
||||
m_agentsInTransit[id] = newState;
|
||||
else
|
||||
throw new Exception(
|
||||
string.Format(
|
||||
"Agent with ID {0} is not allowed to move from old transit state {1} to new state {2} in {3}",
|
||||
id, oldState, newState, m_mod.Scene.RegionInfo.RegionName));
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsInTransit(UUID id)
|
||||
{
|
||||
lock (m_agentsInTransit)
|
||||
return m_agentsInTransit.ContainsKey(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an agent from the transit state machine.
|
||||
/// </summary>
|
||||
/// <param name='id'></param>
|
||||
/// <returns>true if the agent was flagged as being teleported when this method was called, false otherwise</returns>
|
||||
internal bool ResetFromTransit(UUID id)
|
||||
{
|
||||
lock (m_agentsInTransit)
|
||||
{
|
||||
if (m_agentsInTransit.ContainsKey(id))
|
||||
{
|
||||
AgentTransferState state = m_agentsInTransit[id];
|
||||
|
||||
if (state == AgentTransferState.Transferring || state == AgentTransferState.ReceivedAtDestination)
|
||||
{
|
||||
// FIXME: For now, we allow exit from any state since a thrown exception in teleport is now guranteed
|
||||
// to be handled properly - ResetFromTransit() could be invoked at any step along the process
|
||||
m_log.WarnFormat(
|
||||
"[ENTITY TRANSFER STATE MACHINE]: Agent with ID {0} should not exit directly from state {1}, should go to {2} state first in {3}",
|
||||
id, state, AgentTransferState.CleaningUp, m_mod.Scene.RegionInfo.RegionName);
|
||||
|
||||
// throw new Exception(
|
||||
// "Agent with ID {0} cannot exit directly from state {1}, it must go to {2} state first",
|
||||
// state, AgentTransferState.CleaningUp);
|
||||
}
|
||||
|
||||
m_agentsInTransit.Remove(id);
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER STATE MACHINE]: Agent {0} cleared from transit in {1}",
|
||||
id, m_mod.Scene.RegionInfo.RegionName);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
m_log.WarnFormat(
|
||||
"[ENTITY TRANSFER STATE MACHINE]: Agent {0} requested to clear from transit in {1} but was already cleared",
|
||||
id, m_mod.Scene.RegionInfo.RegionName);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal bool WaitForAgentArrivedAtDestination(UUID id)
|
||||
{
|
||||
if (!m_mod.WaitForAgentArrivedAtDestination)
|
||||
return true;
|
||||
|
||||
lock (m_agentsInTransit)
|
||||
{
|
||||
if (!IsInTransit(id))
|
||||
throw new Exception(
|
||||
string.Format(
|
||||
"Asked to wait for destination callback for agent with ID {0} in {1} but agent is not in transit",
|
||||
id, m_mod.Scene.RegionInfo.RegionName));
|
||||
|
||||
AgentTransferState currentState = m_agentsInTransit[id];
|
||||
|
||||
if (currentState != AgentTransferState.Transferring && currentState != AgentTransferState.ReceivedAtDestination)
|
||||
throw new Exception(
|
||||
string.Format(
|
||||
"Asked to wait for destination callback for agent with ID {0} in {1} but agent is in state {2}",
|
||||
id, m_mod.Scene.RegionInfo.RegionName, currentState));
|
||||
}
|
||||
|
||||
int count = 200;
|
||||
|
||||
// There should be no race condition here since no other code should be removing the agent transfer or
|
||||
// changing the state to another other than Transferring => ReceivedAtDestination.
|
||||
while (m_agentsInTransit[id] != AgentTransferState.ReceivedAtDestination && count-- > 0)
|
||||
{
|
||||
// m_log.Debug(" >>> Waiting... " + count);
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
internal void SetAgentArrivedAtDestination(UUID id)
|
||||
{
|
||||
lock (m_agentsInTransit)
|
||||
{
|
||||
if (!m_agentsInTransit.ContainsKey(id))
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[ENTITY TRANSFER STATE MACHINE]: Region {0} received notification of arrival in destination of agent {1} but no teleport request is active",
|
||||
m_mod.Scene.RegionInfo.RegionName, id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
AgentTransferState currentState = m_agentsInTransit[id];
|
||||
|
||||
if (currentState == AgentTransferState.ReceivedAtDestination)
|
||||
{
|
||||
// An anomoly but don't make this an outright failure - destination region could be overzealous in sending notification.
|
||||
m_log.WarnFormat(
|
||||
"[ENTITY TRANSFER STATE MACHINE]: Region {0} received notification of arrival in destination of agent {1} but notification has already previously been received",
|
||||
m_mod.Scene.RegionInfo.RegionName, id);
|
||||
}
|
||||
else if (currentState != AgentTransferState.Transferring)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[ENTITY TRANSFER STATE MACHINE]: Region {0} received notification of arrival in destination of agent {1} but agent is in state {2}",
|
||||
m_mod.Scene.RegionInfo.RegionName, id, currentState);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_agentsInTransit[id] = AgentTransferState.ReceivedAtDestination;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
protected override GridRegion GetFinalDestination(GridRegion region)
|
||||
{
|
||||
int flags = m_scene.GridService.GetRegionFlags(m_scene.RegionInfo.ScopeID, region.RegionID);
|
||||
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID);
|
||||
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags);
|
||||
|
||||
if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
|
||||
@@ -139,7 +139,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
if (base.NeedsClosing(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
|
||||
return true;
|
||||
|
||||
int flags = m_scene.GridService.GetRegionFlags(m_scene.RegionInfo.ScopeID, reg.RegionID);
|
||||
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
|
||||
if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
|
||||
return true;
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
if (logout)
|
||||
{
|
||||
// Log them out of this grid
|
||||
m_scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
|
||||
Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: CreateAgent {0} {1}", reg.ServerURI, finalDestination.ServerURI);
|
||||
reason = string.Empty;
|
||||
logout = false;
|
||||
int flags = m_scene.GridService.GetRegionFlags(m_scene.RegionInfo.ScopeID, reg.RegionID);
|
||||
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
|
||||
if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
|
||||
{
|
||||
// this user is going to another grid
|
||||
@@ -201,7 +201,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
"[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.Name, client.AgentId);
|
||||
|
||||
// Let's find out if this is a foreign user or a local user
|
||||
IUserManagement uMan = m_scene.RequestModuleInterface<IUserManagement>();
|
||||
IUserManagement uMan = Scene.RequestModuleInterface<IUserManagement>();
|
||||
if (uMan != null && uMan.IsLocalGridUser(id))
|
||||
{
|
||||
// local grid user
|
||||
@@ -265,7 +265,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
return;
|
||||
}
|
||||
|
||||
GridRegion info = m_scene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
|
||||
GridRegion info = Scene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
|
||||
|
||||
// Local region?
|
||||
if (info != null)
|
||||
@@ -325,34 +325,30 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
void OnConnectionClosed(IClientAPI obj)
|
||||
{
|
||||
if (obj.IsLoggingOut)
|
||||
if (obj.SceneAgent.IsChildAgent)
|
||||
return;
|
||||
|
||||
// Let's find out if this is a foreign user or a local user
|
||||
IUserManagement uMan = Scene.RequestModuleInterface<IUserManagement>();
|
||||
// UserAccount account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, obj.AgentId);
|
||||
|
||||
if (uMan != null && uMan.IsLocalGridUser(obj.AgentId))
|
||||
{
|
||||
object sp = null;
|
||||
if (obj.Scene.TryGetScenePresence(obj.AgentId, out sp))
|
||||
{
|
||||
if (((ScenePresence)sp).IsChildAgent)
|
||||
return;
|
||||
}
|
||||
// local grid user
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's find out if this is a foreign user or a local user
|
||||
IUserManagement uMan = m_scene.RequestModuleInterface<IUserManagement>();
|
||||
UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, obj.AgentId);
|
||||
if (uMan != null && uMan.IsLocalGridUser(obj.AgentId))
|
||||
{
|
||||
// local grid user
|
||||
return;
|
||||
}
|
||||
AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode);
|
||||
|
||||
AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode);
|
||||
|
||||
if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
|
||||
{
|
||||
string url = aCircuit.ServiceURLs["HomeURI"].ToString();
|
||||
IUserAgentService security = new UserAgentServiceConnector(url);
|
||||
security.LogoutAgent(obj.AgentId, obj.SessionId);
|
||||
//m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Sent logout call to UserAgentService @ {0}", url);
|
||||
}
|
||||
else
|
||||
if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
|
||||
{
|
||||
string url = aCircuit.ServiceURLs["HomeURI"].ToString();
|
||||
IUserAgentService security = new UserAgentServiceConnector(url);
|
||||
security.LogoutAgent(obj.AgentId, obj.SessionId);
|
||||
//m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Sent logout call to UserAgentService @ {0}", url);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: HomeURI not found for agent {0} logout", obj.AgentId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,8 +364,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
{
|
||||
m_log.DebugFormat("[HG INVENTORY ACCESS MODULE]: Changing root inventory for user {0}", client.Name);
|
||||
InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID);
|
||||
List<UUID> fids = new List<UUID>();
|
||||
List<UUID> iids = new List<UUID>();
|
||||
|
||||
List<InventoryFolderBase> keep = new List<InventoryFolderBase>();
|
||||
|
||||
foreach (InventoryFolderBase f in content.Folders)
|
||||
@@ -395,4 +394,4 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,7 +216,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
}
|
||||
else
|
||||
{
|
||||
IAgentAssetTransactions agentTransactions = m_Scene.RequestModuleInterface<IAgentAssetTransactions>();
|
||||
IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule;
|
||||
if (agentTransactions != null)
|
||||
{
|
||||
agentTransactions.HandleItemCreationFromTransaction(
|
||||
|
||||
@@ -49,7 +49,16 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
public bool Enabled { get; private set; }
|
||||
|
||||
private Scene m_scene;
|
||||
private readonly List<IMonitor> m_monitors = new List<IMonitor>();
|
||||
|
||||
/// <summary>
|
||||
/// These are monitors where we know the static details in advance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dynamic monitors also exist (we don't know any of the details of what stats we get back here)
|
||||
/// but these are currently hardcoded.
|
||||
/// </remarks>
|
||||
private readonly List<IMonitor> m_staticMonitors = new List<IMonitor>();
|
||||
|
||||
private readonly List<IAlert> m_alerts = new List<IAlert>();
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
@@ -84,9 +93,18 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
|
||||
public void DebugMonitors(string module, string[] args)
|
||||
{
|
||||
foreach (IMonitor monitor in m_monitors)
|
||||
foreach (IMonitor monitor in m_staticMonitors)
|
||||
{
|
||||
m_log.Info("[MonitorModule]: " + m_scene.RegionInfo.RegionName + " reports " + monitor.GetFriendlyName() + " = " + monitor.GetFriendlyValue());
|
||||
m_log.InfoFormat(
|
||||
"[MONITOR MODULE]: {0} reports {1} = {2}",
|
||||
m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue());
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
|
||||
{
|
||||
m_log.InfoFormat(
|
||||
"[MONITOR MODULE]: {0} reports {1} = {2}",
|
||||
m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,11 +124,12 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
{
|
||||
string monID = (string) request["monitor"];
|
||||
|
||||
foreach (IMonitor monitor in m_monitors)
|
||||
foreach (IMonitor monitor in m_staticMonitors)
|
||||
{
|
||||
string elemName = monitor.ToString();
|
||||
if (elemName.StartsWith(monitor.GetType().Namespace))
|
||||
elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1);
|
||||
|
||||
if (elemName == monID || monitor.ToString() == monID)
|
||||
{
|
||||
Hashtable ereply3 = new Hashtable();
|
||||
@@ -123,6 +142,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Arguably this should also be done with dynamic monitors but I'm not sure what the above code
|
||||
// is even doing. Why are we inspecting the type of the monitor???
|
||||
|
||||
// No monitor with that name
|
||||
Hashtable ereply2 = new Hashtable();
|
||||
|
||||
@@ -134,12 +156,18 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
}
|
||||
|
||||
string xml = "<data>";
|
||||
foreach (IMonitor monitor in m_monitors)
|
||||
foreach (IMonitor monitor in m_staticMonitors)
|
||||
{
|
||||
string elemName = monitor.GetName();
|
||||
xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">";
|
||||
// m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue());
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
|
||||
{
|
||||
xml += "<" + tuple.Key + ">" + tuple.Value + "</" + tuple.Key + ">";
|
||||
}
|
||||
|
||||
xml += "</data>";
|
||||
|
||||
Hashtable ereply = new Hashtable();
|
||||
@@ -156,20 +184,20 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
m_monitors.Add(new AgentCountMonitor(m_scene));
|
||||
m_monitors.Add(new ChildAgentCountMonitor(m_scene));
|
||||
m_monitors.Add(new GCMemoryMonitor());
|
||||
m_monitors.Add(new ObjectCountMonitor(m_scene));
|
||||
m_monitors.Add(new PhysicsFrameMonitor(m_scene));
|
||||
m_monitors.Add(new PhysicsUpdateFrameMonitor(m_scene));
|
||||
m_monitors.Add(new PWSMemoryMonitor());
|
||||
m_monitors.Add(new ThreadCountMonitor());
|
||||
m_monitors.Add(new TotalFrameMonitor(m_scene));
|
||||
m_monitors.Add(new EventFrameMonitor(m_scene));
|
||||
m_monitors.Add(new LandFrameMonitor(m_scene));
|
||||
m_monitors.Add(new LastFrameTimeMonitor(m_scene));
|
||||
m_staticMonitors.Add(new AgentCountMonitor(m_scene));
|
||||
m_staticMonitors.Add(new ChildAgentCountMonitor(m_scene));
|
||||
m_staticMonitors.Add(new GCMemoryMonitor());
|
||||
m_staticMonitors.Add(new ObjectCountMonitor(m_scene));
|
||||
m_staticMonitors.Add(new PhysicsFrameMonitor(m_scene));
|
||||
m_staticMonitors.Add(new PhysicsUpdateFrameMonitor(m_scene));
|
||||
m_staticMonitors.Add(new PWSMemoryMonitor());
|
||||
m_staticMonitors.Add(new ThreadCountMonitor());
|
||||
m_staticMonitors.Add(new TotalFrameMonitor(m_scene));
|
||||
m_staticMonitors.Add(new EventFrameMonitor(m_scene));
|
||||
m_staticMonitors.Add(new LandFrameMonitor(m_scene));
|
||||
m_staticMonitors.Add(new LastFrameTimeMonitor(m_scene));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"TimeDilationMonitor",
|
||||
@@ -177,7 +205,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[0],
|
||||
m => m.GetValue().ToString()));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"SimFPSMonitor",
|
||||
@@ -185,7 +213,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[1],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"PhysicsFPSMonitor",
|
||||
@@ -193,7 +221,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[2],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"AgentUpdatesPerSecondMonitor",
|
||||
@@ -201,15 +229,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[3],
|
||||
m => string.Format("{0} per second", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"ObjectUpdatesPerSecondMonitor",
|
||||
"Object Updates",
|
||||
m => m.Scene.StatsReporter.LastReportedObjectUpdates,
|
||||
m => string.Format("{0} per second", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"ActiveObjectCountMonitor",
|
||||
@@ -217,7 +237,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[7],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"ActiveScriptsMonitor",
|
||||
@@ -225,7 +245,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[19],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"ScriptEventsPerSecondMonitor",
|
||||
@@ -233,7 +253,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[20],
|
||||
m => string.Format("{0} per second", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"InPacketsPerSecondMonitor",
|
||||
@@ -241,7 +261,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[13],
|
||||
m => string.Format("{0} per second", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"OutPacketsPerSecondMonitor",
|
||||
@@ -249,7 +269,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[14],
|
||||
m => string.Format("{0} per second", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"UnackedBytesMonitor",
|
||||
@@ -257,7 +277,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[15],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"PendingDownloadsMonitor",
|
||||
@@ -265,7 +285,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[17],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"PendingUploadsMonitor",
|
||||
@@ -273,7 +293,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[18],
|
||||
m => string.Format("{0}", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"TotalFrameTimeMonitor",
|
||||
@@ -281,7 +301,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[8],
|
||||
m => string.Format("{0} ms", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"NetFrameTimeMonitor",
|
||||
@@ -289,7 +309,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[9],
|
||||
m => string.Format("{0} ms", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"PhysicsFrameTimeMonitor",
|
||||
@@ -297,7 +317,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[10],
|
||||
m => string.Format("{0} ms", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"SimulationFrameTimeMonitor",
|
||||
@@ -305,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[12],
|
||||
m => string.Format("{0} ms", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"AgentFrameTimeMonitor",
|
||||
@@ -313,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[16],
|
||||
m => string.Format("{0} ms", m.GetValue())));
|
||||
|
||||
m_monitors.Add(
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"ImagesFrameTimeMonitor",
|
||||
@@ -321,7 +341,15 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[11],
|
||||
m => string.Format("{0} ms", m.GetValue())));
|
||||
|
||||
m_alerts.Add(new DeadlockAlert(m_monitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor));
|
||||
m_staticMonitors.Add(
|
||||
new GenericMonitor(
|
||||
m_scene,
|
||||
"SpareFrameTimeMonitor",
|
||||
"Spare Frame Time",
|
||||
m => m.Scene.StatsReporter.LastReportedSimStats[21],
|
||||
m => string.Format("{0} ms", m.GetValue())));
|
||||
|
||||
m_alerts.Add(new DeadlockAlert(m_staticMonitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor));
|
||||
|
||||
foreach (IAlert alert in m_alerts)
|
||||
{
|
||||
|
||||
@@ -79,7 +79,6 @@
|
||||
<RegionModule id="AuthenticationServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication.AuthenticationServiceInConnectorModule" />
|
||||
<RegionModule id="AccessModule" type="OpenSim.Region.CoreModules.World.AccessModule" /> \
|
||||
<RegionModule id="MapImageModule" type="OpenSim.Region.CoreModules.World.LegacyMap.MapImageModule" /> \
|
||||
<RegionModule id="Warp3DImageModule" type="OpenSim.Region.CoreModules.World.Warp3DMap.Warp3DImageModule" /> \
|
||||
|
||||
</Extension>
|
||||
|
||||
|
||||
@@ -41,13 +41,39 @@ using OpenSim.Region.Framework.Scenes;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
{
|
||||
/// <summary>
|
||||
/// Data describing an external URL set up by a script.
|
||||
/// </summary>
|
||||
public class UrlData
|
||||
{
|
||||
/// <summary>
|
||||
/// Scene object part hosting the script
|
||||
/// </summary>
|
||||
public UUID hostID;
|
||||
|
||||
/// <summary>
|
||||
/// The item ID of the script that requested the URL.
|
||||
/// </summary>
|
||||
public UUID itemID;
|
||||
|
||||
/// <summary>
|
||||
/// The script engine that runs the script.
|
||||
/// </summary>
|
||||
public IScriptModule engine;
|
||||
|
||||
/// <summary>
|
||||
/// The generated URL.
|
||||
/// </summary>
|
||||
public string url;
|
||||
|
||||
/// <summary>
|
||||
/// The random UUID component of the generated URL.
|
||||
/// </summary>
|
||||
public UUID urlcode;
|
||||
|
||||
/// <summary>
|
||||
/// The external requests currently being processed or awaiting retrieval for this URL.
|
||||
/// </summary>
|
||||
public Dictionary<UUID, RequestData> requests;
|
||||
}
|
||||
|
||||
@@ -64,19 +90,33 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
public string uri;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This module provides external URLs for in-world scripts.
|
||||
/// </summary>
|
||||
public class UrlModule : ISharedRegionModule, IUrlModule
|
||||
{
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(
|
||||
MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private Dictionary<UUID, UrlData> m_RequestMap =
|
||||
new Dictionary<UUID, UrlData>();
|
||||
|
||||
private Dictionary<string, UrlData> m_UrlMap =
|
||||
new Dictionary<string, UrlData>();
|
||||
/// <summary>
|
||||
/// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the request ID
|
||||
/// randomly generated when a request is received for this URL.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Manipulation or retrieval from this dictionary must be locked on m_UrlMap to preserve consistency with
|
||||
/// m_UrlMap
|
||||
/// </remarks>
|
||||
private Dictionary<UUID, UrlData> m_RequestMap = new Dictionary<UUID, UrlData>();
|
||||
|
||||
/// <summary>
|
||||
/// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the full URL
|
||||
/// </summary>
|
||||
private Dictionary<string, UrlData> m_UrlMap = new Dictionary<string, UrlData>();
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of external urls that can be set up by this module.
|
||||
/// </summary>
|
||||
private int m_TotalUrls = 100;
|
||||
|
||||
private uint https_port = 0;
|
||||
@@ -103,10 +143,14 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
{
|
||||
m_ExternalHostNameForLSL = config.Configs["Network"].GetString("ExternalHostNameForLSL", System.Environment.MachineName);
|
||||
bool ssl_enabled = config.Configs["Network"].GetBoolean("https_listener",false);
|
||||
|
||||
if (ssl_enabled)
|
||||
{
|
||||
https_port = (uint) config.Configs["Network"].GetInt("https_port",0);
|
||||
}
|
||||
|
||||
IConfig llFunctionsConfig = config.Configs["LL-Functions"];
|
||||
|
||||
if (llFunctionsConfig != null)
|
||||
m_TotalUrls = llFunctionsConfig.GetInt("max_external_urls_per_simulator", m_TotalUrls);
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
@@ -217,7 +261,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
urlData.urlcode = urlcode;
|
||||
urlData.requests = new Dictionary<UUID, RequestData>();
|
||||
|
||||
|
||||
m_UrlMap[url] = urlData;
|
||||
|
||||
string uri = "/lslhttps/" + urlcode.ToString() + "/";
|
||||
@@ -261,39 +304,47 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
|
||||
public void HttpResponse(UUID request, int status, string body)
|
||||
{
|
||||
if (m_RequestMap.ContainsKey(request))
|
||||
lock (m_UrlMap)
|
||||
{
|
||||
UrlData urlData = m_RequestMap[request];
|
||||
urlData.requests[request].responseCode = status;
|
||||
urlData.requests[request].responseBody = body;
|
||||
//urlData.requests[request].ev.Set();
|
||||
urlData.requests[request].requestDone =true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
|
||||
if (m_RequestMap.ContainsKey(request))
|
||||
{
|
||||
UrlData urlData = m_RequestMap[request];
|
||||
urlData.requests[request].responseCode = status;
|
||||
urlData.requests[request].responseBody = body;
|
||||
//urlData.requests[request].ev.Set();
|
||||
urlData.requests[request].requestDone =true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GetHttpHeader(UUID requestId, string header)
|
||||
{
|
||||
if (m_RequestMap.ContainsKey(requestId))
|
||||
lock (m_UrlMap)
|
||||
{
|
||||
UrlData urlData=m_RequestMap[requestId];
|
||||
string value;
|
||||
if (urlData.requests[requestId].headers.TryGetValue(header,out value))
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId);
|
||||
if (m_RequestMap.ContainsKey(requestId))
|
||||
{
|
||||
UrlData urlData = m_RequestMap[requestId];
|
||||
string value;
|
||||
if (urlData.requests[requestId].headers.TryGetValue(header, out value))
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId);
|
||||
}
|
||||
}
|
||||
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
public int GetFreeUrls()
|
||||
{
|
||||
return m_TotalUrls - m_UrlMap.Count;
|
||||
lock (m_UrlMap)
|
||||
return m_TotalUrls - m_UrlMap.Count;
|
||||
}
|
||||
|
||||
public void ScriptRemoved(UUID itemID)
|
||||
@@ -332,6 +383,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
{
|
||||
RemoveUrl(url.Value);
|
||||
removeURLs.Add(url.Key);
|
||||
|
||||
foreach (UUID req in url.Value.requests.Keys)
|
||||
m_RequestMap.Remove(req);
|
||||
}
|
||||
@@ -342,145 +394,165 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void RemoveUrl(UrlData data)
|
||||
{
|
||||
m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/");
|
||||
m_HttpServer.RemoveHTTPHandler("", "/lslhttp/" + data.urlcode.ToString() + "/");
|
||||
}
|
||||
|
||||
private Hashtable NoEvents(UUID requestID, UUID sessionID)
|
||||
{
|
||||
Hashtable response = new Hashtable();
|
||||
UrlData url;
|
||||
lock (m_RequestMap)
|
||||
UrlData urlData;
|
||||
|
||||
lock (m_UrlMap)
|
||||
{
|
||||
// We need to return a 404 here in case the request URL was removed at exactly the same time that a
|
||||
// request was made. In this case, the request thread can outrace llRemoveURL() and still be polling
|
||||
// for the request ID.
|
||||
if (!m_RequestMap.ContainsKey(requestID))
|
||||
return response;
|
||||
url = m_RequestMap[requestID];
|
||||
}
|
||||
|
||||
if (System.Environment.TickCount - url.requests[requestID].startTime > 25000)
|
||||
{
|
||||
response["int_response_code"] = 500;
|
||||
response["str_response_string"] = "Script timeout";
|
||||
response["content_type"] = "text/plain";
|
||||
response["keepalive"] = false;
|
||||
response["reusecontext"] = false;
|
||||
|
||||
//remove from map
|
||||
lock (url)
|
||||
{
|
||||
url.requests.Remove(requestID);
|
||||
m_RequestMap.Remove(requestID);
|
||||
response["int_response_code"] = 404;
|
||||
response["str_response_string"] = "";
|
||||
response["keepalive"] = false;
|
||||
response["reusecontext"] = false;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
return response;
|
||||
urlData = m_RequestMap[requestID];
|
||||
|
||||
if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000)
|
||||
{
|
||||
response["int_response_code"] = 500;
|
||||
response["str_response_string"] = "Script timeout";
|
||||
response["content_type"] = "text/plain";
|
||||
response["keepalive"] = false;
|
||||
response["reusecontext"] = false;
|
||||
|
||||
//remove from map
|
||||
urlData.requests.Remove(requestID);
|
||||
m_RequestMap.Remove(requestID);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private bool HasEvents(UUID requestID, UUID sessionID)
|
||||
{
|
||||
UrlData url=null;
|
||||
|
||||
lock (m_RequestMap)
|
||||
lock (m_UrlMap)
|
||||
{
|
||||
// We return true here because an external URL request that happened at the same time as an llRemoveURL()
|
||||
// can still make it through to HttpRequestHandler(). That will return without setting up a request
|
||||
// when it detects that the URL has been removed. The poller, however, will continue to ask for
|
||||
// events for that request, so here we will signal that there are events and in GetEvents we will
|
||||
// return a 404.
|
||||
if (!m_RequestMap.ContainsKey(requestID))
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
url = m_RequestMap[requestID];
|
||||
if (!url.requests.ContainsKey(requestID))
|
||||
|
||||
UrlData urlData = m_RequestMap[requestID];
|
||||
|
||||
if (!urlData.requests.ContainsKey(requestID))
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Trigger return of timeout response.
|
||||
if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return urlData.requests[requestID].requestDone;
|
||||
}
|
||||
|
||||
if (System.Environment.TickCount-url.requests[requestID].startTime>25000)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (url.requests[requestID].requestDone)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
private Hashtable GetEvents(UUID requestID, UUID sessionID, string request)
|
||||
{
|
||||
UrlData url = null;
|
||||
RequestData requestData = null;
|
||||
Hashtable response;
|
||||
|
||||
lock (m_RequestMap)
|
||||
lock (m_UrlMap)
|
||||
{
|
||||
UrlData url = null;
|
||||
RequestData requestData = null;
|
||||
|
||||
if (!m_RequestMap.ContainsKey(requestID))
|
||||
return NoEvents(requestID,sessionID);
|
||||
return NoEvents(requestID, sessionID);
|
||||
|
||||
url = m_RequestMap[requestID];
|
||||
requestData = url.requests[requestID];
|
||||
}
|
||||
|
||||
if (!requestData.requestDone)
|
||||
return NoEvents(requestID,sessionID);
|
||||
|
||||
Hashtable response = new Hashtable();
|
||||
if (!requestData.requestDone)
|
||||
return NoEvents(requestID, sessionID);
|
||||
|
||||
if (System.Environment.TickCount - requestData.startTime > 25000)
|
||||
{
|
||||
response["int_response_code"] = 500;
|
||||
response["str_response_string"] = "Script timeout";
|
||||
response = new Hashtable();
|
||||
|
||||
if (System.Environment.TickCount - requestData.startTime > 25000)
|
||||
{
|
||||
response["int_response_code"] = 500;
|
||||
response["str_response_string"] = "Script timeout";
|
||||
response["content_type"] = "text/plain";
|
||||
response["keepalive"] = false;
|
||||
response["reusecontext"] = false;
|
||||
return response;
|
||||
}
|
||||
|
||||
//put response
|
||||
response["int_response_code"] = requestData.responseCode;
|
||||
response["str_response_string"] = requestData.responseBody;
|
||||
response["content_type"] = "text/plain";
|
||||
response["keepalive"] = false;
|
||||
response["reusecontext"] = false;
|
||||
return response;
|
||||
}
|
||||
//put response
|
||||
response["int_response_code"] = requestData.responseCode;
|
||||
response["str_response_string"] = requestData.responseBody;
|
||||
response["content_type"] = "text/plain";
|
||||
response["keepalive"] = false;
|
||||
response["reusecontext"] = false;
|
||||
|
||||
//remove from map
|
||||
lock (url)
|
||||
{
|
||||
|
||||
//remove from map
|
||||
url.requests.Remove(requestID);
|
||||
m_RequestMap.Remove(requestID);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public void HttpRequestHandler(UUID requestID, Hashtable request)
|
||||
{
|
||||
lock (request)
|
||||
{
|
||||
string uri = request["uri"].ToString();
|
||||
bool is_ssl = uri.Contains("lslhttps");
|
||||
string uri = request["uri"].ToString();
|
||||
bool is_ssl = uri.Contains("lslhttps");
|
||||
|
||||
try
|
||||
{
|
||||
Hashtable headers = (Hashtable)request["headers"];
|
||||
try
|
||||
{
|
||||
Hashtable headers = (Hashtable)request["headers"];
|
||||
|
||||
// string uri_full = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/";
|
||||
|
||||
int pos1 = uri.IndexOf("/");// /lslhttp
|
||||
int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/
|
||||
int pos3 = uri.IndexOf("/", pos2 + 1);// /lslhttp/<UUID>/
|
||||
string uri_tmp = uri.Substring(0, pos3 + 1);
|
||||
//HTTP server code doesn't provide us with QueryStrings
|
||||
string pathInfo;
|
||||
string queryString;
|
||||
queryString = "";
|
||||
int pos1 = uri.IndexOf("/");// /lslhttp
|
||||
int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/
|
||||
int pos3 = uri.IndexOf("/", pos2 + 1);// /lslhttp/<UUID>/
|
||||
string uri_tmp = uri.Substring(0, pos3 + 1);
|
||||
//HTTP server code doesn't provide us with QueryStrings
|
||||
string pathInfo;
|
||||
string queryString;
|
||||
queryString = "";
|
||||
|
||||
pathInfo = uri.Substring(pos3);
|
||||
pathInfo = uri.Substring(pos3);
|
||||
|
||||
UrlData url = null;
|
||||
if (!is_ssl)
|
||||
url = m_UrlMap["http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp];
|
||||
UrlData urlData = null;
|
||||
|
||||
lock (m_UrlMap)
|
||||
{
|
||||
string url;
|
||||
|
||||
if (is_ssl)
|
||||
url = "https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp;
|
||||
else
|
||||
url = m_UrlMap["https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp];
|
||||
url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp;
|
||||
|
||||
// Avoid a race - the request URL may have been released via llRequestUrl() whilst this
|
||||
// request was being processed.
|
||||
if (!m_UrlMap.TryGetValue(url, out urlData))
|
||||
return;
|
||||
|
||||
//for llGetHttpHeader support we need to store original URI here
|
||||
//to make x-path-info / x-query-string / x-script-url / x-remote-ip headers
|
||||
@@ -500,6 +572,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
string value = (string)header.Value;
|
||||
requestData.headers.Add(key, value);
|
||||
}
|
||||
|
||||
foreach (DictionaryEntry de in request)
|
||||
{
|
||||
if (de.Key.ToString() == "querystringkeys")
|
||||
@@ -513,11 +586,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
queryString = queryString + key + "=" + val + "&";
|
||||
}
|
||||
}
|
||||
|
||||
if (queryString.Length > 1)
|
||||
queryString = queryString.Substring(0, queryString.Length - 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//if this machine is behind DNAT/port forwarding, currently this is being
|
||||
@@ -525,34 +597,23 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"];
|
||||
requestData.headers["x-path-info"] = pathInfo;
|
||||
requestData.headers["x-query-string"] = queryString;
|
||||
requestData.headers["x-script-url"] = url.url;
|
||||
|
||||
//requestData.ev = new ManualResetEvent(false);
|
||||
lock (url.requests)
|
||||
{
|
||||
url.requests.Add(requestID, requestData);
|
||||
}
|
||||
lock (m_RequestMap)
|
||||
{
|
||||
//add to request map
|
||||
m_RequestMap.Add(requestID, url);
|
||||
}
|
||||
|
||||
url.engine.PostScriptEvent(url.itemID, "http_request", new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() });
|
||||
|
||||
//send initial response?
|
||||
// Hashtable response = new Hashtable();
|
||||
|
||||
return;
|
||||
requestData.headers["x-script-url"] = urlData.url;
|
||||
|
||||
urlData.requests.Add(requestID, requestData);
|
||||
m_RequestMap.Add(requestID, urlData);
|
||||
}
|
||||
catch (Exception we)
|
||||
{
|
||||
//Hashtable response = new Hashtable();
|
||||
m_log.Warn("[HttpRequestHandler]: http-in request failed");
|
||||
m_log.Warn(we.Message);
|
||||
m_log.Warn(we.StackTrace);
|
||||
}
|
||||
|
||||
urlData.engine.PostScriptEvent(
|
||||
urlData.itemID,
|
||||
"http_request",
|
||||
new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() });
|
||||
}
|
||||
catch (Exception we)
|
||||
{
|
||||
//Hashtable response = new Hashtable();
|
||||
m_log.Warn("[HttpRequestHandler]: http-in request failed");
|
||||
m_log.Warn(we.Message);
|
||||
m_log.Warn(we.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,4 +622,4 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
ScriptRemoved(itemID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,11 +131,12 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
|
||||
{
|
||||
// Start http server
|
||||
// Attach xmlrpc handlers
|
||||
m_log.Info("[XML RPC MODULE]: " +
|
||||
"Starting up XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands.");
|
||||
BaseHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort);
|
||||
// m_log.InfoFormat(
|
||||
// "[XML RPC MODULE]: Starting up XMLRPC Server on port {0} for llRemoteData commands.",
|
||||
// m_remoteDataPort);
|
||||
|
||||
IHttpServer httpServer = MainServer.GetHttpServer((uint)m_remoteDataPort);
|
||||
httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData);
|
||||
httpServer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
|
||||
ISimulationService simService = scene.RequestModuleInterface<ISimulationService>();
|
||||
IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>();
|
||||
Object[] args = new Object[] { m_Config };
|
||||
IFriendsService friendsService = ServerUtils.LoadPlugin<IFriendsService>(m_LocalServiceDll, args);
|
||||
// IFriendsService friendsService = ServerUtils.LoadPlugin<IFriendsService>(m_LocalServiceDll, args)
|
||||
ServerUtils.LoadPlugin<IFriendsService>(m_LocalServiceDll, args);
|
||||
|
||||
m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService);
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Land
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
m_log.Info("[LAND IN CONNECTOR]: Starting...");
|
||||
// m_log.Info("[LAND IN CONNECTOR]: Starting...");
|
||||
}
|
||||
|
||||
public void Close()
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Neighbour
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
m_log.Info("[NEIGHBOUR IN CONNECTOR]: Starting...");
|
||||
// m_log.Info("[NEIGHBOUR IN CONNECTOR]: Starting...");
|
||||
}
|
||||
|
||||
public void Close()
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
|
||||
|
||||
m_aScene = scene;
|
||||
|
||||
scene.RegisterModuleInterface<IAssetService>(this);
|
||||
m_aScene.RegisterModuleInterface<IAssetService>(this);
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
|
||||
@@ -41,8 +41,7 @@ using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||
{
|
||||
public class LocalGridServicesConnector :
|
||||
ISharedRegionModule, IGridService
|
||||
public class LocalGridServicesConnector : ISharedRegionModule, IGridService
|
||||
{
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(
|
||||
@@ -51,7 +50,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||
private IGridService m_GridService;
|
||||
private Dictionary<UUID, RegionCache> m_LocalCache = new Dictionary<UUID, RegionCache>();
|
||||
|
||||
private bool m_Enabled = false;
|
||||
private bool m_Enabled;
|
||||
|
||||
public LocalGridServicesConnector()
|
||||
{
|
||||
@@ -59,7 +58,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||
|
||||
public LocalGridServicesConnector(IConfigSource source)
|
||||
{
|
||||
m_log.Debug("[LOCAL GRID CONNECTOR]: LocalGridServicesConnector instantiated");
|
||||
m_log.Debug("[LOCAL GRID SERVICE CONNECTOR]: LocalGridServicesConnector instantiated directly.");
|
||||
InitialiseService(source);
|
||||
}
|
||||
|
||||
@@ -84,8 +83,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||
if (name == Name)
|
||||
{
|
||||
InitialiseService(source);
|
||||
m_Enabled = true;
|
||||
m_log.Info("[LOCAL GRID CONNECTOR]: Local grid connector enabled");
|
||||
m_log.Info("[LOCAL GRID SERVICE CONNECTOR]: Local grid connector enabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,7 +93,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||
IConfig assetConfig = source.Configs["GridService"];
|
||||
if (assetConfig == null)
|
||||
{
|
||||
m_log.Error("[LOCAL GRID CONNECTOR]: GridService missing from OpenSim.ini");
|
||||
m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: GridService missing from OpenSim.ini");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -104,7 +102,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||
|
||||
if (serviceDll == String.Empty)
|
||||
{
|
||||
m_log.Error("[LOCAL GRID CONNECTOR]: No LocalServiceModule named in section GridService");
|
||||
m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: No LocalServiceModule named in section GridService");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -115,16 +113,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||
|
||||
if (m_GridService == null)
|
||||
{
|
||||
m_log.Error("[LOCAL GRID CONNECTOR]: Can't load grid service");
|
||||
m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: Can't load grid service");
|
||||
return;
|
||||
}
|
||||
|
||||
m_Enabled = true;
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
{
|
||||
// FIXME: We will still add this command even if we aren't enabled since RemoteGridServiceConnector
|
||||
// will have instantiated us directly.
|
||||
MainConsole.Instance.Commands.AddCommand("Regions", false, "show neighbours",
|
||||
"show neighbours",
|
||||
"Shows the local regions' neighbours", NeighboursCommand);
|
||||
"Shows the local regions' neighbours", HandleShowNeighboursCommand);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
@@ -133,17 +135,22 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||
|
||||
public void AddRegion(Scene scene)
|
||||
{
|
||||
if (m_Enabled)
|
||||
scene.RegisterModuleInterface<IGridService>(this);
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
scene.RegisterModuleInterface<IGridService>(this);
|
||||
|
||||
if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID))
|
||||
m_log.ErrorFormat("[LOCAL GRID CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
|
||||
m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
|
||||
else
|
||||
m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene));
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
m_LocalCache[scene.RegionInfo.RegionID].Clear();
|
||||
m_LocalCache.Remove(scene.RegionInfo.RegionID);
|
||||
}
|
||||
@@ -232,7 +239,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||
|
||||
#endregion
|
||||
|
||||
public void NeighboursCommand(string module, string[] cmdparams)
|
||||
public void HandleShowNeighboursCommand(string module, string[] cmdparams)
|
||||
{
|
||||
System.Text.StringBuilder caps = new System.Text.StringBuilder();
|
||||
|
||||
|
||||
@@ -79,29 +79,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
|
||||
|
||||
public void OnConnectionClose(IClientAPI client)
|
||||
{
|
||||
if (client.IsLoggingOut)
|
||||
{
|
||||
object sp = null;
|
||||
Vector3 position = new Vector3(128, 128, 0);
|
||||
Vector3 lookat = new Vector3(0, 1, 0);
|
||||
|
||||
if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
|
||||
{
|
||||
if (sp is ScenePresence)
|
||||
{
|
||||
if (((ScenePresence)sp).IsChildAgent)
|
||||
return;
|
||||
|
||||
position = ((ScenePresence)sp).AbsolutePosition;
|
||||
lookat = ((ScenePresence)sp).Lookat;
|
||||
}
|
||||
}
|
||||
|
||||
// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
|
||||
m_GridUserService.LoggedOut(client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID, position, lookat);
|
||||
}
|
||||
if (client.SceneAgent.IsChildAgent)
|
||||
return;
|
||||
|
||||
// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
|
||||
m_GridUserService.LoggedOut(
|
||||
client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID,
|
||||
client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,13 +125,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour
|
||||
uint x, y;
|
||||
Utils.LongToUInts(regionHandle, out x, out y);
|
||||
|
||||
m_log.DebugFormat("[NEIGHBOUR CONNECTOR]: HelloNeighbour from region {0} to region at {1}-{2}",
|
||||
thisRegion.RegionName, x / Constants.RegionSize, y / Constants.RegionSize);
|
||||
|
||||
foreach (Scene s in m_Scenes)
|
||||
{
|
||||
if (s.RegionInfo.RegionHandle == regionHandle)
|
||||
{
|
||||
m_log.DebugFormat("[LOCAL NEIGHBOUR SERVICE CONNECTOR]: HelloNeighbour from region {0} to neighbour {1} at {2}-{3}",
|
||||
thisRegion.RegionName, s.Name, x / Constants.RegionSize, y / Constants.RegionSize);
|
||||
|
||||
//m_log.Debug("[NEIGHBOUR CONNECTOR]: Found region to SendHelloNeighbour");
|
||||
return s.IncomingHelloNeighbour(thisRegion);
|
||||
}
|
||||
|
||||
@@ -193,11 +193,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
|
||||
return m_PresenceService.GetAgents(userIDs);
|
||||
}
|
||||
|
||||
public PresenceInfo VerifyAgent(UUID s_sessionID)
|
||||
{
|
||||
return m_PresenceService.VerifyAgent(s_sessionID);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
@@ -64,7 +64,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
|
||||
scene.EventManager.OnNewClient -= OnNewClient;
|
||||
|
||||
m_PresenceService.LogoutRegionAgents(scene.RegionInfo.RegionID);
|
||||
|
||||
}
|
||||
|
||||
public void OnMakeRootAgent(ScenePresence sp)
|
||||
@@ -80,18 +79,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
|
||||
|
||||
public void OnConnectionClose(IClientAPI client)
|
||||
{
|
||||
if (client.IsLoggingOut)
|
||||
if (!client.SceneAgent.IsChildAgent)
|
||||
{
|
||||
object sp = null;
|
||||
if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
|
||||
{
|
||||
if (sp is ScenePresence)
|
||||
{
|
||||
if (((ScenePresence)sp).IsChildAgent)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
|
||||
m_PresenceService.LogoutAgent(client.SessionId);
|
||||
}
|
||||
|
||||
@@ -153,11 +153,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
|
||||
return m_RemoteConnector.GetAgents(userIDs);
|
||||
}
|
||||
|
||||
public PresenceInfo VerifyAgent(UUID sessionID)
|
||||
{
|
||||
return m_RemoteConnector.VerifyAgent(sessionID);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
@@ -354,24 +354,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CreateObject(GridRegion destination, UUID userID, UUID itemID)
|
||||
{
|
||||
if (destination == null)
|
||||
return false;
|
||||
|
||||
if (m_scenes.ContainsKey(destination.RegionID))
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
|
||||
// s.RegionInfo.RegionName, destination.RegionHandle);
|
||||
|
||||
return m_scenes[destination.RegionID].IncomingCreateObject(userID, itemID);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#endregion /* IInterregionComms */
|
||||
|
||||
#region Misc
|
||||
|
||||
@@ -300,13 +300,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CreateObject(GridRegion destination, UUID userID, UUID itemID)
|
||||
{
|
||||
// Not Implemented
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion /* IInterregionComms */
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,8 +46,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
|
||||
|
||||
/// <summary>
|
||||
/// Store for asset data we received before we get the metadata
|
||||
/// </summary>
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
|
||||
"set terrain heights <corner> <min> <max> [<x>] [<y>]",
|
||||
"Sets the terrain texture heights on corner #<corner> to <min>/<max>, if <x> or <y> are specified, it will only " +
|
||||
"set it on regions with a matching coordinate. Specify -1 in <x> or <y> to wildcard" +
|
||||
" that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3.",
|
||||
" that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.",
|
||||
consoleSetTerrainHeights);
|
||||
|
||||
m_module.Scene.AddCommand(
|
||||
@@ -143,6 +143,16 @@ namespace OpenSim.Region.CoreModules.World.Estate
|
||||
|
||||
switch (corner)
|
||||
{
|
||||
case -1:
|
||||
m_module.Scene.RegionInfo.RegionSettings.Elevation1SW = lowValue;
|
||||
m_module.Scene.RegionInfo.RegionSettings.Elevation2SW = highValue;
|
||||
m_module.Scene.RegionInfo.RegionSettings.Elevation1NW = lowValue;
|
||||
m_module.Scene.RegionInfo.RegionSettings.Elevation2NW = highValue;
|
||||
m_module.Scene.RegionInfo.RegionSettings.Elevation1SE = lowValue;
|
||||
m_module.Scene.RegionInfo.RegionSettings.Elevation2SE = highValue;
|
||||
m_module.Scene.RegionInfo.RegionSettings.Elevation1NE = lowValue;
|
||||
m_module.Scene.RegionInfo.RegionSettings.Elevation2NE = highValue;
|
||||
break;
|
||||
case 0:
|
||||
m_module.Scene.RegionInfo.RegionSettings.Elevation1SW = lowValue;
|
||||
m_module.Scene.RegionInfo.RegionSettings.Elevation2SW = highValue;
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene);
|
||||
SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
|
||||
MediaEntry me = new MediaEntry();
|
||||
|
||||
m_module.SetMediaEntry(part, 1, me);
|
||||
@@ -88,7 +88,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
|
||||
|
||||
string homeUrl = "opensimulator.org";
|
||||
|
||||
SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene);
|
||||
SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
|
||||
MediaEntry me = new MediaEntry() { HomeURL = homeUrl };
|
||||
|
||||
m_module.SetMediaEntry(part, 1, me);
|
||||
|
||||
@@ -98,7 +98,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||
m_console.Commands.AddCommand(
|
||||
"Objects", false, "delete object name",
|
||||
"delete object name [--regex] <name>",
|
||||
"Delete a scene object by name.\nIf --regex is specified then the name is treatead as a regular expression",
|
||||
"Delete a scene object by name.",
|
||||
"If --regex is specified then the name is treatead as a regular expression",
|
||||
HandleDeleteObject);
|
||||
|
||||
m_console.Commands.AddCommand(
|
||||
@@ -118,7 +119,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||
false,
|
||||
"show object name",
|
||||
"show object name [--regex] <name>",
|
||||
"Show details of scene objects with the given name.\nIf --regex is specified then the name is treatead as a regular expression",
|
||||
"Show details of scene objects with the given name.",
|
||||
"If --regex is specified then the name is treatead as a regular expression",
|
||||
HandleShowObjectByName);
|
||||
|
||||
m_console.Commands.AddCommand(
|
||||
@@ -133,7 +135,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||
false,
|
||||
"show part name",
|
||||
"show part name [--regex] <name>",
|
||||
"Show details of scene object parts with the given name.\nIf --regex is specified then the name is treatead as a regular expression",
|
||||
"Show details of scene object parts with the given name.",
|
||||
"If --regex is specified then the name is treatead as a regular expression",
|
||||
HandleShowPartByName);
|
||||
}
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
|
||||
"Force permissions on or off",
|
||||
HandleForcePermissions);
|
||||
|
||||
m_scene.AddCommand("Users", this, "debug permissions",
|
||||
m_scene.AddCommand("Debug", this, "debug permissions",
|
||||
"debug permissions <true / false>",
|
||||
"Turn on permissions debugging",
|
||||
HandleDebugPermissions);
|
||||
@@ -348,12 +348,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions
|
||||
m_friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
|
||||
|
||||
if (m_friendsModule == null)
|
||||
m_log.Warn("[PERMISSIONS]: Friends module not found, friend permissions will not work");
|
||||
m_log.Debug("[PERMISSIONS]: Friends module not found, friend permissions will not work");
|
||||
|
||||
m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
|
||||
|
||||
if (m_groupsModule == null)
|
||||
m_log.Warn("[PERMISSIONS]: Groups module not found, group permissions will not work");
|
||||
m_log.Debug("[PERMISSIONS]: Groups module not found, group permissions will not work");
|
||||
|
||||
m_moapModule = m_scene.RequestModuleInterface<IMoapModule>();
|
||||
|
||||
|
||||
@@ -78,11 +78,8 @@ namespace OpenSim.Region.CoreModules.World.Sound
|
||||
|
||||
if (grp.IsAttachment)
|
||||
{
|
||||
if (grp.AttachmentPoint > 30) // HUD
|
||||
{
|
||||
if (sp.ControllingClient.AgentId != grp.OwnerID)
|
||||
return;
|
||||
}
|
||||
if (grp.HasPrivateAttachmentPoint && sp.ControllingClient.AgentId != grp.OwnerID)
|
||||
return;
|
||||
|
||||
if (sp.ControllingClient.AgentId == grp.OwnerID)
|
||||
dis = 0;
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
|
||||
}
|
||||
|
||||
//Returns true if this extension is supported for terrain save-tile
|
||||
public bool SupportsTileSave()
|
||||
public override bool SupportsTileSave()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
|
||||
bool eof = false;
|
||||
|
||||
int fileXPoints = 0;
|
||||
int fileYPoints = 0;
|
||||
// int fileYPoints = 0;
|
||||
|
||||
// Terragen file
|
||||
while (eof == false)
|
||||
@@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
|
||||
{
|
||||
case "SIZE":
|
||||
fileXPoints = bs.ReadInt16() + 1;
|
||||
fileYPoints = fileXPoints;
|
||||
// fileYPoints = fileXPoints;
|
||||
bs.ReadInt16();
|
||||
break;
|
||||
case "XPTS":
|
||||
@@ -83,7 +83,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
|
||||
bs.ReadInt16();
|
||||
break;
|
||||
case "YPTS":
|
||||
fileYPoints = bs.ReadInt16();
|
||||
// fileYPoints = bs.ReadInt16();
|
||||
bs.ReadInt16();
|
||||
bs.ReadInt16();
|
||||
break;
|
||||
case "ALTW":
|
||||
@@ -164,10 +165,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
|
||||
bool eof = false;
|
||||
if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ")
|
||||
{
|
||||
|
||||
int fileWidth = w;
|
||||
int fileHeight = h;
|
||||
|
||||
// int fileWidth = w;
|
||||
// int fileHeight = h;
|
||||
|
||||
// Terragen file
|
||||
while (eof == false)
|
||||
@@ -176,17 +175,20 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
|
||||
switch (tmp)
|
||||
{
|
||||
case "SIZE":
|
||||
int sztmp = bs.ReadInt16() + 1;
|
||||
fileWidth = sztmp;
|
||||
fileHeight = sztmp;
|
||||
// int sztmp = bs.ReadInt16() + 1;
|
||||
// fileWidth = sztmp;
|
||||
// fileHeight = sztmp;
|
||||
bs.ReadInt16();
|
||||
bs.ReadInt16();
|
||||
break;
|
||||
case "XPTS":
|
||||
fileWidth = bs.ReadInt16();
|
||||
// fileWidth = bs.ReadInt16();
|
||||
bs.ReadInt16();
|
||||
bs.ReadInt16();
|
||||
break;
|
||||
case "YPTS":
|
||||
fileHeight = bs.ReadInt16();
|
||||
// fileHeight = bs.ReadInt16();
|
||||
bs.ReadInt16();
|
||||
bs.ReadInt16();
|
||||
break;
|
||||
case "ALTW":
|
||||
@@ -250,7 +252,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
|
||||
if (horizontalScale < 0.01d)
|
||||
horizontalScale = 0.01d;
|
||||
|
||||
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
|
||||
Encoding enc = Encoding.ASCII;
|
||||
|
||||
bs.Write(enc.GetBytes("TERRAGENTERRAIN "));
|
||||
|
||||
|
||||
@@ -1108,6 +1108,32 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
private void InterfaceMinTerrain(Object[] args)
|
||||
{
|
||||
int x, y;
|
||||
for (x = 0; x < m_channel.Width; x++)
|
||||
{
|
||||
for (y = 0; y < m_channel.Height; y++)
|
||||
{
|
||||
m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]);
|
||||
}
|
||||
}
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
private void InterfaceMaxTerrain(Object[] args)
|
||||
{
|
||||
int x, y;
|
||||
for (x = 0; x < m_channel.Width; x++)
|
||||
{
|
||||
for (y = 0; y < m_channel.Height; y++)
|
||||
{
|
||||
m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]);
|
||||
}
|
||||
}
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
|
||||
private void InterfaceShowDebugStats(Object[] args)
|
||||
{
|
||||
double max = Double.MinValue;
|
||||
@@ -1248,6 +1274,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
rescaleCommand.AddArgument("min", "min terrain height after rescaling", "Double");
|
||||
rescaleCommand.AddArgument("max", "max terrain height after rescaling", "Double");
|
||||
|
||||
Command minCommand = new Command("min", CommandIntentions.COMMAND_HAZARDOUS, InterfaceMinTerrain, "Sets the minimum terrain height to the specified value.");
|
||||
minCommand.AddArgument("min", "terrain height to use as minimum", "Double");
|
||||
|
||||
Command maxCommand = new Command("max", CommandIntentions.COMMAND_HAZARDOUS, InterfaceMaxTerrain, "Sets the maximum terrain height to the specified value.");
|
||||
maxCommand.AddArgument("min", "terrain height to use as maximum", "Double");
|
||||
|
||||
|
||||
// Debug
|
||||
Command showDebugStatsCommand =
|
||||
@@ -1279,6 +1311,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
m_commander.RegisterCommand("effect", pluginRunCommand);
|
||||
m_commander.RegisterCommand("flip", flipCommand);
|
||||
m_commander.RegisterCommand("rescale", rescaleCommand);
|
||||
m_commander.RegisterCommand("min", minCommand);
|
||||
m_commander.RegisterCommand("max", maxCommand);
|
||||
|
||||
// Add this to our scene so scripts can call these functions
|
||||
m_scene.RegisterModuleCommander(m_commander);
|
||||
|
||||
@@ -84,218 +84,241 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
Debug.Assert(heightRanges.Length == 4);
|
||||
|
||||
Bitmap[] detailTexture = new Bitmap[4];
|
||||
Bitmap output = null;
|
||||
BitmapData outputData = null;
|
||||
|
||||
if (textureTerrain)
|
||||
try
|
||||
{
|
||||
// Swap empty terrain textureIDs with default IDs
|
||||
for (int i = 0; i < textureIDs.Length; i++)
|
||||
if (textureTerrain)
|
||||
{
|
||||
if (textureIDs[i] == UUID.Zero)
|
||||
textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i];
|
||||
}
|
||||
|
||||
#region Texture Fetching
|
||||
|
||||
if (assetService != null)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
// Swap empty terrain textureIDs with default IDs
|
||||
for (int i = 0; i < textureIDs.Length; i++)
|
||||
{
|
||||
AssetBase asset;
|
||||
UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]);
|
||||
|
||||
// Try to fetch a cached copy of the decoded/resized version of this texture
|
||||
asset = assetService.GetCached(cacheID.ToString());
|
||||
if (asset != null)
|
||||
if (textureIDs[i] == UUID.Zero)
|
||||
textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i];
|
||||
}
|
||||
|
||||
#region Texture Fetching
|
||||
|
||||
if (assetService != null)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data))
|
||||
detailTexture[i] = (Bitmap)Image.FromStream(stream);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("Failed to decode cached terrain texture " + cacheID +
|
||||
" (textureID: " + textureIDs[i] + "): " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
if (detailTexture[i] == null)
|
||||
{
|
||||
// Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG
|
||||
asset = assetService.Get(textureIDs[i].ToString());
|
||||
AssetBase asset;
|
||||
UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]);
|
||||
|
||||
// Try to fetch a cached copy of the decoded/resized version of this texture
|
||||
asset = assetService.GetCached(cacheID.ToString());
|
||||
if (asset != null)
|
||||
{
|
||||
try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); }
|
||||
// m_log.DebugFormat(
|
||||
// "[TERRAIN SPLAT]: Got asset service cached terrain texture {0} {1}", i, asset.ID);
|
||||
|
||||
try
|
||||
{
|
||||
using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data))
|
||||
detailTexture[i] = (Bitmap)Image.FromStream(stream);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message);
|
||||
m_log.Warn("Failed to decode cached terrain texture " + cacheID +
|
||||
" (textureID: " + textureIDs[i] + "): " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
if (detailTexture[i] != null)
|
||||
|
||||
if (detailTexture[i] == null)
|
||||
{
|
||||
Bitmap bitmap = detailTexture[i];
|
||||
|
||||
// Make sure this texture is the correct size, otherwise resize
|
||||
if (bitmap.Width != 256 || bitmap.Height != 256)
|
||||
bitmap = ImageUtils.ResizeImage(bitmap, 256, 256);
|
||||
|
||||
// Save the decoded and resized texture to the cache
|
||||
byte[] data;
|
||||
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
|
||||
// Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG
|
||||
asset = assetService.Get(textureIDs[i].ToString());
|
||||
if (asset != null)
|
||||
{
|
||||
bitmap.Save(stream, ImageFormat.Png);
|
||||
data = stream.ToArray();
|
||||
// m_log.DebugFormat(
|
||||
// "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID);
|
||||
|
||||
try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); }
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
if (detailTexture[i] != null)
|
||||
{
|
||||
// Make sure this texture is the correct size, otherwise resize
|
||||
if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256)
|
||||
{
|
||||
using (Bitmap origBitmap = detailTexture[i])
|
||||
{
|
||||
detailTexture[i] = ImageUtils.ResizeImage(origBitmap, 256, 256);
|
||||
}
|
||||
}
|
||||
|
||||
// Save the decoded and resized texture to the cache
|
||||
byte[] data;
|
||||
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
|
||||
{
|
||||
detailTexture[i].Save(stream, ImageFormat.Png);
|
||||
data = stream.ToArray();
|
||||
}
|
||||
|
||||
// Cache a PNG copy of this terrain texture
|
||||
AssetBase newAsset = new AssetBase
|
||||
{
|
||||
Data = data,
|
||||
Description = "PNG",
|
||||
Flags = AssetFlags.Collectable,
|
||||
FullID = cacheID,
|
||||
ID = cacheID.ToString(),
|
||||
Local = true,
|
||||
Name = String.Empty,
|
||||
Temporary = true,
|
||||
Type = (sbyte)AssetType.Unknown
|
||||
};
|
||||
newAsset.Metadata.ContentType = "image/png";
|
||||
assetService.Store(newAsset);
|
||||
}
|
||||
|
||||
// Cache a PNG copy of this terrain texture
|
||||
AssetBase newAsset = new AssetBase
|
||||
{
|
||||
Data = data,
|
||||
Description = "PNG",
|
||||
Flags = AssetFlags.Collectable,
|
||||
FullID = cacheID,
|
||||
ID = cacheID.ToString(),
|
||||
Local = true,
|
||||
Name = String.Empty,
|
||||
Temporary = true,
|
||||
Type = (sbyte)AssetType.Unknown
|
||||
};
|
||||
newAsset.Metadata.ContentType = "image/png";
|
||||
assetService.Store(newAsset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Texture Fetching
|
||||
}
|
||||
|
||||
#endregion Texture Fetching
|
||||
}
|
||||
|
||||
// Fill in any missing textures with a solid color
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (detailTexture[i] == null)
|
||||
|
||||
// Fill in any missing textures with a solid color
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
// Create a solid color texture for this layer
|
||||
detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
|
||||
using (Graphics gfx = Graphics.FromImage(detailTexture[i]))
|
||||
if (detailTexture[i] == null)
|
||||
{
|
||||
using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i]))
|
||||
gfx.FillRectangle(brush, 0, 0, 256, 256);
|
||||
// m_log.DebugFormat(
|
||||
// "[TERRAIN SPLAT]: Generating solid colour for missing texture {0}", i);
|
||||
|
||||
// Create a solid color texture for this layer
|
||||
detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
|
||||
using (Graphics gfx = Graphics.FromImage(detailTexture[i]))
|
||||
{
|
||||
using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i]))
|
||||
gfx.FillRectangle(brush, 0, 0, 256, 256);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Layer Map
|
||||
|
||||
float[] layermap = new float[256 * 256];
|
||||
|
||||
for (int y = 0; y < 256; y++)
|
||||
{
|
||||
for (int x = 0; x < 256; x++)
|
||||
{
|
||||
float height = heightmap[y * 256 + x];
|
||||
|
||||
float pctX = (float)x / 255f;
|
||||
float pctY = (float)y / 255f;
|
||||
|
||||
// Use bilinear interpolation between the four corners of start height and
|
||||
// height range to select the current values at this position
|
||||
float startHeight = ImageUtils.Bilinear(
|
||||
startHeights[0],
|
||||
startHeights[2],
|
||||
startHeights[1],
|
||||
startHeights[3],
|
||||
pctX, pctY);
|
||||
startHeight = Utils.Clamp(startHeight, 0f, 255f);
|
||||
|
||||
float heightRange = ImageUtils.Bilinear(
|
||||
heightRanges[0],
|
||||
heightRanges[2],
|
||||
heightRanges[1],
|
||||
heightRanges[3],
|
||||
pctX, pctY);
|
||||
heightRange = Utils.Clamp(heightRange, 0f, 255f);
|
||||
|
||||
// Generate two frequencies of perlin noise based on our global position
|
||||
// The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
|
||||
Vector3 vec = new Vector3
|
||||
(
|
||||
((float)regionPosition.X + x) * 0.20319f,
|
||||
((float)regionPosition.Y + y) * 0.20319f,
|
||||
height * 0.25f
|
||||
);
|
||||
|
||||
float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f;
|
||||
float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
|
||||
float noise = (lowFreq + highFreq) * 2f;
|
||||
|
||||
// Combine the current height, generated noise, start height, and height range parameters, then scale all of it
|
||||
float layer = ((height + noise - startHeight) / heightRange) * 4f;
|
||||
if (Single.IsNaN(layer)) layer = 0f;
|
||||
layermap[y * 256 + x] = Utils.Clamp(layer, 0f, 3f);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Layer Map
|
||||
|
||||
#region Texture Compositing
|
||||
|
||||
Bitmap output = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
|
||||
BitmapData outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
// Get handles to all of the texture data arrays
|
||||
BitmapData[] datas = new BitmapData[]
|
||||
{
|
||||
detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat),
|
||||
detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat),
|
||||
detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat),
|
||||
detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat)
|
||||
};
|
||||
|
||||
int[] comps = new int[]
|
||||
{
|
||||
(datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
|
||||
(datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
|
||||
(datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
|
||||
(datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3
|
||||
};
|
||||
|
||||
|
||||
#region Layer Map
|
||||
|
||||
float[] layermap = new float[256 * 256];
|
||||
|
||||
for (int y = 0; y < 256; y++)
|
||||
{
|
||||
for (int x = 0; x < 256; x++)
|
||||
{
|
||||
float layer = layermap[y * 256 + x];
|
||||
|
||||
// Select two textures
|
||||
int l0 = (int)Math.Floor(layer);
|
||||
int l1 = Math.Min(l0 + 1, 3);
|
||||
|
||||
byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0];
|
||||
byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1];
|
||||
byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3;
|
||||
|
||||
float aB = *(ptrA + 0);
|
||||
float aG = *(ptrA + 1);
|
||||
float aR = *(ptrA + 2);
|
||||
|
||||
float bB = *(ptrB + 0);
|
||||
float bG = *(ptrB + 1);
|
||||
float bR = *(ptrB + 2);
|
||||
|
||||
float layerDiff = layer - l0;
|
||||
|
||||
// Interpolate between the two selected textures
|
||||
*(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB));
|
||||
*(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG));
|
||||
*(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR));
|
||||
float height = heightmap[y * 256 + x];
|
||||
|
||||
float pctX = (float)x / 255f;
|
||||
float pctY = (float)y / 255f;
|
||||
|
||||
// Use bilinear interpolation between the four corners of start height and
|
||||
// height range to select the current values at this position
|
||||
float startHeight = ImageUtils.Bilinear(
|
||||
startHeights[0],
|
||||
startHeights[2],
|
||||
startHeights[1],
|
||||
startHeights[3],
|
||||
pctX, pctY);
|
||||
startHeight = Utils.Clamp(startHeight, 0f, 255f);
|
||||
|
||||
float heightRange = ImageUtils.Bilinear(
|
||||
heightRanges[0],
|
||||
heightRanges[2],
|
||||
heightRanges[1],
|
||||
heightRanges[3],
|
||||
pctX, pctY);
|
||||
heightRange = Utils.Clamp(heightRange, 0f, 255f);
|
||||
|
||||
// Generate two frequencies of perlin noise based on our global position
|
||||
// The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
|
||||
Vector3 vec = new Vector3
|
||||
(
|
||||
((float)regionPosition.X + x) * 0.20319f,
|
||||
((float)regionPosition.Y + y) * 0.20319f,
|
||||
height * 0.25f
|
||||
);
|
||||
|
||||
float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f;
|
||||
float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
|
||||
float noise = (lowFreq + highFreq) * 2f;
|
||||
|
||||
// Combine the current height, generated noise, start height, and height range parameters, then scale all of it
|
||||
float layer = ((height + noise - startHeight) / heightRange) * 4f;
|
||||
if (Single.IsNaN(layer)) layer = 0f;
|
||||
layermap[y * 256 + x] = Utils.Clamp(layer, 0f, 3f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion Layer Map
|
||||
|
||||
#region Texture Compositing
|
||||
|
||||
output = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
|
||||
outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
// Get handles to all of the texture data arrays
|
||||
BitmapData[] datas = new BitmapData[]
|
||||
{
|
||||
detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat),
|
||||
detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat),
|
||||
detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat),
|
||||
detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat)
|
||||
};
|
||||
|
||||
int[] comps = new int[]
|
||||
{
|
||||
(datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
|
||||
(datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
|
||||
(datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
|
||||
(datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3
|
||||
};
|
||||
|
||||
for (int y = 0; y < 256; y++)
|
||||
{
|
||||
for (int x = 0; x < 256; x++)
|
||||
{
|
||||
float layer = layermap[y * 256 + x];
|
||||
|
||||
// Select two textures
|
||||
int l0 = (int)Math.Floor(layer);
|
||||
int l1 = Math.Min(l0 + 1, 3);
|
||||
|
||||
byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0];
|
||||
byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1];
|
||||
byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3;
|
||||
|
||||
float aB = *(ptrA + 0);
|
||||
float aG = *(ptrA + 1);
|
||||
float aR = *(ptrA + 2);
|
||||
|
||||
float bB = *(ptrB + 0);
|
||||
float bG = *(ptrB + 1);
|
||||
float bR = *(ptrB + 2);
|
||||
|
||||
float layerDiff = layer - l0;
|
||||
|
||||
// Interpolate between the two selected textures
|
||||
*(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB));
|
||||
*(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG));
|
||||
*(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
detailTexture[i].UnlockBits(datas[i]);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
detailTexture[i].UnlockBits(datas[i]);
|
||||
if (detailTexture[i] != null)
|
||||
detailTexture[i].Dispose();
|
||||
}
|
||||
|
||||
output.UnlockBits(outputData);
|
||||
|
||||
@@ -54,8 +54,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3");
|
||||
private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216);
|
||||
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private Scene m_scene;
|
||||
private IRendering m_primMesher;
|
||||
@@ -88,11 +87,11 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
if (renderers.Count > 0)
|
||||
{
|
||||
m_primMesher = RenderingLoader.LoadRenderer(renderers[0]);
|
||||
m_log.Debug("[MAPTILE]: Loaded prim mesher " + m_primMesher.ToString());
|
||||
m_log.DebugFormat("[WARP 3D IMAGE MODULE]: Loaded prim mesher {0}", m_primMesher);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Debug("[MAPTILE]: No prim mesher loaded, prim rendering will be disabled");
|
||||
m_log.Debug("[WARP 3D IMAGE MODULE]: No prim mesher loaded, prim rendering will be disabled");
|
||||
}
|
||||
|
||||
m_scene.RegisterModuleInterface<IMapImageGenerator>(this);
|
||||
@@ -150,7 +149,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_log.Warn("[MAPTILE]: Failed to load StartupConfig");
|
||||
m_log.Warn("[WARP 3D IMAGE MODULE]: Failed to load StartupConfig");
|
||||
}
|
||||
|
||||
m_colors.Clear();
|
||||
@@ -204,7 +203,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
Bitmap bitmap = renderer.Scene.getImage();
|
||||
|
||||
if (m_useAntiAliasing)
|
||||
bitmap = ImageUtils.ResizeImage(bitmap, viewport.Width, viewport.Height);
|
||||
{
|
||||
using (Bitmap origBitmap = bitmap)
|
||||
bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
@@ -219,7 +221,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
catch (Exception e)
|
||||
{
|
||||
// JPEG2000 encoder failed
|
||||
m_log.Error("[MAPTILE]: Failed generating terrain map: " + e);
|
||||
m_log.Error("[WARP 3D IMAGE MODULE]: Failed generating terrain map: ", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -318,8 +320,17 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
uint globalX, globalY;
|
||||
Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY);
|
||||
|
||||
Bitmap image = TerrainSplat.Splat(heightmap, textureIDs, startHeights, heightRanges, new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain);
|
||||
warp_Texture texture = new warp_Texture(image);
|
||||
warp_Texture texture;
|
||||
|
||||
using (
|
||||
Bitmap image
|
||||
= TerrainSplat.Splat(
|
||||
heightmap, textureIDs, startHeights, heightRanges,
|
||||
new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain))
|
||||
{
|
||||
texture = new warp_Texture(image);
|
||||
}
|
||||
|
||||
warp_Material material = new warp_Material(texture);
|
||||
material.setReflectivity(50);
|
||||
renderer.Scene.addMaterial("TerrainColor", material);
|
||||
@@ -546,42 +557,46 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
{
|
||||
try
|
||||
{
|
||||
Bitmap bitmap = (Bitmap)J2kImage.FromStream(stream);
|
||||
width = bitmap.Width;
|
||||
height = bitmap.Height;
|
||||
int pixelBytes;
|
||||
|
||||
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||
int pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
|
||||
|
||||
// Sum up the individual channels
|
||||
unsafe
|
||||
using (Bitmap bitmap = (Bitmap)J2kImage.FromStream(stream))
|
||||
{
|
||||
if (pixelBytes == 4)
|
||||
width = bitmap.Width;
|
||||
height = bitmap.Height;
|
||||
|
||||
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||
pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
|
||||
|
||||
// Sum up the individual channels
|
||||
unsafe
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
if (pixelBytes == 4)
|
||||
{
|
||||
byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
b += row[x * pixelBytes + 0];
|
||||
g += row[x * pixelBytes + 1];
|
||||
r += row[x * pixelBytes + 2];
|
||||
a += row[x * pixelBytes + 3];
|
||||
byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
b += row[x * pixelBytes + 0];
|
||||
g += row[x * pixelBytes + 1];
|
||||
r += row[x * pixelBytes + 2];
|
||||
a += row[x * pixelBytes + 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
else
|
||||
{
|
||||
byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
b += row[x * pixelBytes + 0];
|
||||
g += row[x * pixelBytes + 1];
|
||||
r += row[x * pixelBytes + 2];
|
||||
byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
b += row[x * pixelBytes + 0];
|
||||
g += row[x * pixelBytes + 1];
|
||||
r += row[x * pixelBytes + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -603,7 +618,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.WarnFormat("[MAPTILE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}", textureID, j2kData.Length, ex.Message);
|
||||
m_log.WarnFormat(
|
||||
"[WARP 3D IMAGE MODULE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}",
|
||||
textureID, j2kData.Length, ex.Message);
|
||||
|
||||
width = 0;
|
||||
height = 0;
|
||||
return new Color4(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
@@ -730,7 +730,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||
{
|
||||
if (Environment.TickCount > (m_blacklistedregions[regionhandle] + blacklistTimeout))
|
||||
{
|
||||
m_log.DebugFormat("[WORLDMAP]: Unblock blacklisted region {0}", regionhandle);
|
||||
m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted region {0}", regionhandle);
|
||||
|
||||
m_blacklistedregions.Remove(regionhandle);
|
||||
}
|
||||
@@ -781,7 +781,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||
{
|
||||
if (Environment.TickCount > (m_blacklistedurls[httpserver] + blacklistTimeout))
|
||||
{
|
||||
m_log.DebugFormat("[WORLDMAP]: Unblock blacklisted URL {0}", httpserver);
|
||||
m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted URL {0}", httpserver);
|
||||
|
||||
m_blacklistedurls.Remove(httpserver);
|
||||
}
|
||||
@@ -1343,14 +1343,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||
if (terrain == null)
|
||||
return;
|
||||
|
||||
m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.RegionInfo.RegionName);
|
||||
|
||||
byte[] data = terrain.WriteJpeg2000Image();
|
||||
if (data == null)
|
||||
return;
|
||||
|
||||
byte[] overlay = GenerateOverlay();
|
||||
|
||||
m_log.Debug("[WORLDMAP]: STORING MAPTILE IMAGE");
|
||||
|
||||
UUID terrainImageID = UUID.Random();
|
||||
UUID parcelImageID = UUID.Zero;
|
||||
|
||||
@@ -1365,7 +1365,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||
asset.Flags = AssetFlags.Maptile;
|
||||
|
||||
// Store the new one
|
||||
m_log.DebugFormat("[WORLDMAP]: Storing map tile {0}", asset.ID);
|
||||
m_log.DebugFormat("[WORLD MAP]: Storing map tile {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName);
|
||||
|
||||
m_scene.AssetService.Store(asset);
|
||||
|
||||
if (overlay != null)
|
||||
|
||||
@@ -35,6 +35,20 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
{
|
||||
public interface IAttachmentsModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Copy attachment data from a ScenePresence into the AgentData structure for transmission to another simulator
|
||||
/// </summary>
|
||||
/// <param name='sp'></param>
|
||||
/// <param name='ad'></param>
|
||||
void CopyAttachments(IScenePresence sp, AgentData ad);
|
||||
|
||||
/// <summary>
|
||||
/// Copy attachment data from an AgentData structure into a ScenePresence.
|
||||
/// </summary>
|
||||
/// <param name='ad'></param>
|
||||
/// <param name='sp'></param>
|
||||
void CopyAttachments(AgentData ad, IScenePresence sp);
|
||||
|
||||
/// <summary>
|
||||
/// RezAttachments. This should only be called upon login on the first region.
|
||||
/// Attachment rezzings on crossings and TPs are done in a different way.
|
||||
@@ -43,10 +57,15 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
void RezAttachments(IScenePresence sp);
|
||||
|
||||
/// <summary>
|
||||
/// Save the attachments that have change on this presence.
|
||||
/// Derez the attachements for a scene presence that is closing.
|
||||
/// </summary>
|
||||
/// <param name="sp"></param>
|
||||
void SaveChangedAttachments(IScenePresence sp, bool saveAllScripted);
|
||||
/// <remarks>
|
||||
/// Attachment changes are saved.
|
||||
/// </remarks>
|
||||
/// <param name="sp">The presence closing</param>
|
||||
/// <param name="saveChanged">Save changed attachments.</param>
|
||||
/// <param name="saveAllScripted">Save attachments with scripts even if they haven't changed.</para>
|
||||
void DeRezAttachments(IScenePresence sp, bool saveChanged, bool saveAllScripted);
|
||||
|
||||
/// <summary>
|
||||
/// Delete all the presence's attachments from the scene
|
||||
@@ -73,7 +92,7 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// <param name="itemID"></param>
|
||||
/// <param name="AttachmentPt"></param>
|
||||
/// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
|
||||
ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt);
|
||||
SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt);
|
||||
|
||||
/// <summary>
|
||||
/// Rez multiple attachments from a user's inventory
|
||||
@@ -90,11 +109,11 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID);
|
||||
|
||||
/// <summary>
|
||||
/// Detach the given item so that it remains in the user's inventory.
|
||||
/// Detach the given attachment so that it remains in the user's inventory.
|
||||
/// </summary>
|
||||
/// <param name="sp">/param>
|
||||
/// <param name="itemID"></param>
|
||||
void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID);
|
||||
/// <param name="grp">The attachment to detach.</param>
|
||||
void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup grp);
|
||||
|
||||
/// <summary>
|
||||
/// Update the position of an attachment.
|
||||
|
||||
@@ -81,13 +81,18 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// <summary>
|
||||
/// Start all the scripts contained in this entity's inventory
|
||||
/// </summary>
|
||||
void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource);
|
||||
/// <param name="startParam"></param>
|
||||
/// <param name="postOnRez"></param>
|
||||
/// <param name="engine"></param>
|
||||
/// <param name="stateSource"></param>
|
||||
/// <returns>Number of scripts started.</returns>
|
||||
int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource);
|
||||
|
||||
ArrayList GetScriptErrors(UUID itemID);
|
||||
void ResumeScripts();
|
||||
|
||||
/// <summary>
|
||||
/// Stop all the scripts in this entity.
|
||||
/// Stop and remove all the scripts in this entity from the scene.
|
||||
/// </summary>
|
||||
/// <param name="sceneObjectBeingDeleted">
|
||||
/// Should be true if these scripts are being removed because the scene
|
||||
@@ -95,6 +100,11 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// </param>
|
||||
void RemoveScriptInstances(bool sceneObjectBeingDeleted);
|
||||
|
||||
/// <summary>
|
||||
/// Stop all the scripts in this entity.
|
||||
/// </summary>
|
||||
void StopScriptInstances();
|
||||
|
||||
/// <summary>
|
||||
/// Start a script which is in this entity's inventory.
|
||||
/// </summary>
|
||||
@@ -102,7 +112,11 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// <param name="postOnRez"></param>
|
||||
/// <param name="engine"></param>
|
||||
/// <param name="stateSource"></param>
|
||||
void CreateScriptInstance(
|
||||
/// <returns>
|
||||
/// true if the script instance was valid for starting, false otherwise. This does not guarantee
|
||||
/// that the script was actually started, just that the script was valid (i.e. its asset data could be found, etc.)
|
||||
/// </returns>
|
||||
bool CreateScriptInstance(
|
||||
TaskInventoryItem item, int startParam, bool postOnRez, string engine, int stateSource);
|
||||
|
||||
/// <summary>
|
||||
@@ -113,10 +127,14 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// <param name="postOnRez"></param>
|
||||
/// <param name="engine"></param>
|
||||
/// <param name="stateSource"></param>
|
||||
void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
|
||||
/// <returns>
|
||||
/// true if the script instance was valid for starting, false otherwise. This does not guarantee
|
||||
/// that the script was actually started, just that the script was valid (i.e. its asset data could be found, etc.)
|
||||
/// </returns>
|
||||
bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
|
||||
|
||||
/// <summary>
|
||||
/// Stop a script which is in this prim's inventory.
|
||||
/// Stop and remove a script which is in this prim's inventory from the scene.
|
||||
/// </summary>
|
||||
/// <param name="itemId"></param>
|
||||
/// <param name="sceneObjectBeingDeleted">
|
||||
@@ -125,6 +143,12 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// </param>
|
||||
void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted);
|
||||
|
||||
/// <summary>
|
||||
/// Stop a script which is in this prim's inventory.
|
||||
/// </summary>
|
||||
/// <param name="itemId"></param>
|
||||
void StopScriptInstance(UUID itemId);
|
||||
|
||||
/// <summary>
|
||||
/// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative
|
||||
/// name is chosen.
|
||||
@@ -163,6 +187,19 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// </returns>
|
||||
List<TaskInventoryItem> GetInventoryItems();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an inventory item by name
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method returns the first inventory item that matches the given name. In SL this is all you need
|
||||
/// since each item in a prim inventory must have a unique name.
|
||||
/// </remarks>
|
||||
/// <param name='name'></param>
|
||||
/// <returns>
|
||||
/// The inventory item. Null if no such item was found.
|
||||
/// </returns>
|
||||
TaskInventoryItem GetInventoryItem(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Get inventory items by name.
|
||||
/// </summary>
|
||||
|
||||
@@ -183,6 +183,14 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// <returns>true if the stand succeeded, false if not</returns>
|
||||
bool Stand(UUID agentID, Scene scene);
|
||||
|
||||
/// <summary>
|
||||
/// Get the NPC to touch an object.
|
||||
/// </summary>
|
||||
/// <param name="agentID"></param>
|
||||
/// <param name="partID"></param>
|
||||
/// <returns>true if the touch is actually attempted, false if not</returns>
|
||||
bool Touch(UUID agentID, UUID partID);
|
||||
|
||||
/// <summary>
|
||||
/// Delete an NPC.
|
||||
/// </summary>
|
||||
|
||||
@@ -40,6 +40,12 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// </remarks>
|
||||
public interface IScenePresence : ISceneAgent
|
||||
{
|
||||
/// <summary>
|
||||
/// Copy of the script states while the agent is in transit. This state may
|
||||
/// need to be placed back in case of transfer fail.
|
||||
/// </summary>
|
||||
List<string> InTransitScriptStates { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The AttachmentsModule synchronizes on this to avoid race conditions between commands to add and remove attachments.
|
||||
/// </summary>
|
||||
@@ -66,6 +72,10 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// <returns></returns>
|
||||
List<SceneObjectGroup> GetAttachments(uint attachmentPoint);
|
||||
|
||||
/// <summary>
|
||||
/// Does this avatar have any attachments?
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool HasAttachments();
|
||||
|
||||
// Don't use these methods directly. Instead, use the AttachmentsModule
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user