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/ClientAcceptedEventArgs.cs | 50 +++++++
.../TCPJSONStream/ClientNetworkContext.cs | 143 ++++++++++++++++++
.../TCPJSONStream/DisconnectedEventArgs.cs | 17 +++
.../TCPJSONStream/OpenSimWebSocketBase.cs | 73 +++++++++
.../TCPJSONStream/TCPJsonWebSocketServer.cs | 163 +++++++++++++++++++++
5 files changed, 446 insertions(+)
create mode 100644 OpenSim/Region/ClientStack/TCPJSONStream/ClientAcceptedEventArgs.cs
create mode 100644 OpenSim/Region/ClientStack/TCPJSONStream/ClientNetworkContext.cs
create mode 100644 OpenSim/Region/ClientStack/TCPJSONStream/DisconnectedEventArgs.cs
create mode 100644 OpenSim/Region/ClientStack/TCPJSONStream/OpenSimWebSocketBase.cs
create mode 100644 OpenSim/Region/ClientStack/TCPJSONStream/TCPJsonWebSocketServer.cs
(limited to 'OpenSim')
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 @@
+using System;
+using System.Net.Sockets;
+
+namespace OpenSim.Region.ClientStack.TCPJSONStream
+{
+ ///
+ /// Invoked when a client have been accepted by the
+ ///
+ ///
+ /// Can be used to revoke incoming connections
+ ///
+ public class ClientAcceptedEventArgs : EventArgs
+ {
+ private readonly Socket _socket;
+ private bool _revoke;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The socket.
+ public ClientAcceptedEventArgs(Socket socket)
+ {
+ _socket = socket;
+ }
+
+ ///
+ /// Accepted socket.
+ ///
+ public Socket Socket
+ {
+ get { return _socket; }
+ }
+
+ ///
+ /// Client should be revoked.
+ ///
+ public bool Revoked
+ {
+ get { return _revoke; }
+ }
+
+ ///
+ /// Client may not be handled.
+ ///
+ public void Revoke()
+ {
+ _revoke = true;
+ }
+ }
+}
\ 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 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+
+namespace OpenSim.Region.ClientStack.TCPJSONStream
+{
+ public class ClientNetworkContext
+ {
+ private Socket _socket;
+ private string _remoteAddress;
+ private string _remotePort;
+ private WebSocketConnectionStage _wsConnectionStatus = WebSocketConnectionStage.Accept;
+ private int _bytesLeft;
+ private NetworkStream _stream;
+ private byte[] _buffer;
+ public event EventHandler Disconnected = delegate { };
+
+ public ClientNetworkContext(IPEndPoint endPoint, int port, Stream stream, int buffersize, Socket sock)
+ {
+ _socket = sock;
+ _remoteAddress = endPoint.Address.ToString();
+ _remotePort = port.ToString();
+ _stream = stream as NetworkStream;
+ _buffer = new byte[buffersize];
+
+
+ }
+
+ public void BeginRead()
+ {
+ _wsConnectionStatus = WebSocketConnectionStage.Http;
+ try
+ {
+ _stream.BeginRead(_buffer, 0, _buffer.Length, OnReceive, _wsConnectionStatus);
+ }
+ catch (IOException err)
+ {
+ //m_log.Debug(err.ToString());
+ }
+ }
+
+ private void OnReceive(IAsyncResult ar)
+ {
+ try
+ {
+ int bytesRead = _stream.EndRead(ar);
+ if (bytesRead == 0)
+ {
+
+ Disconnected(this, new DisconnectedEventArgs(SocketError.ConnectionReset));
+ return;
+ }
+
+ }
+ }
+ ///
+ /// send a whole buffer
+ ///
+ /// buffer to send
+ ///
+ public void Send(byte[] buffer)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException("buffer");
+ Send(buffer, 0, buffer.Length);
+ }
+
+ ///
+ /// Send data using the stream
+ ///
+ /// Contains data to send
+ /// Start position in buffer
+ /// number of bytes to send
+ ///
+ ///
+ public void Send(byte[] buffer, int offset, int size)
+ {
+
+ if (offset + size > buffer.Length)
+ throw new ArgumentOutOfRangeException("offset", offset, "offset + size is beyond end of buffer.");
+
+ if (_stream != null && _stream.CanWrite)
+ {
+ try
+ {
+ _stream.Write(buffer, offset, size);
+ }
+ catch (IOException)
+ {
+
+ }
+ }
+
+ }
+ private void Reset()
+ {
+ if (_stream == null)
+ return;
+ _stream.Dispose();
+ _stream = null;
+ if (_socket == null)
+ return;
+ if (_socket.Connected)
+ _socket.Disconnect(true);
+ _socket = null;
+ }
+ }
+
+ public enum WebSocketConnectionStage
+ {
+ Reuse,
+ Accept,
+ Http,
+ WebSocket,
+ Closed
+ }
+
+ public enum FrameOpCodesRFC6455
+ {
+ Continue = 0x0,
+ Text = 0x1,
+ Binary = 0x2,
+ Close = 0x8,
+ Ping = 0x9,
+ Pong = 0xA
+ }
+
+ public enum DataState
+ {
+ Empty = 0,
+ Waiting = 1,
+ Receiving = 2,
+ Complete = 3,
+ Closed = 4,
+ Ping = 5,
+ Pong = 6
+ }
+
+
+}
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 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Sockets;
+using System.Text;
+
+namespace OpenSim.Region.ClientStack.TCPJSONStream
+{
+ public class DisconnectedEventArgs:EventArgs
+ {
+ public SocketError Error { get; private set; }
+ public DisconnectedEventArgs(SocketError err)
+ {
+ Error = err;
+ }
+ }
+}
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 @@
+/*
+ * 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 OpenSimulator 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 Nini.Config;
+using OpenSim.Framework;
+
+namespace OpenSim.Region.ClientStack.TCPJSONStream
+{
+ public sealed class TCPJsonWebSocketBase : IClientNetworkServer
+ {
+ private TCPJsonWebSocketServer m_tcpServer;
+
+ public TCPJsonWebSocketBase()
+ {
+ }
+
+ public void Initialise(IPAddress _listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager authenticateClass)
+ {
+ m_tcpServer = new TCPJsonWebSocketServer(_listenIP,ref port, proxyPortOffsetParm, allow_alternate_port,configSource,authenticateClass);
+ }
+
+ public void NetworkStop()
+ {
+ m_tcpServer.Stop();
+ }
+
+ public bool HandlesRegion(Location x)
+ {
+ return m_tcpServer.HandlesRegion(x);
+ }
+
+ public void AddScene(IScene x)
+ {
+ m_tcpServer.AddScene(x);
+ }
+
+ public void Start()
+ {
+ m_tcpServer.Start();
+ }
+
+ public void Stop()
+ {
+ m_tcpServer.Stop();
+ }
+ }
+}
\ 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 @@
+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
From d18fbb98b7f51d46eb3e716c59a8e76bc772bad1 Mon Sep 17 00:00:00 2001
From: teravus
Date: Sun, 3 Feb 2013 07:44:45 -0500
Subject: Adds the ability to load more then one IClientNetworkServer thereby
allowing additional client stacks. Use comma separated values in
clientstack_plugin in your config.
---
OpenSim/Region/Application/OpenSimBase.cs | 37 ++++++----
OpenSim/Region/ClientStack/ClientStackManager.cs | 83 +++++++++++++---------
.../TCPJSONStream/ClientNetworkContext.cs | 3 +
.../TCPJSONStream/TCPJsonWebSocketServer.cs | 2 +-
4 files changed, 77 insertions(+), 48 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index c3c87e7..f5c06df 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -316,7 +316,7 @@ namespace OpenSim
///
///
///
- public IClientNetworkServer CreateRegion(RegionInfo regionInfo, bool portadd_flag, out IScene scene)
+ public List CreateRegion(RegionInfo regionInfo, bool portadd_flag, out IScene scene)
{
return CreateRegion(regionInfo, portadd_flag, false, out scene);
}
@@ -326,7 +326,7 @@ namespace OpenSim
///
///
///
- public IClientNetworkServer CreateRegion(RegionInfo regionInfo, out IScene scene)
+ public List CreateRegion(RegionInfo regionInfo, out IScene scene)
{
return CreateRegion(regionInfo, false, true, out scene);
}
@@ -338,7 +338,7 @@ namespace OpenSim
///
///
///
- public IClientNetworkServer CreateRegion(RegionInfo regionInfo, bool portadd_flag, bool do_post_init, out IScene mscene)
+ public List CreateRegion(RegionInfo regionInfo, bool portadd_flag, bool do_post_init, out IScene mscene)
{
int port = regionInfo.InternalEndPoint.Port;
@@ -363,8 +363,8 @@ namespace OpenSim
Util.XmlRpcCommand(proxyUrl, "AddPort", port, port + proxyOffset, regionInfo.ExternalHostName);
}
- IClientNetworkServer clientServer;
- Scene scene = SetupScene(regionInfo, proxyOffset, Config, out clientServer);
+ List clientServers;
+ Scene scene = SetupScene(regionInfo, proxyOffset, Config, out clientServers);
m_log.Info("[MODULES]: Loading Region's modules (old style)");
@@ -414,8 +414,11 @@ namespace OpenSim
if (m_autoCreateClientStack)
{
- m_clientServers.Add(clientServer);
- clientServer.Start();
+ foreach (IClientNetworkServer clientserver in clientServers)
+ {
+ m_clientServers.Add(clientserver);
+ clientserver.Start();
+ }
}
scene.EventManager.OnShutdown += delegate() { ShutdownRegion(scene); };
@@ -425,7 +428,7 @@ namespace OpenSim
scene.Start();
scene.StartScripts();
- return clientServer;
+ return clientServers;
}
///
@@ -641,7 +644,7 @@ namespace OpenSim
///
///
///
- protected Scene SetupScene(RegionInfo regionInfo, out IClientNetworkServer clientServer)
+ protected Scene SetupScene(RegionInfo regionInfo, out List clientServer)
{
return SetupScene(regionInfo, 0, null, out clientServer);
}
@@ -655,19 +658,20 @@ namespace OpenSim
///
///
protected Scene SetupScene(
- RegionInfo regionInfo, int proxyOffset, IConfigSource configSource, out IClientNetworkServer clientServer)
+ RegionInfo regionInfo, int proxyOffset, IConfigSource configSource, out List clientServer)
{
+ List clientNetworkServers = null;
+
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;
-
+ IClientNetworkServer clientNetworkServer;
if (m_autoCreateClientStack)
{
- clientServer
- = m_clientStackManager.CreateServer(
+ clientNetworkServers = m_clientStackManager.CreateServers(
listenIP, ref port, proxyOffset, regionInfo.m_allow_alternate_ports, configSource,
circuitManager);
}
@@ -682,9 +686,12 @@ namespace OpenSim
if (m_autoCreateClientStack)
{
- clientServer.AddScene(scene);
+ foreach (IClientNetworkServer clientnetserver in clientNetworkServers)
+ {
+ clientnetserver.AddScene(scene);
+ }
}
-
+ clientServer = clientNetworkServers;
scene.LoadWorldMap();
scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName);
diff --git a/OpenSim/Region/ClientStack/ClientStackManager.cs b/OpenSim/Region/ClientStack/ClientStackManager.cs
index 84ea0b3..299aabd 100644
--- a/OpenSim/Region/ClientStack/ClientStackManager.cs
+++ b/OpenSim/Region/ClientStack/ClientStackManager.cs
@@ -26,6 +26,7 @@
*/
using System;
+using System.Collections.Generic;
using System.Net;
using System.Reflection;
using log4net;
@@ -38,39 +39,53 @@ namespace OpenSim.Region.ClientStack
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private Type plugin;
- private Assembly pluginAssembly;
+ private List plugin = new List();
+ private List pluginAssembly = new List();
- public ClientStackManager(string dllName)
+ public ClientStackManager(string pDllName)
{
- m_log.Info("[CLIENTSTACK]: Attempting to load " + dllName);
-
- try
+ List clientstacks = new List();
+ if (pDllName.Contains(","))
+ {
+ clientstacks = new List(pDllName.Split(','));
+ }
+ else
{
- plugin = null;
- pluginAssembly = Assembly.LoadFrom(dllName);
+ clientstacks.Add(pDllName);
+ }
+ foreach (string dllName in clientstacks)
+ {
+ m_log.Info("[CLIENTSTACK]: Attempting to load " + dllName);
- foreach (Type pluginType in pluginAssembly.GetTypes())
+ try
{
- if (pluginType.IsPublic)
- {
- Type typeInterface = pluginType.GetInterface("IClientNetworkServer", true);
+ //plugin = null;
+ Assembly itemAssembly = Assembly.LoadFrom(dllName);
+ pluginAssembly.Add(itemAssembly);
- if (typeInterface != null)
+ foreach (Type pluginType in itemAssembly.GetTypes())
+ {
+ if (pluginType.IsPublic)
{
- m_log.Info("[CLIENTSTACK]: Added IClientNetworkServer Interface");
- plugin = pluginType;
- return;
+ Type typeInterface = pluginType.GetInterface("IClientNetworkServer", true);
+
+ if (typeInterface != null)
+ {
+ m_log.Info("[CLIENTSTACK]: Added IClientNetworkServer Interface");
+ plugin.Add(pluginType);
+ break;
+ }
}
}
}
- } catch (ReflectionTypeLoadException e)
- {
- foreach (Exception e2 in e.LoaderExceptions)
+ catch (ReflectionTypeLoadException e)
{
- m_log.Error(e2.ToString());
+ foreach (Exception e2 in e.LoaderExceptions)
+ {
+ m_log.Error(e2.ToString());
+ }
+ throw e;
}
- throw e;
}
}
@@ -84,11 +99,11 @@ namespace OpenSim.Region.ClientStack
///
///
///
- public IClientNetworkServer CreateServer(
+ public List CreateServers(
IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port,
AgentCircuitManager authenticateClass)
{
- return CreateServer(
+ return CreateServers(
_listenIP, ref port, proxyPortOffset, allow_alternate_port, null, authenticateClass);
}
@@ -105,20 +120,24 @@ namespace OpenSim.Region.ClientStack
///
///
///
- public IClientNetworkServer CreateServer(
+ public List CreateServers(
IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, IConfigSource configSource,
AgentCircuitManager authenticateClass)
{
+ List servers = new List();
if (plugin != null)
{
- IClientNetworkServer server =
- (IClientNetworkServer)Activator.CreateInstance(pluginAssembly.GetType(plugin.ToString()));
-
- server.Initialise(
- _listenIP, ref port, proxyPortOffset, allow_alternate_port,
- configSource, authenticateClass);
-
- return server;
+ for (int i = 0; i < plugin.Count; i++)
+ {
+ IClientNetworkServer server =
+ (IClientNetworkServer) Activator.CreateInstance(pluginAssembly[i].GetType(plugin[i].ToString()));
+
+ server.Initialise(
+ _listenIP, ref port, proxyPortOffset, allow_alternate_port,
+ configSource, authenticateClass);
+ servers.Add(server);
+ }
+ return servers;
}
m_log.Error("[CLIENTSTACK]: Couldn't initialize a new server");
diff --git a/OpenSim/Region/ClientStack/TCPJSONStream/ClientNetworkContext.cs b/OpenSim/Region/ClientStack/TCPJSONStream/ClientNetworkContext.cs
index 591f817..b077b6a 100644
--- a/OpenSim/Region/ClientStack/TCPJSONStream/ClientNetworkContext.cs
+++ b/OpenSim/Region/ClientStack/TCPJSONStream/ClientNetworkContext.cs
@@ -55,6 +55,9 @@ namespace OpenSim.Region.ClientStack.TCPJSONStream
}
}
+ catch (Exception)
+ {
+ }
}
///
/// send a whole buffer
diff --git a/OpenSim/Region/ClientStack/TCPJSONStream/TCPJsonWebSocketServer.cs b/OpenSim/Region/ClientStack/TCPJSONStream/TCPJsonWebSocketServer.cs
index 0713bf4..c0f6792 100644
--- a/OpenSim/Region/ClientStack/TCPJSONStream/TCPJsonWebSocketServer.cs
+++ b/OpenSim/Region/ClientStack/TCPJSONStream/TCPJsonWebSocketServer.cs
@@ -99,7 +99,7 @@ namespace OpenSim.Region.ClientStack.TCPJSONStream
}
ClientNetworkContext context = new ClientNetworkContext((IPEndPoint) socket.RemoteEndPoint, _port,
new NetworkStream(socket), 16384, socket);
- HttpRequestParser parser;
+ //HttpRequestParser parser;
context.BeginRead();
}
--
cgit v1.1
From 1dc09d8e8f4a6caa321d0227722af97ee4aeed6a Mon Sep 17 00:00:00 2001
From: teravus
Date: Tue, 5 Feb 2013 18:02:25 -0500
Subject: We're not really done here.. but we're getting there. Socket Read
is working.. Still have to do Header.ToBytes and compose a websocket frame
with a payload.
---
.../Framework/Servers/HttpServer/BaseHttpServer.cs | 38 +++++++++++++++++++++-
OpenSim/Framework/Servers/Tests/OSHttpTests.cs | 5 +++
.../TCPJSONStream/OpenSimWebSocketBase.cs | 6 ++--
3 files changed, 45 insertions(+), 4 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index b24336d..dcfe99a 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -54,6 +54,8 @@ namespace OpenSim.Framework.Servers.HttpServer
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
+ public delegate void WebSocketRequestDelegate(string servicepath, WebSocketHTTPServerHandler handler);
+
///
/// Gets or sets the debug level.
///
@@ -87,6 +89,9 @@ namespace OpenSim.Framework.Servers.HttpServer
protected Dictionary m_pollHandlers =
new Dictionary();
+ protected Dictionary m_WebSocketHandlers =
+ new Dictionary();
+
protected uint m_port;
protected uint m_sslport;
protected bool m_ssl;
@@ -170,6 +175,22 @@ namespace OpenSim.Framework.Servers.HttpServer
}
}
+ public void AddWebSocketHandler(string servicepath, WebSocketRequestDelegate handler)
+ {
+ lock (m_WebSocketHandlers)
+ {
+ if (!m_WebSocketHandlers.ContainsKey(servicepath))
+ m_WebSocketHandlers.Add(servicepath, handler);
+ }
+ }
+
+ public void RemoveWebSocketHandler(string servicepath)
+ {
+ lock (m_WebSocketHandlers)
+ if (m_WebSocketHandlers.ContainsKey(servicepath))
+ m_WebSocketHandlers.Remove(servicepath);
+ }
+
public List GetStreamHandlerKeys()
{
lock (m_streamHandlers)
@@ -409,9 +430,24 @@ namespace OpenSim.Framework.Servers.HttpServer
public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
{
+
OSHttpRequest req = new OSHttpRequest(context, request);
+ WebSocketRequestDelegate dWebSocketRequestDelegate = null;
+ lock (m_WebSocketHandlers)
+ {
+ if (m_WebSocketHandlers.ContainsKey(req.RawUrl))
+ dWebSocketRequestDelegate = m_WebSocketHandlers[req.RawUrl];
+ }
+ if (dWebSocketRequestDelegate != null)
+ {
+ dWebSocketRequestDelegate(req.Url.AbsolutePath, new WebSocketHTTPServerHandler(req, context, 16384));
+ return;
+ }
+
OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
+
HandleRequest(req, resp);
+
// !!!HACK ALERT!!!
// There seems to be a bug in the underlying http code that makes subsequent requests
@@ -500,7 +536,7 @@ namespace OpenSim.Framework.Servers.HttpServer
LogIncomingToStreamHandler(request, requestHandler);
response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
-
+
if (requestHandler is IStreamedRequestHandler)
{
IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler;
diff --git a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
index 3412e0f..5b912b4 100644
--- a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
+++ b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
@@ -70,6 +70,11 @@ namespace OpenSim.Framework.Servers.Tests
public void Close() { }
public bool EndWhenDone { get { return false;} set { return;}}
+ public HTTPNetworkContext GiveMeTheNetworkStreamIKnowWhatImDoing()
+ {
+ return new HTTPNetworkContext();
+ }
+
public event EventHandler Disconnected = delegate { };
///
/// A request have been received in the context.
diff --git a/OpenSim/Region/ClientStack/TCPJSONStream/OpenSimWebSocketBase.cs b/OpenSim/Region/ClientStack/TCPJSONStream/OpenSimWebSocketBase.cs
index 379438d..6d02543 100644
--- a/OpenSim/Region/ClientStack/TCPJSONStream/OpenSimWebSocketBase.cs
+++ b/OpenSim/Region/ClientStack/TCPJSONStream/OpenSimWebSocketBase.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.ClientStack.TCPJSONStream
public void NetworkStop()
{
- m_tcpServer.Stop();
+ // m_tcpServer.Stop();
}
public bool HandlesRegion(Location x)
@@ -62,12 +62,12 @@ namespace OpenSim.Region.ClientStack.TCPJSONStream
public void Start()
{
- m_tcpServer.Start();
+ //m_tcpServer.Start();
}
public void Stop()
{
- m_tcpServer.Stop();
+ // m_tcpServer.Stop();
}
}
}
\ No newline at end of file
--
cgit v1.1
From 0baa2590bef8ad4e0a78a7c88d55acd0848e0068 Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Wed, 6 Feb 2013 15:52:28 -0800
Subject: BulletSim: check for completely degenerate meshes (ones with all
triangles having zero width) and output an error rather than throwing and
exception.
---
.../Physics/BulletSPlugin/BSShapeCollection.cs | 28 +++++++++++++++-------
1 file changed, 19 insertions(+), 9 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index fe0f984..15747c9 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -608,7 +608,7 @@ public sealed class BSShapeCollection : IDisposable
// Since we're recreating new, get rid of the reference to the previous shape
DereferenceShape(prim.PhysShape, shapeCallback);
- newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod);
+ newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod);
// Take evasive action if the mesh was not constructed.
newShape = VerifyMeshCreated(newShape, prim);
@@ -619,7 +619,7 @@ public sealed class BSShapeCollection : IDisposable
return true; // 'true' means a new shape has been added to this prim
}
- private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
+ private BulletShape CreatePhysicalMesh(BSPhysObject prim, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
{
BulletShape newShape = new BulletShape();
@@ -631,7 +631,7 @@ public sealed class BSShapeCollection : IDisposable
}
else
{
- IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod,
+ IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
false, // say it is not physical so a bounding box is not built
false // do not cache the mesh and do not use previously built versions
);
@@ -651,18 +651,20 @@ public sealed class BSShapeCollection : IDisposable
realIndicesIndex = 0;
for (int tri = 0; tri < indices.Length; tri += 3)
{
+ // Compute displacements into vertex array for each vertex of the triangle
int v1 = indices[tri + 0] * 3;
int v2 = indices[tri + 1] * 3;
int v3 = indices[tri + 2] * 3;
- if (!((verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
+ // Check to see if any two of the vertices are the same
+ if (!( ( verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
&& verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1]
&& verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2])
- || (verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
+ || ( verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
&& verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1]
&& verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2])
- || (verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
+ || ( verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
&& verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1]
- && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]))
+ && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) )
)
{
// None of the vertices of the triangles are the same. This is a good triangle;
@@ -676,8 +678,16 @@ public sealed class BSShapeCollection : IDisposable
DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}",
BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
- newShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World,
- realIndicesIndex, indices, verticesAsFloats.Length/3, verticesAsFloats);
+ if (realIndicesIndex != 0)
+ {
+ newShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World,
+ realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
+ }
+ else
+ {
+ PhysicsScene.Logger.ErrorFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}",
+ LogHeader, prim.PhysObjectName, prim.RawPosition, PhysicsScene.Name);
+ }
}
}
newShape.shapeKey = newMeshKey;
--
cgit v1.1
From d2ece00e68c070bf9ffbda3f76e4eccf3c33545f Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Wed, 6 Feb 2013 15:59:59 -0800
Subject: BulletSim: set removing zero width triangles in meshes to be enabled
by default. This should fix the invisible barrier in sculptie doorways bug.
---
OpenSim/Region/Physics/BulletSPlugin/BSParam.cs | 2 +-
OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 306928a..965c382 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -220,7 +220,7 @@ public static class BSParam
(s) => { return BSParam.NumericBool(ShouldUseHullsForPhysicalObjects); },
(s,p,l,v) => { ShouldUseHullsForPhysicalObjects = BSParam.BoolNumeric(v); } ),
new ParameterDefn("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes",
- ConfigurationParameters.numericFalse,
+ ConfigurationParameters.numericTrue,
(s,cf,p,v) => { ShouldRemoveZeroWidthTriangles = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
(s) => { return BSParam.NumericBool(ShouldRemoveZeroWidthTriangles); },
(s,p,l,v) => { ShouldRemoveZeroWidthTriangles = BSParam.BoolNumeric(v); } ),
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 823402b..ec25aa9 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -75,6 +75,7 @@ public abstract class BSPhysObject : PhysicsActor
PhysicsScene = parentScene;
LocalID = localID;
PhysObjectName = name;
+ Name = name; // PhysicsActor also has the name of the object. Someday consolidate.
TypeName = typeName;
// We don't have any physical representation yet.
--
cgit v1.1
From e2c1e37b077bad2d1b6d0ac5277c3f9001d819dd Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Thu, 7 Feb 2013 00:15:50 +0000
Subject: Add key length validation to DAMap.Add(KeyValuePair
kvp) to match Add(string key, OSDMap store)
---
OpenSim/Framework/DAMap.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Framework/DAMap.cs b/OpenSim/Framework/DAMap.cs
index 291c8b8..dd9c61b 100644
--- a/OpenSim/Framework/DAMap.cs
+++ b/OpenSim/Framework/DAMap.cs
@@ -188,7 +188,8 @@ namespace OpenSim.Framework
}
public void Add(KeyValuePair kvp)
- {
+ {
+ ValidateKey(kvp.Key);
lock (this)
m_map.Add(kvp.Key, kvp.Value);
}
--
cgit v1.1
From c8c5d74c22056deb0b079d0651c005d610626f66 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Thu, 7 Feb 2013 00:22:39 +0000
Subject: minor: add method doc to DAMap.ValidateKey()
---
OpenSim/Framework/DAMap.cs | 4 ++++
1 file changed, 4 insertions(+)
(limited to 'OpenSim')
diff --git a/OpenSim/Framework/DAMap.cs b/OpenSim/Framework/DAMap.cs
index dd9c61b..24e0895 100644
--- a/OpenSim/Framework/DAMap.cs
+++ b/OpenSim/Framework/DAMap.cs
@@ -168,6 +168,10 @@ namespace OpenSim.Framework
}
}
+ ///
+ /// Validate the key used for storing separate data stores.
+ ///
+ ///
private static void ValidateKey(string key)
{
if (key.Length < MIN_STORE_NAME_LENGTH)
--
cgit v1.1
From df37738ce7702774c4d3ff1f3835bfe87e0f1a5e Mon Sep 17 00:00:00 2001
From: Dan Lake
Date: Wed, 6 Feb 2013 16:42:55 -0800
Subject: WebStats will now use actual logfile as specified in
OpenSim.exe.config rather than hardcoded ./OpenSim.log. This allows for
rotating logs and other file appender types
---
OpenSim/Framework/Util.cs | 16 +++++++++++++++-
OpenSim/Region/UserStatistics/WebStatsModule.cs | 2 +-
2 files changed, 16 insertions(+), 2 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 9b1e97d..d9148fb 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -45,6 +45,7 @@ using System.Text.RegularExpressions;
using System.Xml;
using System.Threading;
using log4net;
+using log4net.Appender;
using Nini.Config;
using Nwc.XmlRpc;
using OpenMetaverse;
@@ -816,9 +817,22 @@ namespace OpenSim.Framework
return ".";
}
+ public static string logFile()
+ {
+ foreach (IAppender appender in LogManager.GetRepository().GetAppenders())
+ {
+ if (appender is FileAppender)
+ {
+ return ((FileAppender)appender).File;
+ }
+ }
+
+ return "./OpenSim.log";
+ }
+
public static string logDir()
{
- return ".";
+ return Path.GetDirectoryName(logFile());
}
// From: http://coercedcode.blogspot.com/2008/03/c-generate-unique-filenames-within.html
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs
index 438ef48..b98b762 100644
--- a/OpenSim/Region/UserStatistics/WebStatsModule.cs
+++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs
@@ -420,7 +420,7 @@ namespace OpenSim.Region.UserStatistics
Encoding encoding = Encoding.ASCII;
int sizeOfChar = encoding.GetByteCount("\n");
byte[] buffer = encoding.GetBytes("\n");
- string logfile = Util.logDir() + "/" + "OpenSim.log";
+ string logfile = Util.logFile();
FileStream fs = new FileStream(logfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
Int64 tokenCount = 0;
Int64 endPosition = fs.Length / sizeOfChar;
--
cgit v1.1
From 4d1758985f64fbdbfd142684c1a4ac82c9a4b97a Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Thu, 7 Feb 2013 00:54:09 +0000
Subject: Make json store tests operate on a single thread to ensure we don't
run into any race related test failures in the future.
---
.../JsonStore/Tests/JsonStoreScriptModuleTests.cs | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
index 8042a93..34422b4 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
@@ -54,6 +54,22 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
private MockScriptEngine m_engine;
private ScriptModuleCommsModule m_smcm;
+ [TestFixtureSetUp]
+ public void FixtureInit()
+ {
+ // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
+ Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
+ }
+
+ [TestFixtureTearDown]
+ public void TearDown()
+ {
+ // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
+ // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
+ // tests really shouldn't).
+ Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
+ }
+
[SetUp]
public override void SetUp()
{
--
cgit v1.1
From 3657a08844731e5a24eeda3195c23f417b4570a5 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Thu, 7 Feb 2013 02:19:26 +0000
Subject: Add TestJsonWriteReadNotecard() regression test
---
.../JsonStore/Tests/JsonStoreScriptModuleTests.cs | 45 +++++++++++++++++++++-
OpenSim/Tests/Common/Mock/MockScriptEngine.cs | 2 +-
2 files changed, 45 insertions(+), 2 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
index 34422b4..98b5624 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
@@ -101,7 +101,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
private object InvokeOp(string name, params object[] args)
{
- return m_smcm.InvokeOperation(UUID.Zero, UUID.Zero, name, args);
+ return InvokeOpOnHost(name, UUID.Zero, args);
+ }
+
+ private object InvokeOpOnHost(string name, UUID hostId, params object[] args)
+ {
+ return m_smcm.InvokeOperation(hostId, UUID.Zero, name, args);
}
[Test]
@@ -209,6 +214,44 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
Assert.That(value, Is.EqualTo("World"));
}
+ ///
+ /// Test for reading and writing json to a notecard
+ ///
+ ///
+ /// TODO: Really needs to test correct receipt of the link_message event. Could do this by directly fetching
+ /// it via the MockScriptEngine or perhaps by a dummy script instance.
+ ///
+ [Test]
+ public void TestJsonWriteReadNotecard()
+ {
+ TestHelpers.InMethod();
+ TestHelpers.EnableLogging();
+
+ string notecardName = "nc1";
+
+ SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, TestHelpers.ParseTail(0x1));
+ m_scene.AddSceneObject(so);
+
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello':'World' }");
+
+ // Write notecard
+ UUID writeNotecardRequestId = (UUID)InvokeOpOnHost("JsonWriteNotecard", so.UUID, storeId, "/", notecardName);
+ Assert.That(writeNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
+
+ TaskInventoryItem nc1Item = so.RootPart.Inventory.GetInventoryItem(notecardName);
+ Assert.That(nc1Item, Is.Not.Null);
+
+ // TODO: Should probably independently check the contents.
+
+ // Read notecard
+ UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello':'World' }");
+ UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "/", notecardName);
+ Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "Hello");
+ Assert.That(value, Is.EqualTo("World"));
+ }
+
public object DummyTestMethod(object o1, object o2, object o3, object o4, object o5) { return null; }
}
}
\ No newline at end of file
diff --git a/OpenSim/Tests/Common/Mock/MockScriptEngine.cs b/OpenSim/Tests/Common/Mock/MockScriptEngine.cs
index 51f2712..78bab5b 100644
--- a/OpenSim/Tests/Common/Mock/MockScriptEngine.cs
+++ b/OpenSim/Tests/Common/Mock/MockScriptEngine.cs
@@ -85,7 +85,7 @@ namespace OpenSim.Tests.Common
public bool PostScriptEvent(UUID itemID, string name, object[] args)
{
- throw new System.NotImplementedException ();
+ return false;
}
public bool PostObjectEvent(UUID itemID, string name, object[] args)
--
cgit v1.1
From 6504e3d4cee1573115e8a83c06227a297a32f093 Mon Sep 17 00:00:00 2001
From: Melanie
Date: Thu, 7 Feb 2013 03:30:02 +0000
Subject: Rename "Bounciness" to "Restitution"
---
OpenSim/Data/MySQL/MySQLSimulationData.cs | 4 ++--
OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 6 +++---
.../Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs | 6 +++---
OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +-
4 files changed, 9 insertions(+), 9 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index 41174f4..1b02b4f 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -1311,7 +1311,7 @@ namespace OpenSim.Data.MySQL
prim.Density = (float)(double)row["Density"];
prim.GravityModifier = (float)(double)row["GravityModifier"];
prim.Friction = (float)(double)row["Friction"];
- prim.Bounciness = (float)(double)row["Restitution"];
+ prim.Restitution = (float)(double)row["Restitution"];
return prim;
}
@@ -1663,7 +1663,7 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.AddWithValue("Density", (double)prim.Density);
cmd.Parameters.AddWithValue("GravityModifier", (double)prim.GravityModifier);
cmd.Parameters.AddWithValue("Friction", (double)prim.Friction);
- cmd.Parameters.AddWithValue("Restitution", (double)prim.Bounciness);
+ cmd.Parameters.AddWithValue("Restitution", (double)prim.Restitution);
if (prim.DynAttrs.Count > 0)
cmd.Parameters.AddWithValue("DynAttrs", prim.DynAttrs.ToXml());
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 55b5462..b00f388 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -1390,7 +1390,7 @@ namespace OpenSim.Region.Framework.Scenes
public float Density { get; set; }
public float GravityModifier { get; set; }
public float Friction { get; set; }
- public float Bounciness { get; set; }
+ public float Restitution { get; set; }
#endregion Public Properties with only Get
@@ -3964,8 +3964,8 @@ namespace OpenSim.Region.Framework.Scenes
GravityModifier = physdata.GravitationModifier;
if(Friction != physdata.Friction)
Friction = physdata.Friction;
- if(Bounciness != physdata.Bounce)
- Bounciness = physdata.Bounce;
+ if(Restitution != physdata.Bounce)
+ Restitution = physdata.Bounce;
}
///
/// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 78229fe..39420a6 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -618,7 +618,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
private static void ProcessBounce(SceneObjectPart obj, XmlTextReader reader)
{
- obj.Bounciness = reader.ReadElementContentAsFloat("Bounce", String.Empty);
+ obj.Restitution = reader.ReadElementContentAsFloat("Bounce", String.Empty);
}
private static void ProcessGravityModifier(SceneObjectPart obj, XmlTextReader reader)
@@ -1295,8 +1295,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString("Density", sop.Density.ToString().ToLower());
if (sop.Friction != 0.6f)
writer.WriteElementString("Friction", sop.Friction.ToString().ToLower());
- if (sop.Bounciness != 0.5f)
- writer.WriteElementString("Bounce", sop.Bounciness.ToString().ToLower());
+ if (sop.Restitution != 0.5f)
+ writer.WriteElementString("Bounce", sop.Restitution.ToString().ToLower());
if (sop.GravityModifier != 1.0f)
writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower());
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 64052ae..be6ac0a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -7602,7 +7602,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
ExtraPhysicsData physdata = new ExtraPhysicsData();
physdata.Density = part.Density;
- physdata.Bounce = part.Bounciness;
+ physdata.Bounce = part.Restitution;
physdata.GravitationModifier = part.GravityModifier;
physdata.PhysShapeType = (PhysShapeType)shape_type;
--
cgit v1.1
From 4867a7cbbf7302845fff031db5eae6fbf93bf26b Mon Sep 17 00:00:00 2001
From: teravus
Date: Thu, 7 Feb 2013 10:26:48 -0500
Subject: This is the final commit that enables the Websocket handler
---
.../Framework/Servers/HttpServer/BaseHttpServer.cs | 12 +-
.../Servers/HttpServer/WebsocketServerHandler.cs | 1085 ++++++++++++++++++++
2 files changed, 1095 insertions(+), 2 deletions(-)
create mode 100644 OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
(limited to 'OpenSim')
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index dcfe99a..70c531c 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -54,7 +54,15 @@ namespace OpenSim.Framework.Servers.HttpServer
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
- public delegate void WebSocketRequestDelegate(string servicepath, WebSocketHTTPServerHandler handler);
+
+ ///
+ /// This is a pending websocket request before it got an sucessful upgrade response.
+ /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to
+ /// start the connection and optionally provide an origin authentication method.
+ ///
+ ///
+ ///
+ public delegate void WebSocketRequestDelegate(string servicepath, WebSocketHttpServerHandler handler);
///
/// Gets or sets the debug level.
@@ -440,7 +448,7 @@ namespace OpenSim.Framework.Servers.HttpServer
}
if (dWebSocketRequestDelegate != null)
{
- dWebSocketRequestDelegate(req.Url.AbsolutePath, new WebSocketHTTPServerHandler(req, context, 16384));
+ dWebSocketRequestDelegate(req.Url.AbsolutePath, new WebSocketHttpServerHandler(req, context, 8192));
return;
}
diff --git a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
new file mode 100644
index 0000000..cfb1605
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
@@ -0,0 +1,1085 @@
+/*
+ * 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 OpenSimulator 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.IO;
+using System.Security.Cryptography;
+using System.Text;
+using HttpServer;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ // Sealed class. If you're going to unseal it, implement IDisposable.
+ ///
+ /// This class implements websockets. It grabs the network context from C#Webserver and utilizes it directly as a tcp streaming service
+ ///
+ public sealed class WebSocketHttpServerHandler : BaseRequestHandler
+ {
+
+ private class WebSocketState
+ {
+ public List ReceivedBytes;
+ public int ExpectedBytes;
+ public WebsocketFrameHeader Header;
+ public bool FrameComplete;
+ public WebSocketFrame ContinuationFrame;
+ }
+
+ ///
+ /// Binary Data will trigger this event
+ ///
+ public event DataDelegate OnData;
+
+ ///
+ /// Textual Data will trigger this event
+ ///
+ public event TextDelegate OnText;
+
+ ///
+ /// A ping request form the other side will trigger this event.
+ /// This class responds to the ping automatically. You shouldn't send a pong.
+ /// it's informational.
+ ///
+ public event PingDelegate OnPing;
+
+ ///
+ /// This is a response to a ping you sent.
+ ///
+ public event PongDelegate OnPong;
+
+ ///
+ /// This is a regular HTTP Request... This may be removed in the future.
+ ///
+ public event RegularHttpRequestDelegate OnRegularHttpRequest;
+
+ ///
+ /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired
+ ///
+ public event UpgradeCompletedDelegate OnUpgradeCompleted;
+
+ ///
+ /// If the upgrade failed, this will be fired
+ ///
+ public event UpgradeFailedDelegate OnUpgradeFailed;
+
+ ///
+ /// When the websocket is closed, this will be fired.
+ ///
+ public event CloseDelegate OnClose;
+
+ ///
+ /// Set this delegate to allow your module to validate the origin of the
+ /// Websocket request. Primary line of defense against cross site scripting
+ ///
+ public ValidateHandshake HandshakeValidateMethodOverride = null;
+
+ private OSHttpRequest _request;
+ private HTTPNetworkContext _networkContext;
+ private IHttpClientContext _clientContext;
+
+ private int _pingtime = 0;
+ private byte[] _buffer;
+ private int _bufferPosition;
+ private int _bufferLength;
+ private bool _closing;
+ private bool _upgraded;
+
+ private const string HandshakeAcceptText =
+ "HTTP/1.1 101 Switching Protocols\r\n" +
+ "upgrade: websocket\r\n" +
+ "Connection: Upgrade\r\n" +
+ "sec-websocket-accept: {0}\r\n\r\n";// +
+ //"{1}";
+
+ private const string HandshakeDeclineText =
+ "HTTP/1.1 {0} {1}\r\n" +
+ "Connection: close\r\n\r\n";
+
+ ///
+ /// Mysterious constant defined in RFC6455 to append to the client provided security key
+ ///
+ private const string WebsocketHandshakeAcceptHashConstant = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+
+ public WebSocketHttpServerHandler(OSHttpRequest preq, IHttpClientContext pContext, int bufferlen)
+ : base(preq.HttpMethod, preq.Url.OriginalString)
+ {
+ _request = preq;
+ _networkContext = pContext.GiveMeTheNetworkStreamIKnowWhatImDoing();
+ _clientContext = pContext;
+ _bufferLength = bufferlen;
+ _buffer = new byte[_bufferLength];
+ }
+
+ // Sealed class implments destructor and an internal dispose method. complies with C# unmanaged resource best practices.
+ ~WebSocketHttpServerHandler()
+ {
+ Dispose();
+
+ }
+
+ ///
+ /// Sets the length of the stream buffer
+ ///
+ /// Byte length.
+ public void SetChunksize(int pChunk)
+ {
+ if (!_upgraded)
+ {
+ _buffer = new byte[pChunk];
+ }
+ else
+ {
+ throw new InvalidOperationException("You must set the chunksize before the connection is upgraded");
+ }
+ }
+
+ ///
+ /// This is the famous nagle.
+ ///
+ public bool NoDelay_TCP_Nagle
+ {
+ get
+ {
+ if (_networkContext != null && _networkContext.Socket != null)
+ {
+ return _networkContext.Socket.NoDelay;
+ }
+ else
+ {
+ throw new InvalidOperationException("The socket has been shutdown");
+ }
+ }
+ set
+ {
+ if (_networkContext != null && _networkContext.Socket != null)
+ _networkContext.Socket.NoDelay = value;
+ else
+ {
+ throw new InvalidOperationException("The socket has been shutdown");
+ }
+ }
+ }
+
+ ///
+ /// This triggers the websocket to start the upgrade process...
+ /// This is a Generalized Networking 'common sense' helper method. Some people expect to call Start() instead
+ /// of the more context appropriate HandshakeAndUpgrade()
+ ///
+ public void Start()
+ {
+ HandshakeAndUpgrade();
+ }
+
+ ///
+ /// This triggers the websocket start the upgrade process
+ ///
+ public void HandshakeAndUpgrade()
+ {
+ string webOrigin = string.Empty;
+ string websocketKey = string.Empty;
+ string acceptKey = string.Empty;
+ string accepthost = string.Empty;
+ if (!string.IsNullOrEmpty(_request.Headers["origin"]))
+ webOrigin = _request.Headers["origin"];
+
+ if (!string.IsNullOrEmpty(_request.Headers["sec-websocket-key"]))
+ websocketKey = _request.Headers["sec-websocket-key"];
+
+ if (!string.IsNullOrEmpty(_request.Headers["host"]))
+ accepthost = _request.Headers["host"];
+
+ if (string.IsNullOrEmpty(_request.Headers["upgrade"]))
+ {
+ FailUpgrade(OSHttpStatusCode.ClientErrorBadRequest, "no upgrade request submitted");
+ }
+
+ string connectionheader = _request.Headers["upgrade"];
+ if (connectionheader.ToLower() != "websocket")
+ {
+ FailUpgrade(OSHttpStatusCode.ClientErrorBadRequest, "no connection upgrade request submitted");
+ }
+
+ // If the object consumer provided a method to validate the origin, we should call it and give the client a success or fail.
+ // If not.. we should accept any. The assumption here is that there would be no Websocket handlers registered in baseHTTPServer unless
+ // Something asked for it...
+ if (HandshakeValidateMethodOverride != null)
+ {
+ if (HandshakeValidateMethodOverride(webOrigin, websocketKey, accepthost))
+ {
+ acceptKey = GenerateAcceptKey(websocketKey);
+ string rawaccept = string.Format(HandshakeAcceptText, acceptKey);
+ SendUpgradeSuccess(rawaccept);
+
+ }
+ else
+ {
+ FailUpgrade(OSHttpStatusCode.ClientErrorForbidden, "Origin Validation Failed");
+ }
+ }
+ else
+ {
+ acceptKey = GenerateAcceptKey(websocketKey);
+ string rawaccept = string.Format(HandshakeAcceptText, acceptKey);
+ SendUpgradeSuccess(rawaccept);
+ }
+ }
+
+ ///
+ /// Generates a handshake response key string based on the client's
+ /// provided key to prove to the client that we're allowing the Websocket
+ /// upgrade of our own free will and we were not coerced into doing it.
+ ///
+ /// Client provided security key
+ ///
+ private static string GenerateAcceptKey(string key)
+ {
+ if (string.IsNullOrEmpty(key))
+ return string.Empty;
+
+ string acceptkey = key + WebsocketHandshakeAcceptHashConstant;
+
+ SHA1 hashobj = SHA1.Create();
+ string ret = Convert.ToBase64String(hashobj.ComputeHash(Encoding.UTF8.GetBytes(acceptkey)));
+ hashobj.Clear();
+
+ return ret;
+ }
+
+ ///
+ /// Informs the otherside that we accepted their upgrade request
+ ///
+ /// The HTTP 1.1 101 response that says Yay \o/
+ private void SendUpgradeSuccess(string pHandshakeResponse)
+ {
+ // Create a new websocket state so we can keep track of data in between network reads.
+ WebSocketState socketState = new WebSocketState() { ReceivedBytes = new List(), Header = WebsocketFrameHeader.HeaderDefault(), FrameComplete = true};
+
+ byte[] bhandshakeResponse = Encoding.UTF8.GetBytes(pHandshakeResponse);
+ try
+ {
+
+ // Begin reading the TCP stream before writing the Upgrade success message to the other side of the stream.
+ _networkContext.Stream.BeginRead(_buffer, 0, _bufferLength, OnReceive, socketState);
+
+ // Write the upgrade handshake success message
+ _networkContext.Stream.Write(bhandshakeResponse, 0, bhandshakeResponse.Length);
+ _networkContext.Stream.Flush();
+ _upgraded = true;
+ UpgradeCompletedDelegate d = OnUpgradeCompleted;
+ if (d != null)
+ d(this, new UpgradeCompletedEventArgs());
+ }
+ catch (IOException fail)
+ {
+ Close(string.Empty);
+ }
+ catch (ObjectDisposedException fail)
+ {
+ Close(string.Empty);
+ }
+
+ }
+
+ ///
+ /// The server has decided not to allow the upgrade to a websocket for some reason. The Http 1.1 response that says Nay >:(
+ ///
+ /// HTTP Status reflecting the reason why
+ /// Textual reason for the upgrade fail
+ private void FailUpgrade(OSHttpStatusCode pCode, string pMessage )
+ {
+ string handshakeResponse = string.Format(HandshakeDeclineText, (int)pCode, pMessage.Replace("\n", string.Empty).Replace("\r", string.Empty));
+ byte[] bhandshakeResponse = Encoding.UTF8.GetBytes(handshakeResponse);
+ _networkContext.Stream.Write(bhandshakeResponse, 0, bhandshakeResponse.Length);
+ _networkContext.Stream.Flush();
+ _networkContext.Stream.Dispose();
+
+ UpgradeFailedDelegate d = OnUpgradeFailed;
+ if (d != null)
+ d(this,new UpgradeFailedEventArgs());
+ }
+
+
+ ///
+ /// This is our ugly Async OnReceive event handler.
+ /// This chunks the input stream based on the length of the provided buffer and processes out
+ /// as many frames as it can. It then moves the unprocessed data to the beginning of the buffer.
+ ///
+ /// Our Async State from beginread
+ private void OnReceive(IAsyncResult ar)
+ {
+ WebSocketState _socketState = ar.AsyncState as WebSocketState;
+ try
+ {
+ int bytesRead = _networkContext.Stream.EndRead(ar);
+ if (bytesRead == 0)
+ {
+ // Do Disconnect
+ _networkContext.Stream.Dispose();
+ _networkContext = null;
+ return;
+ }
+ _bufferPosition += bytesRead;
+
+ if (_bufferPosition > _bufferLength)
+ {
+ // Message too big for chunksize.. not sure how this happened...
+ //Close(string.Empty);
+ }
+
+ int offset = 0;
+ bool headerread = true;
+ int headerforwardposition = 0;
+ while (headerread && offset < bytesRead)
+ {
+ if (_socketState.FrameComplete)
+ {
+ WebsocketFrameHeader pheader = WebsocketFrameHeader.ZeroHeader;
+
+ headerread = WebSocketReader.TryReadHeader(_buffer, offset, _bufferPosition - offset, out pheader,
+ out headerforwardposition);
+ offset += headerforwardposition;
+
+ if (headerread)
+ {
+ _socketState.FrameComplete = false;
+
+ if (pheader.PayloadLen > 0)
+ {
+ if ((int) pheader.PayloadLen > _bufferPosition - offset)
+ {
+ byte[] writebytes = new byte[_bufferPosition - offset];
+
+ Buffer.BlockCopy(_buffer, offset, writebytes, 0, (int) _bufferPosition - offset);
+ _socketState.ExpectedBytes = (int) pheader.PayloadLen;
+ _socketState.ReceivedBytes.AddRange(writebytes);
+ _socketState.Header = pheader; // We need to add the header so that we can unmask it
+ offset += (int) _bufferPosition - offset;
+ }
+ else
+ {
+ byte[] writebytes = new byte[pheader.PayloadLen];
+ Buffer.BlockCopy(_buffer, offset, writebytes, 0, (int) pheader.PayloadLen);
+ WebSocketReader.Mask(pheader.Mask, writebytes);
+ pheader.IsMasked = false;
+ _socketState.FrameComplete = true;
+ _socketState.ReceivedBytes.AddRange(writebytes);
+ _socketState.Header = pheader;
+ offset += (int) pheader.PayloadLen;
+ }
+ }
+ else
+ {
+ pheader.Mask = 0;
+ _socketState.FrameComplete = true;
+ _socketState.Header = pheader;
+ }
+
+
+
+ if (_socketState.FrameComplete)
+ {
+ ProcessFrame(_socketState);
+ _socketState.Header.SetDefault();
+ _socketState.ReceivedBytes.Clear();
+ _socketState.ExpectedBytes = 0;
+
+ }
+
+ }
+ }
+ else
+ {
+ WebsocketFrameHeader frameHeader = _socketState.Header;
+ int bytesleft = _socketState.ExpectedBytes - _socketState.ReceivedBytes.Count;
+
+ if (bytesleft > _bufferPosition)
+ {
+ byte[] writebytes = new byte[_bufferPosition];
+
+ Buffer.BlockCopy(_buffer, offset, writebytes, 0, (int) _bufferPosition);
+ _socketState.ReceivedBytes.AddRange(writebytes);
+ _socketState.Header = frameHeader; // We need to add the header so that we can unmask it
+ offset += (int) _bufferPosition;
+ }
+ else
+ {
+ byte[] writebytes = new byte[_bufferPosition];
+ Buffer.BlockCopy(_buffer, offset, writebytes, 0, (int) _bufferPosition);
+ _socketState.FrameComplete = true;
+ _socketState.ReceivedBytes.AddRange(writebytes);
+ _socketState.Header = frameHeader;
+ offset += (int) _bufferPosition;
+ }
+ if (_socketState.FrameComplete)
+ {
+ ProcessFrame(_socketState);
+ _socketState.Header.SetDefault();
+ _socketState.ReceivedBytes.Clear();
+ _socketState.ExpectedBytes = 0;
+ // do some processing
+ }
+
+ }
+ }
+ if (offset > 0)
+ {
+ // If the buffer is maxed out.. we can just move the cursor. Nothing to move to the beginning.
+ if (offset <_buffer.Length)
+ Buffer.BlockCopy(_buffer, offset, _buffer, 0, _bufferPosition - offset);
+ _bufferPosition -= offset;
+ }
+ if (_networkContext.Stream != null && _networkContext.Stream.CanRead && !_closing)
+ {
+ _networkContext.Stream.BeginRead(_buffer, _bufferPosition, _bufferLength - _bufferPosition, OnReceive,
+ _socketState);
+ }
+ else
+ {
+ // We can't read the stream anymore...
+ }
+
+ }
+ catch (IOException fail)
+ {
+ Close(string.Empty);
+ }
+ catch (ObjectDisposedException fail)
+ {
+ Close(string.Empty);
+ }
+ }
+
+ ///
+ /// Sends a string to the other side
+ ///
+ /// the string message that is to be sent
+ public void SendMessage(string message)
+ {
+ byte[] messagedata = Encoding.UTF8.GetBytes(message);
+ WebSocketFrame textMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata };
+ textMessageFrame.Header.Opcode = WebSocketReader.OpCode.Text;
+ textMessageFrame.Header.IsEnd = true;
+ SendSocket(textMessageFrame.ToBytes());
+
+ }
+
+ public void SendData(byte[] data)
+ {
+ WebSocketFrame dataMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = data};
+ dataMessageFrame.Header.IsEnd = true;
+ dataMessageFrame.Header.Opcode = WebSocketReader.OpCode.Binary;
+ SendSocket(dataMessageFrame.ToBytes());
+
+ }
+
+ ///
+ /// Writes raw bytes to the websocket. Unframed data will cause disconnection
+ ///
+ ///
+ private void SendSocket(byte[] data)
+ {
+ if (!_closing)
+ {
+ try
+ {
+
+ _networkContext.Stream.Write(data, 0, data.Length);
+ }
+ catch (IOException)
+ {
+
+ }
+ }
+ }
+
+ ///
+ /// Sends a Ping check to the other side. The other side SHOULD respond as soon as possible with a pong frame. This interleaves with incoming fragmented frames.
+ ///
+ public void SendPingCheck()
+ {
+ WebSocketFrame pingFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = new byte[0] };
+ pingFrame.Header.Opcode = WebSocketReader.OpCode.Ping;
+ pingFrame.Header.IsEnd = true;
+ _pingtime = Util.EnvironmentTickCount();
+ SendSocket(pingFrame.ToBytes());
+ }
+
+ ///
+ /// Closes the websocket connection. Sends a close message to the other side if it hasn't already done so.
+ ///
+ ///
+ public void Close(string message)
+ {
+ if (_networkContext.Stream != null)
+ {
+ if (_networkContext.Stream.CanWrite)
+ {
+ byte[] messagedata = Encoding.UTF8.GetBytes(message);
+ WebSocketFrame closeResponseFrame = new WebSocketFrame()
+ {
+ Header = WebsocketFrameHeader.HeaderDefault(),
+ WebSocketPayload = messagedata
+ };
+ closeResponseFrame.Header.Opcode = WebSocketReader.OpCode.Close;
+ closeResponseFrame.Header.PayloadLen = (ulong) messagedata.Length;
+ closeResponseFrame.Header.IsEnd = true;
+ SendSocket(closeResponseFrame.ToBytes());
+ }
+ }
+ CloseDelegate closeD = OnClose;
+ if (closeD != null)
+ {
+ closeD(this, new CloseEventArgs());
+ }
+
+ _closing = true;
+ }
+
+ ///
+ /// Processes a websocket frame and triggers consumer events
+ ///
+ /// We need to modify the websocket state here depending on the frame
+ private void ProcessFrame(WebSocketState psocketState)
+ {
+ if (psocketState.Header.IsMasked)
+ {
+ byte[] unmask = psocketState.ReceivedBytes.ToArray();
+ WebSocketReader.Mask(psocketState.Header.Mask, unmask);
+ psocketState.ReceivedBytes = new List(unmask);
+ }
+
+ switch (psocketState.Header.Opcode)
+ {
+ case WebSocketReader.OpCode.Ping:
+ PingDelegate pingD = OnPing;
+ if (pingD != null)
+ {
+ pingD(this, new PingEventArgs());
+ }
+
+ WebSocketFrame pongFrame = new WebSocketFrame(){Header = WebsocketFrameHeader.HeaderDefault(),WebSocketPayload = new byte[0]};
+ pongFrame.Header.Opcode = WebSocketReader.OpCode.Pong;
+ pongFrame.Header.IsEnd = true;
+ SendSocket(pongFrame.ToBytes());
+ break;
+ case WebSocketReader.OpCode.Pong:
+
+ PongDelegate pongD = OnPong;
+ if (pongD != null)
+ {
+ pongD(this, new PongEventArgs(){PingResponseMS = Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(),_pingtime)});
+ }
+ break;
+ case WebSocketReader.OpCode.Binary:
+ if (!psocketState.Header.IsEnd) // Not done, so we need to store this and wait for the end frame.
+ {
+ psocketState.ContinuationFrame = new WebSocketFrame
+ {
+ Header = psocketState.Header,
+ WebSocketPayload =
+ psocketState.ReceivedBytes.ToArray()
+ };
+ }
+ else
+ {
+ // Send Done Event!
+ DataDelegate dataD = OnData;
+ if (dataD != null)
+ {
+ dataD(this,new WebsocketDataEventArgs(){Data = psocketState.ReceivedBytes.ToArray()});
+ }
+ }
+ break;
+ case WebSocketReader.OpCode.Text:
+ if (!psocketState.Header.IsEnd) // Not done, so we need to store this and wait for the end frame.
+ {
+ psocketState.ContinuationFrame = new WebSocketFrame
+ {
+ Header = psocketState.Header,
+ WebSocketPayload =
+ psocketState.ReceivedBytes.ToArray()
+ };
+ }
+ else
+ {
+ TextDelegate textD = OnText;
+ if (textD != null)
+ {
+ textD(this, new WebsocketTextEventArgs() { Data = Encoding.UTF8.GetString(psocketState.ReceivedBytes.ToArray()) });
+ }
+
+ // Send Done Event!
+ }
+ break;
+ case WebSocketReader.OpCode.Continue: // Continuation. Multiple frames worth of data for one message. Only valid when not using Control Opcodes
+ //Console.WriteLine("currhead " + psocketState.Header.IsEnd);
+ //Console.WriteLine("Continuation! " + psocketState.ContinuationFrame.Header.IsEnd);
+ byte[] combineddata = new byte[psocketState.ReceivedBytes.Count+psocketState.ContinuationFrame.WebSocketPayload.Length];
+ byte[] newdata = psocketState.ReceivedBytes.ToArray();
+ Buffer.BlockCopy(psocketState.ContinuationFrame.WebSocketPayload, 0, combineddata, 0, psocketState.ContinuationFrame.WebSocketPayload.Length);
+ Buffer.BlockCopy(newdata, 0, combineddata,
+ psocketState.ContinuationFrame.WebSocketPayload.Length, newdata.Length);
+ psocketState.ContinuationFrame.WebSocketPayload = combineddata;
+ psocketState.Header.PayloadLen = (ulong)combineddata.Length;
+ if (psocketState.Header.IsEnd)
+ {
+ if (psocketState.ContinuationFrame.Header.Opcode == WebSocketReader.OpCode.Text)
+ {
+ // Send Done event
+ TextDelegate textD = OnText;
+ if (textD != null)
+ {
+ textD(this, new WebsocketTextEventArgs() { Data = Encoding.UTF8.GetString(combineddata) });
+ }
+ }
+ else if (psocketState.ContinuationFrame.Header.Opcode == WebSocketReader.OpCode.Binary)
+ {
+ // Send Done event
+ DataDelegate dataD = OnData;
+ if (dataD != null)
+ {
+ dataD(this, new WebsocketDataEventArgs() { Data = combineddata });
+ }
+ }
+ else
+ {
+ // protocol violation
+ }
+ psocketState.ContinuationFrame = null;
+ }
+ break;
+ case WebSocketReader.OpCode.Close:
+ Close(string.Empty);
+
+ break;
+
+ }
+ psocketState.Header.SetDefault();
+ psocketState.ReceivedBytes.Clear();
+ psocketState.ExpectedBytes = 0;
+ }
+ public void Dispose()
+ {
+ if (_networkContext != null && _networkContext.Stream != null)
+ {
+ if (_networkContext.Stream.CanWrite)
+ _networkContext.Stream.Flush();
+ _networkContext.Stream.Close();
+ _networkContext.Stream.Dispose();
+ _networkContext.Stream = null;
+ }
+
+ if (_request != null && _request.InputStream != null)
+ {
+ _request.InputStream.Close();
+ _request.InputStream.Dispose();
+ _request = null;
+ }
+
+ if (_clientContext != null)
+ {
+ _clientContext.Close();
+ _clientContext = null;
+ }
+ }
+ }
+
+ ///
+ /// Reads a byte stream and returns Websocket frames.
+ ///
+ public class WebSocketReader
+ {
+ ///
+ /// Bit to determine if the frame read on the stream is the last frame in a sequence of fragmented frames
+ ///
+ private const byte EndBit = 0x80;
+
+ ///
+ /// These are the Frame Opcodes
+ ///
+ public enum OpCode
+ {
+ // Data Opcodes
+ Continue = 0x0,
+ Text = 0x1,
+ Binary = 0x2,
+
+ // Control flow Opcodes
+ Close = 0x8,
+ Ping = 0x9,
+ Pong = 0xA
+ }
+
+ ///
+ /// Masks and Unmasks data using the frame mask. Mask is applied per octal
+ /// Note: Frames from clients MUST be masked
+ /// Note: Frames from servers MUST NOT be masked
+ ///
+ /// Int representing 32 bytes of mask data. Mask is applied per octal
+ ///
+ public static void Mask(int pMask, byte[] pBuffer)
+ {
+ byte[] maskKey = BitConverter.GetBytes(pMask);
+ int currentMaskIndex = 0;
+ for (int i = 0; i < pBuffer.Length; i++)
+ {
+ pBuffer[i] = (byte)(pBuffer[i] ^ maskKey[currentMaskIndex]);
+ if (currentMaskIndex == 3)
+ {
+ currentMaskIndex = 0;
+ }
+ else
+ {
+ currentMaskIndex++;
+
+ }
+
+ }
+ }
+
+ ///
+ /// Attempts to read a header off the provided buffer. Returns true, exports a WebSocketFrameheader,
+ /// and an int to move the buffer forward when it reads a header. False when it can't read a header
+ ///
+ /// Bytes read from the stream
+ /// Starting place in the stream to begin trying to read from
+ /// Lenth in the stream to try and read from. Provided for cases where the
+ /// buffer's length is larger then the data in it
+ /// Outputs the read WebSocket frame header
+ /// Informs the calling stream to move the buffer forward
+ /// True if it got a header, False if it didn't get a header
+ public static bool TryReadHeader(byte[] pBuffer, int pOffset, int length, out WebsocketFrameHeader oHeader,
+ out int moveBuffer)
+ {
+ oHeader = WebsocketFrameHeader.ZeroHeader;
+ int minumheadersize = 2;
+ if (length > pBuffer.Length - pOffset)
+ throw new ArgumentOutOfRangeException("The Length specified was larger the byte array supplied");
+ if (length < minumheadersize)
+ {
+ moveBuffer = 0;
+ return false;
+ }
+
+ byte nibble1 = (byte)(pBuffer[pOffset] & 0xF0); //FIN/RSV1/RSV2/RSV3
+ byte nibble2 = (byte)(pBuffer[pOffset] & 0x0F); // Opcode block
+
+ oHeader = new WebsocketFrameHeader();
+ oHeader.SetDefault();
+
+ if ((nibble1 & WebSocketReader.EndBit) == WebSocketReader.EndBit)
+ {
+ oHeader.IsEnd = true;
+ }
+ else
+ {
+ oHeader.IsEnd = false;
+ }
+ //Opcode
+ oHeader.Opcode = (WebSocketReader.OpCode)nibble2;
+ //Mask
+ oHeader.IsMasked = Convert.ToBoolean((pBuffer[pOffset + 1] & 0x80) >> 7);
+
+ // Payload length
+ oHeader.PayloadLen = (byte)(pBuffer[pOffset + 1] & 0x7F);
+
+ int index = 2; // LargerPayload length starts at byte 3
+
+ switch (oHeader.PayloadLen)
+ {
+ case 126:
+ minumheadersize += 2;
+ if (length < minumheadersize)
+ {
+ moveBuffer = 0;
+ return false;
+ }
+ Array.Reverse(pBuffer, pOffset + index, 2); // two bytes
+ oHeader.PayloadLen = BitConverter.ToUInt16(pBuffer, pOffset + index);
+ index += 2;
+ break;
+ case 127: // we got more this is a bigger frame
+ // 8 bytes - uint64 - most significant bit 0 network byte order
+ minumheadersize += 8;
+ if (length < minumheadersize)
+ {
+ moveBuffer = 0;
+ return false;
+ }
+ Array.Reverse(pBuffer, pOffset + index, 8);
+ oHeader.PayloadLen = BitConverter.ToUInt64(pBuffer, pOffset + index);
+ index += 8;
+ break;
+
+ }
+ //oHeader.PayloadLeft = oHeader.PayloadLen; // Start the count in case it's chunked over the network. This is different then frame fragmentation
+ if (oHeader.IsMasked)
+ {
+ minumheadersize += 4;
+ if (length < minumheadersize)
+ {
+ moveBuffer = 0;
+ return false;
+ }
+ oHeader.Mask = BitConverter.ToInt32(pBuffer, pOffset + index);
+ index += 4;
+ }
+ moveBuffer = index;
+ return true;
+
+ }
+ }
+
+ ///
+ /// RFC6455 Websocket Frame
+ ///
+ public class WebSocketFrame
+ {
+ /*
+ * RFC6455
+nib 0 1 2 3 4 5 6 7
+byt 0 1 2 3
+dec 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-------+-+-------------+-------------------------------+
+ |F|R|R|R| opcode|M| Payload len | Extended payload length |
+ |I|S|S|S| (4) |A| (7) | (16/64) +
+ |N|V|V|V| |S| | (if payload len==126/127) |
+ | |1|2|3| |K| | +
+ +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
+ | Extended payload length continued, if payload len == 127 |
+ + - - - - - - - - - - - - - - - +-------------------------------+
+ | |Masking-key, if MASK set to 1 |
+ +-------------------------------+-------------------------------+
+ | Masking-key (continued) | Payload Data |
+ +-------------------------------- - - - - - - - - - - - - - - - +
+ : Payload Data continued ... :
+ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
+ | Payload Data continued ... |
+ +---------------------------------------------------------------+
+
+ * When reading these, the frames are possibly fragmented and interleaved with control frames
+ * the fragmented frames are not interleaved with data frames. Just control frames
+ */
+ public static readonly WebSocketFrame DefaultFrame = new WebSocketFrame(){Header = new WebsocketFrameHeader(),WebSocketPayload = new byte[0]};
+ public WebsocketFrameHeader Header;
+ public byte[] WebSocketPayload;
+
+ public byte[] ToBytes()
+ {
+ Header.PayloadLen = (ulong)WebSocketPayload.Length;
+ return Header.ToBytes(WebSocketPayload);
+ }
+
+ }
+
+ public struct WebsocketFrameHeader
+ {
+ //public byte CurrentMaskIndex;
+ ///
+ /// The last frame in a sequence of fragmented frames or the one and only frame for this message.
+ ///
+ public bool IsEnd;
+
+ ///
+ /// Returns whether the payload data is masked or not. Data from Clients MUST be masked, Data from Servers MUST NOT be masked
+ ///
+ public bool IsMasked;
+
+ ///
+ /// A set of cryptologically sound random bytes XoR-ed against the payload octally. Looped
+ ///
+ public int Mask;
+ /*
+byt 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +---------------+---------------+---------------+---------------+
+ | Octal 1 | Octal 2 | Octal 3 | Octal 4 |
+ +---------------+---------------+---------------+---------------+
+*/
+
+
+ public WebSocketReader.OpCode Opcode;
+
+ public UInt64 PayloadLen;
+ //public UInt64 PayloadLeft;
+ // Payload is X + Y
+ //public UInt64 ExtensionDataLength;
+ //public UInt64 ApplicationDataLength;
+ public static readonly WebsocketFrameHeader ZeroHeader = WebsocketFrameHeader.HeaderDefault();
+
+ public void SetDefault()
+ {
+
+ //CurrentMaskIndex = 0;
+ IsEnd = true;
+ IsMasked = true;
+ Mask = 0;
+ Opcode = WebSocketReader.OpCode.Close;
+ // PayloadLeft = 0;
+ PayloadLen = 0;
+ // ExtensionDataLength = 0;
+ // ApplicationDataLength = 0;
+
+ }
+
+ ///
+ /// Returns a byte array representing the Frame header
+ ///
+ /// This is the frame data payload. The header describes the size of the payload.
+ /// If payload is null, a Zero sized payload is assumed
+ /// Returns a byte array representing the frame header
+ public byte[] ToBytes(byte[] payload)
+ {
+ List result = new List();
+
+ // Squeeze in our opcode and our ending bit.
+ result.Add((byte)((byte)Opcode | (IsEnd?0x80:0x00) ));
+
+ // Again with the three different byte interpretations of size..
+
+ //bytesize
+ if (PayloadLen <= 125)
+ {
+ result.Add((byte) PayloadLen);
+ } //Uint16
+ else if (PayloadLen <= ushort.MaxValue)
+ {
+ result.Add(126);
+ byte[] payloadLengthByte = BitConverter.GetBytes(Convert.ToUInt16(PayloadLen));
+ Array.Reverse(payloadLengthByte);
+ result.AddRange(payloadLengthByte);
+ } //UInt64
+ else
+ {
+ result.Add(127);
+ byte[] payloadLengthByte = BitConverter.GetBytes(PayloadLen);
+ Array.Reverse(payloadLengthByte);
+ result.AddRange(payloadLengthByte);
+ }
+
+ // Only add a payload if it's not null
+ if (payload != null)
+ {
+ result.AddRange(payload);
+ }
+ return result.ToArray();
+ }
+
+ ///
+ /// A Helper method to define the defaults
+ ///
+ ///
+
+ public static WebsocketFrameHeader HeaderDefault()
+ {
+ return new WebsocketFrameHeader
+ {
+ //CurrentMaskIndex = 0,
+ IsEnd = false,
+ IsMasked = true,
+ Mask = 0,
+ Opcode = WebSocketReader.OpCode.Close,
+ //PayloadLeft = 0,
+ PayloadLen = 0,
+ // ExtensionDataLength = 0,
+ // ApplicationDataLength = 0
+ };
+ }
+ }
+
+ public delegate void DataDelegate(object sender, WebsocketDataEventArgs data);
+
+ public delegate void TextDelegate(object sender, WebsocketTextEventArgs text);
+
+ public delegate void PingDelegate(object sender, PingEventArgs pingdata);
+
+ public delegate void PongDelegate(object sender, PongEventArgs pongdata);
+
+ public delegate void RegularHttpRequestDelegate(object sender, RegularHttpRequestEvnetArgs request);
+
+ public delegate void UpgradeCompletedDelegate(object sender, UpgradeCompletedEventArgs completeddata);
+
+ public delegate void UpgradeFailedDelegate(object sender, UpgradeFailedEventArgs faileddata);
+
+ public delegate void CloseDelegate(object sender, CloseEventArgs closedata);
+
+ public delegate bool ValidateHandshake(string pWebOrigin, string pWebSocketKey, string pHost);
+
+
+ public class WebsocketDataEventArgs : EventArgs
+ {
+ public byte[] Data;
+ }
+
+ public class WebsocketTextEventArgs : EventArgs
+ {
+ public string Data;
+ }
+
+ public class PingEventArgs : EventArgs
+ {
+ ///
+ /// The ping event can arbitrarily contain data
+ ///
+ public byte[] Data;
+ }
+
+ public class PongEventArgs : EventArgs
+ {
+ ///
+ /// The pong event can arbitrarily contain data
+ ///
+ public byte[] Data;
+
+ public int PingResponseMS;
+
+ }
+
+ public class RegularHttpRequestEvnetArgs : EventArgs
+ {
+
+ }
+
+ public class UpgradeCompletedEventArgs : EventArgs
+ {
+
+ }
+
+ public class UpgradeFailedEventArgs : EventArgs
+ {
+
+ }
+
+ public class CloseEventArgs : EventArgs
+ {
+
+ }
+
+
+}
--
cgit v1.1
From 4bd1794b5a05147788950208f9644c2b9d731859 Mon Sep 17 00:00:00 2001
From: teravus
Date: Thu, 7 Feb 2013 12:19:54 -0500
Subject: * missing example module.. Oops.
---
.../WebSocketEchoTest/WebSocketEchoModule.cs | 174 +++++++++++++++++++++
1 file changed, 174 insertions(+)
create mode 100644 OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs
(limited to 'OpenSim')
diff --git a/OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs b/OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs
new file mode 100644
index 0000000..34e20b7
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs
@@ -0,0 +1,174 @@
+/*
+ * 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 OpenSimulator 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.Reflection;
+using OpenSim.Framework.Servers;
+using Mono.Addins;
+using log4net;
+using Nini.Config;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+
+using OpenSim.Framework.Servers.HttpServer;
+
+
+namespace OpenSim.Region.OptionalModules.WebSocketEchoModule
+{
+
+ [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WebSocketEchoModule")]
+ public class WebSocketEchoModule : ISharedRegionModule
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private bool enabled;
+ public string Name { get { return "WebSocketEchoModule"; } }
+
+ public Type ReplaceableInterface { get { return null; } }
+
+
+ private HashSet _activeHandlers = new HashSet();
+
+ public void Initialise(IConfigSource pConfig)
+ {
+ enabled = true;// (pConfig.Configs["WebSocketEcho"] != null);
+ if (enabled)
+ m_log.DebugFormat("[WebSocketEchoModule]: INITIALIZED MODULE");
+ }
+
+ ///
+ /// This method sets up the callback to WebSocketHandlerCallback below when a HTTPRequest comes in for /echo
+ ///
+ public void PostInitialise()
+ {
+ if (enabled)
+ MainServer.Instance.AddWebSocketHandler("/echo", WebSocketHandlerCallback);
+ }
+
+ // This gets called by BaseHttpServer and gives us an opportunity to set things on the WebSocket handler before we turn it on
+ public void WebSocketHandlerCallback(string path, WebSocketHttpServerHandler handler)
+ {
+ SubscribeToEvents(handler);
+ handler.SetChunksize(8192);
+ handler.NoDelay_TCP_Nagle = true;
+ handler.HandshakeAndUpgrade();
+ }
+
+ //These are our normal events
+ public void SubscribeToEvents(WebSocketHttpServerHandler handler)
+ {
+ handler.OnClose += HandlerOnOnClose;
+ handler.OnText += HandlerOnOnText;
+ handler.OnUpgradeCompleted += HandlerOnOnUpgradeCompleted;
+ handler.OnData += HandlerOnOnData;
+ handler.OnPong += HandlerOnOnPong;
+ }
+
+ public void UnSubscribeToEvents(WebSocketHttpServerHandler handler)
+ {
+ handler.OnClose -= HandlerOnOnClose;
+ handler.OnText -= HandlerOnOnText;
+ handler.OnUpgradeCompleted -= HandlerOnOnUpgradeCompleted;
+ handler.OnData -= HandlerOnOnData;
+ handler.OnPong -= HandlerOnOnPong;
+ }
+
+ private void HandlerOnOnPong(object sender, PongEventArgs pongdata)
+ {
+ m_log.Info("[WebSocketEchoModule]: Got a pong.. ping time: " + pongdata.PingResponseMS);
+ }
+
+ private void HandlerOnOnData(object sender, WebsocketDataEventArgs data)
+ {
+ WebSocketHttpServerHandler obj = sender as WebSocketHttpServerHandler;
+ obj.SendData(data.Data);
+ m_log.Info("[WebSocketEchoModule]: We received a bunch of ugly non-printable bytes");
+ obj.SendPingCheck();
+ }
+
+
+ private void HandlerOnOnUpgradeCompleted(object sender, UpgradeCompletedEventArgs completeddata)
+ {
+ WebSocketHttpServerHandler obj = sender as WebSocketHttpServerHandler;
+ _activeHandlers.Add(obj);
+ }
+
+ private void HandlerOnOnText(object sender, WebsocketTextEventArgs text)
+ {
+ WebSocketHttpServerHandler obj = sender as WebSocketHttpServerHandler;
+ obj.SendMessage(text.Data);
+ m_log.Info("[WebSocketEchoModule]: We received this: " + text.Data);
+ }
+
+ // Remove the references to our handler
+ private void HandlerOnOnClose(object sender, CloseEventArgs closedata)
+ {
+ WebSocketHttpServerHandler obj = sender as WebSocketHttpServerHandler;
+ UnSubscribeToEvents(obj);
+
+ lock (_activeHandlers)
+ _activeHandlers.Remove(obj);
+ obj.Dispose();
+ }
+
+ // Shutting down.. so shut down all sockets.
+ // Note.. this should be done outside of an ienumerable if you're also hook to the close event.
+ public void Close()
+ {
+ if (!enabled)
+ return;
+
+ // We convert this to a for loop so we're not in in an IEnumerable when the close
+ //call triggers an event which then removes item from _activeHandlers that we're enumerating
+ WebSocketHttpServerHandler[] items = new WebSocketHttpServerHandler[_activeHandlers.Count];
+ _activeHandlers.CopyTo(items);
+
+ for (int i = 0; i < items.Length; i++)
+ {
+ items[i].Close(string.Empty);
+ items[i].Dispose();
+ }
+ _activeHandlers.Clear();
+ MainServer.Instance.RemoveWebSocketHandler("/echo");
+ }
+
+ public void AddRegion(Scene scene)
+ {
+ m_log.DebugFormat("[WebSocketEchoModule]: REGION {0} ADDED", scene.RegionInfo.RegionName);
+ }
+
+ public void RemoveRegion(Scene scene)
+ {
+ m_log.DebugFormat("[WebSocketEchoModule]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
+ }
+
+ public void RegionLoaded(Scene scene)
+ {
+ m_log.DebugFormat("[WebSocketEchoModule]: REGION {0} LOADED", scene.RegionInfo.RegionName);
+ }
+ }
+}
\ No newline at end of file
--
cgit v1.1
From a5c83f7505bf897c2d445391802f1ac7a2143d3d Mon Sep 17 00:00:00 2001
From: teravus
Date: Thu, 7 Feb 2013 12:22:03 -0500
Subject: Websocket Echo module should not be on by default.
---
.../OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs b/OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs
index 34e20b7..112ba4e 100644
--- a/OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs
+++ b/OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.OptionalModules.WebSocketEchoModule
public void Initialise(IConfigSource pConfig)
{
- enabled = true;// (pConfig.Configs["WebSocketEcho"] != null);
+ enabled =(pConfig.Configs["WebSocketEcho"] != null);
if (enabled)
m_log.DebugFormat("[WebSocketEchoModule]: INITIALIZED MODULE");
}
--
cgit v1.1
From af73ea909cad78eee78bd4e9d9e3a42cf8856263 Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Wed, 6 Feb 2013 22:34:03 -0800
Subject: Change passed PhysicsParameter value from float to the more general
string value
---
.../PhysicsParameters/PhysicsParameters.cs | 19 +++-------
OpenSim/Region/Physics/BulletSPlugin/BSParam.cs | 34 +++++++++---------
OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 41 +++++++++++++++++-----
.../Region/Physics/Manager/IPhysicsParameters.cs | 6 ++--
4 files changed, 57 insertions(+), 43 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
index 40f7fbc..3083a33 100755
--- a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
+++ b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
@@ -146,7 +146,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
{
foreach (PhysParameterEntry ppe in physScene.GetParameterList())
{
- float val = 0.0f;
+ string val = string.Empty;
if (physScene.GetPhysicsParameter(ppe.name, out val))
{
WriteOut(" {0}/{1} = {2}", scene.RegionInfo.RegionName, ppe.name, val);
@@ -159,7 +159,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
}
else
{
- float val = 0.0f;
+ string val = string.Empty;
if (physScene.GetPhysicsParameter(parm, out val))
{
WriteOut(" {0}/{1} = {2}", scene.RegionInfo.RegionName, parm, val);
@@ -185,21 +185,12 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
return;
}
string parm = "xxx";
- float val = 0f;
+ string valparm = String.Empty;
uint localID = (uint)PhysParameterEntry.APPLY_TO_NONE; // set default value
try
{
parm = cmdparms[2];
- string valparm = cmdparms[3].ToLower();
- if (valparm == "true")
- val = PhysParameterEntry.NUMERIC_TRUE;
- else
- {
- if (valparm == "false")
- val = PhysParameterEntry.NUMERIC_FALSE;
- else
- val = float.Parse(valparm, Culture.NumberFormatInfo);
- }
+ valparm = cmdparms[3].ToLower();
if (cmdparms.Length > 4)
{
if (cmdparms[4].ToLower() == "all")
@@ -224,7 +215,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
IPhysicsParameters physScene = scene.PhysicsScene as IPhysicsParameters;
if (physScene != null)
{
- if (!physScene.SetPhysicsParameter(parm, val, localID))
+ if (!physScene.SetPhysicsParameter(parm, valparm, localID))
{
WriteError("Failed set of parameter '{0}' for region '{1}'", parm, scene.RegionInfo.RegionName);
}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 965c382..601c78c 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -641,24 +641,6 @@ public static class BSParam
return (b == ConfigurationParameters.numericTrue ? true : false);
}
- private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v)
- {
- BSScene physScene = pPhysScene;
- physScene.TaintedObject("BSParam.ResetBroadphasePoolTainted", delegate()
- {
- physScene.PE.ResetBroadphasePool(physScene.World);
- });
- }
-
- private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v)
- {
- BSScene physScene = pPhysScene;
- physScene.TaintedObject("BSParam.ResetConstraintSolver", delegate()
- {
- physScene.PE.ResetConstraintSolver(physScene.World);
- });
- }
-
// Search through the parameter definitions and return the matching
// ParameterDefn structure.
// Case does not matter as names are compared after converting to lower case.
@@ -722,6 +704,22 @@ public static class BSParam
}
}
+ private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v)
+ {
+ BSScene physScene = pPhysScene;
+ physScene.TaintedObject("BSParam.ResetBroadphasePoolTainted", delegate()
+ {
+ physScene.PE.ResetBroadphasePool(physScene.World);
+ });
+ }
+ private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v)
+ {
+ BSScene physScene = pPhysScene;
+ physScene.TaintedObject("BSParam.ResetConstraintSolver", delegate()
+ {
+ physScene.PE.ResetConstraintSolver(physScene.World);
+ });
+ }
}
}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 6cd72f2..f8a0c1e 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -876,14 +876,39 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// will use the next time since it's pinned and shared memory.
// Some of the values require calling into the physics engine to get the new
// value activated ('terrainFriction' for instance).
- public bool SetPhysicsParameter(string parm, float val, uint localID)
+ public bool SetPhysicsParameter(string parm, string val, uint localID)
{
bool ret = false;
+
+ float valf = 0f;
+ if (val.ToLower() == "true")
+ {
+ valf = PhysParameterEntry.NUMERIC_TRUE;
+ }
+ else
+ {
+ if (val.ToLower() == "false")
+ {
+ valf = PhysParameterEntry.NUMERIC_FALSE;
+ }
+ else
+ {
+ try
+ {
+ valf = float.Parse(val);
+ }
+ catch
+ {
+ valf = 0f;
+ }
+ }
+ }
+
BSParam.ParameterDefn theParam;
if (BSParam.TryGetParameter(parm, out theParam))
{
// Set the value in the C# code
- theParam.setter(this, parm, localID, val);
+ theParam.setter(this, parm, localID, valf);
// Optionally set the parameter in the unmanaged code
if (theParam.onObject != null)
@@ -898,16 +923,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
case PhysParameterEntry.APPLY_TO_NONE:
// This will cause a call into the physical world if some operation is specified (SetOnObject).
objectIDs.Add(TERRAIN_ID);
- TaintedUpdateParameter(parm, objectIDs, val);
+ TaintedUpdateParameter(parm, objectIDs, valf);
break;
case PhysParameterEntry.APPLY_TO_ALL:
lock (PhysObjects) objectIDs = new List(PhysObjects.Keys);
- TaintedUpdateParameter(parm, objectIDs, val);
+ TaintedUpdateParameter(parm, objectIDs, valf);
break;
default:
// setting only one localID
objectIDs.Add(localID);
- TaintedUpdateParameter(parm, objectIDs, val);
+ TaintedUpdateParameter(parm, objectIDs, valf);
break;
}
}
@@ -942,14 +967,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// Get parameter.
// Return 'false' if not able to get the parameter.
- public bool GetPhysicsParameter(string parm, out float value)
+ public bool GetPhysicsParameter(string parm, out string value)
{
- float val = 0f;
+ string val = String.Empty;
bool ret = false;
BSParam.ParameterDefn theParam;
if (BSParam.TryGetParameter(parm, out theParam))
{
- val = theParam.getter(this);
+ val = theParam.getter(this).ToString();
ret = true;
}
value = val;
diff --git a/OpenSim/Region/Physics/Manager/IPhysicsParameters.cs b/OpenSim/Region/Physics/Manager/IPhysicsParameters.cs
index b8676ba..31a397c 100755
--- a/OpenSim/Region/Physics/Manager/IPhysicsParameters.cs
+++ b/OpenSim/Region/Physics/Manager/IPhysicsParameters.cs
@@ -60,14 +60,14 @@ namespace OpenSim.Region.Physics.Manager
// Set parameter on a specific or all instances.
// Return 'false' if not able to set the parameter.
- bool SetPhysicsParameter(string parm, float value, uint localID);
+ bool SetPhysicsParameter(string parm, string value, uint localID);
// Get parameter.
// Return 'false' if not able to get the parameter.
- bool GetPhysicsParameter(string parm, out float value);
+ bool GetPhysicsParameter(string parm, out string value);
// Get parameter from a particular object
// TODO:
- // bool GetPhysicsParameter(string parm, out float value, uint localID);
+ // bool GetPhysicsParameter(string parm, out string value, uint localID);
}
}
--
cgit v1.1
From c658fa1c0dd83f23c66ccfedb12e8ab02ff01d0a Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Thu, 7 Feb 2013 11:05:21 -0800
Subject: Add plumbing for physics properties to get to the physics engine.
Addition of entries to PhysicsActor and setting code in SceneObjectPart.
---
OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 56 +++++++++++++++++++---
OpenSim/Region/Physics/Manager/PhysicsActor.cs | 5 ++
2 files changed, 55 insertions(+), 6 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index b00f388..a3c7ed3 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -1387,10 +1387,46 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- public float Density { get; set; }
- public float GravityModifier { get; set; }
- public float Friction { get; set; }
- public float Restitution { get; set; }
+ private float m_density = 10f;
+ public float Density {
+ get { return m_density; }
+ set
+ {
+ m_density = value;
+ if (PhysActor != null)
+ PhysActor.Density = m_density;
+ }
+ }
+ private float m_gravityModifier = 1f;
+ public float GravityModifier {
+ get { return m_gravityModifier; }
+ set
+ {
+ m_gravityModifier = value;
+ if (PhysActor != null)
+ PhysActor.GravityModifier = m_gravityModifier;
+ }
+ }
+ private float m_friction = 0.5f;
+ public float Friction {
+ get { return m_friction; }
+ set
+ {
+ m_friction = value;
+ if (PhysActor != null)
+ PhysActor.Friction = m_friction;
+ }
+ }
+ private float m_restitution = 0f;
+ public float Restitution {
+ get { return m_restitution; }
+ set
+ {
+ m_restitution = value;
+ if (PhysActor != null)
+ PhysActor.Restitution = m_restitution;
+ }
+ }
#endregion Public Properties with only Get
@@ -1896,8 +1932,18 @@ namespace OpenSim.Region.Framework.Scenes
{
ParentGroup.Scene.AddPhysicalPrim(1);
+ // Update initial values for various physical properties
+ pa.SetMaterial(Material);
+ pa.Density = Density;
+ pa.Friction = Friction;
+ pa.Restitution = Restitution;
+ pa.GravityModifier = GravityModifier;
+
+ // Link up callbacks for property updates from the physics engine
pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
pa.OnOutOfBounds += PhysicsOutOfBounds;
+
+ // If this is a child prim, tell the physics engine about the parent
if (ParentID != 0 && ParentID != LocalId)
{
PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
@@ -4062,7 +4108,6 @@ namespace OpenSim.Region.Framework.Scenes
if (pa != null)
{
- pa.SetMaterial(Material);
DoPhysicsPropertyUpdate(UsePhysics, true);
if (
@@ -4175,7 +4220,6 @@ namespace OpenSim.Region.Framework.Scenes
if (pa != null)
{
pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
- pa.SetMaterial(Material);
DoPhysicsPropertyUpdate(rigidBody, true);
}
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index d119791..4820ca4 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -235,6 +235,11 @@ namespace OpenSim.Region.Physics.Manager
public abstract float Mass { get; }
public abstract Vector3 Force { get; set; }
+ public virtual float Density { get; set; }
+ public virtual float Friction { get; set; }
+ public virtual float Restitution { get; set; }
+ public virtual float GravityModifier { get; set; }
+
public abstract int VehicleType { get; set; }
public abstract void VehicleFloatParam(int param, float value);
public abstract void VehicleVectorParam(int param, Vector3 value);
--
cgit v1.1
From 9089757ea2cabe49f40de64b7e6befa13a4553c1 Mon Sep 17 00:00:00 2001
From: Melanie
Date: Thu, 7 Feb 2013 21:05:58 +0000
Subject: Revert "Add plumbing for physics properties to get to the physics
engine."
This reverts commit c658fa1c0dd83f23c66ccfedb12e8ab02ff01d0a.
---
OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 56 +++-------------------
OpenSim/Region/Physics/Manager/PhysicsActor.cs | 5 --
2 files changed, 6 insertions(+), 55 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index a3c7ed3..b00f388 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -1387,46 +1387,10 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- private float m_density = 10f;
- public float Density {
- get { return m_density; }
- set
- {
- m_density = value;
- if (PhysActor != null)
- PhysActor.Density = m_density;
- }
- }
- private float m_gravityModifier = 1f;
- public float GravityModifier {
- get { return m_gravityModifier; }
- set
- {
- m_gravityModifier = value;
- if (PhysActor != null)
- PhysActor.GravityModifier = m_gravityModifier;
- }
- }
- private float m_friction = 0.5f;
- public float Friction {
- get { return m_friction; }
- set
- {
- m_friction = value;
- if (PhysActor != null)
- PhysActor.Friction = m_friction;
- }
- }
- private float m_restitution = 0f;
- public float Restitution {
- get { return m_restitution; }
- set
- {
- m_restitution = value;
- if (PhysActor != null)
- PhysActor.Restitution = m_restitution;
- }
- }
+ public float Density { get; set; }
+ public float GravityModifier { get; set; }
+ public float Friction { get; set; }
+ public float Restitution { get; set; }
#endregion Public Properties with only Get
@@ -1932,18 +1896,8 @@ namespace OpenSim.Region.Framework.Scenes
{
ParentGroup.Scene.AddPhysicalPrim(1);
- // Update initial values for various physical properties
- pa.SetMaterial(Material);
- pa.Density = Density;
- pa.Friction = Friction;
- pa.Restitution = Restitution;
- pa.GravityModifier = GravityModifier;
-
- // Link up callbacks for property updates from the physics engine
pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
pa.OnOutOfBounds += PhysicsOutOfBounds;
-
- // If this is a child prim, tell the physics engine about the parent
if (ParentID != 0 && ParentID != LocalId)
{
PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
@@ -4108,6 +4062,7 @@ namespace OpenSim.Region.Framework.Scenes
if (pa != null)
{
+ pa.SetMaterial(Material);
DoPhysicsPropertyUpdate(UsePhysics, true);
if (
@@ -4220,6 +4175,7 @@ namespace OpenSim.Region.Framework.Scenes
if (pa != null)
{
pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
+ pa.SetMaterial(Material);
DoPhysicsPropertyUpdate(rigidBody, true);
}
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index 4820ca4..d119791 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -235,11 +235,6 @@ namespace OpenSim.Region.Physics.Manager
public abstract float Mass { get; }
public abstract Vector3 Force { get; set; }
- public virtual float Density { get; set; }
- public virtual float Friction { get; set; }
- public virtual float Restitution { get; set; }
- public virtual float GravityModifier { get; set; }
-
public abstract int VehicleType { get; set; }
public abstract void VehicleFloatParam(int param, float value);
public abstract void VehicleVectorParam(int param, Vector3 value);
--
cgit v1.1
From 338b02a8bc51d1dc5c1161a2a5a10b85521d1f8e Mon Sep 17 00:00:00 2001
From: Melanie
Date: Thu, 7 Feb 2013 21:23:35 +0000
Subject: Send the new physics params to the viewer build dialog
---
.../Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 35 ++++++++++++++++++++++
1 file changed, 35 insertions(+)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 568e216..1af61db 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -96,6 +96,8 @@ namespace OpenSim.Region.ClientStack.Linden
// private static readonly string m_fetchInventoryPath = "0006/";
private static readonly string m_copyFromNotecardPath = "0007/";
// private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule.
+ private static readonly string m_getObjectPhysicsDataPath = "0101/";
+ /* 0102 - 0103 RESERVED */
private static readonly string m_UpdateAgentInformationPath = "0500/";
// These are callbacks which will be setup by the scene so that we can update scene data when we
@@ -204,6 +206,8 @@ namespace OpenSim.Region.ClientStack.Linden
m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
+ IRequestHandler getObjectPhysicsDataHandler = new RestStreamHandler("POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData);
+ m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
IRequestHandler UpdateAgentInformationHandler = new RestStreamHandler("POST", capsBase + m_UpdateAgentInformationPath, UpdateAgentInformation);
m_HostCapsObj.RegisterHandler("UpdateAgentInformation", UpdateAgentInformationHandler);
@@ -873,6 +877,37 @@ namespace OpenSim.Region.ClientStack.Linden
return LLSDHelpers.SerialiseLLSDReply(response);
}
+ public string GetObjectPhysicsData(string request, string path,
+ string param, IOSHttpRequest httpRequest,
+ IOSHttpResponse httpResponse)
+ {
+ OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
+ OSDMap resp = new OSDMap();
+ OSDArray object_ids = (OSDArray)req["object_ids"];
+
+ for (int i = 0 ; i < object_ids.Count ; i++)
+ {
+ UUID uuid = object_ids[i].AsUUID();
+
+ SceneObjectPart obj = m_Scene.GetSceneObjectPart(uuid);
+ if (obj != null)
+ {
+ OSDMap object_data = new OSDMap();
+
+ object_data["PhysicsShapeType"] = obj.PhysicsShapeType;
+ object_data["Density"] = obj.Density;
+ object_data["Friction"] = obj.Friction;
+ object_data["Restitution"] = obj.Restitution;
+ object_data["GravityMultiplier"] = obj.GravityModifier;
+
+ resp[uuid.ToString()] = object_data;
+ }
+ }
+
+ string response = OSDParser.SerializeLLSDXmlString(resp);
+ return response;
+ }
+
public string UpdateAgentInformation(string request, string path,
string param, IOSHttpRequest httpRequest,
IOSHttpResponse httpResponse)
--
cgit v1.1
From 7bf33d333af6e7393a05940d1ab436f5dce73814 Mon Sep 17 00:00:00 2001
From: Melanie
Date: Thu, 7 Feb 2013 22:25:28 +0000
Subject: Plumb the path from the client to the extra physics params and back
---
OpenSim/Framework/IClientAPI.cs | 4 +-
.../Linden/Caps/EventQueue/EventQueueGetModule.cs | 8 +++
.../Linden/Caps/EventQueue/EventQueueHelper.cs | 20 ++++++++
.../Region/ClientStack/Linden/UDP/LLClientView.cs | 59 ++++++++++++++++++++--
OpenSim/Region/Framework/Interfaces/IEventQueue.cs | 2 +
OpenSim/Region/Framework/Scenes/SceneGraph.cs | 25 ++++++++-
OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 1 +
.../Server/IRCClientView.cs | 5 ++
.../Region/OptionalModules/World/NPC/NPCAvatar.cs | 5 ++
OpenSim/Tests/Common/Mock/TestClient.cs | 5 ++
10 files changed, 127 insertions(+), 7 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 87433cc..f6b7689 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -124,7 +124,7 @@ namespace OpenSim.Framework
public delegate void ObjectDrop(uint localID, IClientAPI remoteClient);
public delegate void UpdatePrimFlags(
- uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom, IClientAPI remoteClient);
+ uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient);
public delegate void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient);
@@ -1356,6 +1356,8 @@ namespace OpenSim.Framework
void SendObjectPropertiesReply(ISceneEntity Entity);
+ void SendPartPhysicsProprieties(ISceneEntity Entity);
+
void SendAgentOffline(UUID[] agentIDs);
void SendAgentOnline(UUID[] agentIDs);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index 4d2c0f2..3cc3950 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -807,5 +807,13 @@ namespace OpenSim.Region.ClientStack.Linden
{
return EventQueueHelper.BuildEvent(eventName, eventBody);
}
+
+ public void partPhysicsProperties(uint localID, byte physhapetype,
+ float density, float friction, float bounce, float gravmod,UUID avatarID)
+ {
+ OSD item = EventQueueHelper.partPhysicsProperties(localID, physhapetype,
+ density, friction, bounce, gravmod);
+ Enqueue(item, avatarID);
+ }
}
}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
index 3f49aba..dab727f 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
@@ -395,5 +395,25 @@ namespace OpenSim.Region.ClientStack.Linden
return message;
}
+ public static OSD partPhysicsProperties(uint localID, byte physhapetype,
+ float density, float friction, float bounce, float gravmod)
+ {
+
+ OSDMap physinfo = new OSDMap(6);
+ physinfo["LocalID"] = localID;
+ physinfo["Density"] = density;
+ physinfo["Friction"] = friction;
+ physinfo["GravityMultiplier"] = gravmod;
+ physinfo["Restitution"] = bounce;
+ physinfo["PhysicsShapeType"] = (int)physhapetype;
+
+ OSDArray array = new OSDArray(1);
+ array.Add(physinfo);
+
+ OSDMap llsdBody = new OSDMap(1);
+ llsdBody.Add("ObjectData", array);
+
+ return BuildEvent("ObjectPhysicsProperties", llsdBody);
+ }
}
}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 88b64f5..bd4a2d1 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -2627,6 +2627,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
+ public void SendPartPhysicsProprieties(ISceneEntity entity)
+ {
+ SceneObjectPart part = (SceneObjectPart)entity;
+ if (part != null && AgentId != UUID.Zero)
+ {
+ try
+ {
+ IEventQueue eq = Scene.RequestModuleInterface();
+ if (eq != null)
+ {
+ uint localid = part.LocalId;
+ byte physshapetype = part.PhysicsShapeType;
+ float density = part.Density;
+ float friction = part.Friction;
+ float bounce = part.Restitution;
+ float gravmod = part.GravityModifier;
+ eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId);
+ }
+ }
+ catch (Exception ex)
+ {
+ m_log.Error("Unable to send part Physics Proprieties - exception: " + ex.ToString());
+ }
+ part.UpdatePhysRequired = false;
+ }
+ }
+
+
public void SendGroupNameReply(UUID groupLLUID, string GroupName)
{
@@ -7035,10 +7063,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// 46,47,48 are special positions within the packet
// This may change so perhaps we need a better way
// of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?)
- bool UsePhysics = (data[46] != 0) ? true : false;
- bool IsTemporary = (data[47] != 0) ? true : false;
- bool IsPhantom = (data[48] != 0) ? true : false;
- handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this);
+ /*
+ bool UsePhysics = (data[46] != 0) ? true : false;
+ bool IsTemporary = (data[47] != 0) ? true : false;
+ bool IsPhantom = (data[48] != 0) ? true : false;
+ handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this);
+ */
+ bool UsePhysics = flags.AgentData.UsePhysics;
+ bool IsPhantom = flags.AgentData.IsPhantom;
+ bool IsTemporary = flags.AgentData.IsTemporary;
+ ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks = flags.ExtraPhysics;
+ ExtraPhysicsData physdata = new ExtraPhysicsData();
+
+ if (blocks == null || blocks.Length == 0)
+ {
+ physdata.PhysShapeType = PhysShapeType.invalid;
+ }
+ else
+ {
+ ObjectFlagUpdatePacket.ExtraPhysicsBlock phsblock = blocks[0];
+ physdata.PhysShapeType = (PhysShapeType)phsblock.PhysicsShapeType;
+ physdata.Bounce = phsblock.Restitution;
+ physdata.Density = phsblock.Density;
+ physdata.Friction = phsblock.Friction;
+ physdata.GravitationModifier = phsblock.GravityMultiplier;
+ }
+
+ handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, this);
}
return true;
}
diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
index bfa5d17..5512642 100644
--- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
@@ -59,5 +59,7 @@ namespace OpenSim.Region.Framework.Interfaces
void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID);
OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono);
OSD BuildEvent(string eventName, OSD eventBody);
+ void partPhysicsProperties(uint localID, byte physhapetype, float density, float friction, float bounce, float gravmod, UUID avatarID);
+
}
}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index a4383fd..a84f6d3 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -1408,7 +1408,7 @@ namespace OpenSim.Region.Framework.Scenes
///
///
protected internal void UpdatePrimFlags(
- uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, IClientAPI remoteClient)
+ uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient)
{
SceneObjectGroup group = GetGroupByPrim(localID);
if (group != null)
@@ -1416,7 +1416,28 @@ namespace OpenSim.Region.Framework.Scenes
if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
{
// VolumeDetect can't be set via UI and will always be off when a change is made there
- group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false);
+ // now only change volume dtc if phantom off
+
+ if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data
+ {
+ bool vdtc;
+ if (SetPhantom) // if phantom keep volumedtc
+ vdtc = group.RootPart.VolumeDetectActive;
+ else // else turn it off
+ vdtc = false;
+
+ group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, vdtc);
+ }
+ else
+ {
+ SceneObjectPart part = GetSceneObjectPart(localID);
+ if (part != null)
+ {
+ part.UpdateExtraPhysics(PhysData);
+ if (part.UpdatePhysRequired)
+ remoteClient.SendPartPhysicsProprieties(part);
+ }
+ }
}
}
}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index b00f388..cd40b29 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -1042,6 +1042,7 @@ namespace OpenSim.Region.Framework.Scenes
}
public UpdateRequired UpdateFlag { get; set; }
+ public bool UpdatePhysRequired { get; set; }
///
/// Used for media on a prim.
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 781539a..0ac56fa 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -1678,5 +1678,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
public void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data)
{
}
+
+ public void SendPartPhysicsProprieties(ISceneEntity entity)
+ {
+ }
+
}
}
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 5ea2bcd..6bd27f0 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -1234,5 +1234,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data)
{
}
+
+ public void SendPartPhysicsProprieties(ISceneEntity entity)
+ {
+ }
+
}
}
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index dde37ab..182f4d9 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -1276,5 +1276,10 @@ namespace OpenSim.Tests.Common.Mock
public void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data)
{
}
+
+ public void SendPartPhysicsProprieties(ISceneEntity entity)
+ {
+ }
+
}
}
--
cgit v1.1