* Rex merge, rest of clientstack. Clean merge.

afrisby-3
Adam Frisby 2008-02-23 03:30:43 +00:00
parent 726b7af464
commit 5745db2a35
4 changed files with 1256 additions and 1099 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,139 +1,151 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
*/ */
using System.Net;
using System.Net.Sockets; using System;
using libsecondlife; using System.Net;
using libsecondlife.Packets; using System.Net.Sockets;
using OpenSim.Framework; using libsecondlife;
using OpenSim.Framework.Communications.Cache; using libsecondlife.Packets;
using OpenSim.Framework;
namespace OpenSim.Region.ClientStack using OpenSim.Framework.Communications.Cache;
{
public class PacketServer namespace OpenSim.Region.ClientStack
{ {
private ClientStackNetworkHandler m_networkHandler; public class PacketServer
private IScene m_scene; {
//private static readonly log4net.ILog m_log
//private readonly ClientManager m_clientManager = new ClientManager(); // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
//public ClientManager ClientManager
//{ private ClientStackNetworkHandler m_networkHandler;
// get { return m_clientManager; } private IScene m_scene;
//}
//private readonly ClientManager m_clientManager = new ClientManager();
public PacketServer(ClientStackNetworkHandler networkHandler) //public ClientManager ClientManager
{ //{
m_networkHandler = networkHandler; // get { return m_clientManager; }
m_networkHandler.RegisterPacketServer(this); //}
}
public PacketServer(ClientStackNetworkHandler networkHandler)
public IScene LocalScene {
{ m_networkHandler = networkHandler;
set { m_scene = value; } m_networkHandler.RegisterPacketServer(this);
} }
/// <summary> public IScene LocalScene
/// {
/// </summary> set { m_scene = value; }
/// <param name="circuitCode"></param> }
/// <param name="packet"></param>
public virtual void InPacket(uint circuitCode, Packet packet) /// <summary>
{ ///
m_scene.ClientManager.InPacket(circuitCode, packet); /// </summary>
} /// <param name="circuitCode"></param>
/// <param name="packet"></param>
protected virtual IClientAPI CreateNewClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, public virtual void InPacket(uint circuitCode, Packet packet)
ClientManager clientManager, IScene scene, AssetCache assetCache, {
PacketServer packServer, AgentCircuitManager authenSessions, m_scene.ClientManager.InPacket(circuitCode, packet);
LLUUID agentId, LLUUID sessionId, uint circuitCode) }
{
return protected virtual IClientAPI CreateNewClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack,
new ClientView(remoteEP, scene, assetCache, packServer, authenSessions, agentId, sessionId, circuitCode); ClientManager clientManager, IScene scene, AssetCache assetCache,
} PacketServer packServer, AgentCircuitManager authenSessions,
LLUUID agentId, LLUUID sessionId, uint circuitCode)
public virtual bool AddNewClient(EndPoint epSender, UseCircuitCodePacket useCircuit, AssetCache assetCache, {
AgentCircuitManager authenticateSessionsClass) return
{ new ClientView(remoteEP, scene, assetCache, packServer, authenSessions, agentId, sessionId, circuitCode);
IClientAPI newuser; }
if (m_scene.ClientManager.TryGetClient(useCircuit.CircuitCode.Code, out newuser)) public virtual bool AddNewClient(EndPoint epSender, UseCircuitCodePacket useCircuit, AssetCache assetCache,
{ AgentCircuitManager authenticateSessionsClass)
return false; {
} IClientAPI newuser;
else
{ if (m_scene.ClientManager.TryGetClient(useCircuit.CircuitCode.Code, out newuser))
newuser = CreateNewClient(epSender, useCircuit, m_scene.ClientManager, m_scene, assetCache, this, {
authenticateSessionsClass, useCircuit.CircuitCode.ID, return false;
useCircuit.CircuitCode.SessionID, useCircuit.CircuitCode.Code); }
else
m_scene.ClientManager.Add(useCircuit.CircuitCode.Code, newuser); {
newuser = CreateNewClient(epSender, useCircuit, m_scene.ClientManager, m_scene, assetCache, this,
newuser.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler; authenticateSessionsClass, useCircuit.CircuitCode.ID,
newuser.OnLogout += LogoutHandler; useCircuit.CircuitCode.SessionID, useCircuit.CircuitCode.Code);
newuser.OnConnectionClosed += CloseClient;
m_scene.ClientManager.Add(useCircuit.CircuitCode.Code, newuser);
return true;
} newuser.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler;
} newuser.OnLogout += LogoutHandler;
newuser.OnConnectionClosed += CloseClient;
public void LogoutHandler(IClientAPI client)
{ return true;
client.SendLogoutPacket(); }
}
CloseClient(client);
} public void LogoutHandler(IClientAPI client)
{
/// <summary> client.SendLogoutPacket();
///
/// </summary> CloseClient(client);
/// <param name="buffer"></param> }
/// <param name="size"></param>
/// <param name="flags"></param> /// <summary>
/// <param name="circuitcode"></param> ///
public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode) /// </summary>
{ /// <param name="buffer"></param>
m_networkHandler.SendPacketTo(buffer, size, flags, circuitcode); /// <param name="size"></param>
} /// <param name="flags"></param>
/// <param name="circuitcode"></param>
/// <summary> public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
/// {
/// </summary> m_networkHandler.SendPacketTo(buffer, size, flags, circuitcode);
/// <param name="circuitcode"></param> }
public virtual void CloseCircuit(uint circuitcode)
{ /// <summary>
m_networkHandler.RemoveClientCircuit(circuitcode); ///
/// </summary>
//m_scene.ClientManager.CloseAllAgents(circuitcode); /// <param name="circuitcode"></param>
} public virtual void CloseCircuit(uint circuitcode)
{
public virtual void CloseClient(IClientAPI client) m_networkHandler.RemoveClientCircuit(circuitcode);
{
CloseCircuit(client.CircuitCode); //m_scene.ClientManager.CloseAllAgents(circuitcode);
client.Close(false); }
}
} /// <summary>
} /// Completely close down the given client.
/// </summary>
/// <param name="client"></param>
public virtual void CloseClient(IClientAPI client)
{
//m_log.Info("PacketServer:CloseClient()");
CloseCircuit(client.CircuitCode);
m_scene.ClientManager.Remove(client.CircuitCode);
client.Close(false);
}
}
}

View File

@ -1,160 +1,166 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using libsecondlife; using libsecondlife;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Communications; using OpenSim.Framework.Communications;
using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Communications.Cache;
using OpenSim.Framework.Console; using OpenSim.Framework.Console;
using OpenSim.Framework.Servers; using OpenSim.Framework.Servers;
using OpenSim.Region.Environment; using OpenSim.Region.Environment;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
using OpenSim.Region.Physics.Manager; using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Communications.VoiceChat; using OpenSim.Region.Communications.VoiceChat;
namespace OpenSim.Region.ClientStack namespace OpenSim.Region.ClientStack
{ {
public abstract class RegionApplicationBase public abstract class RegionApplicationBase : BaseOpenSimServer
{ {
protected AssetCache m_assetCache; private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
protected Dictionary<EndPoint, uint> m_clientCircuits = new Dictionary<EndPoint, uint>();
protected DateTime m_startuptime; protected AssetCache m_assetCache;
protected NetworkServersInfo m_networkServersInfo; protected Dictionary<EndPoint, uint> m_clientCircuits = new Dictionary<EndPoint, uint>();
protected NetworkServersInfo m_networkServersInfo;
protected BaseHttpServer m_httpServer;
protected uint m_httpServerPort; protected BaseHttpServer m_httpServer;
protected uint m_httpServerPort;
protected LogBase m_log;
protected CommunicationsManager m_commsManager; protected CommunicationsManager m_commsManager;
protected SceneManager m_sceneManager = new SceneManager(); protected SceneManager m_sceneManager = new SceneManager();
protected StorageManager m_storageManager; protected StorageManager m_storageManager;
protected string m_storageConnectionString; protected string m_storageConnectionString;
protected VoiceChatServer m_voiceChatServer; // An attribute to indicate whether prim inventories should be persisted.
// Probably will be temporary until this stops being experimental.
public SceneManager SceneManager protected bool m_storagePersistPrimInventories;
{
get { return m_sceneManager; } protected VoiceChatServer m_voiceChatServer;
}
public SceneManager SceneManager
public RegionApplicationBase() {
{ get { return m_sceneManager; }
m_startuptime = DateTime.Now; }
}
public virtual void StartUp()
public virtual void StartUp() {
{ ClientView.TerrainManager = new TerrainManager(new SecondLife());
ClientView.TerrainManager = new TerrainManager(new SecondLife());
m_storageManager = CreateStorageManager(m_storageConnectionString);
m_storageManager = CreateStorageManager(m_storageConnectionString);
Initialize();
Initialize();
m_httpServer = new BaseHttpServer(m_httpServerPort);
m_httpServer = new BaseHttpServer(m_httpServerPort);
m_log.Info("[REGION]: Starting HTTP server");
m_log.Status("REGION", "Starting HTTP server");
m_httpServer.Start(); m_httpServer.Start();
} }
protected abstract void Initialize(); protected abstract void Initialize();
protected void StartLog() protected void StartConsole()
{ {
m_log = CreateLog(); m_console = CreateConsole();
MainLog.Instance = m_log; MainConsole.Instance = m_console;
} }
protected abstract LogBase CreateLog(); protected abstract ConsoleBase CreateConsole();
protected abstract PhysicsScene GetPhysicsScene(); protected abstract PhysicsScene GetPhysicsScene();
protected abstract StorageManager CreateStorageManager(string connectionstring); protected abstract StorageManager CreateStorageManager(string connectionstring);
protected PhysicsScene GetPhysicsScene(string engine, string meshEngine) protected PhysicsScene GetPhysicsScene(string engine, string meshEngine)
{ {
PhysicsPluginManager physicsPluginManager; PhysicsPluginManager physicsPluginManager;
physicsPluginManager = new PhysicsPluginManager(); physicsPluginManager = new PhysicsPluginManager();
physicsPluginManager.LoadPlugins(); physicsPluginManager.LoadPlugins();
return physicsPluginManager.GetPhysicsScene(engine, meshEngine); return physicsPluginManager.GetPhysicsScene(engine, meshEngine);
} }
protected Scene SetupScene(RegionInfo regionInfo, out UDPServer udpServer, bool m_permissions) protected Scene SetupScene(RegionInfo regionInfo, out UDPServer udpServer, bool m_permissions)
{ {
AgentCircuitManager circuitManager = new AgentCircuitManager(); AgentCircuitManager circuitManager = new AgentCircuitManager();
udpServer = new UDPServer((uint) regionInfo.InternalEndPoint.Port, m_assetCache, m_log, circuitManager); IPAddress listenIP = regionInfo.InternalEndPoint.Address;
//if (!IPAddress.TryParse(regionInfo.InternalEndPoint, out listenIP))
Scene scene = CreateScene(regionInfo, m_storageManager, circuitManager); // listenIP = IPAddress.Parse("0.0.0.0");
m_voiceChatServer = new VoiceChatServer(scene);
uint port = (uint) regionInfo.InternalEndPoint.Port;
udpServer.LocalScene = scene; udpServer = new UDPServer(listenIP, ref port, regionInfo.m_allow_alternate_ports, m_assetCache, circuitManager);
regionInfo.InternalEndPoint.Port = (int)port;
scene.LoadWorldMap();
scene.RegisterRegionWithGrid(); Scene scene = CreateScene(regionInfo, m_storageManager, circuitManager);
m_voiceChatServer = new VoiceChatServer(scene);
scene.PhysicsScene = GetPhysicsScene();
scene.PhysicsScene.SetTerrain(scene.Terrain.GetHeights1D()); udpServer.LocalScene = scene;
//Master Avatar Setup scene.LoadWorldMap();
UserProfileData masterAvatar; scene.RegisterRegionWithGrid();
if (scene.RegionInfo.MasterAvatarAssignedUUID != LLUUID.Zero)
{ scene.PhysicsScene = GetPhysicsScene();
masterAvatar = m_commsManager.UserService.SetupMasterUser(scene.RegionInfo.MasterAvatarAssignedUUID); scene.PhysicsScene.SetTerrain(scene.Terrain.GetHeights1D());
}
else //Master Avatar Setup
{ UserProfileData masterAvatar;
masterAvatar = if (scene.RegionInfo.MasterAvatarAssignedUUID != LLUUID.Zero)
m_commsManager.UserService.SetupMasterUser(scene.RegionInfo.MasterAvatarFirstName, {
scene.RegionInfo.MasterAvatarLastName, masterAvatar = m_commsManager.UserService.SetupMasterUser(scene.RegionInfo.MasterAvatarAssignedUUID);
scene.RegionInfo.MasterAvatarSandboxPassword); }
else
} {
masterAvatar =
if (masterAvatar != null) m_commsManager.UserService.SetupMasterUser(scene.RegionInfo.MasterAvatarFirstName,
{ scene.RegionInfo.MasterAvatarLastName,
m_log.Verbose("PARCEL", "Found master avatar [" + masterAvatar.UUID.ToString() + "]"); scene.RegionInfo.MasterAvatarSandboxPassword);
scene.RegionInfo.MasterAvatarAssignedUUID = masterAvatar.UUID;
} }
else
{ if (masterAvatar != null)
m_log.Verbose("PARCEL", "No master avatar found, using null."); {
scene.RegionInfo.MasterAvatarAssignedUUID = LLUUID.Zero; m_log.Info("[PARCEL]: Found master avatar [" + masterAvatar.UUID.ToString() + "]");
} scene.RegionInfo.MasterAvatarAssignedUUID = masterAvatar.UUID;
}
scene.LoadPrimsFromStorage(m_permissions); else
scene.loadAllLandObjectsFromStorage(); {
scene.performParcelPrimCountUpdate(); m_log.Info("[PARCEL]: No master avatar found, using null.");
scene.StartTimer(); scene.RegionInfo.MasterAvatarAssignedUUID = LLUUID.Zero;
return scene; }
}
scene.LoadPrimsFromStorage(m_permissions);
protected abstract Scene CreateScene(RegionInfo regionInfo, StorageManager storageManager, scene.loadAllLandObjectsFromStorage();
AgentCircuitManager circuitManager); scene.performParcelPrimCountUpdate();
} scene.StartTimer();
} return scene;
}
protected abstract Scene CreateScene(RegionInfo regionInfo, StorageManager storageManager,
AgentCircuitManager circuitManager);
}
}

View File

@ -1,315 +1,419 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
*/ */
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using libsecondlife.Packets; using libsecondlife.Packets;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Communications.Cache;
using OpenSim.Framework.Console; using OpenSim.Framework.Console;
namespace OpenSim.Region.ClientStack namespace OpenSim.Region.ClientStack
{ {
public class UDPServer : ClientStackNetworkHandler public class UDPServer : ClientStackNetworkHandler
{ {
protected Dictionary<EndPoint, uint> clientCircuits = new Dictionary<EndPoint, uint>(); private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public Dictionary<uint, EndPoint> clientCircuits_reverse = new Dictionary<uint, EndPoint>();
public Socket Server; protected Dictionary<EndPoint, uint> clientCircuits = new Dictionary<EndPoint, uint>();
protected IPEndPoint ServerIncoming; public Dictionary<uint, EndPoint> clientCircuits_reverse = new Dictionary<uint, EndPoint>();
protected byte[] RecvBuffer = new byte[4096]; public Socket Server;
protected byte[] ZeroBuffer = new byte[8192]; protected IPEndPoint ServerIncoming;
protected IPEndPoint ipeSender; protected byte[] RecvBuffer = new byte[4096];
protected EndPoint epSender; protected byte[] ZeroBuffer = new byte[8192];
protected AsyncCallback ReceivedData; protected IPEndPoint ipeSender;
protected PacketServer m_packetServer; protected EndPoint epSender;
protected ulong m_regionHandle; protected AsyncCallback ReceivedData;
protected PacketServer m_packetServer;
protected uint listenPort; protected ulong m_regionHandle;
protected IScene m_localScene;
protected AssetCache m_assetCache; protected uint listenPort;
protected LogBase m_log; protected bool Allow_Alternate_Port;
protected AgentCircuitManager m_authenticateSessionsClass; protected IPAddress listenIP = IPAddress.Parse("0.0.0.0");
protected IScene m_localScene;
public PacketServer PacketServer protected AssetCache m_assetCache;
{ protected AgentCircuitManager m_authenticateSessionsClass;
get { return m_packetServer; }
set { m_packetServer = value; } public PacketServer PacketServer
} {
get { return m_packetServer; }
public IScene LocalScene set { m_packetServer = value; }
{ }
set
{ public IScene LocalScene
m_localScene = value; {
m_packetServer.LocalScene = m_localScene; set
m_regionHandle = m_localScene.RegionInfo.RegionHandle; {
} m_localScene = value;
} m_packetServer.LocalScene = m_localScene;
m_regionHandle = m_localScene.RegionInfo.RegionHandle;
public ulong RegionHandle }
{ }
get { return m_regionHandle; }
} public ulong RegionHandle
{
public UDPServer() get { return m_regionHandle; }
{ }
}
public UDPServer()
public UDPServer(uint port, AssetCache assetCache, LogBase console, AgentCircuitManager authenticateClass) {
{ }
listenPort = port;
m_assetCache = assetCache; public UDPServer(IPAddress _listenIP, ref uint port, bool allow_alternate_port, AssetCache assetCache, AgentCircuitManager authenticateClass)
m_log = console; {
m_authenticateSessionsClass = authenticateClass; listenIP = _listenIP;
CreatePacketServer(); listenPort = port;
} Allow_Alternate_Port = allow_alternate_port;
m_assetCache = assetCache;
protected virtual void CreatePacketServer() m_authenticateSessionsClass = authenticateClass;
{ CreatePacketServer();
PacketServer packetServer = new PacketServer(this);
} // 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.
protected virtual void OnReceivedData(IAsyncResult result) // So the option allow_alternate_ports="true" was added to default.xml
{ port = listenPort;
ipeSender = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0); }
epSender = (EndPoint) ipeSender;
Packet packet = null; protected virtual void CreatePacketServer()
{
int numBytes; PacketServer packetServer = new PacketServer(this);
}
try
{ protected virtual void OnReceivedData(IAsyncResult result)
numBytes = Server.EndReceiveFrom(result, ref epSender); {
ipeSender = new IPEndPoint(listenIP, 0);
//Report byte count to rex statuswindow epSender = (EndPoint) ipeSender;
OpenSim.Framework.ServerStatus.ServerStatus.ReportInPacketUdp(numBytes); Packet packet = null;
}
catch (SocketException e) int numBytes = 1;
{
// TODO : Actually only handle those states that we have control over, re-throw everything else, try
// TODO: implement cases as we encounter them. {
switch (e.SocketErrorCode) numBytes = Server.EndReceiveFrom(result, ref epSender);
{
case SocketError.AlreadyInProgress: //Report byte count to rex statuswindow
case SocketError.NetworkReset: OpenSim.Framework.ServerStatus.ServerStatus.ReportInPacketUdp(numBytes);
case SocketError.ConnectionReset: }
catch (SocketException e)
try {
{ // TODO : Actually only handle those states that we have control over, re-throw everything else,
CloseEndPoint(epSender); // TODO: implement cases as we encounter them.
} //m_log.Error("[UDPSERVER]: Connection Error! - " + e.ToString());
catch (Exception a) switch (e.SocketErrorCode)
{ {
MainLog.Instance.Verbose("UDPSERVER", a.ToString()); case SocketError.AlreadyInProgress:
} case SocketError.NetworkReset:
try case SocketError.ConnectionReset:
{
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, try
ReceivedData, null); {
CloseEndPoint(epSender);
// Ter: For some stupid reason ConnectionReset basically kills our async event structure.. }
// so therefore.. we've got to tell the server to BeginReceiveFrom again. catch (Exception a)
// This will happen over and over until we've gone through all packets {
// sent to and from this particular user. m_log.Info("[UDPSERVER]: " + a.ToString());
// Stupid I know.. }
// but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method. try
} {
catch (SocketException) Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
{ ReceivedData, null);
}
break; // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
default: // so therefore.. we've got to tell the server to BeginReceiveFrom again.
try // This will happen over and over until we've gone through all packets
{ // sent to and from this particular user.
CloseEndPoint(epSender); // Stupid I know..
} // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
catch (Exception) }
{ catch (SocketException)
//MainLog.Instance.Verbose("UDPSERVER", a.ToString()); {
} }
try break;
{ default:
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, try
ReceivedData, null); {
CloseEndPoint(epSender);
// Ter: For some stupid reason ConnectionReset basically kills our async event structure.. }
// so therefore.. we've got to tell the server to BeginReceiveFrom again. catch (Exception)
// This will happen over and over until we've gone through all packets {
// sent to and from this particular user. //m_log.Info("[UDPSERVER]" + a.ToString());
// Stupid I know.. }
// but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method. try
} {
catch (SocketException) Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
{ ReceivedData, null);
}
// Ter: For some stupid reason ConnectionReset basically kills our async event structure..
// Here's some reference code! :D // so therefore.. we've got to tell the server to BeginReceiveFrom again.
// Shutdown and restart the UDP listener! hehe // This will happen over and over until we've gone through all packets
// Shiny // sent to and from this particular user.
// Stupid I know..
//Server.Shutdown(SocketShutdown.Both); // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
//CloseEndPoint(epSender); }
//ServerListener(); catch (SocketException e2)
break; {
} m_log.Error("[UDPSERVER]: " + e2.ToString());
}
return;
} // Here's some reference code! :D
catch (ObjectDisposedException) // Shutdown and restart the UDP listener! hehe
{ // Shiny
//MainLog.Instance.Debug("UDPSERVER", e.ToString());
return; //Server.Shutdown(SocketShutdown.Both);
} //CloseEndPoint(epSender);
//ServerListener();
int packetEnd = numBytes - 1; break;
}
try
{ //return;
packet = PacketPool.Instance.GetPacket(RecvBuffer, ref packetEnd, ZeroBuffer); }
} catch (ObjectDisposedException e)
catch (Exception) {
{ m_log.Debug("[UDPSERVER]: " + e.ToString());
//MainLog.Instance.Debug("UDPSERVER", e.ToString()); try
} {
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
if (packet != null) ReceivedData, null);
{
// do we already have a circuit for this endpoint // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
uint circuit; // so therefore.. we've got to tell the server to BeginReceiveFrom again.
if (clientCircuits.TryGetValue(epSender, out circuit)) // This will happen over and over until we've gone through all packets
{ // sent to and from this particular user.
//if so then send packet to the packetserver // Stupid I know..
//MainLog.Instance.Warn("UDPSERVER", "ALREADY HAVE Circuit!"); // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
m_packetServer.InPacket(circuit, packet); }
} catch (SocketException e2)
else if (packet.Type == PacketType.UseCircuitCode) {
{ m_log.Error("[UDPSERVER]: " + e2.ToString());
// new client }
MainLog.Instance.Debug("UDPSERVER", "Adding New Client"); //return;
AddNewClient(packet); }
}
else int packetEnd = numBytes - 1;
{
// invalid client try
//CFK: This message seems to have served its usefullness as of 12-15 so I am commenting it out for now {
//m_log.Warn("client", "Got a packet from an invalid client - " + epSender.ToString()); packet = PacketPool.Instance.GetPacket(RecvBuffer, ref packetEnd, ZeroBuffer);
}
} }
catch (Exception e)
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null); {
} m_log.Debug("[UDPSERVER]: " + e.ToString());
}
private void CloseEndPoint(EndPoint sender)
{ try
uint circuit; {
if (clientCircuits.TryGetValue(sender, out circuit)) Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
{ }
m_packetServer.CloseCircuit(circuit); catch (SocketException e4)
} {
} try
{
protected virtual void AddNewClient(Packet packet) CloseEndPoint(epSender);
{ }
UseCircuitCodePacket useCircuit = (UseCircuitCodePacket) packet; catch (Exception a)
clientCircuits.Add(epSender, useCircuit.CircuitCode.Code); {
clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, epSender); m_log.Info("[UDPSERVER]: " + a.ToString());
}
PacketServer.AddNewClient(epSender, useCircuit, m_assetCache, m_authenticateSessionsClass); try
} {
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
public void ServerListener() ReceivedData, null);
{
m_log.Verbose("SERVER", "Opening UDP socket on " + listenPort.ToString()); // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
// so therefore.. we've got to tell the server to BeginReceiveFrom again.
ServerIncoming = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int) listenPort); // This will happen over and over until we've gone through all packets
Server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); // sent to and from this particular user.
Server.Bind(ServerIncoming); // Stupid I know..
// but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
m_log.Verbose("SERVER", "UDP socket bound, getting ready to listen"); }
catch (SocketException e5)
ipeSender = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0); {
epSender = (EndPoint) ipeSender; m_log.Error("[UDPSERVER]: " + e5.ToString());
ReceivedData = new AsyncCallback(OnReceivedData); }
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
}
m_log.Status("SERVER", "Listening...");
} if (packet != null)
{
public virtual void RegisterPacketServer(PacketServer server) try
{ {
m_packetServer = server; // do we already have a circuit for this endpoint
} uint circuit;
public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode) bool ret = false;
//EndPoint packetSender) lock (clientCircuits)
{ {
// find the endpoint for this circuit ret = clientCircuits.TryGetValue(epSender, out circuit);
EndPoint sendto = null; }
if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto)) if (ret)
{ {
//we found the endpoint so send the packet to it //if so then send packet to the packetserver
while (true) //m_log.Warn("[UDPSERVER]: ALREADY HAVE Circuit!");
{ m_packetServer.InPacket(circuit, packet);
try }
{ else if (packet.Type == PacketType.UseCircuitCode)
Server.SendTo(buffer, size, flags, sendto); {
return; // new client
} m_log.Debug("[UDPSERVER]: Adding New Client");
catch (SocketException e) AddNewClient(packet);
{ }
if (e.ErrorCode == 10055) else
{ {
//Send buffer full, halt for half second and retry // invalid client
MainLog.Instance.Warn("SERVER", "Socket send buffer was full, halting for 200ms"); //CFK: This message seems to have served its usefullness as of 12-15 so I am commenting it out for now
System.Threading.Thread.Sleep(200); //m_log.Warn("[UDPSERVER]: Got a packet from an invalid client - " + packet.ToString());
}
else }
{ }
//Rethrow catch (Exception ex)
throw e; {
} m_log.Error("[UDPSERVER]: Exception in processing packet.");
} m_log.Debug("[UDPSERVER]: Adding New Client");
} try
} {
} AddNewClient(packet);
}
public virtual void RemoveClientCircuit(uint circuitcode) catch (Exception e3)
{ {
EndPoint sendto = null; m_log.Error("[UDPSERVER]: Adding New Client threw exception " + e3.ToString());
if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto)) Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
{ ReceivedData, null);
clientCircuits.Remove(sendto); }
}
}
clientCircuits_reverse.Remove(circuitcode);
} }
}
} private void CloseEndPoint(EndPoint sender)
} {
uint circuit;
lock (clientCircuits)
{
if (clientCircuits.TryGetValue(sender, out circuit))
{
m_packetServer.CloseCircuit(circuit);
}
}
}
protected virtual void AddNewClient(Packet packet)
{
UseCircuitCodePacket useCircuit = (UseCircuitCodePacket) packet;
lock (clientCircuits)
{
if (!clientCircuits.ContainsKey(epSender))
clientCircuits.Add(epSender, 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, epSender);
else
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);
}
public void ServerListener()
{
uint newPort = listenPort;
for (uint i = 0; i < 20; i++)
{
newPort = listenPort + i;
m_log.Info("[SERVER]: Opening UDP socket on " + listenIP.ToString() + " " + newPort + ".");// Allow alternate ports: " + Allow_Alternate_Port.ToString());
try
{
ServerIncoming = new IPEndPoint(listenIP, (int) newPort);
Server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
Server.Bind(ServerIncoming);
listenPort = newPort;
break;
}
catch (Exception ex)
{
// We are not looking for alternate ports?
//if (!Allow_Alternate_Port)
throw (ex);
// We are looking for alternate ports!
m_log.Info("[SERVER]: UDP socket on " + listenIP.ToString() + " " + listenPort.ToString() + " is not available, trying next.");
}
System.Threading.Thread.Sleep(100); // Wait before we retry socket
}
m_log.Info("[SERVER]: UDP socket bound, getting ready to listen");
ipeSender = new IPEndPoint(listenIP, 0);
epSender = (EndPoint) ipeSender;
ReceivedData = new AsyncCallback(OnReceivedData);
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
m_log.Info("[SERVER]: Listening on port " + newPort);
}
public virtual void RegisterPacketServer(PacketServer server)
{
m_packetServer = server;
}
public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
//EndPoint packetSender)
{
// find the endpoint for this circuit
EndPoint sendto = null;
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);
}
}
}
public virtual void RemoveClientCircuit(uint circuitcode)
{
EndPoint sendto = null;
lock (clientCircuits_reverse)
{
if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto))
{
clientCircuits.Remove(sendto);
clientCircuits_reverse.Remove(circuitcode);
}
}
}
}
}