Update svn properties.
parent
f8a6ef2d50
commit
74940c7b1d
|
@ -1,30 +1,30 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using OpenSim.Region.Environment.Modules.Terrain;
|
using OpenSim.Region.Environment.Modules.Terrain;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules.Terrain.FloodBrushes
|
namespace OpenSim.Region.Environment.Modules.Terrain.FloodBrushes
|
||||||
{
|
{
|
||||||
class RaiseArea : ITerrainFloodEffect
|
class RaiseArea : ITerrainFloodEffect
|
||||||
{
|
{
|
||||||
#region ITerrainFloodEffect Members
|
#region ITerrainFloodEffect Members
|
||||||
|
|
||||||
public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength)
|
public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
for (x = 0; x < map.Width; x++)
|
for (x = 0; x < map.Width; x++)
|
||||||
{
|
{
|
||||||
for (y = 0; y < map.Height; y++)
|
for (y = 0; y < map.Height; y++)
|
||||||
{
|
{
|
||||||
if (fillArea[x, y] == true)
|
if (fillArea[x, y] == true)
|
||||||
{
|
{
|
||||||
map[x, y] += strength;
|
map[x, y] += strength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,41 +1,41 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using OpenSim.Region.Environment.Modules.Terrain;
|
using OpenSim.Region.Environment.Modules.Terrain;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules.Terrain.PaintBrushes
|
namespace OpenSim.Region.Environment.Modules.Terrain.PaintBrushes
|
||||||
{
|
{
|
||||||
class RaiseSphere : ITerrainPaintableEffect
|
class RaiseSphere : ITerrainPaintableEffect
|
||||||
{
|
{
|
||||||
#region ITerrainPaintableEffect Members
|
#region ITerrainPaintableEffect Members
|
||||||
|
|
||||||
public void PaintEffect(ITerrainChannel map, double rx, double ry, double strength)
|
public void PaintEffect(ITerrainChannel map, double rx, double ry, double strength)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
for (x = 0; x < map.Width; x++)
|
for (x = 0; x < map.Width; x++)
|
||||||
{
|
{
|
||||||
// Skip everything unlikely to be affected
|
// Skip everything unlikely to be affected
|
||||||
if (Math.Abs(x - rx) > strength * 1.1)
|
if (Math.Abs(x - rx) > strength * 1.1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (y = 0; y < map.Height; y++)
|
for (y = 0; y < map.Height; y++)
|
||||||
{
|
{
|
||||||
// Skip everything unlikely to be affected
|
// Skip everything unlikely to be affected
|
||||||
if (Math.Abs(y - ry) > strength * 1.1)
|
if (Math.Abs(y - ry) > strength * 1.1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Calculate a sphere and add it to the heighmap
|
// Calculate a sphere and add it to the heighmap
|
||||||
double z = strength;
|
double z = strength;
|
||||||
z *= z;
|
z *= z;
|
||||||
z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry));
|
z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry));
|
||||||
|
|
||||||
if (z > 0.0)
|
if (z > 0.0)
|
||||||
map[x, y] += z;
|
map[x, y] += z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,343 +1,343 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Scenes;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Environment.Modules;
|
using OpenSim.Region.Environment.Modules;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
using Nini;
|
using Nini;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules.VoiceChat
|
namespace OpenSim.Region.Environment.Modules.VoiceChat
|
||||||
{
|
{
|
||||||
public class VoiceChatServer : IRegionModule
|
public class VoiceChatServer : IRegionModule
|
||||||
{
|
{
|
||||||
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
int m_dummySocketPort = 53134;
|
int m_dummySocketPort = 53134;
|
||||||
|
|
||||||
Thread m_listenerThread;
|
Thread m_listenerThread;
|
||||||
Thread m_mainThread;
|
Thread m_mainThread;
|
||||||
List<Scene> m_scenes = new List<Scene>();
|
List<Scene> m_scenes = new List<Scene>();
|
||||||
Socket m_server;
|
Socket m_server;
|
||||||
Socket m_selectCancel;
|
Socket m_selectCancel;
|
||||||
bool m_enabled = false;
|
bool m_enabled = false;
|
||||||
|
|
||||||
Dictionary<Socket, VoiceClient> m_clients = new Dictionary<Socket,VoiceClient>();
|
Dictionary<Socket, VoiceClient> m_clients = new Dictionary<Socket,VoiceClient>();
|
||||||
Dictionary<LLUUID, VoiceClient> m_uuidToClient = new Dictionary<LLUUID,VoiceClient>();
|
Dictionary<LLUUID, VoiceClient> m_uuidToClient = new Dictionary<LLUUID,VoiceClient>();
|
||||||
|
|
||||||
|
|
||||||
#region IRegionModule Members
|
#region IRegionModule Members
|
||||||
|
|
||||||
public void Initialise(Scene scene, Nini.Config.IConfigSource source)
|
public void Initialise(Scene scene, Nini.Config.IConfigSource source)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_enabled = source.Configs["Voice"].GetBoolean("enabled", m_enabled);
|
m_enabled = source.Configs["Voice"].GetBoolean("enabled", m_enabled);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
if (m_enabled)
|
if (m_enabled)
|
||||||
{
|
{
|
||||||
if (!m_scenes.Contains(scene))
|
if (!m_scenes.Contains(scene))
|
||||||
m_scenes.Add(scene);
|
m_scenes.Add(scene);
|
||||||
|
|
||||||
scene.EventManager.OnNewClient += NewClient;
|
scene.EventManager.OnNewClient += NewClient;
|
||||||
scene.EventManager.OnRemovePresence += RemovePresence;
|
scene.EventManager.OnRemovePresence += RemovePresence;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
{
|
{
|
||||||
if (m_enabled != true)
|
if (m_enabled != true)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CreateListeningSocket();
|
CreateListeningSocket();
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
m_log.Error("[VOICECHAT]: Unable to start listening");
|
m_log.Error("[VOICECHAT]: Unable to start listening");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_listenerThread = new Thread(new ThreadStart(ListenIncomingConnections));
|
m_listenerThread = new Thread(new ThreadStart(ListenIncomingConnections));
|
||||||
m_listenerThread.IsBackground = true;
|
m_listenerThread.IsBackground = true;
|
||||||
m_listenerThread.Start();
|
m_listenerThread.Start();
|
||||||
|
|
||||||
m_mainThread = new Thread(new ThreadStart(RunVoiceChat));
|
m_mainThread = new Thread(new ThreadStart(RunVoiceChat));
|
||||||
m_mainThread.IsBackground = true;
|
m_mainThread.IsBackground = true;
|
||||||
m_mainThread.Start();
|
m_mainThread.Start();
|
||||||
|
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
m_selectCancel = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
m_selectCancel = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
m_selectCancel.Connect("localhost", m_dummySocketPort);
|
m_selectCancel.Connect("localhost", m_dummySocketPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get { return "VoiceChatModule"; }
|
get { return "VoiceChatModule"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSharedModule
|
public bool IsSharedModule
|
||||||
{
|
{
|
||||||
get { return true; } // I think we can share this one.
|
get { return true; } // I think we can share this one.
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public void NewClient(IClientAPI client)
|
public void NewClient(IClientAPI client)
|
||||||
{
|
{
|
||||||
m_log.Info("[VOICECHAT]: New client: " + client.AgentId);
|
m_log.Info("[VOICECHAT]: New client: " + client.AgentId);
|
||||||
lock (m_uuidToClient)
|
lock (m_uuidToClient)
|
||||||
{
|
{
|
||||||
m_uuidToClient[client.AgentId] = null;
|
m_uuidToClient[client.AgentId] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemovePresence(LLUUID uuid)
|
public void RemovePresence(LLUUID uuid)
|
||||||
{
|
{
|
||||||
lock (m_uuidToClient)
|
lock (m_uuidToClient)
|
||||||
{
|
{
|
||||||
if (m_uuidToClient.ContainsKey(uuid))
|
if (m_uuidToClient.ContainsKey(uuid))
|
||||||
{
|
{
|
||||||
if (m_uuidToClient[uuid] != null)
|
if (m_uuidToClient[uuid] != null)
|
||||||
{
|
{
|
||||||
RemoveClient(m_uuidToClient[uuid].m_socket);
|
RemoveClient(m_uuidToClient[uuid].m_socket);
|
||||||
}
|
}
|
||||||
m_uuidToClient.Remove(uuid);
|
m_uuidToClient.Remove(uuid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log.Error("[VOICECHAT]: Presence not found on RemovePresence: " + uuid);
|
m_log.Error("[VOICECHAT]: Presence not found on RemovePresence: " + uuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AddClient(VoiceClient client, LLUUID uuid)
|
public bool AddClient(VoiceClient client, LLUUID uuid)
|
||||||
{
|
{
|
||||||
lock (m_uuidToClient)
|
lock (m_uuidToClient)
|
||||||
{
|
{
|
||||||
if (m_uuidToClient.ContainsKey(uuid))
|
if (m_uuidToClient.ContainsKey(uuid))
|
||||||
{
|
{
|
||||||
if (m_uuidToClient[uuid] != null) {
|
if (m_uuidToClient[uuid] != null) {
|
||||||
m_log.Warn("[VOICECHAT]: Multiple login attempts for " + uuid);
|
m_log.Warn("[VOICECHAT]: Multiple login attempts for " + uuid);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_uuidToClient[uuid] = client;
|
m_uuidToClient[uuid] = client;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveClient(Socket socket)
|
public void RemoveClient(Socket socket)
|
||||||
{
|
{
|
||||||
m_log.Info("[VOICECHAT]: Removing client");
|
m_log.Info("[VOICECHAT]: Removing client");
|
||||||
lock(m_clients)
|
lock(m_clients)
|
||||||
{
|
{
|
||||||
VoiceClient client = m_clients[socket];
|
VoiceClient client = m_clients[socket];
|
||||||
|
|
||||||
lock(m_uuidToClient)
|
lock(m_uuidToClient)
|
||||||
{
|
{
|
||||||
if (m_uuidToClient.ContainsKey(client.m_clientId))
|
if (m_uuidToClient.ContainsKey(client.m_clientId))
|
||||||
{
|
{
|
||||||
m_uuidToClient[client.m_clientId] = null;
|
m_uuidToClient[client.m_clientId] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_clients.Remove(socket);
|
m_clients.Remove(socket);
|
||||||
client.m_socket.Close();
|
client.m_socket.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void CreateListeningSocket()
|
protected void CreateListeningSocket()
|
||||||
{
|
{
|
||||||
IPEndPoint listenEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 12000);
|
IPEndPoint listenEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 12000);
|
||||||
m_server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
m_server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
m_server.Bind(listenEndPoint);
|
m_server.Bind(listenEndPoint);
|
||||||
m_server.Listen(50);
|
m_server.Listen(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListenIncomingConnections()
|
void ListenIncomingConnections()
|
||||||
{
|
{
|
||||||
m_log.Info("[VOICECHAT]: Listening connections...");
|
m_log.Info("[VOICECHAT]: Listening connections...");
|
||||||
//ServerStatus.ReportThreadName("VoiceChat: Connection listener");
|
//ServerStatus.ReportThreadName("VoiceChat: Connection listener");
|
||||||
|
|
||||||
byte[] dummyBuffer = new byte[1];
|
byte[] dummyBuffer = new byte[1];
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Socket connection = m_server.Accept();
|
Socket connection = m_server.Accept();
|
||||||
lock (m_clients)
|
lock (m_clients)
|
||||||
{
|
{
|
||||||
m_clients[connection] = new VoiceClient(connection, this);
|
m_clients[connection] = new VoiceClient(connection, this);
|
||||||
m_selectCancel.Send(dummyBuffer);
|
m_selectCancel.Send(dummyBuffer);
|
||||||
m_log.Info("[VOICECHAT]: Voicechat connection from " + connection.RemoteEndPoint.ToString());
|
m_log.Info("[VOICECHAT]: Voicechat connection from " + connection.RemoteEndPoint.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (SocketException e)
|
catch (SocketException e)
|
||||||
{
|
{
|
||||||
m_log.Error("[VOICECHAT]: During accept: " + e.ToString());
|
m_log.Error("[VOICECHAT]: During accept: " + e.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket ListenLoopbackSocket()
|
Socket ListenLoopbackSocket()
|
||||||
{
|
{
|
||||||
IPEndPoint listenEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), m_dummySocketPort);
|
IPEndPoint listenEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), m_dummySocketPort);
|
||||||
Socket dummyListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
Socket dummyListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
dummyListener.Bind(listenEndPoint);
|
dummyListener.Bind(listenEndPoint);
|
||||||
dummyListener.Listen(1);
|
dummyListener.Listen(1);
|
||||||
Socket socket = dummyListener.Accept();
|
Socket socket = dummyListener.Accept();
|
||||||
dummyListener.Close();
|
dummyListener.Close();
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunVoiceChat()
|
void RunVoiceChat()
|
||||||
{
|
{
|
||||||
m_log.Info("[VOICECHAT]: Connection handler started...");
|
m_log.Info("[VOICECHAT]: Connection handler started...");
|
||||||
//ServerStatus.ReportThreadName("VoiceChat: Connection handler");
|
//ServerStatus.ReportThreadName("VoiceChat: Connection handler");
|
||||||
|
|
||||||
//Listen a loopback socket for aborting select call
|
//Listen a loopback socket for aborting select call
|
||||||
Socket dummySocket = ListenLoopbackSocket();
|
Socket dummySocket = ListenLoopbackSocket();
|
||||||
|
|
||||||
List<Socket> sockets = new List<Socket>();
|
List<Socket> sockets = new List<Socket>();
|
||||||
byte[] buffer = new byte[65536];
|
byte[] buffer = new byte[65536];
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (m_clients.Count == 0)
|
if (m_clients.Count == 0)
|
||||||
{
|
{
|
||||||
Thread.Sleep(100);
|
Thread.Sleep(100);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (m_clients)
|
lock (m_clients)
|
||||||
{
|
{
|
||||||
foreach (Socket s in m_clients.Keys)
|
foreach (Socket s in m_clients.Keys)
|
||||||
{
|
{
|
||||||
sockets.Add(s);
|
sockets.Add(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sockets.Add(dummySocket);
|
sockets.Add(dummySocket);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Socket.Select(sockets, null, null, 200000);
|
Socket.Select(sockets, null, null, 200000);
|
||||||
}
|
}
|
||||||
catch (SocketException e)
|
catch (SocketException e)
|
||||||
{
|
{
|
||||||
m_log.Warn("[VOICECHAT]: " + e.Message);
|
m_log.Warn("[VOICECHAT]: " + e.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Socket s in sockets)
|
foreach (Socket s in sockets)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (s.RemoteEndPoint != dummySocket.RemoteEndPoint)
|
if (s.RemoteEndPoint != dummySocket.RemoteEndPoint)
|
||||||
{
|
{
|
||||||
ReceiveFromSocket(s, buffer);
|
ReceiveFromSocket(s, buffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Receive data and check if there was an error with select abort socket
|
//Receive data and check if there was an error with select abort socket
|
||||||
if (s.Receive(buffer) <= 0)
|
if (s.Receive(buffer) <= 0)
|
||||||
{
|
{
|
||||||
//Just give a warning for now
|
//Just give a warning for now
|
||||||
m_log.Error("[VOICECHAT]: Select abort socket was closed");
|
m_log.Error("[VOICECHAT]: Select abort socket was closed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(ObjectDisposedException e)
|
catch(ObjectDisposedException e)
|
||||||
{
|
{
|
||||||
m_log.Warn("[VOICECHAT]: Connection has been already closed");
|
m_log.Warn("[VOICECHAT]: Connection has been already closed");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.Error("[VOICECHAT]: Exception: " + e.Message);
|
m_log.Error("[VOICECHAT]: Exception: " + e.Message);
|
||||||
|
|
||||||
RemoveClient(s);
|
RemoveClient(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sockets.Clear();
|
sockets.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReceiveFromSocket( Socket s, byte[] buffer )
|
private void ReceiveFromSocket( Socket s, byte[] buffer )
|
||||||
{
|
{
|
||||||
int byteCount = s.Receive(buffer);
|
int byteCount = s.Receive(buffer);
|
||||||
if (byteCount <= 0)
|
if (byteCount <= 0)
|
||||||
{
|
{
|
||||||
m_log.Info("[VOICECHAT]: Connection lost to " + s.RemoteEndPoint);
|
m_log.Info("[VOICECHAT]: Connection lost to " + s.RemoteEndPoint);
|
||||||
lock (m_clients)
|
lock (m_clients)
|
||||||
{
|
{
|
||||||
RemoveClient(s);
|
RemoveClient(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//ServerStatus.ReportInPacketTcp(byteCount);
|
//ServerStatus.ReportInPacketTcp(byteCount);
|
||||||
lock (m_clients)
|
lock (m_clients)
|
||||||
{
|
{
|
||||||
if (m_clients.ContainsKey(s))
|
if (m_clients.ContainsKey(s))
|
||||||
{
|
{
|
||||||
m_clients[s].OnDataReceived(buffer, byteCount);
|
m_clients[s].OnDataReceived(buffer, byteCount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log.Warn("[VOICECHAT]: Got data from " + s.RemoteEndPoint +
|
m_log.Warn("[VOICECHAT]: Got data from " + s.RemoteEndPoint +
|
||||||
", but source is not a valid voice client");
|
", but source is not a valid voice client");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LLVector3 getScenePresencePosition(LLUUID clientID)
|
public LLVector3 getScenePresencePosition(LLUUID clientID)
|
||||||
{
|
{
|
||||||
foreach (Scene scene in m_scenes)
|
foreach (Scene scene in m_scenes)
|
||||||
{
|
{
|
||||||
ScenePresence x;
|
ScenePresence x;
|
||||||
if ((x = scene.GetScenePresence(clientID)) != null)
|
if ((x = scene.GetScenePresence(clientID)) != null)
|
||||||
{
|
{
|
||||||
return x.AbsolutePosition + new LLVector3(Constants.RegionSize * scene.RegionInfo.RegionLocX,
|
return x.AbsolutePosition + new LLVector3(Constants.RegionSize * scene.RegionInfo.RegionLocX,
|
||||||
Constants.RegionSize * scene.RegionInfo.RegionLocY, 0);
|
Constants.RegionSize * scene.RegionInfo.RegionLocY, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return LLVector3.Zero;
|
return LLVector3.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BroadcastVoice(VoicePacket packet)
|
public void BroadcastVoice(VoicePacket packet)
|
||||||
{
|
{
|
||||||
libsecondlife.LLVector3 origPos = getScenePresencePosition(packet.m_clientId);
|
libsecondlife.LLVector3 origPos = getScenePresencePosition(packet.m_clientId);
|
||||||
|
|
||||||
byte[] bytes = packet.GetBytes();
|
byte[] bytes = packet.GetBytes();
|
||||||
foreach (VoiceClient client in m_clients.Values)
|
foreach (VoiceClient client in m_clients.Values)
|
||||||
{
|
{
|
||||||
if (client.IsEnabled() && client.m_clientId != packet.m_clientId &&
|
if (client.IsEnabled() && client.m_clientId != packet.m_clientId &&
|
||||||
client.m_authenticated && client.IsCodecSupported(packet.m_codec))
|
client.m_authenticated && client.IsCodecSupported(packet.m_codec))
|
||||||
{
|
{
|
||||||
LLVector3 presenceLoc = getScenePresencePosition(client.m_clientId);
|
LLVector3 presenceLoc = getScenePresencePosition(client.m_clientId);
|
||||||
|
|
||||||
if (presenceLoc != LLVector3.Zero && Util.GetDistanceTo(presenceLoc, origPos) < 20)
|
if (presenceLoc != LLVector3.Zero && Util.GetDistanceTo(presenceLoc, origPos) < 20)
|
||||||
{
|
{
|
||||||
client.SendTo(bytes);
|
client.SendTo(bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,169 +1,169 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Scenes;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules.VoiceChat
|
namespace OpenSim.Region.Environment.Modules.VoiceChat
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Represents a single voiceclient instance
|
* Represents a single voiceclient instance
|
||||||
**/
|
**/
|
||||||
public class VoiceClient
|
public class VoiceClient
|
||||||
{
|
{
|
||||||
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
public Socket m_socket;
|
public Socket m_socket;
|
||||||
public LLUUID m_clientId;
|
public LLUUID m_clientId;
|
||||||
public bool m_authenticated = false;
|
public bool m_authenticated = false;
|
||||||
|
|
||||||
protected VoicePacketHeader m_header = null;
|
protected VoicePacketHeader m_header = null;
|
||||||
protected int m_headerBytesReceived = 0;
|
protected int m_headerBytesReceived = 0;
|
||||||
|
|
||||||
protected int m_offset = 0;
|
protected int m_offset = 0;
|
||||||
protected int m_supportedCodecs = 0;
|
protected int m_supportedCodecs = 0;
|
||||||
|
|
||||||
protected byte[] m_buffer = null;
|
protected byte[] m_buffer = null;
|
||||||
protected byte[] m_headerBytes = new byte[5];
|
protected byte[] m_headerBytes = new byte[5];
|
||||||
|
|
||||||
protected bool m_enabled = true;
|
protected bool m_enabled = true;
|
||||||
|
|
||||||
protected VoiceChatServer m_server;
|
protected VoiceChatServer m_server;
|
||||||
|
|
||||||
public VoiceClient(Socket socket, VoiceChatServer server)
|
public VoiceClient(Socket socket, VoiceChatServer server)
|
||||||
{
|
{
|
||||||
m_socket = socket;
|
m_socket = socket;
|
||||||
m_server = server;
|
m_server = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnDataReceived(byte[] data, int byteCount)
|
public void OnDataReceived(byte[] data, int byteCount)
|
||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
while (offset < byteCount)
|
while (offset < byteCount)
|
||||||
{
|
{
|
||||||
if (m_header == null)
|
if (m_header == null)
|
||||||
{
|
{
|
||||||
if (m_headerBytesReceived < 5)
|
if (m_headerBytesReceived < 5)
|
||||||
{
|
{
|
||||||
m_headerBytes[m_headerBytesReceived++] = data[offset++];
|
m_headerBytes[m_headerBytesReceived++] = data[offset++];
|
||||||
}
|
}
|
||||||
else if (m_headerBytesReceived == 5)
|
else if (m_headerBytesReceived == 5)
|
||||||
{
|
{
|
||||||
m_header = new VoicePacketHeader();
|
m_header = new VoicePacketHeader();
|
||||||
m_header.Parse(m_headerBytes);
|
m_header.Parse(m_headerBytes);
|
||||||
if (m_header.length > 65535)
|
if (m_header.length > 65535)
|
||||||
{
|
{
|
||||||
throw new Exception("Packet size " + m_header.length + " > 65535");
|
throw new Exception("Packet size " + m_header.length + " > 65535");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_buffer = new byte[m_header.length];
|
m_buffer = new byte[m_header.length];
|
||||||
m_offset = 0;
|
m_offset = 0;
|
||||||
m_headerBytesReceived = 0;
|
m_headerBytesReceived = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int bytesToCopy = m_header.length-m_offset;
|
int bytesToCopy = m_header.length-m_offset;
|
||||||
if (bytesToCopy > byteCount - offset)
|
if (bytesToCopy > byteCount - offset)
|
||||||
bytesToCopy = byteCount - offset;
|
bytesToCopy = byteCount - offset;
|
||||||
|
|
||||||
Buffer.BlockCopy(data, offset, m_buffer, m_offset, bytesToCopy);
|
Buffer.BlockCopy(data, offset, m_buffer, m_offset, bytesToCopy);
|
||||||
|
|
||||||
offset += bytesToCopy;
|
offset += bytesToCopy;
|
||||||
m_offset += bytesToCopy;
|
m_offset += bytesToCopy;
|
||||||
|
|
||||||
if (m_offset == m_header.length)
|
if (m_offset == m_header.length)
|
||||||
{
|
{
|
||||||
ParsePacket(m_header.type, m_buffer);
|
ParsePacket(m_header.type, m_buffer);
|
||||||
m_header = null;
|
m_header = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParsePacket(byte type, byte[] data)
|
void ParsePacket(byte type, byte[] data)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case 0: //LOGIN
|
case 0: //LOGIN
|
||||||
ParseLogin(data);
|
ParseLogin(data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: //AUDIODATA
|
case 1: //AUDIODATA
|
||||||
if (m_authenticated)
|
if (m_authenticated)
|
||||||
{
|
{
|
||||||
VoicePacket packet = new VoicePacket(data);
|
VoicePacket packet = new VoicePacket(data);
|
||||||
packet.m_clientId = m_clientId;
|
packet.m_clientId = m_clientId;
|
||||||
m_server.BroadcastVoice(packet);
|
m_server.BroadcastVoice(packet);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log.Warn("[VOICECHAT]: Got unauthorized audio data from " +
|
m_log.Warn("[VOICECHAT]: Got unauthorized audio data from " +
|
||||||
m_socket.RemoteEndPoint.ToString());
|
m_socket.RemoteEndPoint.ToString());
|
||||||
m_socket.Close();
|
m_socket.Close();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: //ENABLEVOIP
|
case 3: //ENABLEVOIP
|
||||||
if (data[0] == 0)
|
if (data[0] == 0)
|
||||||
{
|
{
|
||||||
m_log.Warn("[VOICECHAT]: VoiceChat has been disabled for " + m_clientId);
|
m_log.Warn("[VOICECHAT]: VoiceChat has been disabled for " + m_clientId);
|
||||||
m_enabled = false;
|
m_enabled = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log.Warn("[VOICECHAT]: VoiceChat has been enabled for " + m_clientId);
|
m_log.Warn("[VOICECHAT]: VoiceChat has been enabled for " + m_clientId);
|
||||||
m_enabled = true;
|
m_enabled = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Exception("Invalid packet received");
|
throw new Exception("Invalid packet received");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseLogin(byte[] data)
|
void ParseLogin(byte[] data)
|
||||||
{
|
{
|
||||||
m_clientId = new LLUUID(data, 0);
|
m_clientId = new LLUUID(data, 0);
|
||||||
|
|
||||||
m_supportedCodecs = data[16];
|
m_supportedCodecs = data[16];
|
||||||
m_supportedCodecs |= data[17] << 8;
|
m_supportedCodecs |= data[17] << 8;
|
||||||
m_supportedCodecs |= data[18] << 16;
|
m_supportedCodecs |= data[18] << 16;
|
||||||
m_supportedCodecs |= data[19] << 24;
|
m_supportedCodecs |= data[19] << 24;
|
||||||
|
|
||||||
if (m_server.AddClient(this, m_clientId))
|
if (m_server.AddClient(this, m_clientId))
|
||||||
{
|
{
|
||||||
m_log.Info("[VOICECHAT]: Client authenticated succesfully: " + m_clientId);
|
m_log.Info("[VOICECHAT]: Client authenticated succesfully: " + m_clientId);
|
||||||
m_authenticated = true;
|
m_authenticated = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Exception("Unable to authenticate with id " + m_clientId);
|
throw new Exception("Unable to authenticate with id " + m_clientId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEnabled()
|
public bool IsEnabled()
|
||||||
{
|
{
|
||||||
return m_enabled;
|
return m_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsCodecSupported(int codec)
|
public bool IsCodecSupported(int codec)
|
||||||
{
|
{
|
||||||
if ((m_supportedCodecs & codec) != 0)
|
if ((m_supportedCodecs & codec) != 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendTo(byte[] data)
|
public void SendTo(byte[] data)
|
||||||
{
|
{
|
||||||
if (m_authenticated)
|
if (m_authenticated)
|
||||||
{
|
{
|
||||||
//ServerStatus.ReportOutPacketTcp(m_socket.Send(data));
|
//ServerStatus.ReportOutPacketTcp(m_socket.Send(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,58 +1,58 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules.VoiceChat
|
namespace OpenSim.Region.Environment.Modules.VoiceChat
|
||||||
{
|
{
|
||||||
public enum VoiceCodec
|
public enum VoiceCodec
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
PCM8 = 1 << 0,
|
PCM8 = 1 << 0,
|
||||||
PCM16 = 1 << 1,
|
PCM16 = 1 << 1,
|
||||||
PCM32 = 1 << 2,
|
PCM32 = 1 << 2,
|
||||||
Speex = 1 << 3,
|
Speex = 1 << 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
public class VoicePacket
|
public class VoicePacket
|
||||||
{
|
{
|
||||||
public LLUUID m_clientId;
|
public LLUUID m_clientId;
|
||||||
byte[] m_audioData;
|
byte[] m_audioData;
|
||||||
public int m_codec;
|
public int m_codec;
|
||||||
|
|
||||||
public VoicePacket(byte[] data)
|
public VoicePacket(byte[] data)
|
||||||
{
|
{
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
m_codec = data[pos++];
|
m_codec = data[pos++];
|
||||||
m_codec |= data[pos++] << 8;
|
m_codec |= data[pos++] << 8;
|
||||||
m_codec |= data[pos++] << 16;
|
m_codec |= data[pos++] << 16;
|
||||||
m_codec |= data[pos++] << 24;
|
m_codec |= data[pos++] << 24;
|
||||||
|
|
||||||
m_audioData = new byte[data.Length - pos];
|
m_audioData = new byte[data.Length - pos];
|
||||||
Buffer.BlockCopy(data, pos, m_audioData, 0, data.Length - pos);
|
Buffer.BlockCopy(data, pos, m_audioData, 0, data.Length - pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] GetBytes()
|
public byte[] GetBytes()
|
||||||
{
|
{
|
||||||
VoicePacketHeader header = new VoicePacketHeader();
|
VoicePacketHeader header = new VoicePacketHeader();
|
||||||
byte[] bytes = new byte[5+16+4+m_audioData.Length];
|
byte[] bytes = new byte[5+16+4+m_audioData.Length];
|
||||||
|
|
||||||
header.length = bytes.Length-5;
|
header.length = bytes.Length-5;
|
||||||
|
|
||||||
//ToClient packets are type 2
|
//ToClient packets are type 2
|
||||||
header.type = 2;
|
header.type = 2;
|
||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
header.CopyTo(bytes, pos); pos += 5;
|
header.CopyTo(bytes, pos); pos += 5;
|
||||||
m_clientId.GetBytes().CopyTo(bytes, pos); pos += 16;
|
m_clientId.GetBytes().CopyTo(bytes, pos); pos += 16;
|
||||||
|
|
||||||
bytes[pos++] = (byte)((m_codec) % 256);
|
bytes[pos++] = (byte)((m_codec) % 256);
|
||||||
bytes[pos++] = (byte)((m_codec << 8) % 256);
|
bytes[pos++] = (byte)((m_codec << 8) % 256);
|
||||||
bytes[pos++] = (byte)((m_codec << 16) % 256);
|
bytes[pos++] = (byte)((m_codec << 16) % 256);
|
||||||
bytes[pos++] = (byte)((m_codec << 24) % 256);
|
bytes[pos++] = (byte)((m_codec << 24) % 256);
|
||||||
|
|
||||||
m_audioData.CopyTo(bytes, pos);
|
m_audioData.CopyTo(bytes, pos);
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules.VoiceChat
|
namespace OpenSim.Region.Environment.Modules.VoiceChat
|
||||||
{
|
{
|
||||||
public class VoicePacketHeader
|
public class VoicePacketHeader
|
||||||
{
|
{
|
||||||
public byte type;
|
public byte type;
|
||||||
public int length;
|
public int length;
|
||||||
|
|
||||||
public void Parse(byte[] data)
|
public void Parse(byte[] data)
|
||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
type = data[offset++];
|
type = data[offset++];
|
||||||
|
|
||||||
length = data[offset++];
|
length = data[offset++];
|
||||||
length |= data[offset++] << 8;
|
length |= data[offset++] << 8;
|
||||||
length |= data[offset++] << 16;
|
length |= data[offset++] << 16;
|
||||||
length |= data[offset++] << 24;
|
length |= data[offset++] << 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyTo(byte[] data, int offset)
|
public void CopyTo(byte[] data, int offset)
|
||||||
{
|
{
|
||||||
data[offset + 0] = type;
|
data[offset + 0] = type;
|
||||||
|
|
||||||
data[offset + 1] = (byte)(length & 0x000000FF);
|
data[offset + 1] = (byte)(length & 0x000000FF);
|
||||||
data[offset + 2] = (byte)((length & 0x0000FF00) >> 8);
|
data[offset + 2] = (byte)((length & 0x0000FF00) >> 8);
|
||||||
data[offset + 3] = (byte)((length & 0x00FF0000) >> 16);
|
data[offset + 3] = (byte)((length & 0x00FF0000) >> 16);
|
||||||
data[offset + 4] = (byte)((length & 0xFF000000) >> 24);
|
data[offset + 4] = (byte)((length & 0xFF000000) >> 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetLength()
|
public int GetLength()
|
||||||
{
|
{
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue