Example #1
0
        public static ByteBuffer Encode(FrameType type, ushort channel, Transfer transfer,
            ByteBuffer payload, int maxFrameSize, out int payloadSize)
        {
            int bufferSize = cmdBufferSize + payload.Length;
            if (bufferSize > maxFrameSize)
            {
                bufferSize = maxFrameSize;
            }

            bool more = false;   // estimate it first
            if (payload.Length > bufferSize - 32)
            {
                transfer.More = more = true;
            }

            ByteBuffer buffer = new ByteBuffer(bufferSize, false);
            EncodeFrame(buffer, type, channel, transfer);

            if (more && payload.Length <= buffer.Size)
            {
                // guessed it wrong. correct it
                transfer.More = false;
                buffer.Reset();
                EncodeFrame(buffer, type, channel, transfer);
            }

            payloadSize = Math.Min(payload.Length, buffer.Size);
            AmqpBitConverter.WriteBytes(buffer, payload.Buffer, payload.Offset, payloadSize);
            payload.Complete(payloadSize);
            AmqpBitConverter.WriteInt(buffer.Buffer, 0, buffer.Length);
            return buffer;
        }
Example #2
0
        internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer)
        {
            if (delivery != null)
            {
                buffer.AddReference();
                delivery.Buffer = buffer;
                this.deliveryCount++;
            }
            else
            {
                delivery = this.deliveryCurrent;
                AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
            }

            if (!transfer.More)
            {
                this.DeliverMessage(delivery);
            }
            else
            {
                this.deliveryCurrent = delivery;
            }
        }
Example #3
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.maxFrameSize;
            if (more)
            {
                transfer.More = true;
                buffer.Reset();
                Frame.Encode(buffer, FrameType.Amqp, channel, transfer);
                frameSize = (int)this.maxFrameSize;
                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.transport.Send(frameBuffer);
            Trace.WriteLine(TraceLevel.Frame, "SEND (ch={0}) {1} payload {2}", channel, transfer, payloadSize);

            return payloadSize;
        }
Example #4
0
        void WriteDelivery(Delivery delivery)
        {
            // Must be called under lock. Delivery must be on list already
            while (this.outgoingWindow > 0 && delivery != null)
            {
                --this.outgoingWindow;
                Transfer transfer = new Transfer() { Handle = delivery.Handle };

                bool first = delivery.BytesTransfered == 0;
                if (first)
                {
                    // initialize properties for first transfer
                    delivery.DeliveryId = this.outgoingDeliveryId++;
                    transfer.DeliveryTag = delivery.Tag;
                    transfer.DeliveryId = delivery.DeliveryId;
                    transfer.State = delivery.State;
                    transfer.MessageFormat = 0;
                    transfer.Settled = delivery.Settled;
                    transfer.Batchable = true;
                }

                int len = this.connection.SendCommand(this.channel, transfer, first,
                    delivery.Buffer, delivery.ReservedBufferSize);
                delivery.BytesTransfered += len;

                if (delivery.Buffer.Length == 0)
                {
                    delivery.Buffer.ReleaseReference();
                    Delivery next = (Delivery)delivery.Next;
                    if (delivery.Settled)
                    {
                        this.outgoingList.Remove(delivery);
                    }

                    delivery = next;
                }
            }
        }
Example #5
0
        void OnTransfer(Transfer transfer, ByteBuffer buffer)
        {
            bool newDelivery;
            lock (this.ThisLock)
            {
                if (this.incomingWindow-- == 0)
                {
                    this.SendFlow(new Flow());
                }

                this.nextIncomingId++;
                newDelivery = transfer.HasDeliveryId && transfer.DeliveryId > this.incomingDeliveryId;
                if (newDelivery)
                {
                    this.incomingDeliveryId = transfer.DeliveryId;
                }
            }

            Link link = this.GetLink(transfer.Handle);
            Delivery delivery = null;
            if (newDelivery)
            {
                delivery = new Delivery()
                {
                    DeliveryId = transfer.DeliveryId,
                    Link = link,
                    Tag = transfer.DeliveryTag,
                    Settled = transfer.Settled,
                    State = transfer.State
                };

                if (!delivery.Settled)
                {
                    lock (this.ThisLock)
                    {
                        this.incomingList.Add(delivery);
                    }
                }
            }

            link.OnTransfer(delivery, transfer, buffer);
        }
Example #6
0
 internal void SendCommand(ushort channel, Transfer transfer, ByteBuffer payload)
 {
     this.ThrowIfClosed("Send");
     int payloadSize;
     ByteBuffer buffer = Frame.Encode(FrameType.Amqp, channel, transfer, payload, (int)this.maxFrameSize, out payloadSize);
     this.transport.Send(buffer);
     Trace.WriteLine(TraceLevel.Frame, "SEND (ch={0}) {1} payload {2}", channel, transfer, payloadSize);
 }
Example #7
0
 internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer)
 {
     throw new InvalidOperationException();
 }
Example #8
0
 internal abstract void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer);
Example #9
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))
                    {
                        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
            {
                this.deliveryCurrent = delivery;
            }
        }
Example #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;
                    }
                }
            }
        }
Example #11
0
 internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer)
 {
     if (delivery != null)
     {
         this.deliveryCount++;
         if (!transfer.More)
         {
             // single transfer message - the most common case
             delivery.Buffer = buffer;
             this.DeliverMessage(delivery);
         }
         else
         {
             delivery.Buffer = new ByteBuffer(buffer.Length * 2, true);
             AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
             this.deliveryCurrent = delivery;
         }
     }
     else
     {
         delivery = this.deliveryCurrent;
         if (!transfer.More)
         {
             AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
             this.deliveryCurrent = null;
             this.DeliverMessage(delivery);
         }
         else
         {
             AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
         }
     }
 }