/* * Copyright (c) Contributors, http://www.openmetaverse.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 System.Net.Sockets; using libsecondlife.Packets; using OpenSim.Assets; using OpenSim.Framework; using OpenSim.Framework.Console; using OpenSim.Framework.Interfaces; using OpenSim.Region.Caches; namespace OpenSim.Region.ClientStack { public class UDPServer : ClientStackNetworkHandler { protected Dictionary clientCircuits = 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 AsyncCallback ReceivedData; protected PacketServer _packetServer; protected int listenPort; protected IWorld m_localWorld; protected AssetCache m_assetCache; protected InventoryCache m_inventoryCache; protected LogBase m_log; protected AuthenticateSessionsBase m_authenticateSessionsClass; public PacketServer PacketServer { get { return _packetServer; } set { _packetServer = value; } } public IWorld LocalWorld { set { this.m_localWorld = value; this._packetServer.LocalWorld = this.m_localWorld; } } public UDPServer() { } public UDPServer(int port, AssetCache assetCache, InventoryCache inventoryCache, LogBase console, AuthenticateSessionsBase authenticateClass) { listenPort = port; this.m_assetCache = assetCache; this.m_inventoryCache = inventoryCache; this.m_log = console; this.m_authenticateSessionsClass = authenticateClass; this.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 = Server.EndReceiveFrom(result, ref epSender); int packetEnd = numBytes - 1; packet = Packet.BuildPacket(RecvBuffer, ref packetEnd, ZeroBuffer); // do we already have a circuit for this endpoint if (this.clientCircuits.ContainsKey(epSender)) { //if so then send packet to the packetserver this._packetServer.ClientInPacket(this.clientCircuits[epSender], packet); } else if (packet.Type == PacketType.UseCircuitCode) { // new client this.AddNewClient(packet); } else { // invalid client m_log.Warn("UDPServer.cs:OnReceivedData() - WARNING: Got a packet from an invalid client - " + epSender.ToString()); } Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null); } protected virtual void AddNewClient(Packet packet) { UseCircuitCodePacket useCircuit = (UseCircuitCodePacket)packet; this.clientCircuits.Add(epSender, useCircuit.CircuitCode.Code); this.PacketServer.AddNewClient(epSender, useCircuit, m_assetCache, m_inventoryCache, m_authenticateSessionsClass); } public void ServerListener() { m_log.Status("UDPServer.cs:ServerListener() - Opening UDP socket on " + listenPort); ServerIncoming = new IPEndPoint(IPAddress.Parse("0.0.0.0"), listenPort); Server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); Server.Bind(ServerIncoming); m_log.Verbose("UDPServer.cs:ServerListener() - UDP socket bound, getting ready to listen"); ipeSender = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0); epSender = (EndPoint)ipeSender; ReceivedData = new AsyncCallback(this.OnReceivedData); Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null); m_log.Verbose("UDPServer.cs:ServerListener() - Listening..."); } public virtual void RegisterPacketServer(PacketServer server) { this._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; foreach (KeyValuePair p in this.clientCircuits) { if (p.Value == circuitcode) { sendto = p.Key; break; } } if (sendto != null) { //we found the endpoint so send the packet to it this.Server.SendTo(buffer, size, flags, sendto); } } public virtual void RemoveClientCircuit(uint circuitcode) { foreach (KeyValuePair p in this.clientCircuits) { if (p.Value == circuitcode) { this.clientCircuits.Remove(p.Key); break; } } } } }