* 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/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* 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
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
using System.Net;
using System.Net.Sockets;
using libsecondlife;
using libsecondlife.Packets;
using OpenSim.Framework;
using OpenSim.Framework.Communications.Cache;
namespace OpenSim.Region.ClientStack
{
public class PacketServer
{
private ClientStackNetworkHandler m_networkHandler;
private IScene m_scene;
//private readonly ClientManager m_clientManager = new ClientManager();
//public ClientManager ClientManager
//{
// get { return m_clientManager; }
//}
public PacketServer(ClientStackNetworkHandler networkHandler)
{
m_networkHandler = networkHandler;
m_networkHandler.RegisterPacketServer(this);
}
public IScene LocalScene
{
set { m_scene = value; }
}
/// <summary>
///
/// </summary>
/// <param name="circuitCode"></param>
/// <param name="packet"></param>
public virtual void InPacket(uint circuitCode, Packet packet)
{
m_scene.ClientManager.InPacket(circuitCode, packet);
}
protected virtual IClientAPI CreateNewClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack,
ClientManager clientManager, IScene scene, AssetCache assetCache,
PacketServer packServer, AgentCircuitManager authenSessions,
LLUUID agentId, LLUUID sessionId, uint circuitCode)
{
return
new ClientView(remoteEP, scene, assetCache, packServer, authenSessions, agentId, sessionId, circuitCode);
}
public virtual bool AddNewClient(EndPoint epSender, UseCircuitCodePacket useCircuit, AssetCache assetCache,
AgentCircuitManager authenticateSessionsClass)
{
IClientAPI newuser;
if (m_scene.ClientManager.TryGetClient(useCircuit.CircuitCode.Code, out newuser))
{
return false;
}
else
{
newuser = CreateNewClient(epSender, useCircuit, m_scene.ClientManager, m_scene, assetCache, this,
authenticateSessionsClass, useCircuit.CircuitCode.ID,
useCircuit.CircuitCode.SessionID, useCircuit.CircuitCode.Code);
m_scene.ClientManager.Add(useCircuit.CircuitCode.Code, newuser);
newuser.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler;
newuser.OnLogout += LogoutHandler;
newuser.OnConnectionClosed += CloseClient;
return true;
}
}
public void LogoutHandler(IClientAPI client)
{
client.SendLogoutPacket();
CloseClient(client);
}
/// <summary>
///
/// </summary>
/// <param name="buffer"></param>
/// <param name="size"></param>
/// <param name="flags"></param>
/// <param name="circuitcode"></param>
public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
{
m_networkHandler.SendPacketTo(buffer, size, flags, circuitcode);
}
/// <summary>
///
/// </summary>
/// <param name="circuitcode"></param>
public virtual void CloseCircuit(uint circuitcode)
{
m_networkHandler.RemoveClientCircuit(circuitcode);
//m_scene.ClientManager.CloseAllAgents(circuitcode);
}
public virtual void CloseClient(IClientAPI client)
{
CloseCircuit(client.CircuitCode);
client.Close(false);
}
}
}
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* 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
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
using System;
using System.Net;
using System.Net.Sockets;
using libsecondlife;
using libsecondlife.Packets;
using OpenSim.Framework;
using OpenSim.Framework.Communications.Cache;
namespace OpenSim.Region.ClientStack
{
public class PacketServer
{
//private static readonly log4net.ILog m_log
// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private ClientStackNetworkHandler m_networkHandler;
private IScene m_scene;
//private readonly ClientManager m_clientManager = new ClientManager();
//public ClientManager ClientManager
//{
// get { return m_clientManager; }
//}
public PacketServer(ClientStackNetworkHandler networkHandler)
{
m_networkHandler = networkHandler;
m_networkHandler.RegisterPacketServer(this);
}
public IScene LocalScene
{
set { m_scene = value; }
}
/// <summary>
///
/// </summary>
/// <param name="circuitCode"></param>
/// <param name="packet"></param>
public virtual void InPacket(uint circuitCode, Packet packet)
{
m_scene.ClientManager.InPacket(circuitCode, packet);
}
protected virtual IClientAPI CreateNewClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack,
ClientManager clientManager, IScene scene, AssetCache assetCache,
PacketServer packServer, AgentCircuitManager authenSessions,
LLUUID agentId, LLUUID sessionId, uint circuitCode)
{
return
new ClientView(remoteEP, scene, assetCache, packServer, authenSessions, agentId, sessionId, circuitCode);
}
public virtual bool AddNewClient(EndPoint epSender, UseCircuitCodePacket useCircuit, AssetCache assetCache,
AgentCircuitManager authenticateSessionsClass)
{
IClientAPI newuser;
if (m_scene.ClientManager.TryGetClient(useCircuit.CircuitCode.Code, out newuser))
{
return false;
}
else
{
newuser = CreateNewClient(epSender, useCircuit, m_scene.ClientManager, m_scene, assetCache, this,
authenticateSessionsClass, useCircuit.CircuitCode.ID,
useCircuit.CircuitCode.SessionID, useCircuit.CircuitCode.Code);
m_scene.ClientManager.Add(useCircuit.CircuitCode.Code, newuser);
newuser.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler;
newuser.OnLogout += LogoutHandler;
newuser.OnConnectionClosed += CloseClient;
return true;
}
}
public void LogoutHandler(IClientAPI client)
{
client.SendLogoutPacket();
CloseClient(client);
}
/// <summary>
///
/// </summary>
/// <param name="buffer"></param>
/// <param name="size"></param>
/// <param name="flags"></param>
/// <param name="circuitcode"></param>
public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
{
m_networkHandler.SendPacketTo(buffer, size, flags, circuitcode);
}
/// <summary>
///
/// </summary>
/// <param name="circuitcode"></param>
public virtual void CloseCircuit(uint circuitcode)
{
m_networkHandler.RemoveClientCircuit(circuitcode);
//m_scene.ClientManager.CloseAllAgents(circuitcode);
}
/// <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/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* 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
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
using System;
using System.Collections.Generic;
using System.Net;
using libsecondlife;
using OpenSim.Framework;
using OpenSim.Framework.Communications;
using OpenSim.Framework.Communications.Cache;
using OpenSim.Framework.Console;
using OpenSim.Framework.Servers;
using OpenSim.Region.Environment;
using OpenSim.Region.Environment.Scenes;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Communications.VoiceChat;
namespace OpenSim.Region.ClientStack
{
public abstract class RegionApplicationBase
{
protected AssetCache m_assetCache;
protected Dictionary<EndPoint, uint> m_clientCircuits = new Dictionary<EndPoint, uint>();
protected DateTime m_startuptime;
protected NetworkServersInfo m_networkServersInfo;
protected BaseHttpServer m_httpServer;
protected uint m_httpServerPort;
protected LogBase m_log;
protected CommunicationsManager m_commsManager;
protected SceneManager m_sceneManager = new SceneManager();
protected StorageManager m_storageManager;
protected string m_storageConnectionString;
protected VoiceChatServer m_voiceChatServer;
public SceneManager SceneManager
{
get { return m_sceneManager; }
}
public RegionApplicationBase()
{
m_startuptime = DateTime.Now;
}
public virtual void StartUp()
{
ClientView.TerrainManager = new TerrainManager(new SecondLife());
m_storageManager = CreateStorageManager(m_storageConnectionString);
Initialize();
m_httpServer = new BaseHttpServer(m_httpServerPort);
m_log.Status("REGION", "Starting HTTP server");
m_httpServer.Start();
}
protected abstract void Initialize();
protected void StartLog()
{
m_log = CreateLog();
MainLog.Instance = m_log;
}
protected abstract LogBase CreateLog();
protected abstract PhysicsScene GetPhysicsScene();
protected abstract StorageManager CreateStorageManager(string connectionstring);
protected PhysicsScene GetPhysicsScene(string engine, string meshEngine)
{
PhysicsPluginManager physicsPluginManager;
physicsPluginManager = new PhysicsPluginManager();
physicsPluginManager.LoadPlugins();
return physicsPluginManager.GetPhysicsScene(engine, meshEngine);
}
protected Scene SetupScene(RegionInfo regionInfo, out UDPServer udpServer, bool m_permissions)
{
AgentCircuitManager circuitManager = new AgentCircuitManager();
udpServer = new UDPServer((uint) regionInfo.InternalEndPoint.Port, m_assetCache, m_log, circuitManager);
Scene scene = CreateScene(regionInfo, m_storageManager, circuitManager);
m_voiceChatServer = new VoiceChatServer(scene);
udpServer.LocalScene = scene;
scene.LoadWorldMap();
scene.RegisterRegionWithGrid();
scene.PhysicsScene = GetPhysicsScene();
scene.PhysicsScene.SetTerrain(scene.Terrain.GetHeights1D());
//Master Avatar Setup
UserProfileData masterAvatar;
if (scene.RegionInfo.MasterAvatarAssignedUUID != LLUUID.Zero)
{
masterAvatar = m_commsManager.UserService.SetupMasterUser(scene.RegionInfo.MasterAvatarAssignedUUID);
}
else
{
masterAvatar =
m_commsManager.UserService.SetupMasterUser(scene.RegionInfo.MasterAvatarFirstName,
scene.RegionInfo.MasterAvatarLastName,
scene.RegionInfo.MasterAvatarSandboxPassword);
}
if (masterAvatar != null)
{
m_log.Verbose("PARCEL", "Found master avatar [" + masterAvatar.UUID.ToString() + "]");
scene.RegionInfo.MasterAvatarAssignedUUID = masterAvatar.UUID;
}
else
{
m_log.Verbose("PARCEL", "No master avatar found, using null.");
scene.RegionInfo.MasterAvatarAssignedUUID = LLUUID.Zero;
}
scene.LoadPrimsFromStorage(m_permissions);
scene.loadAllLandObjectsFromStorage();
scene.performParcelPrimCountUpdate();
scene.StartTimer();
return scene;
}
protected abstract Scene CreateScene(RegionInfo regionInfo, StorageManager storageManager,
AgentCircuitManager circuitManager);
}
}
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* 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
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
using System;
using System.Collections.Generic;
using System.Net;
using libsecondlife;
using OpenSim.Framework;
using OpenSim.Framework.Communications;
using OpenSim.Framework.Communications.Cache;
using OpenSim.Framework.Console;
using OpenSim.Framework.Servers;
using OpenSim.Region.Environment;
using OpenSim.Region.Environment.Scenes;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Communications.VoiceChat;
namespace OpenSim.Region.ClientStack
{
public abstract class RegionApplicationBase : BaseOpenSimServer
{
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
protected AssetCache m_assetCache;
protected Dictionary<EndPoint, uint> m_clientCircuits = new Dictionary<EndPoint, uint>();
protected NetworkServersInfo m_networkServersInfo;
protected BaseHttpServer m_httpServer;
protected uint m_httpServerPort;
protected CommunicationsManager m_commsManager;
protected SceneManager m_sceneManager = new SceneManager();
protected StorageManager m_storageManager;
protected string m_storageConnectionString;
// An attribute to indicate whether prim inventories should be persisted.
// Probably will be temporary until this stops being experimental.
protected bool m_storagePersistPrimInventories;
protected VoiceChatServer m_voiceChatServer;
public SceneManager SceneManager
{
get { return m_sceneManager; }
}
public virtual void StartUp()
{
ClientView.TerrainManager = new TerrainManager(new SecondLife());
m_storageManager = CreateStorageManager(m_storageConnectionString);
Initialize();
m_httpServer = new BaseHttpServer(m_httpServerPort);
m_log.Info("[REGION]: Starting HTTP server");
m_httpServer.Start();
}
protected abstract void Initialize();
protected void StartConsole()
{
m_console = CreateConsole();
MainConsole.Instance = m_console;
}
protected abstract ConsoleBase CreateConsole();
protected abstract PhysicsScene GetPhysicsScene();
protected abstract StorageManager CreateStorageManager(string connectionstring);
protected PhysicsScene GetPhysicsScene(string engine, string meshEngine)
{
PhysicsPluginManager physicsPluginManager;
physicsPluginManager = new PhysicsPluginManager();
physicsPluginManager.LoadPlugins();
return physicsPluginManager.GetPhysicsScene(engine, meshEngine);
}
protected Scene SetupScene(RegionInfo regionInfo, 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);
regionInfo.InternalEndPoint.Port = (int)port;
Scene scene = CreateScene(regionInfo, m_storageManager, circuitManager);
m_voiceChatServer = new VoiceChatServer(scene);
udpServer.LocalScene = scene;
scene.LoadWorldMap();
scene.RegisterRegionWithGrid();
scene.PhysicsScene = GetPhysicsScene();
scene.PhysicsScene.SetTerrain(scene.Terrain.GetHeights1D());
//Master Avatar Setup
UserProfileData masterAvatar;
if (scene.RegionInfo.MasterAvatarAssignedUUID != LLUUID.Zero)
{
masterAvatar = m_commsManager.UserService.SetupMasterUser(scene.RegionInfo.MasterAvatarAssignedUUID);
}
else
{
masterAvatar =
m_commsManager.UserService.SetupMasterUser(scene.RegionInfo.MasterAvatarFirstName,
scene.RegionInfo.MasterAvatarLastName,
scene.RegionInfo.MasterAvatarSandboxPassword);
}
if (masterAvatar != null)
{
m_log.Info("[PARCEL]: Found master avatar [" + masterAvatar.UUID.ToString() + "]");
scene.RegionInfo.MasterAvatarAssignedUUID = masterAvatar.UUID;
}
else
{
m_log.Info("[PARCEL]: No master avatar found, using null.");
scene.RegionInfo.MasterAvatarAssignedUUID = LLUUID.Zero;
}
scene.LoadPrimsFromStorage(m_permissions);
scene.loadAllLandObjectsFromStorage();
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/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* 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
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using libsecondlife.Packets;
using OpenSim.Framework;
using OpenSim.Framework.Communications.Cache;
using OpenSim.Framework.Console;
namespace OpenSim.Region.ClientStack
{
public class UDPServer : ClientStackNetworkHandler
{
protected Dictionary<EndPoint, uint> clientCircuits = new Dictionary<EndPoint, uint>();
public Dictionary<uint, EndPoint> clientCircuits_reverse = new Dictionary<uint, EndPoint>();
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 AsyncCallback ReceivedData;
protected PacketServer m_packetServer;
protected ulong m_regionHandle;
protected uint listenPort;
protected IScene m_localScene;
protected AssetCache m_assetCache;
protected LogBase m_log;
protected AgentCircuitManager m_authenticateSessionsClass;
public PacketServer PacketServer
{
get { return m_packetServer; }
set { m_packetServer = value; }
}
public IScene LocalScene
{
set
{
m_localScene = value;
m_packetServer.LocalScene = m_localScene;
m_regionHandle = m_localScene.RegionInfo.RegionHandle;
}
}
public ulong RegionHandle
{
get { return m_regionHandle; }
}
public UDPServer()
{
}
public UDPServer(uint port, AssetCache assetCache, LogBase console, AgentCircuitManager authenticateClass)
{
listenPort = port;
m_assetCache = assetCache;
m_log = console;
m_authenticateSessionsClass = authenticateClass;
CreatePacketServer();
}
protected virtual void CreatePacketServer()
{
PacketServer packetServer = new PacketServer(this);
}
protected virtual void OnReceivedData(IAsyncResult result)
{
ipeSender = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
epSender = (EndPoint) ipeSender;
Packet packet = null;
int numBytes;
try
{
numBytes = Server.EndReceiveFrom(result, ref epSender);
//Report byte count to rex statuswindow
OpenSim.Framework.ServerStatus.ServerStatus.ReportInPacketUdp(numBytes);
}
catch (SocketException e)
{
// TODO : Actually only handle those states that we have control over, re-throw everything else,
// TODO: implement cases as we encounter them.
switch (e.SocketErrorCode)
{
case SocketError.AlreadyInProgress:
case SocketError.NetworkReset:
case SocketError.ConnectionReset:
try
{
CloseEndPoint(epSender);
}
catch (Exception a)
{
MainLog.Instance.Verbose("UDPSERVER", a.ToString());
}
try
{
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
ReceivedData, null);
// Ter: For some stupid reason ConnectionReset basically kills our async event structure..
// so therefore.. we've got to tell the server to BeginReceiveFrom again.
// This will happen over and over until we've gone through all packets
// sent to and from this particular user.
// Stupid I know..
// but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
}
catch (SocketException)
{
}
break;
default:
try
{
CloseEndPoint(epSender);
}
catch (Exception)
{
//MainLog.Instance.Verbose("UDPSERVER", a.ToString());
}
try
{
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
ReceivedData, null);
// Ter: For some stupid reason ConnectionReset basically kills our async event structure..
// so therefore.. we've got to tell the server to BeginReceiveFrom again.
// This will happen over and over until we've gone through all packets
// sent to and from this particular user.
// Stupid I know..
// but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
}
catch (SocketException)
{
}
// Here's some reference code! :D
// Shutdown and restart the UDP listener! hehe
// Shiny
//Server.Shutdown(SocketShutdown.Both);
//CloseEndPoint(epSender);
//ServerListener();
break;
}
return;
}
catch (ObjectDisposedException)
{
//MainLog.Instance.Debug("UDPSERVER", e.ToString());
return;
}
int packetEnd = numBytes - 1;
try
{
packet = PacketPool.Instance.GetPacket(RecvBuffer, ref packetEnd, ZeroBuffer);
}
catch (Exception)
{
//MainLog.Instance.Debug("UDPSERVER", e.ToString());
}
if (packet != null)
{
// do we already have a circuit for this endpoint
uint circuit;
if (clientCircuits.TryGetValue(epSender, out circuit))
{
//if so then send packet to the packetserver
//MainLog.Instance.Warn("UDPSERVER", "ALREADY HAVE Circuit!");
m_packetServer.InPacket(circuit, packet);
}
else if (packet.Type == PacketType.UseCircuitCode)
{
// new client
MainLog.Instance.Debug("UDPSERVER", "Adding New Client");
AddNewClient(packet);
}
else
{
// invalid client
//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());
}
}
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
}
private void CloseEndPoint(EndPoint sender)
{
uint circuit;
if (clientCircuits.TryGetValue(sender, out circuit))
{
m_packetServer.CloseCircuit(circuit);
}
}
protected virtual void AddNewClient(Packet packet)
{
UseCircuitCodePacket useCircuit = (UseCircuitCodePacket) packet;
clientCircuits.Add(epSender, useCircuit.CircuitCode.Code);
clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, epSender);
PacketServer.AddNewClient(epSender, useCircuit, m_assetCache, m_authenticateSessionsClass);
}
public void ServerListener()
{
m_log.Verbose("SERVER", "Opening UDP socket on " + listenPort.ToString());
ServerIncoming = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int) listenPort);
Server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
Server.Bind(ServerIncoming);
m_log.Verbose("SERVER", "UDP socket bound, getting ready to listen");
ipeSender = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
epSender = (EndPoint) ipeSender;
ReceivedData = new AsyncCallback(OnReceivedData);
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
m_log.Status("SERVER", "Listening...");
}
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;
if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto))
{
//we found the endpoint so send the packet to it
while (true)
{
try
{
Server.SendTo(buffer, size, flags, sendto);
return;
}
catch (SocketException e)
{
if (e.ErrorCode == 10055)
{
//Send buffer full, halt for half second and retry
MainLog.Instance.Warn("SERVER", "Socket send buffer was full, halting for 200ms");
System.Threading.Thread.Sleep(200);
}
else
{
//Rethrow
throw e;
}
}
}
}
}
public virtual void RemoveClientCircuit(uint circuitcode)
{
EndPoint sendto = null;
if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto))
{
clientCircuits.Remove(sendto);
clientCircuits_reverse.Remove(circuitcode);
}
}
}
}
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* 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
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using libsecondlife.Packets;
using OpenSim.Framework;
using OpenSim.Framework.Communications.Cache;
using OpenSim.Framework.Console;
namespace OpenSim.Region.ClientStack
{
public class UDPServer : ClientStackNetworkHandler
{
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
protected Dictionary<EndPoint, uint> clientCircuits = new Dictionary<EndPoint, uint>();
public Dictionary<uint, EndPoint> clientCircuits_reverse = new Dictionary<uint, EndPoint>();
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 AsyncCallback ReceivedData;
protected PacketServer m_packetServer;
protected ulong m_regionHandle;
protected uint listenPort;
protected bool Allow_Alternate_Port;
protected IPAddress listenIP = IPAddress.Parse("0.0.0.0");
protected IScene m_localScene;
protected AssetCache m_assetCache;
protected AgentCircuitManager m_authenticateSessionsClass;
public PacketServer PacketServer
{
get { return m_packetServer; }
set { m_packetServer = value; }
}
public IScene LocalScene
{
set
{
m_localScene = value;
m_packetServer.LocalScene = m_localScene;
m_regionHandle = m_localScene.RegionInfo.RegionHandle;
}
}
public ulong RegionHandle
{
get { return m_regionHandle; }
}
public UDPServer()
{
}
public UDPServer(IPAddress _listenIP, ref uint port, bool allow_alternate_port, AssetCache assetCache, AgentCircuitManager authenticateClass)
{
listenIP = _listenIP;
listenPort = port;
Allow_Alternate_Port = allow_alternate_port;
m_assetCache = assetCache;
m_authenticateSessionsClass = authenticateClass;
CreatePacketServer();
// 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;
}
protected virtual void CreatePacketServer()
{
PacketServer packetServer = new PacketServer(this);
}
protected virtual void OnReceivedData(IAsyncResult result)
{
ipeSender = new IPEndPoint(listenIP, 0);
epSender = (EndPoint) ipeSender;
Packet packet = null;
int numBytes = 1;
try
{
numBytes = Server.EndReceiveFrom(result, ref epSender);
//Report byte count to rex statuswindow
OpenSim.Framework.ServerStatus.ServerStatus.ReportInPacketUdp(numBytes);
}
catch (SocketException e)
{
// TODO : Actually only handle those states that we have control over, re-throw everything else,
// TODO: implement cases as we encounter them.
//m_log.Error("[UDPSERVER]: Connection Error! - " + e.ToString());
switch (e.SocketErrorCode)
{
case SocketError.AlreadyInProgress:
case SocketError.NetworkReset:
case SocketError.ConnectionReset:
try
{
CloseEndPoint(epSender);
}
catch (Exception a)
{
m_log.Info("[UDPSERVER]: " + a.ToString());
}
try
{
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
ReceivedData, null);
// Ter: For some stupid reason ConnectionReset basically kills our async event structure..
// so therefore.. we've got to tell the server to BeginReceiveFrom again.
// This will happen over and over until we've gone through all packets
// sent to and from this particular user.
// Stupid I know..
// but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
}
catch (SocketException)
{
}
break;
default:
try
{
CloseEndPoint(epSender);
}
catch (Exception)
{
//m_log.Info("[UDPSERVER]" + a.ToString());
}
try
{
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
ReceivedData, null);
// Ter: For some stupid reason ConnectionReset basically kills our async event structure..
// so therefore.. we've got to tell the server to BeginReceiveFrom again.
// This will happen over and over until we've gone through all packets
// sent to and from this particular user.
// Stupid I know..
// but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
}
catch (SocketException e2)
{
m_log.Error("[UDPSERVER]: " + e2.ToString());
}
// Here's some reference code! :D
// Shutdown and restart the UDP listener! hehe
// Shiny
//Server.Shutdown(SocketShutdown.Both);
//CloseEndPoint(epSender);
//ServerListener();
break;
}
//return;
}
catch (ObjectDisposedException e)
{
m_log.Debug("[UDPSERVER]: " + e.ToString());
try
{
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
ReceivedData, null);
// Ter: For some stupid reason ConnectionReset basically kills our async event structure..
// so therefore.. we've got to tell the server to BeginReceiveFrom again.
// This will happen over and over until we've gone through all packets
// sent to and from this particular user.
// Stupid I know..
// but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
}
catch (SocketException e2)
{
m_log.Error("[UDPSERVER]: " + e2.ToString());
}
//return;
}
int packetEnd = numBytes - 1;
try
{
packet = PacketPool.Instance.GetPacket(RecvBuffer, ref packetEnd, ZeroBuffer);
}
catch (Exception e)
{
m_log.Debug("[UDPSERVER]: " + e.ToString());
}
try
{
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
}
catch (SocketException e4)
{
try
{
CloseEndPoint(epSender);
}
catch (Exception a)
{
m_log.Info("[UDPSERVER]: " + a.ToString());
}
try
{
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
ReceivedData, null);
// Ter: For some stupid reason ConnectionReset basically kills our async event structure..
// so therefore.. we've got to tell the server to BeginReceiveFrom again.
// This will happen over and over until we've gone through all packets
// sent to and from this particular user.
// Stupid I know..
// but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
}
catch (SocketException e5)
{
m_log.Error("[UDPSERVER]: " + e5.ToString());
}
}
if (packet != null)
{
try
{
// do we already have a circuit for this endpoint
uint circuit;
bool ret = false;
lock (clientCircuits)
{
ret = clientCircuits.TryGetValue(epSender, out circuit);
}
if (ret)
{
//if so then send packet to the packetserver
//m_log.Warn("[UDPSERVER]: ALREADY HAVE Circuit!");
m_packetServer.InPacket(circuit, packet);
}
else if (packet.Type == PacketType.UseCircuitCode)
{
// new client
m_log.Debug("[UDPSERVER]: Adding New Client");
AddNewClient(packet);
}
else
{
// invalid client
//CFK: This message seems to have served its usefullness as of 12-15 so I am commenting it out for now
//m_log.Warn("[UDPSERVER]: Got a packet from an invalid client - " + packet.ToString());
}
}
catch (Exception ex)
{
m_log.Error("[UDPSERVER]: Exception in processing packet.");
m_log.Debug("[UDPSERVER]: Adding New Client");
try
{
AddNewClient(packet);
}
catch (Exception e3)
{
m_log.Error("[UDPSERVER]: Adding New Client threw exception " + e3.ToString());
Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
ReceivedData, null);
}
}
}
}
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);
}
}
}
}
}