diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs new file mode 100644 index 0000000000..9f78948df4 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs @@ -0,0 +1,152 @@ +/* + * 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; +using System.Reflection; +using log4net; +using Nini.Config; +using Mono.Addins; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; + +namespace OpenSim.Region.ClientStack.Linden +{ + /// + /// SimulatorFeatures capability. This is required for uploading Mesh. + /// Since is accepts an open-ended response, we also send more information + /// for viewers that care to interpret it. + /// + /// NOTE: Part of this code was adapted from the Aurora project, specifically + /// the normal part of the response in the capability handler. + /// + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimulatorFeaturesModule : ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; + + private string m_MapImageServerURL = string.Empty; + private string m_SearchURL = string.Empty; + + #region ISharedRegionModule Members + + public void Initialise(IConfigSource source) + { + IConfig config = source.Configs["SimulatorFeatures"]; + if (config == null) + return; + + m_MapImageServerURL = config.GetString("MapImageServerURI", string.Empty); + if (m_MapImageServerURL != string.Empty) + { + m_MapImageServerURL = m_MapImageServerURL.Trim(); + if (!m_MapImageServerURL.EndsWith("/")) + m_MapImageServerURL = m_MapImageServerURL + "/"; + } + + m_SearchURL = config.GetString("SearchServerURI", string.Empty); + } + + public void AddRegion(Scene s) + { + m_scene = s; + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void RemoveRegion(Scene s) + { + m_scene.EventManager.OnRegisterCaps -= RegisterCaps; + } + + public void RegionLoaded(Scene s) + { + } + + public void PostInitialise() + { + } + + public void Close() { } + + public string Name { get { return "SimulatorFeaturesModule"; } } + + public Type ReplaceableInterface + { + get { return null; } + } + + #endregion + + public void RegisterCaps(UUID agentID, Caps caps) + { + IRequestHandler reqHandler = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(), SimulatorFeatures); + caps.RegisterHandler("SimulatorFeatures", reqHandler); + } + + private Hashtable SimulatorFeatures(Hashtable mDhttpMethod) + { + m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request"); + OSDMap data = new OSDMap(); + data["MeshRezEnabled"] = true; + data["MeshUploadEnabled"] = true; + data["MeshXferEnabled"] = true; + data["PhysicsMaterialsEnabled"] = true; + + OSDMap typesMap = new OSDMap(); + typesMap["convex"] = true; + typesMap["none"] = true; + typesMap["prim"] = true; + data["PhysicsShapeTypes"] = typesMap; + + // Extra information for viewers that want to use it + OSDMap gridServicesMap = new OSDMap(); + if (m_MapImageServerURL != string.Empty) + gridServicesMap["map-server-url"] = m_MapImageServerURL; + if (m_SearchURL != string.Empty) + gridServicesMap["search"] = m_SearchURL; + data["GridServices"] = gridServicesMap; + + //Send back data + Hashtable responsedata = new Hashtable(); + responsedata["int_response_code"] = 200; + responsedata["content_type"] = "text/plain"; + responsedata["keepalive"] = false; + responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(data); + return responsedata; + } + + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index 93657a8e58..63fde078a9 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -146,6 +146,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary options, IUserAccountService userAccountService) { + if (options.ContainsKey("verbose")) + m_log.InfoFormat( + "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", + inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); + string filename = path + CreateArchiveItemName(inventoryItem); // Record the creator of this item for user record purposes (which might go away soon) @@ -441,4 +446,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return s; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs new file mode 100644 index 0000000000..786e0b5737 --- /dev/null +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs @@ -0,0 +1,137 @@ +/* + * 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.Reflection; +using System.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Services.Interfaces; +using OpenMetaverse; +using log4net; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid +{ + public class RegionInfoCache + { + private const double CACHE_EXPIRATION_SECONDS = 300.0; // 5 minutes + +// private static readonly ILog m_log = +// LogManager.GetLogger( +// MethodBase.GetCurrentMethod().DeclaringType); + + internal struct ScopedRegionUUID + { + public UUID m_scopeID; + public UUID m_regionID; + public ScopedRegionUUID(UUID scopeID, UUID regionID) + { + m_scopeID = scopeID; + m_regionID = regionID; + } + } + + internal struct ScopedRegionName + { + public UUID m_scopeID; + public string m_name; + public ScopedRegionName(UUID scopeID, string name) + { + m_scopeID = scopeID; + m_name = name; + } + } + + private ExpiringCache m_UUIDCache; + private ExpiringCache m_NameCache; + + public RegionInfoCache() + { + m_UUIDCache = new ExpiringCache(); + m_NameCache = new ExpiringCache(); + } + + public void Cache(GridRegion rinfo) + { + if (rinfo != null) + this.Cache(rinfo.ScopeID,rinfo.RegionID,rinfo); + } + + public void Cache(UUID scopeID, UUID regionID, GridRegion rinfo) + { + // for now, do not cache negative results; this is because + // we need to figure out how to handle regions coming online + // in a timely way + if (rinfo == null) + return; + + ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID); + + // Cache even null accounts + m_UUIDCache.AddOrUpdate(id, rinfo, CACHE_EXPIRATION_SECONDS); + if (rinfo != null) + { + ScopedRegionName name = new ScopedRegionName(scopeID,rinfo.RegionName); + m_NameCache.AddOrUpdate(name, id, CACHE_EXPIRATION_SECONDS); + } + } + + public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache) + { + inCache = false; + + GridRegion rinfo = null; + ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID); + if (m_UUIDCache.TryGetValue(id, out rinfo)) + { + inCache = true; + return rinfo; + } + + return null; + } + + public GridRegion Get(UUID scopeID, string name, out bool inCache) + { + inCache = false; + + ScopedRegionName sname = new ScopedRegionName(scopeID,name); + + ScopedRegionUUID id; + if (m_NameCache.TryGetValue(sname, out id)) + { + GridRegion rinfo = null; + if (m_UUIDCache.TryGetValue(id, out rinfo)) + { + inCache = true; + return rinfo; + } + } + + return null; + } + } +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs index 33cc838322..6f364ae4c8 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs @@ -53,6 +53,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid private IGridService m_LocalGridService; private IGridService m_RemoteGridService; + private RegionInfoCache m_RegionInfoCache = new RegionInfoCache(); + public RemoteGridServicesConnector() { } @@ -169,10 +171,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) { - GridRegion rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID); + bool inCache = false; + GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionID,out inCache); + if (inCache) + return rinfo; + + rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID); if (rinfo == null) rinfo = m_RemoteGridService.GetRegionByUUID(scopeID, regionID); + m_RegionInfoCache.Cache(scopeID,regionID,rinfo); return rinfo; } @@ -187,10 +195,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid public GridRegion GetRegionByName(UUID scopeID, string regionName) { - GridRegion rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName); + bool inCache = false; + GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionName, out inCache); + if (inCache) + return rinfo; + + rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName); if (rinfo == null) rinfo = m_RemoteGridService.GetRegionByName(scopeID, regionName); + // can't cache negative results for name lookups + m_RegionInfoCache.Cache(rinfo); return rinfo; } @@ -204,8 +219,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetRegionsByName {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; @@ -221,8 +239,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetRegionRange {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; @@ -238,8 +259,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetDefaultRegions {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; @@ -255,8 +279,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetFallbackRegions {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; @@ -272,8 +299,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetHyperlinks {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs index ee90859744..e224670756 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs @@ -112,6 +112,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage Object[] args = new Object[] { source }; m_MapService = ServerUtils.LoadPlugin(service, args); + if (m_MapService == null) + { + m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Unable to load LocalServiceModule from {0}. MapService module disabled. Please fix the configuration.", service); + return; + } m_refreshTimer.Enabled = true; m_refreshTimer.AutoReset = true; @@ -202,7 +207,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage { m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: upload maptile for {0}", scene.RegionInfo.RegionName); - // Create a PNG map tile and upload it to the AddMapTile API + // Create a JPG map tile and upload it to the AddMapTile API byte[] jpgData = Utils.EmptyBytes; IMapImageGenerator tileGenerator = scene.RequestModuleInterface(); if (tileGenerator == null) @@ -220,13 +225,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage } } + if (jpgData == Utils.EmptyBytes) + { + m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Tile image generation failed"); + return; + } + string reason = string.Empty; if (!m_MapService.AddMapTile((int)scene.RegionInfo.RegionLocX, (int)scene.RegionInfo.RegionLocY, jpgData, out reason)) { m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: Unable to upload tile image for {0} at {1}-{2}: {3}", scene.RegionInfo.RegionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, reason); } - } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index eb00de84e1..f8f3713f8f 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -198,11 +198,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_log.ErrorFormat( "[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT); - m_log.Error("[ARCHIVER]: OAR save aborted. PLEASE DO NOT USE THIS OAR, IT WILL BE INCOMPLETE."); + m_log.Error("[ARCHIVER]: Archive save aborted. PLEASE DO NOT USE THIS ARCHIVE, IT WILL BE INCOMPLETE."); } catch (Exception e) { - m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}", e); + m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace); } finally { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 43dd8357aa..e3744bd306 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1643,7 +1643,6 @@ namespace OpenSim.Region.Framework.Scenes { PhysActor.SOPName = this.Name; // save object name and desc into the PhysActor so ODE internals know the joint/body info PhysActor.SOPDescription = this.Description; - PhysActor.LocalID = LocalId; DoPhysicsPropertyUpdate(RigidBody, true); PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); } @@ -4435,6 +4434,7 @@ namespace OpenSim.Region.Framework.Scenes { // It's not phantom anymore. So make sure the physics engine get's knowledge of it PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( + LocalId, string.Format("{0}/{1}", Name, UUID), Shape, AbsolutePosition, @@ -4446,7 +4446,6 @@ namespace OpenSim.Region.Framework.Scenes pa = PhysActor; if (pa != null) { - pa.LocalID = LocalId; DoPhysicsPropertyUpdate(UsePhysics, true); if (m_parentGroup != null) { diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 880c3ea3cb..1c36e55b95 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -142,7 +142,12 @@ namespace OpenSim.Region.Physics.Manager public abstract PrimitiveBaseShape Shape { set; } - public abstract uint LocalID { set; } + uint m_baseLocalID; + public virtual uint LocalID + { + set { m_baseLocalID = value; } + get { return m_baseLocalID; } + } public abstract bool Grabbed { set; } diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index 217d307443..54c50f8eda 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -66,6 +66,13 @@ namespace OpenSim.Region.Physics.Manager public abstract PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying); + public virtual PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, bool isFlying) + { + PhysicsActor ret = AddAvatar(avName, position, size, isFlying); + if (ret != null) ret.LocalID = localID; + return ret; + } + public abstract void RemoveAvatar(PhysicsActor actor); public abstract void RemovePrim(PhysicsActor prim); @@ -75,6 +82,14 @@ namespace OpenSim.Region.Physics.Manager public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical); + public virtual PhysicsActor AddPrimShape(uint localID, string primName, PrimitiveBaseShape pbs, Vector3 position, + Vector3 size, Quaternion rotation, bool isPhysical) + { + PhysicsActor ret = AddPrimShape(primName, pbs, position, size, rotation, isPhysical); + if (ret != null) ret.LocalID = localID; + return ret; + } + public virtual float TimeDilation { get { return 1.0f; } diff --git a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs index a953cd7eaf..99f98b60d7 100644 --- a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs @@ -26,7 +26,14 @@ */ using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml; + using Nini.Config; +using log4net; + using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenSim.Framework.Servers.HttpServer; @@ -55,7 +62,122 @@ namespace OpenSim.Server.Handlers.MapImage Object[] args = new Object[] { config }; m_MapService = ServerUtils.LoadPlugin(gridService, args); - //server.AddStreamHandler(new PresenceServerPostHandler(m_PresenceService)); + server.AddStreamHandler(new MapServerPostHandler(m_MapService)); + } + } + + class MapServerPostHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IMapImageService m_MapService; + + public MapServerPostHandler(IMapImageService service) : + base("POST", "/map") + { + m_MapService = service; + } + + public override byte[] Handle(string path, Stream requestData, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: Received {0}", path); + StreamReader sr = new StreamReader(requestData); + string body = sr.ReadToEnd(); + sr.Close(); + body = body.Trim(); + + try + { + Dictionary request = ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("X") || !request.ContainsKey("Y") || !request.ContainsKey("DATA")) + { + httpResponse.StatusCode = (int)OSHttpStatusCode.ClientErrorBadRequest; + return FailureResult("Bad request."); + } + int x = 0, y = 0; + Int32.TryParse(request["X"].ToString(), out x); + Int32.TryParse(request["Y"].ToString(), out y); + string type = "image/jpeg"; + if (request.ContainsKey("TYPE")) + type = request["TYPE"].ToString(); + byte[] data = Convert.FromBase64String(request["DATA"].ToString()); + + string reason = string.Empty; + bool result = m_MapService.AddMapTile(x, y, data, out reason); + + if (result) + return SuccessResult(); + else + return FailureResult(reason); + + } + catch (Exception e) + { + m_log.ErrorFormat("[MAP SERVICE IMAGE HANDLER]: Exception {0} {1}", e.Message, e.StackTrace); + } + + return FailureResult("Unexpected server error"); + + } + + private byte[] SuccessResult() + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Success")); + + rootElement.AppendChild(result); + + return DocToBytes(doc); + } + + private byte[] FailureResult(string msg) + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Failure")); + + rootElement.AppendChild(result); + + XmlElement message = doc.CreateElement("", "Message", ""); + message.AppendChild(doc.CreateTextNode(msg)); + + rootElement.AppendChild(message); + + return DocToBytes(doc); + } + + private byte[] DocToBytes(XmlDocument doc) + { + MemoryStream ms = new MemoryStream(); + XmlTextWriter xw = new XmlTextWriter(ms, null); + xw.Formatting = Formatting.Indented; + doc.WriteTo(xw); + xw.Flush(); + + return ms.ToArray(); } } } diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs index 53d08faa3b..e8a424f513 100644 --- a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs @@ -80,7 +80,6 @@ namespace OpenSim.Server.Handlers.MapImage public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { - m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: retrieving {0}", path); byte[] result = new byte[0]; string format = string.Empty; diff --git a/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs index ff0e9d9aee..520d639ccf 100644 --- a/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs +++ b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs @@ -36,6 +36,7 @@ using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Console; using OpenSim.Framework.Communications; +using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenMetaverse; using OpenMetaverse.StructuredData; @@ -83,60 +84,57 @@ namespace OpenSim.Services.Connectors throw new Exception("MapImage connector init error"); } m_ServerURI = serviceURI; + m_ServerURI = serviceURI.TrimEnd('/'); } - public bool AddMapTile(int x, int y, byte[] pngData, out string reason) + public bool AddMapTile(int x, int y, byte[] jpgData, out string reason) { - List postParameters = new List() - { - new MultipartForm.Parameter("X", x.ToString()), - new MultipartForm.Parameter("Y", y.ToString()), - new MultipartForm.File("Tile", "tile.png", "image/png", pngData) - }; - - reason = string.Empty; + reason = string.Empty; int tickstart = Util.EnvironmentTickCount(); + Dictionary sendData = new Dictionary(); + sendData["X"] = x.ToString(); + sendData["Y"] = y.ToString(); + sendData["TYPE"] = "image/jpeg"; + sendData["DATA"] = Convert.ToBase64String(jpgData); + + string reqString = ServerUtils.BuildQueryString(sendData); - // Make the remote storage request try { - HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI); - request.Timeout = 20000; - request.ReadWriteTimeout = 5000; - - using (HttpWebResponse response = MultipartForm.Post(request, postParameters)) + string reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/map", + reqString); + if (reply != string.Empty) { - using (Stream responseStream = response.GetResponseStream()) + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "success")) { - string responseStr = responseStream.GetStreamString(); - OSD responseOSD = OSDParser.Deserialize(responseStr); - if (responseOSD.Type == OSDType.Map) - { - OSDMap responseMap = (OSDMap)responseOSD; - if (responseMap["Success"].AsBoolean()) - return true; - - reason = "Upload failed: " + responseMap["Message"].AsString(); - } - else - { - reason = "Response format was invalid:\n" + responseStr; - } + return true; } + else if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "failure")) + { + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Registration failed: {0}", replyData["Message"].ToString()); + reason = replyData["Message"].ToString(); + return false; + } + else if (!replyData.ContainsKey("Result")) + { + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: reply data does not contain result field"); + } + else + { + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: unexpected result {0}", replyData["Result"].ToString()); + reason = "Unexpected result " + replyData["Result"].ToString(); + } + } + else + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: RegisterRegion received null reply"); } - catch (WebException we) + catch (Exception e) { - reason = we.Message; - if (we.Status == WebExceptionStatus.ProtocolError) - { - HttpWebResponse webResponse = (HttpWebResponse)we.Response; - reason = String.Format("[{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription); - } - } - catch (Exception ex) - { - reason = ex.Message; + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Exception when contacting grid server: {0}", e.Message); } finally { @@ -146,6 +144,7 @@ namespace OpenSim.Services.Connectors } return false; + } public byte[] GetMapTile(string fileName, out string format) diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs index 27722bb4b7..7e7391c988 100644 --- a/OpenSim/Services/MapImageService/MapImageService.cs +++ b/OpenSim/Services/MapImageService/MapImageService.cs @@ -143,7 +143,7 @@ namespace OpenSim.Services.MapImageService if (File.Exists(fullName)) { format = Path.GetExtension(fileName).ToLower(); - m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format); + //m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format); return File.ReadAllBytes(fullName); } else if (File.Exists(m_WaterTileFile)) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 813c5b828c..bab118fd63 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -307,6 +307,14 @@ ; serving this cap from the simulators may lead to poor performace. Cap_WebFetchInventoryDescendents = "" +[SimulatorFeatures] + ; Experimental new information sent in SimulatorFeatures cap for Kokua viewers + ; meant to override the MapImage and search server url given at login, and varying + ; on a sim-basis. + ; Viewers that don't understand it, will ignore it + ;MapImageServerURI = "http://127.0.0.1:9000/ + ;SearchServerURI = "http://127.0.0.1:9000/ + [Chat] ;# {whisper_distance} {} {Distance at which a whisper is heard, in meters?} {} 10 ;; Distance in meters that whispers should travel. diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 812d2659fa..ea271b864a 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -21,7 +21,7 @@ ; * [[@]/][:] ; * [Startup] -ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector,8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector,8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector" +ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector,8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector,8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector,8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector,8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector" ; * This is common for all services, it's the network setup for the entire ; * server instance, if none is specified above @@ -206,6 +206,9 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 WelcomeMessage = "Welcome, Avatar!" AllowRemoteSetLoginLevel = "false" + ; For V2 map + ; MapTileURL = "http://127.0.0.1:8002"; + ; If you run this login server behind a proxy, set this to true ; HasProxy = false @@ -237,6 +240,11 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 ;AllowedClients = "" ;DeniedClients = "" +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + ; Set this if you want to change the default + ; TilesStoragePath = "maptiles" + [GridInfoService] ; These settings are used to return information on a get_grid_info call. ; Client launcher scripts and third-party clients make use of this to diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example index 5d0ec09d7d..14f79aac14 100644 --- a/bin/Robust.ini.example +++ b/bin/Robust.ini.example @@ -13,7 +13,7 @@ ; * [[@]/][:] ; * [Startup] -ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector" +ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector,8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector" ; * This is common for all services, it's the network setup for the entire ; * server instance, if none is specified above @@ -191,8 +191,8 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 WelcomeMessage = "Welcome, Avatar!" AllowRemoteSetLoginLevel = "false" - ; For snowglobe's web map - ; MapTileURL = ""; + ; For V2 map + ; MapTileURL = "http://127.0.0.1:8002"; ; If you run this login server behind a proxy, set this to true ; HasProxy = false @@ -214,6 +214,12 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 ;AllowedClients = "" ;DeniedClients = "" +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + ; Set this if you want to change the default + ; TilesStoragePath = "maptiles" + + [GridInfoService] ; These settings are used to return information on a get_grid_info call. ; Client launcher scripts and third-party clients make use of this to diff --git a/bin/config-include/Grid.ini b/bin/config-include/Grid.ini index 52205732f0..da860c6859 100644 --- a/bin/config-include/Grid.ini +++ b/bin/config-include/Grid.ini @@ -21,6 +21,7 @@ EntityTransferModule = "BasicEntityTransferModule" InventoryAccessModule = "BasicInventoryAccessModule" LandServices = "RemoteLandServicesConnector" + MapImageService = "MapImageServiceModule" LandServiceInConnector = true NeighbourServiceInConnector = true @@ -50,3 +51,8 @@ [Friends] Connector = "OpenSim.Services.Connectors.dll:FriendsServicesConnector" + +[MapImageService] + LocalServiceModule = "OpenSim.Services.Connectors.dll:MapImageServicesConnector" + ; in minutes + RefreshTime = 60 diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index 27f262f374..4eb6fcf333 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -116,6 +116,9 @@ ; UserAgentServerURI = "http://mygridserver.com:8002" +[MapImageService] + MapImageServerURI = "http://mygridserver.com:8003" + [Modules] ;; Choose 0 or 1 cache modules, and the corresponding config file, if it exists. ;; Copy the config .example file into your own .ini file and change configs there diff --git a/bin/config-include/GridHypergrid.ini b/bin/config-include/GridHypergrid.ini index b8e66c2733..60a3c625f2 100644 --- a/bin/config-include/GridHypergrid.ini +++ b/bin/config-include/GridHypergrid.ini @@ -25,6 +25,7 @@ InventoryAccessModule = "HGInventoryAccessModule" LandServices = "RemoteLandServicesConnector" FriendsModule = "HGFriendsModule" + MapImageService = "MapImageServiceModule" LandServiceInConnector = true NeighbourServiceInConnector = true @@ -76,4 +77,9 @@ LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" GridService = "OpenSim.Services.Connectors.dll:GridServicesConnector" PresenceService = "OpenSim.Services.Connectors.dll:PresenceServicesConnector" - UserAgentService = "OpenSim.Services.Connectors.dll:UserAgentServiceConnector" \ No newline at end of file + UserAgentService = "OpenSim.Services.Connectors.dll:UserAgentServiceConnector" + +[MapImageService] + LocalServiceModule = "OpenSim.Services.Connectors.dll:MapImageServicesConnector" + ; in minutes + RefreshTime = 60 diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 29c2af1f96..cbe3fa0aef 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -223,3 +223,7 @@ ; password help: optional: page providing password assistance for users of your grid ; currently unused ;password = http://127.0.0.1/password + +[MapImageService] + ; Set this if you want to change the default + ; TilesStoragePath = "maptiles"