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; }
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; } }
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; }
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; } } }
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); }
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); }
internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer) { throw new InvalidOperationException(); }
internal abstract void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer);
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; } }
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; } } } }
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); } } }