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(); } } }
void ITransport.Send(ByteBuffer buffer) { lock (this.SyncRoot) { if (this.closed) { buffer.ReleaseReference(); throw new ObjectDisposedException(this.GetType().Name); } this.bufferQueue.Enqueue(buffer); if (this.writing) { return; } this.writing = true; } this.WriteAsync(); }
void ITransport.Send(ByteBuffer buffer) { lock (this.SyncRoot) { if (this.closed) { buffer.ReleaseReference(); throw new ObjectDisposedException(this.GetType().Name); } if (this.writing) { this.bufferQueue.Enqueue(buffer); return; } this.writing = true; } this.WriteAsync(buffer); }
async void WriteAsync() { const int maxBatchSize = 128 * 1024; List <ByteBuffer> buffers = new List <ByteBuffer>(); while (true) { ByteBuffer buffer = null; int size = 0; lock (this.SyncRoot) { while (size < maxBatchSize && this.bufferQueue.Count > 0) { ByteBuffer item = this.bufferQueue.Dequeue(); if (item.Length == 0) // special buffer { buffer = item; break; } else { buffers.Add(item); size += item.Length; } } if (size == 0) { this.writing = false; if (buffer == null) { break; } } } try { if (size > 0) { await this.transport.SendAsync(buffers, size); } } catch (Exception exception) { lock (this.SyncRoot) { this.closed = true; this.writing = false; this.transport.Close(); buffers.AddRange(this.bufferQueue); this.bufferQueue.Clear(); } this.onException(exception); break; } finally { for (int i = 0; i < buffers.Count; i++) { buffers[i].ReleaseReference(); } buffers.Clear(); if (buffer != null) { buffer.ReleaseReference(); } } } }