diff --git a/OpenSim/ApplicationPlugins/CreateCommsManager/CreateCommsManagerPlugin.cs b/OpenSim/ApplicationPlugins/CreateCommsManager/CreateCommsManagerPlugin.cs index 7323ad72c6..e6b4a89580 100644 --- a/OpenSim/ApplicationPlugins/CreateCommsManager/CreateCommsManagerPlugin.cs +++ b/OpenSim/ApplicationPlugins/CreateCommsManager/CreateCommsManagerPlugin.cs @@ -176,7 +176,7 @@ namespace OpenSim.ApplicationPlugins.CreateCommsManager LocalBackEndServices backendService = new LocalBackEndServices(); - LocalLoginService loginService = CreateLoginService(libraryRootFolder, inventoryService, userService, backendService); + //LocalLoginService loginService = CreateLoginService(libraryRootFolder, inventoryService, userService, backendService); m_commsManager = new CommunicationsLocal( @@ -207,10 +207,9 @@ namespace OpenSim.ApplicationPlugins.CreateCommsManager m_openSim.NetServersInfo.DefaultHomeLocX, m_openSim.NetServersInfo.DefaultHomeLocY, inventoryService); userService.AddPlugin(m_openSim.ConfigurationSettings.StandaloneUserPlugin, m_openSim.ConfigurationSettings.StandaloneUserSource); - //LocalBackEndServices backendService = new LocalBackEndServices(); HGGridServicesStandalone gridService = new HGGridServicesStandalone(m_openSim.NetServersInfo, m_httpServer, m_openSim.AssetCache, m_openSim.SceneManager); - LocalLoginService loginService = CreateLoginService(libraryRootFolder, inventoryService, userService, gridService.LocalBackend); + // LocalLoginService loginService = CreateLoginService(libraryRootFolder, inventoryService, userService, gridService.LocalBackend); m_commsManager = new HGCommunicationsStandalone(m_openSim.NetServersInfo, m_httpServer, m_openSim.AssetCache, userService, userService, inventoryService, gridService, userService, libraryRootFolder, m_openSim.ConfigurationSettings.DumpAssetsToFile); @@ -231,24 +230,24 @@ namespace OpenSim.ApplicationPlugins.CreateCommsManager m_httpServer.AddStreamHandler(new OpenSim.SimStatusHandler()); } - private LocalLoginService CreateLoginService(LibraryRootFolder libraryRootFolder, IInterServiceInventoryServices inventoryService, LocalUserServices userService, LocalBackEndServices backendService) - { - LocalLoginService loginService = - new LocalLoginService( - userService, m_openSim.ConfigurationSettings.StandaloneWelcomeMessage, inventoryService, backendService, m_openSim.NetServersInfo, - m_openSim.ConfigurationSettings.StandaloneAuthenticate, libraryRootFolder); + //private LocalLoginService CreateLoginService(LibraryRootFolder libraryRootFolder, IInterServiceInventoryServices inventoryService, LocalUserServices userService, LocalBackEndServices backendService) + //{ + // LocalLoginService loginService = + // new LocalLoginService( + // userService, m_openSim.ConfigurationSettings.StandaloneWelcomeMessage, inventoryService, backendService, m_openSim.NetServersInfo, + // m_openSim.ConfigurationSettings.StandaloneAuthenticate, libraryRootFolder); - // set up XMLRPC handler for client's initial login request message - m_httpServer.AddXmlRPCHandler("login_to_simulator", loginService.XmlRpcLoginMethod); + // // set up XMLRPC handler for client's initial login request message + // m_httpServer.AddXmlRPCHandler("login_to_simulator", loginService.XmlRpcLoginMethod); - // provides the web form login - m_httpServer.AddHTTPHandler("login", loginService.ProcessHTMLLogin); + // // provides the web form login + // m_httpServer.AddHTTPHandler("login", loginService.ProcessHTMLLogin); - // Provides the LLSD login - m_httpServer.SetDefaultLLSDHandler(loginService.LLSDLoginMethod); + // // Provides the LLSD login + // m_httpServer.SetDefaultLLSDHandler(loginService.LLSDLoginMethod); - return loginService; - } + // return loginService; + //} private void CreateGridInfoService() { diff --git a/OpenSim/Client/Linden/ILoginRegionsConnector.cs b/OpenSim/Client/Linden/ILoginRegionsConnector.cs new file mode 100644 index 0000000000..3f3cee0342 --- /dev/null +++ b/OpenSim/Client/Linden/ILoginRegionsConnector.cs @@ -0,0 +1,43 @@ +/* + * 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 OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Client.Linden +{ + public interface ILoginRegionsConnector + { + bool RegionLoginsEnabled { get; } + void LogOffUserFromGrid(ulong regionHandle, UUID AvatarID, UUID RegionSecret, string message); + bool NewUserConnection(ulong regionHandle, AgentCircuitData agent); + RegionInfo RequestClosestRegion(string region); + RegionInfo RequestNeighbourInfo(UUID regionID); + RegionInfo RequestNeighbourInfo(ulong regionhandle); + } +} diff --git a/OpenSim/Client/Linden/LLClientStackModule.cs b/OpenSim/Client/Linden/LLClientStackModule.cs index 6b232244f4..4639db8104 100644 --- a/OpenSim/Client/Linden/LLClientStackModule.cs +++ b/OpenSim/Client/Linden/LLClientStackModule.cs @@ -1,4 +1,31 @@ -using System; +/* + * 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; diff --git a/OpenSim/Client/Linden/LLStandaloneLoginModule.cs b/OpenSim/Client/Linden/LLStandaloneLoginModule.cs new file mode 100644 index 0000000000..c5db38b172 --- /dev/null +++ b/OpenSim/Client/Linden/LLStandaloneLoginModule.cs @@ -0,0 +1,259 @@ +/* + * 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.Collections.Generic; +using System.Net; +using System.Reflection; +using System.Text.RegularExpressions; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Communications.Capabilities; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Client.Linden +{ + public class LLStandaloneLoginModule : IRegionModule, ILoginRegionsConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected List m_scenes = new List(); + protected Scene m_firstScene; + + protected bool m_enabled = false; // Module is only enabled if running in standalone mode + + + public bool RegionLoginsEnabled + { + get + { + if (m_firstScene != null) + { + return m_firstScene.CommsManager.GridService.RegionLoginsEnabled; + } + else + { + return false; + } + } + } + + protected LLStandaloneLoginService m_loginService; + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource source) + { + if (m_firstScene == null) + { + m_firstScene = scene; + + IConfig startupConfig = source.Configs["Startup"]; + if (startupConfig != null) + { + m_enabled = !startupConfig.GetBoolean("gridmode", false); + } + + if (m_enabled) + { + bool authenticate = true; + string welcomeMessage = "Welcome to OpenSim"; + IConfig standaloneConfig = source.Configs["StandAlone"]; + if (standaloneConfig != null) + { + authenticate = standaloneConfig.GetBoolean("accounts_authenticate", true); + welcomeMessage = standaloneConfig.GetString("welcome_message"); + } + + //TODO: fix casting. + LibraryRootFolder rootFolder = m_firstScene.CommsManager.UserProfileCacheService.LibraryRoot as LibraryRootFolder; + + BaseHttpServer httpServer = m_firstScene.CommsManager.HttpServer; + + //TODO: fix the casting of the user service, maybe by registering the userManagerBase with scenes, or refactoring so we just need a IUserService reference + m_loginService = new LLStandaloneLoginService((UserManagerBase)m_firstScene.CommsManager.UserService, welcomeMessage, m_firstScene.CommsManager.InterServiceInventoryService, m_firstScene.CommsManager.NetworkServersInfo, authenticate, rootFolder, this); + + httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod); + + // provides the web form login + httpServer.AddHTTPHandler("login", m_loginService.ProcessHTMLLogin); + + // Provides the LLSD login + httpServer.SetDefaultLLSDHandler(m_loginService.LLSDLoginMethod); + } + } + + if (m_enabled) + { + AddScene(scene); + } + } + + public void PostInitialise() + { + + } + + public void Close() + { + + } + + public string Name + { + get { return "LLStandaloneLoginModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + protected void AddScene(Scene scene) + { + lock (m_scenes) + { + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + } + } + } + + public bool NewUserConnection(ulong regionHandle, AgentCircuitData agent) + { + Scene scene; + if (TryGetRegion(regionHandle, out scene)) + { + return scene.NewUserConnection(agent); + } + return false; + } + + public void LogOffUserFromGrid(ulong regionHandle, UUID AvatarID, UUID RegionSecret, string message) + { + Scene scene; + if (TryGetRegion(regionHandle, out scene)) + { + scene.HandleLogOffUserFromGrid(AvatarID, RegionSecret, message); + } + } + + public RegionInfo RequestNeighbourInfo(ulong regionhandle) + { + Scene scene; + if (TryGetRegion(regionhandle, out scene)) + { + return scene.RegionInfo; + } + return null; + } + + public RegionInfo RequestClosestRegion(string region) + { + Scene scene; + if (TryGetRegion(region, out scene)) + { + return scene.RegionInfo; + } + return null; + } + + public RegionInfo RequestNeighbourInfo(UUID regionID) + { + Scene scene; + if (TryGetRegion(regionID, out scene)) + { + return scene.RegionInfo; + } + return null; + } + + protected bool TryGetRegion(ulong regionHandle, out Scene scene) + { + lock (m_scenes) + { + foreach (Scene nextScene in m_scenes) + { + if (nextScene.RegionInfo.RegionHandle == regionHandle) + { + scene = nextScene; + return true; + } + } + } + + scene = null; + return false; + } + + protected bool TryGetRegion(UUID regionID, out Scene scene) + { + lock (m_scenes) + { + foreach (Scene nextScene in m_scenes) + { + if (nextScene.RegionInfo.RegionID == regionID) + { + scene = nextScene; + return true; + } + } + } + + scene = null; + return false; + } + + protected bool TryGetRegion(string regionName, out Scene scene) + { + lock (m_scenes) + { + foreach (Scene nextScene in m_scenes) + { + if (nextScene.RegionInfo.RegionName == regionName) + { + scene = nextScene; + return true; + } + } + } + + scene = null; + return false; + } + } +} diff --git a/OpenSim/Client/Linden/LLStandaloneLoginService.cs b/OpenSim/Client/Linden/LLStandaloneLoginService.cs new file mode 100644 index 0000000000..f772185d69 --- /dev/null +++ b/OpenSim/Client/Linden/LLStandaloneLoginService.cs @@ -0,0 +1,433 @@ +/* + * 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.Collections.Generic; +using System.Net; +using System.Reflection; +using System.Text.RegularExpressions; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Communications.Capabilities; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Client.Linden +{ + public class LLStandaloneLoginService : LoginService + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected NetworkServersInfo serversInfo; + protected uint defaultHomeX; + protected uint defaultHomeY; + protected bool authUsers = false; + + /// + /// Used by the login service to make requests to the inventory service. + /// + protected IInterServiceInventoryServices m_interServiceInventoryService; + + /// + /// Used to make requests to the local regions. + /// + protected ILoginRegionsConnector m_regionsConnector; + + + public LLStandaloneLoginService( + UserManagerBase userManager, string welcomeMess, + IInterServiceInventoryServices interServiceInventoryService, + NetworkServersInfo serversInfo, + bool authenticate, LibraryRootFolder libraryRootFolder, ILoginRegionsConnector regionsConnector) + : base(userManager, libraryRootFolder, welcomeMess) + { + this.serversInfo = serversInfo; + defaultHomeX = this.serversInfo.DefaultHomeLocX; + defaultHomeY = this.serversInfo.DefaultHomeLocY; + authUsers = authenticate; + + m_interServiceInventoryService = interServiceInventoryService; + m_regionsConnector = regionsConnector; + } + + public override UserProfileData GetTheUser(string firstname, string lastname) + { + UserProfileData profile = m_userManager.GetUserProfile(firstname, lastname); + if (profile != null) + { + return profile; + } + + if (!authUsers) + { + //no current user account so make one + m_log.Info("[LOGIN]: No user account found so creating a new one."); + + m_userManager.AddUser(firstname, lastname, "test", "", defaultHomeX, defaultHomeY); + + return m_userManager.GetUserProfile(firstname, lastname); + } + + return null; + } + + public override bool AuthenticateUser(UserProfileData profile, string password) + { + if (!authUsers) + { + //for now we will accept any password in sandbox mode + m_log.Info("[LOGIN]: Authorising user (no actual password check)"); + + return true; + } + else + { + m_log.Info( + "[LOGIN]: Authenticating " + profile.FirstName + " " + profile.SurName); + + if (!password.StartsWith("$1$")) + password = "$1$" + Util.Md5Hash(password); + + password = password.Remove(0, 3); //remove $1$ + + string s = Util.Md5Hash(password + ":" + profile.PasswordSalt); + + bool loginresult = (profile.PasswordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase) + || profile.PasswordHash.Equals(password, StringComparison.InvariantCultureIgnoreCase)); + return loginresult; + } + } + + /// + /// Customises the login response and fills in missing values. + /// + /// The existing response + /// The user profile + /// The requested start location + public override bool CustomiseResponse(LoginResponse response, UserProfileData theUser, string startLocationRequest) + { + // add active gestures to login-response + AddActiveGestures(response, theUser); + + // HomeLocation + RegionInfo homeInfo = null; + + // use the homeRegionID if it is stored already. If not, use the regionHandle as before + UUID homeRegionId = theUser.HomeRegionID; + ulong homeRegionHandle = theUser.HomeRegion; + if (homeRegionId != UUID.Zero) + { + homeInfo = GetRegionInfo(homeRegionId); + } + else + { + homeInfo = GetRegionInfo(homeRegionHandle); + } + + if (homeInfo != null) + { + response.Home = + string.Format( + "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}", + (homeInfo.RegionLocX * Constants.RegionSize), + (homeInfo.RegionLocY * Constants.RegionSize), + theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z, + theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z); + } + else + { + m_log.InfoFormat("not found the region at {0} {1}", theUser.HomeRegionX, theUser.HomeRegionY); + // Emergency mode: Home-region isn't available, so we can't request the region info. + // Use the stored home regionHandle instead. + // NOTE: If the home-region moves, this will be wrong until the users update their user-profile again + ulong regionX = homeRegionHandle >> 32; + ulong regionY = homeRegionHandle & 0xffffffff; + response.Home = + string.Format( + "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}", + regionX, regionY, + theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z, + theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z); + + m_log.InfoFormat("[LOGIN] Home region of user {0} {1} is not available; using computed region position {2} {3}", + theUser.FirstName, theUser.SurName, + regionX, regionY); + } + + // StartLocation + RegionInfo regionInfo = null; + if (startLocationRequest == "home") + { + regionInfo = homeInfo; + theUser.CurrentAgent.Position = theUser.HomeLocation; + response.LookAt = "[r" + theUser.HomeLookAt.X.ToString() + ",r" + theUser.HomeLookAt.Y.ToString() + ",r" + theUser.HomeLookAt.Z.ToString() + "]"; + } + else if (startLocationRequest == "last") + { + UUID lastRegion = theUser.CurrentAgent.Region; + regionInfo = GetRegionInfo(lastRegion); + response.LookAt = "[r" + theUser.CurrentAgent.LookAt.X.ToString() + ",r" + theUser.CurrentAgent.LookAt.Y.ToString() + ",r" + theUser.CurrentAgent.LookAt.Z.ToString() + "]"; + } + else + { + Regex reURI = new Regex(@"^uri:(?[^&]+)&(?\d+)&(?\d+)&(?\d+)$"); + Match uriMatch = reURI.Match(startLocationRequest); + if (uriMatch == null) + { + m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, but can't process it", startLocationRequest); + } + else + { + string region = uriMatch.Groups["region"].ToString(); + regionInfo = RequestClosestRegion(region); + if (regionInfo == null) + { + m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, can't locate region {1}", startLocationRequest, region); + } + else + { + theUser.CurrentAgent.Position = new Vector3(float.Parse(uriMatch.Groups["x"].Value), + float.Parse(uriMatch.Groups["y"].Value), float.Parse(uriMatch.Groups["z"].Value)); + } + } + response.LookAt = "[r0,r1,r0]"; + // can be: last, home, safe, url + response.StartLocation = "url"; + } + + if ((regionInfo != null) && (PrepareLoginToRegion(regionInfo, theUser, response))) + { + return true; + } + + // StartLocation not available, send him to a nearby region instead + // regionInfo = m_gridService.RequestClosestRegion(""); + //m_log.InfoFormat("[LOGIN]: StartLocation not available sending to region {0}", regionInfo.regionName); + + // Send him to default region instead + ulong defaultHandle = (((ulong)defaultHomeX * Constants.RegionSize) << 32) | + ((ulong)defaultHomeY * Constants.RegionSize); + + if ((regionInfo != null) && (defaultHandle == regionInfo.RegionHandle)) + { + m_log.ErrorFormat("[LOGIN]: Not trying the default region since this is the same as the selected region"); + return false; + } + + m_log.Error("[LOGIN]: Sending user to default region " + defaultHandle + " instead"); + regionInfo = GetRegionInfo(defaultHandle); + + // Customise the response + //response.Home = + // string.Format( + // "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}", + // (SimInfo.regionLocX * Constants.RegionSize), + // (SimInfo.regionLocY*Constants.RegionSize), + // theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z, + // theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z); + theUser.CurrentAgent.Position = new Vector3(128, 128, 0); + response.StartLocation = "safe"; + + return PrepareLoginToRegion(regionInfo, theUser, response); + } + + protected RegionInfo RequestClosestRegion(string region) + { + return m_regionsConnector.RequestClosestRegion(region); + } + + protected RegionInfo GetRegionInfo(ulong homeRegionHandle) + { + return m_regionsConnector.RequestNeighbourInfo(homeRegionHandle); + } + + protected RegionInfo GetRegionInfo(UUID homeRegionId) + { + return m_regionsConnector.RequestNeighbourInfo(homeRegionId); + } + + /// + /// Add active gestures of the user to the login response. + /// + /// + /// A + /// + /// + /// A + /// + private void AddActiveGestures(LoginResponse response, UserProfileData theUser) + { + List gestures = m_interServiceInventoryService.GetActiveGestures(theUser.ID); + //m_log.DebugFormat("[LOGIN]: AddActiveGestures, found {0}", gestures == null ? 0 : gestures.Count); + ArrayList list = new ArrayList(); + if (gestures != null) + { + foreach (InventoryItemBase gesture in gestures) + { + Hashtable item = new Hashtable(); + item["item_id"] = gesture.ID.ToString(); + item["asset_id"] = gesture.AssetID.ToString(); + list.Add(item); + } + } + response.ActiveGestures = list; + } + + /// + /// Prepare a login to the given region. This involves both telling the region to expect a connection + /// and appropriately customising the response to the user. + /// + /// + /// + /// + /// true if the region was successfully contacted, false otherwise + protected bool PrepareLoginToRegion(RegionInfo regionInfo, UserProfileData user, LoginResponse response) + { + IPEndPoint endPoint = regionInfo.ExternalEndPoint; + response.SimAddress = endPoint.Address.ToString(); + response.SimPort = (uint)endPoint.Port; + response.RegionX = regionInfo.RegionLocX; + response.RegionY = regionInfo.RegionLocY; + + string capsPath = CapsUtil.GetRandomCapsObjectPath(); + string capsSeedPath = CapsUtil.GetCapsSeedPath(capsPath); + + // Don't use the following! It Fails for logging into any region not on the same port as the http server! + // Kept here so it doesn't happen again! + // response.SeedCapability = regionInfo.ServerURI + capsSeedPath; + + string seedcap = "http://"; + + if (serversInfo.HttpUsesSSL) + { + seedcap = "https://" + serversInfo.HttpSSLCN + ":" + serversInfo.httpSSLPort + capsSeedPath; + } + else + { + seedcap = "http://" + regionInfo.ExternalHostName + ":" + serversInfo.HttpListenerPort + capsSeedPath; + } + + response.SeedCapability = seedcap; + + // Notify the target of an incoming user + m_log.InfoFormat( + "[LOGIN]: Telling {0} @ {1},{2} ({3}) to prepare for client connection", + regionInfo.RegionName, response.RegionX, response.RegionY, regionInfo.ServerURI); + + // Update agent with target sim + user.CurrentAgent.Region = regionInfo.RegionID; + user.CurrentAgent.Handle = regionInfo.RegionHandle; + + AgentCircuitData agent = new AgentCircuitData(); + agent.AgentID = user.ID; + agent.firstname = user.FirstName; + agent.lastname = user.SurName; + agent.SessionID = user.CurrentAgent.SessionID; + agent.SecureSessionID = user.CurrentAgent.SecureSessionID; + agent.circuitcode = Convert.ToUInt32(response.CircuitCode); + agent.BaseFolder = UUID.Zero; + agent.InventoryFolder = UUID.Zero; + agent.startpos = user.CurrentAgent.Position; + agent.CapsPath = capsPath; + agent.Appearance = m_userManager.GetUserAppearance(user.ID); + if (agent.Appearance == null) + { + m_log.WarnFormat("[INTER]: Appearance not found for {0} {1}. Creating default.", agent.firstname, agent.lastname); + agent.Appearance = new AvatarAppearance(); + } + + if (m_regionsConnector.RegionLoginsEnabled) + { + // m_log.Info("[LLStandaloneLoginModule] Informing region about user"); + return m_regionsConnector.NewUserConnection(regionInfo.RegionHandle, agent); + } + + return false; + } + + // See LoginService + protected override InventoryData GetInventorySkeleton(UUID userID) + { + List folders = m_interServiceInventoryService.GetInventorySkeleton(userID); + + // If we have user auth but no inventory folders for some reason, create a new set of folders. + if (null == folders || 0 == folders.Count) + { + m_interServiceInventoryService.CreateNewUserInventory(userID); + folders = m_interServiceInventoryService.GetInventorySkeleton(userID); + } + + UUID rootID = UUID.Zero; + ArrayList AgentInventoryArray = new ArrayList(); + Hashtable TempHash; + foreach (InventoryFolderBase InvFolder in folders) + { + if (InvFolder.ParentID == UUID.Zero) + { + rootID = InvFolder.ID; + } + TempHash = new Hashtable(); + TempHash["name"] = InvFolder.Name; + TempHash["parent_id"] = InvFolder.ParentID.ToString(); + TempHash["version"] = (Int32)InvFolder.Version; + TempHash["type_default"] = (Int32)InvFolder.Type; + TempHash["folder_id"] = InvFolder.ID.ToString(); + AgentInventoryArray.Add(TempHash); + } + + return new InventoryData(AgentInventoryArray, rootID); + } + + public override void LogOffUser(UserProfileData theUser, string message) + { + RegionInfo SimInfo; + try + { + SimInfo = this.m_regionsConnector.RequestNeighbourInfo(theUser.CurrentAgent.Handle); + + if (SimInfo == null) + { + m_log.Error("[LOCAL LOGIN]: Region user was in isn't currently logged in"); + return; + } + } + catch (Exception) + { + m_log.Error("[LOCAL LOGIN]: Unable to look up region to log user off"); + return; + } + + m_regionsConnector.LogOffUserFromGrid(SimInfo.RegionHandle, theUser.ID, theUser.CurrentAgent.SecureSessionID, "Logging you off"); + } + } +} diff --git a/OpenSim/Framework/Communications/CommunicationsManager.cs b/OpenSim/Framework/Communications/CommunicationsManager.cs index bb8e452a32..3363c24ee3 100644 --- a/OpenSim/Framework/Communications/CommunicationsManager.cs +++ b/OpenSim/Framework/Communications/CommunicationsManager.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework.Communications.Cache; @@ -111,6 +112,7 @@ namespace OpenSim.Framework.Communications } protected BaseHttpServer m_httpServer; + /// /// Constructor /// @@ -125,7 +127,6 @@ namespace OpenSim.Framework.Communications m_assetCache = assetCache; m_userProfileCacheService = new UserProfileCacheService(this, libraryRootFolder); m_httpServer = httpServer; - // m_transactionsManager = new AgentAssetTransactionsManager(this, dumpAssetsToFile); } #region Inventory diff --git a/OpenSim/Framework/Communications/Tests/LoginServiceTests.cs b/OpenSim/Framework/Communications/Tests/LoginServiceTests.cs index 57ed0f5f1b..854d68da59 100644 --- a/OpenSim/Framework/Communications/Tests/LoginServiceTests.cs +++ b/OpenSim/Framework/Communications/Tests/LoginServiceTests.cs @@ -27,6 +27,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Net; using System.Text.RegularExpressions; using NUnit.Framework; @@ -35,6 +36,7 @@ using Nwc.XmlRpc; using OpenSim.Framework.Communications.Cache; using OpenSim.Region.Communications.Local; using OpenSim.Tests.Common.Mock; +using OpenSim.Client.Linden; namespace OpenSim.Framework.Communications.Tests { @@ -60,16 +62,22 @@ namespace OpenSim.Framework.Communications.Tests CommunicationsManager commsManager = new TestCommunicationsManager(new NetworkServersInfo(42, 43)); + + //commsManager.GridService.RegisterRegion( + // new RegionInfo(42, 43, capsEndPoint, regionExternalName)); + //commsManager.GridService.RegionLoginsEnabled = true; - commsManager.GridService.RegisterRegion( - new RegionInfo(42, 43, capsEndPoint, regionExternalName)); - commsManager.GridService.RegionLoginsEnabled = true; + //LoginService loginService + // = new LocalLoginService( + // (UserManagerBase)commsManager.UserService, "Hello folks", commsManager.InterServiceInventoryService, + // (LocalBackEndServices)commsManager.GridService, + // commsManager.NetworkServersInfo, false, new LibraryRootFolder(String.Empty)); - LoginService loginService - = new LocalLoginService( - (UserManagerBase)commsManager.UserService, "Hello folks", commsManager.InterServiceInventoryService, - (LocalBackEndServices)commsManager.GridService, - commsManager.NetworkServersInfo, false, new LibraryRootFolder(String.Empty)); + TestLoginToRegionConnector regionConnector = new TestLoginToRegionConnector(); + regionConnector.AddRegion(new RegionInfo(42, 43, capsEndPoint, regionExternalName)); + + LoginService loginService = new LLStandaloneLoginService((UserManagerBase)commsManager.UserService, "Hello folks", commsManager.InterServiceInventoryService, + commsManager.NetworkServersInfo, false, new LibraryRootFolder(String.Empty), regionConnector); Hashtable loginParams = new Hashtable(); loginParams["first"] = firstName; @@ -108,21 +116,25 @@ namespace OpenSim.Framework.Communications.Tests CommunicationsManager commsManager = new TestCommunicationsManager(new NetworkServersInfo(42, 43)); - commsManager.GridService.RegisterRegion( - new RegionInfo(42, 43, capsEndPoint, regionExternalName)); - commsManager.GridService.RegionLoginsEnabled = true; - LocalUserServices lus = (LocalUserServices)commsManager.UserService; lus.AddUser(firstName,lastName,"boingboing","abc@ftw.com",42,43); + //commsManager.GridService.RegisterRegion( + // new RegionInfo(42, 43, capsEndPoint, regionExternalName)); + //commsManager.GridService.RegionLoginsEnabled = true; - LoginService loginService - = new LocalLoginService( - (UserManagerBase)lus, "Hello folks", commsManager.InterServiceInventoryService, - (LocalBackEndServices)commsManager.GridService, - commsManager.NetworkServersInfo, true, new LibraryRootFolder(String.Empty)); + //LoginService loginService + // = new LocalLoginService( + // (UserManagerBase)lus, "Hello folks", commsManager.InterServiceInventoryService, + // (LocalBackEndServices)commsManager.GridService, + // commsManager.NetworkServersInfo, true, new LibraryRootFolder(String.Empty)); + TestLoginToRegionConnector regionConnector = new TestLoginToRegionConnector(); + regionConnector.AddRegion(new RegionInfo(42, 43, capsEndPoint, regionExternalName)); + + LoginService loginService = new LLStandaloneLoginService((UserManagerBase) lus, "Hello folks", commsManager.InterServiceInventoryService, + commsManager.NetworkServersInfo, true, new LibraryRootFolder(String.Empty), regionConnector); // TODO: Not check inventory part of response yet. // TODO: Not checking all of login response thoroughly yet. @@ -277,5 +289,89 @@ namespace OpenSim.Framework.Communications.Tests responseData = (Hashtable)response.Value; Assert.That(responseData["message"], Is.EqualTo("Hello folks")); } + + public class TestLoginToRegionConnector : ILoginRegionsConnector + { + + private List m_regionsList = new List(); + + public void AddRegion(RegionInfo regionInfo) + { + lock (m_regionsList) + { + if (!m_regionsList.Contains(regionInfo)) + { + m_regionsList.Add(regionInfo); + } + } + } + + #region ILoginRegionsConnector Members + public bool RegionLoginsEnabled + { + get { return true; } + } + + public void LogOffUserFromGrid(ulong regionHandle, OpenMetaverse.UUID AvatarID, OpenMetaverse.UUID RegionSecret, string message) + { + } + + public bool NewUserConnection(ulong regionHandle, AgentCircuitData agent) + { + lock (m_regionsList) + { + foreach (RegionInfo regInfo in m_regionsList) + { + if (regInfo.RegionHandle == regionHandle) + return true; + } + } + return false; + } + + public RegionInfo RequestClosestRegion(string region) + { + lock (m_regionsList) + { + foreach (RegionInfo regInfo in m_regionsList) + { + if (regInfo.RegionName == region) + return regInfo; + } + } + + return null; + } + + public RegionInfo RequestNeighbourInfo(OpenMetaverse.UUID regionID) + { + lock (m_regionsList) + { + foreach (RegionInfo regInfo in m_regionsList) + { + if (regInfo.RegionID == regionID) + return regInfo; + } + } + + return null; + } + + public RegionInfo RequestNeighbourInfo(ulong regionHandle) + { + lock (m_regionsList) + { + foreach (RegionInfo regInfo in m_regionsList) + { + if (regInfo.RegionHandle == regionHandle) + return regInfo; + } + } + + return null; + } + + #endregion + } } } diff --git a/OpenSim/Region/Communications/Local/LocalLoginService.cs b/OpenSim/Region/Communications/Local/LocalLoginService.cs index 4e0ed13393..bd2910f3ee 100644 --- a/OpenSim/Region/Communications/Local/LocalLoginService.cs +++ b/OpenSim/Region/Communications/Local/LocalLoginService.cs @@ -39,6 +39,7 @@ using OpenSim.Framework.Communications.Capabilities; namespace OpenSim.Region.Communications.Local { + /* public delegate void LoginToRegionEvent(ulong regionHandle, Login login); public class LocalLoginService : LoginService @@ -168,6 +169,7 @@ namespace OpenSim.Region.Communications.Local } else { + m_log.InfoFormat("not found the region at {0} {1}", theUser.HomeRegionX, theUser.HomeRegionY); // Emergency mode: Home-region isn't available, so we can't request the region info. // Use the stored home regionHandle instead. // NOTE: If the home-region moves, this will be wrong until the users update their user-profile again @@ -427,5 +429,5 @@ namespace OpenSim.Region.Communications.Local m_gridService.TriggerLogOffUser(SimInfo.RegionHandle, theUser.ID, theUser.CurrentAgent.SecureSessionID, "Logging you off"); } - } + }*/ } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2006c2bd6c..b1a79c23a2 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2296,7 +2296,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void RegisterCommsEvents() { - m_sceneGridService.OnExpectUser += NewUserConnection; + m_sceneGridService.OnExpectUser += HandleNewUserConnection; m_sceneGridService.OnAvatarCrossingIntoRegion += AgentCrossing; m_sceneGridService.OnCloseAgentConnection += IncomingCloseAgent; m_sceneGridService.OnRegionUp += OtherRegionUp; @@ -2328,7 +2328,7 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGridService.OnExpectPrim -= IncomingInterRegionPrimGroup; //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; m_sceneGridService.OnRegionUp -= OtherRegionUp; - m_sceneGridService.OnExpectUser -= NewUserConnection; + m_sceneGridService.OnExpectUser -= HandleNewUserConnection; m_sceneGridService.OnAvatarCrossingIntoRegion -= AgentCrossing; m_sceneGridService.OnCloseAgentConnection -= IncomingCloseAgent; m_sceneGridService.OnGetLandData -= GetLandData; @@ -2339,13 +2339,27 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGridService.Close(); } + /// + /// A handler for the SceneCommunicationService event, to match that events return type of void. + /// Use NewUserConnection() directly if possible so the return type can refuse connections. + /// At the moment nothing actually seems to use this event, + /// as everything is switching to calling the NewUserConnection method directly. + /// + /// + public void HandleNewUserConnection(AgentCircuitData agent) + { + NewUserConnection(agent); + } + /// /// Do the work necessary to initiate a new user connection for a particular scene. /// At the moment, this consists of setting up the caps infrastructure + /// The return bool should allow for connections to be refused, but as not all calling paths + /// take proper notice of it let, we allowed banned users in still. /// /// /// - public void NewUserConnection(AgentCircuitData agent) + public bool NewUserConnection(AgentCircuitData agent) { CapsModule.NewUserConnection(agent); @@ -2358,7 +2372,7 @@ namespace OpenSim.Region.Framework.Scenes sp.AdjustKnownSeeds(); - return; + return true; } // Don't disable this log message - it's too helpful @@ -2371,6 +2385,7 @@ namespace OpenSim.Region.Framework.Scenes m_log.WarnFormat( "[CONNECTION BEGIN]: Incoming user {0} at {1} is on the region banlist", agent.AgentID, RegionInfo.RegionName); + //return false; } CapsModule.AddCapsHandler(agent.AgentID); @@ -2402,6 +2417,8 @@ namespace OpenSim.Region.Framework.Scenes m_log.WarnFormat( "[CONNECTION BEGIN]: We couldn't find a User Info record for {0}. This is usually an indication that the UUID we're looking up is invalid", agent.AgentID); } + + return true; } public void UpdateCircuitData(AgentCircuitData data) @@ -2414,7 +2431,7 @@ namespace OpenSim.Region.Framework.Scenes return m_authenticateHandler.TryChangeCiruitCode(oldcc, newcc); } - protected void HandleLogOffUserFromGrid(UUID AvatarID, UUID RegionSecret, string message) + public void HandleLogOffUserFromGrid(UUID AvatarID, UUID RegionSecret, string message) { ScenePresence loggingOffUser = null; loggingOffUser = GetScenePresence(AvatarID); diff --git a/prebuild.xml b/prebuild.xml index 5a1fcaaf3e..c7ddb2ad91 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1734,10 +1734,12 @@ - - + + + + @@ -2911,6 +2913,7 @@ +