From abc5df12c883ab14bf7926fc047431249ba52cb5 Mon Sep 17 00:00:00 2001
From: Homer Horwitz
Date: Sun, 15 Mar 2009 21:34:28 +0000
Subject: This patch improves MXP connect and disconnect functionality. -
 Avatars are now properly on top of terrain. - ScenePresence is now removed
 from Scene only once. Fixes Mantis #3302. Thanks tlaukkan.

---
 OpenSim/Client/MXP/ClientStack/MXPClientView.cs    |  34 ++-
 OpenSim/Client/MXP/MXPModule.cs                    |  18 +-
 .../Client/MXP/PacketHandler/MXPPacketServer.cs    | 271 ++++++++++++++-------
 3 files changed, 208 insertions(+), 115 deletions(-)

diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
index 9052443..5a7accf 100644
--- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
+++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
@@ -189,8 +189,6 @@ namespace OpenSim.Client.MXP.ClientStack
 
         private void MXPProcessModifyRequest(ModifyRequestMessage modifyRequest)
         {
-            m_log.Debug("Received modify request for: " + modifyRequest.ObjectFragment.ObjectName);
-
             ObjectFragment objectFragment=modifyRequest.ObjectFragment;
             if (objectFragment.ObjectId == m_userID.Guid)
             {
@@ -448,7 +446,7 @@ namespace OpenSim.Client.MXP.ClientStack
             Session.Send(pe);
         }
 
-        public void MXPSentSynchronizationBegin(int objectCount)
+        public void MXPSendSynchronizationBegin(int objectCount)
         {
             m_objectsToSynchronize = objectCount;
             m_objectsSynchronized = 0;
@@ -767,6 +765,15 @@ namespace OpenSim.Client.MXP.ClientStack
             //throw new System.NotImplementedException();
         }
 
+        public void OnClean()
+        {
+            if (OnLogout != null)
+                OnLogout(this);
+
+            if (OnConnectionClosed != null)
+                OnConnectionClosed(this);
+        }
+
         public void Close(bool ShutdownCircuit)
         {
             m_log.Info("[MXP ClientStack] Close Called with SC=" + ShutdownCircuit);
@@ -780,16 +787,6 @@ namespace OpenSim.Client.MXP.ClientStack
                 Session.SetStateDisconnected();
             }
 
-            // Handle OpenSim cleanup
-            if (ShutdownCircuit)
-            {
-                if (OnConnectionClosed != null)
-                    OnConnectionClosed(this);
-            }
-            else
-            {
-                Scene.RemoveClient(AgentId);
-            }
         }
 
         public void Kick(string message)
@@ -800,6 +797,17 @@ namespace OpenSim.Client.MXP.ClientStack
         public void Start()
         {
             Scene.AddNewClient(this);
+
+            // Mimicking LLClientView which gets always set appearance from client.
+            OpenSim.Region.Framework.Scenes.Scene scene=(OpenSim.Region.Framework.Scenes.Scene)Scene;
+            AvatarAppearance appearance;
+            scene.GetAvatarAppearance(this,out appearance);
+            List<byte> visualParams = new List<byte>();
+            foreach (byte visualParam in appearance.VisualParams)
+            {
+                visualParams.Add(visualParam);
+            }
+            OnSetAppearance(appearance.Texture.ToBytes(), visualParams);
         }
 
         public void Stop()
diff --git a/OpenSim/Client/MXP/MXPModule.cs b/OpenSim/Client/MXP/MXPModule.cs
index 6ec7744..4eb0058 100644
--- a/OpenSim/Client/MXP/MXPModule.cs
+++ b/OpenSim/Client/MXP/MXPModule.cs
@@ -38,21 +38,20 @@ using OpenSim.Region.Framework.Scenes;
 
 namespace OpenSim.Client.MXP
 {
+
     /**
      * MXP Client Module which adds MXP support to client / region communication.
      */
     public class MXPModule : IRegionModule
     {
+        private MXPPacketServer m_server;
 
+        private IConfigSource m_config;
         private int m_port = 1253;
-        //private int m_ticks = 0;
-        private bool m_shutdown = false;
 
-        private IConfigSource m_config;
-        private readonly Timer m_ticker = new Timer(100);
         private readonly Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
-
-        private MXPPacketServer m_server;
+        private readonly Timer m_ticker = new Timer(100);
+        private bool m_shutdown = false;
 
         public void Initialise(Scene scene, IConfigSource source)
         {
@@ -88,13 +87,6 @@ namespace OpenSim.Client.MXP
 
             if (!m_shutdown)
                 m_ticker.Start();
-
-            // Commenting this at because of the excess flood to log.
-            // TODO: Add ini file option.
-            /*if (++ticks % 100 == 0)
-            {
-                server.PrintDebugInformation();
-            }*/
         }
 
         public void Close()
diff --git a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
index ba7bd00..bb04955 100644
--- a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
+++ b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
@@ -40,6 +40,7 @@ using OpenSim.Client.MXP.ClientStack;
 using OpenSim.Framework;
 using OpenSim.Region.Framework.Scenes;
 using OpenSim.Framework.Communications;
+using System.Security.Cryptography;
 
 namespace OpenSim.Client.MXP.PacketHandler
 {
@@ -214,17 +215,6 @@ namespace OpenSim.Client.MXP.PacketHandler
 
         #region Processing
 
-        public void PrintDebugInformation()
-        {
-            m_log.Info("[MXP ClientStack] Statistics report");
-            m_log.Info("Pending Sessions: " + PendingSessionCount);
-            m_log.Info("Sessions: " + SessionCount + " (Clients: " + m_clients.Count + " )");
-            m_log.Info("Transmitter Alive?: " + IsTransmitterAlive);
-            m_log.Info("Packets Sent/Received: " + PacketsSent + " / " + PacketsReceived);
-            m_log.Info("Bytes Sent/Received: " + BytesSent + " / " + BytesReceived);
-            m_log.Info("Send/Receive Rate (bps): " + SendRate + " / " + ReceiveRate);
-        }
-
         public void Process()
         {
             ProcessMessages();
@@ -243,7 +233,7 @@ namespace OpenSim.Client.MXP.PacketHandler
 
             foreach (MXPClientView clientView in m_sessionsToRemove)
             {
-                clientView.Scene.RemoveClient(clientView.AgentId);
+                clientView.OnClean();
                 m_clients.Remove(clientView);
                 m_sessions.Remove(clientView.Session);
             }
@@ -251,59 +241,6 @@ namespace OpenSim.Client.MXP.PacketHandler
             m_sessionsToRemove.Clear();
         }
 
-        public bool AuthoriseUser(string participantName, string password, UUID sceneId, out UUID userId, out string firstName, out string lastName)
-        {
-            userId = UUID.Zero;
-            firstName = "";
-            lastName = "";
-
-            if (!m_scenes.ContainsKey(sceneId))
-            {
-                m_log.Info("Login failed as region was not found: " + sceneId);
-                return false;
-            }
-           
-            string[] nameParts=participantName.Split(' ');
-            if (nameParts.Length != 2)
-            {
-                m_log.Info("Login failed as user name is not formed of first and last name separated by space: " + participantName);
-                return false;
-            }
-            firstName = nameParts[0];
-            lastName = nameParts[1];
-            
-            UserProfileData userProfile = m_scenes[sceneId].CommsManager.UserService.GetUserProfile(firstName, lastName);
-            if (userProfile == null && !m_accountsAuthenticate)
-            {
-                userId = ((UserManagerBase)m_scenes[sceneId].CommsManager.UserService).AddUser(firstName, lastName, "test", "", 1000, 1000);
-            }
-            else
-            {
-                if (userProfile == null)
-                {
-                    m_log.Info("Login failed as user was not found: " + participantName);
-                    return false;
-                }
-                userId = userProfile.ID;
-            }
-
-            if (m_accountsAuthenticate)
-            {
-                if (!password.StartsWith("$1$"))
-                {
-                    password = "$1$" + Util.Md5Hash(password);
-                }
-                password = password.Remove(0, 3); //remove $1$
-                string s = Util.Md5Hash(password + ":" + userProfile.PasswordSalt);
-                return (userProfile.PasswordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase)
-                                   || userProfile.PasswordHash.Equals(password, StringComparison.InvariantCultureIgnoreCase));
-            }
-            else
-            {
-                return true;
-            }
-        }
-
         public void ProcessMessages()
         {
             if (m_transmitter.PendingSessionCount > 0)
@@ -327,9 +264,9 @@ namespace OpenSim.Client.MXP.PacketHandler
 
                         JoinRequestMessage joinRequestMessage = (JoinRequestMessage) message;
 
-                        UUID userId;
-                        string firstName;
-                        string lastName;
+                        m_log.Info("[MXP ClientStack] Session join request: " + session.SessionId + " (" +
+                           (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" +
+                            session.RemoteEndPoint.Port + ")");
 
                         if (joinRequestMessage.BubbleId == Guid.Empty)
                         {
@@ -337,7 +274,7 @@ namespace OpenSim.Client.MXP.PacketHandler
                             {
                                 if (scene.RegionInfo.RegionName == joinRequestMessage.BubbleName)
                                 {
-                                    m_log.Info("Resolved region by name: " + joinRequestMessage.BubbleName + " (" + scene.RegionInfo.RegionID+")");
+                                    m_log.Info("[MXP ClientStack] Resolved region by name: " + joinRequestMessage.BubbleName + " (" + scene.RegionInfo.RegionID + ")");
                                     joinRequestMessage.BubbleId = scene.RegionInfo.RegionID.Guid;
                                 }
                             }
@@ -345,47 +282,71 @@ namespace OpenSim.Client.MXP.PacketHandler
 
                         if (joinRequestMessage.BubbleId == Guid.Empty)
                         {
-                            m_log.Warn("Failed to resolve region by name: "+joinRequestMessage.BubbleName);
+                            m_log.Warn("[MXP ClientStack] Failed to resolve region by name: " + joinRequestMessage.BubbleName);
+                        }
+                        
+                        UUID sceneId = new UUID(joinRequestMessage.BubbleId);
+
+                        bool regionExists = true;
+                        if (!m_scenes.ContainsKey(sceneId))
+                        {
+                            m_log.Info("[MXP ClientStack] No such region: " + sceneId);
+                            regionExists=false;
                         }
 
-                        bool authorized = AuthoriseUser(joinRequestMessage.ParticipantName,
+                        UserProfileData user=null;
+                        UUID userId=UUID.Zero;
+                        string firstName=null;
+                        string lastName=null;
+                        bool authorized = regionExists?AuthoriseUser(joinRequestMessage.ParticipantName,
                                                         joinRequestMessage.ParticipantPassphrase,
-                                                        new UUID(joinRequestMessage.BubbleId), out userId, out firstName, out lastName);
+                                                        new UUID(joinRequestMessage.BubbleId), out userId, out firstName, out lastName, out user)
+                                                        :false;
 
                         if (authorized)
-                        {
-                            Scene target = m_scenes[new UUID(joinRequestMessage.BubbleId)];
-
+                        {                            
+                            Scene scene = m_scenes[sceneId];
                             UUID mxpSessionID = UUID.Random();
 
                             m_log.Info("[MXP ClientStack] Session join request success: " + session.SessionId + " (" +
-                                       (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" +
-                                       session.RemoteEndPoint.Port + ")");
-
-                            AcceptConnection(session, joinRequestMessage, mxpSessionID,userId);
-
-                            MXPClientView client = new MXPClientView(session, mxpSessionID,userId, target,
-                                                                     firstName, lastName);
-                            m_log.Info("[MXP ClientStack] Created Client");
+                               (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" +
+                               session.RemoteEndPoint.Port + ")");
+
+                            m_log.Info("[MXP ClientStack] Attaching UserAgent to UserProfile...");
+                            AttachUserAgentToUserProfile(session, mxpSessionID, sceneId, user);
+                            m_log.Info("[MXP ClientStack] Attached UserAgent to UserProfile.");
+                            m_log.Info("[MXP ClientStack] Preparing Scene to Connection...");
+                            PrepareSceneForConnection(mxpSessionID, sceneId, user);
+                            m_log.Info("[MXP ClientStack] Prepared Scene to Connection.");
+                            m_log.Info("[MXP ClientStack] Accepting connection...");
+                            AcceptConnection(session, joinRequestMessage, mxpSessionID, userId);
+                            m_log.Info("[MXP ClientStack] Accepted connection.");
+
+                            m_log.Info("[MXP ClientStack] Creating ClientView....");
+                            MXPClientView client = new MXPClientView(session, mxpSessionID, userId, scene, firstName, lastName);
                             m_clients.Add(client);
+                            m_log.Info("[MXP ClientStack] Created ClientView.");
 
-                            m_log.Info("[MXP ClientStack] Adding to Scene");
-                            target.ClientManager.Add(client.CircuitCode, client);
 
-                            m_log.Info("[MXP ClientStack] Initialising...");
+                            m_log.Info("[MXP ClientStack] Adding ClientView to Scene...");                            
+                            scene.ClientManager.Add(client.CircuitCode, client);
+                            m_log.Info("[MXP ClientStack] Added ClientView to Scene.");                            
 
-                            client.MXPSentSynchronizationBegin(m_scenes[new UUID(joinRequestMessage.BubbleId)].SceneContents.GetTotalObjectsCount());
+                            
+                            client.MXPSendSynchronizationBegin(m_scenes[new UUID(joinRequestMessage.BubbleId)].SceneContents.GetTotalObjectsCount());
 
+                            m_log.Info("[MXP ClientStack] Starting ClientView...");
                             try
                             {
                                 client.Start();
-                            } catch( Exception e)
+                                m_log.Info("[MXP ClientStack] Started ClientView.");
+                            }
+                            catch (Exception e)
                             {
                                 m_log.Info(e);
                             }
 
                             m_log.Info("[MXP ClientStack] Connected");
-                            //target.EventManager.TriggerOnNewClient(client);
                         }
                         else
                         {
@@ -512,6 +473,138 @@ namespace OpenSim.Client.MXP.PacketHandler
             session.SetStateDisconnected();
         }
 
+        public bool AuthoriseUser(string participantName, string password, UUID sceneId, out UUID userId, out string firstName, out string lastName, out UserProfileData userProfile)
+        {
+            userId = UUID.Zero;
+            firstName = "";
+            lastName = "";
+            userProfile = null;
+
+            string[] nameParts = participantName.Split(' ');
+            if (nameParts.Length != 2)
+            {
+                m_log.Info("[MXP ClientStack] Login failed as user name is not formed of first and last name separated by space: " + participantName);
+                return false;
+            }
+            firstName = nameParts[0];
+            lastName = nameParts[1];
+
+            userProfile = m_scenes[sceneId].CommsManager.UserService.GetUserProfile(firstName, lastName);
+            if (userProfile == null && !m_accountsAuthenticate)
+            {
+                userId = ((UserManagerBase)m_scenes[sceneId].CommsManager.UserService).AddUser(firstName, lastName, "test", "", 1000, 1000);
+            }
+            else
+            {
+                if (userProfile == null)
+                {
+                    m_log.Info("Login failed as user was not found: " + participantName);
+                    return false;
+                }
+                userId = userProfile.ID;
+            }
+
+            if (m_accountsAuthenticate)
+            {
+                if (!password.StartsWith("$1$"))
+                {
+                    password = "$1$" + Util.Md5Hash(password);
+                }
+                password = password.Remove(0, 3); //remove $1$
+                string s = Util.Md5Hash(password + ":" + userProfile.PasswordSalt);
+                return (userProfile.PasswordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase)
+                                   || userProfile.PasswordHash.Equals(password, StringComparison.InvariantCultureIgnoreCase));
+            }
+            else
+            {
+                return true;
+            }
+        }
+
+        private void AttachUserAgentToUserProfile(Session session, UUID sessionId, UUID sceneId, UserProfileData userProfile)
+        {
+            Scene scene = m_scenes[sceneId];
+            CommunicationsManager commsManager = m_scenes[sceneId].CommsManager;
+            UserManagerBase userService = (UserManagerBase)commsManager.UserService;
+
+            UserAgentData agent = new UserAgentData();
+
+            // User connection
+            agent.AgentOnline = true;
+            agent.AgentIP = session.RemoteEndPoint.Address.ToString();
+            agent.AgentPort = (uint)session.RemoteEndPoint.Port;
+
+            agent.SecureSessionID = UUID.Random();
+            agent.SessionID = sessionId;
+
+            // Profile UUID
+            agent.ProfileID = userProfile.ID;
+
+            // Current location/position/alignment
+            if (userProfile.CurrentAgent != null)
+            {
+                agent.Region = userProfile.CurrentAgent.Region;
+                agent.Handle = userProfile.CurrentAgent.Handle;
+                agent.Position = userProfile.CurrentAgent.Position;
+                agent.LookAt = userProfile.CurrentAgent.LookAt;
+            }
+            else
+            {
+                agent.Region = userProfile.HomeRegionID;
+                agent.Handle = userProfile.HomeRegion;
+                agent.Position = userProfile.HomeLocation;
+                agent.LookAt = userProfile.HomeLookAt;
+            }
+
+            // What time did the user login?
+            agent.LoginTime = Util.UnixTimeSinceEpoch();
+            agent.LogoutTime = 0;
+
+            userProfile.CurrentAgent = agent;
+
+            userService.CommitAgent(ref userProfile);
+        }
+
+        private void PrepareSceneForConnection(UUID sessionId, UUID sceneId, UserProfileData userProfile)
+        {
+            Scene scene = m_scenes[sceneId];
+            CommunicationsManager commsManager = m_scenes[sceneId].CommsManager;
+            UserManagerBase userService = (UserManagerBase)commsManager.UserService;
+
+            AgentCircuitData agent = new AgentCircuitData();
+            agent.AgentID = userProfile.ID;
+            agent.firstname = userProfile.FirstName;
+            agent.lastname = userProfile.SurName;
+            agent.SessionID = sessionId;
+            agent.SecureSessionID = userProfile.CurrentAgent.SecureSessionID;
+            agent.circuitcode = sessionId.CRC();
+            agent.BaseFolder = UUID.Zero;
+            agent.InventoryFolder = UUID.Zero;
+            agent.startpos = new Vector3(0, 0, 0); // TODO Fill in region start position
+            agent.CapsPath = "http://localhost/";
+            agent.Appearance = userService.GetUserAppearance(userProfile.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();
+            }
+
+            scene.NewUserConnection(agent);
+
+        }
+
+        public void PrintDebugInformation()
+        {
+            m_log.Info("[MXP ClientStack] Statistics report");
+            m_log.Info("Pending Sessions: " + PendingSessionCount);
+            m_log.Info("Sessions: " + SessionCount + " (Clients: " + m_clients.Count + " )");
+            m_log.Info("Transmitter Alive?: " + IsTransmitterAlive);
+            m_log.Info("Packets Sent/Received: " + PacketsSent + " / " + PacketsReceived);
+            m_log.Info("Bytes Sent/Received: " + BytesSent + " / " + BytesReceived);
+            m_log.Info("Send/Receive Rate (bps): " + SendRate + " / " + ReceiveRate);
+        }
+
         #endregion
     
     }
-- 
cgit v1.1