in src/Proton/Engine/Implementation/ProtonFrameDecodingHandler.cs [360:432]
internal override void Parse(IEngineHandlerContext context, IProtonBuffer input)
{
int dataOffset = (input.ReadUnsignedByte() << 2) & 0x3FF;
int frameSize = length + FRAME_SIZE_BYTES;
ValidateDataOffset(dataOffset, frameSize);
byte type = input.ReadUnsignedByte();
ushort channel = input.ReadUnsignedShort();
// Skip over the extended header if present (i.e offset > 8)
if (dataOffset != 8)
{
input.ReadOffset += dataOffset - 8;
}
long frameBodySize = frameSize - dataOffset;
IProtonBuffer payload = null;
object val;
if (frameBodySize > 0)
{
long startReadIndex = input.ReadOffset;
val = handler.decoder.ReadObject(input, handler.decoderState);
// Copy the payload portion of the incoming bytes for now as the incoming may be
// from a wrapped pooled buffer and for now we have no way of retaining or otherwise
// ensuring that the buffer remains ours. Since we might want to store received
// data at a client level and decode later we could end up losing the data to reuse
// if it was pooled.
if (input.IsReadable)
{
long payloadSize = frameBodySize - (input.ReadOffset - startReadIndex);
// Check that the remaining bytes aren't part of another frame.
if (payloadSize > 0)
{
payload = handler.configuration.BufferAllocator.Allocate(payloadSize, payloadSize);
input.CopyInto(input.ReadOffset, payload, 0, payloadSize);
input.ReadOffset += payloadSize;
payload.WriteOffset += payloadSize;
}
}
}
else
{
handler.TransitionToFrameSizeParsingStage();
context.FireRead(EmptyEnvelope.Instance);
return;
}
if (type == AMQP_FRAME_TYPE)
{
IPerformative performative = (IPerformative)val;
IncomingAmqpEnvelope frame = handler.framePool.Take(performative, channel, payload);
handler.TransitionToFrameSizeParsingStage();
context.FireRead(frame);
}
else if (type == SASL_FRAME_TYPE)
{
ISaslPerformative performative = (ISaslPerformative)val;
SaslEnvelope saslFrame = new(performative);
handler.TransitionToFrameSizeParsingStage();
// Ensure we process transition from SASL to AMQP header state
handler.HandleRead(context, saslFrame);
}
else
{
throw new FrameDecodingException(string.Format("unknown frame type: {0}", type));
}
}