void ReadFrame(out byte frameType, out ushort channel, out ulong code, out List fields, out ByteBuffer payload) { byte[] headerBuffer = this.ReadFixedSizeBuffer(8); int size = AmqpBitConverter.ReadInt(headerBuffer, 0); frameType = headerBuffer[5]; // TODO: header EXT channel = (ushort)(headerBuffer[6] << 8 | headerBuffer[7]); size -= 8; if (size > 0) { byte[] frameBuffer = this.ReadFixedSizeBuffer(size); ByteBuffer buffer = new ByteBuffer(frameBuffer, 0, size, size); Fx.AssertAndThrow(ErrorCode.ClientInvalidFormatCodeRead, Encoder.ReadFormatCode(buffer) == FormatCode.Described); code = Encoder.ReadULong(buffer, Encoder.ReadFormatCode(buffer)); fields = Encoder.ReadList(buffer, Encoder.ReadFormatCode(buffer)); if (buffer.Length > 0) { payload = new ByteBuffer(buffer.Buffer, buffer.Offset, buffer.Length, buffer.Length); } else { payload = null; } } else { code = 0; fields = null; payload = null; } }
void WriteFrame(byte frameType, ushort channel, ulong code, List fields) { ByteBuffer buffer = new ByteBuffer(64, true); // frame header buffer.Append(FixedWidth.UInt); AmqpBitConverter.WriteUByte(buffer, 2); AmqpBitConverter.WriteUByte(buffer, (byte)frameType); AmqpBitConverter.WriteUShort(buffer, channel); // command AmqpBitConverter.WriteUByte(buffer, FormatCode.Described); Encoder.WriteULong(buffer, code, true); AmqpBitConverter.WriteUByte(buffer, FormatCode.List32); int sizeOffset = buffer.WritePos; buffer.Append(8); AmqpBitConverter.WriteInt(buffer.Buffer, sizeOffset + 4, fields.Count); for (int i = 0; i < fields.Count; i++) { Encoder.WriteObject(buffer, fields[i]); } AmqpBitConverter.WriteInt(buffer.Buffer, sizeOffset, buffer.Length - sizeOffset); AmqpBitConverter.WriteInt(buffer.Buffer, 0, buffer.Length); // frame size this.transport.Write(buffer.Buffer, buffer.Offset, buffer.Length); this.sendActive = true; }
public async Task PumpAsync(Func <ProtocolHeader, bool> onHeader, Func <ByteBuffer, bool> onBuffer) { byte[] header = new byte[FixedWidth.ULong]; if (onHeader != null) { // header await this.ReceiveBufferAsync(header, 0, FixedWidth.ULong); if (!onHeader(ProtocolHeader.Create(header, 0))) { return; } } // frames while (true) { await this.ReceiveBufferAsync(header, 0, FixedWidth.UInt); int frameSize = AmqpBitConverter.ReadInt(header, 0); byte[] buffer = new byte[frameSize]; Buffer.BlockCopy(header, 0, buffer, 0, FixedWidth.UInt); await this.ReceiveBufferAsync(buffer, FixedWidth.UInt, frameSize - FixedWidth.UInt); if (!onBuffer(new ByteBuffer(buffer, 0, frameSize, frameSize))) { break; } } }
internal void OnTransfer(List transfer, ByteBuffer payload) { for (int i = transfer.Count; i < 11; i++) { transfer.Add(null); } bool more = transfer[5] != null && true.Equals(transfer[5]); if (transfer[1] == null || (this.deliveryReceived && this.lastDeliveryId.Equals(transfer[1]))) { AmqpBitConverter.WriteBytes(this.messageBuffer, payload.Buffer, payload.Offset, payload.Length); } else { lock (this) { Fx.AssertAndThrow(ErrorCode.InvalidCreditOnTransfer, this.credit > 0); this.deliveryCount++; if (this.credit < uint.MaxValue) { this.credit--; } } this.lastDeliveryId = (uint)transfer[1]; this.deliveryReceived = true; if (this.messageBuffer == null) { if (more) { this.messageBuffer = new ByteBuffer(payload.Length * 2, true); AmqpBitConverter.WriteBytes(this.messageBuffer, payload.Buffer, payload.Offset, payload.Length); } else { this.messageBuffer = payload; } } } if (!more) // more { Message message = Message.Decode(this.messageBuffer); this.messageBuffer = null; message.deliveryId = this.lastDeliveryId; message.settled = transfer[4] != null && true.Equals(transfer[4]); this.onMessage(this, message); } }
public async Task PumpAsync(uint maxFrameSize, Func <ProtocolHeader, bool> onHeader, Func <ByteBuffer, bool> onBuffer) { byte[] header = new byte[FixedWidth.ULong]; if (onHeader != null) { // header await this.ReceiveBufferAsync(header, 0, FixedWidth.ULong).ConfigureAwait(false); Trace.WriteBuffer("RECV {0}", header, 0, header.Length); if (!onHeader(ProtocolHeader.Create(header, 0))) { return; } } // frames while (true) { await this.ReceiveBufferAsync(header, 0, FixedWidth.UInt).ConfigureAwait(false); int frameSize = AmqpBitConverter.ReadInt(header, 0); if ((uint)frameSize > maxFrameSize) { throw new AmqpException(ErrorCode.InvalidField, Fx.Format(SRAmqp.InvalidFrameSize, frameSize, maxFrameSize)); } ByteBuffer buffer = this.bufferManager.GetByteBuffer(frameSize); try { Buffer.BlockCopy(header, 0, buffer.Buffer, buffer.Offset, FixedWidth.UInt); await this.ReceiveBufferAsync(buffer.Buffer, buffer.Offset + FixedWidth.UInt, frameSize - FixedWidth.UInt).ConfigureAwait(false); buffer.Append(frameSize); Trace.WriteBuffer("RECV {0}", buffer.Buffer, buffer.Offset, buffer.Length); if (!onBuffer(buffer)) { break; } } finally { buffer.ReleaseReference(); } } }
internal int SendCommand(ushort channel, Transfer transfer, bool first, ByteBuffer payload, int reservedBytes) { this.ThrowIfClosed("Send"); ByteBuffer buffer = this.AllocateBuffer(Frame.CmdBufferSize); Frame.Encode(buffer, FrameType.Amqp, channel, transfer); int payloadSize = payload.Length; int frameSize = buffer.Length + payloadSize; bool more = frameSize > this.remoteMaxFrameSize; if (more) { transfer.More = true; buffer.Reset(); Frame.Encode(buffer, FrameType.Amqp, channel, transfer); frameSize = (int)this.remoteMaxFrameSize; payloadSize = frameSize - buffer.Length; } AmqpBitConverter.WriteInt(buffer.Buffer, buffer.Offset, frameSize); ByteBuffer frameBuffer; if (first && !more && reservedBytes >= buffer.Length) { // optimize for most common case: single-transfer message frameBuffer = this.WrapBuffer(payload, payload.Offset - buffer.Length, frameSize); Array.Copy(buffer.Buffer, buffer.Offset, frameBuffer.Buffer, frameBuffer.Offset, buffer.Length); buffer.ReleaseReference(); } else { AmqpBitConverter.WriteBytes(buffer, payload.Buffer, payload.Offset, payloadSize); frameBuffer = buffer; } payload.Complete(payloadSize); this.writer.Send(frameBuffer); if (Trace.TraceLevel >= TraceLevel.Frame) { Trace.WriteLine(TraceLevel.Frame, "SEND (ch={0}) {1} payload {2}", channel, transfer, payloadSize); } return(payloadSize); }
public async Task PumpAsync(Func <ProtocolHeader, bool> onHeader, Func <ByteBuffer, bool> onBuffer) { byte[] header = new byte[FixedWidth.ULong]; if (onHeader != null) { // header await this.ReceiveBufferAsync(header, 0, FixedWidth.ULong); if (!onHeader(ProtocolHeader.Create(header, 0))) { return; } } // frames while (true) { await this.ReceiveBufferAsync(header, 0, FixedWidth.UInt); int frameSize = AmqpBitConverter.ReadInt(header, 0); ByteBuffer buffer = this.bufferManager.GetByteBuffer(frameSize); try { Buffer.BlockCopy(header, 0, buffer.Buffer, buffer.Offset, FixedWidth.UInt); await this.ReceiveBufferAsync(buffer.Buffer, buffer.Offset + FixedWidth.UInt, frameSize - FixedWidth.UInt); buffer.Append(frameSize); if (!onBuffer(buffer)) { break; } } finally { buffer.ReleaseReference(); } } }
internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer) { if (delivery == null) { delivery = this.deliveryCurrent; AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length); } else { buffer.AddReference(); delivery.Buffer = buffer; lock (this.ThisLock) { this.OnDelivery(transfer.DeliveryId); } } if (!transfer.More) { this.deliveryCurrent = null; delivery.Message = Message.Decode(delivery.Buffer); Waiter waiter; MessageCallback callback = this.onMessage; lock (this.ThisLock) { waiter = (Waiter)this.waiterList.First; if (waiter != null) { this.waiterList.Remove(waiter); } else if (callback == null) { this.receivedMessages.Add(new MessageNode() { Message = delivery.Message }); return; } } while (waiter != null) { if (waiter.Signal(delivery.Message)) { return; } lock (this.ThisLock) { waiter = (Waiter)this.waiterList.First; if (waiter != null) { this.waiterList.Remove(waiter); } else if (callback == null) { this.receivedMessages.Add(new MessageNode() { Message = delivery.Message }); return; } } } Fx.Assert(waiter == null, "waiter must be null now"); Fx.Assert(callback != null, "callback must not be null now"); callback(this, delivery.Message); } else { this.deliveryCurrent = delivery; } }
public static byte[] GetDeliveryTag(uint tag) { byte[] buffer = new byte[FixedWidth.UInt]; AmqpBitConverter.WriteInt(buffer, 0, (int)tag); return(buffer); }
internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer) { if (!transfer.More) { Waiter waiter; MessageCallback callback; lock (this.ThisLock) { if (delivery == null) { // multi-transfer delivery delivery = this.deliveryCurrent; this.deliveryCurrent = null; Fx.Assert(delivery != null, "Must have a delivery in the queue"); AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length); delivery.Message = Message.Decode(delivery.Buffer); delivery.Buffer = null; } else { // single tranfer delivery this.OnDelivery(transfer.DeliveryId); delivery.Message = Message.Decode(buffer); } callback = this.onMessage; waiter = (Waiter)this.waiterList.First; if (waiter != null) { this.waiterList.Remove(waiter); } if (waiter == null && callback == null) { this.receivedMessages.Add(new MessageNode() { Message = delivery.Message }); return; } } while (waiter != null) { if (waiter.Signal(delivery.Message)) { this.OnDeliverMessage(); return; } lock (this.ThisLock) { waiter = (Waiter)this.waiterList.First; if (waiter != null) { this.waiterList.Remove(waiter); } else if (callback == null) { this.receivedMessages.Add(new MessageNode() { Message = delivery.Message }); return; } } } Fx.Assert(waiter == null, "waiter must be null now"); Fx.Assert(callback != null, "callback must not be null now"); callback(this, delivery.Message); this.OnDeliverMessage(); } else { lock (this.ThisLock) { if (delivery == null) { delivery = this.deliveryCurrent; Fx.Assert(delivery != null, "Must have a current delivery"); AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length); } else { this.OnDelivery(transfer.DeliveryId); delivery.Buffer = new ByteBuffer(buffer.Length * 2, true); AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length); this.deliveryCurrent = delivery; } } } }