174 lines
4.9 KiB
C#
174 lines
4.9 KiB
C#
using System;
|
|
|
|
namespace Barotrauma.Networking
|
|
{
|
|
class VoipQueue : IDisposable
|
|
{
|
|
public const int BUFFER_COUNT = 8;
|
|
protected int[] bufferLengths;
|
|
protected byte[][] buffers;
|
|
protected int newestBufferInd;
|
|
protected bool firstRead;
|
|
|
|
public int EnqueuedTotalLength
|
|
{
|
|
get
|
|
{
|
|
int enqueuedTotalLength = 0;
|
|
for (int i = 0; i < BUFFER_COUNT; i++)
|
|
{
|
|
enqueuedTotalLength += bufferLengths[i];
|
|
}
|
|
return enqueuedTotalLength;
|
|
}
|
|
}
|
|
|
|
public byte[] BufferToQueue
|
|
{
|
|
get;
|
|
protected set;
|
|
}
|
|
|
|
public virtual byte QueueID
|
|
{
|
|
get;
|
|
protected set;
|
|
}
|
|
|
|
public UInt16 LatestBufferID
|
|
{
|
|
get;
|
|
protected set;
|
|
}
|
|
|
|
public bool CanSend
|
|
{
|
|
get;
|
|
protected set;
|
|
}
|
|
|
|
public bool CanReceive
|
|
{
|
|
get;
|
|
protected set;
|
|
}
|
|
|
|
public bool ForceLocal
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public DateTime LastReadTime
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
public VoipQueue(byte id, bool canSend, bool canReceive)
|
|
{
|
|
BufferToQueue = new byte[VoipConfig.MAX_COMPRESSED_SIZE];
|
|
newestBufferInd = BUFFER_COUNT - 1;
|
|
bufferLengths = new int[BUFFER_COUNT];
|
|
buffers = new byte[BUFFER_COUNT][];
|
|
for (int i = 0; i < BUFFER_COUNT; i++)
|
|
{
|
|
buffers[i] = new byte[VoipConfig.MAX_COMPRESSED_SIZE];
|
|
}
|
|
QueueID = id;
|
|
CanSend = canSend;
|
|
CanReceive = canReceive;
|
|
LatestBufferID = BUFFER_COUNT - 1;
|
|
firstRead = true;
|
|
|
|
LastReadTime = DateTime.Now;
|
|
}
|
|
|
|
public void EnqueueBuffer(int length)
|
|
{
|
|
if (length > byte.MaxValue) { return; }
|
|
|
|
newestBufferInd = (newestBufferInd + 1) % BUFFER_COUNT;
|
|
|
|
int enqueuedTotalLength = EnqueuedTotalLength;
|
|
|
|
bufferLengths[newestBufferInd] = length;
|
|
BufferToQueue.CopyTo(buffers[newestBufferInd], 0);
|
|
|
|
if ((enqueuedTotalLength + length) > 0) { LatestBufferID++; }
|
|
}
|
|
|
|
public void RetrieveBuffer(int id, out int outSize, out byte[] outBuf)
|
|
{
|
|
lock (buffers)
|
|
{
|
|
if (id >= LatestBufferID - (BUFFER_COUNT - 1) && id <= LatestBufferID)
|
|
{
|
|
int index = newestBufferInd - (LatestBufferID - id);
|
|
if (index < 0) { index += BUFFER_COUNT; }
|
|
outSize = bufferLengths[index];
|
|
outBuf = buffers[index];
|
|
return;
|
|
}
|
|
}
|
|
outSize = -1;
|
|
outBuf = null;
|
|
}
|
|
|
|
public virtual void Write(IWriteMessage msg)
|
|
{
|
|
if (!CanSend) { throw new Exception("Called Write on a VoipQueue not set up for sending"); }
|
|
|
|
msg.WriteUInt16((UInt16)LatestBufferID);
|
|
msg.WriteBoolean(ForceLocal); msg.WritePadBits();
|
|
lock (buffers)
|
|
{
|
|
for (int i = 0; i < BUFFER_COUNT; i++)
|
|
{
|
|
int index = (newestBufferInd + i + 1) % BUFFER_COUNT;
|
|
|
|
msg.WriteByte((byte)bufferLengths[index]);
|
|
msg.WriteBytes(buffers[index], 0, bufferLengths[index]);
|
|
}
|
|
}
|
|
}
|
|
|
|
public virtual bool Read(IReadMessage msg, bool discardData = false)
|
|
{
|
|
if (!CanReceive) { throw new Exception("Called Read on a VoipQueue not set up for receiving"); }
|
|
|
|
UInt16 incLatestBufferID = msg.ReadUInt16();
|
|
if ((firstRead || NetIdUtils.IdMoreRecent(incLatestBufferID, LatestBufferID)) && !discardData)
|
|
{
|
|
ForceLocal = msg.ReadBoolean(); msg.ReadPadBits();
|
|
|
|
firstRead = false;
|
|
lock (buffers)
|
|
{
|
|
for (int i = 0; i < BUFFER_COUNT; i++)
|
|
{
|
|
bufferLengths[i] = msg.ReadByte();
|
|
buffers[i] = msg.ReadBytes(bufferLengths[i]);
|
|
}
|
|
}
|
|
newestBufferInd = BUFFER_COUNT - 1;
|
|
LatestBufferID = incLatestBufferID;
|
|
LastReadTime = DateTime.Now;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
msg.ReadBoolean(); msg.ReadPadBits();
|
|
for (int i = 0; i < BUFFER_COUNT; i++)
|
|
{
|
|
byte len = msg.ReadByte();
|
|
msg.BitPosition += len * 8;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public virtual void Dispose() { }
|
|
}
|
|
}
|