mirror of
https://github.com/opensim/opensim.git
synced 2026-06-25 15:55:46 +08:00
197 lines
6.7 KiB
C#
197 lines
6.7 KiB
C#
/*
|
|
* 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 OpenSim 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.IO;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Net.Sockets;
|
|
using OpenSim.Region.Environment.Scenes;
|
|
using libsecondlife;
|
|
|
|
namespace OpenSim.Region.Environment.Modules.VoiceChat
|
|
{
|
|
/**
|
|
* Represents a single voiceclient instance
|
|
**/
|
|
public class VoiceClient
|
|
{
|
|
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
|
|
public Socket m_socket;
|
|
public LLUUID m_clientId;
|
|
public bool m_authenticated = false;
|
|
|
|
protected VoicePacketHeader m_header = null;
|
|
protected int m_headerBytesReceived = 0;
|
|
|
|
protected int m_offset = 0;
|
|
protected int m_supportedCodecs = 0;
|
|
|
|
protected byte[] m_buffer = null;
|
|
protected byte[] m_headerBytes = new byte[5];
|
|
|
|
protected bool m_enabled = true;
|
|
|
|
protected VoiceChatServer m_server;
|
|
|
|
public VoiceClient(Socket socket, VoiceChatServer server)
|
|
{
|
|
m_socket = socket;
|
|
m_server = server;
|
|
}
|
|
|
|
public void OnDataReceived(byte[] data, int byteCount)
|
|
{
|
|
int offset = 0;
|
|
while (offset < byteCount)
|
|
{
|
|
if (m_header == null)
|
|
{
|
|
if (m_headerBytesReceived < 5)
|
|
{
|
|
m_headerBytes[m_headerBytesReceived++] = data[offset++];
|
|
}
|
|
else if (m_headerBytesReceived == 5)
|
|
{
|
|
m_header = new VoicePacketHeader();
|
|
m_header.Parse(m_headerBytes);
|
|
if (m_header.length > 65535)
|
|
{
|
|
throw new Exception("Packet size " + m_header.length + " > 65535");
|
|
}
|
|
|
|
m_buffer = new byte[m_header.length];
|
|
m_offset = 0;
|
|
m_headerBytesReceived = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int bytesToCopy = m_header.length-m_offset;
|
|
if (bytesToCopy > byteCount - offset)
|
|
bytesToCopy = byteCount - offset;
|
|
|
|
Buffer.BlockCopy(data, offset, m_buffer, m_offset, bytesToCopy);
|
|
|
|
offset += bytesToCopy;
|
|
m_offset += bytesToCopy;
|
|
|
|
if (m_offset == m_header.length)
|
|
{
|
|
ParsePacket(m_header.type, m_buffer);
|
|
m_header = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ParsePacket(byte type, byte[] data)
|
|
{
|
|
switch (type)
|
|
{
|
|
case 0: //LOGIN
|
|
ParseLogin(data);
|
|
break;
|
|
|
|
case 1: //AUDIODATA
|
|
if (m_authenticated)
|
|
{
|
|
VoicePacket packet = new VoicePacket(data);
|
|
packet.m_clientId = m_clientId;
|
|
m_server.BroadcastVoice(packet);
|
|
}
|
|
else
|
|
{
|
|
m_log.Warn("[VOICECHAT]: Got unauthorized audio data from " +
|
|
m_socket.RemoteEndPoint.ToString());
|
|
m_socket.Close();
|
|
}
|
|
break;
|
|
|
|
case 3: //ENABLEVOIP
|
|
if (data[0] == 0)
|
|
{
|
|
m_log.Warn("[VOICECHAT]: VoiceChat has been disabled for " + m_clientId);
|
|
m_enabled = false;
|
|
}
|
|
else
|
|
{
|
|
m_log.Warn("[VOICECHAT]: VoiceChat has been enabled for " + m_clientId);
|
|
m_enabled = true;
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
throw new Exception("Invalid packet received");
|
|
}
|
|
}
|
|
|
|
void ParseLogin(byte[] data)
|
|
{
|
|
m_clientId = new LLUUID(data, 0);
|
|
|
|
m_supportedCodecs = data[16];
|
|
m_supportedCodecs |= data[17] << 8;
|
|
m_supportedCodecs |= data[18] << 16;
|
|
m_supportedCodecs |= data[19] << 24;
|
|
|
|
if (m_server.AddClient(this, m_clientId))
|
|
{
|
|
m_log.Info("[VOICECHAT]: Client authenticated succesfully: " + m_clientId);
|
|
m_authenticated = true;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Unable to authenticate with id " + m_clientId);
|
|
}
|
|
}
|
|
|
|
public bool IsEnabled()
|
|
{
|
|
return m_enabled;
|
|
}
|
|
|
|
public bool IsCodecSupported(int codec)
|
|
{
|
|
if ((m_supportedCodecs & codec) != 0)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
public void SendTo(byte[] data)
|
|
{
|
|
if (m_authenticated)
|
|
{
|
|
//ServerStatus.ReportOutPacketTcp(m_socket.Send(data));
|
|
}
|
|
}
|
|
}
|
|
}
|