From 27a0b3ecbdcf248b331742c7b2771d2a87dc8c3a Mon Sep 17 00:00:00 2001 From: teravus Date: Sun, 3 Feb 2013 06:49:17 -0500 Subject: Commit 1 in of this branch feature. This is one of many... --- .../TCPJSONStream/TCPJsonWebSocketServer.cs | 163 +++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 OpenSim/Region/ClientStack/TCPJSONStream/TCPJsonWebSocketServer.cs (limited to 'OpenSim/Region/ClientStack/TCPJSONStream/TCPJsonWebSocketServer.cs') diff --git a/OpenSim/Region/ClientStack/TCPJSONStream/TCPJsonWebSocketServer.cs b/OpenSim/Region/ClientStack/TCPJSONStream/TCPJsonWebSocketServer.cs new file mode 100644 index 0000000..0713bf4 --- /dev/null +++ b/OpenSim/Region/ClientStack/TCPJSONStream/TCPJsonWebSocketServer.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Text; +using System.Threading; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using log4net; + +namespace OpenSim.Region.ClientStack.TCPJSONStream +{ + public delegate void ExceptionHandler(object source, Exception exception); + + public class TCPJsonWebSocketServer + { + private readonly IPAddress _address; + private readonly int _port; + private readonly ManualResetEvent _shutdownEvent = new ManualResetEvent(false); + private TcpListener _listener; + private int _pendingAccepts; + private bool _shutdown; + private int _backlogAcceptQueueLength = 5; + private Scene m_scene; + private Location m_location; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public event EventHandler Accepted = delegate { }; + + + public TCPJsonWebSocketServer(IPAddress _listenIP, ref uint port, int proxyPortOffsetParm, + bool allow_alternate_port, IConfigSource configSource, + AgentCircuitManager authenticateClass) + { + _address = _listenIP; + _port = (int)port; //Why is a uint passed in? + } + public void Stop() + { + _shutdown = true; + _listener.Stop(); + if (!_shutdownEvent.WaitOne()) + m_log.Error("[WEBSOCKETSERVER]: Failed to shutdown listener properly."); + _listener = null; + } + + public bool HandlesRegion(Location x) + { + return x == m_location; + } + + public void AddScene(IScene scene) + { + if (m_scene != null) + { + m_log.Debug("[WEBSOCKETSERVER]: AddScene() called but I already have a scene."); + return; + } + if (!(scene is Scene)) + { + m_log.Error("[WEBSOCKETSERVER]: AddScene() called with an unrecognized scene type " + scene.GetType()); + return; + } + + m_scene = (Scene)scene; + m_location = new Location(m_scene.RegionInfo.RegionHandle); + } + + public void Start() + { + _listener = new TcpListener(_address, _port); + _listener.Start(_backlogAcceptQueueLength); + Interlocked.Increment(ref _pendingAccepts); + _listener.BeginAcceptSocket(OnAccept, null); + } + + private void OnAccept(IAsyncResult ar) + { + bool beginAcceptCalled = false; + try + { + int count = Interlocked.Decrement(ref _pendingAccepts); + if (_shutdown) + { + if (count == 0) + _shutdownEvent.Set(); + return; + } + Interlocked.Increment(ref _pendingAccepts); + _listener.BeginAcceptSocket(OnAccept, null); + beginAcceptCalled = true; + Socket socket = _listener.EndAcceptSocket(ar); + if (!OnAcceptingSocket(socket)) + { + socket.Disconnect(true); + return; + } + ClientNetworkContext context = new ClientNetworkContext((IPEndPoint) socket.RemoteEndPoint, _port, + new NetworkStream(socket), 16384, socket); + HttpRequestParser parser; + context.BeginRead(); + + } + catch (Exception err) + { + if (ExceptionThrown == null) +#if DEBUG + throw; +#else + _logWriter.Write(this, LogPrio.Fatal, err.Message); + // we can't really do anything but close the connection +#endif + if (ExceptionThrown != null) + ExceptionThrown(this, err); + + if (!beginAcceptCalled) + RetryBeginAccept(); + + } + } + + private void RetryBeginAccept() + { + try + { + + _listener.BeginAcceptSocket(OnAccept, null); + } + catch (Exception err) + { + + if (ExceptionThrown == null) +#if DEBUG + throw; +#else + // we can't really do anything but close the connection +#endif + if (ExceptionThrown != null) + ExceptionThrown(this, err); + } + } + + private bool OnAcceptingSocket(Socket sock) + { + ClientAcceptedEventArgs args = new ClientAcceptedEventArgs(sock); + Accepted(this, args); + return !args.Revoked; + } + /// + /// Catch exceptions not handled by the listener. + /// + /// + /// Exceptions will be thrown during debug mode if this event is not used, + /// exceptions will be printed to console and suppressed during release mode. + /// + public event ExceptionHandler ExceptionThrown = delegate { }; + + + + } +} -- cgit v1.1