/// <summary> /// Called when we receive the client's initial XMLRPC login_to_simulator request message /// </summary> /// <param name="request">The XMLRPC request</param> /// <returns>The response to send</returns> public virtual XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request, IPEndPoint remoteClient) { string loginUsername = null; try { LoginResponse logResponse = new LoginResponse(); IPAddress IPaddr = remoteClient.Address; string IPstr = IPaddr.ToString(); if (this.IsBannedIP(IPstr)) { m_log.WarnFormat("[LOGIN]: Denying login, IP {0} is BANNED.", IPstr); return logResponse.CreateIPBannedResponseLLSD(); } XmlRpcResponse response = new XmlRpcResponse(); Hashtable requestData = (Hashtable)request.Params[0]; SniffLoginKey((Uri)request.Params[2], requestData); bool GoodXML = (requestData.Contains("first") && requestData.Contains("last") && (requestData.Contains("passwd") || requestData.Contains("web_login_key"))); string firstname = null; string lastname = null; if (GoodXML) { //make sure the user isn't already trying to log in firstname = (string)requestData["first"]; lastname = (string)requestData["last"]; loginUsername = firstname + " " + lastname; lock (_loginsProcessing) { if (_loginsProcessing.Contains(loginUsername)) { return logResponse.CreateAlreadyLoggedInResponse(); } else { _loginsProcessing.Add(loginUsername); } } } string startLocationRequest = "last"; UserProfileData userProfile; string clientChannel = "Unknown"; string clientVersion = "Unknown"; string clientPlatform = "Unknown"; string clientPlatformVer = "Unknown"; if (GoodXML) { if (requestData.Contains("start")) { startLocationRequest = (string)requestData["start"]; } m_log.InfoFormat( "[LOGIN BEGIN]: XMLRPC Received login request message from user '{0}' '{1}'", firstname, lastname); if (requestData.Contains("channel")) { clientChannel = (string)requestData["channel"]; } if (requestData.Contains("version")) { clientVersion = (string)requestData["version"]; } if (requestData.Contains("platform")) { clientPlatform = (string)requestData["platform"]; } if (requestData.Contains("platform_version")) { clientPlatformVer = (string)requestData["platform_version"]; } if (this.IsViewerBlacklisted(clientVersion)) { m_log.WarnFormat("[LOGIN]: Denying login, Client {0} is blacklisted", clientVersion); return logResponse.CreateViewerNotAllowedResponse(); } m_log.InfoFormat( "[LOGIN]: XMLRPC Client is {0} {1} on {2} {3}, start location is {4}", clientChannel, clientVersion, clientPlatform, clientPlatformVer, startLocationRequest); if (!TryAuthenticateXmlRpcLogin(request, firstname, lastname, out userProfile)) { return logResponse.CreateLoginFailedResponse(); } } else { m_log.Info("[LOGIN END]: XMLRPC login_to_simulator login message did not contain all the required data"); return logResponse.CreateGridErrorResponse(); } if (userProfile.GodLevel < m_minLoginLevel) { return logResponse.CreateLoginBlockedResponse(); } else { // If we already have a session... if (userProfile.CurrentAgent != null && userProfile.CurrentAgent.AgentOnline) { // Force a refresh for this due to Commit below UUID userID = userProfile.ID; userProfile = m_userManager.GetUserProfile(userID,true); // on an error, return the former error we returned before recovery was supported. if (userProfile == null) return logResponse.CreateAlreadyLoggedInResponse(); //TODO: The following statements can cause trouble: // If agentOnline could not turn from true back to false normally // because of some problem, for instance, the crashment of server or client, // the user cannot log in any longer. userProfile.CurrentAgent.AgentOnline = false; userProfile.CurrentAgent.LogoutTime = Util.UnixTimeSinceEpoch(); m_userManager.CommitAgent(ref userProfile); // try to tell the region that their user is dead. LogOffUser(userProfile, " XMLRPC You were logged off because you logged in from another location"); // Don't reject the login. We've already cleaned it up, above. m_log.InfoFormat( "[LOGIN END]: XMLRPC Reset user {0} {1} that we believe is already logged in", firstname, lastname); // return logResponse.CreateAlreadyLoggedInResponse(); } // Otherwise... // Create a new agent session m_userManager.ResetAttachments(userProfile.ID); CreateAgent(userProfile, request); // We need to commit the agent right here, even though the userProfile info is not complete // at this point. There is another commit further down. // This is for the new sessionID to be stored so that the region can check it for session authentication. // CustomiseResponse->PrepareLoginToRegion CommitAgent(ref userProfile); try { UUID agentID = userProfile.ID; InventoryData inventData = null; try { inventData = GetInventorySkeleton(agentID); } catch (Exception e) { m_log.ErrorFormat( "[LOGIN END]: Error retrieving inventory skeleton of agent {0} - {1}", agentID, e); return logResponse.CreateLoginInventoryFailedResponse(); } if (inventData != null) { ArrayList AgentInventoryArray = inventData.InventoryArray; Hashtable InventoryRootHash = new Hashtable(); InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString(); ArrayList InventoryRoot = new ArrayList(); InventoryRoot.Add(InventoryRootHash); userProfile.RootInventoryFolderID = inventData.RootFolderID; logResponse.InventoryRoot = InventoryRoot; logResponse.InventorySkeleton = AgentInventoryArray; } // Inventory Library Section Hashtable InventoryLibRootHash = new Hashtable(); InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000"; ArrayList InventoryLibRoot = new ArrayList(); InventoryLibRoot.Add(InventoryLibRootHash); logResponse.InventoryLibRoot = InventoryLibRoot; logResponse.InventoryLibraryOwner = GetLibraryOwner(); logResponse.InventoryLibrary = GetInventoryLibrary(); logResponse.CircuitCode = Util.RandomClass.Next(); logResponse.Lastname = userProfile.SurName; logResponse.Firstname = userProfile.FirstName; logResponse.AgentID = agentID; logResponse.SessionID = userProfile.CurrentAgent.SessionID; logResponse.SecureSessionID = userProfile.CurrentAgent.SecureSessionID; logResponse.Message = GetMessage(); logResponse.MapServerURI = m_MapServerURI; logResponse.ProfileServerURI = m_ProfileServerURI; logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID)); logResponse.StartLocation = startLocationRequest; // m_log.WarnFormat("[LOGIN END]: >>> Login response for {0} SSID={1}", logResponse.AgentID, logResponse.SecureSessionID); if (CustomiseResponse(logResponse, userProfile, startLocationRequest, clientVersion)) { userProfile.LastLogin = userProfile.CurrentAgent.LoginTime; CommitAgent(ref userProfile); // If we reach this point, then the login has successfully logged onto the grid if (StatsManager.UserStats != null) StatsManager.UserStats.AddSuccessfulLogin(); m_log.DebugFormat( "[LOGIN END]: XMLRPC Authentication of user {0} {1} successful. Sending response to client.", firstname, lastname); return logResponse.ToXmlRpcResponse(); } else { m_log.ErrorFormat("[LOGIN END]: XMLRPC informing user {0} {1} that login failed due to an unavailable region", firstname, lastname); return logResponse.CreateDeadRegionResponse(); } } catch (Exception e) { m_log.Error("[LOGIN END]: XMLRPC Login failed, " + e); m_log.Error(e.StackTrace); } } m_log.Info("[LOGIN END]: XMLRPC Login failed. Sending back blank XMLRPC response"); return response; } finally { if (loginUsername != null) { lock (_loginsProcessing) { _loginsProcessing.Remove(loginUsername); } } } }