Merge branch 'httptests' of opensimulator.org:/var/git/opensim into httptests

httptests
UbitUmarov 2016-08-07 00:24:17 +01:00
commit 68a4e363dd
14 changed files with 355 additions and 5918 deletions

View File

@ -30,6 +30,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenMetaverse; using OpenMetaverse;
@ -59,7 +60,6 @@ namespace OpenSim.Capabilities.Handlers
m_LibraryService = libService; m_LibraryService = libService;
m_Scene = s; m_Scene = s;
} }
public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{ {
@ -93,8 +93,8 @@ namespace OpenSim.Capabilities.Handlers
ArrayList foldersrequested = (ArrayList)hash["folders"]; ArrayList foldersrequested = (ArrayList)hash["folders"];
string response = ""; StringBuilder tmpresponse = new StringBuilder(1024);
string bad_folders_response = ""; StringBuilder tmpbadfolders = new StringBuilder(1024);
List<LLSDFetchInventoryDescendents> folders = new List<LLSDFetchInventoryDescendents>(); List<LLSDFetchInventoryDescendents> folders = new List<LLSDFetchInventoryDescendents>();
for (int i = 0; i < foldersrequested.Count; i++) for (int i = 0; i < foldersrequested.Count; i++)
@ -136,49 +136,44 @@ namespace OpenSim.Capabilities.Handlers
string inventoryitemstr = string.Empty; string inventoryitemstr = string.Empty;
foreach (InventoryCollectionWithDescendents icoll in invcollSet) foreach (InventoryCollectionWithDescendents icoll in invcollSet)
{ {
LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents); LLSDInventoryFolderContents thiscontents = contentsToLLSD(icoll.Collection, icoll.Descendents);
inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(thiscontents);
inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); // inventoryitemstr = inventoryitemstr.Replace("<llsd>", "");
inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", ""); // inventoryitemstr = inventoryitemstr.Replace("</llsd>", "");
inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", ""); // inventoryitemstr = inventoryitemstr.Substring(6,inventoryitemstr.Length - 13);
// tmpresponse.Append(inventoryitemstr);
response += inventoryitemstr; tmpresponse.Append(inventoryitemstr.Substring(6,inventoryitemstr.Length - 13));
} }
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders)); //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders));
foreach (UUID bad in bad_folders) foreach (UUID bad in bad_folders)
bad_folders_response += "<uuid>" + bad + "</uuid>"; {
tmpbadfolders.Append("<map><key>folder_id</key><uuid>");
tmpbadfolders.Append(bad.ToString());
tmpbadfolders.Append("</uuid><key>error</key><string>Unknown</string></map>");
}
} }
if (response.Length == 0) StringBuilder lastresponse = new StringBuilder(1024);
lastresponse.Append("<llsd>");
if(tmpresponse.Length > 0)
{ {
/* Viewers expect a bad_folders array when not available */ lastresponse.Append("<map><key>folders</key><array>");
if (bad_folders_response.Length != 0) lastresponse.Append(tmpresponse.ToString());
{ lastresponse.Append("</array></map>");
response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
}
else
{
response = "<llsd><map><key>folders</key><array /></map></llsd>";
}
} }
else else
lastresponse.Append("<map><key>folders</key><array /></map>");
if(tmpbadfolders.Length > 0)
{ {
if (bad_folders_response.Length != 0) lastresponse.Append("<map><key>bad_folders</key><array>");
{ lastresponse.Append(tmpbadfolders.ToString());
response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>"; lastresponse.Append("</array></map>");
}
else
{
response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
}
} }
lastresponse.Append("</llsd>");
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request for {0} folders. Item count {1}", folders.Count, item_count); return lastresponse.ToString();
//m_log.Debug("[WEB FETCH INV DESC HANDLER] " + response);
return response;
} }
/// <summary> /// <summary>
@ -240,24 +235,19 @@ namespace OpenSim.Capabilities.Handlers
return reply; return reply;
} }
private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents) private LLSDInventoryFolderContents contentsToLLSD(InventoryCollection inv, int descendents)
{ {
LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
contents.agent_id = inv.OwnerID; contents.agent_id = inv.OwnerID;
contents.owner_id = inv.OwnerID; contents.owner_id = inv.OwnerID;
contents.folder_id = inv.FolderID; contents.folder_id = inv.FolderID;
reply.folders.Array.Add(contents);
if (inv.Folders != null) if (inv.Folders != null)
{ {
foreach (InventoryFolderBase invFolder in inv.Folders) foreach (InventoryFolderBase invFolder in inv.Folders)
{ {
contents.categories.Array.Add(ConvertInventoryFolder(invFolder)); contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
} }
descendents += inv.Folders.Count;
} }
if (inv.Items != null) if (inv.Items != null)
@ -271,7 +261,7 @@ namespace OpenSim.Capabilities.Handlers
contents.descendents = descendents; contents.descendents = descendents;
contents.version = inv.Version; contents.version = inv.Version;
return reply; return contents;
} }
/// <summary> /// <summary>
/// Old style. Soon to be deprecated. /// Old style. Soon to be deprecated.
@ -285,8 +275,8 @@ namespace OpenSim.Capabilities.Handlers
{ {
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count); //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count);
string response = ""; StringBuilder tmpresponse = new StringBuilder(1024);
string bad_folders_response = ""; StringBuilder tmpbadfolders = new StringBuilder(1024);
for (int i = 0; i < foldersrequested.Count; i++) for (int i = 0; i < foldersrequested.Count; i++)
{ {
@ -308,7 +298,9 @@ namespace OpenSim.Capabilities.Handlers
if (null == reply) if (null == reply)
{ {
bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>"; tmpbadfolders.Append("<map><key>folder_id</key><uuid>");
tmpbadfolders.Append(llsdRequest.folder_id.ToString());
tmpbadfolders.Append("</uuid><key>error</key><string>Unknown</string></map>");
} }
else else
{ {
@ -317,39 +309,29 @@ namespace OpenSim.Capabilities.Handlers
inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", ""); inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
} }
response += inventoryitemstr; tmpresponse.Append(inventoryitemstr);
} }
if (response.Length == 0) StringBuilder lastresponse = new StringBuilder(1024);
lastresponse.Append("<llsd>");
if(tmpresponse.Length > 0)
{ {
/* Viewers expect a bad_folders array when not available */ lastresponse.Append("<map><key>folders</key><array>");
if (bad_folders_response.Length != 0) lastresponse.Append(tmpresponse.ToString());
{ lastresponse.Append("</array></map>");
response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
}
else
{
response = "<llsd><map><key>folders</key><array /></map></llsd>";
}
} }
else else
lastresponse.Append("<map><key>folders</key><array /></map>");
if(tmpbadfolders.Length > 0)
{ {
if (bad_folders_response.Length != 0) lastresponse.Append("<map><key>bad_folders</key><array>");
{ lastresponse.Append(tmpbadfolders.ToString());
response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>"; lastresponse.Append("</array></map>");
}
else
{
response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
}
} }
lastresponse.Append("</llsd>");
// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request"); return lastresponse.ToString();
//m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
return response;
// }
} }
/// <summary> /// <summary>
@ -436,108 +418,7 @@ namespace OpenSim.Capabilities.Handlers
itemsToReturn.Insert(0, linkedItem); 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
/* dont send contents of LinkFolders.
from docs seems this was never a spec
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)
// {
// 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)
// {
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
// linkedItem.Name, folderID, agentID);
//
// contents.Items.Add(linkedItem);
// }
//
// // If the folder requested contains links, then we need to send those folders first, otherwise the links
// // will be broken in the viewer.
// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
// 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)
// {
// // We don't need to send the folder if source and destination of the link are in the same
// // folder.
// if (linkedItem.Folder != containingFolder.ID)
// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
// }
// }
// }
//
// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
// {
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
// linkedItemFolderId, folderID, agentID);
//
// int dummyVersion;
// InventoryCollection linkedCollection
// = Fetch(
// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
//
// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
// linkedFolder.Owner = agentID;
// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
//
//// contents.Folders.AddRange(linkedCollection.Folders);
//
// contents.Folders.Add(linkedFolder);
// contents.Items.AddRange(linkedCollection.Items);
// }
// }
} }
} }
else else
@ -566,13 +447,14 @@ from docs seems this was never a spec
{ {
InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents(); InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents();
ret.Collection = new InventoryCollection(); ret.Collection = new InventoryCollection();
ret.Collection.Folders = new List<InventoryFolderBase>(); // ret.Collection.Folders = new List<InventoryFolderBase>();
ret.Collection.Folders = fold.RequestListOfFolders();
ret.Collection.Items = fold.RequestListOfItems(); ret.Collection.Items = fold.RequestListOfItems();
ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner; ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner;
ret.Collection.FolderID = f.folder_id; ret.Collection.FolderID = f.folder_id;
ret.Collection.Version = fold.Version; ret.Collection.Version = fold.Version;
ret.Descendents = ret.Collection.Items.Count; ret.Descendents = ret.Collection.Items.Count + ret.Collection.Folders.Count;
result.Add(ret); result.Add(ret);
//m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID); //m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID);
@ -594,11 +476,18 @@ from docs seems this was never a spec
// Filter folder Zero right here. Some viewers (Firestorm) send request for folder Zero, which doesn't make sense // Filter folder Zero right here. Some viewers (Firestorm) send request for folder Zero, which doesn't make sense
// and can kill the sim (all root folders have parent_id Zero) // and can kill the sim (all root folders have parent_id Zero)
// send something.
LLSDFetchInventoryDescendents zero = fetchFolders.Find(f => f.folder_id == UUID.Zero); LLSDFetchInventoryDescendents zero = fetchFolders.Find(f => f.folder_id == UUID.Zero);
if (zero != null) if (zero != null)
{ {
fetchFolders.Remove(zero); fetchFolders.Remove(zero);
BadFolder(zero, null, bad_folders); InventoryCollectionWithDescendents zeroColl = new InventoryCollectionWithDescendents();
zeroColl.Collection = new InventoryCollection();
zeroColl.Collection.OwnerID = zero.owner_id;
zeroColl.Collection.Version = 0;
zeroColl.Collection.FolderID = zero.folder_id;
zeroColl.Descendents = 0;
result.Add(zeroColl);
} }
if (fetchFolders.Count > 0) if (fetchFolders.Count > 0)
@ -666,35 +555,8 @@ from docs seems this was never a spec
} }
else else
{ {
// Was it really a request for folder Zero? m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
// This is an overkill, but Firestorm really asks for folder Zero. bad_folders.Add(freq.folder_id);
// I'm leaving the code here for the time being, but commented.
if (freq.folder_id == UUID.Zero)
{
//coll.Collection.OwnerID = freq.owner_id;
//coll.Collection.FolderID = contents.FolderID;
//containingFolder = m_InventoryService.GetRootFolder(freq.owner_id);
//if (containingFolder != null)
//{
// m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID);
// coll.Collection.Folders.Clear();
// coll.Collection.Folders.Add(containingFolder);
// if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
// {
// InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner);
// lib.Name = m_LibraryService.LibraryRootFolder.Name;
// lib.Type = m_LibraryService.LibraryRootFolder.Type;
// lib.Version = m_LibraryService.LibraryRootFolder.Version;
// coll.Collection.Folders.Add(lib);
// }
// coll.Collection.Items.Clear();
//}
}
else
{
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
bad_folders.Add(freq.folder_id);
}
bad = true; bad = true;
} }
} }
@ -708,42 +570,21 @@ from docs seems this was never a spec
if (freq.fetch_items && contents.Items != null) if (freq.fetch_items && contents.Items != null)
{ {
List<InventoryItemBase> itemsToReturn = contents.Items; // viewers are lasy and want a copy of the linked item sent before the link to it
// descendents must only include the links, not the linked items we add // descendents must only include the links, not the linked items we add
coll.Descendents = itemsToReturn.Count; coll.Descendents = contents.Items.Count + contents.Folders.Count;
// Add target items for links in this folder before the links themselves. // look for item links
List<UUID> itemIDs = new List<UUID>(); List<UUID> itemIDs = new List<UUID>();
List<UUID> folderIDs = new List<UUID>(); foreach (InventoryItemBase item in contents.Items)
foreach (InventoryItemBase item in itemsToReturn)
{ {
//m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType); //m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType);
if (item.AssetType == (int)AssetType.Link) if (item.AssetType == (int)AssetType.Link)
itemIDs.Add(item.AssetID); itemIDs.Add(item.AssetID);
// else if (item.AssetType == (int)AssetType.LinkFolder)
// folderIDs.Add(item.AssetID);
}
//m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count);
// Scan for folder links and insert the items they target and those links at the head of the return data
if (folderIDs.Count > 0)
{
InventoryCollection[] linkedFolders = m_InventoryService.GetMultipleFoldersContent(coll.Collection.OwnerID, folderIDs.ToArray());
foreach (InventoryCollection linkedFolderContents in linkedFolders)
{
if (linkedFolderContents == null)
continue;
List<InventoryItemBase> links = linkedFolderContents.Items;
itemsToReturn.InsertRange(0, links);
}
} }
// get the linked if any
if (itemIDs.Count > 0) if (itemIDs.Count > 0)
{ {
InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray()); InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray());
@ -758,13 +599,11 @@ from docs seems this was never a spec
linked[i++] = m_InventoryService.GetItem(freq.owner_id, id); linked[i++] = m_InventoryService.GetItem(freq.owner_id, id);
} }
} }
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Processing folder {0}. Existing items:", freq.folder_id);
//foreach (InventoryItemBase item in itemsToReturn)
// m_log.DebugFormat("[XXX]: {0} {1} {2}", item.Name, item.AssetType, item.Folder);
if (linked != null) if (linked != null)
{ {
List<InventoryItemBase> linkedItems = new List<InventoryItemBase>();
// check for broken
foreach (InventoryItemBase linkedItem in linked) foreach (InventoryItemBase linkedItem in linked)
{ {
// Take care of genuinely broken links where the target doesn't exist // Take care of genuinely broken links where the target doesn't exist
@ -773,14 +612,16 @@ from docs seems this was never a spec
// rather than having to keep track of every folder requested in the recursion. // rather than having to keep track of every folder requested in the recursion.
if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
{ {
itemsToReturn.Insert(0, linkedItem); linkedItems.Add(linkedItem);
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder); //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder);
} }
} }
// insert them
if(linkedItems.Count > 0)
contents.Items.InsertRange(0,linkedItems);
} }
} }
} }
} }
/// <summary> /// <summary>

View File

@ -234,7 +234,7 @@ namespace OpenSim.Framework.Console
string uri = "/ReadResponses/" + sessionID.ToString() + "/"; string uri = "/ReadResponses/" + sessionID.ToString() + "/";
m_Server.AddPollServiceHTTPHandler( m_Server.AddPollServiceHTTPHandler(
uri, new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, sessionID,25000)); // 25 secs timeout uri, new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, Drop, sessionID, 25000)); // 25 secs timeout
XmlDocument xmldoc = new XmlDocument(); XmlDocument xmldoc = new XmlDocument();
XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
@ -425,6 +425,15 @@ namespace OpenSim.Framework.Console
return false; return false;
} }
private void Drop(UUID RequestID, UUID sessionID)
{
lock (m_Connections)
{
if (m_Connections.ContainsKey(sessionID))
m_Connections.Remove(sessionID);
}
}
private Hashtable GetEvents(UUID RequestID, UUID sessionID) private Hashtable GetEvents(UUID RequestID, UUID sessionID)
{ {
ConsoleConnection c = null; ConsoleConnection c = null;

View File

@ -37,6 +37,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId); public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId);
public delegate Hashtable NoEventsMethod(UUID requestID, UUID pId); public delegate Hashtable NoEventsMethod(UUID requestID, UUID pId);
public delegate void DropMethod(UUID requestID, UUID pId);
public class PollServiceEventArgs : EventArgs public class PollServiceEventArgs : EventArgs
{ {
@ -44,6 +45,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public GetEventsMethod GetEvents; public GetEventsMethod GetEvents;
public NoEventsMethod NoEvents; public NoEventsMethod NoEvents;
public RequestMethod Request; public RequestMethod Request;
public DropMethod Drop;
public UUID Id; public UUID Id;
public int TimeOutms; public int TimeOutms;
public EventType Type; public EventType Type;
@ -73,13 +75,14 @@ namespace OpenSim.Framework.Servers.HttpServer
RequestMethod pRequest, RequestMethod pRequest,
string pUrl, string pUrl,
HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents, HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,
UUID pId, int pTimeOutms) DropMethod pDrop, UUID pId, int pTimeOutms)
{ {
Request = pRequest; Request = pRequest;
Url = pUrl; Url = pUrl;
HasEvents = pHasEvents; HasEvents = pHasEvents;
GetEvents = pGetEvents; GetEvents = pGetEvents;
NoEvents = pNoEvents; NoEvents = pNoEvents;
Drop = pDrop;
Id = pId; Id = pId;
TimeOutms = pTimeOutms; TimeOutms = pTimeOutms;
Type = EventType.LongPoll; Type = EventType.LongPoll;

View File

@ -47,8 +47,10 @@ namespace OpenSim.Framework.Servers.HttpServer
public readonly UUID RequestID; public readonly UUID RequestID;
public int contextHash; public int contextHash;
/*
private void GenContextHash() private void GenContextHash()
{ {
Random rnd = new Random(); Random rnd = new Random();
contextHash = 0; contextHash = 0;
if (Request.Headers["remote_addr"] != null) if (Request.Headers["remote_addr"] != null)
@ -62,8 +64,9 @@ namespace OpenSim.Framework.Servers.HttpServer
} }
else else
contextHash += rnd.Next() & 0xffff; contextHash += rnd.Next() & 0xffff;
}
}
*/
public PollServiceHttpRequest( public PollServiceHttpRequest(
PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest) PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest)
{ {
@ -72,7 +75,8 @@ namespace OpenSim.Framework.Servers.HttpServer
Request = pRequest; Request = pRequest;
RequestTime = System.Environment.TickCount; RequestTime = System.Environment.TickCount;
RequestID = UUID.Random(); RequestID = UUID.Random();
GenContextHash(); // GenContextHash();
contextHash = HttpContext.contextID;
} }
internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata) internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata)
@ -132,8 +136,9 @@ namespace OpenSim.Framework.Servers.HttpServer
{ {
if (b1.contextHash != b2.contextHash) if (b1.contextHash != b2.contextHash)
return false; return false;
bool b = Object.ReferenceEquals(b1.HttpContext, b2.HttpContext); // bool b = Object.ReferenceEquals(b1.HttpContext, b2.HttpContext);
return b; // return b;
return true;
} }
public int GetHashCode(PollServiceHttpRequest b2) public int GetHashCode(PollServiceHttpRequest b2)

View File

@ -160,6 +160,19 @@ namespace OpenSim.Framework.Servers.HttpServer
} }
} }
public void DropByContext(PollServiceHttpRequest req)
{
Queue<PollServiceHttpRequest> ctxQeueue;
lock (m_bycontext)
{
if (m_bycontext.TryGetValue(req, out ctxQeueue))
{
ctxQeueue.Clear();
m_bycontext.Remove(req);
}
}
}
public void EnqueueInt(PollServiceHttpRequest req) public void EnqueueInt(PollServiceHttpRequest req)
{ {
if (m_running) if (m_running)
@ -263,22 +276,61 @@ namespace OpenSim.Framework.Servers.HttpServer
PollServiceHttpRequest req = m_requests.Dequeue(5000); PollServiceHttpRequest req = m_requests.Dequeue(5000);
Watchdog.UpdateThread(); Watchdog.UpdateThread();
if (req != null) if(req == null)
{ continue;
try
{
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
{
Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
try
{
if(!req.HttpContext.CanSend())
{
req.PollServiceArgs.Drop(req.RequestID, req.PollServiceArgs.Id);
byContextDequeue(req);
continue;
}
if(req.HttpContext.IsSending())
{
if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
{
req.PollServiceArgs.Drop(req.RequestID, req.PollServiceArgs.Id);
byContextDequeue(req);
}
else
ReQueueEvent(req);
continue;
}
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
{
Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
m_threadPool.QueueWorkItem(x =>
{
try
{
req.DoHTTPGruntWork(m_server, responsedata);
byContextDequeue(req);
}
catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
{
// Ignore it, no need to reply
}
return null;
}, null);
}
else
{
if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
{
m_threadPool.QueueWorkItem(x => m_threadPool.QueueWorkItem(x =>
{ {
try try
{ {
req.DoHTTPGruntWork(m_server, responsedata); req.DoHTTPGruntWork(m_server,
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
byContextDequeue(req); byContextDequeue(req);
} }
catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream catch (ObjectDisposedException)
{ {
// Ignore it, no need to reply // Ignore it, no need to reply
} }
@ -287,36 +339,15 @@ namespace OpenSim.Framework.Servers.HttpServer
} }
else else
{ {
if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) ReQueueEvent(req);
{
m_threadPool.QueueWorkItem(x =>
{
try
{
req.DoHTTPGruntWork(m_server,
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
byContextDequeue(req);
}
catch (ObjectDisposedException)
{
// Ignore it, no need to reply
}
return null;
}, null);
}
else
{
ReQueueEvent(req);
}
} }
} }
catch (Exception e) }
{ catch (Exception e)
m_log.ErrorFormat("Exception in poll service thread: " + e.ToString()); {
} m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
} }
} }
} }
} }
} }

View File

@ -372,7 +372,7 @@ namespace OpenSim.Region.ClientStack.Linden
caps.RegisterPollHandler( caps.RegisterPollHandler(
"EventQueueGet", "EventQueueGet",
new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS)); new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, Drop, agentID, SERVER_EQ_TIME_NO_EVENTS));
} }
public bool HasEvents(UUID requestID, UUID agentID) public bool HasEvents(UUID requestID, UUID agentID)

View File

@ -222,11 +222,12 @@ namespace OpenSim.Region.ClientStack.Linden
new List<Hashtable>(); new List<Hashtable>();
private Dictionary<UUID, aPollResponse> responses = private Dictionary<UUID, aPollResponse> responses =
new Dictionary<UUID, aPollResponse>(); new Dictionary<UUID, aPollResponse>();
private HashSet<UUID> dropedResponses = new HashSet<UUID>();
private Scene m_scene; private Scene m_scene;
private MeshCapsDataThrottler m_throttler; private MeshCapsDataThrottler m_throttler;
public PollServiceMeshEventArgs(string uri, UUID pId, Scene scene) : public PollServiceMeshEventArgs(string uri, UUID pId, Scene scene) :
base(null, uri, null, null, null, pId, int.MaxValue) base(null, uri, null, null, null, null, pId, int.MaxValue)
{ {
m_scene = scene; m_scene = scene;
m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId); m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId);
@ -241,6 +242,17 @@ namespace OpenSim.Region.ClientStack.Linden
} }
}; };
Drop = (x, y) =>
{
lock (responses)
{
responses.Remove(x);
lock(dropedResponses)
dropedResponses.Add(x);
}
};
GetEvents = (x, y) => GetEvents = (x, y) =>
{ {
lock (responses) lock (responses)
@ -298,26 +310,47 @@ namespace OpenSim.Region.ClientStack.Linden
if(m_scene.ShuttingDown) if(m_scene.ShuttingDown)
return; return;
// If the avatar is gone, don't bother to get the texture lock(responses)
if (m_scene.GetScenePresence(Id) == null)
{ {
response = new Hashtable(); lock(dropedResponses)
{
if(dropedResponses.Contains(requestID))
{
dropedResponses.Remove(requestID);
return;
}
}
// If the avatar is gone, don't bother to get the texture
if (m_scene.GetScenePresence(Id) == null)
{
response = new Hashtable();
response["int_response_code"] = 500; response["int_response_code"] = 500;
response["str_response_string"] = "Script timeout"; response["str_response_string"] = "Script timeout";
response["content_type"] = "text/plain"; response["content_type"] = "text/plain";
response["keepalive"] = false; response["keepalive"] = false;
response["reusecontext"] = false; response["reusecontext"] = false;
lock (responses)
responses[requestID] = new aPollResponse() { bytes = 0, response = response, lod = 0 }; responses[requestID] = new aPollResponse() { bytes = 0, response = response, lod = 0 };
return; return;
}
} }
response = m_getMeshHandler.Handle(requestinfo.request); response = m_getMeshHandler.Handle(requestinfo.request);
lock (responses) lock (responses)
{ {
lock(dropedResponses)
{
if(dropedResponses.Contains(requestID))
{
dropedResponses.Remove(requestID);
return;
}
}
responses[requestID] = new aPollResponse() responses[requestID] = new aPollResponse()
{ {
bytes = (int)response["int_bytes"], bytes = (int)response["int_bytes"],

View File

@ -218,11 +218,12 @@ namespace OpenSim.Region.ClientStack.Linden
new List<Hashtable>(); new List<Hashtable>();
private Dictionary<UUID, aPollResponse> responses = private Dictionary<UUID, aPollResponse> responses =
new Dictionary<UUID, aPollResponse>(); new Dictionary<UUID, aPollResponse>();
private HashSet<UUID> dropedResponses = new HashSet<UUID>();
private Scene m_scene; private Scene m_scene;
private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000); private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000);
public PollServiceTextureEventArgs(UUID pId, Scene scene) : public PollServiceTextureEventArgs(UUID pId, Scene scene) :
base(null, "", null, null, null, pId, int.MaxValue) base(null, "", null, null, null, null, pId, int.MaxValue)
{ {
m_scene = scene; m_scene = scene;
// x is request id, y is userid // x is request id, y is userid
@ -236,6 +237,16 @@ namespace OpenSim.Region.ClientStack.Linden
} }
}; };
Drop = (x, y) =>
{
lock (responses)
{
responses.Remove(x);
dropedResponses.Add(x);
}
};
GetEvents = (x, y) => GetEvents = (x, y) =>
{ {
lock (responses) lock (responses)
@ -304,52 +315,71 @@ namespace OpenSim.Region.ClientStack.Linden
if(m_scene.ShuttingDown) if(m_scene.ShuttingDown)
return; return;
if (requestinfo.send503)
{
response = new Hashtable();
response["int_response_code"] = 503;
response["str_response_string"] = "Throttled";
response["content_type"] = "text/plain";
response["keepalive"] = false;
response["reusecontext"] = false;
Hashtable headers = new Hashtable();
headers["Retry-After"] = 30;
response["headers"] = headers;
lock (responses)
responses[requestID] = new aPollResponse() {bytes = 0, response = response};
return;
}
// If the avatar is gone, don't bother to get the texture
if (m_scene.GetScenePresence(Id) == null)
{
response = new Hashtable();
response["int_response_code"] = 500;
response["str_response_string"] = "Script timeout";
response["content_type"] = "text/plain";
response["keepalive"] = false;
response["reusecontext"] = false;
lock (responses)
responses[requestID] = new aPollResponse() {bytes = 0, response = response};
return;
}
response = m_getTextureHandler.Handle(requestinfo.request);
lock (responses) lock (responses)
{ {
responses[requestID] = new aPollResponse() lock(dropedResponses)
{ {
bytes = (int) response["int_bytes"], if(dropedResponses.Contains(requestID))
response = response {
}; dropedResponses.Remove(requestID);
return;
}
}
if (requestinfo.send503)
{
response = new Hashtable();
response["int_response_code"] = 503;
response["str_response_string"] = "Throttled";
response["content_type"] = "text/plain";
response["keepalive"] = false;
response["reusecontext"] = false;
Hashtable headers = new Hashtable();
headers["Retry-After"] = 30;
response["headers"] = headers;
responses[requestID] = new aPollResponse() {bytes = 0, response = response};
return;
}
// If the avatar is gone, don't bother to get the texture
if (m_scene.GetScenePresence(Id) == null)
{
response = new Hashtable();
response["int_response_code"] = 500;
response["str_response_string"] = "Script timeout";
response["content_type"] = "text/plain";
response["keepalive"] = false;
response["reusecontext"] = false;
responses[requestID] = new aPollResponse() {bytes = 0, response = response};
return;
}
}
response = m_getTextureHandler.Handle(requestinfo.request);
lock (responses)
{
lock(dropedResponses)
{
if(dropedResponses.Contains(requestID))
{
dropedResponses.Remove(requestID);
m_throttler.ProcessTime();
return;
}
}
responses[requestID] = new aPollResponse()
{
bytes = (int) response["int_bytes"],
response = response
};
} }
m_throttler.ProcessTime(); m_throttler.ProcessTime();
} }
@ -423,7 +453,6 @@ namespace OpenSim.Region.ClientStack.Linden
internal sealed class CapsDataThrottler internal sealed class CapsDataThrottler
{ {
private volatile int currenttime = 0; private volatile int currenttime = 0;
private volatile int lastTimeElapsed = 0; private volatile int lastTimeElapsed = 0;
private volatile int BytesSent = 0; private volatile int BytesSent = 0;

View File

@ -61,7 +61,6 @@ namespace OpenSim.Region.ClientStack.Linden
public UUID reqID; public UUID reqID;
public Hashtable request; public Hashtable request;
public ScenePresence presence; public ScenePresence presence;
public List<UUID> folders;
} }
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -250,17 +249,28 @@ namespace OpenSim.Region.ClientStack.Linden
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Dictionary<UUID, Hashtable> responses = private Dictionary<UUID, Hashtable> responses = new Dictionary<UUID, Hashtable>();
new Dictionary<UUID, Hashtable>(); private HashSet<UUID> dropedResponses = new HashSet<UUID>();
private WebFetchInvDescModule m_module; private WebFetchInvDescModule m_module;
public PollServiceInventoryEventArgs(WebFetchInvDescModule module, string url, UUID pId) : public PollServiceInventoryEventArgs(WebFetchInvDescModule module, string url, UUID pId) :
base(null, url, null, null, null, pId, int.MaxValue) base(null, url, null, null, null, null, pId, int.MaxValue)
{ {
m_module = module; m_module = module;
HasEvents = (x, y) => { lock (responses) return responses.ContainsKey(x); }; HasEvents = (x, y) => { lock (responses) return responses.ContainsKey(x); };
Drop = (x, y) =>
{
lock (responses)
{
responses.Remove(x);
lock(dropedResponses)
dropedResponses.Add(x);
}
};
GetEvents = (x, y) => GetEvents = (x, y) =>
{ {
lock (responses) lock (responses)
@ -285,8 +295,10 @@ namespace OpenSim.Region.ClientStack.Linden
reqinfo.reqID = x; reqinfo.reqID = x;
reqinfo.request = y; reqinfo.request = y;
reqinfo.presence = sp; reqinfo.presence = sp;
reqinfo.folders = new List<UUID>();
/* why where we doing this? just to get cof ?
List<UUID> folders = new List<UUID>();
// Decode the request here // Decode the request here
string request = y["body"].ToString(); string request = y["body"].ToString();
@ -322,11 +334,11 @@ namespace OpenSim.Region.ClientStack.Linden
UUID folderID; UUID folderID;
if (UUID.TryParse(folder, out folderID)) if (UUID.TryParse(folder, out folderID))
{ {
if (!reqinfo.folders.Contains(folderID)) if (!folders.Contains(folderID))
{ {
if (sp.COF != UUID.Zero && sp.COF == folderID) if (sp.COF != UUID.Zero && sp.COF == folderID)
highPriority = true; highPriority = true;
reqinfo.folders.Add(folderID); folders.Add(folderID);
} }
} }
} }
@ -334,6 +346,7 @@ namespace OpenSim.Region.ClientStack.Linden
if (highPriority) if (highPriority)
m_queue.PriorityEnqueue(reqinfo); m_queue.PriorityEnqueue(reqinfo);
else else
*/
m_queue.Enqueue(reqinfo); m_queue.Enqueue(reqinfo);
}; };
@ -365,6 +378,19 @@ namespace OpenSim.Region.ClientStack.Linden
UUID requestID = requestinfo.reqID; UUID requestID = requestinfo.reqID;
lock(responses)
{
lock(dropedResponses)
{
if(dropedResponses.Contains(requestID))
{
dropedResponses.Remove(requestID);
return;
}
}
}
Hashtable response = new Hashtable(); Hashtable response = new Hashtable();
response["int_response_code"] = 200; response["int_response_code"] = 200;
@ -377,11 +403,21 @@ namespace OpenSim.Region.ClientStack.Linden
lock (responses) lock (responses)
{ {
lock(dropedResponses)
{
if(dropedResponses.Contains(requestID))
{
dropedResponses.Remove(requestID);
requestinfo.request.Clear();
WebFetchInvDescModule.ProcessedRequestsCount++;
return;
}
}
if (responses.ContainsKey(requestID)) if (responses.ContainsKey(requestID))
m_log.WarnFormat("[FETCH INVENTORY DESCENDENTS2 MODULE]: Caught in the act of loosing responses! Please report this on mantis #7054"); m_log.WarnFormat("[FETCH INVENTORY DESCENDENTS2 MODULE]: Caught in the act of loosing responses! Please report this on mantis #7054");
responses[requestID] = response; responses[requestID] = response;
} }
requestinfo.folders.Clear();
requestinfo.request.Clear(); requestinfo.request.Clear();
WebFetchInvDescModule.ProcessedRequestsCount++; WebFetchInvDescModule.ProcessedRequestsCount++;
} }

View File

@ -225,7 +225,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
string uri = "/lslhttp/" + urlcode.ToString() + "/"; string uri = "/lslhttp/" + urlcode.ToString() + "/";
PollServiceEventArgs args PollServiceEventArgs args
= new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, Drop, urlcode, 25000);
args.Type = PollServiceEventArgs.EventType.LslHttp; args.Type = PollServiceEventArgs.EventType.LslHttp;
m_HttpServer.AddPollServiceHTTPHandler(uri, args); m_HttpServer.AddPollServiceHTTPHandler(uri, args);
@ -276,7 +276,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
string uri = "/lslhttps/" + urlcode.ToString() + "/"; string uri = "/lslhttps/" + urlcode.ToString() + "/";
PollServiceEventArgs args PollServiceEventArgs args
= new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, Drop, urlcode, 25000);
args.Type = PollServiceEventArgs.EventType.LslHttp; args.Type = PollServiceEventArgs.EventType.LslHttp;
m_HttpsServer.AddPollServiceHTTPHandler(uri, args); m_HttpsServer.AddPollServiceHTTPHandler(uri, args);
@ -530,6 +530,28 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
} }
} }
} }
private void Drop(UUID requestID, UUID sessionID)
{
UrlData url = null;
lock (m_RequestMap)
{
if (m_RequestMap.ContainsKey(requestID))
{
url = m_RequestMap[requestID];
m_RequestMap.Remove(requestID);
if(url != null)
{
lock (url.requests)
{
if(url.requests.ContainsKey(requestID))
url.requests.Remove(requestID);
}
}
}
}
}
private Hashtable GetEvents(UUID requestID, UUID sessionID) private Hashtable GetEvents(UUID requestID, UUID sessionID)
{ {
UrlData url = null; UrlData url = null;

View File

@ -275,6 +275,7 @@ namespace OpenSim.Services.HypergridService
if (!am.Success) if (!am.Success)
{ {
reason = "Login failed: client " + curViewer + " is not allowed";
m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is not allowed", curViewer); m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is not allowed", curViewer);
return false; return false;
} }
@ -287,6 +288,7 @@ namespace OpenSim.Services.HypergridService
if (dm.Success) if (dm.Success)
{ {
reason = "Login failed: client " + curViewer + " is denied";
m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is denied", curViewer); m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is denied", curViewer);
return false; return false;
} }

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff