aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
authorteravus2013-02-03 06:49:17 -0500
committerteravus2013-02-03 06:49:17 -0500
commit27a0b3ecbdcf248b331742c7b2771d2a87dc8c3a (patch)
tree13d597bd5a621b1b3a0d104fd870c4416aafcfe3 /OpenSim/Region/ClientStack
parentSit and Spin reduction. If sitting, slam avatar angular velocity to zero. (diff)
downloadopensim-SC-27a0b3ecbdcf248b331742c7b2771d2a87dc8c3a.zip
opensim-SC-27a0b3ecbdcf248b331742c7b2771d2a87dc8c3a.tar.gz
opensim-SC-27a0b3ecbdcf248b331742c7b2771d2a87dc8c3a.tar.bz2
opensim-SC-27a0b3ecbdcf248b331742c7b2771d2a87dc8c3a.tar.xz
Commit 1 in of this branch feature. This is one of many...
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/TCPJSONStream/ClientAcceptedEventArgs.cs50
-rw-r--r--OpenSim/Region/ClientStack/TCPJSONStream/ClientNetworkContext.cs143
-rw-r--r--OpenSim/Region/ClientStack/TCPJSONStream/DisconnectedEventArgs.cs17
-rw-r--r--OpenSim/Region/ClientStack/TCPJSONStream/OpenSimWebSocketBase.cs73
-rw-r--r--OpenSim/Region/ClientStack/TCPJSONStream/TCPJsonWebSocketServer.cs163
5 files changed, 446 insertions, 0 deletions
diff --git a/OpenSim/Region/ClientStack/TCPJSONStream/ClientAcceptedEventArgs.cs b/OpenSim/Region/ClientStack/TCPJSONStream/ClientAcceptedEventArgs.cs
new file mode 100644
index 0000000..a58eab1
--- /dev/null
+++ b/OpenSim/Region/ClientStack/TCPJSONStream/ClientAcceptedEventArgs.cs
@@ -0,0 +1,50 @@
1using System;
2using System.Net.Sockets;
3
4namespace OpenSim.Region.ClientStack.TCPJSONStream
5{
6 /// <summary>
7 /// Invoked when a client have been accepted by the <see cref="HttpListener"/>
8 /// </summary>
9 /// <remarks>
10 /// Can be used to revoke incoming connections
11 /// </remarks>
12 public class ClientAcceptedEventArgs : EventArgs
13 {
14 private readonly Socket _socket;
15 private bool _revoke;
16
17 /// <summary>
18 /// Initializes a new instance of the <see cref="ClientAcceptedEventArgs"/> class.
19 /// </summary>
20 /// <param name="socket">The socket.</param>
21 public ClientAcceptedEventArgs(Socket socket)
22 {
23 _socket = socket;
24 }
25
26 /// <summary>
27 /// Accepted socket.
28 /// </summary>
29 public Socket Socket
30 {
31 get { return _socket; }
32 }
33
34 /// <summary>
35 /// Client should be revoked.
36 /// </summary>
37 public bool Revoked
38 {
39 get { return _revoke; }
40 }
41
42 /// <summary>
43 /// Client may not be handled.
44 /// </summary>
45 public void Revoke()
46 {
47 _revoke = true;
48 }
49 }
50} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/TCPJSONStream/ClientNetworkContext.cs b/OpenSim/Region/ClientStack/TCPJSONStream/ClientNetworkContext.cs
new file mode 100644
index 0000000..591f817
--- /dev/null
+++ b/OpenSim/Region/ClientStack/TCPJSONStream/ClientNetworkContext.cs
@@ -0,0 +1,143 @@
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Net;
5using System.Net.Sockets;
6using System.Text;
7
8namespace OpenSim.Region.ClientStack.TCPJSONStream
9{
10 public class ClientNetworkContext
11 {
12 private Socket _socket;
13 private string _remoteAddress;
14 private string _remotePort;
15 private WebSocketConnectionStage _wsConnectionStatus = WebSocketConnectionStage.Accept;
16 private int _bytesLeft;
17 private NetworkStream _stream;
18 private byte[] _buffer;
19 public event EventHandler<DisconnectedEventArgs> Disconnected = delegate { };
20
21 public ClientNetworkContext(IPEndPoint endPoint, int port, Stream stream, int buffersize, Socket sock)
22 {
23 _socket = sock;
24 _remoteAddress = endPoint.Address.ToString();
25 _remotePort = port.ToString();
26 _stream = stream as NetworkStream;
27 _buffer = new byte[buffersize];
28
29
30 }
31
32 public void BeginRead()
33 {
34 _wsConnectionStatus = WebSocketConnectionStage.Http;
35 try
36 {
37 _stream.BeginRead(_buffer, 0, _buffer.Length, OnReceive, _wsConnectionStatus);
38 }
39 catch (IOException err)
40 {
41 //m_log.Debug(err.ToString());
42 }
43 }
44
45 private void OnReceive(IAsyncResult ar)
46 {
47 try
48 {
49 int bytesRead = _stream.EndRead(ar);
50 if (bytesRead == 0)
51 {
52
53 Disconnected(this, new DisconnectedEventArgs(SocketError.ConnectionReset));
54 return;
55 }
56
57 }
58 }
59 /// <summary>
60 /// send a whole buffer
61 /// </summary>
62 /// <param name="buffer">buffer to send</param>
63 /// <exception cref="ArgumentNullException"></exception>
64 public void Send(byte[] buffer)
65 {
66 if (buffer == null)
67 throw new ArgumentNullException("buffer");
68 Send(buffer, 0, buffer.Length);
69 }
70
71 /// <summary>
72 /// Send data using the stream
73 /// </summary>
74 /// <param name="buffer">Contains data to send</param>
75 /// <param name="offset">Start position in buffer</param>
76 /// <param name="size">number of bytes to send</param>
77 /// <exception cref="ArgumentNullException"></exception>
78 /// <exception cref="ArgumentOutOfRangeException"></exception>
79 public void Send(byte[] buffer, int offset, int size)
80 {
81
82 if (offset + size > buffer.Length)
83 throw new ArgumentOutOfRangeException("offset", offset, "offset + size is beyond end of buffer.");
84
85 if (_stream != null && _stream.CanWrite)
86 {
87 try
88 {
89 _stream.Write(buffer, offset, size);
90 }
91 catch (IOException)
92 {
93
94 }
95 }
96
97 }
98 private void Reset()
99 {
100 if (_stream == null)
101 return;
102 _stream.Dispose();
103 _stream = null;
104 if (_socket == null)
105 return;
106 if (_socket.Connected)
107 _socket.Disconnect(true);
108 _socket = null;
109 }
110 }
111
112 public enum WebSocketConnectionStage
113 {
114 Reuse,
115 Accept,
116 Http,
117 WebSocket,
118 Closed
119 }
120
121 public enum FrameOpCodesRFC6455
122 {
123 Continue = 0x0,
124 Text = 0x1,
125 Binary = 0x2,
126 Close = 0x8,
127 Ping = 0x9,
128 Pong = 0xA
129 }
130
131 public enum DataState
132 {
133 Empty = 0,
134 Waiting = 1,
135 Receiving = 2,
136 Complete = 3,
137 Closed = 4,
138 Ping = 5,
139 Pong = 6
140 }
141
142
143}
diff --git a/OpenSim/Region/ClientStack/TCPJSONStream/DisconnectedEventArgs.cs b/OpenSim/Region/ClientStack/TCPJSONStream/DisconnectedEventArgs.cs
new file mode 100644
index 0000000..32880cc
--- /dev/null
+++ b/OpenSim/Region/ClientStack/TCPJSONStream/DisconnectedEventArgs.cs
@@ -0,0 +1,17 @@
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Net.Sockets;
5using System.Text;
6
7namespace OpenSim.Region.ClientStack.TCPJSONStream
8{
9 public class DisconnectedEventArgs:EventArgs
10 {
11 public SocketError Error { get; private set; }
12 public DisconnectedEventArgs(SocketError err)
13 {
14 Error = err;
15 }
16 }
17}
diff --git a/OpenSim/Region/ClientStack/TCPJSONStream/OpenSimWebSocketBase.cs b/OpenSim/Region/ClientStack/TCPJSONStream/OpenSimWebSocketBase.cs
new file mode 100644
index 0000000..379438d
--- /dev/null
+++ b/OpenSim/Region/ClientStack/TCPJSONStream/OpenSimWebSocketBase.cs
@@ -0,0 +1,73 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Net;
30using Nini.Config;
31using OpenSim.Framework;
32
33namespace OpenSim.Region.ClientStack.TCPJSONStream
34{
35 public sealed class TCPJsonWebSocketBase : IClientNetworkServer
36 {
37 private TCPJsonWebSocketServer m_tcpServer;
38
39 public TCPJsonWebSocketBase()
40 {
41 }
42
43 public void Initialise(IPAddress _listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager authenticateClass)
44 {
45 m_tcpServer = new TCPJsonWebSocketServer(_listenIP,ref port, proxyPortOffsetParm, allow_alternate_port,configSource,authenticateClass);
46 }
47
48 public void NetworkStop()
49 {
50 m_tcpServer.Stop();
51 }
52
53 public bool HandlesRegion(Location x)
54 {
55 return m_tcpServer.HandlesRegion(x);
56 }
57
58 public void AddScene(IScene x)
59 {
60 m_tcpServer.AddScene(x);
61 }
62
63 public void Start()
64 {
65 m_tcpServer.Start();
66 }
67
68 public void Stop()
69 {
70 m_tcpServer.Stop();
71 }
72 }
73} \ No newline at end of file
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 @@
1using System;
2using System.Collections.Generic;
3using System.Net;
4using System.Net.Sockets;
5using System.Reflection;
6using System.Text;
7using System.Threading;
8using Nini.Config;
9using OpenSim.Framework;
10using OpenSim.Region.Framework.Scenes;
11using log4net;
12
13namespace 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}