diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/TCPJSONStream/TCPJsonWebSocketServer.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/TCPJSONStream/TCPJsonWebSocketServer.cs | 163 |
1 files changed, 163 insertions, 0 deletions
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 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Net; | ||
4 | using System.Net.Sockets; | ||
5 | using System.Reflection; | ||
6 | using System.Text; | ||
7 | using System.Threading; | ||
8 | using Nini.Config; | ||
9 | using OpenSim.Framework; | ||
10 | using OpenSim.Region.Framework.Scenes; | ||
11 | using log4net; | ||
12 | |||
13 | namespace OpenSim.Region.ClientStack.TCPJSONStream | ||
14 | { | ||
15 | public delegate void ExceptionHandler(object source, Exception exception); | ||
16 | |||
17 | public class TCPJsonWebSocketServer | ||
18 | { | ||
19 | private readonly IPAddress _address; | ||
20 | private readonly int _port; | ||
21 | private readonly ManualResetEvent _shutdownEvent = new ManualResetEvent(false); | ||
22 | private TcpListener _listener; | ||
23 | private int _pendingAccepts; | ||
24 | private bool _shutdown; | ||
25 | private int _backlogAcceptQueueLength = 5; | ||
26 | private Scene m_scene; | ||
27 | private Location m_location; | ||
28 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
29 | |||
30 | public event EventHandler<ClientAcceptedEventArgs> Accepted = delegate { }; | ||
31 | |||
32 | |||
33 | public TCPJsonWebSocketServer(IPAddress _listenIP, ref uint port, int proxyPortOffsetParm, | ||
34 | bool allow_alternate_port, IConfigSource configSource, | ||
35 | AgentCircuitManager authenticateClass) | ||
36 | { | ||
37 | _address = _listenIP; | ||
38 | _port = (int)port; //Why is a uint passed in? | ||
39 | } | ||
40 | public void Stop() | ||
41 | { | ||
42 | _shutdown = true; | ||
43 | _listener.Stop(); | ||
44 | if (!_shutdownEvent.WaitOne()) | ||
45 | m_log.Error("[WEBSOCKETSERVER]: Failed to shutdown listener properly."); | ||
46 | _listener = null; | ||
47 | } | ||
48 | |||
49 | public bool HandlesRegion(Location x) | ||
50 | { | ||
51 | return x == m_location; | ||
52 | } | ||
53 | |||
54 | public void AddScene(IScene scene) | ||
55 | { | ||
56 | if (m_scene != null) | ||
57 | { | ||
58 | m_log.Debug("[WEBSOCKETSERVER]: AddScene() called but I already have a scene."); | ||
59 | return; | ||
60 | } | ||
61 | if (!(scene is Scene)) | ||
62 | { | ||
63 | m_log.Error("[WEBSOCKETSERVER]: AddScene() called with an unrecognized scene type " + scene.GetType()); | ||
64 | return; | ||
65 | } | ||
66 | |||
67 | m_scene = (Scene)scene; | ||
68 | m_location = new Location(m_scene.RegionInfo.RegionHandle); | ||
69 | } | ||
70 | |||
71 | public void Start() | ||
72 | { | ||
73 | _listener = new TcpListener(_address, _port); | ||
74 | _listener.Start(_backlogAcceptQueueLength); | ||
75 | Interlocked.Increment(ref _pendingAccepts); | ||
76 | _listener.BeginAcceptSocket(OnAccept, null); | ||
77 | } | ||
78 | |||
79 | private void OnAccept(IAsyncResult ar) | ||
80 | { | ||
81 | bool beginAcceptCalled = false; | ||
82 | try | ||
83 | { | ||
84 | int count = Interlocked.Decrement(ref _pendingAccepts); | ||
85 | if (_shutdown) | ||
86 | { | ||
87 | if (count == 0) | ||
88 | _shutdownEvent.Set(); | ||
89 | return; | ||
90 | } | ||
91 | Interlocked.Increment(ref _pendingAccepts); | ||
92 | _listener.BeginAcceptSocket(OnAccept, null); | ||
93 | beginAcceptCalled = true; | ||
94 | Socket socket = _listener.EndAcceptSocket(ar); | ||
95 | if (!OnAcceptingSocket(socket)) | ||
96 | { | ||
97 | socket.Disconnect(true); | ||
98 | return; | ||
99 | } | ||
100 | ClientNetworkContext context = new ClientNetworkContext((IPEndPoint) socket.RemoteEndPoint, _port, | ||
101 | new NetworkStream(socket), 16384, socket); | ||
102 | HttpRequestParser parser; | ||
103 | context.BeginRead(); | ||
104 | |||
105 | } | ||
106 | catch (Exception err) | ||
107 | { | ||
108 | if (ExceptionThrown == null) | ||
109 | #if DEBUG | ||
110 | throw; | ||
111 | #else | ||
112 | _logWriter.Write(this, LogPrio.Fatal, err.Message); | ||
113 | // we can't really do anything but close the connection | ||
114 | #endif | ||
115 | if (ExceptionThrown != null) | ||
116 | ExceptionThrown(this, err); | ||
117 | |||
118 | if (!beginAcceptCalled) | ||
119 | RetryBeginAccept(); | ||
120 | |||
121 | } | ||
122 | } | ||
123 | |||
124 | private void RetryBeginAccept() | ||
125 | { | ||
126 | try | ||
127 | { | ||
128 | |||
129 | _listener.BeginAcceptSocket(OnAccept, null); | ||
130 | } | ||
131 | catch (Exception err) | ||
132 | { | ||
133 | |||
134 | if (ExceptionThrown == null) | ||
135 | #if DEBUG | ||
136 | throw; | ||
137 | #else | ||
138 | // we can't really do anything but close the connection | ||
139 | #endif | ||
140 | if (ExceptionThrown != null) | ||
141 | ExceptionThrown(this, err); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | private bool OnAcceptingSocket(Socket sock) | ||
146 | { | ||
147 | ClientAcceptedEventArgs args = new ClientAcceptedEventArgs(sock); | ||
148 | Accepted(this, args); | ||
149 | return !args.Revoked; | ||
150 | } | ||
151 | /// <summary> | ||
152 | /// Catch exceptions not handled by the listener. | ||
153 | /// </summary> | ||
154 | /// <remarks> | ||
155 | /// Exceptions will be thrown during debug mode if this event is not used, | ||
156 | /// exceptions will be printed to console and suppressed during release mode. | ||
157 | /// </remarks> | ||
158 | public event ExceptionHandler ExceptionThrown = delegate { }; | ||
159 | |||
160 | |||
161 | |||
162 | } | ||
163 | } | ||