From 279e0061c515ee0a03036bef68eea9738273d785 Mon Sep 17 00:00:00 2001 From: Johan Berntsson Date: Tue, 4 Mar 2008 05:31:54 +0000 Subject: Merged 3Di code that provides scene and avatar serialization, and plugin support for region move/split/merge. See ThirdParty/3Di/README.txt. Unless the new modules are used there should be no noticeable changes when running OpenSim. --- OpenSim/Region/ClientStack/ClientView.cs | 145 ++++++++++++++++++++- OpenSim/Region/ClientStack/PacketQueue.cs | 12 +- OpenSim/Region/ClientStack/PacketServer.cs | 8 +- .../Region/ClientStack/RegionApplicationBase.cs | 11 +- OpenSim/Region/ClientStack/UDPServer.cs | 92 +++++++++++-- 5 files changed, 248 insertions(+), 20 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/ClientView.cs b/OpenSim/Region/ClientStack/ClientView.cs index b719086..b5cd6fb 100644 --- a/OpenSim/Region/ClientStack/ClientView.cs +++ b/OpenSim/Region/ClientStack/ClientView.cs @@ -61,6 +61,8 @@ namespace OpenSim.Region.ClientStack /* static variables */ public static TerrainManager TerrainManager; + public delegate bool SynchronizeClientHandler(IScene scene, Packet packet, LLUUID agentID, ThrottleOutPacketType throttlePacketType); + public static SynchronizeClientHandler SynchronizeClient = null; /* private variables */ private readonly LLUUID m_sessionId; private LLUUID m_secureSessionId = LLUUID.Zero; @@ -118,6 +120,7 @@ namespace OpenSim.Region.ClientStack protected Thread m_clientThread; protected LLVector3 m_startpos; protected EndPoint m_userEndPoint; + protected EndPoint m_proxyEndPoint; /* Instantiated Designated Event Delegates */ //- used so we don't create new objects for each incoming packet and then toss it out later */ @@ -291,7 +294,7 @@ namespace OpenSim.Region.ClientStack /* METHODS */ public ClientView(EndPoint remoteEP, IScene scene, AssetCache assetCache, PacketServer packServer, - AgentCircuitManager authenSessions, LLUUID agentId, LLUUID sessionId, uint circuitCode) + AgentCircuitManager authenSessions, LLUUID agentId, LLUUID sessionId, uint circuitCode, EndPoint proxyEP) { m_moneyBalance = 1000; @@ -311,6 +314,7 @@ namespace OpenSim.Region.ClientStack m_circuitCode = circuitCode; m_userEndPoint = remoteEP; + m_proxyEndPoint = proxyEP; m_startpos = m_authenticateSessionsHandler.GetPosition(circuitCode); @@ -411,7 +415,37 @@ namespace OpenSim.Region.ClientStack public void Stop() { - m_log.Info("[BUG]: Stop called, please find out where and remove it"); + // Shut down timers + m_ackTimer.Stop(); + m_clientPingTimer.Stop(); + } + + public void Restart() + { + // re-construct + m_pendingAcks = new Dictionary(); + m_needAck = new Dictionary(); + m_sequence += 1000000; + + m_ackTimer = new Timer(750); + m_ackTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed); + m_ackTimer.Start(); + + m_clientPingTimer = new Timer(5000); + m_clientPingTimer.Elapsed += new ElapsedEventHandler(CheckClientConnectivity); + m_clientPingTimer.Enabled = true; + } + + public void Terminate() + { + // disable blocking queue + m_packetQueue.Enqueue(null); + + // wait for thread stoped + m_clientThread.Join(); + + // delete circuit code + m_networkServer.CloseClient(this); } #endregion @@ -507,6 +541,10 @@ namespace OpenSim.Region.ClientStack while (true) { QueItem nextPacket = m_packetQueue.Dequeue(); + if (nextPacket == null) + { + break; + } if (nextPacket.Incoming) { if (nextPacket.Packet.Type != PacketType.AgentUpdate) @@ -2642,7 +2680,7 @@ namespace OpenSim.Region.ClientStack try { byte[] sendbuffer = Pack.ToBytes(); - PacketPool.Instance.ReturnPacket(Pack); + PacketPool.Instance.ReturnPacket(Pack); if (Pack.Header.Zerocoded) { @@ -2651,8 +2689,11 @@ namespace OpenSim.Region.ClientStack } else { - m_networkServer.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, m_circuitCode); + //Need some extra space in case we need to add proxy information to the message later + Buffer.BlockCopy(sendbuffer, 0, ZeroOutBuffer, 0, sendbuffer.Length); + m_networkServer.SendPacketTo(ZeroOutBuffer, sendbuffer.Length, SocketFlags.None, m_circuitCode); } + } catch (Exception e) { @@ -2666,6 +2707,12 @@ namespace OpenSim.Region.ClientStack public virtual void InPacket(Packet NewPack) { + if(!m_packetProcessingEnabled && NewPack.Type != PacketType.LogoutRequest) + { + PacketPool.Instance.ReturnPacket(NewPack); + return; + } + // Handle appended ACKs if (NewPack != null) { @@ -2726,6 +2773,15 @@ namespace OpenSim.Region.ClientStack public virtual void OutPacket(Packet NewPack, ThrottleOutPacketType throttlePacketType) { + if ((SynchronizeClient != null) && (!PacketProcessingEnabled)) + { + // Sending packet to active client's server. + if (SynchronizeClient(m_scene, NewPack, m_agentId, throttlePacketType)) + { + return; + } + } + QueItem item = new QueItem(); item.Packet = NewPack; item.Incoming = false; @@ -2853,6 +2909,13 @@ namespace OpenSim.Region.ClientStack } } + private bool m_packetProcessingEnabled = true; + + public bool PacketProcessingEnabled { + get { return m_packetProcessingEnabled; } + set { m_packetProcessingEnabled = value; } + } + protected void ProcessInPacket(Packet Pack) { ack_pack(Pack); @@ -4373,5 +4436,79 @@ namespace OpenSim.Region.ClientStack OutPacket(logReply, ThrottleOutPacketType.Task); } + + public ClientInfo GetClientInfo() + { + //MainLog.Instance.Verbose("CLIENT", "GetClientInfo BGN"); + + ClientInfo info = new ClientInfo(); + info.userEP = this.m_userEndPoint; + info.proxyEP = this.m_proxyEndPoint; + info.agentcircuit = new sAgentCircuitData(RequestClientInfo()); + + info.pendingAcks = m_pendingAcks; + + info.needAck = new Dictionary(); + + lock (m_needAck) + { + foreach (uint key in m_needAck.Keys) + { + info.needAck.Add(key, m_needAck[key].ToBytes()); + } + } + +/* pending + QueItem[] queitems = m_packetQueue.GetQueueArray(); + + MainLog.Instance.Verbose("CLIENT", "Queue Count : [{0}]", queitems.Length); + + for (int i = 0; i < queitems.Length; i++) + { + if (queitems[i].Incoming == false) + { + info.out_packets.Add(queitems[i].Packet.ToBytes()); + MainLog.Instance.Verbose("CLIENT", "Add OutPacket [{0}]", queitems[i].Packet.Type.ToString()); + } + } +*/ + + info.sequence = m_sequence; + + //MainLog.Instance.Verbose("CLIENT", "GetClientInfo END"); + + return info; + } + + public void SetClientInfo(ClientInfo info) + { + m_pendingAcks = info.pendingAcks; + + m_needAck = new Dictionary(); + + Packet packet = null; + int packetEnd = 0; + byte[] zero = new byte[3000]; + + foreach (uint key in info.needAck.Keys) + { + byte[] buff = info.needAck[key]; + + packetEnd = buff.Length - 1; + + try + { + packet = PacketPool.Instance.GetPacket(buff, ref packetEnd, zero); + } + catch (Exception) + { + //MainLog.Instance.Debug("UDPSERVER", e.ToString()); + } + + m_needAck.Add(key, packet); + } + + m_sequence = info.sequence; + } } } diff --git a/OpenSim/Region/ClientStack/PacketQueue.cs b/OpenSim/Region/ClientStack/PacketQueue.cs index a04828f..82f96e8 100644 --- a/OpenSim/Region/ClientStack/PacketQueue.cs +++ b/OpenSim/Region/ClientStack/PacketQueue.cs @@ -142,8 +142,13 @@ namespace OpenSim.Region.ClientStack // We could micro lock, but that will tend to actually // probably be worse than just synchronizing on SendQueue - lock (this) + if (item == null) { + SendQueue.Enqueue(item); + return; + } + + lock (this) { switch (item.throttleType) { case ThrottleOutPacketType.Resend: @@ -518,5 +523,10 @@ namespace OpenSim.Region.ClientStack TextureOutgoingPacketQueue.Count, AssetOutgoingPacketQueue.Count); } + + public QueItem[] GetQueueArray() + { + return SendQueue.GetQueueArray(); + } } } diff --git a/OpenSim/Region/ClientStack/PacketServer.cs b/OpenSim/Region/ClientStack/PacketServer.cs index 250b90a..02ae79b 100644 --- a/OpenSim/Region/ClientStack/PacketServer.cs +++ b/OpenSim/Region/ClientStack/PacketServer.cs @@ -74,14 +74,14 @@ namespace OpenSim.Region.ClientStack protected virtual IClientAPI CreateNewClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, ClientManager clientManager, IScene scene, AssetCache assetCache, PacketServer packServer, AgentCircuitManager authenSessions, - LLUUID agentId, LLUUID sessionId, uint circuitCode) + LLUUID agentId, LLUUID sessionId, uint circuitCode, EndPoint proxyEP) { return - new ClientView(remoteEP, scene, assetCache, packServer, authenSessions, agentId, sessionId, circuitCode); + new ClientView(remoteEP, scene, assetCache, packServer, authenSessions, agentId, sessionId, circuitCode, proxyEP); } public virtual bool AddNewClient(EndPoint epSender, UseCircuitCodePacket useCircuit, AssetCache assetCache, - AgentCircuitManager authenticateSessionsClass) + AgentCircuitManager authenticateSessionsClass, EndPoint proxyEP) { IClientAPI newuser; @@ -93,7 +93,7 @@ namespace OpenSim.Region.ClientStack { newuser = CreateNewClient(epSender, useCircuit, m_scene.ClientManager, m_scene, assetCache, this, authenticateSessionsClass, useCircuit.CircuitCode.ID, - useCircuit.CircuitCode.SessionID, useCircuit.CircuitCode.Code); + useCircuit.CircuitCode.SessionID, useCircuit.CircuitCode.Code, proxyEP); m_scene.ClientManager.Add(useCircuit.CircuitCode.Code, newuser); diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs index a760712..660c3b3 100644 --- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs +++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs @@ -104,13 +104,18 @@ namespace OpenSim.Region.ClientStack protected Scene SetupScene(RegionInfo regionInfo, out UDPServer udpServer, bool m_permissions) { + return SetupScene(regionInfo, 0, out udpServer, m_permissions); + } + + protected Scene SetupScene(RegionInfo regionInfo, int proxyOffset, out UDPServer udpServer, bool m_permissions) + { AgentCircuitManager circuitManager = new AgentCircuitManager(); IPAddress listenIP = regionInfo.InternalEndPoint.Address; //if (!IPAddress.TryParse(regionInfo.InternalEndPoint, out listenIP)) // listenIP = IPAddress.Parse("0.0.0.0"); uint port = (uint) regionInfo.InternalEndPoint.Port; - udpServer = new UDPServer(listenIP, ref port, regionInfo.m_allow_alternate_ports, m_assetCache, circuitManager); + udpServer = new UDPServer(listenIP, ref port, proxyOffset, regionInfo.m_allow_alternate_ports, m_assetCache, circuitManager); regionInfo.InternalEndPoint.Port = (int)port; Scene scene = CreateScene(regionInfo, m_storageManager, circuitManager); @@ -148,8 +153,8 @@ namespace OpenSim.Region.ClientStack scene.RegionInfo.MasterAvatarAssignedUUID = LLUUID.Zero; } - scene.LoadPrimsFromStorage(m_permissions); - scene.loadAllLandObjectsFromStorage(); + scene.LoadPrimsFromStorage(m_permissions, regionInfo.originRegionID); + scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID); scene.performParcelPrimCountUpdate(); scene.StartTimer(); return scene; diff --git a/OpenSim/Region/ClientStack/UDPServer.cs b/OpenSim/Region/ClientStack/UDPServer.cs index 9c572cf..5501d3f 100644 --- a/OpenSim/Region/ClientStack/UDPServer.cs +++ b/OpenSim/Region/ClientStack/UDPServer.cs @@ -43,12 +43,15 @@ namespace OpenSim.Region.ClientStack protected Dictionary clientCircuits = new Dictionary(); public Dictionary clientCircuits_reverse = new Dictionary(); + protected Dictionary proxyCircuits = new Dictionary(); public Socket Server; protected IPEndPoint ServerIncoming; protected byte[] RecvBuffer = new byte[4096]; protected byte[] ZeroBuffer = new byte[8192]; protected IPEndPoint ipeSender; protected EndPoint epSender; + protected EndPoint epProxy; + protected int proxyPortOffset; protected AsyncCallback ReceivedData; protected PacketServer m_packetServer; protected ulong m_regionHandle; @@ -85,10 +88,11 @@ namespace OpenSim.Region.ClientStack { } - public UDPServer(IPAddress _listenIP, ref uint port, bool allow_alternate_port, AssetCache assetCache, AgentCircuitManager authenticateClass) + public UDPServer(IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, AssetCache assetCache, AgentCircuitManager authenticateClass) { + this.proxyPortOffset = proxyPortOffset; + listenPort = (uint) (port + proxyPortOffset); listenIP = _listenIP; - listenPort = port; Allow_Alternate_Port = allow_alternate_port; m_assetCache = assetCache; m_authenticateSessionsClass = authenticateClass; @@ -97,7 +101,7 @@ namespace OpenSim.Region.ClientStack // Return new port // This because in Grid mode it is not really important what port the region listens to as long as it is correctly registered. // So the option allow_alternate_ports="true" was added to default.xml - port = listenPort; + port = (uint)(listenPort - proxyPortOffset); } protected virtual void CreatePacketServer() @@ -211,6 +215,13 @@ namespace OpenSim.Region.ClientStack //return; } + //System.Console.WriteLine("UDPServer : recieved message from {0}", epSender.ToString()); + epProxy = epSender; + if (proxyPortOffset != 0) + { + epSender = PacketPool.DecodeProxyMessage(RecvBuffer, ref numBytes); + } + int packetEnd = numBytes - 1; try @@ -318,6 +329,9 @@ namespace OpenSim.Region.ClientStack protected virtual void AddNewClient(Packet packet) { + //Slave regions don't accept new clients + if(m_localScene.Region_Status != RegionStatus.SlaveScene) + { UseCircuitCodePacket useCircuit = (UseCircuitCodePacket) packet; lock (clientCircuits) { @@ -334,7 +348,17 @@ namespace OpenSim.Region.ClientStack m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); } - PacketServer.AddNewClient(epSender, useCircuit, m_assetCache, m_authenticateSessionsClass); + lock (proxyCircuits) + { + if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code)) + proxyCircuits.Add(useCircuit.CircuitCode.Code, epProxy); + else + m_log.Error("[UDPSERVER]: proxyCircuits already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); + } + + PacketServer.AddNewClient(epSender, useCircuit, m_assetCache, m_authenticateSessionsClass, epProxy); + } + PacketPool.Instance.ReturnPacket(packet); } public void ServerListener() @@ -387,10 +411,20 @@ namespace OpenSim.Region.ClientStack lock (clientCircuits_reverse) { if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto)) - { - //we found the endpoint so send the packet to it - Server.SendTo(buffer, size, flags, sendto); - } + { + //we found the endpoint so send the packet to it + if (proxyPortOffset != 0) + { + //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo proxy " + proxyCircuits[circuitcode].ToString() + ": client " + sendto.ToString()); + PacketPool.EncodeProxyMessage(buffer, ref size, sendto); + Server.SendTo(buffer, size, flags, proxyCircuits[circuitcode]); + } + else + { + //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo : client " + sendto.ToString()); + Server.SendTo(buffer, size, flags, sendto); + } + } } } @@ -404,8 +438,50 @@ namespace OpenSim.Region.ClientStack clientCircuits.Remove(sendto); clientCircuits_reverse.Remove(circuitcode); + proxyCircuits.Remove(circuitcode); } } } + + public void RestoreClient(AgentCircuitData circuit, EndPoint userEP, EndPoint proxyEP) + { + //MainLog.Instance.Verbose("UDPSERVER", "RestoreClient"); + + UseCircuitCodePacket useCircuit = new UseCircuitCodePacket(); + useCircuit.CircuitCode.Code = circuit.circuitcode; + useCircuit.CircuitCode.ID = circuit.AgentID; + useCircuit.CircuitCode.SessionID = circuit.SessionID; + + lock (clientCircuits) + { + if (!clientCircuits.ContainsKey(userEP)) + clientCircuits.Add(userEP, useCircuit.CircuitCode.Code); + else + m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); + } + lock (clientCircuits_reverse) + { + if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code)) + clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, userEP); + else + m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); + } + + lock (proxyCircuits) + { + if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code)) + { + proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP); + } + else + { + // re-set proxy endpoint + proxyCircuits.Remove(useCircuit.CircuitCode.Code); + proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP); + } + } + + PacketServer.AddNewClient(userEP, useCircuit, m_assetCache, m_authenticateSessionsClass, proxyEP); + } } } -- cgit v1.1