예제 #1
0
        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;
            }
        }
예제 #2
0
        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;
        }
예제 #3
0
        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;
                }
            }
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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();
                }
            }
        }
예제 #6
0
        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);
        }
예제 #7
0
        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();
                }
            }
        }
예제 #8
0
        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;
            }
        }
예제 #9
0
 public static byte[] GetDeliveryTag(uint tag)
 {
     byte[] buffer = new byte[FixedWidth.UInt];
     AmqpBitConverter.WriteInt(buffer, 0, (int)tag);
     return(buffer);
 }
예제 #10
0
        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;
                    }
                }
            }
        }