From 130c80efe004fa06808cc639ad8e2ee31c35744b Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 31 Dec 2009 17:18:55 -0800 Subject: A lot more beef on the login service. The LLLoginResponse is a MONSTER! Almost done... --- OpenSim/Server/Handlers/Login/LLLoginHandlers.cs | 14 +- OpenSim/Services/Interfaces/ILoginService.cs | 3 +- OpenSim/Services/LLLoginService/LLLoginResponse.cs | 225 +++++++++++++++++++++ OpenSim/Services/LLLoginService/LLLoginService.cs | 84 ++++++-- prebuild.xml | 1 + 5 files changed, 303 insertions(+), 24 deletions(-) diff --git a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs index b973c11..aaa958b 100644 --- a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs +++ b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs @@ -68,12 +68,22 @@ namespace OpenSim.Server.Handlers.Login requestData.ContainsKey("last") && requestData["last"] != null && requestData.ContainsKey("passwd") && requestData["passwd"] != null) { + string first = requestData["first"].ToString(); + string last = requestData["last"].ToString(); + string passwd = requestData["passwd"].ToString(); string startLocation = string.Empty; if (requestData.ContainsKey("start")) startLocation = requestData["start"].ToString(); + string clientVersion = "Unknown"; + if (requestData.Contains("version")) + clientVersion = requestData["version"].ToString(); + // We should do something interesting with the client version... + + m_log.InfoFormat("[LOGIN]: XMLRPC Login Requested for {0} {1}, starting in {2}, using {3}", first, last, startLocation, clientVersion); + LoginResponse reply = null; - reply = m_LocalService.Login(requestData["first"].ToString(), requestData["last"].ToString(), requestData["passwd"].ToString(), startLocation); + reply = m_LocalService.Login(first, last, passwd, startLocation, remoteClient); XmlRpcResponse response = new XmlRpcResponse(); response.Value = reply.ToHashtable(); @@ -102,7 +112,7 @@ namespace OpenSim.Server.Handlers.Login m_log.Info("[LOGIN]: LLSD Login Requested for: '" + map["first"].AsString() + "' '" + map["last"].AsString() + "' / " + startLocation); LoginResponse reply = null; - reply = m_LocalService.Login(map["first"].AsString(), map["last"].AsString(), map["passwd"].AsString(), startLocation); + reply = m_LocalService.Login(map["first"].AsString(), map["last"].AsString(), map["passwd"].AsString(), startLocation, remoteClient); return reply.ToOSDMap(); } diff --git a/OpenSim/Services/Interfaces/ILoginService.cs b/OpenSim/Services/Interfaces/ILoginService.cs index 0f82de5..24bf342 100644 --- a/OpenSim/Services/Interfaces/ILoginService.cs +++ b/OpenSim/Services/Interfaces/ILoginService.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Net; using OpenMetaverse.StructuredData; @@ -45,7 +46,7 @@ namespace OpenSim.Services.Interfaces public interface ILoginService { - LoginResponse Login(string firstName, string lastName, string passwd, string startLocation); + LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, IPEndPoint clientIP); } diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index fbce63f..18a4f02 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -28,11 +28,19 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Net; using System.Reflection; + using OpenSim.Framework; +using OpenSim.Framework.Capabilities; +using OpenSim.Services.Interfaces; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + using log4net; using OpenMetaverse; using OpenMetaverse.StructuredData; +using OSDArray = OpenMetaverse.StructuredData.OSDArray; +using OSDMap = OpenMetaverse.StructuredData.OSDMap; namespace OpenSim.Services.LLLoginService { @@ -202,6 +210,132 @@ namespace OpenSim.Services.LLLoginService SetDefaultValues(); } + public LLLoginResponse(UserAccount account, AgentCircuitData aCircuit, PresenceInfo pinfo, + GridRegion destination, List invSkel, + string where, string startlocation, Vector3 position, Vector3 lookAt, string message, + GridRegion home, IPEndPoint clientIP) + : this() + { + FillOutInventoryData(invSkel); + + CircuitCode = (int)aCircuit.circuitcode; + Lastname = account.LastName; + Firstname = account.FirstName; + AgentID = account.PrincipalID; + SessionID = aCircuit.SessionID; + SecureSessionID = aCircuit.SecureSessionID; + Message = message; + // While we don't have friends... + //BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID)); + BuddList = new LLLoginResponse.BuddyList(); + StartLocation = where; + + FillOutHomeData(pinfo, home); + LookAt = String.Format("[r{0},r{1},r{2}]", lookAt.X, lookAt.Y, lookAt.Z); + + FillOutRegionData(destination); + + FillOutSeedCap(aCircuit, destination, clientIP); + + } + + private void FillOutInventoryData(List invSkel) + { + InventoryData inventData = null; + + try + { + inventData = GetInventorySkeleton(invSkel); + } + catch (Exception e) + { + m_log.WarnFormat( + "[LLLOGIN SERVICE]: Error processing inventory skeleton of agent {0} - {1}", + agentID, e); + + // ignore and continue + } + + if (inventData != null) + { + ArrayList AgentInventoryArray = inventData.InventoryArray; + + Hashtable InventoryRootHash = new Hashtable(); + InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString(); + InventoryRoot = new ArrayList(); + InventoryRoot.Add(InventoryRootHash); + InventorySkeleton = AgentInventoryArray; + } + + // Inventory Library Section + Hashtable InventoryLibRootHash = new Hashtable(); + InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000"; + InventoryLibRoot = new ArrayList(); + InventoryLibRoot.Add(InventoryLibRootHash); + + InventoryLibraryOwner = GetLibraryOwner(); + InventoryLibrary = GetInventoryLibrary(); + } + + private void FillOutHomeData(PresenceInfo pinfo, GridRegion home) + { + int x = 1000 * (int)Constants.RegionSize, y = 1000 * (int)Constants.RegionSize; + if (home != null) + { + x = home.RegionLocX; + y = home.RegionLocY; + } + + Home = string.Format( + "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}", + home.RegionLocX, + home.RegionLocY, + pinfo.HomePosition.X, pinfo.HomePosition.Y, pinfo.HomePosition.Z, + pinfo.HomeLookAt.X, pinfo.HomeLookAt.Y, pinfo.HomeLookAt.Z); + + } + + private void FillOutRegionData(GridRegion destination) + { + IPEndPoint endPoint = destination.ExternalEndPoint; + SimAddress = endPoint.Address.ToString(); + SimPort = (uint)endPoint.Port; + RegionX = (uint)destination.RegionLocX; + RegionY = (uint)destination.RegionLocY; + } + + private void FillOutSeedCap(AgentCircuitData aCircuit, GridRegion destination, IPEndPoint ipepClient) + { + string capsSeedPath = String.Empty; + + // 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; + + #region IP Translation for NAT + if (ipepClient != null) + { + capsSeedPath + = "http://" + + NetworkUtil.GetHostFor(ipepClient.Address, destination.ExternalHostName) + + ":" + + destination.HttpPort + + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); + } + else + { + capsSeedPath + = "http://" + + destination.ExternalHostName + + ":" + + destination.HttpPort + + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); + } + #endregion + + SeedCapability = capsSeedPath; + } + private void SetDefaultValues() { DST = TimeZone.CurrentTimeZone.IsDaylightSavingTime(DateTime.Now) ? "Y" : "N"; @@ -465,6 +599,97 @@ namespace OpenSim.Services.LLLoginService // this.classifiedCategoriesHash.Clear(); } + + private static LLLoginResponse.BuddyList ConvertFriendListItem(List LFL) + { + LLLoginResponse.BuddyList buddylistreturn = new LLLoginResponse.BuddyList(); + foreach (FriendListItem fl in LFL) + { + LLLoginResponse.BuddyList.BuddyInfo buddyitem = new LLLoginResponse.BuddyList.BuddyInfo(fl.Friend); + buddyitem.BuddyID = fl.Friend; + buddyitem.BuddyRightsHave = (int)fl.FriendListOwnerPerms; + buddyitem.BuddyRightsGiven = (int)fl.FriendPerms; + buddylistreturn.AddNewBuddy(buddyitem); + } + return buddylistreturn; + } + + private InventoryData GetInventorySkeleton(List folders) + { + 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); + + } + + /// + /// Converts the inventory library skeleton into the form required by the rpc request. + /// + /// + protected virtual ArrayList GetInventoryLibrary() + { + // While we don't have library... + //Dictionary rootFolders + // = m_libraryRootFolder.RequestSelfAndDescendentFolders(); + Dictionary rootFolders = new Dictionary(); + ArrayList folderHashes = new ArrayList(); + + foreach (InventoryFolderBase folder in rootFolders.Values) + { + Hashtable TempHash = new Hashtable(); + TempHash["name"] = folder.Name; + TempHash["parent_id"] = folder.ParentID.ToString(); + TempHash["version"] = (Int32)folder.Version; + TempHash["type_default"] = (Int32)folder.Type; + TempHash["folder_id"] = folder.ID.ToString(); + folderHashes.Add(TempHash); + } + + return folderHashes; + } + + /// + /// + /// + /// + protected virtual ArrayList GetLibraryOwner() + { + //for now create random inventory library owner + Hashtable TempHash = new Hashtable(); + TempHash["agent_id"] = "11111111-1111-0000-0000-000100bba000"; + ArrayList inventoryLibOwner = new ArrayList(); + inventoryLibOwner.Add(TempHash); + return inventoryLibOwner; + } + + public class InventoryData + { + public ArrayList InventoryArray = null; + public UUID RootFolderID = UUID.Zero; + + public InventoryData(ArrayList invList, UUID rootID) + { + InventoryArray = invList; + RootFolderID = rootID; + } + } + #region Properties public string Login diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 25a65b5..7d24637 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Net; using System.Reflection; using System.Text.RegularExpressions; @@ -8,6 +9,7 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Framework.Capabilities; using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; @@ -27,6 +29,8 @@ namespace OpenSim.Services.LLLoginService private string m_DefaultRegionName; private string m_RemoteSimulationDll; + private string m_WelcomeMessage; + private bool m_RequireInventory; public LLLoginService(IConfigSource config, ISimulationService simService) { @@ -42,6 +46,8 @@ namespace OpenSim.Services.LLLoginService m_DefaultRegionName = serverConfig.GetString("DefaultRegion", String.Empty); m_RemoteSimulationDll = serverConfig.GetString("RemoteSimulationService", String.Empty); + m_WelcomeMessage = serverConfig.GetString("WelcomeMessage", "Welcome to OpenSim!"); + m_RequireInventory = serverConfig.GetBoolean("RequireInventory", true); // These 3 are required; the other 2 aren't if (accountService == string.Empty || authService == string.Empty || @@ -64,50 +70,76 @@ namespace OpenSim.Services.LLLoginService { } - public LoginResponse Login(string firstName, string lastName, string passwd, string startLocation) + public LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, IPEndPoint clientIP) { bool success = false; // Get the account and check that it exists UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, firstName, lastName); if (account == null) + { + m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: user not found"); return LLFailedLoginResponse.UserProblem; + } // Authenticate this user string token = m_AuthenticationService.Authenticate(account.PrincipalID, passwd, 30); UUID secureSession = UUID.Zero; if ((token == string.Empty) || (token != string.Empty && !UUID.TryParse(token, out secureSession))) + { + m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: authentication failed"); return LLFailedLoginResponse.UserProblem; + } // Get the user's inventory List inventorySkel = m_InventoryService.GetInventorySkeleton(account.PrincipalID); - if ((inventorySkel == null) || (inventorySkel != null && inventorySkel.Count == 0)) + if (m_RequireInventory && ((inventorySkel == null) || (inventorySkel != null && inventorySkel.Count == 0))) + { + m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: unable to retrieve user inventory"); return LLFailedLoginResponse.InventoryProblem; + } // Login the presence + // We may want to check for user already logged in, to + // stay compatible with what people expect... UUID session = UUID.Random(); + PresenceInfo presence = null; + GridRegion home = null; if (m_PresenceService != null) { success = m_PresenceService.LoginAgent(account.PrincipalID.ToString(), session, secureSession); if (!success) + { + m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: could not login presence"); return LLFailedLoginResponse.GridProblem; + } + // Get the updated presence info + presence = m_PresenceService.GetAgent(session); + + // Get the home region + if ((presence.HomeRegionID != UUID.Zero) && m_GridService != null) + { + home = m_GridService.GetRegionByUUID(account.ScopeID, presence.HomeRegionID); + } } // Find the destination region/grid string where = string.Empty; Vector3 position = Vector3.Zero; Vector3 lookAt = Vector3.Zero; - GridRegion destination = FindDestination(account, session, startLocation, out where, out position, out lookAt); + GridRegion destination = FindDestination(account, presence, session, startLocation, out where, out position, out lookAt); if (destination == null) { m_PresenceService.LogoutAgent(session); + m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: destination not found"); return LLFailedLoginResponse.GridProblem; } // Instantiate/get the simulation interface and launch an agent at the destination ISimulationService simConnector = null; - success = false; string reason = string.Empty; + uint circuitCode = 0; + AgentCircuitData aCircuit = null; Object[] args = new Object[] { destination }; // HG standalones have both a localSimulatonDll and a remoteSimulationDll // non-HG standalones have just a localSimulationDll @@ -117,20 +149,27 @@ namespace OpenSim.Services.LLLoginService else if (m_RemoteSimulationDll != string.Empty) simConnector = ServerUtils.LoadPlugin(m_RemoteSimulationDll, args); if (simConnector != null) - success = LaunchAgent(simConnector, destination, account, session, out reason); - if (!success) + { + circuitCode = (uint)Util.RandomClass.Next(); ; + aCircuit = LaunchAgent(simConnector, destination, account, session, secureSession, circuitCode, position, out reason); + } + if (aCircuit == null) { m_PresenceService.LogoutAgent(session); + m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: {0}", reason); return LLFailedLoginResponse.GridProblem; } + // TODO: Get Friends list... + // Finally, fill out the response and return it - LLLoginResponse response = new LLLoginResponse(); - //.... + LLLoginResponse response = new LLLoginResponse(account, aCircuit, presence, destination, inventorySkel, + where, startLocation, position, lookAt, m_WelcomeMessage, home, clientIP); + return response; } - private GridRegion FindDestination(UserAccount account, UUID sessionID, string startLocation, out string where, out Vector3 position, out Vector3 lookAt) + private GridRegion FindDestination(UserAccount account, PresenceInfo pinfo, UUID sessionID, string startLocation, out string where, out Vector3 position, out Vector3 lookAt) { where = "home"; position = new Vector3(128, 128, 0); @@ -141,12 +180,11 @@ namespace OpenSim.Services.LLLoginService if (m_PresenceService == null || m_GridService == null) return null; - GridRegion region = null; - PresenceInfo pinfo = m_PresenceService.GetAgent(sessionID); - // this should succeed; if it doesn't there's something wrong with this grid if (pinfo == null) return null; + GridRegion region = null; + if (pinfo.HomeRegionID.Equals(UUID.Zero)) region = m_GridService.GetRegionByName(account.ScopeID, m_DefaultRegionName); else @@ -161,12 +199,11 @@ namespace OpenSim.Services.LLLoginService if (m_PresenceService == null || m_GridService == null) return null; - GridRegion region = null; - PresenceInfo pinfo = m_PresenceService.GetAgent(sessionID); - // this should succeed; if it doesn't there's something wrong with this grid if (pinfo == null) return null; + GridRegion region = null; + if (pinfo.RegionID.Equals(UUID.Zero)) region = m_GridService.GetRegionByName(account.ScopeID, m_DefaultRegionName); else @@ -250,24 +287,29 @@ namespace OpenSim.Services.LLLoginService } - private bool LaunchAgent(ISimulationService simConnector, GridRegion region, UserAccount account, UUID session, out string reason) + private AgentCircuitData LaunchAgent(ISimulationService simConnector, GridRegion region, UserAccount account, + UUID session, UUID secureSession, uint circuit, Vector3 position, out string reason) { reason = string.Empty; AgentCircuitData aCircuit = new AgentCircuitData(); + aCircuit.AgentID = account.PrincipalID; //aCircuit.Appearance = optional //aCircuit.BaseFolder = irrelevant - //aCircuit.CapsPath = required + aCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); aCircuit.child = false; - //aCircuit.circuitcode = required + aCircuit.circuitcode = circuit; aCircuit.firstname = account.FirstName; //aCircuit.InventoryFolder = irrelevant aCircuit.lastname = account.LastName; - //aCircuit.SecureSessionID = required + aCircuit.SecureSessionID = secureSession; aCircuit.SessionID = session; - //aCircuit.startpos = required + aCircuit.startpos = position; + + if (simConnector.CreateAgent(region.RegionHandle, aCircuit, 0, out reason)) + return aCircuit; - return simConnector.CreateAgent(region.RegionHandle, aCircuit, 0, out reason); + return null; } } diff --git a/prebuild.xml b/prebuild.xml index 61f5d50..b533f7b 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1494,6 +1494,7 @@ ../../../bin/ + -- cgit v1.1