From 70d9cec3b5064d874f8b9622804c964beeac5f0d Mon Sep 17 00:00:00 2001
From: lbsa71
Date: Tue, 18 Sep 2007 13:29:16 +0000
Subject: * Yet some more connectivity restructuring   * We now have
 CloseAllAgents( circuit ) and CloseAllCircuits( agentId ) for great justice (
 but alas, still only closing on one single scene - be brave! )   * Login and
 ConnectionClosed now eventified and moveified awayified   * Killed off unused
 NullClientAPI   * Now the client is almost only responsible for its own
 closing. ( I will get that scene out of there )   * Lookin' good!

---
 OpenSim/Framework/General/ClientManager.cs         |  38 ++++-
 OpenSim/Framework/General/Interfaces/IClientAPI.cs |   9 +
 OpenSim/Framework/General/NullClientAPI.cs         | 183 ---------------------
 OpenSim/Region/ClientStack/ClientView.API.cs       |   4 +-
 .../ClientStack/ClientView.PacketHandlers.cs       |  17 +-
 .../Region/ClientStack/ClientView.PacketQueue.cs   |  12 +-
 OpenSim/Region/ClientStack/ClientView.cs           |  14 +-
 OpenSim/Region/ClientStack/PacketServer.cs         |  41 +++--
 OpenSim/Region/ClientStack/UDPServer.cs            |  16 +-
 .../Region/Examples/SimpleApp/MyNpcCharacter.cs    |  17 ++
 10 files changed, 120 insertions(+), 231 deletions(-)
 delete mode 100644 OpenSim/Framework/General/NullClientAPI.cs

diff --git a/OpenSim/Framework/General/ClientManager.cs b/OpenSim/Framework/General/ClientManager.cs
index 274a2d3..b032849 100644
--- a/OpenSim/Framework/General/ClientManager.cs
+++ b/OpenSim/Framework/General/ClientManager.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Text;
 using libsecondlife.Packets;
 using OpenSim.Framework.Interfaces;
+using libsecondlife;
 
 namespace OpenSim.Framework
 {
@@ -24,7 +25,7 @@ namespace OpenSim.Framework
             m_clients = new Dictionary<uint, IClientAPI>();
         }
 
-        public void Remove(uint id)
+        private void Remove(uint id)
         {
             m_clients.Remove(id);
         }
@@ -44,19 +45,46 @@ namespace OpenSim.Framework
             }
         }
 
-        public void ConnectionClosed(uint circuitCode)
+        public void CloseAllAgents(uint circuitCode)
         {
             IClientAPI client;
 
             if (m_clients.TryGetValue(circuitCode, out client))
             {
-                m_clients.Remove(circuitCode);
-                client.Close();
+                CloseAllCircuits(client.AgentId);
+            }
+        }
+
+        public void CloseAllCircuits( LLUUID agentId )
+        {
+            uint[] circuits = GetAllCircuits(agentId);
+            foreach (uint circuit in circuits )
+            {
+                IClientAPI client;
+                if (m_clients.TryGetValue(circuit, out client))
+                {
+                    Remove(circuit);
+                    client.Close();
+                }
+            }            
+        }
+
+        private uint[] GetAllCircuits(LLUUID agentId)
+        {
+            List<uint> circuits = new List<uint>();
 
-                // TODO: Now remove all local childagents too
+            foreach (KeyValuePair<uint, IClientAPI> pair in m_clients)
+            {
+                if( pair.Value.AgentId == agentId )
+                {
+                    circuits.Add( pair.Key );
+                }
             }
+
+            return circuits.ToArray();
         }
 
+      
         public void ViewerEffectHandler(IClientAPI sender, ViewerEffectPacket.EffectBlock[] effectBlock)
         {
             ViewerEffectPacket packet = new ViewerEffectPacket();
diff --git a/OpenSim/Framework/General/Interfaces/IClientAPI.cs b/OpenSim/Framework/General/Interfaces/IClientAPI.cs
index 9c0771f..5fd5adf 100644
--- a/OpenSim/Framework/General/Interfaces/IClientAPI.cs
+++ b/OpenSim/Framework/General/Interfaces/IClientAPI.cs
@@ -25,6 +25,7 @@
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */
+using System;
 using System.Collections.Generic;
 using System.Net;
 using libsecondlife;
@@ -192,6 +193,12 @@ namespace OpenSim.Framework.Interfaces
             get;
         }
 
+        uint CircuitCode
+        {
+            get;
+            set;
+        }
+
         void OutPacket(Packet newPack);
         void SendWearables(AvatarWearable[] wearables);
         void SendAppearance(LLUUID agentID, byte[] visualParams, byte[] textureEntry);
@@ -245,5 +252,7 @@ namespace OpenSim.Framework.Interfaces
         void InPacket(Packet NewPack);
         void Close();
         event ViewerEffectEventHandler OnViewerEffect;
+        event Action<IClientAPI> OnLogout;
+        event Action<IClientAPI> OnConnectionClosed;
     }
 }
diff --git a/OpenSim/Framework/General/NullClientAPI.cs b/OpenSim/Framework/General/NullClientAPI.cs
deleted file mode 100644
index 2fe46d6..0000000
--- a/OpenSim/Framework/General/NullClientAPI.cs
+++ /dev/null
@@ -1,183 +0,0 @@
-using System.Collections.Generic;
-using System.Net;
-using OpenSim.Framework.Interfaces;
-using OpenSim.Framework.Types;
-using OpenSim.Framework.Data;
-using libsecondlife;
-using libsecondlife.Packets;
-
-
-namespace OpenSim.Framework
-{
-   public  class NullClientAPI : IClientAPI
-   {
-#pragma warning disable 67
-       public event ImprovedInstantMessage OnInstantMessage;
-       public event ChatFromViewer OnChatFromViewer;
-       public event RezObject OnRezObject;
-       public event ModifyTerrain OnModifyTerrain;
-       public event SetAppearance OnSetAppearance;
-       public event StartAnim OnStartAnim;
-       public event LinkObjects OnLinkObjects;
-       public event RequestMapBlocks OnRequestMapBlocks;
-       public event TeleportLocationRequest OnTeleportLocationRequest;
-       public event DisconnectUser OnDisconnectUser;
-       public event RequestAvatarProperties OnRequestAvatarProperties;
-
-       public event GenericCall4 OnDeRezObject;
-       public event GenericCall OnRegionHandShakeReply;
-       public event GenericCall OnRequestWearables;
-       public event GenericCall2 OnCompleteMovementToRegion;
-       public event UpdateAgent OnAgentUpdate;
-       public event GenericCall OnRequestAvatarsData;
-       public event AddNewPrim OnAddPrim;
-       public event ObjectDuplicate OnObjectDuplicate;
-       public event UpdateVector OnGrabObject;
-       public event ObjectSelect OnDeGrabObject;
-       public event MoveObject OnGrabUpdate;
-
-       public event UpdateShape OnUpdatePrimShape;
-       public event ObjectExtraParams OnUpdateExtraParams;
-       public event ObjectSelect OnObjectSelect;
-       public event GenericCall7 OnObjectDescription;
-       public event GenericCall7 OnObjectName;
-       public event UpdatePrimFlags OnUpdatePrimFlags;
-       public event UpdatePrimTexture OnUpdatePrimTexture;
-       public event UpdateVector OnUpdatePrimGroupPosition;
-       public event UpdateVector OnUpdatePrimSinglePosition;
-       public event UpdatePrimRotation OnUpdatePrimGroupRotation;
-       public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation;
-       public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation;
-       public event UpdateVector OnUpdatePrimScale;
-       public event StatusChange OnChildAgentStatus;
-       public event GenericCall2 OnStopMovement;
-       public event GenericCall6 OnRemoveAvatar;
-       public event ViewerEffectEventHandler OnViewerEffect;
-
-       public event CreateNewInventoryItem OnCreateNewInventoryItem;
-       public event CreateInventoryFolder OnCreateNewInventoryFolder;
-       public event FetchInventoryDescendents OnFetchInventoryDescendents;
-       public event FetchInventory OnFetchInventory;
-       public event RequestTaskInventory OnRequestTaskInventory;
-       public event UpdateInventoryItemTransaction OnUpdateInventoryItem;
-       public event UDPAssetUploadRequest OnAssetUploadRequest;
-       public event XferReceive OnXferReceive;
-       public event RequestXfer OnRequestXfer;
-       public event ConfirmXfer OnConfirmXfer;
-       public event RezScript OnRezScript;
-       public event UpdateTaskInventory OnUpdateTaskInventory;
-       public event RemoveTaskInventory OnRemoveTaskItem;
-
-       public event UUIDNameRequest OnNameFromUUIDRequest;
-
-       public event ParcelPropertiesRequest OnParcelPropertiesRequest;
-       public event ParcelDivideRequest OnParcelDivideRequest;
-       public event ParcelJoinRequest OnParcelJoinRequest;
-       public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
-       public event ParcelSelectObjects OnParcelSelectObjects;
-       public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest;
-       public event ObjectDeselect OnObjectDeselect;
-
-
-       public event EstateOwnerMessageRequest OnEstateOwnerMessage;
-#pragma warning restore 67
-
-       private LLUUID m_uuid = LLUUID.Random();
-       public virtual LLVector3 StartPos
-       {
-           get { return new LLVector3(); }
-           set {  }
-       }
-
-       public virtual LLUUID AgentId
-       {
-           get { return m_uuid; }
-       }
-
-       public LLUUID SessionId
-       {
-           get { return LLUUID.Zero; }
-       }
-
-       public virtual string FirstName
-       {
-           get { return ""; }
-       }
-
-       public virtual string LastName
-       {
-           get { return ""; }
-       }
-
-       public NullClientAPI()
-       {
-       }
-
-       public virtual void OutPacket(Packet newPack){}
-       public virtual void SendWearables(AvatarWearable[] wearables){}
-       public virtual void SendAppearance(LLUUID agentID, byte[] visualParams, byte[] textureEntry) { }
-       public virtual void SendStartPingCheck(byte seq){}
-       public virtual void SendKillObject(ulong regionHandle, uint localID){}
-       public virtual void SendAnimation(LLUUID animID, int seq, LLUUID sourceAgentId){}
-       public virtual void SendRegionHandshake(RegionInfo regionInfo){}
-       public virtual void SendChatMessage(string message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID) { }
-       public virtual void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID){}
-       public virtual void SendInstantMessage(LLUUID fromAgent, LLUUID fromAgentSession, string message, LLUUID toAgent, LLUUID imSessionID, string fromName, byte dialog, uint timeStamp){}
-       public virtual void SendLayerData(float[] map){}
-       public virtual void SendLayerData(int px, int py, float[] map){}
-       public virtual void MoveAgentIntoRegion(RegionInfo regInfo, LLVector3 pos, LLVector3 look){}
-       public virtual void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourExternalEndPoint){}
-       public virtual AgentCircuitData RequestClientInfo() { return new AgentCircuitData(); }
-       public virtual void CrossRegion(ulong newRegionHandle, LLVector3 pos, LLVector3 lookAt, IPEndPoint newRegionExternalEndPoint, string capsURL){}
-       public virtual void SendMapBlock(List<MapBlockData> mapBlocks){}
-       public virtual void SendLocalTeleport(LLVector3 position, LLVector3 lookAt, uint flags){}
-       public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, uint locationID, uint flags, string capsURL){}
-       public virtual void SendTeleportCancel(){}
-       public virtual void SendTeleportLocationStart(){}
-       public virtual void SendMoneyBalance(LLUUID transaction, bool success, byte[] description, int balance){}
-
-       public virtual void SendAvatarData(ulong regionHandle, string firstName, string lastName, LLUUID avatarID, uint avatarLocalID, LLVector3 Pos, byte[] textureEntry){}
-       public virtual void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, LLVector3 velocity, LLQuaternion rotation){}
-       public virtual void SendCoarseLocationUpdate(List<LLVector3> CoarseLocations) { }
-
-       public virtual void AttachObject(uint localID, LLQuaternion rotation, byte attachPoint){}
-       public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, LLVector3 pos, uint flags, LLUUID objectID, LLUUID ownerID, string text, uint parentID, byte[] particleSystem, LLQuaternion rotation){}
-       public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, LLQuaternion rotation){}
-
-       public virtual void SendInventoryFolderDetails(LLUUID ownerID, LLUUID folderID, List<InventoryItemBase> items){}
-       public virtual void SendInventoryItemDetails(LLUUID ownerID, InventoryItemBase item){}
-       public virtual void SendInventoryItemUpdate(InventoryItemBase Item) { }
-       public virtual void SendRemoveInventoryItem(LLUUID itemID) { }
-       public virtual void SendTaskInventory(LLUUID taskID, short serial, byte[] fileName) { }
-       public virtual void SendXferPacket(ulong xferID, uint packet, byte[] data) { }
-
-       public virtual void SendPreLoadSound(LLUUID objectID, LLUUID ownerID, LLUUID soundID) { }
-       public virtual void SendPlayAttachedSound(LLUUID soundID, LLUUID objectID, LLUUID ownerID, float gain, byte flags) { }
-
-       public virtual void SendNameReply(LLUUID profileId, string firstname, string lastname){}
-       public void SendAlertMessage(string message) { }
-       public void SendAgentAlertMessage(string message, bool modal) { }
-       public void SendLoadURL(string objectname, LLUUID objectID, LLUUID ownerID, bool groupOwned, string message, string url) { }
-
-
-       public bool AddMoney(int debit)
-       {
-            return false;
-       }
-
-       public void SendViewerTime(int phase) { }
-       public void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember, string flAbout, uint flags, LLUUID flImageID, LLUUID imageID, string profileURL, LLUUID partnerID) { }
-       public void SetDebug(int newDebug) { }
-
-       public void InPacket(Packet NewPack)
-       {
-       }
-
-       public void Close()
-       {
-       }
-
-
-   }
-}
-
diff --git a/OpenSim/Region/ClientStack/ClientView.API.cs b/OpenSim/Region/ClientStack/ClientView.API.cs
index a15a964..253807c 100644
--- a/OpenSim/Region/ClientStack/ClientView.API.cs
+++ b/OpenSim/Region/ClientStack/ClientView.API.cs
@@ -42,6 +42,8 @@ namespace OpenSim.Region.ClientStack
 {
     partial class ClientView
     {
+        public event Action<IClientAPI> OnLogout;
+        public event Action<IClientAPI> OnConnectionClosed;
         public event ViewerEffectEventHandler OnViewerEffect;
         public event ImprovedInstantMessage OnInstantMessage;
         public event ChatFromViewer OnChatFromViewer;
@@ -373,7 +375,7 @@ namespace OpenSim.Region.ClientStack
             agentData.AgentID = this.AgentId;
             agentData.SessionID = this.m_sessionId;
             agentData.SecureSessionID = this.SecureSessionID;
-            agentData.circuitcode = this.CircuitCode;
+            agentData.circuitcode = this.m_circuitCode;
             agentData.child = false;
             agentData.firstname = this.firstName;
             agentData.lastname = this.lastName;
diff --git a/OpenSim/Region/ClientStack/ClientView.PacketHandlers.cs b/OpenSim/Region/ClientStack/ClientView.PacketHandlers.cs
index 65ad431..643b158 100644
--- a/OpenSim/Region/ClientStack/ClientView.PacketHandlers.cs
+++ b/OpenSim/Region/ClientStack/ClientView.PacketHandlers.cs
@@ -56,19 +56,12 @@ namespace OpenSim.Region.ClientStack
 
         protected virtual bool Logout(IClientAPI client, Packet packet)
         {
-            // TODO: Refactor out this into an OnLogout so the ClientManager can close all clients.
-
             MainLog.Instance.Verbose("OpenSimClient.cs:ProcessInPacket() - Got a logout request");
-            //send reply to let the client logout
-            LogoutReplyPacket logReply = new LogoutReplyPacket();
-            logReply.AgentData.AgentID = this.AgentId;
-            logReply.AgentData.SessionID = this.m_sessionId;
-            logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
-            logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
-            logReply.InventoryData[0].ItemID = LLUUID.Zero;
-            OutPacket(logReply);
-            //
-            this.Close();
+
+            if( OnLogout != null )
+            {
+                OnLogout(client);
+            }
 
             return true;
         }
diff --git a/OpenSim/Region/ClientStack/ClientView.PacketQueue.cs b/OpenSim/Region/ClientStack/ClientView.PacketQueue.cs
index 05c2869..bfcb19f 100644
--- a/OpenSim/Region/ClientStack/ClientView.PacketQueue.cs
+++ b/OpenSim/Region/ClientStack/ClientView.PacketQueue.cs
@@ -51,11 +51,17 @@ namespace OpenSim.Region.ClientStack
         protected const int RESEND_TIMEOUT = 4000;
         protected const int MAX_SEQUENCE = 0xFFFFFF;
 
-        public uint CircuitCode;
+        private uint m_circuitCode;
         public EndPoint userEP;
 
         protected PacketServer m_networkServer;
 
+        public uint CircuitCode
+        {
+            get { return m_circuitCode; }
+            set { m_circuitCode = value; }
+        }
+
         protected virtual void ProcessOutPacket(Packet Pack)
         {
             // Keep track of when this packet was sent out
@@ -142,11 +148,11 @@ namespace OpenSim.Region.ClientStack
                 if (Pack.Header.Zerocoded)
                 {
                     int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer);
-                    m_networkServer.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, CircuitCode);//userEP);
+                    m_networkServer.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, m_circuitCode);//userEP);
                 }
                 else
                 {
-                    m_networkServer.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, CircuitCode); //userEP);
+                    m_networkServer.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, m_circuitCode); //userEP);
                 }
             }
             catch (Exception)
diff --git a/OpenSim/Region/ClientStack/ClientView.cs b/OpenSim/Region/ClientStack/ClientView.cs
index f8ac1d8..2341b7b 100644
--- a/OpenSim/Region/ClientStack/ClientView.cs
+++ b/OpenSim/Region/ClientStack/ClientView.cs
@@ -133,8 +133,6 @@ namespace OpenSim.Region.ClientStack
 
             m_scene.RemoveClient(this.AgentId);
 
-            m_clientManager.Remove(this.CircuitCode); // TODO: Move out and delete ref to clientmanager.
-            m_networkServer.RemoveClientCircuit(this.CircuitCode);
             this.ClientThread.Abort();
         }
 
@@ -215,7 +213,7 @@ namespace OpenSim.Region.ClientStack
                 } else {
                     info = packet.Type.ToString();
                 }
-                Console.WriteLine(CircuitCode + ":" + direction + ": " + info);
+                Console.WriteLine(m_circuitCode + ":" + direction + ": " + info);
             }
         }
 
@@ -252,8 +250,10 @@ namespace OpenSim.Region.ClientStack
                 probesWithNoIngressPackets++;
                 if (probesWithNoIngressPackets > 30)
                 {
-                    // Refactor out this into an OnConnectionClosed so the ClientManager can clean up
-                    this.Close();
+                    if( OnConnectionClosed != null )
+                    {
+                        OnConnectionClosed(this);
+                    }
                 }
                 else
                 {
@@ -283,7 +283,7 @@ namespace OpenSim.Region.ClientStack
 
         protected virtual void AuthUser()
         {
-            // AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(cirpack.CircuitCode.m_sessionId, cirpack.CircuitCode.ID, cirpack.CircuitCode.Code);
+            // AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(cirpack.m_circuitCode.m_sessionId, cirpack.m_circuitCode.ID, cirpack.m_circuitCode.Code);
             AuthenticateResponse sessionInfo = this.m_authenticateSessionsHandler.AuthenticateSession(cirpack.CircuitCode.SessionID, cirpack.CircuitCode.ID, cirpack.CircuitCode.Code);
             if (!sessionInfo.Authorised)
             {
@@ -297,7 +297,7 @@ namespace OpenSim.Region.ClientStack
                 //session is authorised
                 m_agentId = cirpack.CircuitCode.ID;
                 this.m_sessionId = cirpack.CircuitCode.SessionID;
-                this.CircuitCode = cirpack.CircuitCode.Code;
+                this.m_circuitCode = cirpack.CircuitCode.Code;
                 this.firstName = sessionInfo.LoginInfo.First;
                 this.lastName = sessionInfo.LoginInfo.Last;
 
diff --git a/OpenSim/Region/ClientStack/PacketServer.cs b/OpenSim/Region/ClientStack/PacketServer.cs
index bceeeb3..28f25bd 100644
--- a/OpenSim/Region/ClientStack/PacketServer.cs
+++ b/OpenSim/Region/ClientStack/PacketServer.cs
@@ -33,14 +33,15 @@ using OpenSim.Framework;
 using OpenSim.Framework.Types;
 using OpenSim.Framework.Interfaces;
 using OpenSim.Framework.Communications.Caches;
+using libsecondlife;
 
 namespace OpenSim.Region.ClientStack
 {
     public class PacketServer
     {
-        private ClientStackNetworkHandler _networkHandler;
+        private ClientStackNetworkHandler m_networkHandler;
         private IScene _localScene;
-        private ClientManager m_clientManager = new ClientManager();
+        private readonly ClientManager m_clientManager = new ClientManager();
         public ClientManager ClientManager
         {
             get { return m_clientManager; }
@@ -48,8 +49,8 @@ namespace OpenSim.Region.ClientStack
 
         public PacketServer(ClientStackNetworkHandler networkHandler)
         {
-            _networkHandler = networkHandler;
-            _networkHandler.RegisterPacketServer(this);
+            m_networkHandler = networkHandler;
+            m_networkHandler.RegisterPacketServer(this);
         }
 
         public IScene LocalScene
@@ -70,11 +71,6 @@ namespace OpenSim.Region.ClientStack
             m_clientManager.InPacket(circuitCode, packet);
         }
 
-        public virtual void ConnectionClosed(uint circuitCode)
-        {
-            m_clientManager.ConnectionClosed(circuitCode);
-        }
-
         /// <summary>
         /// 
         /// </summary>
@@ -145,10 +141,24 @@ namespace OpenSim.Region.ClientStack
             this.m_clientManager.Add(useCircuit.CircuitCode.Code, newuser);
 
             newuser.OnViewerEffect += m_clientManager.ViewerEffectHandler;
+            newuser.OnLogout += LogoutHandler;
+            newuser.OnConnectionClosed += CloseClient;
 
             return true;
         }
 
+        public void LogoutHandler(IClientAPI client)
+        {
+            LogoutReplyPacket logReply = new LogoutReplyPacket();
+            logReply.AgentData.AgentID = client.AgentId;
+            logReply.AgentData.SessionID = client.SessionId;
+            logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
+            logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
+            logReply.InventoryData[0].ItemID = LLUUID.Zero;
+            client.OutPacket(logReply);
+
+            CloseClient( client );
+        }
 
 
         /// <summary>
@@ -160,17 +170,22 @@ namespace OpenSim.Region.ClientStack
         /// <param name="circuitcode"></param>
         public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
         {
-            this._networkHandler.SendPacketTo(buffer, size, flags, circuitcode);
+            this.m_networkHandler.SendPacketTo(buffer, size, flags, circuitcode);
         }
 
         /// <summary>
         /// 
         /// </summary>
         /// <param name="circuitcode"></param>
-        public virtual void RemoveClientCircuit(uint circuitcode)
+        public virtual void CloseCircuit(uint circuitcode)
+        {
+            m_networkHandler.RemoveClientCircuit( circuitcode );
+            m_clientManager.CloseAllAgents( circuitcode );
+        }
+
+        public virtual void CloseClient( IClientAPI client )
         {
-            this._networkHandler.RemoveClientCircuit(circuitcode);
-            this.m_clientManager.Remove(circuitcode);
+            CloseCircuit( client.CircuitCode );
         }
     }
 }
diff --git a/OpenSim/Region/ClientStack/UDPServer.cs b/OpenSim/Region/ClientStack/UDPServer.cs
index efc9c87..b0b529c 100644
--- a/OpenSim/Region/ClientStack/UDPServer.cs
+++ b/OpenSim/Region/ClientStack/UDPServer.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.ClientStack
         protected IPEndPoint ipeSender;
         protected EndPoint epSender;
         protected AsyncCallback ReceivedData;
-        protected PacketServer _packetServer;
+        protected PacketServer m_packetServer;
 
         protected int listenPort;
         protected IScene m_localScene;
@@ -61,11 +61,11 @@ namespace OpenSim.Region.ClientStack
         {
             get
             {
-                return _packetServer;
+                return m_packetServer;
             }
             set
             {
-                _packetServer = value;
+                m_packetServer = value;
             }
         }
 
@@ -74,7 +74,7 @@ namespace OpenSim.Region.ClientStack
             set
             {
                 this.m_localScene = value;
-                this._packetServer.LocalScene = this.m_localScene;
+                this.m_packetServer.LocalScene = this.m_localScene;
             }
         }
 
@@ -111,7 +111,9 @@ namespace OpenSim.Region.ClientStack
             catch (System.Net.Sockets.SocketException)
             {
                 Console.WriteLine("Remote host Closed connection");
-                this._packetServer.ConnectionClosed(this.clientCircuits[epSender]);
+                
+                this.m_packetServer.CloseCircuit(this.clientCircuits[epSender]);
+
                 ipeSender = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
                 epSender = (EndPoint)ipeSender;
                 Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
@@ -126,7 +128,7 @@ namespace OpenSim.Region.ClientStack
             if (this.clientCircuits.ContainsKey(epSender))
             {
                 //if so then send packet to the packetserver
-                this._packetServer.InPacket(this.clientCircuits[epSender], packet);
+                this.m_packetServer.InPacket(this.clientCircuits[epSender], packet);
             }
             else if (packet.Type == PacketType.UseCircuitCode)
             {
@@ -170,7 +172,7 @@ namespace OpenSim.Region.ClientStack
 
         public virtual void RegisterPacketServer(PacketServer server)
         {
-            this._packetServer = server;
+            this.m_packetServer = server;
         }
 
         public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)//EndPoint packetSender)
diff --git a/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs
index a055339..9839b0c 100644
--- a/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs
@@ -232,5 +232,22 @@ namespace SimpleApp
         public void Close()
         {
         }
+     
+        private uint m_circuitCode;
+        public uint CircuitCode
+        {
+            get
+            {
+                return m_circuitCode;
+            }
+            set
+            {
+                m_circuitCode = value;
+            }
+        }
+
+        public event System.Action<IClientAPI> OnLogout;
+
+        public event System.Action<IClientAPI> OnConnectionClosed;
     }
 }
-- 
cgit v1.1