private async Task <bool> RecvMessage(Queue <RTMPMessage> messages, CancellationToken cancel_token)
{
var basic_header = (await RecvStream(1, cancel_token).ConfigureAwait(false))[0];
var chunk_stream_id = basic_header & 0x3F;
if (chunk_stream_id == 0)
{
chunk_stream_id = (await RecvStream(1, cancel_token).ConfigureAwait(false))[0] + 64;
}
else if (chunk_stream_id == 1)
{
var buf = await RecvStream(2, cancel_token).ConfigureAwait(false);
chunk_stream_id = (buf[1] * 256 | buf[0]) + 64;
}
RTMPMessageBuilder msg = null;
RTMPMessageBuilder last_msg = null;
if (!lastMessages.TryGetValue(chunk_stream_id, out last_msg))
{
last_msg = RTMPMessageBuilder.NullPacket;
}
switch ((basic_header & 0xC0) >> 6)
{
case 0:
using (var reader = new RTMPBinaryReader(await RecvStream(11, cancel_token).ConfigureAwait(false))) {
long timestamp = reader.ReadUInt24();
var body_length = reader.ReadUInt24();
var type_id = reader.ReadByte();
var stream_id = reader.ReadUInt32LE();
if (timestamp == 0xFFFFFF)
{
using (var ext_reader = new RTMPBinaryReader(await RecvStream(4, cancel_token).ConfigureAwait(false))) {
timestamp = ext_reader.ReadUInt32();
}
}
msg = new RTMPMessageBuilder(
last_msg,
timestamp,
type_id,
stream_id,
body_length);
lastMessages[chunk_stream_id] = msg;
}
break;
case 1:
using (var reader = new RTMPBinaryReader(await RecvStream(7, cancel_token).ConfigureAwait(false))) {
long timestamp_delta = reader.ReadUInt24();
var body_length = reader.ReadUInt24();
var type_id = reader.ReadByte();
if (timestamp_delta == 0xFFFFFF)
{
using (var ext_reader = new RTMPBinaryReader(await RecvStream(4, cancel_token).ConfigureAwait(false))) {
timestamp_delta = ext_reader.ReadUInt32();
}
}
msg = new RTMPMessageBuilder(
last_msg,
timestamp_delta,
type_id,
body_length);
lastMessages[chunk_stream_id] = msg;
}
break;
case 2:
using (var reader = new RTMPBinaryReader(await RecvStream(3, cancel_token).ConfigureAwait(false))) {
long timestamp_delta = reader.ReadUInt24();
if (timestamp_delta == 0xFFFFFF)
{
using (var ext_reader = new RTMPBinaryReader(await RecvStream(4, cancel_token).ConfigureAwait(false))) {
timestamp_delta = ext_reader.ReadUInt32();
}
}
msg = new RTMPMessageBuilder(last_msg, timestamp_delta);
lastMessages[chunk_stream_id] = msg;
}
break;
case 3:
msg = last_msg;
if (msg.ReceivedLength >= msg.BodyLength)
{
msg = new RTMPMessageBuilder(last_msg);
lastMessages[chunk_stream_id] = msg;
}
break;
}
msg.ReceivedLength += await RecvStream(
msg.Body,
msg.ReceivedLength,
Math.Min(recvChunkSize, msg.BodyLength - msg.ReceivedLength),
cancel_token).ConfigureAwait(false);
if (msg.ReceivedLength >= msg.BodyLength)
{
messages.Enqueue(msg.ToMessage());
}
return(true); //TODO:接続エラー時はfalseを返す
}